memoscan
← all memos

Memo 0xcce4eda4…7f6bf4 on Ethereum

ex,cellIndices:n}),n}doesLineFullyIntersectFace(e,t){const n=this.lines.get(e),i=this.lineMeta.get(e);if(!n||!i)return!1;const l=t.hedges.map((e=>{let t=new nn;return t.expands([e.origin,e.nexthedge.origin]),{aabb:t,edge:e}})),a=[],s=i.isClosed?n.length:n.length-1;for(let e=0;e<s;e++){const t=new zt(...n[e]),i=new zt(...n[(e+1)%n.length]),s=i.x-t.x,o=i.y-t.y,r=s*s+o*o;let c=new nn;c.expands([t,i]);for(const{aabb:n,edge:d}of l){if(!n.intersects(c))continue;const l=d.intersectWithLineSegment([t,i]);if(l?.type===gn.intersecting&&l.point){const n=((l.point.x-t.x)*s+(l.point.y-t.y)*o)/r;a.push(e+n)}}}a.sort(((e,t)=>e-t));const o=a.filter(((e,t)=>0===t||Math.abs(e-a[t-1])>b));if(o.length<2)return!1;const r=new zt(...n[0]);let c=t.containsPoint(r)&&!t.isPointOnBoundary(r);for(let e=0;e<o.length-1;e++){c=!c;const i=o[e],l=o[e+1];if(i<b||l>s-b)continue;if(!c)continue;const a=(i+l)/2,r=Math.floor(a)%n.length,d=a-Math.floor(a),u=new zt(...n[r]),h=new zt(...n[(r+1)%n.length]),m=new zt(u.x+(h.x-u.x)*d,u.y+(h.y-u.y)*d);if(t.containsPoint(m)&&!t.isPointOnBoundary(m))return!0}return!1}linesIntersectingAABB(e){const t=this.aabbLineIntersectionCache.get(e);if(t)return t;const n=new Set,i=f(e.minX/this.cellSize),l=f(e.maxX/this.cellSize),a=f(e.minY/this.cellSize),s=f(e.maxY/this.cellSize);for(let e=i;e<=l;e++)for(let t=a;t<=s;t++){const i=this.getCellIndex(e,t);this.cells.has(i)&&this.cells.get(i).forEach((e=>n.add(e)))}const o=[...n].map((e=>({constructionLine:{id:e,line:this.lines.get(e),meta:this.lineMeta.get(e)},intersectionType:Qn.intersecting})));return this.aabbLineIntersectionCache.set(e,o),o}getLinesIntersectingFace(e,t=!0){const n=this.getCellsIntersectedByFace(e),i=new Set;for(const e of n){const t=this.cells.get(e);if(t)for(const e of t)i.add(e)}let l=Array.from(i);return t&&(l=l.filter((t=>this.doesLineFullyIntersectFace(t,e)))),l.map((e=>({constructionLine:{id:e,line:this.lines.get(e),meta:this.lineMeta.get(e)},intersectionType:Qn.intersecting})))}getGridDistanceField(e=0,t=0){let{cellSize:n}=this;const i=new Set,l=new Set,a=[];let s=f(t/n),o=f((Y-2*t)/n),r=f(t/n),c=f((P-2*t)/n);for(let t=s;t<=o;t++)for(let n=r;n<=c;n++){const l=this.getCellIndex(t,n);(!this.cells.has(l)||this.cells.get(l)?.size<=e)&&i.add(l)}const d=(e,t)=>{const n=[e];for(;n.length>0;){const e=n.pop();if(!e||l.has(e)||!i.has(e))continue;l.add(e);const[a,s]=this.getCellXYfromIndex(e);t.indices.push(e);const o=[this.getCellIndex(a-1,s),this.getCellIndex(a+1,s),this.getCellIndex(a,s-1),this.getCellIndex(a,s+1)];for(const e of o)!l.has(e)&&i.has(e)&&n.push(e)}};i.forEach((e=>{if(!l.has(e)){const t={vertices:[],indices:[]};d(e,t),t.indices.length>1&&a.push(t)}}));let u=this.distanceCalculator||new Bn(s,r,o,c);return u.initializeWithEmptyCells(i,this.getCellXYfromIndex.bind(this)),a.map((e=>{const t=new nn;let n=[];e.indices.forEach((e=>{const[t,i]=this.getCellXYfromIndex(e),l=u.getDistance(t,i);n.push([l,this.getCellVertexFromIndex(e)])}));let i=n.reduce(((e,t)=>e[0]>t[0]?e:t));return t.expands(n.map((([,e])=>e))),{aabb:t,cellCount:e.indices.length,maxDistance:i[0],cellsByDistance:n,indices:e.indices.map((e=>this.getCellVertexFromIndex(e)))}}))}}function jn(e){const[t,n,i]=e;return`oklch(${(100*(t||0)).toFixed(2)}% ${(n||0).toFixed(2)} ${(i||0).toFixed(2)})`}function An(e){e.forEach((e=>{const[t,n,i]=e;jn(e)}))}function En(e){const n=e.slice();for(let e=n.length-1;e>0;e--){const i=t(J.dec()*(e+1));[n[e],n[i]]=[n[i],n[e]]}return n}function _n(e,t="right"){const n=e.slice();if("right"===t){const e=n.pop();void 0!==e&&n.unshift(e)}else if("left"===t){const e=n.shift();void 0!==e&&n.push(e)}return n}const qn=e=>e,$n=e=>1-l(e*g/2),ei=e=>-(l(g*e)-1)/2,ti=e=>e<.5?(1-d(1-a(2*e,2)))/2:(d(1-a(-2*e+2,2))+1)/2;let ni={};const ii=(e,t=5,n=0,i=qn,l=[])=>{const a=`${e}-${n}-${t}`;if(ni[a]?.min)return ni[a];let s=0,o=-1/0,r=1/0,c=0,d=[],u=(t,l)=>{let a=i(mn(t,l,n,e));s+=a,c+=1,a>o&&(o=a),a<r&&(r=a),d.push(a)};if(l.length)for(let e of l)u(e.x,e.y);else for(let e=0;e<20*ze.countX;e+=ze.w/20)for(let t=0;t<20*ze.countY;t+=ze.h/20)u(e,t);let h={max:o,min:r,mean:s/c,indexValues:[],mostCommonIndex:0,leastCommonIndex:0};return d.map((e=>{let n=f(Tt(e,h.min,h.max,0,t-1));h.indexValues[n]=h.indexValues[n]?h.indexValues[n]+1:1})),h.mostCommonIndex=h.indexValues.reduce(((e,t,n)=>t>h.indexValues[e]?n:e),0),h.leastCommonIndex=h.indexValues.reduce(((e,t,n)=>t<h.indexValues[e]?n:e),0),ni[a]=h,h};let li=[],ai=[],si=[],oi=new Set,ri={L:1,C:1,H:2/Math.PI},ci=30,di=ei;function ui(e,t,n=ri){e=Nt(e),t=Nt(t);const{L:i,C:l,H:a}=n,s=e[0]-t[0],o=e[1]-t[1];let r=e[2]-t[2];r=(r+180)%360-180;const c=r*Math.PI/180;return Math.sqrt(s*s*i+o*o*l+c*c*a)}function hi(e,t,n,i=1,l="fg",a=[]){let s,o=t,r=ve.bg[0][0]>=.5,c=a?.[0];if(o==ye.previous)return c;if(o==ye.brightnessBasedShadowOrHighlight){let t,a=c||Gi(e,n,i,null,l),s=i>=wt(Ke.max,Ke.min,.5),o=.2;if(a[0]>.75&&!s&&(o=.02),s){let e=bi(a,si,o);t=[wt(a[0]+o,e[0],.5),e[1],e[2]]}else{let e=bi(a,si,-o);t=[wt(a[0]+-o,e[0],.5),e[1],e[2]]}return Nt(t)}ye.lightestOrDarkestBasedOnBg==o&&(o=r?ye.lightest:ye.darkest);let d=c||Gi(e,n,i,null,l),u=d[0]>.7&&d[1]<.05;switch(o){case ye.color:s=Gi(e,n,i,null,l);break;case ye.randomAccent:s=e.choice(li);break;case ye.base:s=ve.base[0];break;case ye.line:s=ve.line.reduce(((e,t)=>r?e[0]<t[0]?e:t:e[0]>t[0]?e:t),ve.line[0]);break;case ye.shadow:let t=c||Gi(e,n,i,null,l);s=gi([.3*t[0],t[1],t[2]],si,0)[0];break;case ye.highlight:let a=c||Gi(e,n,i,null,l);s=gi([kt(0,1,1.5*a[0]),a[1],a[2]],si,0)[0];break;case ye.offset:s=u?d:gi(c||d,si,ci*e.choice([-1,1]),1)[0];break;case ye.offsetUp:s=u?d:gi(c||d,si,ci,1)[0];break;case ye.palettecomplement:s=gi(c||d,li,180)[0];break;case ye.offsetDown:s=u?d:gi(c||d,si,ci,-1)[0];break;case ye.darkest:s=li.reduce(((e,t)=>e[0]<t[0]?e:t),li[0]);break;case ye.lightest:s=li.reduce(((e,t)=>e[0]>t[0]?e:t),li[0])}return oi.add(s),s}function mi(e,t,n=0){if(0===t.length)throw Error("Palette is empty.");const i=t.map((t=>({color:t,dist:ui(e,t)})));return i.sort(((e,t)=>e.dist-t.dist)),i.slice(0,n).map((e=>e.color))}function pi(e,t){let n=e.leastCommonIndex,i=e.mostCommonIndex,l=t.reduce(((e,t)=>e[0]<t[0]?e:t),t[0]),a=t.reduce(((e,t)=>e[0]>t[0]?e:t),t[0]);const s=(t.indexOf(l)-n+t.length)%t.length;let o=t.slice(s).concat(t.slice(0,s));if(o.indexOf(a)===i){const e=[];for(let t=0;t<o.length;t++)t!==i&&t!==n&&e.push(t);if(e.length>0){const t=J.choice(e);[o[i],o[t]]=[o[t],o[i]]}}return o}function gi(e,t,n=20,i=1){return mi([e[0],e[1],Ft(e[2]+n)],t.filter((e=>e)),i)}function bi(e,t,n=1){const i=[kt(0,1,e[0]+n),e[1],e[2]];let l;for(let e of t){let t=ui(i,e,ri);(!l||t<l.dist)&&(l={color:e,dist:t})}return l.color}let fi,xi,Zi=new Map,yi=new Set;function Gi(e,t,n=1,i=null,l="fg",a=null){let{freqMultiplier:o,singleAccent:r,usePolyIDColorOffset:d}=Oe,u=0,h="fg"==l?li:ai,m="fg"==l?fi:xi,p="fg"==l?o:500*o,g="bg"==l?Tt(t.y,0,P,0,h.length-1):Tt(di(mn(t.x,t.y,0,p,0,1)),m.min,m.max,0,h.length-1);if(d){let n=Xl.getPolygonsAtPoint(t.toArray()).filter((e=>yi.has(e.meta.meta.id))).sort(((e,t)=>e.meta.meta.totalArea-t.meta.meta.totalArea)),i=n?.[0];if(i){let t=i.meta.meta.id;Zi.has(t)||Zi.set(t,e.int(1,h.length-1)),u+=Zi.get(t)}}if(null!==i){let t=gi(a||h[c(s(g+u))%h.length],si,ci*i,Oe.samplesForComplimentary);return e.choice(t)}return h[c(s(g+u))%h.length]}function Wi(e,t,n){var i;return function(t){return i=i||function(e){var t=function(e){return atob(e)}(e),n=t.indexOf("\n",10)+1,i=t.substring(n)+"",l=new Blob([i],{type:"application/javascript"});return URL.createObjectURL(l)}(e),new Worker(i,t)}}var vi=Wi("Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwohZnVuY3Rpb24oKXsidXNlIHN0cmljdCI7Y29uc3R7Zmxvb3I6ZSxjZWlsOnQsc2luOmksY29zOm4scG93OnMsYWJzOnIsbWluOm8sbWF4OmwsaHlwb3Q6aCxyb3VuZDphLHNxcnQ6YyxhY29zOmQsc2lnbjpnLGxvZzpmLFBJOnV9PU1hdGgscD0xZS03O2Z1bmN0aW9uIHgodCxpPXApe3JldHVybiBlKHQraSl9ZnVuY3Rpb24geShlLGk9cCl7cmV0dXJuIHQoZS1pKX1mdW5jdGlvbiBtKGUsdD1wKXtyZXR1cm4gYShlL3QpKnR9ZnVuY3Rpb24gdyhlLHQ9cCl7Y29uc3QgaT10KmcoZSk7cmV0dXJuIGEoZStpKX1jbGFzcyBie3VzZUE7cHJuZ0E7cHJuZ0I7aGFzaDtjb25zdHJ1Y3RvcihlKXt0aGlzLnVzZUE9ITEsdGhpcy5oYXNoPWU7Y29uc3QgdD1nbG9iYWxUaGlzLnBhcnNlSW50O2xldCBpPWZ1bmN0aW9uKGUpe2xldCBpPXQoZS5zdWJzdHJpbmcoMCw4KSwxNiksbj10KGUuc3Vic3RyaW5nKDgsMTYpLDE2KSxzPXQoZS5zdWJzdHJpbmcoMTYsMjQpLDE2KSxyPXQoZS5zdWJzdHJpbmcoMjQsMzIpLDE2KTtyZXR1cm4gZnVuY3Rpb24oKXtpfD0wLG58PTAsc3w9MCxyfD0wO2xldCBlPShpK258MCkrcnwwO3JldHVybiByPXIrMXwwLGk9bl5uPj4+OSxuPXMrKHM8PDMpfDAscz1zPDwyMXxzPj4+MTEscz1zK2V8MCwoZT4+PjApLzQyOTQ5NjcyOTZ9fTt0aGlzLnBybmdBPWkodGhpcy5oYXNoLnN1YnN0cmluZygyLDM0KSksdGhpcy5wcm5nQj1pKHRoaXMuaGFzaC5zdWJzdHJpbmcoMzQsNjYpKX1kZWMoKXtyZXR1cm4gdGhpcy51c2VBPSF0aGlzLnVzZUEsdGhpcy51c2VBP3RoaXMucHJuZ0EoKTp0aGlzLnBybmdCKCl9bnVtKGUsdCl7cmV0dXJuIGUrKHQtZSkqdGhpcy5kZWMoKX1pbnQodCxpKXtyZXR1cm4gZSh0aGlzLm51bSh0LGkrMSkpfWJvb2woZT01MCl7cmV0dXJuIHRoaXMuZGVjKCk8ZS8xMDB9Y2hvaWNlKGUpe3JldHVybiBlW3RoaXMuaW50KDAsZS5sZW5ndGgtMSldfWVhc2VkRGVjKGUpe3JldHVybiBlKHRoaXMuZGVjKCkpfWVhc2VkSW50KHQsaSxuKXtyZXR1cm4gZSh0aGlzLmVhc2VkTnVtKHQsaSxuKSl9ZWFzZWROdW0oZSx0LGkpe3JldHVybiB0KyhpLXQpKnRoaXMuZWFzZWREZWMoZSl9d2VpZ2h0ZWRDaG9pY2UoLi4uZSl7Y29uc3QgdD1lLnJlZHVjZSgoKGUsW3RdKT0+ZSt0KSwwKTtsZXQgaT10aGlzLmRlYygpKnQ7Zm9yKGNvbnN0W3Qsbl1vZiBlKWlmKChpLT10KTwwKXJldHVybiBuO3JldHVybiBlW2UubGVuZ3RoLTFdWzFdfWdhdXNzaWFuKGU9MCx0PTEpe2xldCBpPTAscz0wO2Zvcig7MD09PWk7KWk9dGhpcy5kZWMoKTtmb3IoOzA9PT1zOylzPXRoaXMuZGVjKCk7cmV0dXJuIGMoLTIqZihpKSkqbigyKnUqcykqdCtlfWdhdXNzaWFuQm9vbChlPTAsdD0wLGk9MSl7cmV0dXJuIHRoaXMuZ2F1c3NpYW4odCxpKT49ZX19bGV0IHY7Y29uc3QgTT00MDk1LFA9ZT0+LjUqKDEtbihlKnUpKTtsZXQgWTtmdW5jdGlvbiBBKGUpe2lmKGUpWT1lO2Vsc2V7WT1uZXcgRmxvYXQzMkFycmF5KDQwOTYpO2ZvcihsZXQgZT0wO2U8NDA5NjtlKyspWVtlXT12LmRlYygpfX1sZXQgUz0wO2NsYXNzIER7eDt5O2lkPVMrKztoZWRnZWxpc3Q9W107Y29uc3RydWN0b3IoZT0wLHQ9MCl7dGhpcy54PWUsdGhpcy55PXR9c29ydGluY2lkZW50KCl7dGhpcy5oZWRnZWxpc3QmJnRoaXMuaGVkZ2VsaXN0LnNvcnQoWCl9c3VidHJhY3QoZSl7cmV0dXJuIG5ldyBEKHRoaXMueC1lLngsdGhpcy55LWUueSl9YWRkUG9sYXIoZSx0KXtyZXR1cm4gbmV3IEQodGhpcy54K3QqbihlKSx0aGlzLnkrdCppKGUpKX1ub3JtYWxpemUoZT1wKXtjb25zdCB0PWModGhpcy54KnRoaXMueCt0aGlzLnkqdGhpcy55KTtyZXR1cm4gdDxlP25ldyBEKDAsMCk6bmV3IEQodGhpcy54L3QsdGhpcy55L3QpfW11bHRpcGx5KGUpe3JldHVybiBuZXcgRCh0aGlzLngqZSx0aGlzLnkqZSl9YWRkKGUpe3JldHVybiBuZXcgRCh0aGlzLngrZS54LHRoaXMueStlLnkpfXRvQXJyYXkoKXtyZXR1cm5bdGhpcy54LHRoaXMueV19ZnJvbUFycmF5KGUpe3JldHVybiB0aGlzLng9ZVswXSx0aGlzLnk9ZVsxXSx0aGlzfWRpc3RhbmNlVG8oZSl7cmV0dXJuIGMocyhlLngtdGhpcy54LDIpK3MoZS55LXRoaXMueSwyKSl9YW5nbGVUbyhlKXtyZXR1cm4gTWF0aC5hdGFuMihlLnktdGhpcy55LGUueC10aGlzLngpfWxlcnAoZSx0KXtyZXR1cm4gbmV3IEQodGhpcy54KyhlLngtdGhpcy54KSp0LHRoaXMueSsoZS55LXRoaXMueSkqdCl9dHJhbnNsYXRlKGUsdCl7dGhpcy54Kz10Km4oZSksdGhpcy55Kz10KmkoZSl9Y2xvbmUoKXtyZXR1cm4gbmV3IEQodGhpcy54LHRoaXMueSl9aXNFcXVhbFRvKGUsdD1wKXtjb25zdCBpPWUueC10aGlzLngsbj1lLnktdGhpcy55O3JldHVybiBpKmkrbipuPD10KnR9aXNDbG9zZVRvKGUsdD1wKXtyZXR1cm4gdGhpcy5kaXN0YW5jZVRvKGUpPHR9ZGlzcG9zZSgpe3RoaXMuaGVkZ2VsaXN0Lmxlbmd0aD0wfX1mdW5jdGlvbiBYKGUsdCl7cmV0dXJuIHQuYW5nbGUtZS5hbmdsZX1jb25zdCBfPXA7dmFyIEY7ZnVuY3Rpb24gSShlLHQsaT0hMSl7bGV0IG49MS8wO2NvbnN0IHM9dC5sZW5ndGgscj1pP3M6cy0xO2ZvcihsZXQgaT0wO2k8cjtpKyspe2NvbnN0IHI9VihlLHRbaV0saT09PXMtMT90WzBdOnRbaSsxXSk7aWYocjxfKXJldHVybiAwO249TWF0aC5taW4obixyKX1yZXR1cm4gTWF0aC5zcXJ0KG4pfWZ1bmN0aW9uIEIoZSx0LGkpe3JldHVybiBjKFYoZSx0LGkpKX1mdW5jdGlvbiBWKGUsdCxpKXtjb25zdFtuLHNdPXQsW3Isb109aSxbbCxoXT1lLGE9ci1uLGM9by1zLGQ9YSphK2MqYztpZihkPF8pe2NvbnN0IGU9bC1uLHQ9aC1zO3JldHVybiBlKmUrdCp0fWxldCBnPSgobC1uKSphKyhoLXMpKmMpL2Q7ZzwtMWUtNz9nPTA6Zz4xK18mJihnPTEpO2NvbnN0IGY9bC0obitnKmEpLHU9aC0ocytnKmMpO3JldHVybiBmKmYrdSp1fSFmdW5jdGlvbihlKXtlW2UuaW50ZXJzZWN0aW5nPTBdPSJpbnRlcnNlY3RpbmciLGVbZS5jb2xpbmVhcj0xXT0iY29saW5lYXIiLGVbZS5wYXJhbGxlbD0yXT0icGFyYWxsZWwifShGfHwoRj17fSkpO2NvbnN0IEM9KGUsdCxpKT0+KHQtZSkqaStlLEw9KGUsdCxpLG4scyk9PkMobixzLCgoZSx0LGkpPT4oaS1lKS8odC1lKSkodCxpLGUpKTtmdW5jdGlvbiBSKGUsdCxpKXtyZXR1cm4gbyhsKGUsdCksaSl9Y29uc3QgTz0oZSx0LGksbixzKT0+UihMKGUsdCxpLG4scyksbixzKSxFPWU9PmkoZSp1LzIpLFQ9ZT0+MT09PWU/MToxLXMoMiwtMTAqZSk7Y2xhc3MgTnttaW5YPTEvMDttaW5ZPTEvMDttYXhYPS0xLzA7bWF4WT0tMS8wO2NvbnN0cnVjdG9yKCl7fWdldCB3aWR0aCgpe3JldHVybiB0aGlzLm1heFgtdGhpcy5taW5YfWdldCBoZWlnaHQoKXtyZXR1cm4gdGhpcy5tYXhZLXRoaXMubWluWX1nZXQgY2VudGVyKCl7cmV0dXJuIG5ldyBEKCh0aGlzLm1pblgrdGhpcy5tYXhYKS8yLCh0aGlzLm1pblkrdGhpcy5tYXhZKS8yKX1nZXQgdmVydGV4TGlzdCgpe3JldHVybltuZXcgRCh0aGlzLm1pblgsdGhpcy5taW5ZKSxuZXcgRCh0aGlzLm1heFgsdGhpcy5taW5ZKSxuZXcgRCh0aGlzLm1heFgsdGhpcy5tYXhZKSxuZXcgRCh0aGlzLm1pblgsdGhpcy5tYXhZKV19Z2V0IGFyZWEoKXtyZXR1cm4gdGhpcy53aWR0aCp0aGlzLmhlaWdodH1yZXNldCgpe3RoaXMubWluWD0xLzAsdGhpcy5taW5ZPTEvMCx0aGlzLm1heFg9LTEvMCx0aGlzLm1heFk9LTEvMH1leHBhbmQoZSl7dGhpcy5taW5YPU1hdGgubWluKGUueCx0aGlzLm1pblgpLHRoaXMubWluWT1NYXRoLm1pbihlLnksdGhpcy5taW5ZKSx0aGlzLm1heFg9TWF0aC5tYXgoZS54LHRoaXMubWF4WCksdGhpcy5tYXhZPU1hdGgubWF4KGUueSx0aGlzLm1heFkpfWV4cGFuZHMoZSl7Zm9yKGxldCB0PTAsaT1lLmxlbmd0aDt0PGk7dCsrKXRoaXMuZXhwYW5kKGVbdF0pO3JldHVybiB0aGlzfWV4cGFuZEJ5UG9pbnQoZSl7cmV0dXJuIHRoaXMubWluWD1NYXRoLm1pbihlWzBdLHRoaXMubWluWCksdGhpcy5taW5ZPU1hdGgubWluKGVbMV0sdGhpcy5taW5ZKSx0aGlzLm1heFg9TWF0aC5tYXgoZVswXSx0aGlzLm1heFgpLHRoaXMubWF4WT1NYXRoLm1heChlWzFdLHRoaXMubWF4WSksdGhpc31leHBhbmRzQnlQb2ludChlKXtmb3IobGV0IHQ9MCxpPWUubGVuZ3RoO3Q8aTt0KyspdGhpcy5leHBhbmRCeVBvaW50KGVbdF0pfWludGVyc2VjdHMoZSx0PXApe3JldHVybiEoZS5tYXhYPHRoaXMubWluWC10fHxlLm1pblg+dGhpcy5tYXhYK3R8fGUubWF4WTx0aGlzLm1pblktdHx8ZS5taW5ZPnRoaXMubWF4WSt0KX1leHBhbmRCeVZhbHVlKGUpe3JldHVybiB0aGlzLm1pblgtPWUsdGhpcy5taW5ZLT1lLHRoaXMubWF4WCs9ZSx0aGlzLm1heFkrPWUsdGhpc31jb250YWluc1BvaW50KGUpe3JldHVybiBlLng8PXRoaXMubWF4WCtwJiZlLng+PXRoaXMubWluWC1wJiZlLnk8PXRoaXMubWF4WStwJiZlLnk+PXRoaXMubWluWS1wfWRpc3RhbmNlVG9Qb2ludChlKXtjb25zdCB0PWwodGhpcy5taW5YLWUueCwwLGUueC10aGlzLm1heFgpLGk9bCh0aGlzLm1pblktZS55LDAsZS55LXRoaXMubWF4WSk7cmV0dXJuIGModCp0K2kqaSl9Y29udGFpbnNCQihlKXtyZXR1cm4gZS5taW5YPj10aGlzLm1pblgtcCYmZS5tYXhYPD10aGlzLm1heFgrcCYmZS5taW5ZPj10aGlzLm1pblktcCYmZS5tYXhZPD10aGlzLm1heFkrcH1jb250YWluc1BvaW50cyhlKXtmb3IobGV0IHQ9MCxpPWUubGVuZ3RoO3Q8aTt0KyspaWYoIXRoaXMuY29udGFpbnNQb2ludChlW3RdKSlyZXR1cm4hMTtyZXR1cm4hMH1zaXplKCl7cmV0dXJue3dpZHRoOnRoaXMubWF4WC10aGlzLm1pblgsaGVpZ2h0OnRoaXMubWF4WS10aGlzLm1pbll9fX1sZXQgaz0wO2NsYXNzIHp7djE7djI7aWQ9aysrO29yaWdpbjthbmdsZTtsZW5ndGg7dHdpbj1udWxsO25leHRoZWRnZT1udWxsO3ByZXZoZWRnZT1udWxsO2ZhY2U9bnVsbDtjb25zdHJ1Y3RvcihlLHQpe3RoaXMudjE9ZSx0aGlzLnYyPXQsdGhpcy5pZD1rKyssdGhpcy5vcmlnaW49dCx0aGlzLmFuZ2xlPWZ1bmN0aW9uKGUsdCl7bGV0IGk9dC54LWUueCxuPXQueS1lLnk7Y29uc3Qgcz1jKGkqaStuKm4pO3JldHVybiBuPjA/ZChpL3MpOjIqdS1kKGkvcyl9KGUsdCksdGhpcy5sZW5ndGg9YyhzKHQueC1lLngsMikrcyh0LnktZS55LDIpKX1kaXNwb3NlKCl7dGhpcy5vcmlnaW49bnVsbCx0aGlzLnR3aW49bnVsbCx0aGlzLm5leHRoZWRnZT1udWxsLHRoaXMucHJldmhlZGdlPW51bGwsdGhpcy5mYWNlPW51bGx9Z2V0QUFCQigpe2xldCBlPW5ldyBOO3JldHVybiBlLmV4cGFuZHMoW3RoaXMub3JpZ2luLHRoaXMudHdpbi5vcmlnaW5dKSxlfWludGVyc2VjdFdpdGhMaW5lU2VnbWVudChbZSx0XSl7cmV0dXJuIGZ1bmN0aW9uKGUsdCxpLG4pe2NvbnN0e3g6cyx5OnJ9PWUse3g6byx5Omx9PXQse3g6aCx5OmF9PWkse3g6Yyx5OmR9PW4sZz0oZC1hKSooby1zKS0oYy1oKSoobC1yKSxmPShjLWgpKihyLWEpLShkLWEpKihzLWgpLHU9KG8tcykqKHItYSktKGwtcikqKHMtaCk7aWYoTWF0aC5hYnMoZyk8XylyZXR1cm4gTWF0aC5hYnMoZik8XyYmTWF0aC5hYnModSk8Xz97dHlwZTpGLmNvbGluZWFyLHBvaW50Om51bGwsdWE6MCx1YjowfTp7dHlwZTpGLnBhcmFsbGVsLHBvaW50Om51bGwsdWE6MCx1YjowfTtjb25zdCBwPWYvZyx4PXUvZztyZXR1cm4gcD49LTFlLTcmJnA8PTErXyYmeD49LTFlLTcmJng8PTErXz97dHlwZTpGLmludGVyc2VjdGluZyxwb2ludDpuZXcgRChzK3AqKG8tcykscitwKihsLXIpKSx1YTpwLHViOnh9Ont0eXBlOm51bGwscG9pbnQ6bnVsbCx1YTpwLHViOnh9fSh0aGlzLm9yaWdpbix0aGlzLnR3aW4ub3JpZ2luLGUsdCl9fWNvbnN0IFc9cDtjbGFzcyBHe3RvbGVyYW5jZTt2ZXJ0aWNlcz1bXTtoZWRnZXM9W107ZmFjZXM9W107dmVydGV4TWFwPW5ldyBNYXA7Y29uc3RydWN0b3IoZSx0LGk9Vyl7dGhpcy50b2xlcmFuY2U9aSxlJiZ0JiZ0aGlzLnNldERhdGFzKGUsdCl9Z2V0VmVydGV4S2V5KGUsdCl7Y29uc3QgaT1lL3RoaXMudG9sZXJhbmNlLG49dC90aGlzLnRvbGVyYW5jZTtyZXR1cm5gJHt3KGksdGhpcy50b2xlcmFuY2UpfSwke3cobix0aGlzLnRvbGVyYW5jZSl9YH1hZGRWZXJ0ZXgoZSx0KXtjb25zdCBpPXRoaXMuZ2V0VmVydGV4S2V5KGUsdCk7bGV0IG49dGhpcy52ZXJ0ZXhNYXAuZ2V0KGkpO258fChuPVtdLHRoaXMudmVydGV4TWFwLnNldChpLG4pKTtmb3IoY29uc3QgaSBvZiBuKWlmKHRoaXMuaXNDbG9zZShpLngsZSkmJnRoaXMuaXNDbG9zZShpLnksdCkpcmV0dXJuIGk7Y29uc3Qgcz1uZXcgRChlLHQpO3JldHVybiB0aGlzLnZlcnRpY2VzLnB1c2gocyksbi5wdXNoKHMpLHN9ZGVsZXRlVmVydGV4KGUpe2NvbnN0IHQ9dGhpcy5nZXRWZXJ0ZXhLZXkoZS54LGUueSksaT10aGlzLnZlcnRleE1hcC5nZXQodCk7aWYoaSl7Y29uc3Qgbj1pLmluZGV4T2YoZSk7bj4tMSYmKGkuc3BsaWNlKG4sMSksMD09PWkubGVuZ3RoJiZ0aGlzLnZlcnRleE1hcC5kZWxldGUodCkpfWNvbnN0IG49dGhpcy52ZXJ0aWNlcy5pbmRleE9mKGUpO24+LTEmJnRoaXMudmVydGljZXMuc3BsaWNlKG4sMSksZS5kaXNwb3NlKCl9ZmluZFZlcnRleChlLHQpe2NvbnN0IGk9dGhpcy5nZXRWZXJ0ZXhLZXkoZSx0KSxuPXRoaXMudmVydGV4TWFwLmdldChpKTtpZihuKWZvcihjb25zdCBpIG9mIG4paWYodGhpcy5pc0Nsb3NlKGkueCxlKSYmdGhpcy5pc0Nsb3NlKGkueSx0KSlyZXR1cm4gaTtyZXR1cm4gbnVsbH12ZXJ0aWNlc0luUG9seShlKXtsZXQgdD1lLm1hcCgoZT0+KG5ldyBEKS5mcm9tQXJyYXkoZSkpKSxpPW5ldyBOO2kuZXhwYW5kcyh0KTtsZXQgbj1bXSxzPXRoaXMudmVydGljZXNJbkJCKGkpO2ZvcihsZXQgZSBvZiBzKWVlKHQsZSkmJm4ucHVzaChlKTtyZXR1cm4gbn12ZXJ0aWNlc0luQkIoZSl7Y29uc3QgdD1bXTtmb3IobGV0IGkgb2YgdGhpcy52ZXJ0aWNlcyllLmNvbnRhaW5zUG9pbnQoaSkmJnQucHVzaChpKTtyZXR1cm4gdH1zZXREYXRhcyhlLHQpe2NvbnN0e3ZlcnRpY2VzOmksaGVkZ2VzOm4sZmFjZXM6c309dGhpcztmb3IobGV0IHQ9MCxpPWUubGVuZ3RoO3Q8aTt0Kyspe2NvbnN0IGk9ZVt0XTt0aGlzLmFkZFZlcnRleChpWzBdLGlbMV0pfWZvcihsZXQgZT0wLHM9dC5sZW5ndGg7ZTxzO2UrKyl7Y29uc3Qgcz10W2VdLHI9bmV3IHooaVtzWzBdXSxpW3NbMV1dKSxvPW5ldyB6KGlbc1sxXV0saVtzWzBdXSk7ci50d2luPW8sby50d2luPXIsaVtzWzFdXS5oZWRnZWxpc3QucHVzaChyKSxpW3NbMF1dLmhlZGdlbGlzdC5wdXNoKG8pLG4ucHVzaChvKSxuLnB1c2gocil9Zm9yKGxldCBlPTAsdD1pLmxlbmd0aDtlPHQ7ZSsrKXtjb25zdCB0PWlbZV07dC5zb3J0aW5jaWRlbnQoKTtjb25zdCBuPXQuaGVkZ2VsaXN0Lmxlbmd0aDtpZigwIT1uKWlmKG48Mil0LmhlZGdlbGlzdFswXS5wcmV2aGVkZ2U9dC5oZWRnZWxpc3RbMF0udHdpbix0LmhlZGdlbGlzdFswXS50d2luLm5leHRoZWRnZT10LmhlZGdlbGlzdFswXTtlbHNle2ZvcihsZXQgZT0wO2U8bi0xO2UrKyl0LmhlZGdlbGlzdFtlXS50d2luLm5leHRoZWRnZT10LmhlZGdlbGlzdFtlKzFdLHQuaGVkZ2VsaXN0W2UrMV0ucHJldmhlZGdlPXQuaGVkZ2VsaXN0W2VdLnR3aW47dC5oZWRnZWxpc3Rbbi0xXS50d2luLm5leHRoZWRnZT10LmhlZGdlbGlzdFswXSx0LmhlZGdlbGlzdFswXS5wcmV2aGVkZ2U9dC5oZWRnZWxpc3Rbbi0xXS50d2lufX1jb25zdCByPW4uc2xpY2UoMCk7bGV0IG89bi5sZW5ndGg7Zm9yKDtvPjA7KXtsZXQgZT1yLnBvcCgpO2lmKG8tPTEsbnVsbD09ZS5mYWNlKXtjb25zdCB0PW5ldyBKKHRoaXMpO2Zvcih0LndlZGdlPWUsdC53ZWRnZS5mYWNlPXQ7ZS5uZXh0aGVkZ2UhPT10LndlZGdlOyllPWUubmV4dGhlZGdlLGUuZmFjZT10O3MucHVzaCh0KX19fWludGVybmFsRmFjZXMoKXtjb25zdCBlPVtdLHQ9dGhpcy5mYWNlcztmb3IobGV0IGk9MCxuPXQubGVuZ3RoO2k8bjtpKyspe2NvbnN0IG49dFtpXTtuLmludGVybmFsJiZlLnB1c2gobil9cmV0dXJuIGV9ZXh0ZXJuYWxGYWNlcygpe2NvbnN0IGU9W10sdD10aGlzLmZhY2VzO2ZvcihsZXQgaT0wLG49dC5sZW5ndGg7aTxuO2krKyl7Y29uc3Qgbj10W2ldO24uZXh0ZXJuYWwmJmUucHVzaChuKX1yZXR1cm4gZX1kaXNwb3NlKCl7Y29uc3R7dmVydGljZXM6ZSxoZWRnZXM6dCxmYWNlczppfT10aGlzO2ZvcihsZXQgdD0wLGk9ZS5sZW5ndGg7dDxpO3QrKyllW3RdLmRpc3Bvc2UoKTtmb3IobGV0IGU9MCxpPXQubGVuZ3RoO2U8aTtlKyspdFtlXS5kaXNwb3NlKCk7Zm9yKGxldCBlPTAsdD1pLmxlbmd0aDtlPHQ7ZSsrKWlbZV0uZGlzcG9zZSgpO2UubGVuZ3RoPTAsdC5sZW5ndGg9MCxpLmxlbmd0aD0wfWlzQ2xvc2U9KGUsdCk9PnIoZS10KTx0aGlzLnRvbGVyYW5jZTtmaW5kSGVkZ2UoZSx0LGksbil7Y29uc3R7aXNDbG9zZTpzfT10aGlzLHI9dGhpcy5maW5kVmVydGV4KGUsdCk7aWYocilmb3IoY29uc3QgZSBvZiByLmhlZGdlbGlzdCl7Y29uc3QgdD1lLnR3aW4ub3JpZ2luO2lmKHModC54LGkpJiZzKHQueSxuKSlyZXR1cm4gZX1jb25zdCBvPXRoaXMuZmluZFZlcnRleChpLG4pO2lmKG8pZm9yKGNvbnN0IGkgb2Ygby5oZWRnZWxpc3Qpe2NvbnN0IG49aS50d2luLm9yaWdpbjtpZihzKG4ueCxlKSYmcyhuLnksdCkpcmV0dXJuIGl9cmV0dXJuIG51bGx9YWRkRWRnZShlLHQsaSxuKXtjb25zdHt2ZXJ0aWNlczpzLGhlZGdlczpyLGZhY2VzOm99PXRoaXM7bGV0IGw9ITEsaD0hMSxhPSExLGM9dGhpcy5maW5kVmVydGV4KGUsdCk7Y3x8KGM9dGhpcy5hZGRWZXJ0ZXgoZSx0KSxsPSEwKTtsZXQgZD10aGlzLmZpbmRWZXJ0ZXgoaSxuKTtkfHwoZD10aGlzLmFkZFZlcnRleChpLG4pLGg9ITApO2NvbnN0IGc9bmV3IHooZCxjKTtyLnB1c2goZyksYy5oZWRnZWxpc3QucHVzaChnKSxjLnNvcnRpbmNpZGVudCgpO2NvbnN0IGY9bmV3IHooYyxkKTtpZihyLnB1c2goZiksZC5oZWRnZWxpc3QucHVzaChmKSxkLnNvcnRpbmNpZGVudCgpLGcudHdpbj1mLGYudHdpbj1nLGwpZy5wcmV2aGVkZ2U9ZixmLm5leHRoZWRnZT1nO2Vsc2V7Y29uc3QgZT1jLmhlZGdlbGlzdC5pbmRleE9mKGcpO2xldCB0LGk7MD09PWU/KHQ9Yy5oZWRnZWxpc3RbYy5oZWRnZWxpc3QubGVuZ3RoLTFdLGk9Yy5oZWRnZWxpc3RbKGUrMSklYy5oZWRnZWxpc3QubGVuZ3RoXSk6KHQ9Yy5oZWRnZWxpc3RbZS0xXSxpPWMuaGVkZ2VsaXN0WyhlKzEpJWMuaGVkZ2VsaXN0Lmxlbmd0aF0pLGcucHJldmhlZGdlPXQudHdpbix0LnR3aW4ubmV4dGhlZGdlPWcsZi5uZXh0aGVkZ2U9aSxpLnByZXZoZWRnZT1mfWlmKGgpZi5wcmV2aGVkZ2U9ZyxnLm5leHRoZWRnZT1mO2Vsc2V7Y29uc3QgZT1kLmhlZGdlbGlzdC5pbmRleE9mKGYpO2xldCB0LGk7MD09PWU/KHQ9ZC5oZWRnZWxpc3RbZC5oZWRnZWxpc3QubGVuZ3RoLTFdLGk9ZC5oZWRnZWxpc3RbKGUrMSklZC5oZWRnZWxpc3QubGVuZ3RoXSk6KHQ9ZC5oZWRnZWxpc3RbZS0xXSxpPWQuaGVkZ2VsaXN0WyhlKzEpJWQuaGVkZ2VsaXN0Lmxlbmd0aF0pLGYucHJldmhlZGdlPXQudHdpbix0LnR3aW4ubmV4dGhlZGdlPWYsZy5uZXh0aGVkZ2U9aSxpLnByZXZoZWRnZT1nfWNvbnN0IHU9Zy5uZXh0aGVkZ2UscD1mLm5leHRoZWRnZTtpZih1LmZhY2Upe2NvbnN0IGU9by5pbmRleE9mKHUuZmFjZSk7ZT4tMSYmby5zcGxpY2UoZSwxKSx1LmZhY2UuZGlzcG9zZSgpLHUuZmFjZS5hcmVhPD10aGlzLnRvbGVyYW5jZSYmKGE9ITApfWlmKHAuZmFjZSl7Y29uc3QgZT1vLmluZGV4T2YocC5mYWNlKTtlPi0xJiZvLnNwbGljZShlLDEpLHAuZmFjZS5kaXNwb3NlKCkscC5mYWNlLmFyZWE8PXRoaXMudG9sZXJhbmNlJiYoYT0hMCl9Y29uc3QgeD1uZXcgSih0aGlzKTt4LndlZGdlPXU7bGV0IHk9bmV3IEoodGhpcyk7aWYoeS53ZWRnZT1wLHguZXF1YWxzKHkpJiYoeS5kaXNwb3NlKCkseT1udWxsKSx4KXtsZXQgZT14LndlZGdlO2ZvcihlLmZhY2U9eDtlLm5leHRoZWRnZSE9PXgud2VkZ2U7KWU9ZS5uZXh0aGVkZ2UsZS5mYWNlPXg7eC5hcmVhPD10aGlzLnRvbGVyYW5jZSYmKGE9ITApLG8ucHVzaCh4KX1pZih5KXtsZXQgZT15LndlZGdlO2ZvcihlLmZhY2U9eTtlLm5leHRoZWRnZSE9PXkud2VkZ2U7KWU9ZS5uZXh0aGVkZ2UsZS5mYWNlPXk7eS5hcmVhPD10aGlzLnRvbGVyYW5jZSYmKGE9ITApLG8ucHVzaCh5KX1pZihhKWZvcihsZXQgZT0wLHQ9by5sZW5ndGg7ZTx0O2UrKylvW2VdLl9ob2xlc0RpcnR5PSEwfXJlbW92ZUVkZ2UoZSx0LGksbil7Y29uc3R7dmVydGljZXM6cyxoZWRnZXM6cixmYWNlczpvfT10aGlzLGw9dGhpcy5maW5kSGVkZ2UoZSx0LGksbik7aWYoIWwpcmV0dXJuO2NvbnN0IGg9bC50d2luLGE9bC5uZXh0aGVkZ2UsYz1oLm5leHRoZWRnZTtsZXQgZCxnPSEwLGY9ITAsdT0hMTtpZihkPXIuaW5kZXhPZihsKSxyLnNwbGljZShkLDEpLGQ9ci5pbmRleE9mKGgpLHIuc3BsaWNlKGQsMSksZD1vLmluZGV4T2YobC5mYWNlKSxkPi0xJiZvLnNwbGljZShkLDEpLGwuZmFjZS5kaXNwb3NlKCksbC5mYWNlLmFyZWE8PXRoaXMudG9sZXJhbmNlJiYodT0hMCksZD1vLmluZGV4T2YoaC5mYWNlKSxkPi0xJiZvLnNwbGljZShkLDEpLGguZmFjZS5kaXNwb3NlKCksaC5mYWNlLmFyZWE8PXRoaXMudG9sZXJhbmNlJiYodT0hMCksZD1sLm9yaWdpbi5oZWRnZWxpc3QuaW5kZXhPZihsKSxsLm9yaWdpbi5oZWRnZWxpc3Quc3BsaWNlKGQsMSksbC5vcmlnaW4uaGVkZ2VsaXN0Lmxlbmd0aD4wKXtsZXQgZSx0OzA9PT1kPyhlPWwub3JpZ2luLmhlZGdlbGlzdFtsLm9yaWdpbi5oZWRnZWxpc3QubGVuZ3RoLTFdLHQ9bC5vcmlnaW4uaGVkZ2VsaXN0W2RdKTooZT1sLm9yaWdpbi5oZWRnZWxpc3RbZC0xXSx0PWwub3JpZ2luLmhlZGdlbGlzdFtkJWwub3JpZ2luLmhlZGdlbGlzdC5sZW5ndGhdKSx0LnByZXZoZWRnZT1lLnR3aW4sZS50d2luLm5leHRoZWRnZT10fWVsc2UgdGhpcy5kZWxldGVWZXJ0ZXgobC5vcmlnaW4pLGY9ITE7aWYoZD1oLm9yaWdpbi5oZWRnZWxpc3QuaW5kZXhPZihoKSxoLm9yaWdpbi5oZWRnZWxpc3Quc3BsaWNlKGQsMSksaC5vcmlnaW4uaGVkZ2VsaXN0Lmxlbmd0aD4wKXtsZXQgZSx0OzA9PT1kPyhlPWgub3JpZ2luLmhlZGdlbGlzdFtoLm9yaWdpbi5oZWRnZWxpc3QubGVuZ3RoLTFdLHQ9aC5vcmlnaW4uaGVkZ2VsaXN0W2RdKTooZT1oLm9yaWdpbi5oZWRnZWxpc3RbZC0xXSx0PWgub3JpZ2luLmhlZGdlbGlzdFtkJWgub3JpZ2luLmhlZGdlbGlzdC5sZW5ndGhdKSx0LnByZXZoZWRnZT1lLnR3aW4sZS50d2luLm5leHRoZWRnZT10fWVsc2UgdGhpcy