js13kGames. Depending on the input it can provide up to 15% additional compression compared to Zopfli.
Roadroller is considered “heavyweight” unlike typical JS packers such as JSCrush or RegPack, because it is quite resource intensive and requires both a considerable amount of memory and a non-negligible run time. The default should work for most devices, but you can configure both aspects as you need.
Usage
By default Roadroller receives your JS code and returns a compressed JS code that should be further compressed with ZIP/gzip (or more accurately, DEFLATE). Ideally your JS code should be already minified, probably using Terser or Closure Compiler; Roadroller only does a minimal whitespace and comment suppression.
The first line is a compressed data. It can contain control characters that might not render in certain environments. Nevertheless you should make sure that they are all copied in verbatim.
The second line is a compressor tuned for this particular input. By default the decompressed data immediately goes through eval, but you can configure what to do with that.
The first line is very incompressible unlike the second line, so ideally you should compress two lines separately. This is best done by using ADVZIP from AdvanceCOMP or the aforementioned Zopfli. The first line and second line may form a single statement as above so they should not be separated; you can only concatenate them.
Input Configuration
Each input can be further configured by input type and action.
Input type determines the preprocessing step to improve the compression.
JavaScript
Assumes a valid JS code. Automatically removes all redundant whitespace and comments and enables a separate modelling for embedded strings. This also works for JSON.
Text
Assumes a human-readable Unicode text that can be encoded in UTF-8. This can also be used for JavaScript code that should not undergo preprocessing.
Input action determines what to do with the decompressed data.
Evaluate
Evaluates the decompressed JavaScript code. If there are multiple inputs there should be exactly one JavaScript input with evaluate action, since subsequent inputs will be decompressed in that code. The resulting value is always a code string, which may include decoders for subsequent inputs.
Write to document
Writes a decompressed string to document. Typically used with HTML.
Output Configuration
Number of contexts relates to the complexity of modelling. The larger number of contexts will compress better, but at the expense of linear increase in both the time and memory usage. The default is 12, which targets at most 1 second of latency permitted for typical 30 KB input.
Maximum memory usage configures the maximum memory to be used both for compression and decompression. Increasing or decreasing memory usage only affects the compression ratio and not the run time. The actual memory usage can be as low as a half of the specified due to the internal architecture. The default is 150 MB.
Allowing the decoder to pollute the global scope is unsafe especially when the Roadroller output should coexist with other code or there are elements with single letter id attributes and turned off by default. But if you can control your environment (typical for demos), you can turn this on for a smaller decoder.
Optimize parameters button searches for better modelling parameters. At the first click it runs a quick search that takes 10 seconds for typical 30 KB input, and subsequent click will run a full search. Parameters are solely related to the compression ratio so you can try this as many as you can afford.
Advanced Configuration
Following parameters can be automatically optimized and normally you don't have to touch them unless you want to reproduce a particular set of parameters.
Chosen contexts determine which byte contexts are used for each model. Kth bit of the number (where K > 0) is set if the context contains the Kth-to-last byte: 5 = 101(2) for example would correspond to the context of the last byte and third-to-last byte, also called a sparse context (0,2). There is no particular limit for the number, but Roadroller only considers up to 9th order for the optimization process.
Precision is the number of fractional bits used in the internal fixed point representation. This is shared between the entropy coder and context models and can't be decoupled. The default of 16 should be enough, you can also try to decrease it.
Learning rate adjusts how fast would the context mixer adapt, where smaller is faster. The default is 500 which should be fine for long enough inputs. If your demo is smaller than 10 KB you can also try smaller numbers.
Model max count adjusts how fast would individual contexts adapt, where smaller is faster. The model adapts fastest when a particular context is first seen, but that process becomes slower as the context is seen multiple times. This parameter limits how slowest the adaptation process can be. The default of 5 is specifically tuned for JS code inputs.
Model base divisor adjusts how fast should individual contexts adapt initially, where larger is faster. The optimal value typically ranges from 10 to 100 for JS code inputs.
Number of abbreviations affects the preprocessing for JS code inputs. Common identifiers and reserved words can be abbreviated to single otherwise unused bytes during the preprocessing; this lessens the burden of context modelling which can only look at the limited number of past bytes. If this parameter is less than the number of allowable abbreviations some identifiers will be left as is, which can sometimes improve the compression.
You can also use Roadroller as a library to integrate with your build pipeline. Please take a look at the GitHub project page for details.
Roadroller is brought to you by Kang Seonghoon.`;var t=/\/(?![*\/])(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)*(\/[$_\u200C\u200D\p{ID_Continue}]*|\\)?/uy,e=/--|\+\+|=>|\.{3}|\??\.(?!\d)|(?:&&|\|\||\?\?|[+\-%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2}|\/(?![\/*]))=?|[?~,:;[\](){}]/y,r=/(?=[$_\p{ID_Start}\\])(?:[$_\u200C\u200D\p{ID_Continue}]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+/uy,i=/(['"])(?:(?!\1)[^\\\n\r]|\\(?:\r\n|[^]))*(\1)?/y,a=/(?:0[xX][\da-fA-F](?:_?[\da-fA-F])*|0[oO][0-7](?:_?[0-7])*|0[bB][01](?:_?[01])*)n?|0n|[1-9](?:_?\d)*n|(?:(?:0(?!\d)|0\d*[89]\d*|[1-9](?:_?\d)*)(?:\.(?:\d(?:_?\d)*)?)?|\.\d(?:_?\d)*)(?:[eE][+-]?\d(?:_?\d)*)?|0[0-7]+/y,s=/[`}](?:[^`\\$]|\\[^]|\$(?!\{))*(`|\$\{)?/y,o=/[\t\v\f\ufeff\p{Zs}]+/uy,n=/\r?\n|[\r\u2028\u2029]/y,h=/\/\*(?:[^*]|\*(?!\/))*(\*\/)?/y,u=/\/\/.*/y,c=/^(?:[\/+-]|\.{3}|\?[C-F])?$|[{}([,;<>=*%&|^!~?:]$/,f=/^(?:=>|[;\]){}]|else|\?[EF])?$/,l=/^(?:await|case|default|delete|do|else|instanceof|new|return|throw|typeof|void|yield)$/,p=/^(?:return|throw|yield)$/,v=RegExp(n.source);function*d(d){var w,$,y,m,b,_,g,x,M,B,E,S,A,k;for(({length:_}=d),m=0,b="",k=[{t:1}],w=[],E=0,S=!1;m<_;){switch((x=k[k.length-1]).t){case 1:case 2:case 3:if("/"===d[m]&&(c.test(b)||l.test(b))&&(t.lastIndex=m,g=t.exec(d))){m=t.lastIndex,b=g[0],S=!0,yield{i:6,o:g[0],h:void 0!==g[1]&&"\\"!==g[1]};continue}if(e.lastIndex=m,g=e.exec(d)){switch(M=e.lastIndex,B=A=g[0],A){case"(":"?G"===b&&k.push({t:2,u:E}),E++,S=!1;break;case")":E--,S=!0,2===x.t&&E===x.u&&(k.pop(),B="?F",S=!1);break;case"{":e.lastIndex=0,y=!f.test(b)&&(c.test(b)||l.test(b)),w.push(y),S=!1;break;case"}":if(3===x.t&&w.length===x.u){s.lastIndex=m,g=s.exec(d),m=s.lastIndex,b=g[0],"${"===g[1]?(b="?D",S=!1,yield{i:4,o:g[0]}):(k.pop(),S=!0,yield{i:5,o:g[0],h:"`"===g[1]});continue}B=(S=w.pop())?"?A":"}";break;case"]":S=!0;break;case"++":case"--":B=S?"?B":"?C";break;case"<":S=!1;break;default:S=!1}m=M,b=B,yield{i:11,o:A};continue}if(r.lastIndex=m,g=r.exec(d)){switch(m=r.lastIndex,B=g[0],g[0]){case"for":case"if":case"while":case"with":"."!==b&&"?."!==b&&(B="?G")}b=B,S=!l.test(g[0]),yield{i:9,o:g[0]};continue}if(i.lastIndex=m,g=i.exec(d)){m=i.lastIndex,b=g[0],S=!0,yield{i:1,o:g[0],h:void 0!==g[2]};continue}if(a.lastIndex=m,g=a.exec(d)){m=a.lastIndex,b=g[0],S=!0,yield{i:10,o:g[0]};continue}if(s.lastIndex=m,g=s.exec(d)){m=s.lastIndex,b=g[0],"${"===g[1]?(b="?D",k.push({t:3,u:w.length}),S=!1,yield{i:3,o:g[0]}):(S=!0,yield{i:2,o:g[0],h:"`"===g[1]});continue}}o.lastIndex=m,(g=o.exec(d))?(m=o.lastIndex,yield{i:12,o:g[0]}):(n.lastIndex=m,(g=n.exec(d))?(m=n.lastIndex,S=!1,p.test(b)&&(b="?E"),yield{i:13,o:g[0]}):(h.lastIndex=m,(g=h.exec(d))?(m=h.lastIndex,v.test(g[0])&&(S=!1,p.test(b)&&(b="?E")),yield{i:7,o:g[0],h:void 0!==g[1]}):(u.lastIndex=m,(g=u.exec(d))?(m=u.lastIndex,S=!1,yield{i:8,o:g[0]}):(m+=($=String.fromCodePoint(d.codePointAt(m))).length,b=$,S=!1,yield{i:14,o:$}))))}}var w=(t,e=1)=>{var r=1;return t>65536*e&&(e*=65536,r+=16),t>256*e&&(e*=256,r+=8),t>16*e&&(e*=16,r+=4),t>4*e&&(e*=4,r+=2),t>2*e&&(r+=1),r},$=(t,e,r,i)=>{if(r<=8)return new Uint8Array(t?t.l(e,i):i);if(r<=16)return new Uint16Array(t?t.l(e,2*i):i);if(r<=32)return new Uint32Array(t?t.l(e,4*i):i);throw"newUintArray: nbits is too large"};class y{constructor({p:t,v:e}){this.v=e,this.p=t,this.input=[]}$(t,e){if(0!==t&&1!==t)throw Error("AnsEncoder.writeBit: bad bit");if(e!==~~e||e<0||e>=1<=c;)r.push(e%t),e=e/t|0;if((e=((e/h|0)<=2147483648)throw Error("ANSEncoder.finish: state overflow")}return r.reverse(),{state:e,M:r}}}class m extends class{constructor({B:t,S:e,v:r,A:i,k:a,C:s}){this.B=t,this.S=e,this.v=r,this.A=i,this.L=1/a,this.C=s,this.R=$(s,this,r,1<>29-this.v,this.U=this.U<<1|t}O(){this.U=1}D(){this.C&&(this.R&&this.C.D(this.R.buffer),this.I&&this.C.D(this.I.buffer),this.P&&this.C.D(this.P.buffer),this.R=null,this.I=null,this.P=null)}}{constructor(t){super(t),this.selector=t.J,this.N=[];for(var e=0;this.selector>>e>0;++e)this.N.push(0);this.T=0}F(t=0){return super.F(this.T+t)}j(t,e=0){super.j(t,this.T+e)}O(t,e){super.O(t,e),this.N.unshift(t),this.N.pop();for(var r=0,i=this.N.length-1;i>=0;--i)this.selector>>i&1&&(r=997*(r+this.N[i])|0);this.T=r}}class b extends class{constructor(t,{W:e,v:r}){this.q=t,this.v=r,this.W=e,this.V=0,this.G=[],this.Z=[];for(var i=0;i>1}j(t,e=0){for(var r=this.V/(2<new m({...t,J:e}))),t),this.H=r,this.K=0,this.Y=new Set}F(t=0){return this.K>0&&(t+=129),super.F(t)}j(t,e=0){this.K>0&&(e+=129),super.j(t,e)}O(t,e){super.O(t,e),this.H&&(this.K&&this.K===t?this.K=0:!this.K&&[34,39,96].includes(t)&&(this.K=t,this.Y.add(t)))}}var _=(t=12)=>{for(var e=[0,1,2,3,6,7,13,21,25,42,50,57].slice(0,t=Math.max(0,Math.min(64,t)));e.lengtht-e))},g=t=>t.v<=8?1:t.v<=16?2:4,x=t=>t.A<128?1:t.A<32768?2:4,M=t=>{var e=g(t)+x(t);return((t,e=1)=>{var r=0;return t>=65536*e&&(e*=65536,r+=16),t>=256*e&&(e*=256,r+=8),t>=16*e&&(e*=16,r+=4),t>=4*e&&(e*=4,r+=2),t>=2*e&&(r+=1),r})(1048576*t.tt,t.X.length*e)};class B{constructor(t,e={}){this.et={X:e.X?e.X.slice():_(),tt:e.tt||150,v:e.v||16,A:e.A||5,k:e.k||20,W:e.W||500,S:e.S,C:e.C,rt:"number"==typeof e.rt?e.rt:64,it:e.it},this.st={},this.ot=null;for(var r=0;rt.nt)).join("");return e.length>=65e3||e.match(/[\u0100-\uffff]/)?{ft:!0,text:unescape(encodeURIComponent(e))}:{ft:!1,text:e}}static lt(t,{rt:e}){var r=(t,e)=>t.replace(RegExp(`\\\\?(${e})|\\\\.`,"g"),((t,e)=>e?"\\x"+e.charCodeAt(0).toString(16).padStart(2,"0"):t)),i=new Map,a=[];for(var s of t){var o=[];for(var n of d(s.nt)){if(!1===n.h)throw Error("Packer: invalid JS code in the input");switch(n.i){case 12:case 7:case 8:continue;case 13:if(13===(o[o.length-1]||{}).i)continue;n.o="\n";break;case 9:n.o.length>1&&i.set(n.o,(i.get(n.o)||0)+1);break;case 1:case 2:n.o=n.o[0]+r(n.o.slice(1,-1),n.o[0])+n.o[0];break;case 3:n.o="`"+r(n.o.slice(1),"`");break;case 5:n.o=r(n.o.slice(0,-1),"`")+"`";break;case 6:n.o=r(n.o,"['\"`]");break;case 14:throw Error("Packer: invalid JS code in the input")}n.o=n.o.replace(/\r\n?/g,"\n").replace(/[^\n\x20-\x7f]/g,(t=>"\\u"+t.charCodeAt(0).toString(16).padStart(4,"0"))),o.push(n)}13===(o[o.length-1]||{}).i&&o.pop(),a.push(o)}for(var h=new Set,u=0;u<128;++u)[32,34,39,96].includes(u)||h.add(String.fromCharCode(u));for(var o of a)for(var n of o)for(var c of n.o)h.delete(c);var f=[...h].sort(),l=[...i.entries()].map((([t,e])=>[t,t.length*(e-1)])).filter((([,t])=>t>0)).sort((([,t],[,e])=>e-t)).slice(0,f.length).map((([t],e)=>[t,f[e]])),p=l.length;l=l.slice(0,e);var v,w=new Map(l),$="",y={},m=new Set;for(var o of a)for(var n of o)9===n.i&&(n.vt=w.get(n.o)),v&&(9===v.i&&n.o.match(/^[\w$\\]/)||(v.o+" "+n.o).match(/^\/ \/|\/ in(?:stanceof)?$|^(?:\+ \+|- -|! --|-- >)$/))&&(v.vt?n.vt?m.add(v.vt+n.vt):y[v.vt]|=2:n.vt?y[n.vt]|=1:$+=" "),$+=n.vt||n.o,v=n;for(;0!==(m=new Set([...m].filter((t=>!(2&y[t[0]]||1&y[t[1]]))))).size;){var b=new Map;for(var _ of m){var g=_.charCodeAt(0)<<1,x=_.charCodeAt(1)<<1|1;b.set(g,(b.get(g)||0)+1),b.set(x,(b.get(x)||0)+1)}var[[M]]=[...b.entries()].sort((([t,e],[r,i])=>i-e||t-r));y[String.fromCharCode(M>>1)]|=1&M?1:2}var B="";for(var[E,S]of l)1&y[S]&&(B+=" "),B+=E,2&y[S]&&(B+=" "),B+=S;return{dt:l,wt:B+$,undefined:p}}static yt(t,e){var r=B.ct(t.text||[],e),i=B.lt(t.js||[],e),a=[...r.text,...i.wt].map((t=>t.charCodeAt(0))),s=a.every((t=>t<=127))?7:8,o=i.wt.length>0,{X:n,v:h,A:u,k:c,W:f}=e,l=e.S||M(e),p={...e,B:s,p:6,H:o,S:l},v=new b(p),{M:d,state:w,bt:$,_t:m}=((t,e,r)=>{var{B:i,p:a,v:s,gt:o=[],xt:n,Mt:h}=r,u=new y(r);if(void 0!==n){if(0===t.length)throw Error("compressWithModel: inputEndsWithByte given but input is empty");if(t[t.length-1]!==n)throw Error("compressWithModel: input does not agree with inputEndsWithByte");for(var c=0;c=0;--l)e.F(),e.j(f>>l&1);e.O(f,i)}var p=[];for(c=0;c=0;--l){var d=f>>l&1,w=e.F();v&&(v*=2*(d?w:(1<(s+1)*i-Math.log2(t))));var _=Math.ceil(b.length*(a<0?Math.log2(-a):a)/8);return{state:m,M:b,bt:void 0===n?t.length:-1,_t:_,Bt:$}})(a,v,p),_=n.length,E=8*g(p),S=8*x(p),A=[];for(var k of n){for(var C=[],z=0;1<>z&1&&C.push(z+1);A.push(C.reverse())}for(var L=n.every((t=>t<512)),R=[...v.Y].sort(((t,e)=>t-e)),I={1:"1",2:".5",5:".2",10:".1"}[c]||"1/"+c,P={"\0":"\\0","\r":e.it?"\\r":"\\\\r","\\":e.it?"\\\\":"\\\\\\\\","`":e.it?"\\`":"\\\\`"},U={"\0":"\\0",'"':e.it?'"':'\\"',"\r":e.it?"\\r":"\\\\r","\n":e.it?"\\n":"\\\\n","\\":e.it?"\\\\":"\\\\\\\\","]":e.it?"\\]":"\\\\]"},F=t=>U[t]||t,j=(t,e)=>{for(var r=[],i=-1,a=0;a<=1<=0){var o=a-1,n=F(String.fromCharCode(i));i+10&&"^"===r[0][0]&&(r.length>1?r.push(r.unshift()):r[0]="\\"+r[0]),(e?"":"^")+r.join("")},O=t=>t||$>=65e3?"new TextDecoder().decode(new Uint8Array(ο))":"String.fromCharCode(...ο)",D=t=>t<10||t>h+10?""+(1<0?"θ*"+(1<28===t||63===t?t:64|t)));J+="'";var T=[["τ",""+w],["θ","1<<"+(h+1)],["ω",""+JSON.stringify(Array(_).fill(0))],["π",`new Uint${E}Array(${_}<<${l}).fill(1<<${h-1})`],["κ",`new Uint${S}Array(${_}<<${l})`]];e.it||(T.unshift(["ο","[]"]),T.push(["ρ","0"],["λ","0"]),R.length>0&&T.push(["χ","0"]));var W,q=`for(${e.it?`ο=[ρ=λ=${R.length>0?"χ=":""}0]`:""};λ<${$};`+(R.length>0?"ο[λ++]=ν-="+(1<1?`(${R.map((t=>"ν=="+t)).join("|")})&&ν`:`ν==${R[0]}&&ν`):"ο[λ++]=ν-"+(1<(α=π[δ]+=`+`(β*${D(h)}-π[δ]<<${29-h})/`+`((κ[δ]+=κ[δ]<${u})+${I})`+`>>${29-h},ω[μ]+=ε[μ]*(β-Σ/θ))),ν=ν*2+β)for(`+(L?`φ='${A.map((t=>t.join(""))).join("0")}'.split(Σ=0)`:"Σ=0,φ="+JSON.stringify(A))+".map((δ,μ)=>(α=0,"+(L?"[...δ]":"δ")+".map((δ,μ)=>(α=α*997+(ο[λ-δ]|0)|0)),"+`${D(l)}-1&α*997+ν${R.length>0?"+!!χ*129":""}`+`)*${_}+μ),ε=φ.map((δ,μ)=>(α=π[δ]*2+1,α=Math.log(α/(θ-α)),Σ-=ω[μ]*α,α/`+f+")),Σ=~-θ/(1+Math.exp(Σ))|1,β=τ%θ<Σ,"+`τ=τ%θ+(β?Σ:θ-Σ)*(τ>>${h+1})-!β*Σ;τ<`+D(22)+";τ=τ*64|ι.charCodeAt(ρ++)&63);",V="κ",[G]=t.text||t.js;switch(G.i){case"text":V=O(r.ft);break;case"js":if(0===i.dt.length)V=`κ=${e.it?"π=":""}${O()}`;else if(i.dt.length<3)for(var[,Q]of(q+=`κ=${e.it?"π=":""}${O()};`,i.dt))q+=`with(κ.split(\`${W=Q,P[W]||W}\`))κ=join(shift());`;else{var Z=new Set(i.dt.map((([,t])=>t.charCodeAt(0)))),X=j(Z,!0),H=j(Z,!1),K=H.lengtht)).join("")+[..."Σαβδεθκλμνοπρτφχω"].filter((t=>T.every((([e])=>t!==e)))).join(""),it="McharCodeAtUinyxp"+(R.length>0?"f":"");if(e.it)J+=";",q=T.map((([t,e])=>`${t}=${e};`)).join("")+q+tt+V+et;else{J=`Function("[${J}"`,q=`,...']${it.slice(1)}',"`+q;var at="[],"+T.map((([,t])=>t)).join(",");Y?(J=tt+J,q+=`return${V.match(/^[A-Za-z0-9_$\u0380-\u03ff]/)?" ":""}${V}")(${at})${et}`):q+=`${tt}${V}${et}")(${at})`}var st=new Map([...rt].map(((t,e)=>[t,it[e]])));J=J.replace(/[^\0-\x7f]/g,(t=>st.get(t))),q=q.replace(/[^\0-\x7f]/g,(t=>st.get(t)));var ot=["δ","μ"];return{Et:J,St:m,At:q,kt:e.it?Object.keys(st).filter((t=>!ot.includes(t))).map((t=>st[t])).sort():[],undefined:i.undefined}}Ct(){var t=B.yt(this.st,this.et);return this.et.rt>t.undefined&&(this.et.rt=t.undefined),new E(t)}async zt(t,e){"function"==typeof t&&(e=t,t=0),t=t||1;var r=await(async()=>globalThis.performance||(await"perf_hooks").performance)(),i=-1,a=t=>{var e={...this.st};t.Lt&&(e.text||e.js)&&(e.text=[...e.text||[],...(e.js||[]).map((t=>({...t,i:"text"})))],delete e.js);var r=B.yt(e,{...this.et,...t});return i<0&&(i=r.undefined),new E(r).Rt()},s=async(t,r,i,a,s,o)=>{if(e){var u={It:t,Pt:r,Ut:i,Ft:a,jt:s,Ot:n,Dt:h,Jt:o};if(!1===await e(u))throw Error("search aborted")}},o=r.now(),n={},h=a(n);await s("initial",void 0,n,h,!1,!0);var u=t=>{var e=a(t),r=!1;return e{var{size:i,Jt:a}=u(t);return await s(e,r,t,i,!a,a),i},f=async(e,r,i,a,s)=>{if(t<=1)for(var o=0;oMath.round(Math.sqrt(t*e)):(t,e)=>t+e>>1;for(var h=new Map,u=1===i?Math.log2(r)-Math.log2(e)+1:r-e,c=async t=>{var a=h.get(t);if(!a){var o=1===i?Math.log2(r)-Math.log2(e)+1:r-e;a=await s(t,1-Math.log(o)/Math.log(u)),h.set(t,a)}return a},f=n(e,r);r-e>=4;){var l=[e,n(e,f),f,n(f,r),r],p=[];for(var v of l)p.push(await c(v));var d=0;for(o=1;o<5;++o)p[d]>p[o]&&(d=o);0===d?f=n(e,r=l[1]):4===d?f=n(e=l[3],r):(e=l[d-1],f=l[d],r=l[d+1])}for(v=e+1;vawait c({...n,k:t},"modelRecipBaseCount",e))),await f(1,32767,1,[4,5,6],(async(t,e)=>await c({...n,A:t},"modelMaxCount",e))),n.A===this.et.A&&delete n.A,await f(0,i,0,[0,16,32,64],(async(t,e)=>await c({...n,rt:t},"numAbbreviations",e))),n.rt===this.et.rt&&delete n.rt,await c({...n,Lt:!0},"preferTextOverJS");for(var l=this.et.X.slice(),p=h,v=(new Map,1),d=t>=2?.1:.9;v>d;){var w,$=l.slice();do{w=512*Math.random()|0}while($.includes(w));$[Math.random()*$.length|0]=w,$.sort(((t,e)=>t-e));var{size:y,Jt:m}=u({...n,X:$}),b=Math.exp((p-y)/(6*v))await c({...n,v:t},"precision",e))),n.v===this.et.v&&delete n.v,await f(1,99999,1,[500,750,1e3,1250,1500],(async(t,e)=>await c({...n,W:t},"recipLearningRate",e))),n.W===this.et.W&&delete n.W,this.et={...this.et,...n},n.Lt&&(this.st.text||this.st.js)&&(this.st.text=[...this.st.text||[],...(this.st.js||[]).map((t=>({...t,i:"text"})))],delete this.st.js),{Nt:r.now()-o,Ot:n,Dt:h}}}class E{constructor({Et:t,St:e,At:r,kt:i}){this.Et=t,this.St=e,this.At=r,this.kt=i}Rt(){return 35+this.Et.replace(/[\x1c\x3f-\x7e]/g,"").length+Math.ceil(this.St*(1+1/384))+(t=>{if(t.length>2583||t.match(/[^\0-\xff]/))throw Error("estimateDeflatedSize: too long or non-Latin1 input");var e=[256],r=[],i=0,a={},s=(e,r)=>{var i;for(i=0;i<258&&t[e+i]===t[r+i];++i);return i};t:for(var o=0;o>2))<0);++f);for(l=0;l<29&&!((v-=1<>1))<0);++l);e.push(257+f),r.push(l),i+=(f<28?Math.max(0,f-4>>2):0)+Math.max(0,l-2>>1),o+=n}}var d=t=>{var e=new Map;for(var r of t)e.set(r,(e.get(r)||0)+1);for(var i=[...e.entries()];i.length>1;){i.sort((([t,e],[r,i])=>i-e||(tr?1:0)));var[a,s]=i.pop(),[o,n]=i.pop();i.push([[a,o],s+n])}var h=[],u=0,c=(t,r)=>{t.length?(c(t[0],r+1),c(t[1],r+1)):(h[t]=r,u+=r*e.get(t))};return c(i[0][0],0),[u,h]},[w,$]=d(e),[y,m]=d(r),b=[],_=0,g=-1,x=0;for(var p of[...$,...m,-1])if((p|=0)===g)++x;else{for(;x>=(g>0?4:3);){var[M,B,E]=g>0?[16,2,7]:x<11?[17,3,10]:[18,7,138];g>0&&b.push(g),b.push(M),_+=B,x-=E}for(;x-- >0;)b.push(g);g=p,x=1}var[S]=d(b),A=17+3*Math.max(...b.map((t=>[4,18,16,14,12,10,8,6,5,7,9,11,13,15,17,19,1,2,3][t])))+S+_+w+y+i,k=3+e.reduce(((t,e)=>t+(e<144?8:e<256?9:e<280?7:8)),0)+5*r.length+i;return Math.min(A,k,40+8*t.length)+7>>3})(this.At)}}var S=new class{constructor(){this.Tt=new Map}l(t,e){var r,i=this.Tt.get(e);return i&&(r=i.pop()),r||(r=new ArrayBuffer(e)),r}D(t){var e=this.Tt.get(t.byteLength);e||this.Tt.set(t.byteLength,e=[]),e.push(t)}},A=!0,k=null,C=0,z=!1,L=0,R=()=>{_L.textContent="Optimize parameters",L=0,z||P(!1)},I=(t,e,r)=>{var i=e>0?100-r/e*100:-1/0;_Q.textContent=`${t}${r.toLocaleString()}B estimated, ${Math.abs(i).toFixed(2)}% ${i>0?"smaller":"larger"}`},P=async t=>{_M.classList.add("_Z"),_P.textContent="",_Q.textContent="waiting...",_V.textContent="-",_I.hidden=!0,k=null;var e=C;try{var r=Number(_E.value);if(!(10<=r&&r<=1024))throw"maximum memory usage should be between 10 MB and 1 GB";var i=[];for(var a of _B.children)i.push(a.Wt());if(i.some((t=>!t)))return;var s,o=i.reduce(((t,e)=>t+e.qt),0);if(e=++C,A||t)A=!1;else if(await new Promise((t=>setTimeout(t,300))),e!==C)return;if(_Q.textContent=t?"optimizing...":"compressing...",await new Promise((t=>setTimeout(t,1))),_T.value.trim()){if((s=_T.value.split(/,/g).map((t=>parseInt(t,10))).sort(((t,e)=>t-e))).length<1)throw"no contexts";if(s.length>64)throw"too many contexts";if(s.some((t=>t!=t||t<0||t>=2147483648)))throw"invalid context selector";if(s.find(((t,e)=>s[e-1]===t)))throw"duplicate context selectors"}else s=_();var n=parseInt(_R.value,10);if(!(1<=n&&n<=28))throw"invalid precision";var h=parseInt(_D.value,10);if(!(1<=h&&h<=99999))throw"invalid learning rate";var u=parseInt(_G.value,10);if(!(1<=u&&u<=32767))throw"invalid model max count";var c=parseInt(_F.value,10);if(!(1<=c&&c<=99999))throw"invalid model base divisor";var f=parseInt(_J.value,10);if(!(0<=f&&f<=64))throw"invalid number of abbreviations";var l={tt:r,C:S,X:s,v:n,W:h,A:u,k:c,rt:f,it:_A.checked},p="",v=new B(i,l);if(_V.textContent=v.ut,t){L<2&&++L;var d=0,w=await v.zt(L,(async t=>{var e=128336+d++%12,r=t.It+("number"==typeof t.Pt?` ${(100*t.Pt).toFixed(1)}%`:"");I(`${String.fromCodePoint(e)} optimizing ${r}: `,o,t.Dt),console.info(`(${r}) ${JSON.stringify(t.Ut)}:`,t.Ft,...t.Jt?["<-"]:t.jt?["x"]:[]),await new Promise((t=>requestAnimationFrame(t)))}));if(p=`optimized in ${(w.Nt/1e3).toFixed(1)}s: `,w.Ot.X&&(s=w.Ot.X),w.Ot.v&&(_R.value=w.Ot.v),w.Ot.A&&(_G.value=w.Ot.A),w.Ot.k&&(_F.value=w.Ot.k),w.Ot.W&&(_D.value=w.Ot.W),void 0!==w.Ot.rt&&(_J.value=w.Ot.rt),w.Ot.Lt)for(var a of _B.children)"js"===a._i.value&&(a._i.value="text");_L.textContent="Optimize parameters (harder)"}_T.value=s.join(",");var $=v.Ct();if(!t&&e!==C)return;k=$.Et+"\n"+$.At,_N.textContent=$.Et+"\n",_O.textContent=$.At,I(p,o,$.Rt()),_I.hidden=!1}catch(t){_Q.textContent="failed",_P.textContent="Error: "+t,_N.textContent=_O.textContent="",console.error(t)}finally{e===C&&_M.classList.remove("_Z")}};_I.onclick=()=>{var t=window.open(""),e=document.createElement("script");e.textContent=k,t.document.head.append(e)},_K.onchange=()=>{var t=parseInt(_K.value,10);if(!(1<=t&&t<=64))throw"invalid number of contexts";var e=_T.value.split(/,/g).map((t=>{var e=parseInt(t,10);return e==e?e:t}));if(e.lengtht-e)));e.length{_K.value=_T.value.split(/,/g).length,R()},_E.onchange=_R.onchange=_D.onchange=_G.onchange=_F.onchange=_J.onchange=_A.onchange=()=>R(),_S.onclick=()=>{for(var t of[_E,_K,_T,_R,_D,_G,_F,_J])t.value=t.getAttribute("value");_A.checked=!1,R()},_L.onclick=async()=>{if(!z){z=!0,_S.disabled=_L.disabled=!0;try{await P(!0)}finally{z=!1,_S.disabled=_L.disabled=!1}}};var U=(()=>{var t=_C.content.firstElementChild.cloneNode(!0);for(var e of t.querySelectorAll("[id]"))t[e.id]=e,e.removeAttribute("id");var r="",i=-1;return t._c.oninput=()=>{t._e.textContent="",null!==(r=t._c.value)?(t._h.textContent=(i=Array.isArray(r)?r.length:unescape(encodeURIComponent(r)).length).toLocaleString(),R()):(i=-1,t._h.textContent="-")},t._i.onchange=()=>{t._c.oninput(),null!==r&&R()},t._b.onchange=()=>{null!==r&&R()},t.Wt=()=>{if(null!==r)return{i:t._i.value.replace(/:.*$/,""),nt:r,qt:i,ht:t._b.value}},t})();_B.append(U),U._c.value="document.write`\n\n"+__.innerText+"`",U._c.oninput(),github.hidden=!0;