@c4h/chuci 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -32
- package/LICENSE +20 -20
- package/README.ja.md +143 -143
- package/README.md +224 -224
- package/dist/chuci.js +9068 -6596
- package/dist/chuci.umd.js +165 -166
- package/dist/index.d.ts +1 -0
- package/package.json +36 -33
- package/src/components/swiper/cc-swiper-slide.ts +49 -49
- package/src/components/swiper/cc-swiper-styles.ts +28 -28
- package/src/components/swiper/cc-swiper.ts +379 -361
- package/src/components/swiper/swiper-styles.css +4 -4
- package/src/components/viewer/cc-viewer-3dmodel.ts +491 -491
- package/src/components/viewer/cc-viewer-base.ts +278 -278
- package/src/components/viewer/cc-viewer-gaussian.ts +380 -380
- package/src/components/viewer/cc-viewer-image.ts +189 -189
- package/src/components/viewer/cc-viewer-panorama.ts +85 -85
- package/src/components/viewer/cc-viewer-styles.ts +55 -55
- package/src/components/viewer/cc-viewer-video.ts +109 -109
- package/src/components/viewer/cc-viewer-youtube.ts +75 -75
- package/src/components/viewer/cc-viewer.ts +290 -290
- package/src/index.ts +24 -24
- package/src/types/css-modules.d.ts +1 -1
- package/src/types/global.d.ts +10 -10
- package/src/utils/base-element.ts +76 -76
- package/dist/assets/azumaya_panorama1.png +0 -0
- package/dist/chuci.cjs +0 -4483
- package/dist/index-8VMexD2a.cjs +0 -255
- package/dist/index-kvsisbKS.js +0 -2125
- package/dist/index.html +0 -241
- package/dist/test-image.html +0 -63
package/dist/index-8VMexD2a.cjs
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class I{constructor(t=0,F=0,U=0){this.x=t,this.y=F,this.z=U}equals(t){return this.x===t.x&&this.y===t.y&&this.z===t.z}add(t){return typeof t=="number"?new I(this.x+t,this.y+t,this.z+t):new I(this.x+t.x,this.y+t.y,this.z+t.z)}subtract(t){return typeof t=="number"?new I(this.x-t,this.y-t,this.z-t):new I(this.x-t.x,this.y-t.y,this.z-t.z)}multiply(t){return typeof t=="number"?new I(this.x*t,this.y*t,this.z*t):t instanceof I?new I(this.x*t.x,this.y*t.y,this.z*t.z):new I(this.x*t.buffer[0]+this.y*t.buffer[4]+this.z*t.buffer[8]+t.buffer[12],this.x*t.buffer[1]+this.y*t.buffer[5]+this.z*t.buffer[9]+t.buffer[13],this.x*t.buffer[2]+this.y*t.buffer[6]+this.z*t.buffer[10]+t.buffer[14])}divide(t){return typeof t=="number"?new I(this.x/t,this.y/t,this.z/t):new I(this.x/t.x,this.y/t.y,this.z/t.z)}cross(t){const F=this.y*t.z-this.z*t.y,U=this.z*t.x-this.x*t.z,l=this.x*t.y-this.y*t.x;return new I(F,U,l)}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lerp(t,F){return new I(this.x+(t.x-this.x)*F,this.y+(t.y-this.y)*F,this.z+(t.z-this.z)*F)}min(t){return new I(Math.min(this.x,t.x),Math.min(this.y,t.y),Math.min(this.z,t.z))}max(t){return new I(Math.max(this.x,t.x),Math.max(this.y,t.y),Math.max(this.z,t.z))}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error(`Invalid component index: ${t}`)}}minComponent(){return this.x<this.y&&this.x<this.z?0:this.y<this.z?1:2}maxComponent(){return this.x>this.y&&this.x>this.z?0:this.y>this.z?1:2}magnitude(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}distanceTo(t){return Math.sqrt((this.x-t.x)**2+(this.y-t.y)**2+(this.z-t.z)**2)}normalize(){const t=this.magnitude();return new I(this.x/t,this.y/t,this.z/t)}flat(){return[this.x,this.y,this.z]}clone(){return new I(this.x,this.y,this.z)}toString(){return`[${this.flat().join(", ")}]`}static One(t=1){return new I(t,t,t)}}class z{constructor(t=0,F=0,U=0,l=1){this.x=t,this.y=F,this.z=U,this.w=l}equals(t){return this.x===t.x&&this.y===t.y&&this.z===t.z&&this.w===t.w}normalize(){const t=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);return new z(this.x/t,this.y/t,this.z/t,this.w/t)}multiply(t){const F=this.w,U=this.x,l=this.y,a=this.z,n=t.w,e=t.x,Q=t.y,d=t.z;return new z(F*e+U*n+l*d-a*Q,F*Q-U*d+l*n+a*e,F*d+U*Q-l*e+a*n,F*n-U*e-l*Q-a*d)}inverse(){const t=this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w;return new z(-this.x/t,-this.y/t,-this.z/t,this.w/t)}apply(t){const F=new z(t.x,t.y,t.z,0),U=new z(-this.x,-this.y,-this.z,this.w),l=this.multiply(F).multiply(U);return new I(l.x,l.y,l.z)}flat(){return[this.x,this.y,this.z,this.w]}clone(){return new z(this.x,this.y,this.z,this.w)}static FromEuler(t){const F=t.x/2,U=t.y/2,l=t.z/2,a=Math.cos(U),n=Math.sin(U),e=Math.cos(F),Q=Math.sin(F),d=Math.cos(l),A=Math.sin(l);return new z(a*Q*d+n*e*A,n*e*d-a*Q*A,a*e*A-n*Q*d,a*e*d+n*Q*A)}toEuler(){const t=2*(this.w*this.x+this.y*this.z),F=1-2*(this.x*this.x+this.y*this.y),U=Math.atan2(t,F);let l;const a=2*(this.w*this.y-this.z*this.x);l=Math.abs(a)>=1?Math.sign(a)*Math.PI/2:Math.asin(a);const n=2*(this.w*this.z+this.x*this.y),e=1-2*(this.y*this.y+this.z*this.z),Q=Math.atan2(n,e);return new I(U,l,Q)}static FromMatrix3(t){const F=t.buffer,U=F[0]+F[4]+F[8];let l,a,n,e;if(U>0){const Q=.5/Math.sqrt(U+1);e=.25/Q,l=(F[7]-F[5])*Q,a=(F[2]-F[6])*Q,n=(F[3]-F[1])*Q}else if(F[0]>F[4]&&F[0]>F[8]){const Q=2*Math.sqrt(1+F[0]-F[4]-F[8]);e=(F[7]-F[5])/Q,l=.25*Q,a=(F[1]+F[3])/Q,n=(F[2]+F[6])/Q}else if(F[4]>F[8]){const Q=2*Math.sqrt(1+F[4]-F[0]-F[8]);e=(F[2]-F[6])/Q,l=(F[1]+F[3])/Q,a=.25*Q,n=(F[5]+F[7])/Q}else{const Q=2*Math.sqrt(1+F[8]-F[0]-F[4]);e=(F[3]-F[1])/Q,l=(F[2]+F[6])/Q,a=(F[5]+F[7])/Q,n=.25*Q}return new z(l,a,n,e)}static FromAxisAngle(t,F){const U=F/2,l=Math.sin(U),a=Math.cos(U);return new z(t.x*l,t.y*l,t.z*l,a)}static LookRotation(t){const F=new I(0,0,1),U=F.dot(t);if(Math.abs(U- -1)<1e-6)return new z(0,1,0,Math.PI);if(Math.abs(U-1)<1e-6)return new z;const l=Math.acos(U),a=F.cross(t).normalize();return z.FromAxisAngle(a,l)}toString(){return`[${this.flat().join(", ")}]`}}class ut{constructor(){const t=new Map;this.addEventListener=(F,U)=>{t.has(F)||t.set(F,new Set),t.get(F).add(U)},this.removeEventListener=(F,U)=>{t.has(F)&&t.get(F).delete(U)},this.hasEventListener=(F,U)=>!!t.has(F)&&t.get(F).has(U),this.dispatchEvent=F=>{if(t.has(F.type))for(const U of t.get(F.type))U(F)}}}class Ut{constructor(t=1,F=0,U=0,l=0,a=0,n=1,e=0,Q=0,d=0,A=0,i=1,r=0,c=0,B=0,W=0,J=1){this.buffer=[t,F,U,l,a,n,e,Q,d,A,i,r,c,B,W,J]}equals(t){if(this.buffer.length!==t.buffer.length)return!1;if(this.buffer===t.buffer)return!0;for(let F=0;F<this.buffer.length;F++)if(this.buffer[F]!==t.buffer[F])return!1;return!0}multiply(t){const F=this.buffer,U=t.buffer;return new Ut(U[0]*F[0]+U[1]*F[4]+U[2]*F[8]+U[3]*F[12],U[0]*F[1]+U[1]*F[5]+U[2]*F[9]+U[3]*F[13],U[0]*F[2]+U[1]*F[6]+U[2]*F[10]+U[3]*F[14],U[0]*F[3]+U[1]*F[7]+U[2]*F[11]+U[3]*F[15],U[4]*F[0]+U[5]*F[4]+U[6]*F[8]+U[7]*F[12],U[4]*F[1]+U[5]*F[5]+U[6]*F[9]+U[7]*F[13],U[4]*F[2]+U[5]*F[6]+U[6]*F[10]+U[7]*F[14],U[4]*F[3]+U[5]*F[7]+U[6]*F[11]+U[7]*F[15],U[8]*F[0]+U[9]*F[4]+U[10]*F[8]+U[11]*F[12],U[8]*F[1]+U[9]*F[5]+U[10]*F[9]+U[11]*F[13],U[8]*F[2]+U[9]*F[6]+U[10]*F[10]+U[11]*F[14],U[8]*F[3]+U[9]*F[7]+U[10]*F[11]+U[11]*F[15],U[12]*F[0]+U[13]*F[4]+U[14]*F[8]+U[15]*F[12],U[12]*F[1]+U[13]*F[5]+U[14]*F[9]+U[15]*F[13],U[12]*F[2]+U[13]*F[6]+U[14]*F[10]+U[15]*F[14],U[12]*F[3]+U[13]*F[7]+U[14]*F[11]+U[15]*F[15])}clone(){const t=this.buffer;return new Ut(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])}determinant(){const t=this.buffer;return t[12]*t[9]*t[6]*t[3]-t[8]*t[13]*t[6]*t[3]-t[12]*t[5]*t[10]*t[3]+t[4]*t[13]*t[10]*t[3]+t[8]*t[5]*t[14]*t[3]-t[4]*t[9]*t[14]*t[3]-t[12]*t[9]*t[2]*t[7]+t[8]*t[13]*t[2]*t[7]+t[12]*t[1]*t[10]*t[7]-t[0]*t[13]*t[10]*t[7]-t[8]*t[1]*t[14]*t[7]+t[0]*t[9]*t[14]*t[7]+t[12]*t[5]*t[2]*t[11]-t[4]*t[13]*t[2]*t[11]-t[12]*t[1]*t[6]*t[11]+t[0]*t[13]*t[6]*t[11]+t[4]*t[1]*t[14]*t[11]-t[0]*t[5]*t[14]*t[11]-t[8]*t[5]*t[2]*t[15]+t[4]*t[9]*t[2]*t[15]+t[8]*t[1]*t[6]*t[15]-t[0]*t[9]*t[6]*t[15]-t[4]*t[1]*t[10]*t[15]+t[0]*t[5]*t[10]*t[15]}invert(){const t=this.buffer,F=this.determinant();if(F===0)throw new Error("Matrix is not invertible.");const U=1/F;return new Ut(U*(t[5]*t[10]*t[15]-t[5]*t[11]*t[14]-t[9]*t[6]*t[15]+t[9]*t[7]*t[14]+t[13]*t[6]*t[11]-t[13]*t[7]*t[10]),U*(-t[1]*t[10]*t[15]+t[1]*t[11]*t[14]+t[9]*t[2]*t[15]-t[9]*t[3]*t[14]-t[13]*t[2]*t[11]+t[13]*t[3]*t[10]),U*(t[1]*t[6]*t[15]-t[1]*t[7]*t[14]-t[5]*t[2]*t[15]+t[5]*t[3]*t[14]+t[13]*t[2]*t[7]-t[13]*t[3]*t[6]),U*(-t[1]*t[6]*t[11]+t[1]*t[7]*t[10]+t[5]*t[2]*t[11]-t[5]*t[3]*t[10]-t[9]*t[2]*t[7]+t[9]*t[3]*t[6]),U*(-t[4]*t[10]*t[15]+t[4]*t[11]*t[14]+t[8]*t[6]*t[15]-t[8]*t[7]*t[14]-t[12]*t[6]*t[11]+t[12]*t[7]*t[10]),U*(t[0]*t[10]*t[15]-t[0]*t[11]*t[14]-t[8]*t[2]*t[15]+t[8]*t[3]*t[14]+t[12]*t[2]*t[11]-t[12]*t[3]*t[10]),U*(-t[0]*t[6]*t[15]+t[0]*t[7]*t[14]+t[4]*t[2]*t[15]-t[4]*t[3]*t[14]-t[12]*t[2]*t[7]+t[12]*t[3]*t[6]),U*(t[0]*t[6]*t[11]-t[0]*t[7]*t[10]-t[4]*t[2]*t[11]+t[4]*t[3]*t[10]+t[8]*t[2]*t[7]-t[8]*t[3]*t[6]),U*(t[4]*t[9]*t[15]-t[4]*t[11]*t[13]-t[8]*t[5]*t[15]+t[8]*t[7]*t[13]+t[12]*t[5]*t[11]-t[12]*t[7]*t[9]),U*(-t[0]*t[9]*t[15]+t[0]*t[11]*t[13]+t[8]*t[1]*t[15]-t[8]*t[3]*t[13]-t[12]*t[1]*t[11]+t[12]*t[3]*t[9]),U*(t[0]*t[5]*t[15]-t[0]*t[7]*t[13]-t[4]*t[1]*t[15]+t[4]*t[3]*t[13]+t[12]*t[1]*t[7]-t[12]*t[3]*t[5]),U*(-t[0]*t[5]*t[11]+t[0]*t[7]*t[9]+t[4]*t[1]*t[11]-t[4]*t[3]*t[9]-t[8]*t[1]*t[7]+t[8]*t[3]*t[5]),U*(-t[4]*t[9]*t[14]+t[4]*t[10]*t[13]+t[8]*t[5]*t[14]-t[8]*t[6]*t[13]-t[12]*t[5]*t[10]+t[12]*t[6]*t[9]),U*(t[0]*t[9]*t[14]-t[0]*t[10]*t[13]-t[8]*t[1]*t[14]+t[8]*t[2]*t[13]+t[12]*t[1]*t[10]-t[12]*t[2]*t[9]),U*(-t[0]*t[5]*t[14]+t[0]*t[6]*t[13]+t[4]*t[1]*t[14]-t[4]*t[2]*t[13]-t[12]*t[1]*t[6]+t[12]*t[2]*t[5]),U*(t[0]*t[5]*t[10]-t[0]*t[6]*t[9]-t[4]*t[1]*t[10]+t[4]*t[2]*t[9]+t[8]*t[1]*t[6]-t[8]*t[2]*t[5]))}static Compose(t,F,U){const l=F.x,a=F.y,n=F.z,e=F.w,Q=l+l,d=a+a,A=n+n,i=l*Q,r=l*d,c=l*A,B=a*d,W=a*A,J=n*A,h=e*Q,C=e*d,k=e*A,p=U.x,X=U.y,D=U.z;return new Ut((1-(B+J))*p,(r+k)*p,(c-C)*p,0,(r-k)*X,(1-(i+J))*X,(W+h)*X,0,(c+C)*D,(W-h)*D,(1-(i+B))*D,0,t.x,t.y,t.z,1)}toString(){return`[${this.buffer.join(", ")}]`}}class qt extends Event{constructor(t){super("objectAdded"),this.object=t}}class $t extends Event{constructor(t){super("objectRemoved"),this.object=t}}class tl extends Event{constructor(t){super("objectChanged"),this.object=t}}class It extends ut{constructor(){super(),this.positionChanged=!1,this.rotationChanged=!1,this.scaleChanged=!1,this._position=new I,this._rotation=new z,this._scale=new I(1,1,1),this._transform=new Ut,this._changeEvent=new tl(this),this.update=()=>{},this.applyPosition=()=>{this.position=new I},this.applyRotation=()=>{this.rotation=new z},this.applyScale=()=>{this.scale=new I(1,1,1)},this.raiseChangeEvent=()=>{this.dispatchEvent(this._changeEvent)}}_updateMatrix(){this._transform=Ut.Compose(this._position,this._rotation,this._scale)}get position(){return this._position}set position(t){this._position.equals(t)||(this._position=t,this.positionChanged=!0,this._updateMatrix(),this.dispatchEvent(this._changeEvent))}get rotation(){return this._rotation}set rotation(t){this._rotation.equals(t)||(this._rotation=t,this.rotationChanged=!0,this._updateMatrix(),this.dispatchEvent(this._changeEvent))}get scale(){return this._scale}set scale(t){this._scale.equals(t)||(this._scale=t,this.scaleChanged=!0,this._updateMatrix(),this.dispatchEvent(this._changeEvent))}get forward(){let t=new I(0,0,1);return t=this.rotation.apply(t),t}get transform(){return this._transform}}class tt{constructor(t=1,F=0,U=0,l=0,a=1,n=0,e=0,Q=0,d=1){this.buffer=[t,F,U,l,a,n,e,Q,d]}equals(t){if(this.buffer.length!==t.buffer.length)return!1;if(this.buffer===t.buffer)return!0;for(let F=0;F<this.buffer.length;F++)if(this.buffer[F]!==t.buffer[F])return!1;return!0}multiply(t){const F=this.buffer,U=t.buffer;return new tt(U[0]*F[0]+U[3]*F[1]+U[6]*F[2],U[1]*F[0]+U[4]*F[1]+U[7]*F[2],U[2]*F[0]+U[5]*F[1]+U[8]*F[2],U[0]*F[3]+U[3]*F[4]+U[6]*F[5],U[1]*F[3]+U[4]*F[4]+U[7]*F[5],U[2]*F[3]+U[5]*F[4]+U[8]*F[5],U[0]*F[6]+U[3]*F[7]+U[6]*F[8],U[1]*F[6]+U[4]*F[7]+U[7]*F[8],U[2]*F[6]+U[5]*F[7]+U[8]*F[8])}clone(){const t=this.buffer;return new tt(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8])}static Eye(t=1){return new tt(t,0,0,0,t,0,0,0,t)}static Diagonal(t){return new tt(t.x,0,0,0,t.y,0,0,0,t.z)}static RotationFromQuaternion(t){return new tt(1-2*t.y*t.y-2*t.z*t.z,2*t.x*t.y-2*t.z*t.w,2*t.x*t.z+2*t.y*t.w,2*t.x*t.y+2*t.z*t.w,1-2*t.x*t.x-2*t.z*t.z,2*t.y*t.z-2*t.x*t.w,2*t.x*t.z-2*t.y*t.w,2*t.y*t.z+2*t.x*t.w,1-2*t.x*t.x-2*t.y*t.y)}static RotationFromEuler(t){const F=Math.cos(t.x),U=Math.sin(t.x),l=Math.cos(t.y),a=Math.sin(t.y),n=Math.cos(t.z),e=Math.sin(t.z);return new tt(l*n+a*U*e,-l*e+a*U*n,a*F,F*e,F*n,-U,-a*n+l*U*e,a*e+l*U*n,l*F)}toString(){return`[${this.buffer.join(", ")}]`}}class lt{constructor(t=0,F=null,U=null,l=null,a=null){this.changed=!1,this.detached=!1,this._vertexCount=t,this._positions=F||new Float32Array(0),this._rotations=U||new Float32Array(0),this._scales=l||new Float32Array(0),this._colors=a||new Uint8Array(0),this._selection=new Uint8Array(this.vertexCount),this.translate=n=>{for(let e=0;e<this.vertexCount;e++)this.positions[3*e+0]+=n.x,this.positions[3*e+1]+=n.y,this.positions[3*e+2]+=n.z;this.changed=!0},this.rotate=n=>{const e=tt.RotationFromQuaternion(n).buffer;for(let Q=0;Q<this.vertexCount;Q++){const d=this.positions[3*Q+0],A=this.positions[3*Q+1],i=this.positions[3*Q+2];this.positions[3*Q+0]=e[0]*d+e[1]*A+e[2]*i,this.positions[3*Q+1]=e[3]*d+e[4]*A+e[5]*i,this.positions[3*Q+2]=e[6]*d+e[7]*A+e[8]*i;const r=new z(this.rotations[4*Q+1],this.rotations[4*Q+2],this.rotations[4*Q+3],this.rotations[4*Q+0]),c=n.multiply(r);this.rotations[4*Q+1]=c.x,this.rotations[4*Q+2]=c.y,this.rotations[4*Q+3]=c.z,this.rotations[4*Q+0]=c.w}this.changed=!0},this.scale=n=>{for(let e=0;e<this.vertexCount;e++)this.positions[3*e+0]*=n.x,this.positions[3*e+1]*=n.y,this.positions[3*e+2]*=n.z,this.scales[3*e+0]*=n.x,this.scales[3*e+1]*=n.y,this.scales[3*e+2]*=n.z;this.changed=!0},this.serialize=()=>{const n=new Uint8Array(this.vertexCount*lt.RowLength),e=new Float32Array(n.buffer),Q=new Uint8Array(n.buffer);for(let d=0;d<this.vertexCount;d++)e[8*d+0]=this.positions[3*d+0],e[8*d+1]=this.positions[3*d+1],e[8*d+2]=this.positions[3*d+2],Q[32*d+24+0]=this.colors[4*d+0],Q[32*d+24+1]=this.colors[4*d+1],Q[32*d+24+2]=this.colors[4*d+2],Q[32*d+24+3]=this.colors[4*d+3],e[8*d+3+0]=this.scales[3*d+0],e[8*d+3+1]=this.scales[3*d+1],e[8*d+3+2]=this.scales[3*d+2],Q[32*d+28+0]=128*this.rotations[4*d+0]+128&255,Q[32*d+28+1]=128*this.rotations[4*d+1]+128&255,Q[32*d+28+2]=128*this.rotations[4*d+2]+128&255,Q[32*d+28+3]=128*this.rotations[4*d+3]+128&255;return n},this.reattach=(n,e,Q,d,A)=>{console.assert(n.byteLength===3*this.vertexCount*4,`Expected ${3*this.vertexCount*4} bytes, got ${n.byteLength} bytes`),this._positions=new Float32Array(n),this._rotations=new Float32Array(e),this._scales=new Float32Array(Q),this._colors=new Uint8Array(d),this._selection=new Uint8Array(A),this.detached=!1}}static Deserialize(t){const F=t.length/lt.RowLength,U=new Float32Array(3*F),l=new Float32Array(4*F),a=new Float32Array(3*F),n=new Uint8Array(4*F),e=new Float32Array(t.buffer),Q=new Uint8Array(t.buffer);for(let d=0;d<F;d++)U[3*d+0]=e[8*d+0],U[3*d+1]=e[8*d+1],U[3*d+2]=e[8*d+2],l[4*d+0]=(Q[32*d+28+0]-128)/128,l[4*d+1]=(Q[32*d+28+1]-128)/128,l[4*d+2]=(Q[32*d+28+2]-128)/128,l[4*d+3]=(Q[32*d+28+3]-128)/128,a[3*d+0]=e[8*d+3+0],a[3*d+1]=e[8*d+3+1],a[3*d+2]=e[8*d+3+2],n[4*d+0]=Q[32*d+24+0],n[4*d+1]=Q[32*d+24+1],n[4*d+2]=Q[32*d+24+2],n[4*d+3]=Q[32*d+24+3];return new lt(F,U,l,a,n)}get vertexCount(){return this._vertexCount}get positions(){return this._positions}get rotations(){return this._rotations}get scales(){return this._scales}get colors(){return this._colors}get selection(){return this._selection}}lt.RowLength=32;class rt{constructor(t,F,U,l,a){this._vertexCount=t,this._positions=F,this._data=U,this._width=l,this._height=a,this.serialize=()=>new Uint8Array(this._data.buffer)}static Deserialize(t,F,U){const l=new Uint32Array(t.buffer),a=new Float32Array(t.buffer),n=Math.floor(a.byteLength/this.RowLength),e=new Float32Array(3*n);for(let Q=0;Q<n;Q++)e[3*Q+0]=a[16*Q+0],e[3*Q+1]=a[16*Q+1],e[3*Q+2]=a[16*Q+2],e[3*Q+0]=a[16*Q+3];return new rt(n,e,l,F,U)}get vertexCount(){return this._vertexCount}get positions(){return this._positions}get data(){return this._data}get width(){return this._width}get height(){return this._height}}rt.RowLength=64;class Rt{static SplatToPLY(t,F){let U=`ply
|
|
2
|
-
format binary_little_endian 1.0
|
|
3
|
-
`;U+=`element vertex ${F}
|
|
4
|
-
`;const l=["x","y","z","nx","ny","nz","f_dc_0","f_dc_1","f_dc_2"];for(let B=0;B<45;B++)l.push(`f_rest_${B}`);l.push("opacity"),l.push("scale_0"),l.push("scale_1"),l.push("scale_2"),l.push("rot_0"),l.push("rot_1"),l.push("rot_2"),l.push("rot_3");for(const B of l)U+=`property float ${B}
|
|
5
|
-
`;U+=`end_header
|
|
6
|
-
`;const a=new TextEncoder().encode(U),n=248,e=F*n,Q=new DataView(new ArrayBuffer(a.length+e));new Uint8Array(Q.buffer).set(a,0);const d=new Float32Array(t),A=new Uint8Array(t),i=a.length,r=220,c=232;for(let B=0;B<F;B++){const W=d[8*B+0],J=d[8*B+1],h=d[8*B+2],C=(A[32*B+24+0]/255-.5)/this.SH_C0,k=(A[32*B+24+1]/255-.5)/this.SH_C0,p=(A[32*B+24+2]/255-.5)/this.SH_C0,X=A[32*B+24+3]/255,D=Math.log(X/(1-X)),u=Math.log(d[8*B+3+0]),M=Math.log(d[8*B+3+1]),E=Math.log(d[8*B+3+2]);let w=new z((A[32*B+28+1]-128)/128,(A[32*B+28+2]-128)/128,(A[32*B+28+3]-128)/128,(A[32*B+28+0]-128)/128);w=w.normalize();const et=w.w,Y=w.x,H=w.y,at=w.z;Q.setFloat32(i+n*B+0,W,!0),Q.setFloat32(i+n*B+4,J,!0),Q.setFloat32(i+n*B+8,h,!0),Q.setFloat32(i+n*B+24+0,C,!0),Q.setFloat32(i+n*B+24+4,k,!0),Q.setFloat32(i+n*B+24+8,p,!0),Q.setFloat32(i+n*B+216,D,!0),Q.setFloat32(i+n*B+r+0,u,!0),Q.setFloat32(i+n*B+r+4,M,!0),Q.setFloat32(i+n*B+r+8,E,!0),Q.setFloat32(i+n*B+c+0,et,!0),Q.setFloat32(i+n*B+c+4,Y,!0),Q.setFloat32(i+n*B+c+8,H,!0),Q.setFloat32(i+n*B+c+12,at,!0)}return Q.buffer}}Rt.SH_C0=.28209479177387814;class ot{constructor(t,F){this.min=t,this.max=F}contains(t){return t.x>=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.max.y&&t.z>=this.min.z&&t.z<=this.max.z}intersects(t){return this.max.x>=t.min.x&&this.min.x<=t.max.x&&this.max.y>=t.min.y&&this.min.y<=t.max.y&&this.max.z>=t.min.z&&this.min.z<=t.max.z}size(){return this.max.subtract(this.min)}center(){return this.min.add(this.max).divide(2)}expand(t){this.min=this.min.min(t),this.max=this.max.max(t)}permute(){const t=this.min,F=this.max;this.min=new I(Math.min(t.x,F.x),Math.min(t.y,F.y),Math.min(t.z,F.z)),this.max=new I(Math.max(t.x,F.x),Math.max(t.y,F.y),Math.max(t.z,F.z))}}class Qt extends It{constructor(t=void 0){super(),this.selectedChanged=!1,this.colorTransformChanged=!1,this._selected=!1,this._colorTransforms=[],this._colorTransformsMap=new Map,this._data=t||new lt,this._bounds=new ot(new I(1/0,1/0,1/0),new I(-1/0,-1/0,-1/0)),this.recalculateBounds=()=>{this._bounds=new ot(new I(1/0,1/0,1/0),new I(-1/0,-1/0,-1/0));for(let F=0;F<this._data.vertexCount;F++)this._bounds.expand(new I(this._data.positions[3*F],this._data.positions[3*F+1],this._data.positions[3*F+2]))},this.applyPosition=()=>{this.data.translate(this.position),this.position=new I},this.applyRotation=()=>{this.data.rotate(this.rotation),this.rotation=new z},this.applyScale=()=>{this.data.scale(this.scale),this.scale=new I(1,1,1)},this.recalculateBounds()}saveToFile(t=null,F=null){if(!document)return;if(F){if(F!=="splat"&&F!=="ply")throw new Error("Invalid format. Must be 'splat' or 'ply'")}else F="splat";if(!t){const n=new Date;t=`splat-${n.getFullYear()}-${n.getMonth()+1}-${n.getDate()}.${F}`}this.applyRotation(),this.applyScale(),this.applyPosition();const U=this.data.serialize();let l;if(F==="ply"){const n=Rt.SplatToPLY(U.buffer,this.data.vertexCount);l=new Blob([n],{type:"application/octet-stream"})}else l=new Blob([U.buffer],{type:"application/octet-stream"});const a=document.createElement("a");a.download=t,a.href=URL.createObjectURL(l),a.click()}get data(){return this._data}get selected(){return this._selected}set selected(t){this._selected!==t&&(this._selected=t,this.selectedChanged=!0,this.dispatchEvent(this._changeEvent))}get colorTransforms(){return this._colorTransforms}get colorTransformsMap(){return this._colorTransformsMap}get bounds(){let t=this._bounds.center();t=t.add(this.position);let F=this._bounds.size();return F=F.multiply(this.scale),new ot(t.subtract(F.divide(2)),t.add(F.divide(2)))}}class Zt extends It{constructor(t){super(),this._data=t}get data(){return this._data}}class Yt{constructor(){this._fx=1132,this._fy=1132,this._near=.1,this._far=100,this._width=512,this._height=512,this._projectionMatrix=new Ut,this._viewMatrix=new Ut,this._viewProj=new Ut,this._updateProjectionMatrix=()=>{this._projectionMatrix=new Ut(2*this.fx/this.width,0,0,0,0,-2*this.fy/this.height,0,0,0,0,this.far/(this.far-this.near),1,0,0,-this.far*this.near/(this.far-this.near),0),this._viewProj=this.projectionMatrix.multiply(this.viewMatrix)},this.update=(t,F)=>{const U=tt.RotationFromQuaternion(F).buffer,l=t.flat();this._viewMatrix=new Ut(U[0],U[1],U[2],0,U[3],U[4],U[5],0,U[6],U[7],U[8],0,-l[0]*U[0]-l[1]*U[3]-l[2]*U[6],-l[0]*U[1]-l[1]*U[4]-l[2]*U[7],-l[0]*U[2]-l[1]*U[5]-l[2]*U[8],1),this._viewProj=this.projectionMatrix.multiply(this.viewMatrix)},this.setSize=(t,F)=>{this._width=t,this._height=F,this._updateProjectionMatrix()}}get fx(){return this._fx}set fx(t){this._fx!==t&&(this._fx=t,this._updateProjectionMatrix())}get fy(){return this._fy}set fy(t){this._fy!==t&&(this._fy=t,this._updateProjectionMatrix())}get near(){return this._near}set near(t){this._near!==t&&(this._near=t,this._updateProjectionMatrix())}get far(){return this._far}set far(t){this._far!==t&&(this._far=t,this._updateProjectionMatrix())}get width(){return this._width}get height(){return this._height}get projectionMatrix(){return this._projectionMatrix}get viewMatrix(){return this._viewMatrix}get viewProj(){return this._viewProj}}class Ft{constructor(t=0,F=0,U=0,l=0){this.x=t,this.y=F,this.z=U,this.w=l}equals(t){return this.x===t.x&&this.y===t.y&&this.z===t.z&&this.w===t.w}add(t){return typeof t=="number"?new Ft(this.x+t,this.y+t,this.z+t,this.w+t):new Ft(this.x+t.x,this.y+t.y,this.z+t.z,this.w+t.w)}subtract(t){return typeof t=="number"?new Ft(this.x-t,this.y-t,this.z-t,this.w-t):new Ft(this.x-t.x,this.y-t.y,this.z-t.z,this.w-t.w)}multiply(t){return typeof t=="number"?new Ft(this.x*t,this.y*t,this.z*t,this.w*t):t instanceof Ft?new Ft(this.x*t.x,this.y*t.y,this.z*t.z,this.w*t.w):new Ft(this.x*t.buffer[0]+this.y*t.buffer[4]+this.z*t.buffer[8]+this.w*t.buffer[12],this.x*t.buffer[1]+this.y*t.buffer[5]+this.z*t.buffer[9]+this.w*t.buffer[13],this.x*t.buffer[2]+this.y*t.buffer[6]+this.z*t.buffer[10]+this.w*t.buffer[14],this.x*t.buffer[3]+this.y*t.buffer[7]+this.z*t.buffer[11]+this.w*t.buffer[15])}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z+this.w*t.w}lerp(t,F){return new Ft(this.x+(t.x-this.x)*F,this.y+(t.y-this.y)*F,this.z+(t.z-this.z)*F,this.w+(t.w-this.w)*F)}magnitude(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)}distanceTo(t){return Math.sqrt((this.x-t.x)**2+(this.y-t.y)**2+(this.z-t.z)**2+(this.w-t.w)**2)}normalize(){const t=this.magnitude();return new Ft(this.x/t,this.y/t,this.z/t,this.w/t)}flat(){return[this.x,this.y,this.z,this.w]}clone(){return new Ft(this.x,this.y,this.z,this.w)}toString(){return`[${this.flat().join(", ")}]`}}class ll extends It{constructor(t=void 0){super(),this._data=t||new Yt,this._position=new I(0,0,-5),this.update=()=>{this.data.update(this.position,this.rotation)},this.screenPointToRay=(F,U)=>{const l=new Ft(F,U,-1,1),a=this._data.projectionMatrix.invert(),n=l.multiply(a),e=this._data.viewMatrix.invert(),Q=n.multiply(e);return new I(Q.x/Q.w,Q.y/Q.w,Q.z/Q.w).subtract(this.position).normalize()}}get data(){return this._data}}class Ul extends ut{constructor(){super(),this._objects=[],this.addObject=t=>{this.objects.push(t),this.dispatchEvent(new qt(t))},this.removeObject=t=>{const F=this.objects.indexOf(t);if(F<0)throw new Error("Object not found in scene");this.objects.splice(F,1),this.dispatchEvent(new $t(t))},this.findObject=t=>{for(const F of this.objects)if(t(F))return F},this.findObjectOfType=t=>{for(const F of this.objects)if(F instanceof t)return F},this.reset=()=>{const t=this.objects.slice();for(const F of t)this.removeObject(F)},this.reset()}saveToFile(t=null,F=null){if(!document)return;if(F){if(F!=="splat"&&F!=="ply")throw new Error("Invalid format. Must be 'splat' or 'ply'")}else F="splat";if(!t){const d=new Date;t=`scene-${d.getFullYear()}-${d.getMonth()+1}-${d.getDate()}.${F}`}const U=[];let l=0;for(const d of this.objects)if(d.applyRotation(),d.applyScale(),d.applyPosition(),d instanceof Qt){const A=d.data.serialize();U.push(A),l+=d.data.vertexCount}const a=new Uint8Array(l*lt.RowLength);let n,e=0;for(const d of U)a.set(d,e),e+=d.length;if(F==="ply"){const d=Rt.SplatToPLY(a.buffer,l);n=new Blob([d],{type:"application/octet-stream"})}else n=new Blob([a.buffer],{type:"application/octet-stream"});const Q=document.createElement("a");Q.download=t,Q.href=URL.createObjectURL(n),Q.click()}get objects(){return this._objects}}async function Ct(G,t){const F=await fetch(G,{mode:"cors",credentials:"omit",cache:t?"force-cache":"default"});if(F.status!=200)throw new Error(F.status+" Unable to load "+F.url);return F}async function gt(G,t){return G.headers.has("content-length")?async function(F,U){const l=F.body.getReader(),a=parseInt(F.headers.get("content-length")),n=new Uint8Array(a);let e=0;for(;;){const{done:Q,value:d}=await l.read();if(Q)break;n.set(d,e),e+=d.length,U==null||U(e/a)}return n}(G,t):async function(F,U){const l=F.body.getReader(),a=[];let n=0;for(;;){const{done:d,value:A}=await l.read();if(d)break;a.push(A),n+=A.length}const e=new Uint8Array(n);let Q=0;for(const d of a)e.set(d,Q),Q+=d.length,U==null||U(Q/n);return e}(G,t)}class Fl{static async LoadAsync(t,F,U,l=!1){const a=await Ct(t,l),n=await gt(a,U);return this.LoadFromArrayBuffer(n,F)}static async LoadFromFileAsync(t,F,U){const l=new FileReader;let a=new Qt;return l.onload=n=>{a=this.LoadFromArrayBuffer(n.target.result,F)},l.onprogress=n=>{U==null||U(n.loaded/n.total)},l.readAsArrayBuffer(t),await new Promise(n=>{l.onloadend=()=>{n()}}),a}static LoadFromArrayBuffer(t,F){const U=new Uint8Array(t),l=lt.Deserialize(U),a=new Qt(l);return F.addObject(a),a}}class el{static async LoadAsync(t,F,U,l="",a=!1){const n=await Ct(t,a),e=await gt(n,U);if(e[0]!==112||e[1]!==108||e[2]!==121||e[3]!==10)throw new Error("Invalid PLY file");return this.LoadFromArrayBuffer(e.buffer,F,l)}static async LoadFromFileAsync(t,F,U,l=""){const a=new FileReader;let n=new Qt;return a.onload=e=>{n=this.LoadFromArrayBuffer(e.target.result,F,l)},a.onprogress=e=>{U==null||U(e.loaded/e.total)},a.readAsArrayBuffer(t),await new Promise(e=>{a.onloadend=()=>{e()}}),n}static LoadFromArrayBuffer(t,F,U=""){const l=new Uint8Array(this._ParsePLYBuffer(t,U)),a=lt.Deserialize(l),n=new Qt(a);return F.addObject(n),n}static _ParsePLYBuffer(t,F){const U=new Uint8Array(t),l=new TextDecoder().decode(U.slice(0,10240)),a=`end_header
|
|
7
|
-
`,n=l.indexOf(a);if(n<0)throw new Error("Unable to read .ply file header");const e=parseInt(/element vertex (\d+)\n/.exec(l)[1]);let Q=0;const d={double:8,int:4,uint:4,float:4,short:2,ushort:2,uchar:1},A=[];for(const B of l.slice(0,n).split(`
|
|
8
|
-
`).filter(W=>W.startsWith("property "))){const[W,J,h]=B.split(" ");if(A.push({name:h,type:J,offset:Q}),console.log(h,J,Q),!d[J])throw new Error(`Unsupported property type: ${J}`);Q+=d[J]}const i=new DataView(t,n+11),r=new ArrayBuffer(lt.RowLength*e),c=z.FromEuler(new I(Math.PI/2,0,0));for(let B=0;B<e;B++){const W=new Float32Array(r,B*lt.RowLength,3),J=new Float32Array(r,B*lt.RowLength+12,3),h=new Uint8ClampedArray(r,B*lt.RowLength+24,4),C=new Uint8ClampedArray(r,B*lt.RowLength+28,4);let k=255,p=0,X=0,D=0;A.forEach(M=>{let E;switch(M.type){case"float":E=i.getFloat32(M.offset+B*Q,!0);break;case"int":E=i.getInt32(M.offset+B*Q,!0);break;default:throw new Error(`Unsupported property type: ${M.type}`)}switch(M.name){case"x":W[0]=E;break;case"y":W[1]=E;break;case"z":W[2]=E;break;case"scale_0":case"scaling_0":J[0]=Math.exp(E);break;case"scale_1":case"scaling_1":J[1]=Math.exp(E);break;case"scale_2":case"scaling_2":J[2]=Math.exp(E);break;case"red":h[0]=E;break;case"green":h[1]=E;break;case"blue":h[2]=E;break;case"f_dc_0":case"features_0":h[0]=255*(.5+Rt.SH_C0*E);break;case"f_dc_1":case"features_1":h[1]=255*(.5+Rt.SH_C0*E);break;case"f_dc_2":case"features_2":h[2]=255*(.5+Rt.SH_C0*E);break;case"f_dc_3":h[3]=255*(.5+Rt.SH_C0*E);break;case"opacity":case"opacity_0":h[3]=1/(1+Math.exp(-E))*255;break;case"rot_0":case"rotation_0":k=E;break;case"rot_1":case"rotation_1":p=E;break;case"rot_2":case"rotation_2":X=E;break;case"rot_3":case"rotation_3":D=E}});let u=new z(p,X,D,k);switch(F){case"polycam":{const M=W[1];W[1]=-W[2],W[2]=M,u=c.multiply(u);break}case"":break;default:throw new Error(`Unsupported format: ${F}`)}u=u.normalize(),C[0]=128*u.w+128,C[1]=128*u.x+128,C[2]=128*u.y+128,C[3]=128*u.z+128}return r}}class nl{static async LoadAsync(t,F,U,l,a=!1){const n=await Ct(t,a),e=await gt(n,l);return this._ParseSplatvBuffer(e.buffer,F,U)}static async LoadFromFileAsync(t,F,U,l){const a=new FileReader;let n=null;if(a.onload=e=>{n=this._ParseSplatvBuffer(e.target.result,F,U)},a.onprogress=e=>{l==null||l(e.loaded/e.total)},a.readAsArrayBuffer(t),await new Promise(e=>{a.onloadend=()=>{e()}}),!n)throw new Error("Failed to load splatv file");return n}static _ParseSplatvBuffer(t,F,U){let l=null;const a=(r,c,B)=>{if(r.type==="magic"){const W=new Int32Array(c.buffer);if(W[0]!==26443)throw new Error("Invalid splatv file");B.push({size:W[1],type:"chunks"})}else if(r.type==="chunks"){const W=JSON.parse(new TextDecoder("utf-8").decode(c));if(W.length==0)throw new Error("Invalid splatv file");W.length>1&&console.warn("Splatv file contains more than one chunk, only the first one will be loaded");const J=W[0],h=J.cameras;if(U&&h&&h.length){const C=h[0],k=new I(C.position[0],C.position[1],C.position[2]),p=z.FromMatrix3(new tt(C.rotation[0][0],C.rotation[0][1],C.rotation[0][2],C.rotation[1][0],C.rotation[1][1],C.rotation[1][2],C.rotation[2][0],C.rotation[2][1],C.rotation[2][2]));U.position=k,U.rotation=p}B.push(J)}else if(r.type==="splat"){const W=rt.Deserialize(c,r.texwidth,r.texheight),J=new Zt(W);F.addObject(J),l=J}},n=new Uint8Array(t),e=[{size:8,type:"magic",texwidth:0,texheight:0}];let Q=e.shift(),d=new Uint8Array(Q.size),A=0,i=0;for(;Q;){for(;A<Q.size;){const r=Math.min(Q.size-A,n.length-i);d.set(n.subarray(i,i+r),A),A+=r,i+=r}if(a(Q,d,e),l)return l;Q=e.shift(),Q&&(d=new Uint8Array(Q.size),A=0)}throw new Error("Invalid splatv file")}}function Ql(G,t,F){var U=t===void 0?null:t,l=function(Q,d){var A=atob(Q);return A}(G),a=l.indexOf(`
|
|
9
|
-
`,10)+1,n=l.substring(a)+(U?"//# sourceMappingURL="+U:""),e=new Blob([n],{type:"application/javascript"});return URL.createObjectURL(e)}function kt(G,t,F){var U;return function(l){return U=U||Ql(G,t),new Worker(U,l)}}var dl=kt("Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICd1c2Ugc3RyaWN0JzsKCiAgdmFyIGxvYWRXYXNtID0gKCgpID0+IHsKICAgIAogICAgcmV0dXJuICgKICBmdW5jdGlvbihtb2R1bGVBcmcgPSB7fSkgewoKICB2YXIgTW9kdWxlPW1vZHVsZUFyZzt2YXIgcmVhZHlQcm9taXNlUmVzb2x2ZSxyZWFkeVByb21pc2VSZWplY3Q7TW9kdWxlWyJyZWFkeSJdPW5ldyBQcm9taXNlKChyZXNvbHZlLHJlamVjdCk9PntyZWFkeVByb21pc2VSZXNvbHZlPXJlc29sdmU7cmVhZHlQcm9taXNlUmVqZWN0PXJlamVjdDt9KTt2YXIgbW9kdWxlT3ZlcnJpZGVzPU9iamVjdC5hc3NpZ24oe30sTW9kdWxlKTt2YXIgc2NyaXB0RGlyZWN0b3J5PSIiO2Z1bmN0aW9uIGxvY2F0ZUZpbGUocGF0aCl7aWYoTW9kdWxlWyJsb2NhdGVGaWxlIl0pe3JldHVybiBNb2R1bGVbImxvY2F0ZUZpbGUiXShwYXRoLHNjcmlwdERpcmVjdG9yeSl9cmV0dXJuIHNjcmlwdERpcmVjdG9yeStwYXRofXZhciByZWFkQmluYXJ5O3t7c2NyaXB0RGlyZWN0b3J5PXNlbGYubG9jYXRpb24uaHJlZjt9aWYoc2NyaXB0RGlyZWN0b3J5LmluZGV4T2YoImJsb2I6IikhPT0wKXtzY3JpcHREaXJlY3Rvcnk9c2NyaXB0RGlyZWN0b3J5LnN1YnN0cigwLHNjcmlwdERpcmVjdG9yeS5yZXBsYWNlKC9bPyNdLiovLCIiKS5sYXN0SW5kZXhPZigiLyIpKzEpO31lbHNlIHtzY3JpcHREaXJlY3Rvcnk9IiI7fXt7cmVhZEJpbmFyeT11cmw9Pnt2YXIgeGhyPW5ldyBYTUxIdHRwUmVxdWVzdDt4aHIub3BlbigiR0VUIix1cmwsZmFsc2UpO3hoci5yZXNwb25zZVR5cGU9ImFycmF5YnVmZmVyIjt4aHIuc2VuZChudWxsKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoeGhyLnJlc3BvbnNlKX07fX19TW9kdWxlWyJwcmludCJdfHxjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpO3ZhciBlcnI9TW9kdWxlWyJwcmludEVyciJdfHxjb25zb2xlLmVycm9yLmJpbmQoY29uc29sZSk7T2JqZWN0LmFzc2lnbihNb2R1bGUsbW9kdWxlT3ZlcnJpZGVzKTttb2R1bGVPdmVycmlkZXM9bnVsbDtpZihNb2R1bGVbImFyZ3VtZW50cyJdKU1vZHVsZVsiYXJndW1lbnRzIl07aWYoTW9kdWxlWyJ0aGlzUHJvZ3JhbSJdKU1vZHVsZVsidGhpc1Byb2dyYW0iXTtpZihNb2R1bGVbInF1aXQiXSlNb2R1bGVbInF1aXQiXTt2YXIgd2FzbUJpbmFyeTtpZihNb2R1bGVbIndhc21CaW5hcnkiXSl3YXNtQmluYXJ5PU1vZHVsZVsid2FzbUJpbmFyeSJdO2lmKHR5cGVvZiBXZWJBc3NlbWJseSE9Im9iamVjdCIpe2Fib3J0KCJubyBuYXRpdmUgd2FzbSBzdXBwb3J0IGRldGVjdGVkIik7fXZhciB3YXNtTWVtb3J5O3ZhciBBQk9SVD1mYWxzZTt2YXIgSEVBUDgsSEVBUFU4LEhFQVAxNixIRUFQVTE2LEhFQVAzMixIRUFQVTMyLEhFQVBGMzIsSEVBUEY2NDtmdW5jdGlvbiB1cGRhdGVNZW1vcnlWaWV3cygpe3ZhciBiPXdhc21NZW1vcnkuYnVmZmVyO01vZHVsZVsiSEVBUDgiXT1IRUFQOD1uZXcgSW50OEFycmF5KGIpO01vZHVsZVsiSEVBUDE2Il09SEVBUDE2PW5ldyBJbnQxNkFycmF5KGIpO01vZHVsZVsiSEVBUFU4Il09SEVBUFU4PW5ldyBVaW50OEFycmF5KGIpO01vZHVsZVsiSEVBUFUxNiJdPUhFQVBVMTY9bmV3IFVpbnQxNkFycmF5KGIpO01vZHVsZVsiSEVBUDMyIl09SEVBUDMyPW5ldyBJbnQzMkFycmF5KGIpO01vZHVsZVsiSEVBUFUzMiJdPUhFQVBVMzI9bmV3IFVpbnQzMkFycmF5KGIpO01vZHVsZVsiSEVBUEYzMiJdPUhFQVBGMzI9bmV3IEZsb2F0MzJBcnJheShiKTtNb2R1bGVbIkhFQVBGNjQiXT1IRUFQRjY0PW5ldyBGbG9hdDY0QXJyYXkoYik7fXZhciBfX0FUUFJFUlVOX189W107dmFyIF9fQVRJTklUX189W107dmFyIF9fQVRQT1NUUlVOX189W107ZnVuY3Rpb24gcHJlUnVuKCl7aWYoTW9kdWxlWyJwcmVSdW4iXSl7aWYodHlwZW9mIE1vZHVsZVsicHJlUnVuIl09PSJmdW5jdGlvbiIpTW9kdWxlWyJwcmVSdW4iXT1bTW9kdWxlWyJwcmVSdW4iXV07d2hpbGUoTW9kdWxlWyJwcmVSdW4iXS5sZW5ndGgpe2FkZE9uUHJlUnVuKE1vZHVsZVsicHJlUnVuIl0uc2hpZnQoKSk7fX1jYWxsUnVudGltZUNhbGxiYWNrcyhfX0FUUFJFUlVOX18pO31mdW5jdGlvbiBpbml0UnVudGltZSgpe2NhbGxSdW50aW1lQ2FsbGJhY2tzKF9fQVRJTklUX18pO31mdW5jdGlvbiBwb3N0UnVuKCl7aWYoTW9kdWxlWyJwb3N0UnVuIl0pe2lmKHR5cGVvZiBNb2R1bGVbInBvc3RSdW4iXT09ImZ1bmN0aW9uIilNb2R1bGVbInBvc3RSdW4iXT1bTW9kdWxlWyJwb3N0UnVuIl1dO3doaWxlKE1vZHVsZVsicG9zdFJ1biJdLmxlbmd0aCl7YWRkT25Qb3N0UnVuKE1vZHVsZVsicG9zdFJ1biJdLnNoaWZ0KCkpO319Y2FsbFJ1bnRpbWVDYWxsYmFja3MoX19BVFBPU1RSVU5fXyk7fWZ1bmN0aW9uIGFkZE9uUHJlUnVuKGNiKXtfX0FUUFJFUlVOX18udW5zaGlmdChjYik7fWZ1bmN0aW9uIGFkZE9uSW5pdChjYil7X19BVElOSVRfXy51bnNoaWZ0KGNiKTt9ZnVuY3Rpb24gYWRkT25Qb3N0UnVuKGNiKXtfX0FUUE9TVFJVTl9fLnVuc2hpZnQoY2IpO312YXIgcnVuRGVwZW5kZW5jaWVzPTA7dmFyIGRlcGVuZGVuY2llc0Z1bGZpbGxlZD1udWxsO2Z1bmN0aW9uIGFkZFJ1bkRlcGVuZGVuY3koaWQpe3J1bkRlcGVuZGVuY2llcysrO2lmKE1vZHVsZVsibW9uaXRvclJ1bkRlcGVuZGVuY2llcyJdKXtNb2R1bGVbIm1vbml0b3JSdW5EZXBlbmRlbmNpZXMiXShydW5EZXBlbmRlbmNpZXMpO319ZnVuY3Rpb24gcmVtb3ZlUnVuRGVwZW5kZW5jeShpZCl7cnVuRGVwZW5kZW5jaWVzLS07aWYoTW9kdWxlWyJtb25pdG9yUnVuRGVwZW5kZW5jaWVzIl0pe01vZHVsZVsibW9uaXRvclJ1bkRlcGVuZGVuY2llcyJdKHJ1bkRlcGVuZGVuY2llcyk7fWlmKHJ1bkRlcGVuZGVuY2llcz09MCl7aWYoZGVwZW5kZW5jaWVzRnVsZmlsbGVkKXt2YXIgY2FsbGJhY2s9ZGVwZW5kZW5jaWVzRnVsZmlsbGVkO2RlcGVuZGVuY2llc0Z1bGZpbGxlZD1udWxsO2NhbGxiYWNrKCk7fX19ZnVuY3Rpb24gYWJvcnQod2hhdCl7aWYoTW9kdWxlWyJvbkFib3J0Il0pe01vZHVsZVsib25BYm9ydCJdKHdoYXQpO313aGF0PSJBYm9ydGVkKCIrd2hhdCsiKSI7ZXJyKHdoYXQpO0FCT1JUPXRydWU7d2hhdCs9Ii4gQnVpbGQgd2l0aCAtc0FTU0VSVElPTlMgZm9yIG1vcmUgaW5mby4iO3ZhciBlPW5ldyBXZWJBc3NlbWJseS5SdW50aW1lRXJyb3Iod2hhdCk7cmVhZHlQcm9taXNlUmVqZWN0KGUpO3Rocm93IGV9dmFyIGRhdGFVUklQcmVmaXg9ImRhdGE6YXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtO2Jhc2U2NCwiO3ZhciBpc0RhdGFVUkk9ZmlsZW5hbWU9PmZpbGVuYW1lLnN0YXJ0c1dpdGgoZGF0YVVSSVByZWZpeCk7dmFyIHdhc21CaW5hcnlGaWxlO3dhc21CaW5hcnlGaWxlPSJkYXRhOmFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbTtiYXNlNjQsQUdGemJRRUFBQUFCV2cxZ0JIOS9mMzhBWUFOL2YzOEFZQVYvZjM5L2Z3QmdCbjkvZjM5L2Z3QmdBWDhCZjJBQUFHQUNmMzhBWUFOL2YzOEJmMkFCZndCZ0IzOS9mMzkvZjM4QVlBSi9md0YvWUFSL2YzNStBR0FKZjM5L2YzOS9mMzkvQUFJOUNnRmhBV0VBQVFGaEFXSUFBZ0ZoQVdNQUFRRmhBV1FBQmdGaEFXVUFBUUZoQVdZQUNRRmhBV2NBQkFGaEFXZ0FCZ0ZoQVdrQUFBRmhBV29BQmdNWkdBY0VDQVVJQ2dVTEFRQUJDQVFGQXdNQ0FnQUFCd2NFREFRRkFYQUJFQkFGQndFQmdBS0FnQUlHQ0FGL0FVSGduUVFMQngwSEFXc0NBQUZzQUEwQmJRQWhBVzRBRndGdkFRQUJjQUFXQVhFQURna1ZBUUJCQVFzUEVDQU1GUlVmREI0WUdoME1HUnNjQ3ZCSUdIRUJBWDhnQWtVRVFDQUFLQUlFSUFFb0FnUkdEd3NnQUNBQlJnUkFRUUVQQ3dKQUlBQW9BZ1FpQWkwQUFDSUFSU0FBSUFFb0FnUWlBUzBBQUNJRFIzSU5BQU5BSUFFdEFBRWhBeUFDTFFBQklnQkZEUUVnQVVFQmFpRUJJQUpCQVdvaEFpQUFJQU5HRFFBTEN5QUFJQU5HQzA4QkFuOUIyQmtvQWdBaUFTQUFRUWRxUVhoeElnSnFJUUFDUUNBQ1FRQWdBQ0FCVFJzTkFDQUFQd0JCRUhSTEJFQWdBQkFHUlEwQkMwSFlHU0FBTmdJQUlBRVBDMEhvR1VFd05nSUFRWDhMQmdBZ0FCQU9DeWtBUWVBWlFRRTJBZ0JCNUJsQkFEWUNBQkFRUWVRWlFkd1pLQUlBTmdJQVFkd1pRZUFaTmdJQUM5SUxBUWQvQWtBZ0FFVU5BQ0FBUVFocklnSWdBRUVFYXlnQ0FDSUJRWGh4SWdCcUlRVUNRQ0FCUVFGeERRQWdBVUVEY1VVTkFTQUNJQUlvQWdBaUFXc2lBa0g4R1NnQ0FFa05BU0FBSUFGcUlRQUNRQUpBUVlBYUtBSUFJQUpIQkVBZ0FVSC9BVTBFUUNBQlFRTjJJUVFnQWlnQ0RDSUJJQUlvQWdnaUEwWUVRRUhzR1VIc0dTZ0NBRUYrSUFSM2NUWUNBQXdGQ3lBRElBRTJBZ3dnQVNBRE5nSUlEQVFMSUFJb0FoZ2hCaUFDSUFJb0Fnd2lBVWNFUUNBQ0tBSUlJZ01nQVRZQ0RDQUJJQU0yQWdnTUF3c2dBa0VVYWlJRUtBSUFJZ05GQkVBZ0FpZ0NFQ0lEUlEwQ0lBSkJFR29oQkFzRFFDQUVJUWNnQXlJQlFSUnFJZ1FvQWdBaUF3MEFJQUZCRUdvaEJDQUJLQUlRSWdNTkFBc2dCMEVBTmdJQURBSUxJQVVvQWdRaUFVRURjVUVEUncwQ1FmUVpJQUEyQWdBZ0JTQUJRWDV4TmdJRUlBSWdBRUVCY2pZQ0JDQUZJQUEyQWdBUEMwRUFJUUVMSUFaRkRRQUNRQ0FDS0FJY0lnTkJBblJCbkJ4cUlnUW9BZ0FnQWtZRVFDQUVJQUUyQWdBZ0FRMEJRZkFaUWZBWktBSUFRWDRnQTNkeE5nSUFEQUlMSUFaQkVFRVVJQVlvQWhBZ0FrWWJhaUFCTmdJQUlBRkZEUUVMSUFFZ0JqWUNHQ0FDS0FJUUlnTUVRQ0FCSUFNMkFoQWdBeUFCTmdJWUN5QUNLQUlVSWdORkRRQWdBU0FETmdJVUlBTWdBVFlDR0FzZ0FpQUZUdzBBSUFVb0FnUWlBVUVCY1VVTkFBSkFBa0FDUUFKQUlBRkJBbkZGQkVCQmhCb29BZ0FnQlVZRVFFR0VHaUFDTmdJQVFmZ1pRZmdaS0FJQUlBQnFJZ0EyQWdBZ0FpQUFRUUZ5TmdJRUlBSkJnQm9vQWdCSERRWkI5QmxCQURZQ0FFR0FHa0VBTmdJQUR3dEJnQm9vQWdBZ0JVWUVRRUdBR2lBQ05nSUFRZlFaUWZRWktBSUFJQUJxSWdBMkFnQWdBaUFBUVFGeU5nSUVJQUFnQW1vZ0FEWUNBQThMSUFGQmVIRWdBR29oQUNBQlFmOEJUUVJBSUFGQkEzWWhCQ0FGS0FJTUlnRWdCU2dDQ0NJRFJnUkFRZXdaUWV3WktBSUFRWDRnQkhkeE5nSUFEQVVMSUFNZ0FUWUNEQ0FCSUFNMkFnZ01CQXNnQlNnQ0dDRUdJQVVnQlNnQ0RDSUJSd1JBUWZ3WktBSUFHaUFGS0FJSUlnTWdBVFlDRENBQklBTTJBZ2dNQXdzZ0JVRVVhaUlFS0FJQUlnTkZCRUFnQlNnQ0VDSURSUTBDSUFWQkVHb2hCQXNEUUNBRUlRY2dBeUlCUVJScUlnUW9BZ0FpQXcwQUlBRkJFR29oQkNBQktBSVFJZ01OQUFzZ0IwRUFOZ0lBREFJTElBVWdBVUYrY1RZQ0JDQUNJQUJCQVhJMkFnUWdBQ0FDYWlBQU5nSUFEQU1MUVFBaEFRc2dCa1VOQUFKQUlBVW9BaHdpQTBFQ2RFR2NIR29pQkNnQ0FDQUZSZ1JBSUFRZ0FUWUNBQ0FCRFFGQjhCbEI4QmtvQWdCQmZpQURkM0UyQWdBTUFnc2dCa0VRUVJRZ0JpZ0NFQ0FGUmh0cUlBRTJBZ0FnQVVVTkFRc2dBU0FHTmdJWUlBVW9BaEFpQXdSQUlBRWdBellDRUNBRElBRTJBaGdMSUFVb0FoUWlBMFVOQUNBQklBTTJBaFFnQXlBQk5nSVlDeUFDSUFCQkFYSTJBZ1FnQUNBQ2FpQUFOZ0lBSUFKQmdCb29BZ0JIRFFCQjlCa2dBRFlDQUE4TElBQkIvd0ZOQkVBZ0FFRjRjVUdVR21vaEFRSi9RZXdaS0FJQUlnTkJBU0FBUVFOMmRDSUFjVVVFUUVIc0dTQUFJQU55TmdJQUlBRU1BUXNnQVNnQ0NBc2hBQ0FCSUFJMkFnZ2dBQ0FDTmdJTUlBSWdBVFlDRENBQ0lBQTJBZ2dQQzBFZklRTWdBRUgvLy84SFRRUkFJQUJCSmlBQVFRaDJaeUlCYTNaQkFYRWdBVUVCZEd0QlBtb2hBd3NnQWlBRE5nSWNJQUpDQURjQ0VDQURRUUowUVp3Y2FpRUJBa0FDUUFKQVFmQVpLQUlBSWdSQkFTQURkQ0lIY1VVRVFFSHdHU0FFSUFkeU5nSUFJQUVnQWpZQ0FDQUNJQUUyQWhnTUFRc2dBRUVaSUFOQkFYWnJRUUFnQTBFZlJ4dDBJUU1nQVNnQ0FDRUJBMEFnQVNJRUtBSUVRWGh4SUFCR0RRSWdBMEVkZGlFQklBTkJBWFFoQXlBRUlBRkJCSEZxSWdkQkVHb29BZ0FpQVEwQUN5QUhJQUkyQWhBZ0FpQUVOZ0lZQ3lBQ0lBSTJBZ3dnQWlBQ05nSUlEQUVMSUFRb0FnZ2lBQ0FDTmdJTUlBUWdBallDQ0NBQ1FRQTJBaGdnQWlBRU5nSU1JQUlnQURZQ0NBdEJqQnBCakJvb0FnQkJBV3NpQUVGL0lBQWJOZ0lBQ3dzcEFRRi9JQUVFUUNBQUlRSURRQ0FDUVFBNkFBQWdBa0VCYWlFQ0lBRkJBV3NpQVEwQUN3c2dBQXZoQXdCQmpCZEJtZ2tRQ1VHWUYwRzVDRUVCUVFBUUNFR2tGMEcwQ0VFQlFZQi9RZjhBRUFGQnZCZEJyUWhCQVVHQWYwSC9BQkFCUWJBWFFhc0lRUUZCQUVIL0FSQUJRY2dYUVlrSVFRSkJnSUIrUWYvL0FSQUJRZFFYUVlBSVFRSkJBRUgvL3dNUUFVSGdGMEdZQ0VFRVFZQ0FnSUI0UWYvLy8vOEhFQUZCN0JkQmp3aEJCRUVBUVg4UUFVSDRGMEhYQ0VFRVFZQ0FnSUI0UWYvLy8vOEhFQUZCaEJoQnpnaEJCRUVBUVg4UUFVR1FHRUdqQ0VLQWdJQ0FnSUNBZ0lCL1F2Ly8vLy8vLy8vLy93QVFFVUdjR0VHaUNFSUFRbjhRRVVHb0dFR2NDRUVFRUFSQnRCaEJrd2xCQ0JBRVFZUVBRZWtJRUFOQnpBOUJsdzBRQTBHVUVFRUVRZHdJRUFKQjRCQkJBa0gxQ0JBQ1Fhd1JRUVJCaEFrUUFrSElFVUcrQ0JBSFFmQVJRUUJCMGd3UUFFR1lFa0VBUWJnTkVBQkJ3QkpCQVVId0RCQUFRZWdTUVFKQm53a1FBRUdRRTBFRFFiNEpFQUJCdUJOQkJFSG1DUkFBUWVBVFFRVkJnd29RQUVHSUZFRUVRZDBORUFCQnNCUkJCVUg3RFJBQVFaZ1NRUUJCNlFvUUFFSEFFa0VCUWNnS0VBQkI2QkpCQWtHckN4QUFRWkFUUVFOQmlRc1FBRUc0RTBFRVFiRU1FQUJCNEJOQkJVR1BEQkFBUWRnVVFRaEI3Z3NRQUVHQUZVRUpRY3dMRUFCQnFCVkJCa0dwQ2hBQVFkQVZRUWRCb2c0UUFBc2NBQ0FBSUFGQkNDQUNweUFDUWlDSXB5QURweUFEUWlDSXB4QUZDeUFBQWtBZ0FDZ0NCQ0FCUncwQUlBQW9BaHhCQVVZTkFDQUFJQUkyQWh3TEM1b0JBQ0FBUVFFNkFEVUNRQ0FBS0FJRUlBSkhEUUFnQUVFQk9nQTBBa0FnQUNnQ0VDSUNSUVJBSUFCQkFUWUNKQ0FBSUFNMkFoZ2dBQ0FCTmdJUUlBTkJBVWNOQWlBQUtBSXdRUUZHRFFFTUFnc2dBU0FDUmdSQUlBQW9BaGdpQWtFQ1JnUkFJQUFnQXpZQ0dDQURJUUlMSUFBb0FqQkJBVWNOQWlBQ1FRRkdEUUVNQWdzZ0FDQUFLQUlrUVFGcU5nSWtDeUFBUVFFNkFEWUxDMTBCQVg4Z0FDZ0NFQ0lEUlFSQUlBQkJBVFlDSkNBQUlBSTJBaGdnQUNBQk5nSVFEd3NDUUNBQklBTkdCRUFnQUNnQ0dFRUNSdzBCSUFBZ0FqWUNHQThMSUFCQkFUb0FOaUFBUVFJMkFoZ2dBQ0FBS0FJa1FRRnFOZ0lrQ3dzQ0FBdTlKd0VNZnlNQVFSQnJJZ29rQUFKQUFrQUNRQUpBQWtBQ1FBSkFBa0FDUUFKQUFrQUNRQUpBQWtBZ0FFSDBBVTBFUUVIc0dTZ0NBQ0lHUVJBZ0FFRUxha0Y0Y1NBQVFRdEpHeUlGUVFOMklnQjJJZ0ZCQTNFRVFBSkFJQUZCZjNOQkFYRWdBR29pQWtFRGRDSUJRWlFhYWlJQUlBRkJuQnBxS0FJQUlnRW9BZ2dpQkVZRVFFSHNHU0FHUVg0Z0FuZHhOZ0lBREFFTElBUWdBRFlDRENBQUlBUTJBZ2dMSUFGQkNHb2hBQ0FCSUFKQkEzUWlBa0VEY2pZQ0JDQUJJQUpxSWdFZ0FTZ0NCRUVCY2pZQ0JBd1BDeUFGUWZRWktBSUFJZ2RORFFFZ0FRUkFBa0JCQWlBQWRDSUNRUUFnQW10eUlBRWdBSFJ4YUNJQlFRTjBJZ0JCbEJwcUlnSWdBRUdjR21vb0FnQWlBQ2dDQ0NJRVJnUkFRZXdaSUFaQmZpQUJkM0VpQmpZQ0FBd0JDeUFFSUFJMkFnd2dBaUFFTmdJSUN5QUFJQVZCQTNJMkFnUWdBQ0FGYWlJSUlBRkJBM1FpQVNBRmF5SUVRUUZ5TmdJRUlBQWdBV29nQkRZQ0FDQUhCRUFnQjBGNGNVR1VHbW9oQVVHQUdpZ0NBQ0VDQW44Z0JrRUJJQWRCQTNaMElnTnhSUVJBUWV3WklBTWdCbkkyQWdBZ0FRd0JDeUFCS0FJSUN5RURJQUVnQWpZQ0NDQURJQUkyQWd3Z0FpQUJOZ0lNSUFJZ0F6WUNDQXNnQUVFSWFpRUFRWUFhSUFnMkFnQkI5QmtnQkRZQ0FBd1BDMEh3R1NnQ0FDSUxSUTBCSUF0b1FRSjBRWndjYWlnQ0FDSUNLQUlFUVhoeElBVnJJUU1nQWlFQkEwQUNRQ0FCS0FJUUlnQkZCRUFnQVNnQ0ZDSUFSUTBCQ3lBQUtBSUVRWGh4SUFWcklnRWdBeUFCSUFOSklnRWJJUU1nQUNBQ0lBRWJJUUlnQUNFQkRBRUxDeUFDS0FJWUlRa2dBaUFDS0FJTUlnUkhCRUJCL0Jrb0FnQWFJQUlvQWdnaUFDQUVOZ0lNSUFRZ0FEWUNDQXdPQ3lBQ1FSUnFJZ0VvQWdBaUFFVUVRQ0FDS0FJUUlnQkZEUU1nQWtFUWFpRUJDd05BSUFFaENDQUFJZ1JCRkdvaUFTZ0NBQ0lBRFFBZ0JFRVFhaUVCSUFRb0FoQWlBQTBBQ3lBSVFRQTJBZ0FNRFF0QmZ5RUZJQUJCdjM5TERRQWdBRUVMYWlJQVFYaHhJUVZCOEJrb0FnQWlDRVVOQUVFQUlBVnJJUU1DUUFKQUFrQUNmMEVBSUFWQmdBSkpEUUFhUVI4Z0JVSC8vLzhIU3cwQUdpQUZRU1lnQUVFSWRtY2lBR3QyUVFGeElBQkJBWFJyUVQ1cUN5SUhRUUowUVp3Y2FpZ0NBQ0lCUlFSQVFRQWhBQXdCQzBFQUlRQWdCVUVaSUFkQkFYWnJRUUFnQjBFZlJ4dDBJUUlEUUFKQUlBRW9BZ1JCZUhFZ0JXc2lCaUFEVHcwQUlBRWhCQ0FHSWdNTkFFRUFJUU1nQVNFQURBTUxJQUFnQVNnQ0ZDSUdJQVlnQVNBQ1FSMTJRUVJ4YWlnQ0VDSUJSaHNnQUNBR0d5RUFJQUpCQVhRaEFpQUJEUUFMQ3lBQUlBUnlSUVJBUVFBaEJFRUNJQWQwSWdCQkFDQUFhM0lnQ0hFaUFFVU5BeUFBYUVFQ2RFR2NIR29vQWdBaEFBc2dBRVVOQVFzRFFDQUFLQUlFUVhoeElBVnJJZ0lnQTBraEFTQUNJQU1nQVJzaEF5QUFJQVFnQVJzaEJDQUFLQUlRSWdFRWZ5QUJCU0FBS0FJVUN5SUFEUUFMQ3lBRVJRMEFJQU5COUJrb0FnQWdCV3RQRFFBZ0JDZ0NHQ0VISUFRZ0JDZ0NEQ0lDUndSQVFmd1pLQUlBR2lBRUtBSUlJZ0FnQWpZQ0RDQUNJQUEyQWdnTURBc2dCRUVVYWlJQktBSUFJZ0JGQkVBZ0JDZ0NFQ0lBUlEwRElBUkJFR29oQVFzRFFDQUJJUVlnQUNJQ1FSUnFJZ0VvQWdBaUFBMEFJQUpCRUdvaEFTQUNLQUlRSWdBTkFBc2dCa0VBTmdJQURBc0xJQVZCOUJrb0FnQWlCRTBFUUVHQUdpZ0NBQ0VBQWtBZ0JDQUZheUlCUVJCUEJFQWdBQ0FGYWlJQ0lBRkJBWEkyQWdRZ0FDQUVhaUFCTmdJQUlBQWdCVUVEY2pZQ0JBd0JDeUFBSUFSQkEzSTJBZ1FnQUNBRWFpSUJJQUVvQWdSQkFYSTJBZ1JCQUNFQ1FRQWhBUXRCOUJrZ0FUWUNBRUdBR2lBQ05nSUFJQUJCQ0dvaEFBd05DeUFGUWZnWktBSUFJZ0pKQkVCQitCa2dBaUFGYXlJQk5nSUFRWVFhUVlRYUtBSUFJZ0FnQldvaUFqWUNBQ0FDSUFGQkFYSTJBZ1FnQUNBRlFRTnlOZ0lFSUFCQkNHb2hBQXdOQzBFQUlRQWdCVUV2YWlJREFuOUJ4QjBvQWdBRVFFSE1IU2dDQUF3QkMwSFFIVUovTndJQVFjZ2RRb0NnZ0lDQWdBUTNBZ0JCeEIwZ0NrRU1ha0Z3Y1VIWXF0V3FCWE0yQWdCQjJCMUJBRFlDQUVHb0hVRUFOZ0lBUVlBZ0N5SUJhaUlHUVFBZ0FXc2lDSEVpQVNBRlRRME1RYVFkS0FJQUlnUUVRRUdjSFNnQ0FDSUhJQUZxSWdrZ0IwMGdCQ0FKU1hJTkRRc0NRRUdvSFMwQUFFRUVjVVVFUUFKQUFrQUNRQUpBUVlRYUtBSUFJZ1FFUUVHc0hTRUFBMEFnQkNBQUtBSUFJZ2RQQkVBZ0J5QUFLQUlFYWlBRVN3MERDeUFBS0FJSUlnQU5BQXNMUVFBUUN5SUNRWDlHRFFNZ0FTRUdRY2dkS0FJQUlnQkJBV3NpQkNBQ2NRUkFJQUVnQW1zZ0FpQUVha0VBSUFCcmNXb2hCZ3NnQlNBR1R3MERRYVFkS0FJQUlnQUVRRUdjSFNnQ0FDSUVJQVpxSWdnZ0JFMGdBQ0FJU1hJTkJBc2dCaEFMSWdBZ0FrY05BUXdGQ3lBR0lBSnJJQWh4SWdZUUN5SUNJQUFvQWdBZ0FDZ0NCR3BHRFFFZ0FpRUFDeUFBUVg5R0RRRWdCVUV3YWlBR1RRUkFJQUFoQWd3RUMwSE1IU2dDQUNJQ0lBTWdCbXRxUVFBZ0FtdHhJZ0lRQzBGL1JnMEJJQUlnQm1vaEJpQUFJUUlNQXdzZ0FrRi9SdzBDQzBHb0hVR29IU2dDQUVFRWNqWUNBQXNnQVJBTElnSkJmMFpCQUJBTElnQkJmMFp5SUFBZ0FrMXlEUVVnQUNBQ2F5SUdJQVZCS0dwTkRRVUxRWndkUVp3ZEtBSUFJQVpxSWdBMkFnQkJvQjBvQWdBZ0FFa0VRRUdnSFNBQU5nSUFDd0pBUVlRYUtBSUFJZ01FUUVHc0hTRUFBMEFnQWlBQUtBSUFJZ0VnQUNnQ0JDSUVha1lOQWlBQUtBSUlJZ0FOQUFzTUJBdEIvQmtvQWdBaUFFRUFJQUFnQWswYlJRUkFRZndaSUFJMkFnQUxRUUFoQUVHd0hTQUdOZ0lBUWF3ZElBSTJBZ0JCakJwQmZ6WUNBRUdRR2tIRUhTZ0NBRFlDQUVHNEhVRUFOZ0lBQTBBZ0FFRURkQ0lCUVp3YWFpQUJRWlFhYWlJRU5nSUFJQUZCb0JwcUlBUTJBZ0FnQUVFQmFpSUFRU0JIRFFBTFFmZ1pJQVpCS0dzaUFFRjRJQUpyUVFkeElnRnJJZ1EyQWdCQmhCb2dBU0FDYWlJQk5nSUFJQUVnQkVFQmNqWUNCQ0FBSUFKcVFTZzJBZ1JCaUJwQjFCMG9BZ0EyQWdBTUJBc2dBaUFEVFNBQklBTkxjZzBDSUFBb0FneEJDSEVOQWlBQUlBUWdCbW8yQWdSQmhCb2dBMEY0SUFOclFRZHhJZ0JxSWdFMkFnQkIrQmxCK0Jrb0FnQWdCbW9pQWlBQWF5SUFOZ0lBSUFFZ0FFRUJjallDQkNBQ0lBTnFRU2cyQWdSQmlCcEIxQjBvQWdBMkFnQU1Bd3RCQUNFRURBb0xRUUFoQWd3SUMwSDhHU2dDQUNBQ1N3UkFRZndaSUFJMkFnQUxJQUlnQm1vaEFVR3NIU0VBQWtBQ1FBSkFBMEFnQVNBQUtBSUFSd1JBSUFBb0FnZ2lBQTBCREFJTEN5QUFMUUFNUVFoeFJRMEJDMEdzSFNFQUEwQWdBeUFBS0FJQUlnRlBCRUFnQVNBQUtBSUVhaUlFSUFOTERRTUxJQUFvQWdnaEFBd0FDd0FMSUFBZ0FqWUNBQ0FBSUFBb0FnUWdCbW8yQWdRZ0FrRjRJQUpyUVFkeGFpSUhJQVZCQTNJMkFnUWdBVUY0SUFGclFRZHhhaUlHSUFVZ0Iyb2lCV3NoQUNBRElBWkdCRUJCaEJvZ0JUWUNBRUg0R1VINEdTZ0NBQ0FBYWlJQU5nSUFJQVVnQUVFQmNqWUNCQXdJQzBHQUdpZ0NBQ0FHUmdSQVFZQWFJQVUyQWdCQjlCbEI5QmtvQWdBZ0FHb2lBRFlDQUNBRklBQkJBWEkyQWdRZ0FDQUZhaUFBTmdJQURBZ0xJQVlvQWdRaUEwRURjVUVCUncwR0lBTkJlSEVoQ1NBRFFmOEJUUVJBSUFZb0Fnd2lBU0FHS0FJSUlnSkdCRUJCN0JsQjdCa29BZ0JCZmlBRFFRTjJkM0UyQWdBTUJ3c2dBaUFCTmdJTUlBRWdBallDQ0F3R0N5QUdLQUlZSVFnZ0JpQUdLQUlNSWdKSEJFQWdCaWdDQ0NJQklBSTJBZ3dnQWlBQk5nSUlEQVVMSUFaQkZHb2lBU2dDQUNJRFJRUkFJQVlvQWhBaUEwVU5CQ0FHUVJCcUlRRUxBMEFnQVNFRUlBTWlBa0VVYWlJQktBSUFJZ01OQUNBQ1FSQnFJUUVnQWlnQ0VDSUREUUFMSUFSQkFEWUNBQXdFQzBINEdTQUdRU2hySWdCQmVDQUNhMEVIY1NJQmF5SUlOZ0lBUVlRYUlBRWdBbW9pQVRZQ0FDQUJJQWhCQVhJMkFnUWdBQ0FDYWtFb05nSUVRWWdhUWRRZEtBSUFOZ0lBSUFNZ0JFRW5JQVJyUVFkeGFrRXZheUlBSUFBZ0EwRVFha2tiSWdGQkd6WUNCQ0FCUWJRZEtRSUFOd0lRSUFGQnJCMHBBZ0EzQWdoQnRCMGdBVUVJYWpZQ0FFR3dIU0FHTmdJQVFhd2RJQUkyQWdCQnVCMUJBRFlDQUNBQlFSaHFJUUFEUUNBQVFRYzJBZ1FnQUVFSWFpRU1JQUJCQkdvaEFDQU1JQVJKRFFBTElBRWdBMFlOQUNBQklBRW9BZ1JCZm5FMkFnUWdBeUFCSUFOcklnSkJBWEkyQWdRZ0FTQUNOZ0lBSUFKQi93Rk5CRUFnQWtGNGNVR1VHbW9oQUFKL1Fld1pLQUlBSWdGQkFTQUNRUU4yZENJQ2NVVUVRRUhzR1NBQklBSnlOZ0lBSUFBTUFRc2dBQ2dDQ0FzaEFTQUFJQU0yQWdnZ0FTQUROZ0lNSUFNZ0FEWUNEQ0FESUFFMkFnZ01BUXRCSHlFQUlBSkIvLy8vQjAwRVFDQUNRU1lnQWtFSWRtY2lBR3QyUVFGeElBQkJBWFJyUVQ1cUlRQUxJQU1nQURZQ0hDQURRZ0EzQWhBZ0FFRUNkRUdjSEdvaEFRSkFBa0JCOEJrb0FnQWlCRUVCSUFCMElnWnhSUVJBUWZBWklBUWdCbkkyQWdBZ0FTQUROZ0lBREFFTElBSkJHU0FBUVFGMmEwRUFJQUJCSDBjYmRDRUFJQUVvQWdBaEJBTkFJQVFpQVNnQ0JFRjRjU0FDUmcwQ0lBQkJIWFloQkNBQVFRRjBJUUFnQVNBRVFRUnhhaUlHS0FJUUlnUU5BQXNnQmlBRE5nSVFDeUFESUFFMkFoZ2dBeUFETmdJTUlBTWdBellDQ0F3QkN5QUJLQUlJSWdBZ0F6WUNEQ0FCSUFNMkFnZ2dBMEVBTmdJWUlBTWdBVFlDRENBRElBQTJBZ2dMUWZnWktBSUFJZ0FnQlUwTkFFSDRHU0FBSUFWcklnRTJBZ0JCaEJwQmhCb29BZ0FpQUNBRmFpSUNOZ0lBSUFJZ0FVRUJjallDQkNBQUlBVkJBM0kyQWdRZ0FFRUlhaUVBREFnTFFlZ1pRVEEyQWdCQkFDRUFEQWNMUVFBaEFnc2dDRVVOQUFKQUlBWW9BaHdpQVVFQ2RFR2NIR29pQkNnQ0FDQUdSZ1JBSUFRZ0FqWUNBQ0FDRFFGQjhCbEI4QmtvQWdCQmZpQUJkM0UyQWdBTUFnc2dDRUVRUVJRZ0NDZ0NFQ0FHUmh0cUlBSTJBZ0FnQWtVTkFRc2dBaUFJTmdJWUlBWW9BaEFpQVFSQUlBSWdBVFlDRUNBQklBSTJBaGdMSUFZb0FoUWlBVVVOQUNBQ0lBRTJBaFFnQVNBQ05nSVlDeUFBSUFscUlRQWdCaUFKYWlJR0tBSUVJUU1MSUFZZ0EwRitjVFlDQkNBRklBQkJBWEkyQWdRZ0FDQUZhaUFBTmdJQUlBQkIvd0ZOQkVBZ0FFRjRjVUdVR21vaEFRSi9RZXdaS0FJQUlnSkJBU0FBUVFOMmRDSUFjVVVFUUVIc0dTQUFJQUp5TmdJQUlBRU1BUXNnQVNnQ0NBc2hBQ0FCSUFVMkFnZ2dBQ0FGTmdJTUlBVWdBVFlDRENBRklBQTJBZ2dNQVF0Qkh5RURJQUJCLy8vL0IwMEVRQ0FBUVNZZ0FFRUlkbWNpQVd0MlFRRnhJQUZCQVhSclFUNXFJUU1MSUFVZ0F6WUNIQ0FGUWdBM0FoQWdBMEVDZEVHY0hHb2hBUUpBQWtCQjhCa29BZ0FpQWtFQklBTjBJZ1J4UlFSQVFmQVpJQUlnQkhJMkFnQWdBU0FGTmdJQURBRUxJQUJCR1NBRFFRRjJhMEVBSUFOQkgwY2JkQ0VESUFFb0FnQWhBZ05BSUFJaUFTZ0NCRUY0Y1NBQVJnMENJQU5CSFhZaEFpQURRUUYwSVFNZ0FTQUNRUVJ4YWlJRUtBSVFJZ0lOQUFzZ0JDQUZOZ0lRQ3lBRklBRTJBaGdnQlNBRk5nSU1JQVVnQlRZQ0NBd0JDeUFCS0FJSUlnQWdCVFlDRENBQklBVTJBZ2dnQlVFQU5nSVlJQVVnQVRZQ0RDQUZJQUEyQWdnTElBZEJDR29oQUF3Q0N3SkFJQWRGRFFBQ1FDQUVLQUljSWdCQkFuUkJuQnhxSWdFb0FnQWdCRVlFUUNBQklBSTJBZ0FnQWcwQlFmQVpJQWhCZmlBQWQzRWlDRFlDQUF3Q0N5QUhRUkJCRkNBSEtBSVFJQVJHRzJvZ0FqWUNBQ0FDUlEwQkN5QUNJQWMyQWhnZ0JDZ0NFQ0lBQkVBZ0FpQUFOZ0lRSUFBZ0FqWUNHQXNnQkNnQ0ZDSUFSUTBBSUFJZ0FEWUNGQ0FBSUFJMkFoZ0xBa0FnQTBFUFRRUkFJQVFnQXlBRmFpSUFRUU55TmdJRUlBQWdCR29pQUNBQUtBSUVRUUZ5TmdJRURBRUxJQVFnQlVFRGNqWUNCQ0FFSUFWcUlnSWdBMEVCY2pZQ0JDQUNJQU5xSUFNMkFnQWdBMEgvQVUwRVFDQURRWGh4UVpRYWFpRUFBbjlCN0Jrb0FnQWlBVUVCSUFOQkEzWjBJZ054UlFSQVFld1pJQUVnQTNJMkFnQWdBQXdCQ3lBQUtBSUlDeUVCSUFBZ0FqWUNDQ0FCSUFJMkFnd2dBaUFBTmdJTUlBSWdBVFlDQ0F3QkMwRWZJUUFnQTBILy8vOEhUUVJBSUFOQkppQURRUWgyWnlJQWEzWkJBWEVnQUVFQmRHdEJQbW9oQUFzZ0FpQUFOZ0ljSUFKQ0FEY0NFQ0FBUVFKMFFad2NhaUVCQWtBQ1FDQUlRUUVnQUhRaUJuRkZCRUJCOEJrZ0JpQUljallDQUNBQklBSTJBZ0FNQVFzZ0EwRVpJQUJCQVhaclFRQWdBRUVmUnh0MElRQWdBU2dDQUNFRkEwQWdCU0lCS0FJRVFYaHhJQU5HRFFJZ0FFRWRkaUVHSUFCQkFYUWhBQ0FCSUFaQkJIRnFJZ1lvQWhBaUJRMEFDeUFHSUFJMkFoQUxJQUlnQVRZQ0dDQUNJQUkyQWd3Z0FpQUNOZ0lJREFFTElBRW9BZ2dpQUNBQ05nSU1JQUVnQWpZQ0NDQUNRUUEyQWhnZ0FpQUJOZ0lNSUFJZ0FEWUNDQXNnQkVFSWFpRUFEQUVMQWtBZ0NVVU5BQUpBSUFJb0Fod2lBRUVDZEVHY0hHb2lBU2dDQUNBQ1JnUkFJQUVnQkRZQ0FDQUVEUUZCOEJrZ0MwRitJQUIzY1RZQ0FBd0NDeUFKUVJCQkZDQUpLQUlRSUFKR0cyb2dCRFlDQUNBRVJRMEJDeUFFSUFrMkFoZ2dBaWdDRUNJQUJFQWdCQ0FBTmdJUUlBQWdCRFlDR0FzZ0FpZ0NGQ0lBUlEwQUlBUWdBRFlDRkNBQUlBUTJBaGdMQWtBZ0EwRVBUUVJBSUFJZ0F5QUZhaUlBUVFOeU5nSUVJQUFnQW1vaUFDQUFLQUlFUVFGeU5nSUVEQUVMSUFJZ0JVRURjallDQkNBQ0lBVnFJZ1FnQTBFQmNqWUNCQ0FESUFScUlBTTJBZ0FnQndSQUlBZEJlSEZCbEJwcUlRQkJnQm9vQWdBaEFRSi9RUUVnQjBFRGRuUWlCU0FHY1VVRVFFSHNHU0FGSUFaeU5nSUFJQUFNQVFzZ0FDZ0NDQXNoQmlBQUlBRTJBZ2dnQmlBQk5nSU1JQUVnQURZQ0RDQUJJQVkyQWdnTFFZQWFJQVEyQWdCQjlCa2dBellDQUFzZ0FrRUlhaUVBQ3lBS1FSQnFKQUFnQUFzakFRRi9RZHdaS0FJQUlnQUVRQU5BSUFBb0FnQVJCUUFnQUNnQ0JDSUFEUUFMQ3dzYUFDQUFJQUVvQWdnZ0JSQUtCRUFnQVNBQ0lBTWdCQkFUQ3dzM0FDQUFJQUVvQWdnZ0JSQUtCRUFnQVNBQ0lBTWdCQkFURHdzZ0FDZ0NDQ0lBSUFFZ0FpQURJQVFnQlNBQUtBSUFLQUlVRVFNQUM1RUJBQ0FBSUFFb0FnZ2dCQkFLQkVBZ0FTQUNJQU1RRWc4TEFrQWdBQ0FCS0FJQUlBUVFDa1VOQUFKQUlBSWdBU2dDRUVjRVFDQUJLQUlVSUFKSERRRUxJQU5CQVVjTkFTQUJRUUUyQWlBUEN5QUJJQUkyQWhRZ0FTQUROZ0lnSUFFZ0FTZ0NLRUVCYWpZQ0tBSkFJQUVvQWlSQkFVY05BQ0FCS0FJWVFRSkhEUUFnQVVFQk9nQTJDeUFCUVFRMkFpd0xDL0lCQUNBQUlBRW9BZ2dnQkJBS0JFQWdBU0FDSUFNUUVnOExBa0FnQUNBQktBSUFJQVFRQ2dSQUFrQWdBaUFCS0FJUVJ3UkFJQUVvQWhRZ0FrY05BUXNnQTBFQlJ3MENJQUZCQVRZQ0lBOExJQUVnQXpZQ0lBSkFJQUVvQWl4QkJFWU5BQ0FCUVFBN0FUUWdBQ2dDQ0NJQUlBRWdBaUFDUVFFZ0JDQUFLQUlBS0FJVUVRTUFJQUV0QURVRVFDQUJRUU0yQWl3Z0FTMEFORVVOQVF3REN5QUJRUVEyQWl3TElBRWdBallDRkNBQklBRW9BaWhCQVdvMkFpZ2dBU2dDSkVFQlJ3MEJJQUVvQWhoQkFrY05BU0FCUVFFNkFEWVBDeUFBS0FJSUlnQWdBU0FDSUFNZ0JDQUFLQUlBS0FJWUVRSUFDd3N4QUNBQUlBRW9BZ2hCQUJBS0JFQWdBU0FDSUFNUUZBOExJQUFvQWdnaUFDQUJJQUlnQXlBQUtBSUFLQUljRVFBQUN4Z0FJQUFnQVNnQ0NFRUFFQW9FUUNBQklBSWdBeEFVQ3d2S0F3RUZmeU1BUVVCcUlnUWtBQUovUVFFZ0FDQUJRUUFRQ2cwQUdrRUFJQUZGRFFBYUl3QkJRR29pQXlRQUlBRW9BZ0FpQlVFRWF5Z0NBQ0VHSUFWQkNHc29BZ0FoQlNBRFFnQTNBaUFnQTBJQU53SW9JQU5DQURjQ01DQURRZ0EzQURjZ0EwSUFOd0lZSUFOQkFEWUNGQ0FEUWZ3Vk5nSVFJQU1nQVRZQ0RDQURRYXdXTmdJSUlBRWdCV29oQVVFQUlRVUNRQ0FHUWF3V1FRQVFDZ1JBSUFOQkFUWUNPQ0FHSUFOQkNHb2dBU0FCUVFGQkFDQUdLQUlBS0FJVUVRTUFJQUZCQUNBREtBSWdRUUZHR3lFRkRBRUxJQVlnQTBFSWFpQUJRUUZCQUNBR0tBSUFLQUlZRVFJQUFrQUNRQ0FES0FJc0RnSUFBUUlMSUFNb0FoeEJBQ0FES0FJb1FRRkdHMEVBSUFNb0FpUkJBVVliUVFBZ0F5Z0NNRUVCUmhzaEJRd0JDeUFES0FJZ1FRRkhCRUFnQXlnQ01BMEJJQU1vQWlSQkFVY05BU0FES0FJb1FRRkhEUUVMSUFNb0FoZ2hCUXNnQTBGQWF5UUFRUUFnQlNJQlJRMEFHaUFFUVF4cVFUUVFEeG9nQkVFQk5nSTRJQVJCZnpZQ0ZDQUVJQUEyQWhBZ0JDQUJOZ0lJSUFFZ0JFRUlhaUFDS0FJQVFRRWdBU2dDQUNnQ0hCRUFBQ0FFS0FJZ0lnQkJBVVlFUUNBQ0lBUW9BaGcyQWdBTElBQkJBVVlMSVFjZ0JFRkFheVFBSUFjTENnQWdBQ0FCUVFBUUNnc0VBQ0FBQy9vRUFnWi9DbjFCLy8vLy93Y2hERUdBZ0lDQWVDRU5RWDhoQ2dOQUlBTWdDMFlFUUVFQUlRa2dDRUdBZ0JBUUR5RUFRd0QvZjBjZ0RTQU1hN0tWSVJBRFFDQURJQWxHQkVCQkFDRUpJQWRCQURZQ0FDQUFRUVJySVFCQkFDRU1RUUVoQ3dOQUlBdEJnSUFFUmtVRVFDQUhJQXRCQW5RaUFXb2dBQ0FCYWlnQ0FDQU1haUlNTmdJQUlBdEJBV29oQ3d3QkN3c0RRQ0FESUFsR1JRUkFJQWNnQlNBSlFRSjBhaWdDQUVFQ2RHb2lBQ0FBS0FJQUlnQkJBV28yQWdBZ0JpQUFRUUowYWlBSk5nSUFJQWxCQVdvaENRd0JDd3NGQW44Z0VDQUZJQWxCQW5ScUlnRW9BZ0FnREd1emxDSVBRd0FBZ0U5ZElBOURBQUFBQUdCeEJFQWdENmtNQVF0QkFBc2hDeUFCSUFzMkFnQWdBQ0FMUVFKMGFpSUJJQUVvQWdCQkFXbzJBZ0FnQ1VFQmFpRUpEQUVMQ3dVZ0JDQUxRUXhzYWlJSktnSUFJUk1nQ1NvQ0NDRVVJQWtxQWdRaEZTQUtJQUlnQzBFQ2RDSU9haWdDQUNJSlJ3UkFJQUVnQ1VIUUFHeHFJZ29xQWp3Z0FDb0NPQ0lQbENBS0tnSTRJQUFxQWlnaUVKUWdDaW9DTUNBQUtnSUlJaEdVSUFBcUFoZ2lFaUFLS2dJMGxKS1NraUVXSUFvcUFpd2dENVFnQ2lvQ0tDQVFsQ0FLS2dJZ0lCR1VJQklnQ2lvQ0pKU1NrcEloRnlBS0tnSWNJQStVSUFvcUFoZ2dFSlFnQ2lvQ0VDQVJsQ0FTSUFvcUFoU1VrcEtTSVJnZ0Npb0NEQ0FQbENBS0tnSUlJQkNVSUFvcUFnQWdFWlFnQ2lvQ0JDQVNsSktTa2lFUElBa2hDZ3NnQlNBT2FnSi9JQllnRnlBVWxDQVBJQk9VSUJVZ0dKU1NrcEpEQUFDQVJaUWlFSXREQUFBQVQxMEVRQ0FRcUF3QkMwR0FnSUNBZUFzaUNUWUNBQ0FNSUFrZ0NTQU1TaHNoRENBTklBa2dDU0FOU0JzaERTQUxRUUZxSVFzTUFRc0xDd3ZuRVFJQVFZQUlDOVlSZFc1emFXZHVaV1FnYzJodmNuUUFkVzV6YVdkdVpXUWdhVzUwQUdac2IyRjBBSFZwYm5RMk5GOTBBSFZ1YzJsbmJtVmtJR05vWVhJQVltOXZiQUJsYlhOamNtbHdkR1Z1T2pwMllXd0FkVzV6YVdkdVpXUWdiRzl1WndCemRHUTZPbmR6ZEhKcGJtY0FjM1JrT2pwemRISnBibWNBYzNSa09qcDFNVFp6ZEhKcGJtY0FjM1JrT2pwMU16SnpkSEpwYm1jQVpHOTFZbXhsQUhadmFXUUFaVzF6WTNKcGNIUmxiam82YldWdGIzSjVYM1pwWlhjOGMyaHZjblErQUdWdGMyTnlhWEIwWlc0Nk9tMWxiVzl5ZVY5MmFXVjNQSFZ1YzJsbmJtVmtJSE5vYjNKMFBnQmxiWE5qY21sd2RHVnVPanB0WlcxdmNubGZkbWxsZHp4cGJuUStBR1Z0YzJOeWFYQjBaVzQ2T20xbGJXOXllVjkyYVdWM1BIVnVjMmxuYm1Wa0lHbHVkRDRBWlcxelkzSnBjSFJsYmpvNmJXVnRiM0o1WDNacFpYYzhabXh2WVhRK0FHVnRjMk55YVhCMFpXNDZPbTFsYlc5eWVWOTJhV1YzUEhWcGJuUTRYM1ErQUdWdGMyTnlhWEIwWlc0Nk9tMWxiVzl5ZVY5MmFXVjNQR2x1ZERoZmRENEFaVzF6WTNKcGNIUmxiam82YldWdGIzSjVYM1pwWlhjOGRXbHVkREUyWDNRK0FHVnRjMk55YVhCMFpXNDZPbTFsYlc5eWVWOTJhV1YzUEdsdWRERTJYM1ErQUdWdGMyTnlhWEIwWlc0Nk9tMWxiVzl5ZVY5MmFXVjNQSFZwYm5RMk5GOTBQZ0JsYlhOamNtbHdkR1Z1T2pwdFpXMXZjbmxmZG1sbGR6eHBiblEyTkY5MFBnQmxiWE5qY21sd2RHVnVPanB0WlcxdmNubGZkbWxsZHp4MWFXNTBNekpmZEQ0QVpXMXpZM0pwY0hSbGJqbzZiV1Z0YjNKNVgzWnBaWGM4YVc1ME16SmZkRDRBWlcxelkzSnBjSFJsYmpvNmJXVnRiM0o1WDNacFpYYzhZMmhoY2o0QVpXMXpZM0pwY0hSbGJqbzZiV1Z0YjNKNVgzWnBaWGM4ZFc1emFXZHVaV1FnWTJoaGNqNEFjM1JrT2pwaVlYTnBZMTl6ZEhKcGJtYzhkVzV6YVdkdVpXUWdZMmhoY2o0QVpXMXpZM0pwY0hSbGJqbzZiV1Z0YjNKNVgzWnBaWGM4YzJsbmJtVmtJR05vWVhJK0FHVnRjMk55YVhCMFpXNDZPbTFsYlc5eWVWOTJhV1YzUEd4dmJtYytBR1Z0YzJOeWFYQjBaVzQ2T20xbGJXOXllVjkyYVdWM1BIVnVjMmxuYm1Wa0lHeHZibWMrQUdWdGMyTnlhWEIwWlc0Nk9tMWxiVzl5ZVY5MmFXVjNQR1J2ZFdKc1pUNEFUbE4wTTE5Zk1qRXlZbUZ6YVdOZmMzUnlhVzVuU1dOT1UxOHhNV05vWVhKZmRISmhhWFJ6U1dORlJVNVRYemxoYkd4dlkyRjBiM0pKWTBWRlJVVUFBQUFBUkF3QUFFSUhBQUJPVTNRelgxOHlNVEppWVhOcFkxOXpkSEpwYm1kSmFFNVRYekV4WTJoaGNsOTBjbUZwZEhOSmFFVkZUbE5mT1dGc2JHOWpZWFJ2Y2tsb1JVVkZSUUFBUkF3QUFJd0hBQUJPVTNRelgxOHlNVEppWVhOcFkxOXpkSEpwYm1kSmQwNVRYekV4WTJoaGNsOTBjbUZwZEhOSmQwVkZUbE5mT1dGc2JHOWpZWFJ2Y2tsM1JVVkZSUUFBUkF3QUFOUUhBQUJPVTNRelgxOHlNVEppWVhOcFkxOXpkSEpwYm1kSlJITk9VMTh4TVdOb1lYSmZkSEpoYVhSelNVUnpSVVZPVTE4NVlXeHNiMk5oZEc5eVNVUnpSVVZGUlFBQUFFUU1BQUFjQ0FBQVRsTjBNMTlmTWpFeVltRnphV05mYzNSeWFXNW5TVVJwVGxOZk1URmphR0Z5WDNSeVlXbDBjMGxFYVVWRlRsTmZPV0ZzYkc5allYUnZja2xFYVVWRlJVVUFBQUJFREFBQWFBZ0FBRTR4TUdWdGMyTnlhWEIwWlc0emRtRnNSUUFBUkF3QUFMUUlBQUJPTVRCbGJYTmpjbWx3ZEdWdU1URnRaVzF2Y25sZmRtbGxkMGxqUlVVQUFFUU1BQURRQ0FBQVRqRXdaVzF6WTNKcGNIUmxiakV4YldWdGIzSjVYM1pwWlhkSllVVkZBQUJFREFBQStBZ0FBRTR4TUdWdGMyTnlhWEIwWlc0eE1XMWxiVzl5ZVY5MmFXVjNTV2hGUlFBQVJBd0FBQ0FKQUFCT01UQmxiWE5qY21sd2RHVnVNVEZ0WlcxdmNubGZkbWxsZDBselJVVUFBRVFNQUFCSUNRQUFUakV3WlcxelkzSnBjSFJsYmpFeGJXVnRiM0o1WDNacFpYZEpkRVZGQUFCRURBQUFjQWtBQUU0eE1HVnRjMk55YVhCMFpXNHhNVzFsYlc5eWVWOTJhV1YzU1dsRlJRQUFSQXdBQUpnSkFBQk9NVEJsYlhOamNtbHdkR1Z1TVRGdFpXMXZjbmxmZG1sbGQwbHFSVVVBQUVRTUFBREFDUUFBVGpFd1pXMXpZM0pwY0hSbGJqRXhiV1Z0YjNKNVgzWnBaWGRKYkVWRkFBQkVEQUFBNkFrQUFFNHhNR1Z0YzJOeWFYQjBaVzR4TVcxbGJXOXllVjkyYVdWM1NXMUZSUUFBUkF3QUFCQUtBQUJPTVRCbGJYTmpjbWx3ZEdWdU1URnRaVzF2Y25sZmRtbGxkMGw0UlVVQUFFUU1BQUE0Q2dBQVRqRXdaVzF6WTNKcGNIUmxiakV4YldWdGIzSjVYM1pwWlhkSmVVVkZBQUJFREFBQVlBb0FBRTR4TUdWdGMyTnlhWEIwWlc0eE1XMWxiVzl5ZVY5MmFXVjNTV1pGUlFBQVJBd0FBSWdLQUFCT01UQmxiWE5qY21sd2RHVnVNVEZ0WlcxdmNubGZkbWxsZDBsa1JVVUFBRVFNQUFDd0NnQUFUakV3WDE5amVIaGhZbWwyTVRFMlgxOXphR2x0WDNSNWNHVmZhVzVtYjBVQUFBQUFiQXdBQU5nS0FBRFFEQUFBVGpFd1gxOWplSGhoWW1sMk1URTNYMTlqYkdGemMxOTBlWEJsWDJsdVptOUZBQUFBYkF3QUFBZ0xBQUQ4Q2dBQUFBQUFBSHdMQUFBQ0FBQUFBd0FBQUFRQUFBQUZBQUFBQmdBQUFFNHhNRjlmWTNoNFlXSnBkakV5TTE5ZlpuVnVaR0Z0Wlc1MFlXeGZkSGx3WlY5cGJtWnZSUUJzREFBQVZBc0FBUHdLQUFCMkFBQUFRQXNBQUlnTEFBQmlBQUFBUUFzQUFKUUxBQUJqQUFBQVFBc0FBS0FMQUFCb0FBQUFRQXNBQUt3TEFBQmhBQUFBUUFzQUFMZ0xBQUJ6QUFBQVFBc0FBTVFMQUFCMEFBQUFRQXNBQU5BTEFBQnBBQUFBUUFzQUFOd0xBQUJxQUFBQVFBc0FBT2dMQUFCc0FBQUFRQXNBQVBRTEFBQnRBQUFBUUFzQUFBQU1BQUI0QUFBQVFBc0FBQXdNQUFCNUFBQUFRQXNBQUJnTUFBQm1BQUFBUUFzQUFDUU1BQUJrQUFBQVFBc0FBREFNQUFBQUFBQUFMQXNBQUFJQUFBQUhBQUFBQkFBQUFBVUFBQUFJQUFBQUNRQUFBQW9BQUFBTEFBQUFBQUFBQUxRTUFBQUNBQUFBREFBQUFBUUFBQUFGQUFBQUNBQUFBQTBBQUFBT0FBQUFEd0FBQUU0eE1GOWZZM2g0WVdKcGRqRXlNRjlmYzJsZlkyeGhjM05mZEhsd1pWOXBibVp2UlFBQUFBQnNEQUFBakF3QUFDd0xBQUJUZERsMGVYQmxYMmx1Wm04QUFBQUFSQXdBQU1BTUFFSFlHUXNENEE0QiI7aWYoIWlzRGF0YVVSSSh3YXNtQmluYXJ5RmlsZSkpe3dhc21CaW5hcnlGaWxlPWxvY2F0ZUZpbGUod2FzbUJpbmFyeUZpbGUpO31mdW5jdGlvbiBnZXRCaW5hcnlTeW5jKGZpbGUpe2lmKGZpbGU9PXdhc21CaW5hcnlGaWxlJiZ3YXNtQmluYXJ5KXtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkod2FzbUJpbmFyeSl9dmFyIGJpbmFyeT10cnlQYXJzZUFzRGF0YVVSSShmaWxlKTtpZihiaW5hcnkpe3JldHVybiBiaW5hcnl9aWYocmVhZEJpbmFyeSl7cmV0dXJuIHJlYWRCaW5hcnkoZmlsZSl9dGhyb3cgImJvdGggYXN5bmMgYW5kIHN5bmMgZmV0Y2hpbmcgb2YgdGhlIHdhc20gZmFpbGVkIn1mdW5jdGlvbiBnZXRCaW5hcnlQcm9taXNlKGJpbmFyeUZpbGUpe3JldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpPT5nZXRCaW5hcnlTeW5jKGJpbmFyeUZpbGUpKX1mdW5jdGlvbiBpbnN0YW50aWF0ZUFycmF5QnVmZmVyKGJpbmFyeUZpbGUsaW1wb3J0cyxyZWNlaXZlcil7cmV0dXJuIGdldEJpbmFyeVByb21pc2UoYmluYXJ5RmlsZSkudGhlbihiaW5hcnk9PldlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGJpbmFyeSxpbXBvcnRzKSkudGhlbihpbnN0YW5jZT0+aW5zdGFuY2UpLnRoZW4ocmVjZWl2ZXIscmVhc29uPT57ZXJyKGBmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiAke3JlYXNvbn1gKTthYm9ydChyZWFzb24pO30pfWZ1bmN0aW9uIGluc3RhbnRpYXRlQXN5bmMoYmluYXJ5LGJpbmFyeUZpbGUsaW1wb3J0cyxjYWxsYmFjayl7cmV0dXJuIGluc3RhbnRpYXRlQXJyYXlCdWZmZXIoYmluYXJ5RmlsZSxpbXBvcnRzLGNhbGxiYWNrKX1mdW5jdGlvbiBjcmVhdGVXYXNtKCl7dmFyIGluZm89eyJhIjp3YXNtSW1wb3J0c307ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbmNlKGluc3RhbmNlLG1vZHVsZSl7d2FzbUV4cG9ydHM9aW5zdGFuY2UuZXhwb3J0czt3YXNtTWVtb3J5PXdhc21FeHBvcnRzWyJrIl07dXBkYXRlTWVtb3J5Vmlld3MoKTthZGRPbkluaXQod2FzbUV4cG9ydHNbImwiXSk7cmVtb3ZlUnVuRGVwZW5kZW5jeSgpO3JldHVybiB3YXNtRXhwb3J0c31hZGRSdW5EZXBlbmRlbmN5KCk7ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbnRpYXRpb25SZXN1bHQocmVzdWx0KXtyZWNlaXZlSW5zdGFuY2UocmVzdWx0WyJpbnN0YW5jZSJdKTt9aWYoTW9kdWxlWyJpbnN0YW50aWF0ZVdhc20iXSl7dHJ5e3JldHVybiBNb2R1bGVbImluc3RhbnRpYXRlV2FzbSJdKGluZm8scmVjZWl2ZUluc3RhbmNlKX1jYXRjaChlKXtlcnIoYE1vZHVsZS5pbnN0YW50aWF0ZVdhc20gY2FsbGJhY2sgZmFpbGVkIHdpdGggZXJyb3I6ICR7ZX1gKTtyZWFkeVByb21pc2VSZWplY3QoZSk7fX1pbnN0YW50aWF0ZUFzeW5jKHdhc21CaW5hcnksd2FzbUJpbmFyeUZpbGUsaW5mbyxyZWNlaXZlSW5zdGFudGlhdGlvblJlc3VsdCkuY2F0Y2gocmVhZHlQcm9taXNlUmVqZWN0KTtyZXR1cm4ge319dmFyIGNhbGxSdW50aW1lQ2FsbGJhY2tzPWNhbGxiYWNrcz0+e3doaWxlKGNhbGxiYWNrcy5sZW5ndGg+MCl7Y2FsbGJhY2tzLnNoaWZ0KCkoTW9kdWxlKTt9fTtNb2R1bGVbIm5vRXhpdFJ1bnRpbWUiXXx8dHJ1ZTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfYmlnaW50PShwcmltaXRpdmVUeXBlLG5hbWUsc2l6ZSxtaW5SYW5nZSxtYXhSYW5nZSk9Pnt9O3ZhciBlbWJpbmRfaW5pdF9jaGFyQ29kZXM9KCk9Pnt2YXIgY29kZXM9bmV3IEFycmF5KDI1Nik7Zm9yKHZhciBpPTA7aTwyNTY7KytpKXtjb2Rlc1tpXT1TdHJpbmcuZnJvbUNoYXJDb2RlKGkpO31lbWJpbmRfY2hhckNvZGVzPWNvZGVzO307dmFyIGVtYmluZF9jaGFyQ29kZXM7dmFyIHJlYWRMYXRpbjFTdHJpbmc9cHRyPT57dmFyIHJldD0iIjt2YXIgYz1wdHI7d2hpbGUoSEVBUFU4W2NdKXtyZXQrPWVtYmluZF9jaGFyQ29kZXNbSEVBUFU4W2MrK11dO31yZXR1cm4gcmV0fTt2YXIgYXdhaXRpbmdEZXBlbmRlbmNpZXM9e307dmFyIHJlZ2lzdGVyZWRUeXBlcz17fTt2YXIgQmluZGluZ0Vycm9yO3ZhciB0aHJvd0JpbmRpbmdFcnJvcj1tZXNzYWdlPT57dGhyb3cgbmV3IEJpbmRpbmdFcnJvcihtZXNzYWdlKX07ZnVuY3Rpb24gc2hhcmVkUmVnaXN0ZXJUeXBlKHJhd1R5cGUscmVnaXN0ZXJlZEluc3RhbmNlLG9wdGlvbnM9e30pe3ZhciBuYW1lPXJlZ2lzdGVyZWRJbnN0YW5jZS5uYW1lO2lmKCFyYXdUeXBlKXt0aHJvd0JpbmRpbmdFcnJvcihgdHlwZSAiJHtuYW1lfSIgbXVzdCBoYXZlIGEgcG9zaXRpdmUgaW50ZWdlciB0eXBlaWQgcG9pbnRlcmApO31pZihyZWdpc3RlcmVkVHlwZXMuaGFzT3duUHJvcGVydHkocmF3VHlwZSkpe2lmKG9wdGlvbnMuaWdub3JlRHVwbGljYXRlUmVnaXN0cmF0aW9ucyl7cmV0dXJufWVsc2Uge3Rocm93QmluZGluZ0Vycm9yKGBDYW5ub3QgcmVnaXN0ZXIgdHlwZSAnJHtuYW1lfScgdHdpY2VgKTt9fXJlZ2lzdGVyZWRUeXBlc1tyYXdUeXBlXT1yZWdpc3RlcmVkSW5zdGFuY2U7aWYoYXdhaXRpbmdEZXBlbmRlbmNpZXMuaGFzT3duUHJvcGVydHkocmF3VHlwZSkpe3ZhciBjYWxsYmFja3M9YXdhaXRpbmdEZXBlbmRlbmNpZXNbcmF3VHlwZV07ZGVsZXRlIGF3YWl0aW5nRGVwZW5kZW5jaWVzW3Jhd1R5cGVdO2NhbGxiYWNrcy5mb3JFYWNoKGNiPT5jYigpKTt9fWZ1bmN0aW9uIHJlZ2lzdGVyVHlwZShyYXdUeXBlLHJlZ2lzdGVyZWRJbnN0YW5jZSxvcHRpb25zPXt9KXtpZighKCJhcmdQYWNrQWR2YW5jZSJpbiByZWdpc3RlcmVkSW5zdGFuY2UpKXt0aHJvdyBuZXcgVHlwZUVycm9yKCJyZWdpc3RlclR5cGUgcmVnaXN0ZXJlZEluc3RhbmNlIHJlcXVpcmVzIGFyZ1BhY2tBZHZhbmNlIil9cmV0dXJuIHNoYXJlZFJlZ2lzdGVyVHlwZShyYXdUeXBlLHJlZ2lzdGVyZWRJbnN0YW5jZSxvcHRpb25zKX12YXIgR2VuZXJpY1dpcmVUeXBlU2l6ZT04O3ZhciBfX2VtYmluZF9yZWdpc3Rlcl9ib29sPShyYXdUeXBlLG5hbWUsdHJ1ZVZhbHVlLGZhbHNlVmFsdWUpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3JlZ2lzdGVyVHlwZShyYXdUeXBlLHtuYW1lOm5hbWUsImZyb21XaXJlVHlwZSI6ZnVuY3Rpb24od3Qpe3JldHVybiAhIXd0fSwidG9XaXJlVHlwZSI6ZnVuY3Rpb24oZGVzdHJ1Y3RvcnMsbyl7cmV0dXJuIG8/dHJ1ZVZhbHVlOmZhbHNlVmFsdWV9LCJhcmdQYWNrQWR2YW5jZSI6R2VuZXJpY1dpcmVUeXBlU2l6ZSwicmVhZFZhbHVlRnJvbVBvaW50ZXIiOmZ1bmN0aW9uKHBvaW50ZXIpe3JldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShIRUFQVThbcG9pbnRlcl0pfSxkZXN0cnVjdG9yRnVuY3Rpb246bnVsbH0pO307ZnVuY3Rpb24gaGFuZGxlQWxsb2NhdG9ySW5pdCgpe09iamVjdC5hc3NpZ24oSGFuZGxlQWxsb2NhdG9yLnByb3RvdHlwZSx7Z2V0KGlkKXtyZXR1cm4gdGhpcy5hbGxvY2F0ZWRbaWRdfSxoYXMoaWQpe3JldHVybiB0aGlzLmFsbG9jYXRlZFtpZF0hPT11bmRlZmluZWR9LGFsbG9jYXRlKGhhbmRsZSl7dmFyIGlkPXRoaXMuZnJlZWxpc3QucG9wKCl8fHRoaXMuYWxsb2NhdGVkLmxlbmd0aDt0aGlzLmFsbG9jYXRlZFtpZF09aGFuZGxlO3JldHVybiBpZH0sZnJlZShpZCl7dGhpcy5hbGxvY2F0ZWRbaWRdPXVuZGVmaW5lZDt0aGlzLmZyZWVsaXN0LnB1c2goaWQpO319KTt9ZnVuY3Rpb24gSGFuZGxlQWxsb2NhdG9yKCl7dGhpcy5hbGxvY2F0ZWQ9W3VuZGVmaW5lZF07dGhpcy5mcmVlbGlzdD1bXTt9dmFyIGVtdmFsX2hhbmRsZXM9bmV3IEhhbmRsZUFsbG9jYXRvcjt2YXIgX19lbXZhbF9kZWNyZWY9aGFuZGxlPT57aWYoaGFuZGxlPj1lbXZhbF9oYW5kbGVzLnJlc2VydmVkJiYwPT09LS1lbXZhbF9oYW5kbGVzLmdldChoYW5kbGUpLnJlZmNvdW50KXtlbXZhbF9oYW5kbGVzLmZyZWUoaGFuZGxlKTt9fTt2YXIgY291bnRfZW12YWxfaGFuZGxlcz0oKT0+e3ZhciBjb3VudD0wO2Zvcih2YXIgaT1lbXZhbF9oYW5kbGVzLnJlc2VydmVkO2k8ZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWQubGVuZ3RoOysraSl7aWYoZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWRbaV0hPT11bmRlZmluZWQpeysrY291bnQ7fX1yZXR1cm4gY291bnR9O3ZhciBpbml0X2VtdmFsPSgpPT57ZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWQucHVzaCh7dmFsdWU6dW5kZWZpbmVkfSx7dmFsdWU6bnVsbH0se3ZhbHVlOnRydWV9LHt2YWx1ZTpmYWxzZX0pO2VtdmFsX2hhbmRsZXMucmVzZXJ2ZWQ9ZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWQubGVuZ3RoO01vZHVsZVsiY291bnRfZW12YWxfaGFuZGxlcyJdPWNvdW50X2VtdmFsX2hhbmRsZXM7fTt2YXIgRW12YWw9e3RvVmFsdWU6aGFuZGxlPT57aWYoIWhhbmRsZSl7dGhyb3dCaW5kaW5nRXJyb3IoIkNhbm5vdCB1c2UgZGVsZXRlZCB2YWwuIGhhbmRsZSA9ICIraGFuZGxlKTt9cmV0dXJuIGVtdmFsX2hhbmRsZXMuZ2V0KGhhbmRsZSkudmFsdWV9LHRvSGFuZGxlOnZhbHVlPT57c3dpdGNoKHZhbHVlKXtjYXNlIHVuZGVmaW5lZDpyZXR1cm4gMTtjYXNlIG51bGw6cmV0dXJuIDI7Y2FzZSB0cnVlOnJldHVybiAzO2Nhc2UgZmFsc2U6cmV0dXJuIDQ7ZGVmYXVsdDp7cmV0dXJuIGVtdmFsX2hhbmRsZXMuYWxsb2NhdGUoe3JlZmNvdW50OjEsdmFsdWU6dmFsdWV9KX19fX07ZnVuY3Rpb24gc2ltcGxlUmVhZFZhbHVlRnJvbVBvaW50ZXIocG9pbnRlcil7cmV0dXJuIHRoaXNbImZyb21XaXJlVHlwZSJdKEhFQVAzMltwb2ludGVyPj4yXSl9dmFyIF9fZW1iaW5kX3JlZ2lzdGVyX2VtdmFsPShyYXdUeXBlLG5hbWUpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3JlZ2lzdGVyVHlwZShyYXdUeXBlLHtuYW1lOm5hbWUsImZyb21XaXJlVHlwZSI6aGFuZGxlPT57dmFyIHJ2PUVtdmFsLnRvVmFsdWUoaGFuZGxlKTtfX2VtdmFsX2RlY3JlZihoYW5kbGUpO3JldHVybiBydn0sInRvV2lyZVR5cGUiOihkZXN0cnVjdG9ycyx2YWx1ZSk9PkVtdmFsLnRvSGFuZGxlKHZhbHVlKSwiYXJnUGFja0FkdmFuY2UiOkdlbmVyaWNXaXJlVHlwZVNpemUsInJlYWRWYWx1ZUZyb21Qb2ludGVyIjpzaW1wbGVSZWFkVmFsdWVGcm9tUG9pbnRlcixkZXN0cnVjdG9yRnVuY3Rpb246bnVsbH0pO307dmFyIGZsb2F0UmVhZFZhbHVlRnJvbVBvaW50ZXI9KG5hbWUsd2lkdGgpPT57c3dpdGNoKHdpZHRoKXtjYXNlIDQ6cmV0dXJuIGZ1bmN0aW9uKHBvaW50ZXIpe3JldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShIRUFQRjMyW3BvaW50ZXI+PjJdKX07Y2FzZSA4OnJldHVybiBmdW5jdGlvbihwb2ludGVyKXtyZXR1cm4gdGhpc1siZnJvbVdpcmVUeXBlIl0oSEVBUEY2NFtwb2ludGVyPj4zXSl9O2RlZmF1bHQ6dGhyb3cgbmV3IFR5cGVFcnJvcihgaW52YWxpZCBmbG9hdCB3aWR0aCAoJHt3aWR0aH0pOiAke25hbWV9YCl9fTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfZmxvYXQ9KHJhd1R5cGUsbmFtZSxzaXplKT0+e25hbWU9cmVhZExhdGluMVN0cmluZyhuYW1lKTtyZWdpc3RlclR5cGUocmF3VHlwZSx7bmFtZTpuYW1lLCJmcm9tV2lyZVR5cGUiOnZhbHVlPT52YWx1ZSwidG9XaXJlVHlwZSI6KGRlc3RydWN0b3JzLHZhbHVlKT0+dmFsdWUsImFyZ1BhY2tBZHZhbmNlIjpHZW5lcmljV2lyZVR5cGVTaXplLCJyZWFkVmFsdWVGcm9tUG9pbnRlciI6ZmxvYXRSZWFkVmFsdWVGcm9tUG9pbnRlcihuYW1lLHNpemUpLGRlc3RydWN0b3JGdW5jdGlvbjpudWxsfSk7fTt2YXIgaW50ZWdlclJlYWRWYWx1ZUZyb21Qb2ludGVyPShuYW1lLHdpZHRoLHNpZ25lZCk9Pntzd2l0Y2god2lkdGgpe2Nhc2UgMTpyZXR1cm4gc2lnbmVkP3BvaW50ZXI9PkhFQVA4W3BvaW50ZXI+PjBdOnBvaW50ZXI9PkhFQVBVOFtwb2ludGVyPj4wXTtjYXNlIDI6cmV0dXJuIHNpZ25lZD9wb2ludGVyPT5IRUFQMTZbcG9pbnRlcj4+MV06cG9pbnRlcj0+SEVBUFUxNltwb2ludGVyPj4xXTtjYXNlIDQ6cmV0dXJuIHNpZ25lZD9wb2ludGVyPT5IRUFQMzJbcG9pbnRlcj4+Ml06cG9pbnRlcj0+SEVBUFUzMltwb2ludGVyPj4yXTtkZWZhdWx0OnRocm93IG5ldyBUeXBlRXJyb3IoYGludmFsaWQgaW50ZWdlciB3aWR0aCAoJHt3aWR0aH0pOiAke25hbWV9YCl9fTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfaW50ZWdlcj0ocHJpbWl0aXZlVHlwZSxuYW1lLHNpemUsbWluUmFuZ2UsbWF4UmFuZ2UpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3ZhciBmcm9tV2lyZVR5cGU9dmFsdWU9PnZhbHVlO2lmKG1pblJhbmdlPT09MCl7dmFyIGJpdHNoaWZ0PTMyLTgqc2l6ZTtmcm9tV2lyZVR5cGU9dmFsdWU9PnZhbHVlPDxiaXRzaGlmdD4+PmJpdHNoaWZ0O312YXIgaXNVbnNpZ25lZFR5cGU9bmFtZS5pbmNsdWRlcygidW5zaWduZWQiKTt2YXIgY2hlY2tBc3NlcnRpb25zPSh2YWx1ZSx0b1R5cGVOYW1lKT0+e307dmFyIHRvV2lyZVR5cGU7aWYoaXNVbnNpZ25lZFR5cGUpe3RvV2lyZVR5cGU9ZnVuY3Rpb24oZGVzdHJ1Y3RvcnMsdmFsdWUpe2NoZWNrQXNzZXJ0aW9ucyh2YWx1ZSx0aGlzLm5hbWUpO3JldHVybiB2YWx1ZT4+PjB9O31lbHNlIHt0b1dpcmVUeXBlPWZ1bmN0aW9uKGRlc3RydWN0b3JzLHZhbHVlKXtjaGVja0Fzc2VydGlvbnModmFsdWUsdGhpcy5uYW1lKTtyZXR1cm4gdmFsdWV9O31yZWdpc3RlclR5cGUocHJpbWl0aXZlVHlwZSx7bmFtZTpuYW1lLCJmcm9tV2lyZVR5cGUiOmZyb21XaXJlVHlwZSwidG9XaXJlVHlwZSI6dG9XaXJlVHlwZSwiYXJnUGFja0FkdmFuY2UiOkdlbmVyaWNXaXJlVHlwZVNpemUsInJlYWRWYWx1ZUZyb21Qb2ludGVyIjppbnRlZ2VyUmVhZFZhbHVlRnJvbVBvaW50ZXIobmFtZSxzaXplLG1pblJhbmdlIT09MCksZGVzdHJ1Y3RvckZ1bmN0aW9uOm51bGx9KTt9O3ZhciBfX2VtYmluZF9yZWdpc3Rlcl9tZW1vcnlfdmlldz0ocmF3VHlwZSxkYXRhVHlwZUluZGV4LG5hbWUpPT57dmFyIHR5cGVNYXBwaW5nPVtJbnQ4QXJyYXksVWludDhBcnJheSxJbnQxNkFycmF5LFVpbnQxNkFycmF5LEludDMyQXJyYXksVWludDMyQXJyYXksRmxvYXQzMkFycmF5LEZsb2F0NjRBcnJheV07dmFyIFRBPXR5cGVNYXBwaW5nW2RhdGFUeXBlSW5kZXhdO2Z1bmN0aW9uIGRlY29kZU1lbW9yeVZpZXcoaGFuZGxlKXt2YXIgc2l6ZT1IRUFQVTMyW2hhbmRsZT4+Ml07dmFyIGRhdGE9SEVBUFUzMltoYW5kbGUrND4+Ml07cmV0dXJuIG5ldyBUQShIRUFQOC5idWZmZXIsZGF0YSxzaXplKX1uYW1lPXJlYWRMYXRpbjFTdHJpbmcobmFtZSk7cmVnaXN0ZXJUeXBlKHJhd1R5cGUse25hbWU6bmFtZSwiZnJvbVdpcmVUeXBlIjpkZWNvZGVNZW1vcnlWaWV3LCJhcmdQYWNrQWR2YW5jZSI6R2VuZXJpY1dpcmVUeXBlU2l6ZSwicmVhZFZhbHVlRnJvbVBvaW50ZXIiOmRlY29kZU1lbW9yeVZpZXd9LHtpZ25vcmVEdXBsaWNhdGVSZWdpc3RyYXRpb25zOnRydWV9KTt9O2Z1bmN0aW9uIHJlYWRQb2ludGVyKHBvaW50ZXIpe3JldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShIRUFQVTMyW3BvaW50ZXI+PjJdKX12YXIgc3RyaW5nVG9VVEY4QXJyYXk9KHN0cixoZWFwLG91dElkeCxtYXhCeXRlc1RvV3JpdGUpPT57aWYoIShtYXhCeXRlc1RvV3JpdGU+MCkpcmV0dXJuIDA7dmFyIHN0YXJ0SWR4PW91dElkeDt2YXIgZW5kSWR4PW91dElkeCttYXhCeXRlc1RvV3JpdGUtMTtmb3IodmFyIGk9MDtpPHN0ci5sZW5ndGg7KytpKXt2YXIgdT1zdHIuY2hhckNvZGVBdChpKTtpZih1Pj01NTI5NiYmdTw9NTczNDMpe3ZhciB1MT1zdHIuY2hhckNvZGVBdCgrK2kpO3U9NjU1MzYrKCh1JjEwMjMpPDwxMCl8dTEmMTAyMzt9aWYodTw9MTI3KXtpZihvdXRJZHg+PWVuZElkeClicmVhaztoZWFwW291dElkeCsrXT11O31lbHNlIGlmKHU8PTIwNDcpe2lmKG91dElkeCsxPj1lbmRJZHgpYnJlYWs7aGVhcFtvdXRJZHgrK109MTkyfHU+PjY7aGVhcFtvdXRJZHgrK109MTI4fHUmNjM7fWVsc2UgaWYodTw9NjU1MzUpe2lmKG91dElkeCsyPj1lbmRJZHgpYnJlYWs7aGVhcFtvdXRJZHgrK109MjI0fHU+PjEyO2hlYXBbb3V0SWR4KytdPTEyOHx1Pj42JjYzO2hlYXBbb3V0SWR4KytdPTEyOHx1JjYzO31lbHNlIHtpZihvdXRJZHgrMz49ZW5kSWR4KWJyZWFrO2hlYXBbb3V0SWR4KytdPTI0MHx1Pj4xODtoZWFwW291dElkeCsrXT0xMjh8dT4+MTImNjM7aGVhcFtvdXRJZHgrK109MTI4fHU+PjYmNjM7aGVhcFtvdXRJZHgrK109MTI4fHUmNjM7fX1oZWFwW291dElkeF09MDtyZXR1cm4gb3V0SWR4LXN0YXJ0SWR4fTt2YXIgc3RyaW5nVG9VVEY4PShzdHIsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk9PnN0cmluZ1RvVVRGOEFycmF5KHN0cixIRUFQVTgsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk7dmFyIGxlbmd0aEJ5dGVzVVRGOD1zdHI9Pnt2YXIgbGVuPTA7Zm9yKHZhciBpPTA7aTxzdHIubGVuZ3RoOysraSl7dmFyIGM9c3RyLmNoYXJDb2RlQXQoaSk7aWYoYzw9MTI3KXtsZW4rKzt9ZWxzZSBpZihjPD0yMDQ3KXtsZW4rPTI7fWVsc2UgaWYoYz49NTUyOTYmJmM8PTU3MzQzKXtsZW4rPTQ7KytpO31lbHNlIHtsZW4rPTM7fX1yZXR1cm4gbGVufTt2YXIgVVRGOERlY29kZXI9dHlwZW9mIFRleHREZWNvZGVyIT0idW5kZWZpbmVkIj9uZXcgVGV4dERlY29kZXIoInV0ZjgiKTp1bmRlZmluZWQ7dmFyIFVURjhBcnJheVRvU3RyaW5nPShoZWFwT3JBcnJheSxpZHgsbWF4Qnl0ZXNUb1JlYWQpPT57dmFyIGVuZElkeD1pZHgrbWF4Qnl0ZXNUb1JlYWQ7dmFyIGVuZFB0cj1pZHg7d2hpbGUoaGVhcE9yQXJyYXlbZW5kUHRyXSYmIShlbmRQdHI+PWVuZElkeCkpKytlbmRQdHI7aWYoZW5kUHRyLWlkeD4xNiYmaGVhcE9yQXJyYXkuYnVmZmVyJiZVVEY4RGVjb2Rlcil7cmV0dXJuIFVURjhEZWNvZGVyLmRlY29kZShoZWFwT3JBcnJheS5zdWJhcnJheShpZHgsZW5kUHRyKSl9dmFyIHN0cj0iIjt3aGlsZShpZHg8ZW5kUHRyKXt2YXIgdTA9aGVhcE9yQXJyYXlbaWR4KytdO2lmKCEodTAmMTI4KSl7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHUwKTtjb250aW51ZX12YXIgdTE9aGVhcE9yQXJyYXlbaWR4KytdJjYzO2lmKCh1MCYyMjQpPT0xOTIpe3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZSgodTAmMzEpPDw2fHUxKTtjb250aW51ZX12YXIgdTI9aGVhcE9yQXJyYXlbaWR4KytdJjYzO2lmKCh1MCYyNDApPT0yMjQpe3UwPSh1MCYxNSk8PDEyfHUxPDw2fHUyO31lbHNlIHt1MD0odTAmNyk8PDE4fHUxPDwxMnx1Mjw8NnxoZWFwT3JBcnJheVtpZHgrK10mNjM7fWlmKHUwPDY1NTM2KXtzdHIrPVN0cmluZy5mcm9tQ2hhckNvZGUodTApO31lbHNlIHt2YXIgY2g9dTAtNjU1MzY7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGNoPj4xMCw1NjMyMHxjaCYxMDIzKTt9fXJldHVybiBzdHJ9O3ZhciBVVEY4VG9TdHJpbmc9KHB0cixtYXhCeXRlc1RvUmVhZCk9PnB0cj9VVEY4QXJyYXlUb1N0cmluZyhIRUFQVTgscHRyLG1heEJ5dGVzVG9SZWFkKToiIjt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfc3RkX3N0cmluZz0ocmF3VHlwZSxuYW1lKT0+e25hbWU9cmVhZExhdGluMVN0cmluZyhuYW1lKTt2YXIgc3RkU3RyaW5nSXNVVEY4PW5hbWU9PT0ic3RkOjpzdHJpbmciO3JlZ2lzdGVyVHlwZShyYXdUeXBlLHtuYW1lOm5hbWUsImZyb21XaXJlVHlwZSIodmFsdWUpe3ZhciBsZW5ndGg9SEVBUFUzMlt2YWx1ZT4+Ml07dmFyIHBheWxvYWQ9dmFsdWUrNDt2YXIgc3RyO2lmKHN0ZFN0cmluZ0lzVVRGOCl7dmFyIGRlY29kZVN0YXJ0UHRyPXBheWxvYWQ7Zm9yKHZhciBpPTA7aTw9bGVuZ3RoOysraSl7dmFyIGN1cnJlbnRCeXRlUHRyPXBheWxvYWQraTtpZihpPT1sZW5ndGh8fEhFQVBVOFtjdXJyZW50Qnl0ZVB0cl09PTApe3ZhciBtYXhSZWFkPWN1cnJlbnRCeXRlUHRyLWRlY29kZVN0YXJ0UHRyO3ZhciBzdHJpbmdTZWdtZW50PVVURjhUb1N0cmluZyhkZWNvZGVTdGFydFB0cixtYXhSZWFkKTtpZihzdHI9PT11bmRlZmluZWQpe3N0cj1zdHJpbmdTZWdtZW50O31lbHNlIHtzdHIrPVN0cmluZy5mcm9tQ2hhckNvZGUoMCk7c3RyKz1zdHJpbmdTZWdtZW50O31kZWNvZGVTdGFydFB0cj1jdXJyZW50Qnl0ZVB0cisxO319fWVsc2Uge3ZhciBhPW5ldyBBcnJheShsZW5ndGgpO2Zvcih2YXIgaT0wO2k8bGVuZ3RoOysraSl7YVtpXT1TdHJpbmcuZnJvbUNoYXJDb2RlKEhFQVBVOFtwYXlsb2FkK2ldKTt9c3RyPWEuam9pbigiIik7fV9mcmVlKHZhbHVlKTtyZXR1cm4gc3RyfSwidG9XaXJlVHlwZSIoZGVzdHJ1Y3RvcnMsdmFsdWUpe2lmKHZhbHVlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpe3ZhbHVlPW5ldyBVaW50OEFycmF5KHZhbHVlKTt9dmFyIGxlbmd0aDt2YXIgdmFsdWVJc09mVHlwZVN0cmluZz10eXBlb2YgdmFsdWU9PSJzdHJpbmciO2lmKCEodmFsdWVJc09mVHlwZVN0cmluZ3x8dmFsdWUgaW5zdGFuY2VvZiBVaW50OEFycmF5fHx2YWx1ZSBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5fHx2YWx1ZSBpbnN0YW5jZW9mIEludDhBcnJheSkpe3Rocm93QmluZGluZ0Vycm9yKCJDYW5ub3QgcGFzcyBub24tc3RyaW5nIHRvIHN0ZDo6c3RyaW5nIik7fWlmKHN0ZFN0cmluZ0lzVVRGOCYmdmFsdWVJc09mVHlwZVN0cmluZyl7bGVuZ3RoPWxlbmd0aEJ5dGVzVVRGOCh2YWx1ZSk7fWVsc2Uge2xlbmd0aD12YWx1ZS5sZW5ndGg7fXZhciBiYXNlPV9tYWxsb2MoNCtsZW5ndGgrMSk7dmFyIHB0cj1iYXNlKzQ7SEVBUFUzMltiYXNlPj4yXT1sZW5ndGg7aWYoc3RkU3RyaW5nSXNVVEY4JiZ2YWx1ZUlzT2ZUeXBlU3RyaW5nKXtzdHJpbmdUb1VURjgodmFsdWUscHRyLGxlbmd0aCsxKTt9ZWxzZSB7aWYodmFsdWVJc09mVHlwZVN0cmluZyl7Zm9yKHZhciBpPTA7aTxsZW5ndGg7KytpKXt2YXIgY2hhckNvZGU9dmFsdWUuY2hhckNvZGVBdChpKTtpZihjaGFyQ29kZT4yNTUpe19mcmVlKHB0cik7dGhyb3dCaW5kaW5nRXJyb3IoIlN0cmluZyBoYXMgVVRGLTE2IGNvZGUgdW5pdHMgdGhhdCBkbyBub3QgZml0IGluIDggYml0cyIpO31IRUFQVThbcHRyK2ldPWNoYXJDb2RlO319ZWxzZSB7Zm9yKHZhciBpPTA7aTxsZW5ndGg7KytpKXtIRUFQVThbcHRyK2ldPXZhbHVlW2ldO319fWlmKGRlc3RydWN0b3JzIT09bnVsbCl7ZGVzdHJ1Y3RvcnMucHVzaChfZnJlZSxiYXNlKTt9cmV0dXJuIGJhc2V9LCJhcmdQYWNrQWR2YW5jZSI6R2VuZXJpY1dpcmVUeXBlU2l6ZSwicmVhZFZhbHVlRnJvbVBvaW50ZXIiOnJlYWRQb2ludGVyLGRlc3RydWN0b3JGdW5jdGlvbihwdHIpe19mcmVlKHB0cik7fX0pO307dmFyIFVURjE2RGVjb2Rlcj10eXBlb2YgVGV4dERlY29kZXIhPSJ1bmRlZmluZWQiP25ldyBUZXh0RGVjb2RlcigidXRmLTE2bGUiKTp1bmRlZmluZWQ7dmFyIFVURjE2VG9TdHJpbmc9KHB0cixtYXhCeXRlc1RvUmVhZCk9Pnt2YXIgZW5kUHRyPXB0cjt2YXIgaWR4PWVuZFB0cj4+MTt2YXIgbWF4SWR4PWlkeCttYXhCeXRlc1RvUmVhZC8yO3doaWxlKCEoaWR4Pj1tYXhJZHgpJiZIRUFQVTE2W2lkeF0pKytpZHg7ZW5kUHRyPWlkeDw8MTtpZihlbmRQdHItcHRyPjMyJiZVVEYxNkRlY29kZXIpcmV0dXJuIFVURjE2RGVjb2Rlci5kZWNvZGUoSEVBUFU4LnN1YmFycmF5KHB0cixlbmRQdHIpKTt2YXIgc3RyPSIiO2Zvcih2YXIgaT0wOyEoaT49bWF4Qnl0ZXNUb1JlYWQvMik7KytpKXt2YXIgY29kZVVuaXQ9SEVBUDE2W3B0citpKjI+PjFdO2lmKGNvZGVVbml0PT0wKWJyZWFrO3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZShjb2RlVW5pdCk7fXJldHVybiBzdHJ9O3ZhciBzdHJpbmdUb1VURjE2PShzdHIsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk9PntpZihtYXhCeXRlc1RvV3JpdGU9PT11bmRlZmluZWQpe21heEJ5dGVzVG9Xcml0ZT0yMTQ3NDgzNjQ3O31pZihtYXhCeXRlc1RvV3JpdGU8MilyZXR1cm4gMDttYXhCeXRlc1RvV3JpdGUtPTI7dmFyIHN0YXJ0UHRyPW91dFB0cjt2YXIgbnVtQ2hhcnNUb1dyaXRlPW1heEJ5dGVzVG9Xcml0ZTxzdHIubGVuZ3RoKjI/bWF4Qnl0ZXNUb1dyaXRlLzI6c3RyLmxlbmd0aDtmb3IodmFyIGk9MDtpPG51bUNoYXJzVG9Xcml0ZTsrK2kpe3ZhciBjb2RlVW5pdD1zdHIuY2hhckNvZGVBdChpKTtIRUFQMTZbb3V0UHRyPj4xXT1jb2RlVW5pdDtvdXRQdHIrPTI7fUhFQVAxNltvdXRQdHI+PjFdPTA7cmV0dXJuIG91dFB0ci1zdGFydFB0cn07dmFyIGxlbmd0aEJ5dGVzVVRGMTY9c3RyPT5zdHIubGVuZ3RoKjI7dmFyIFVURjMyVG9TdHJpbmc9KHB0cixtYXhCeXRlc1RvUmVhZCk9Pnt2YXIgaT0wO3ZhciBzdHI9IiI7d2hpbGUoIShpPj1tYXhCeXRlc1RvUmVhZC80KSl7dmFyIHV0ZjMyPUhFQVAzMltwdHIraSo0Pj4yXTtpZih1dGYzMj09MClicmVhazsrK2k7aWYodXRmMzI+PTY1NTM2KXt2YXIgY2g9dXRmMzItNjU1MzY7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGNoPj4xMCw1NjMyMHxjaCYxMDIzKTt9ZWxzZSB7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHV0ZjMyKTt9fXJldHVybiBzdHJ9O3ZhciBzdHJpbmdUb1VURjMyPShzdHIsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk9PntpZihtYXhCeXRlc1RvV3JpdGU9PT11bmRlZmluZWQpe21heEJ5dGVzVG9Xcml0ZT0yMTQ3NDgzNjQ3O31pZihtYXhCeXRlc1RvV3JpdGU8NClyZXR1cm4gMDt2YXIgc3RhcnRQdHI9b3V0UHRyO3ZhciBlbmRQdHI9c3RhcnRQdHIrbWF4Qnl0ZXNUb1dyaXRlLTQ7Zm9yKHZhciBpPTA7aTxzdHIubGVuZ3RoOysraSl7dmFyIGNvZGVVbml0PXN0ci5jaGFyQ29kZUF0KGkpO2lmKGNvZGVVbml0Pj01NTI5NiYmY29kZVVuaXQ8PTU3MzQzKXt2YXIgdHJhaWxTdXJyb2dhdGU9c3RyLmNoYXJDb2RlQXQoKytpKTtjb2RlVW5pdD02NTUzNisoKGNvZGVVbml0JjEwMjMpPDwxMCl8dHJhaWxTdXJyb2dhdGUmMTAyMzt9SEVBUDMyW291dFB0cj4+Ml09Y29kZVVuaXQ7b3V0UHRyKz00O2lmKG91dFB0cis0PmVuZFB0cilicmVha31IRUFQMzJbb3V0UHRyPj4yXT0wO3JldHVybiBvdXRQdHItc3RhcnRQdHJ9O3ZhciBsZW5ndGhCeXRlc1VURjMyPXN0cj0+e3ZhciBsZW49MDtmb3IodmFyIGk9MDtpPHN0ci5sZW5ndGg7KytpKXt2YXIgY29kZVVuaXQ9c3RyLmNoYXJDb2RlQXQoaSk7aWYoY29kZVVuaXQ+PTU1Mjk2JiZjb2RlVW5pdDw9NTczNDMpKytpO2xlbis9NDt9cmV0dXJuIGxlbn07dmFyIF9fZW1iaW5kX3JlZ2lzdGVyX3N0ZF93c3RyaW5nPShyYXdUeXBlLGNoYXJTaXplLG5hbWUpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3ZhciBkZWNvZGVTdHJpbmcsZW5jb2RlU3RyaW5nLGdldEhlYXAsbGVuZ3RoQnl0ZXNVVEYsc2hpZnQ7aWYoY2hhclNpemU9PT0yKXtkZWNvZGVTdHJpbmc9VVRGMTZUb1N0cmluZztlbmNvZGVTdHJpbmc9c3RyaW5nVG9VVEYxNjtsZW5ndGhCeXRlc1VURj1sZW5ndGhCeXRlc1VURjE2O2dldEhlYXA9KCk9PkhFQVBVMTY7c2hpZnQ9MTt9ZWxzZSBpZihjaGFyU2l6ZT09PTQpe2RlY29kZVN0cmluZz1VVEYzMlRvU3RyaW5nO2VuY29kZVN0cmluZz1zdHJpbmdUb1VURjMyO2xlbmd0aEJ5dGVzVVRGPWxlbmd0aEJ5dGVzVVRGMzI7Z2V0SGVhcD0oKT0+SEVBUFUzMjtzaGlmdD0yO31yZWdpc3RlclR5cGUocmF3VHlwZSx7bmFtZTpuYW1lLCJmcm9tV2lyZVR5cGUiOnZhbHVlPT57dmFyIGxlbmd0aD1IRUFQVTMyW3ZhbHVlPj4yXTt2YXIgSEVBUD1nZXRIZWFwKCk7dmFyIHN0cjt2YXIgZGVjb2RlU3RhcnRQdHI9dmFsdWUrNDtmb3IodmFyIGk9MDtpPD1sZW5ndGg7KytpKXt2YXIgY3VycmVudEJ5dGVQdHI9dmFsdWUrNCtpKmNoYXJTaXplO2lmKGk9PWxlbmd0aHx8SEVBUFtjdXJyZW50Qnl0ZVB0cj4+c2hpZnRdPT0wKXt2YXIgbWF4UmVhZEJ5dGVzPWN1cnJlbnRCeXRlUHRyLWRlY29kZVN0YXJ0UHRyO3ZhciBzdHJpbmdTZWdtZW50PWRlY29kZVN0cmluZyhkZWNvZGVTdGFydFB0cixtYXhSZWFkQnl0ZXMpO2lmKHN0cj09PXVuZGVmaW5lZCl7c3RyPXN0cmluZ1NlZ21lbnQ7fWVsc2Uge3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZSgwKTtzdHIrPXN0cmluZ1NlZ21lbnQ7fWRlY29kZVN0YXJ0UHRyPWN1cnJlbnRCeXRlUHRyK2NoYXJTaXplO319X2ZyZWUodmFsdWUpO3JldHVybiBzdHJ9LCJ0b1dpcmVUeXBlIjooZGVzdHJ1Y3RvcnMsdmFsdWUpPT57aWYoISh0eXBlb2YgdmFsdWU9PSJzdHJpbmciKSl7dGhyb3dCaW5kaW5nRXJyb3IoYENhbm5vdCBwYXNzIG5vbi1zdHJpbmcgdG8gQysrIHN0cmluZyB0eXBlICR7bmFtZX1gKTt9dmFyIGxlbmd0aD1sZW5ndGhCeXRlc1VURih2YWx1ZSk7dmFyIHB0cj1fbWFsbG9jKDQrbGVuZ3RoK2NoYXJTaXplKTtIRUFQVTMyW3B0cj4+Ml09bGVuZ3RoPj5zaGlmdDtlbmNvZGVTdHJpbmcodmFsdWUscHRyKzQsbGVuZ3RoK2NoYXJTaXplKTtpZihkZXN0cnVjdG9ycyE9PW51bGwpe2Rlc3RydWN0b3JzLnB1c2goX2ZyZWUscHRyKTt9cmV0dXJuIHB0cn0sImFyZ1BhY2tBZHZhbmNlIjpHZW5lcmljV2lyZVR5cGVTaXplLCJyZWFkVmFsdWVGcm9tUG9pbnRlciI6c2ltcGxlUmVhZFZhbHVlRnJvbVBvaW50ZXIsZGVzdHJ1Y3RvckZ1bmN0aW9uKHB0cil7X2ZyZWUocHRyKTt9fSk7fTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfdm9pZD0ocmF3VHlwZSxuYW1lKT0+e25hbWU9cmVhZExhdGluMVN0cmluZyhuYW1lKTtyZWdpc3RlclR5cGUocmF3VHlwZSx7aXNWb2lkOnRydWUsbmFtZTpuYW1lLCJhcmdQYWNrQWR2YW5jZSI6MCwiZnJvbVdpcmVUeXBlIjooKT0+dW5kZWZpbmVkLCJ0b1dpcmVUeXBlIjooZGVzdHJ1Y3RvcnMsbyk9PnVuZGVmaW5lZH0pO307dmFyIGdldEhlYXBNYXg9KCk9PjIxNDc0ODM2NDg7dmFyIGdyb3dNZW1vcnk9c2l6ZT0+e3ZhciBiPXdhc21NZW1vcnkuYnVmZmVyO3ZhciBwYWdlcz0oc2l6ZS1iLmJ5dGVMZW5ndGgrNjU1MzUpLzY1NTM2O3RyeXt3YXNtTWVtb3J5Lmdyb3cocGFnZXMpO3VwZGF0ZU1lbW9yeVZpZXdzKCk7cmV0dXJuIDF9Y2F0Y2goZSl7fX07dmFyIF9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwPXJlcXVlc3RlZFNpemU9Pnt2YXIgb2xkU2l6ZT1IRUFQVTgubGVuZ3RoO3JlcXVlc3RlZFNpemU+Pj49MDt2YXIgbWF4SGVhcFNpemU9Z2V0SGVhcE1heCgpO2lmKHJlcXVlc3RlZFNpemU+bWF4SGVhcFNpemUpe3JldHVybiBmYWxzZX12YXIgYWxpZ25VcD0oeCxtdWx0aXBsZSk9PngrKG11bHRpcGxlLXglbXVsdGlwbGUpJW11bHRpcGxlO2Zvcih2YXIgY3V0RG93bj0xO2N1dERvd248PTQ7Y3V0RG93bio9Mil7dmFyIG92ZXJHcm93bkhlYXBTaXplPW9sZFNpemUqKDErLjIvY3V0RG93bik7b3Zlckdyb3duSGVhcFNpemU9TWF0aC5taW4ob3Zlckdyb3duSGVhcFNpemUscmVxdWVzdGVkU2l6ZSsxMDA2NjMyOTYpO3ZhciBuZXdTaXplPU1hdGgubWluKG1heEhlYXBTaXplLGFsaWduVXAoTWF0aC5tYXgocmVxdWVzdGVkU2l6ZSxvdmVyR3Jvd25IZWFwU2l6ZSksNjU1MzYpKTt2YXIgcmVwbGFjZW1lbnQ9Z3Jvd01lbW9yeShuZXdTaXplKTtpZihyZXBsYWNlbWVudCl7cmV0dXJuIHRydWV9fXJldHVybiBmYWxzZX07ZW1iaW5kX2luaXRfY2hhckNvZGVzKCk7QmluZGluZ0Vycm9yPU1vZHVsZVsiQmluZGluZ0Vycm9yIl09Y2xhc3MgQmluZGluZ0Vycm9yIGV4dGVuZHMgRXJyb3J7Y29uc3RydWN0b3IobWVzc2FnZSl7c3VwZXIobWVzc2FnZSk7dGhpcy5uYW1lPSJCaW5kaW5nRXJyb3IiO319O01vZHVsZVsiSW50ZXJuYWxFcnJvciJdPWNsYXNzIEludGVybmFsRXJyb3IgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3RvcihtZXNzYWdlKXtzdXBlcihtZXNzYWdlKTt0aGlzLm5hbWU9IkludGVybmFsRXJyb3IiO319O2hhbmRsZUFsbG9jYXRvckluaXQoKTtpbml0X2VtdmFsKCk7dmFyIHdhc21JbXBvcnRzPXtmOl9fZW1iaW5kX3JlZ2lzdGVyX2JpZ2ludCxpOl9fZW1iaW5kX3JlZ2lzdGVyX2Jvb2wsaDpfX2VtYmluZF9yZWdpc3Rlcl9lbXZhbCxlOl9fZW1iaW5kX3JlZ2lzdGVyX2Zsb2F0LGI6X19lbWJpbmRfcmVnaXN0ZXJfaW50ZWdlcixhOl9fZW1iaW5kX3JlZ2lzdGVyX21lbW9yeV92aWV3LGQ6X19lbWJpbmRfcmVnaXN0ZXJfc3RkX3N0cmluZyxjOl9fZW1iaW5kX3JlZ2lzdGVyX3N0ZF93c3RyaW5nLGo6X19lbWJpbmRfcmVnaXN0ZXJfdm9pZCxnOl9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwfTt2YXIgd2FzbUV4cG9ydHM9Y3JlYXRlV2FzbSgpO01vZHVsZVsiX3NvcnQiXT0oYTAsYTEsYTIsYTMsYTQsYTUsYTYsYTcsYTgpPT4oTW9kdWxlWyJfc29ydCJdPXdhc21FeHBvcnRzWyJtIl0pKGEwLGExLGEyLGEzLGE0LGE1LGE2LGE3LGE4KTtNb2R1bGVbIl9fZW1iaW5kX2luaXRpYWxpemVfYmluZGluZ3MiXT0oKT0+KE1vZHVsZVsiX19lbWJpbmRfaW5pdGlhbGl6ZV9iaW5kaW5ncyJdPXdhc21FeHBvcnRzWyJuIl0pKCk7dmFyIF9tYWxsb2M9TW9kdWxlWyJfbWFsbG9jIl09YTA9PihfbWFsbG9jPU1vZHVsZVsiX21hbGxvYyJdPXdhc21FeHBvcnRzWyJwIl0pKGEwKTt2YXIgX2ZyZWU9TW9kdWxlWyJfZnJlZSJdPWEwPT4oX2ZyZWU9TW9kdWxlWyJfZnJlZSJdPXdhc21FeHBvcnRzWyJxIl0pKGEwKTtmdW5jdGlvbiBpbnRBcnJheUZyb21CYXNlNjQocyl7dmFyIGRlY29kZWQ9YXRvYihzKTt2YXIgYnl0ZXM9bmV3IFVpbnQ4QXJyYXkoZGVjb2RlZC5sZW5ndGgpO2Zvcih2YXIgaT0wO2k8ZGVjb2RlZC5sZW5ndGg7KytpKXtieXRlc1tpXT1kZWNvZGVkLmNoYXJDb2RlQXQoaSk7fXJldHVybiBieXRlc31mdW5jdGlvbiB0cnlQYXJzZUFzRGF0YVVSSShmaWxlbmFtZSl7aWYoIWlzRGF0YVVSSShmaWxlbmFtZSkpe3JldHVybn1yZXR1cm4gaW50QXJyYXlGcm9tQmFzZTY0KGZpbGVuYW1lLnNsaWNlKGRhdGFVUklQcmVmaXgubGVuZ3RoKSl9dmFyIGNhbGxlZFJ1bjtkZXBlbmRlbmNpZXNGdWxmaWxsZWQ9ZnVuY3Rpb24gcnVuQ2FsbGVyKCl7aWYoIWNhbGxlZFJ1bilydW4oKTtpZighY2FsbGVkUnVuKWRlcGVuZGVuY2llc0Z1bGZpbGxlZD1ydW5DYWxsZXI7fTtmdW5jdGlvbiBydW4oKXtpZihydW5EZXBlbmRlbmNpZXM+MCl7cmV0dXJufXByZVJ1bigpO2lmKHJ1bkRlcGVuZGVuY2llcz4wKXtyZXR1cm59ZnVuY3Rpb24gZG9SdW4oKXtpZihjYWxsZWRSdW4pcmV0dXJuO2NhbGxlZFJ1bj10cnVlO01vZHVsZVsiY2FsbGVkUnVuIl09dHJ1ZTtpZihBQk9SVClyZXR1cm47aW5pdFJ1bnRpbWUoKTtyZWFkeVByb21pc2VSZXNvbHZlKE1vZHVsZSk7aWYoTW9kdWxlWyJvblJ1bnRpbWVJbml0aWFsaXplZCJdKU1vZHVsZVsib25SdW50aW1lSW5pdGlhbGl6ZWQiXSgpO3Bvc3RSdW4oKTt9aWYoTW9kdWxlWyJzZXRTdGF0dXMiXSl7TW9kdWxlWyJzZXRTdGF0dXMiXSgiUnVubmluZy4uLiIpO3NldFRpbWVvdXQoZnVuY3Rpb24oKXtzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7TW9kdWxlWyJzZXRTdGF0dXMiXSgiIik7fSwxKTtkb1J1bigpO30sMSk7fWVsc2Uge2RvUnVuKCk7fX1pZihNb2R1bGVbInByZUluaXQiXSl7aWYodHlwZW9mIE1vZHVsZVsicHJlSW5pdCJdPT0iZnVuY3Rpb24iKU1vZHVsZVsicHJlSW5pdCJdPVtNb2R1bGVbInByZUluaXQiXV07d2hpbGUoTW9kdWxlWyJwcmVJbml0Il0ubGVuZ3RoPjApe01vZHVsZVsicHJlSW5pdCJdLnBvcCgpKCk7fX1ydW4oKTsKCgogICAgcmV0dXJuIG1vZHVsZUFyZy5yZWFkeQogIH0KCiAgKTsKICB9KSgpOwoKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueQogIGxldCB3YXNtTW9kdWxlOwogIGFzeW5jIGZ1bmN0aW9uIGluaXRXYXNtKCkgewogICAgICB3YXNtTW9kdWxlID0gYXdhaXQgbG9hZFdhc20oKTsKICB9CiAgbGV0IHNvcnREYXRhOwogIGxldCB2aWV3UHJvalB0cjsKICBsZXQgdHJhbnNmb3Jtc1B0cjsKICBsZXQgdHJhbnNmb3JtSW5kaWNlc1B0cjsKICBsZXQgcG9zaXRpb25zUHRyOwogIGxldCBkZXB0aEJ1ZmZlclB0cjsKICBsZXQgZGVwdGhJbmRleFB0cjsKICBsZXQgc3RhcnRzUHRyOwogIGxldCBjb3VudHNQdHI7CiAgbGV0IGFsbG9jYXRlZFZlcnRleENvdW50ID0gMDsKICBsZXQgYWxsb2NhdGVkVHJhbnNmb3JtQ291bnQgPSAwOwogIGxldCB2aWV3UHJvaiA9IG5ldyBGbG9hdDMyQXJyYXkoMTYpOwogIGxldCBsb2NrID0gZmFsc2U7CiAgbGV0IGFsbG9jYXRpb25QZW5kaW5nID0gZmFsc2U7CiAgbGV0IHNvcnRpbmcgPSBmYWxzZTsKICBjb25zdCBhbGxvY2F0ZUJ1ZmZlcnMgPSBhc3luYyAoKSA9PiB7CiAgICAgIGlmIChsb2NrKSB7CiAgICAgICAgICBhbGxvY2F0aW9uUGVuZGluZyA9IHRydWU7CiAgICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgbG9jayA9IHRydWU7CiAgICAgIGFsbG9jYXRpb25QZW5kaW5nID0gZmFsc2U7CiAgICAgIGlmICghd2FzbU1vZHVsZSkKICAgICAgICAgIGF3YWl0IGluaXRXYXNtKCk7CiAgICAgIGNvbnN0IHRhcmdldEFsbG9jYXRlZFZlcnRleENvdW50ID0gTWF0aC5wb3coMiwgTWF0aC5jZWlsKE1hdGgubG9nMihzb3J0RGF0YS52ZXJ0ZXhDb3VudCkpKTsKICAgICAgaWYgKGFsbG9jYXRlZFZlcnRleENvdW50IDwgdGFyZ2V0QWxsb2NhdGVkVmVydGV4Q291bnQpIHsKICAgICAgICAgIGlmIChhbGxvY2F0ZWRWZXJ0ZXhDb3VudCA+IDApIHsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHZpZXdQcm9qUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHRyYW5zZm9ybUluZGljZXNQdHIpOwogICAgICAgICAgICAgIHdhc21Nb2R1bGUuX2ZyZWUocG9zaXRpb25zUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKGRlcHRoQnVmZmVyUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKGRlcHRoSW5kZXhQdHIpOwogICAgICAgICAgICAgIHdhc21Nb2R1bGUuX2ZyZWUoc3RhcnRzUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKGNvdW50c1B0cik7CiAgICAgICAgICB9CiAgICAgICAgICBhbGxvY2F0ZWRWZXJ0ZXhDb3VudCA9IHRhcmdldEFsbG9jYXRlZFZlcnRleENvdW50OwogICAgICAgICAgdmlld1Byb2pQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoMTYgKiA0KTsKICAgICAgICAgIHRyYW5zZm9ybUluZGljZXNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoYWxsb2NhdGVkVmVydGV4Q291bnQgKiA0KTsKICAgICAgICAgIHBvc2l0aW9uc1B0ciA9IHdhc21Nb2R1bGUuX21hbGxvYygzICogYWxsb2NhdGVkVmVydGV4Q291bnQgKiA0KTsKICAgICAgICAgIGRlcHRoQnVmZmVyUHRyID0gd2FzbU1vZHVsZS5fbWFsbG9jKGFsbG9jYXRlZFZlcnRleENvdW50ICogNCk7CiAgICAgICAgICBkZXB0aEluZGV4UHRyID0gd2FzbU1vZHVsZS5fbWFsbG9jKGFsbG9jYXRlZFZlcnRleENvdW50ICogNCk7CiAgICAgICAgICBzdGFydHNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoYWxsb2NhdGVkVmVydGV4Q291bnQgKiA0KTsKICAgICAgICAgIGNvdW50c1B0ciA9IHdhc21Nb2R1bGUuX21hbGxvYyhhbGxvY2F0ZWRWZXJ0ZXhDb3VudCAqIDQpOwogICAgICB9CiAgICAgIGlmIChhbGxvY2F0ZWRUcmFuc2Zvcm1Db3VudCA8IHNvcnREYXRhLnRyYW5zZm9ybXMubGVuZ3RoKSB7CiAgICAgICAgICBpZiAoYWxsb2NhdGVkVHJhbnNmb3JtQ291bnQgPiAwKSB7CiAgICAgICAgICAgICAgd2FzbU1vZHVsZS5fZnJlZSh0cmFuc2Zvcm1zUHRyKTsKICAgICAgICAgIH0KICAgICAgICAgIGFsbG9jYXRlZFRyYW5zZm9ybUNvdW50ID0gc29ydERhdGEudHJhbnNmb3Jtcy5sZW5ndGg7CiAgICAgICAgICB0cmFuc2Zvcm1zUHRyID0gd2FzbU1vZHVsZS5fbWFsbG9jKGFsbG9jYXRlZFRyYW5zZm9ybUNvdW50ICogNCk7CiAgICAgIH0KICAgICAgbG9jayA9IGZhbHNlOwogICAgICBpZiAoYWxsb2NhdGlvblBlbmRpbmcpIHsKICAgICAgICAgIGFsbG9jYXRpb25QZW5kaW5nID0gZmFsc2U7CiAgICAgICAgICBhd2FpdCBhbGxvY2F0ZUJ1ZmZlcnMoKTsKICAgICAgfQogIH07CiAgY29uc3QgcnVuU29ydCA9ICgpID0+IHsKICAgICAgaWYgKGxvY2sgfHwgYWxsb2NhdGlvblBlbmRpbmcgfHwgIXdhc21Nb2R1bGUpCiAgICAgICAgICByZXR1cm47CiAgICAgIGxvY2sgPSB0cnVlOwogICAgICB3YXNtTW9kdWxlLkhFQVBGMzIuc2V0KHNvcnREYXRhLnBvc2l0aW9ucywgcG9zaXRpb25zUHRyIC8gNCk7CiAgICAgIHdhc21Nb2R1bGUuSEVBUEYzMi5zZXQoc29ydERhdGEudHJhbnNmb3JtcywgdHJhbnNmb3Jtc1B0ciAvIDQpOwogICAgICB3YXNtTW9kdWxlLkhFQVBVMzIuc2V0KHNvcnREYXRhLnRyYW5zZm9ybUluZGljZXMsIHRyYW5zZm9ybUluZGljZXNQdHIgLyA0KTsKICAgICAgd2FzbU1vZHVsZS5IRUFQRjMyLnNldCh2aWV3UHJvaiwgdmlld1Byb2pQdHIgLyA0KTsKICAgICAgd2FzbU1vZHVsZS5fc29ydCh2aWV3UHJvalB0ciwgdHJhbnNmb3Jtc1B0ciwgdHJhbnNmb3JtSW5kaWNlc1B0ciwgc29ydERhdGEudmVydGV4Q291bnQsIHBvc2l0aW9uc1B0ciwgZGVwdGhCdWZmZXJQdHIsIGRlcHRoSW5kZXhQdHIsIHN0YXJ0c1B0ciwgY291bnRzUHRyKTsKICAgICAgY29uc3QgZGVwdGhJbmRleCA9IG5ldyBVaW50MzJBcnJheSh3YXNtTW9kdWxlLkhFQVBVMzIuYnVmZmVyLCBkZXB0aEluZGV4UHRyLCBzb3J0RGF0YS52ZXJ0ZXhDb3VudCk7CiAgICAgIGNvbnN0IGRldGFjaGVkRGVwdGhJbmRleCA9IG5ldyBVaW50MzJBcnJheShkZXB0aEluZGV4LnNsaWNlKCkuYnVmZmVyKTsKICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7IGRlcHRoSW5kZXg6IGRldGFjaGVkRGVwdGhJbmRleCB9LCBbZGV0YWNoZWREZXB0aEluZGV4LmJ1ZmZlcl0pOwogICAgICBsb2NrID0gZmFsc2U7CiAgfTsKICBjb25zdCB0aHJvdHRsZWRTb3J0ID0gKCkgPT4gewogICAgICBpZiAoIXNvcnRpbmcpIHsKICAgICAgICAgIHNvcnRpbmcgPSB0cnVlOwogICAgICAgICAgcnVuU29ydCgpOwogICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7CiAgICAgICAgICAgICAgc29ydGluZyA9IGZhbHNlOwogICAgICAgICAgICAgIHRocm90dGxlZFNvcnQoKTsKICAgICAgICAgIH0pOwogICAgICB9CiAgfTsKICBzZWxmLm9ubWVzc2FnZSA9IChlKSA9PiB7CiAgICAgIGlmIChlLmRhdGEuc29ydERhdGEpIHsKICAgICAgICAgIC8vUmVjcmVhdGluZyB0aGUgdHlwZWQgYXJyYXlzIGV2ZXJ5IHRpbWUsIHdpbGwgY2F1c2UgZmlyZWZveCB0byBsZWFrIG1lbW9yeQogICAgICAgICAgaWYgKCFzb3J0RGF0YSkgewogICAgICAgICAgICAgIHNvcnREYXRhID0gewogICAgICAgICAgICAgICAgICBwb3NpdGlvbnM6IG5ldyBGbG9hdDMyQXJyYXkoZS5kYXRhLnNvcnREYXRhLnBvc2l0aW9ucyksCiAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybXM6IG5ldyBGbG9hdDMyQXJyYXkoZS5kYXRhLnNvcnREYXRhLnRyYW5zZm9ybXMpLAogICAgICAgICAgICAgICAgICB0cmFuc2Zvcm1JbmRpY2VzOiBuZXcgVWludDMyQXJyYXkoZS5kYXRhLnNvcnREYXRhLnRyYW5zZm9ybUluZGljZXMpLAogICAgICAgICAgICAgICAgICB2ZXJ0ZXhDb3VudDogZS5kYXRhLnNvcnREYXRhLnZlcnRleENvdW50LAogICAgICAgICAgICAgIH07CiAgICAgICAgICB9CiAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICBzb3J0RGF0YS5wb3NpdGlvbnMuc2V0KGUuZGF0YS5zb3J0RGF0YS5wb3NpdGlvbnMpOwogICAgICAgICAgICAgIHNvcnREYXRhLnRyYW5zZm9ybXMuc2V0KGUuZGF0YS5zb3J0RGF0YS50cmFuc2Zvcm1zKTsKICAgICAgICAgICAgICBzb3J0RGF0YS50cmFuc2Zvcm1JbmRpY2VzLnNldChlLmRhdGEuc29ydERhdGEudHJhbnNmb3JtSW5kaWNlcyk7CiAgICAgICAgICAgICAgc29ydERhdGEudmVydGV4Q291bnQgPSBlLmRhdGEuc29ydERhdGEudmVydGV4Q291bnQ7CiAgICAgICAgICB9CiAgICAgICAgICBhbGxvY2F0ZUJ1ZmZlcnMoKTsKICAgICAgfQogICAgICBpZiAoZS5kYXRhLnZpZXdQcm9qKSB7CiAgICAgICAgICB2aWV3UHJvaiA9IEZsb2F0MzJBcnJheS5mcm9tKGUuZGF0YS52aWV3UHJvaik7CiAgICAgICAgICB0aHJvdHRsZWRTb3J0KCk7CiAgICAgIH0KICB9OwoKfSkoKTsKLy8jIHNvdXJjZU1hcHBpbmdVUkw9U29ydFdvcmtlci5qcy5tYXAKCg==",null);class Nt{constructor(t,F){this._scene=null,this._camera=null,this._started=!1,this._initialized=!1,this._renderer=t;const U=t.gl;this._program=U.createProgram(),this._passes=F||[];const l=U.createShader(U.VERTEX_SHADER);U.shaderSource(l,this._getVertexSource()),U.compileShader(l),U.getShaderParameter(l,U.COMPILE_STATUS)||console.error(U.getShaderInfoLog(l));const a=U.createShader(U.FRAGMENT_SHADER);U.shaderSource(a,this._getFragmentSource()),U.compileShader(a),U.getShaderParameter(a,U.COMPILE_STATUS)||console.error(U.getShaderInfoLog(a)),U.attachShader(this.program,l),U.attachShader(this.program,a),U.linkProgram(this.program),U.getProgramParameter(this.program,U.LINK_STATUS)||console.error(U.getProgramInfoLog(this.program)),this.resize=()=>{U.useProgram(this._program),this._resize()},this.initialize=()=>{console.assert(!this._initialized,"ShaderProgram already initialized"),U.useProgram(this._program),this._initialize();for(const n of this.passes)n.initialize(this);this._initialized=!0,this._started=!0},this.render=(n,e)=>{U.useProgram(this._program),this._scene===n&&this._camera===e||(this.dispose(),this._scene=n,this._camera=e,this.initialize());for(const Q of this.passes)Q.render();this._render()},this.dispose=()=>{if(this._initialized){U.useProgram(this._program);for(const n of this.passes)n.dispose();this._dispose(),this._scene=null,this._camera=null,this._initialized=!1}}}get renderer(){return this._renderer}get scene(){return this._scene}get camera(){return this._camera}get program(){return this._program}get passes(){return this._passes}get started(){return this._started}}var al=kt("Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICd1c2Ugc3RyaWN0JzsKCiAgdmFyIGxvYWRXYXNtID0gKCgpID0+IHsKICAgIAogICAgcmV0dXJuICgKICBmdW5jdGlvbihtb2R1bGVBcmcgPSB7fSkgewoKICB2YXIgTW9kdWxlPW1vZHVsZUFyZzt2YXIgcmVhZHlQcm9taXNlUmVzb2x2ZSxyZWFkeVByb21pc2VSZWplY3Q7TW9kdWxlWyJyZWFkeSJdPW5ldyBQcm9taXNlKChyZXNvbHZlLHJlamVjdCk9PntyZWFkeVByb21pc2VSZXNvbHZlPXJlc29sdmU7cmVhZHlQcm9taXNlUmVqZWN0PXJlamVjdDt9KTt2YXIgbW9kdWxlT3ZlcnJpZGVzPU9iamVjdC5hc3NpZ24oe30sTW9kdWxlKTt2YXIgc2NyaXB0RGlyZWN0b3J5PSIiO2Z1bmN0aW9uIGxvY2F0ZUZpbGUocGF0aCl7aWYoTW9kdWxlWyJsb2NhdGVGaWxlIl0pe3JldHVybiBNb2R1bGVbImxvY2F0ZUZpbGUiXShwYXRoLHNjcmlwdERpcmVjdG9yeSl9cmV0dXJuIHNjcmlwdERpcmVjdG9yeStwYXRofXZhciByZWFkQmluYXJ5O3t7c2NyaXB0RGlyZWN0b3J5PXNlbGYubG9jYXRpb24uaHJlZjt9aWYoc2NyaXB0RGlyZWN0b3J5LmluZGV4T2YoImJsb2I6IikhPT0wKXtzY3JpcHREaXJlY3Rvcnk9c2NyaXB0RGlyZWN0b3J5LnN1YnN0cigwLHNjcmlwdERpcmVjdG9yeS5yZXBsYWNlKC9bPyNdLiovLCIiKS5sYXN0SW5kZXhPZigiLyIpKzEpO31lbHNlIHtzY3JpcHREaXJlY3Rvcnk9IiI7fXt7cmVhZEJpbmFyeT11cmw9Pnt2YXIgeGhyPW5ldyBYTUxIdHRwUmVxdWVzdDt4aHIub3BlbigiR0VUIix1cmwsZmFsc2UpO3hoci5yZXNwb25zZVR5cGU9ImFycmF5YnVmZmVyIjt4aHIuc2VuZChudWxsKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoeGhyLnJlc3BvbnNlKX07fX19TW9kdWxlWyJwcmludCJdfHxjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpO3ZhciBlcnI9TW9kdWxlWyJwcmludEVyciJdfHxjb25zb2xlLmVycm9yLmJpbmQoY29uc29sZSk7T2JqZWN0LmFzc2lnbihNb2R1bGUsbW9kdWxlT3ZlcnJpZGVzKTttb2R1bGVPdmVycmlkZXM9bnVsbDtpZihNb2R1bGVbImFyZ3VtZW50cyJdKU1vZHVsZVsiYXJndW1lbnRzIl07aWYoTW9kdWxlWyJ0aGlzUHJvZ3JhbSJdKU1vZHVsZVsidGhpc1Byb2dyYW0iXTtpZihNb2R1bGVbInF1aXQiXSlNb2R1bGVbInF1aXQiXTt2YXIgd2FzbUJpbmFyeTtpZihNb2R1bGVbIndhc21CaW5hcnkiXSl3YXNtQmluYXJ5PU1vZHVsZVsid2FzbUJpbmFyeSJdO2lmKHR5cGVvZiBXZWJBc3NlbWJseSE9Im9iamVjdCIpe2Fib3J0KCJubyBuYXRpdmUgd2FzbSBzdXBwb3J0IGRldGVjdGVkIik7fXZhciB3YXNtTWVtb3J5O3ZhciBBQk9SVD1mYWxzZTt2YXIgSEVBUDgsSEVBUFU4LEhFQVAxNixIRUFQVTE2LEhFQVAzMixIRUFQVTMyLEhFQVBGMzIsSEVBUEY2NDtmdW5jdGlvbiB1cGRhdGVNZW1vcnlWaWV3cygpe3ZhciBiPXdhc21NZW1vcnkuYnVmZmVyO01vZHVsZVsiSEVBUDgiXT1IRUFQOD1uZXcgSW50OEFycmF5KGIpO01vZHVsZVsiSEVBUDE2Il09SEVBUDE2PW5ldyBJbnQxNkFycmF5KGIpO01vZHVsZVsiSEVBUFU4Il09SEVBUFU4PW5ldyBVaW50OEFycmF5KGIpO01vZHVsZVsiSEVBUFUxNiJdPUhFQVBVMTY9bmV3IFVpbnQxNkFycmF5KGIpO01vZHVsZVsiSEVBUDMyIl09SEVBUDMyPW5ldyBJbnQzMkFycmF5KGIpO01vZHVsZVsiSEVBUFUzMiJdPUhFQVBVMzI9bmV3IFVpbnQzMkFycmF5KGIpO01vZHVsZVsiSEVBUEYzMiJdPUhFQVBGMzI9bmV3IEZsb2F0MzJBcnJheShiKTtNb2R1bGVbIkhFQVBGNjQiXT1IRUFQRjY0PW5ldyBGbG9hdDY0QXJyYXkoYik7fXZhciBfX0FUUFJFUlVOX189W107dmFyIF9fQVRJTklUX189W107dmFyIF9fQVRQT1NUUlVOX189W107ZnVuY3Rpb24gcHJlUnVuKCl7aWYoTW9kdWxlWyJwcmVSdW4iXSl7aWYodHlwZW9mIE1vZHVsZVsicHJlUnVuIl09PSJmdW5jdGlvbiIpTW9kdWxlWyJwcmVSdW4iXT1bTW9kdWxlWyJwcmVSdW4iXV07d2hpbGUoTW9kdWxlWyJwcmVSdW4iXS5sZW5ndGgpe2FkZE9uUHJlUnVuKE1vZHVsZVsicHJlUnVuIl0uc2hpZnQoKSk7fX1jYWxsUnVudGltZUNhbGxiYWNrcyhfX0FUUFJFUlVOX18pO31mdW5jdGlvbiBpbml0UnVudGltZSgpe2NhbGxSdW50aW1lQ2FsbGJhY2tzKF9fQVRJTklUX18pO31mdW5jdGlvbiBwb3N0UnVuKCl7aWYoTW9kdWxlWyJwb3N0UnVuIl0pe2lmKHR5cGVvZiBNb2R1bGVbInBvc3RSdW4iXT09ImZ1bmN0aW9uIilNb2R1bGVbInBvc3RSdW4iXT1bTW9kdWxlWyJwb3N0UnVuIl1dO3doaWxlKE1vZHVsZVsicG9zdFJ1biJdLmxlbmd0aCl7YWRkT25Qb3N0UnVuKE1vZHVsZVsicG9zdFJ1biJdLnNoaWZ0KCkpO319Y2FsbFJ1bnRpbWVDYWxsYmFja3MoX19BVFBPU1RSVU5fXyk7fWZ1bmN0aW9uIGFkZE9uUHJlUnVuKGNiKXtfX0FUUFJFUlVOX18udW5zaGlmdChjYik7fWZ1bmN0aW9uIGFkZE9uSW5pdChjYil7X19BVElOSVRfXy51bnNoaWZ0KGNiKTt9ZnVuY3Rpb24gYWRkT25Qb3N0UnVuKGNiKXtfX0FUUE9TVFJVTl9fLnVuc2hpZnQoY2IpO312YXIgcnVuRGVwZW5kZW5jaWVzPTA7dmFyIGRlcGVuZGVuY2llc0Z1bGZpbGxlZD1udWxsO2Z1bmN0aW9uIGFkZFJ1bkRlcGVuZGVuY3koaWQpe3J1bkRlcGVuZGVuY2llcysrO2lmKE1vZHVsZVsibW9uaXRvclJ1bkRlcGVuZGVuY2llcyJdKXtNb2R1bGVbIm1vbml0b3JSdW5EZXBlbmRlbmNpZXMiXShydW5EZXBlbmRlbmNpZXMpO319ZnVuY3Rpb24gcmVtb3ZlUnVuRGVwZW5kZW5jeShpZCl7cnVuRGVwZW5kZW5jaWVzLS07aWYoTW9kdWxlWyJtb25pdG9yUnVuRGVwZW5kZW5jaWVzIl0pe01vZHVsZVsibW9uaXRvclJ1bkRlcGVuZGVuY2llcyJdKHJ1bkRlcGVuZGVuY2llcyk7fWlmKHJ1bkRlcGVuZGVuY2llcz09MCl7aWYoZGVwZW5kZW5jaWVzRnVsZmlsbGVkKXt2YXIgY2FsbGJhY2s9ZGVwZW5kZW5jaWVzRnVsZmlsbGVkO2RlcGVuZGVuY2llc0Z1bGZpbGxlZD1udWxsO2NhbGxiYWNrKCk7fX19ZnVuY3Rpb24gYWJvcnQod2hhdCl7aWYoTW9kdWxlWyJvbkFib3J0Il0pe01vZHVsZVsib25BYm9ydCJdKHdoYXQpO313aGF0PSJBYm9ydGVkKCIrd2hhdCsiKSI7ZXJyKHdoYXQpO0FCT1JUPXRydWU7d2hhdCs9Ii4gQnVpbGQgd2l0aCAtc0FTU0VSVElPTlMgZm9yIG1vcmUgaW5mby4iO3ZhciBlPW5ldyBXZWJBc3NlbWJseS5SdW50aW1lRXJyb3Iod2hhdCk7cmVhZHlQcm9taXNlUmVqZWN0KGUpO3Rocm93IGV9dmFyIGRhdGFVUklQcmVmaXg9ImRhdGE6YXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtO2Jhc2U2NCwiO3ZhciBpc0RhdGFVUkk9ZmlsZW5hbWU9PmZpbGVuYW1lLnN0YXJ0c1dpdGgoZGF0YVVSSVByZWZpeCk7dmFyIHdhc21CaW5hcnlGaWxlO3dhc21CaW5hcnlGaWxlPSJkYXRhOmFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbTtiYXNlNjQsQUdGemJRRUFBQUFCWVE1Z0JIOS9mMzhBWUFOL2YzOEFZQVYvZjM5L2Z3QmdCbjkvZjM5L2Z3QmdBbjkvQUdBQmZ3Ri9ZQUFBWUFOL2YzOEJmMkFCZndCZ0IzOS9mMzkvZjM4QVlBSjlmUUYvWUFSL2YzNStBR0FCZlFGL1lBdC9mMzkvZjM5L2YzOS9md0FDUFFvQllRRmhBQUVCWVFGaUFBSUJZUUZqQUFFQllRRmtBQVFCWVFGbEFBRUJZUUZtQUFrQllRRm5BQVVCWVFGb0FBUUJZUUZwQUFBQllRRnFBQVFER3hvSEJRb0lCZ1FHQ3dFQUFRZ0lEQVlOQXdNQ0FnQUFCd2NGQlFRRkFYQUJFQkFGQndFQmdBS0FnQUlHQ0FGL0FVSGduUVFMQngwSEFXc0NBQUZzQUE0QmJRQVpBVzRBR0FGdkFRQUJjQUFqQVhFQUZna1ZBUUJCQVFzUEVDSU5GUlVoRFNBYUhCOE5HeDBlQ3JKUUduRUJBWDhnQWtVRVFDQUFLQUlFSUFFb0FnUkdEd3NnQUNBQlJnUkFRUUVQQ3dKQUlBQW9BZ1FpQWkwQUFDSUFSU0FBSUFFb0FnUWlBUzBBQUNJRFIzSU5BQU5BSUFFdEFBRWhBeUFDTFFBQklnQkZEUUVnQVVFQmFpRUJJQUpCQVdvaEFpQUFJQU5HRFFBTEN5QUFJQU5HQzA4QkFuOUIyQmtvQWdBaUFTQUFRUWRxUVhoeElnSnFJUUFDUUNBQ1FRQWdBQ0FCVFJzTkFDQUFQd0JCRUhSTEJFQWdBQkFHUlEwQkMwSFlHU0FBTmdJQUlBRVBDMEhvR1VFd05nSUFRWDhMRGdBZ0FCQVhJQUVRRjBFUWRISUxCZ0FnQUJBV0N5a0FRZUFaUVFFMkFnQkI1QmxCQURZQ0FCQVFRZVFaUWR3WktBSUFOZ0lBUWR3WlFlQVpOZ0lBQ3lFQUlBRUVRQU5BSUFCQkFEb0FBQ0FBUVFGcUlRQWdBVUVCYXlJQkRRQUxDd3ZoQXdCQmpCZEJtZ2tRQ1VHWUYwRzVDRUVCUVFBUUNFR2tGMEcwQ0VFQlFZQi9RZjhBRUFGQnZCZEJyUWhCQVVHQWYwSC9BQkFCUWJBWFFhc0lRUUZCQUVIL0FSQUJRY2dYUVlrSVFRSkJnSUIrUWYvL0FSQUJRZFFYUVlBSVFRSkJBRUgvL3dNUUFVSGdGMEdZQ0VFRVFZQ0FnSUI0UWYvLy8vOEhFQUZCN0JkQmp3aEJCRUVBUVg4UUFVSDRGMEhYQ0VFRVFZQ0FnSUI0UWYvLy8vOEhFQUZCaEJoQnpnaEJCRUVBUVg4UUFVR1FHRUdqQ0VLQWdJQ0FnSUNBZ0lCL1F2Ly8vLy8vLy8vLy93QVFFVUdjR0VHaUNFSUFRbjhRRVVHb0dFR2NDRUVFRUFSQnRCaEJrd2xCQ0JBRVFZUVBRZWtJRUFOQnpBOUJsdzBRQTBHVUVFRUVRZHdJRUFKQjRCQkJBa0gxQ0JBQ1Fhd1JRUVJCaEFrUUFrSElFVUcrQ0JBSFFmQVJRUUJCMGd3UUFFR1lFa0VBUWJnTkVBQkJ3QkpCQVVId0RCQUFRZWdTUVFKQm53a1FBRUdRRTBFRFFiNEpFQUJCdUJOQkJFSG1DUkFBUWVBVFFRVkJnd29RQUVHSUZFRUVRZDBORUFCQnNCUkJCVUg3RFJBQVFaZ1NRUUJCNlFvUUFFSEFFa0VCUWNnS0VBQkI2QkpCQWtHckN4QUFRWkFUUVFOQmlRc1FBRUc0RTBFRVFiRU1FQUJCNEJOQkJVR1BEQkFBUWRnVVFRaEI3Z3NRQUVHQUZVRUpRY3dMRUFCQnFCVkJCa0dwQ2hBQVFkQVZRUWRCb2c0UUFBc2NBQ0FBSUFGQkNDQUNweUFDUWlDSXB5QURweUFEUWlDSXB4QUZDeUFBQWtBZ0FDZ0NCQ0FCUncwQUlBQW9BaHhCQVVZTkFDQUFJQUkyQWh3TEM1b0JBQ0FBUVFFNkFEVUNRQ0FBS0FJRUlBSkhEUUFnQUVFQk9nQTBBa0FnQUNnQ0VDSUNSUVJBSUFCQkFUWUNKQ0FBSUFNMkFoZ2dBQ0FCTmdJUUlBTkJBVWNOQWlBQUtBSXdRUUZHRFFFTUFnc2dBU0FDUmdSQUlBQW9BaGdpQWtFQ1JnUkFJQUFnQXpZQ0dDQURJUUlMSUFBb0FqQkJBVWNOQWlBQ1FRRkdEUUVNQWdzZ0FDQUFLQUlrUVFGcU5nSWtDeUFBUVFFNkFEWUxDMTBCQVg4Z0FDZ0NFQ0lEUlFSQUlBQkJBVFlDSkNBQUlBSTJBaGdnQUNBQk5nSVFEd3NDUUNBQklBTkdCRUFnQUNnQ0dFRUNSdzBCSUFBZ0FqWUNHQThMSUFCQkFUb0FOaUFBUVFJMkFoZ2dBQ0FBS0FJa1FRRnFOZ0lrQ3dzQ0FBdlNDd0VIZndKQUlBQkZEUUFnQUVFSWF5SUNJQUJCQkdzb0FnQWlBVUY0Y1NJQWFpRUZBa0FnQVVFQmNRMEFJQUZCQTNGRkRRRWdBaUFDS0FJQUlnRnJJZ0pCL0Jrb0FnQkpEUUVnQUNBQmFpRUFBa0FDUUVHQUdpZ0NBQ0FDUndSQUlBRkIvd0ZOQkVBZ0FVRURkaUVFSUFJb0Fnd2lBU0FDS0FJSUlnTkdCRUJCN0JsQjdCa29BZ0JCZmlBRWQzRTJBZ0FNQlFzZ0F5QUJOZ0lNSUFFZ0F6WUNDQXdFQ3lBQ0tBSVlJUVlnQWlBQ0tBSU1JZ0ZIQkVBZ0FpZ0NDQ0lESUFFMkFnd2dBU0FETmdJSURBTUxJQUpCRkdvaUJDZ0NBQ0lEUlFSQUlBSW9BaEFpQTBVTkFpQUNRUkJxSVFRTEEwQWdCQ0VISUFNaUFVRVVhaUlFS0FJQUlnTU5BQ0FCUVJCcUlRUWdBU2dDRUNJRERRQUxJQWRCQURZQ0FBd0NDeUFGS0FJRUlnRkJBM0ZCQTBjTkFrSDBHU0FBTmdJQUlBVWdBVUYrY1RZQ0JDQUNJQUJCQVhJMkFnUWdCU0FBTmdJQUR3dEJBQ0VCQ3lBR1JRMEFBa0FnQWlnQ0hDSURRUUowUVp3Y2FpSUVLQUlBSUFKR0JFQWdCQ0FCTmdJQUlBRU5BVUh3R1VId0dTZ0NBRUYrSUFOM2NUWUNBQXdDQ3lBR1FSQkJGQ0FHS0FJUUlBSkdHMm9nQVRZQ0FDQUJSUTBCQ3lBQklBWTJBaGdnQWlnQ0VDSURCRUFnQVNBRE5nSVFJQU1nQVRZQ0dBc2dBaWdDRkNJRFJRMEFJQUVnQXpZQ0ZDQURJQUUyQWhnTElBSWdCVThOQUNBRktBSUVJZ0ZCQVhGRkRRQUNRQUpBQWtBQ1FDQUJRUUp4UlFSQVFZUWFLQUlBSUFWR0JFQkJoQm9nQWpZQ0FFSDRHVUg0R1NnQ0FDQUFhaUlBTmdJQUlBSWdBRUVCY2pZQ0JDQUNRWUFhS0FJQVJ3MEdRZlFaUVFBMkFnQkJnQnBCQURZQ0FBOExRWUFhS0FJQUlBVkdCRUJCZ0JvZ0FqWUNBRUgwR1VIMEdTZ0NBQ0FBYWlJQU5nSUFJQUlnQUVFQmNqWUNCQ0FBSUFKcUlBQTJBZ0FQQ3lBQlFYaHhJQUJxSVFBZ0FVSC9BVTBFUUNBQlFRTjJJUVFnQlNnQ0RDSUJJQVVvQWdnaUEwWUVRRUhzR1VIc0dTZ0NBRUYrSUFSM2NUWUNBQXdGQ3lBRElBRTJBZ3dnQVNBRE5nSUlEQVFMSUFVb0FoZ2hCaUFGSUFVb0Fnd2lBVWNFUUVIOEdTZ0NBQm9nQlNnQ0NDSURJQUUyQWd3Z0FTQUROZ0lJREFNTElBVkJGR29pQkNnQ0FDSURSUVJBSUFVb0FoQWlBMFVOQWlBRlFSQnFJUVFMQTBBZ0JDRUhJQU1pQVVFVWFpSUVLQUlBSWdNTkFDQUJRUkJxSVFRZ0FTZ0NFQ0lERFFBTElBZEJBRFlDQUF3Q0N5QUZJQUZCZm5FMkFnUWdBaUFBUVFGeU5nSUVJQUFnQW1vZ0FEWUNBQXdEQzBFQUlRRUxJQVpGRFFBQ1FDQUZLQUljSWdOQkFuUkJuQnhxSWdRb0FnQWdCVVlFUUNBRUlBRTJBZ0FnQVEwQlFmQVpRZkFaS0FJQVFYNGdBM2R4TmdJQURBSUxJQVpCRUVFVUlBWW9BaEFnQlVZYmFpQUJOZ0lBSUFGRkRRRUxJQUVnQmpZQ0dDQUZLQUlRSWdNRVFDQUJJQU0yQWhBZ0F5QUJOZ0lZQ3lBRktBSVVJZ05GRFFBZ0FTQUROZ0lVSUFNZ0FUWUNHQXNnQWlBQVFRRnlOZ0lFSUFBZ0Ftb2dBRFlDQUNBQ1FZQWFLQUlBUncwQVFmUVpJQUEyQWdBUEN5QUFRZjhCVFFSQUlBQkJlSEZCbEJwcUlRRUNmMEhzR1NnQ0FDSURRUUVnQUVFRGRuUWlBSEZGQkVCQjdCa2dBQ0FEY2pZQ0FDQUJEQUVMSUFFb0FnZ0xJUUFnQVNBQ05nSUlJQUFnQWpZQ0RDQUNJQUUyQWd3Z0FpQUFOZ0lJRHd0Qkh5RURJQUJCLy8vL0IwMEVRQ0FBUVNZZ0FFRUlkbWNpQVd0MlFRRnhJQUZCQVhSclFUNXFJUU1MSUFJZ0F6WUNIQ0FDUWdBM0FoQWdBMEVDZEVHY0hHb2hBUUpBQWtBQ1FFSHdHU2dDQUNJRVFRRWdBM1FpQjNGRkJFQkI4QmtnQkNBSGNqWUNBQ0FCSUFJMkFnQWdBaUFCTmdJWURBRUxJQUJCR1NBRFFRRjJhMEVBSUFOQkgwY2JkQ0VESUFFb0FnQWhBUU5BSUFFaUJDZ0NCRUY0Y1NBQVJnMENJQU5CSFhZaEFTQURRUUYwSVFNZ0JDQUJRUVJ4YWlJSFFSQnFLQUlBSWdFTkFBc2dCeUFDTmdJUUlBSWdCRFlDR0FzZ0FpQUNOZ0lNSUFJZ0FqWUNDQXdCQ3lBRUtBSUlJZ0FnQWpZQ0RDQUVJQUkyQWdnZ0FrRUFOZ0lZSUFJZ0JEWUNEQ0FDSUFBMkFnZ0xRWXdhUVl3YUtBSUFRUUZySWdCQmZ5QUFHellDQUFzTGR3RUVmeUFBdkNJRVFmLy8vd054SVFFQ1FDQUVRUmQyUWY4QmNTSUNSUTBBSUFKQjhBQk5CRUFnQVVHQWdJQUVja0h4QUNBQ2EzWWhBUXdCQ3lBQ1FZMEJTd1JBUVlENEFTRURRUUFoQVF3QkN5QUNRUXAwUVlDQUIyc2hBd3NnQXlBRVFSQjJRWUNBQW5GeUlBRkJEWFp5UWYvL0EzRUxJd0VCZjBIY0dTZ0NBQ0lBQkVBRFFDQUFLQUlBRVFZQUlBQW9BZ1FpQUEwQUN3c0x2Z3NDQzM4SmZTTUFRYUFCYXlJTEpBQWdDMEV3YWtFa0VBOERRQ0FCSUExSEJFQWdBaUFOUVFOc0lneEJBbXBCQW5RaURtb3FBZ0FoRnlBQ0lBeEJBV3BCQW5RaUQyb3FBZ0FoR0NBSUlBeEJBblFpRUdvZ0FpQVFhaW9DQUNJWk9BSUFJQWdnRDJvZ0dEZ0NBQ0FJSUE1cUlCYzRBZ0FnQnlBTlFRVjBhaUlNSUJnNEFnUWdEQ0FaT0FJQUlBd2dGemdDQ0NBTVFRQTJBZ3dDUUNBQVJRUkFJQVlnRFdvdEFBQkZEUUVMSUF4QmdJQ0FDRFlDREFzZ0J5QU5RUVYwSWhGQkhISnFJQVVnRFVFQ2RDSU1RUUZ5SWhKcUxRQUFRUWgwSUFVZ0RHb3RBQUJ5SUFVZ0RFRUNjaUlUYWkwQUFFRVFkSElnQlNBTVFRTnlJZ3hxTFFBQVFSaDBjallDQUNBTElBTWdFa0VDZENJU2Fpb0NBQ0lYT0FLUUFTQUxJQU1nRTBFQ2RDSVRhaW9DQUNJWU9BS1VBU0FMSUFNZ0RFRUNkQ0lVYWlvQ0FDSVpPQUtZQVNBTElBTWdEVUVFZENJVmFpb0NBSXdpR2pnQ25BRWdDMEhnQUdvaURDQUxLZ0tZQVNJV1F3QUFBTUNVSUJhVUlBc3FBcFFCSWhaREFBQUF3SlFnRnBSREFBQ0FQNUtTT0FJQUlBd2dDeW9Da0FFaUZpQVdraUFMS2dLVUFaUWdDeW9DbUFGREFBQUF3SlFnQ3lvQ25BR1VramdDQkNBTUlBc3FBcEFCSWhZZ0ZwSWdDeW9DbUFHVUlBc3FBcFFCSWhZZ0ZwSWdDeW9DbkFHVWtqZ0NDQ0FNSUFzcUFwQUJJaFlnRnBJZ0N5b0NsQUdVSUFzcUFwZ0JJaFlnRnBJZ0N5b0NuQUdVa2pnQ0RDQU1JQXNxQXBnQkloWkRBQUFBd0pRZ0ZwUWdDeW9Da0FFaUZrTUFBQURBbENBV2xFTUFBSUEva3BJNEFoQWdEQ0FMS2dLVUFTSVdJQmFTSUFzcUFwZ0JsQ0FMS2dLUUFVTUFBQURBbENBTEtnS2NBWlNTT0FJVUlBd2dDeW9Da0FFaUZpQVdraUFMS2dLWUFaUWdDeW9DbEFGREFBQUF3SlFnQ3lvQ25BR1VramdDR0NBTUlBc3FBcFFCSWhZZ0ZwSWdDeW9DbUFHVUlBc3FBcEFCSWhZZ0ZwSWdDeW9DbkFHVWtqZ0NIQ0FNSUFzcUFwUUJJaFpEQUFBQXdKUWdGcFFnQ3lvQ2tBRWlGa01BQUFEQWxDQVdsRU1BQUlBL2twSTRBaUFnQ1NBVmFpQVhPQUlBSUFrZ0Vtb2dHRGdDQUNBSklCTnFJQms0QWdBZ0NTQVVhaUFhT0FJQUlBc2dCQ0FRYWlvQ0FDSVhPQUl3SUFzZ0JDQVBhaW9DQUNJWU9BSkFJQXNnQkNBT2Fpb0NBQ0laT0FKUUlBb2dFR29nRnpnQ0FDQUtJQTlxSUJnNEFnQWdDaUFPYWlBWk9BSUFJQXNnRENvQ0dDQUxLZ0k0bENBTUtnSUFJQXNxQWpDVUlBd3FBZ3dnQ3lvQ05KU1NramdDQUNBTElBd3FBaHdnQ3lvQ09KUWdEQ29DQkNBTEtnSXdsQ0FNS2dJUUlBc3FBalNVa3BJNEFnUWdDeUFNS2dJZ0lBc3FBamlVSUF3cUFnZ2dDeW9DTUpRZ0RDb0NGQ0FMS2dJMGxKS1NPQUlJSUFzZ0RDb0NHQ0FMS2dKRWxDQU1LZ0lBSUFzcUFqeVVJQXdxQWd3Z0N5b0NRSlNTa2pnQ0RDQUxJQXdxQWh3Z0N5b0NSSlFnRENvQ0JDQUxLZ0k4bENBTUtnSVFJQXNxQWtDVWtwSTRBaEFnQ3lBTUtnSWdJQXNxQWtTVUlBd3FBZ2dnQ3lvQ1BKUWdEQ29DRkNBTEtnSkFsSktTT0FJVUlBc2dEQ29DR0NBTEtnSlFsQ0FNS2dJQUlBc3FBa2lVSUF3cUFnd2dDeW9DVEpTU2tqZ0NHQ0FMSUF3cUFod2dDeW9DVUpRZ0RDb0NCQ0FMS2dKSWxDQU1LZ0lRSUFzcUFreVVrcEk0QWh3Z0N5QU1LZ0lnSUFzcUFsQ1VJQXdxQWdnZ0N5b0NTSlFnRENvQ0ZDQUxLZ0pNbEpLU09BSWdJQXNxQWlBaEZ5QUxLZ0lJSVJnZ0N5b0NGQ0VaSUFjZ0VVRVFjbW9nQ3lvQ0dDSWFJQnFVSUFzcUFnQWlGaUFXbENBTEtnSU1JaHNnRzVTU2trTUFBSUJBbENBYUlBc3FBaHdpSEpRZ0ZpQUxLZ0lFSWgyVUlCc2dDeW9DRUNJZWxKS1NRd0FBZ0VDVUVBdzJBZ0FnQnlBUlFSUnlhaUFhSUJlVUlCWWdHSlFnR3lBWmxKS1NRd0FBZ0VDVUlCd2dISlFnSFNBZGxDQWVJQjZVa3BKREFBQ0FRSlFRRERZQ0FDQUhJQkZCR0hKcUlCd2dGNVFnSFNBWWxDQWVJQm1Va3BKREFBQ0FRSlFnRnlBWGxDQVlJQmlVSUJrZ0daU1Nra01BQUlCQWxCQU1OZ0lBSUExQkFXb2hEUXdCQ3dzZ0MwR2dBV29rQUFzYUFDQUFJQUVvQWdnZ0JSQUtCRUFnQVNBQ0lBTWdCQkFUQ3dzM0FDQUFJQUVvQWdnZ0JSQUtCRUFnQVNBQ0lBTWdCQkFURHdzZ0FDZ0NDQ0lBSUFFZ0FpQURJQVFnQlNBQUtBSUFLQUlVRVFNQUM1RUJBQ0FBSUFFb0FnZ2dCQkFLQkVBZ0FTQUNJQU1RRWc4TEFrQWdBQ0FCS0FJQUlBUVFDa1VOQUFKQUlBSWdBU2dDRUVjRVFDQUJLQUlVSUFKSERRRUxJQU5CQVVjTkFTQUJRUUUyQWlBUEN5QUJJQUkyQWhRZ0FTQUROZ0lnSUFFZ0FTZ0NLRUVCYWpZQ0tBSkFJQUVvQWlSQkFVY05BQ0FCS0FJWVFRSkhEUUFnQVVFQk9nQTJDeUFCUVFRMkFpd0xDL0lCQUNBQUlBRW9BZ2dnQkJBS0JFQWdBU0FDSUFNUUVnOExBa0FnQUNBQktBSUFJQVFRQ2dSQUFrQWdBaUFCS0FJUVJ3UkFJQUVvQWhRZ0FrY05BUXNnQTBFQlJ3MENJQUZCQVRZQ0lBOExJQUVnQXpZQ0lBSkFJQUVvQWl4QkJFWU5BQ0FCUVFBN0FUUWdBQ2dDQ0NJQUlBRWdBaUFDUVFFZ0JDQUFLQUlBS0FJVUVRTUFJQUV0QURVRVFDQUJRUU0yQWl3Z0FTMEFORVVOQVF3REN5QUJRUVEyQWl3TElBRWdBallDRkNBQklBRW9BaWhCQVdvMkFpZ2dBU2dDSkVFQlJ3MEJJQUVvQWhoQkFrY05BU0FCUVFFNkFEWVBDeUFBS0FJSUlnQWdBU0FDSUFNZ0JDQUFLQUlBS0FJWUVRSUFDd3N4QUNBQUlBRW9BZ2hCQUJBS0JFQWdBU0FDSUFNUUZBOExJQUFvQWdnaUFDQUJJQUlnQXlBQUtBSUFLQUljRVFBQUN4Z0FJQUFnQVNnQ0NFRUFFQW9FUUNBQklBSWdBeEFVQ3d2SkF3RUZmeU1BUVVCcUlnUWtBQUovUVFFZ0FDQUJRUUFRQ2cwQUdrRUFJQUZGRFFBYUl3QkJRR29pQXlRQUlBRW9BZ0FpQlVFRWF5Z0NBQ0VHSUFWQkNHc29BZ0FoQlNBRFFnQTNBaUFnQTBJQU53SW9JQU5DQURjQ01DQURRZ0EzQURjZ0EwSUFOd0lZSUFOQkFEWUNGQ0FEUWZ3Vk5nSVFJQU1nQVRZQ0RDQURRYXdXTmdJSUlBRWdCV29oQVVFQUlRVUNRQ0FHUWF3V1FRQVFDZ1JBSUFOQkFUWUNPQ0FHSUFOQkNHb2dBU0FCUVFGQkFDQUdLQUlBS0FJVUVRTUFJQUZCQUNBREtBSWdRUUZHR3lFRkRBRUxJQVlnQTBFSWFpQUJRUUZCQUNBR0tBSUFLQUlZRVFJQUFrQUNRQ0FES0FJc0RnSUFBUUlMSUFNb0FoeEJBQ0FES0FJb1FRRkdHMEVBSUFNb0FpUkJBVVliUVFBZ0F5Z0NNRUVCUmhzaEJRd0JDeUFES0FJZ1FRRkhCRUFnQXlnQ01BMEJJQU1vQWlSQkFVY05BU0FES0FJb1FRRkhEUUVMSUFNb0FoZ2hCUXNnQTBGQWF5UUFRUUFnQlNJQlJRMEFHaUFFUVF4cVFUUVFEeUFFUVFFMkFqZ2dCRUYvTmdJVUlBUWdBRFlDRUNBRUlBRTJBZ2dnQVNBRVFRaHFJQUlvQWdCQkFTQUJLQUlBS0FJY0VRQUFJQVFvQWlBaUFFRUJSZ1JBSUFJZ0JDZ0NHRFlDQUFzZ0FFRUJSZ3NoQnlBRVFVQnJKQUFnQndzS0FDQUFJQUZCQUJBS0N3UUFJQUFMdlNjQkRIOGpBRUVRYXlJS0pBQUNRQUpBQWtBQ1FBSkFBa0FDUUFKQUFrQUNRQUpBQWtBQ1FBSkFJQUJCOUFGTkJFQkI3QmtvQWdBaUJrRVFJQUJCQzJwQmVIRWdBRUVMU1JzaUJVRURkaUlBZGlJQlFRTnhCRUFDUUNBQlFYOXpRUUZ4SUFCcUlnSkJBM1FpQVVHVUdtb2lBQ0FCUVp3YWFpZ0NBQ0lCS0FJSUlnUkdCRUJCN0JrZ0JrRitJQUozY1RZQ0FBd0JDeUFFSUFBMkFnd2dBQ0FFTmdJSUN5QUJRUWhxSVFBZ0FTQUNRUU4wSWdKQkEzSTJBZ1FnQVNBQ2FpSUJJQUVvQWdSQkFYSTJBZ1FNRHdzZ0JVSDBHU2dDQUNJSFRRMEJJQUVFUUFKQVFRSWdBSFFpQWtFQUlBSnJjaUFCSUFCMGNXZ2lBVUVEZENJQVFaUWFhaUlDSUFCQm5CcHFLQUlBSWdBb0FnZ2lCRVlFUUVIc0dTQUdRWDRnQVhkeElnWTJBZ0FNQVFzZ0JDQUNOZ0lNSUFJZ0JEWUNDQXNnQUNBRlFRTnlOZ0lFSUFBZ0JXb2lDQ0FCUVFOMElnRWdCV3NpQkVFQmNqWUNCQ0FBSUFGcUlBUTJBZ0FnQndSQUlBZEJlSEZCbEJwcUlRRkJnQm9vQWdBaEFnSi9JQVpCQVNBSFFRTjJkQ0lEY1VVRVFFSHNHU0FESUFaeU5nSUFJQUVNQVFzZ0FTZ0NDQXNoQXlBQklBSTJBZ2dnQXlBQ05nSU1JQUlnQVRZQ0RDQUNJQU0yQWdnTElBQkJDR29oQUVHQUdpQUlOZ0lBUWZRWklBUTJBZ0FNRHd0QjhCa29BZ0FpQzBVTkFTQUxhRUVDZEVHY0hHb29BZ0FpQWlnQ0JFRjRjU0FGYXlFRElBSWhBUU5BQWtBZ0FTZ0NFQ0lBUlFSQUlBRW9BaFFpQUVVTkFRc2dBQ2dDQkVGNGNTQUZheUlCSUFNZ0FTQURTU0lCR3lFRElBQWdBaUFCR3lFQ0lBQWhBUXdCQ3dzZ0FpZ0NHQ0VKSUFJZ0FpZ0NEQ0lFUndSQVFmd1pLQUlBR2lBQ0tBSUlJZ0FnQkRZQ0RDQUVJQUEyQWdnTURnc2dBa0VVYWlJQktBSUFJZ0JGQkVBZ0FpZ0NFQ0lBUlEwRElBSkJFR29oQVFzRFFDQUJJUWdnQUNJRVFSUnFJZ0VvQWdBaUFBMEFJQVJCRUdvaEFTQUVLQUlRSWdBTkFBc2dDRUVBTmdJQURBMExRWDhoQlNBQVFiOS9TdzBBSUFCQkMyb2lBRUY0Y1NFRlFmQVpLQUlBSWdoRkRRQkJBQ0FGYXlFREFrQUNRQUpBQW45QkFDQUZRWUFDU1EwQUdrRWZJQVZCLy8vL0Iwc05BQm9nQlVFbUlBQkJDSFpuSWdCcmRrRUJjU0FBUVFGMGEwRSthZ3NpQjBFQ2RFR2NIR29vQWdBaUFVVUVRRUVBSVFBTUFRdEJBQ0VBSUFWQkdTQUhRUUYyYTBFQUlBZEJIMGNiZENFQ0EwQUNRQ0FCS0FJRVFYaHhJQVZySWdZZ0EwOE5BQ0FCSVFRZ0JpSUREUUJCQUNFRElBRWhBQXdEQ3lBQUlBRW9BaFFpQmlBR0lBRWdBa0VkZGtFRWNXb29BaEFpQVVZYklBQWdCaHNoQUNBQ1FRRjBJUUlnQVEwQUN3c2dBQ0FFY2tVRVFFRUFJUVJCQWlBSGRDSUFRUUFnQUd0eUlBaHhJZ0JGRFFNZ0FHaEJBblJCbkJ4cUtBSUFJUUFMSUFCRkRRRUxBMEFnQUNnQ0JFRjRjU0FGYXlJQ0lBTkpJUUVnQWlBRElBRWJJUU1nQUNBRUlBRWJJUVFnQUNnQ0VDSUJCSDhnQVFVZ0FDZ0NGQXNpQUEwQUN3c2dCRVVOQUNBRFFmUVpLQUlBSUFWclR3MEFJQVFvQWhnaEJ5QUVJQVFvQWd3aUFrY0VRRUg4R1NnQ0FCb2dCQ2dDQ0NJQUlBSTJBZ3dnQWlBQU5nSUlEQXdMSUFSQkZHb2lBU2dDQUNJQVJRUkFJQVFvQWhBaUFFVU5BeUFFUVJCcUlRRUxBMEFnQVNFR0lBQWlBa0VVYWlJQktBSUFJZ0FOQUNBQ1FSQnFJUUVnQWlnQ0VDSUFEUUFMSUFaQkFEWUNBQXdMQ3lBRlFmUVpLQUlBSWdSTkJFQkJnQm9vQWdBaEFBSkFJQVFnQldzaUFVRVFUd1JBSUFBZ0JXb2lBaUFCUVFGeU5nSUVJQUFnQkdvZ0FUWUNBQ0FBSUFWQkEzSTJBZ1FNQVFzZ0FDQUVRUU55TmdJRUlBQWdCR29pQVNBQktBSUVRUUZ5TmdJRVFRQWhBa0VBSVFFTFFmUVpJQUUyQWdCQmdCb2dBallDQUNBQVFRaHFJUUFNRFFzZ0JVSDRHU2dDQUNJQ1NRUkFRZmdaSUFJZ0JXc2lBVFlDQUVHRUdrR0VHaWdDQUNJQUlBVnFJZ0kyQWdBZ0FpQUJRUUZ5TmdJRUlBQWdCVUVEY2pZQ0JDQUFRUWhxSVFBTURRdEJBQ0VBSUFWQkwyb2lBd0ovUWNRZEtBSUFCRUJCekIwb0FnQU1BUXRCMEIxQ2Z6Y0NBRUhJSFVLQW9JQ0FnSUFFTndJQVFjUWRJQXBCREdwQmNIRkIyS3JWcWdWek5nSUFRZGdkUVFBMkFnQkJxQjFCQURZQ0FFR0FJQXNpQVdvaUJrRUFJQUZySWdoeElnRWdCVTBOREVHa0hTZ0NBQ0lFQkVCQm5CMG9BZ0FpQnlBQmFpSUpJQWROSUFRZ0NVbHlEUTBMQWtCQnFCMHRBQUJCQkhGRkJFQUNRQUpBQWtBQ1FFR0VHaWdDQUNJRUJFQkJyQjBoQUFOQUlBUWdBQ2dDQUNJSFR3UkFJQWNnQUNnQ0JHb2dCRXNOQXdzZ0FDZ0NDQ0lBRFFBTEMwRUFFQXNpQWtGL1JnMERJQUVoQmtISUhTZ0NBQ0lBUVFGcklnUWdBbkVFUUNBQklBSnJJQUlnQkdwQkFDQUFhM0ZxSVFZTElBVWdCazhOQTBHa0hTZ0NBQ0lBQkVCQm5CMG9BZ0FpQkNBR2FpSUlJQVJOSUFBZ0NFbHlEUVFMSUFZUUN5SUFJQUpIRFFFTUJRc2dCaUFDYXlBSWNTSUdFQXNpQWlBQUtBSUFJQUFvQWdScVJnMEJJQUloQUFzZ0FFRi9SZzBCSUFWQk1Hb2dCazBFUUNBQUlRSU1CQXRCekIwb0FnQWlBaUFESUFacmFrRUFJQUpyY1NJQ0VBdEJmMFlOQVNBQ0lBWnFJUVlnQUNFQ0RBTUxJQUpCZjBjTkFndEJxQjFCcUIwb0FnQkJCSEkyQWdBTElBRVFDeUlDUVg5R1FRQVFDeUlBUVg5R2NpQUFJQUpOY2cwRklBQWdBbXNpQmlBRlFTaHFUUTBGQzBHY0hVR2NIU2dDQUNBR2FpSUFOZ0lBUWFBZEtBSUFJQUJKQkVCQm9CMGdBRFlDQUFzQ1FFR0VHaWdDQUNJREJFQkJyQjBoQUFOQUlBSWdBQ2dDQUNJQklBQW9BZ1FpQkdwR0RRSWdBQ2dDQ0NJQURRQUxEQVFMUWZ3WktBSUFJZ0JCQUNBQUlBSk5HMFVFUUVIOEdTQUNOZ0lBQzBFQUlRQkJzQjBnQmpZQ0FFR3NIU0FDTmdJQVFZd2FRWDgyQWdCQmtCcEJ4QjBvQWdBMkFnQkJ1QjFCQURZQ0FBTkFJQUJCQTNRaUFVR2NHbW9nQVVHVUdtb2lCRFlDQUNBQlFhQWFhaUFFTmdJQUlBQkJBV29pQUVFZ1J3MEFDMEg0R1NBR1FTaHJJZ0JCZUNBQ2EwRUhjU0lCYXlJRU5nSUFRWVFhSUFFZ0Ftb2lBVFlDQUNBQklBUkJBWEkyQWdRZ0FDQUNha0VvTmdJRVFZZ2FRZFFkS0FJQU5nSUFEQVFMSUFJZ0EwMGdBU0FEUzNJTkFpQUFLQUlNUVFoeERRSWdBQ0FFSUFacU5nSUVRWVFhSUFOQmVDQURhMEVIY1NJQWFpSUJOZ0lBUWZnWlFmZ1pLQUlBSUFacUlnSWdBR3NpQURZQ0FDQUJJQUJCQVhJMkFnUWdBaUFEYWtFb05nSUVRWWdhUWRRZEtBSUFOZ0lBREFNTFFRQWhCQXdLQzBFQUlRSU1DQXRCL0Jrb0FnQWdBa3NFUUVIOEdTQUNOZ0lBQ3lBQ0lBWnFJUUZCckIwaEFBSkFBa0FDUUFOQUlBRWdBQ2dDQUVjRVFDQUFLQUlJSWdBTkFRd0NDd3NnQUMwQURFRUljVVVOQVF0QnJCMGhBQU5BSUFNZ0FDZ0NBQ0lCVHdSQUlBRWdBQ2dDQkdvaUJDQURTdzBEQ3lBQUtBSUlJUUFNQUFzQUN5QUFJQUkyQWdBZ0FDQUFLQUlFSUFacU5nSUVJQUpCZUNBQ2EwRUhjV29pQnlBRlFRTnlOZ0lFSUFGQmVDQUJhMEVIY1dvaUJpQUZJQWRxSWdWcklRQWdBeUFHUmdSQVFZUWFJQVUyQWdCQitCbEIrQmtvQWdBZ0FHb2lBRFlDQUNBRklBQkJBWEkyQWdRTUNBdEJnQm9vQWdBZ0JrWUVRRUdBR2lBRk5nSUFRZlFaUWZRWktBSUFJQUJxSWdBMkFnQWdCU0FBUVFGeU5nSUVJQUFnQldvZ0FEWUNBQXdJQ3lBR0tBSUVJZ05CQTNGQkFVY05CaUFEUVhoeElRa2dBMEgvQVUwRVFDQUdLQUlNSWdFZ0JpZ0NDQ0lDUmdSQVFld1pRZXdaS0FJQVFYNGdBMEVEZG5keE5nSUFEQWNMSUFJZ0FUWUNEQ0FCSUFJMkFnZ01CZ3NnQmlnQ0dDRUlJQVlnQmlnQ0RDSUNSd1JBSUFZb0FnZ2lBU0FDTmdJTUlBSWdBVFlDQ0F3RkN5QUdRUlJxSWdFb0FnQWlBMFVFUUNBR0tBSVFJZ05GRFFRZ0JrRVFhaUVCQ3dOQUlBRWhCQ0FESWdKQkZHb2lBU2dDQUNJRERRQWdBa0VRYWlFQklBSW9BaEFpQXcwQUN5QUVRUUEyQWdBTUJBdEIrQmtnQmtFb2F5SUFRWGdnQW10QkIzRWlBV3NpQ0RZQ0FFR0VHaUFCSUFKcUlnRTJBZ0FnQVNBSVFRRnlOZ0lFSUFBZ0FtcEJLRFlDQkVHSUdrSFVIU2dDQURZQ0FDQURJQVJCSnlBRWEwRUhjV3BCTDJzaUFDQUFJQU5CRUdwSkd5SUJRUnMyQWdRZ0FVRzBIU2tDQURjQ0VDQUJRYXdkS1FJQU53SUlRYlFkSUFGQkNHbzJBZ0JCc0IwZ0JqWUNBRUdzSFNBQ05nSUFRYmdkUVFBMkFnQWdBVUVZYWlFQUEwQWdBRUVITmdJRUlBQkJDR29oRENBQVFRUnFJUUFnRENBRVNRMEFDeUFCSUFOR0RRQWdBU0FCS0FJRVFYNXhOZ0lFSUFNZ0FTQURheUlDUVFGeU5nSUVJQUVnQWpZQ0FDQUNRZjhCVFFSQUlBSkJlSEZCbEJwcUlRQUNmMEhzR1NnQ0FDSUJRUUVnQWtFRGRuUWlBbkZGQkVCQjdCa2dBU0FDY2pZQ0FDQUFEQUVMSUFBb0FnZ0xJUUVnQUNBRE5nSUlJQUVnQXpZQ0RDQURJQUEyQWd3Z0F5QUJOZ0lJREFFTFFSOGhBQ0FDUWYvLy93ZE5CRUFnQWtFbUlBSkJDSFpuSWdCcmRrRUJjU0FBUVFGMGEwRSthaUVBQ3lBRElBQTJBaHdnQTBJQU53SVFJQUJCQW5SQm5CeHFJUUVDUUFKQVFmQVpLQUlBSWdSQkFTQUFkQ0lHY1VVRVFFSHdHU0FFSUFaeU5nSUFJQUVnQXpZQ0FBd0JDeUFDUVJrZ0FFRUJkbXRCQUNBQVFSOUhHM1FoQUNBQktBSUFJUVFEUUNBRUlnRW9BZ1JCZUhFZ0FrWU5BaUFBUVIxMklRUWdBRUVCZENFQUlBRWdCRUVFY1dvaUJpZ0NFQ0lFRFFBTElBWWdBellDRUFzZ0F5QUJOZ0lZSUFNZ0F6WUNEQ0FESUFNMkFnZ01BUXNnQVNnQ0NDSUFJQU0yQWd3Z0FTQUROZ0lJSUFOQkFEWUNHQ0FESUFFMkFnd2dBeUFBTmdJSUMwSDRHU2dDQUNJQUlBVk5EUUJCK0JrZ0FDQUZheUlCTmdJQVFZUWFRWVFhS0FJQUlnQWdCV29pQWpZQ0FDQUNJQUZCQVhJMkFnUWdBQ0FGUVFOeU5nSUVJQUJCQ0dvaEFBd0lDMEhvR1VFd05nSUFRUUFoQUF3SEMwRUFJUUlMSUFoRkRRQUNRQ0FHS0FJY0lnRkJBblJCbkJ4cUlnUW9BZ0FnQmtZRVFDQUVJQUkyQWdBZ0FnMEJRZkFaUWZBWktBSUFRWDRnQVhkeE5nSUFEQUlMSUFoQkVFRVVJQWdvQWhBZ0JrWWJhaUFDTmdJQUlBSkZEUUVMSUFJZ0NEWUNHQ0FHS0FJUUlnRUVRQ0FDSUFFMkFoQWdBU0FDTmdJWUN5QUdLQUlVSWdGRkRRQWdBaUFCTmdJVUlBRWdBallDR0FzZ0FDQUphaUVBSUFZZ0NXb2lCaWdDQkNFREN5QUdJQU5CZm5FMkFnUWdCU0FBUVFGeU5nSUVJQUFnQldvZ0FEWUNBQ0FBUWY4QlRRUkFJQUJCZUhGQmxCcHFJUUVDZjBIc0dTZ0NBQ0lDUVFFZ0FFRURkblFpQUhGRkJFQkI3QmtnQUNBQ2NqWUNBQ0FCREFFTElBRW9BZ2dMSVFBZ0FTQUZOZ0lJSUFBZ0JUWUNEQ0FGSUFFMkFnd2dCU0FBTmdJSURBRUxRUjhoQXlBQVFmLy8vd2ROQkVBZ0FFRW1JQUJCQ0habklnRnJka0VCY1NBQlFRRjBhMEUrYWlFREN5QUZJQU0yQWh3Z0JVSUFOd0lRSUFOQkFuUkJuQnhxSVFFQ1FBSkFRZkFaS0FJQUlnSkJBU0FEZENJRWNVVUVRRUh3R1NBQ0lBUnlOZ0lBSUFFZ0JUWUNBQXdCQ3lBQVFSa2dBMEVCZG10QkFDQURRUjlIRzNRaEF5QUJLQUlBSVFJRFFDQUNJZ0VvQWdSQmVIRWdBRVlOQWlBRFFSMTJJUUlnQTBFQmRDRURJQUVnQWtFRWNXb2lCQ2dDRUNJQ0RRQUxJQVFnQlRZQ0VBc2dCU0FCTmdJWUlBVWdCVFlDRENBRklBVTJBZ2dNQVFzZ0FTZ0NDQ0lBSUFVMkFnd2dBU0FGTmdJSUlBVkJBRFlDR0NBRklBRTJBZ3dnQlNBQU5nSUlDeUFIUVFocUlRQU1BZ3NDUUNBSFJRMEFBa0FnQkNnQ0hDSUFRUUowUVp3Y2FpSUJLQUlBSUFSR0JFQWdBU0FDTmdJQUlBSU5BVUh3R1NBSVFYNGdBSGR4SWdnMkFnQU1BZ3NnQjBFUVFSUWdCeWdDRUNBRVJodHFJQUkyQWdBZ0FrVU5BUXNnQWlBSE5nSVlJQVFvQWhBaUFBUkFJQUlnQURZQ0VDQUFJQUkyQWhnTElBUW9BaFFpQUVVTkFDQUNJQUEyQWhRZ0FDQUNOZ0lZQ3dKQUlBTkJEMDBFUUNBRUlBTWdCV29pQUVFRGNqWUNCQ0FBSUFScUlnQWdBQ2dDQkVFQmNqWUNCQXdCQ3lBRUlBVkJBM0kyQWdRZ0JDQUZhaUlDSUFOQkFYSTJBZ1FnQWlBRGFpQUROZ0lBSUFOQi93Rk5CRUFnQTBGNGNVR1VHbW9oQUFKL1Fld1pLQUlBSWdGQkFTQURRUU4yZENJRGNVVUVRRUhzR1NBQklBTnlOZ0lBSUFBTUFRc2dBQ2dDQ0FzaEFTQUFJQUkyQWdnZ0FTQUNOZ0lNSUFJZ0FEWUNEQ0FDSUFFMkFnZ01BUXRCSHlFQUlBTkIvLy8vQjAwRVFDQURRU1lnQTBFSWRtY2lBR3QyUVFGeElBQkJBWFJyUVQ1cUlRQUxJQUlnQURZQ0hDQUNRZ0EzQWhBZ0FFRUNkRUdjSEdvaEFRSkFBa0FnQ0VFQklBQjBJZ1p4UlFSQVFmQVpJQVlnQ0hJMkFnQWdBU0FDTmdJQURBRUxJQU5CR1NBQVFRRjJhMEVBSUFCQkgwY2JkQ0VBSUFFb0FnQWhCUU5BSUFVaUFTZ0NCRUY0Y1NBRFJnMENJQUJCSFhZaEJpQUFRUUYwSVFBZ0FTQUdRUVJ4YWlJR0tBSVFJZ1VOQUFzZ0JpQUNOZ0lRQ3lBQ0lBRTJBaGdnQWlBQ05nSU1JQUlnQWpZQ0NBd0JDeUFCS0FJSUlnQWdBallDRENBQklBSTJBZ2dnQWtFQU5nSVlJQUlnQVRZQ0RDQUNJQUEyQWdnTElBUkJDR29oQUF3QkN3SkFJQWxGRFFBQ1FDQUNLQUljSWdCQkFuUkJuQnhxSWdFb0FnQWdBa1lFUUNBQklBUTJBZ0FnQkEwQlFmQVpJQXRCZmlBQWQzRTJBZ0FNQWdzZ0NVRVFRUlFnQ1NnQ0VDQUNSaHRxSUFRMkFnQWdCRVVOQVFzZ0JDQUpOZ0lZSUFJb0FoQWlBQVJBSUFRZ0FEWUNFQ0FBSUFRMkFoZ0xJQUlvQWhRaUFFVU5BQ0FFSUFBMkFoUWdBQ0FFTmdJWUN3SkFJQU5CRDAwRVFDQUNJQU1nQldvaUFFRURjallDQkNBQUlBSnFJZ0FnQUNnQ0JFRUJjallDQkF3QkN5QUNJQVZCQTNJMkFnUWdBaUFGYWlJRUlBTkJBWEkyQWdRZ0F5QUVhaUFETmdJQUlBY0VRQ0FIUVhoeFFaUWFhaUVBUVlBYUtBSUFJUUVDZjBFQklBZEJBM1owSWdVZ0JuRkZCRUJCN0JrZ0JTQUdjallDQUNBQURBRUxJQUFvQWdnTElRWWdBQ0FCTmdJSUlBWWdBVFlDRENBQklBQTJBZ3dnQVNBR05nSUlDMEdBR2lBRU5nSUFRZlFaSUFNMkFnQUxJQUpCQ0dvaEFBc2dDa0VRYWlRQUlBQUxDK2NSQWdCQmdBZ0wxaEYxYm5OcFoyNWxaQ0J6YUc5eWRBQjFibk5wWjI1bFpDQnBiblFBWm14dllYUUFkV2x1ZERZMFgzUUFkVzV6YVdkdVpXUWdZMmhoY2dCaWIyOXNBR1Z0YzJOeWFYQjBaVzQ2T25aaGJBQjFibk5wWjI1bFpDQnNiMjVuQUhOMFpEbzZkM04wY21sdVp3QnpkR1E2T25OMGNtbHVad0J6ZEdRNk9uVXhObk4wY21sdVp3QnpkR1E2T25Vek1uTjBjbWx1WndCa2IzVmliR1VBZG05cFpBQmxiWE5qY21sd2RHVnVPanB0WlcxdmNubGZkbWxsZHp4emFHOXlkRDRBWlcxelkzSnBjSFJsYmpvNmJXVnRiM0o1WDNacFpYYzhkVzV6YVdkdVpXUWdjMmh2Y25RK0FHVnRjMk55YVhCMFpXNDZPbTFsYlc5eWVWOTJhV1YzUEdsdWRENEFaVzF6WTNKcGNIUmxiam82YldWdGIzSjVYM1pwWlhjOGRXNXphV2R1WldRZ2FXNTBQZ0JsYlhOamNtbHdkR1Z1T2pwdFpXMXZjbmxmZG1sbGR6eG1iRzloZEQ0QVpXMXpZM0pwY0hSbGJqbzZiV1Z0YjNKNVgzWnBaWGM4ZFdsdWREaGZkRDRBWlcxelkzSnBjSFJsYmpvNmJXVnRiM0o1WDNacFpYYzhhVzUwT0Y5MFBnQmxiWE5qY21sd2RHVnVPanB0WlcxdmNubGZkbWxsZHp4MWFXNTBNVFpmZEQ0QVpXMXpZM0pwY0hSbGJqbzZiV1Z0YjNKNVgzWnBaWGM4YVc1ME1UWmZkRDRBWlcxelkzSnBjSFJsYmpvNmJXVnRiM0o1WDNacFpYYzhkV2x1ZERZMFgzUStBR1Z0YzJOeWFYQjBaVzQ2T20xbGJXOXllVjkyYVdWM1BHbHVkRFkwWDNRK0FHVnRjMk55YVhCMFpXNDZPbTFsYlc5eWVWOTJhV1YzUEhWcGJuUXpNbDkwUGdCbGJYTmpjbWx3ZEdWdU9qcHRaVzF2Y25sZmRtbGxkenhwYm5Rek1sOTBQZ0JsYlhOamNtbHdkR1Z1T2pwdFpXMXZjbmxmZG1sbGR6eGphR0Z5UGdCbGJYTmpjbWx3ZEdWdU9qcHRaVzF2Y25sZmRtbGxkengxYm5OcFoyNWxaQ0JqYUdGeVBnQnpkR1E2T21KaGMybGpYM04wY21sdVp6eDFibk5wWjI1bFpDQmphR0Z5UGdCbGJYTmpjbWx3ZEdWdU9qcHRaVzF2Y25sZmRtbGxkenh6YVdkdVpXUWdZMmhoY2o0QVpXMXpZM0pwY0hSbGJqbzZiV1Z0YjNKNVgzWnBaWGM4Ykc5dVp6NEFaVzF6WTNKcGNIUmxiam82YldWdGIzSjVYM1pwWlhjOGRXNXphV2R1WldRZ2JHOXVaejRBWlcxelkzSnBjSFJsYmpvNmJXVnRiM0o1WDNacFpYYzhaRzkxWW14bFBnQk9VM1F6WDE4eU1USmlZWE5wWTE5emRISnBibWRKWTA1VFh6RXhZMmhoY2w5MGNtRnBkSE5KWTBWRlRsTmZPV0ZzYkc5allYUnZja2xqUlVWRlJRQUFBQUJFREFBQVFnY0FBRTVUZEROZlh6SXhNbUpoYzJsalgzTjBjbWx1WjBsb1RsTmZNVEZqYUdGeVgzUnlZV2wwYzBsb1JVVk9VMTg1WVd4c2IyTmhkRzl5U1doRlJVVkZBQUJFREFBQWpBY0FBRTVUZEROZlh6SXhNbUpoYzJsalgzTjBjbWx1WjBsM1RsTmZNVEZqYUdGeVgzUnlZV2wwYzBsM1JVVk9VMTg1WVd4c2IyTmhkRzl5U1hkRlJVVkZBQUJFREFBQTFBY0FBRTVUZEROZlh6SXhNbUpoYzJsalgzTjBjbWx1WjBsRWMwNVRYekV4WTJoaGNsOTBjbUZwZEhOSlJITkZSVTVUWHpsaGJHeHZZMkYwYjNKSlJITkZSVVZGQUFBQVJBd0FBQndJQUFCT1UzUXpYMTh5TVRKaVlYTnBZMTl6ZEhKcGJtZEpSR2xPVTE4eE1XTm9ZWEpmZEhKaGFYUnpTVVJwUlVWT1UxODVZV3hzYjJOaGRHOXlTVVJwUlVWRlJRQUFBRVFNQUFCb0NBQUFUakV3WlcxelkzSnBjSFJsYmpOMllXeEZBQUJFREFBQXRBZ0FBRTR4TUdWdGMyTnlhWEIwWlc0eE1XMWxiVzl5ZVY5MmFXVjNTV05GUlFBQVJBd0FBTkFJQUFCT01UQmxiWE5qY21sd2RHVnVNVEZ0WlcxdmNubGZkbWxsZDBsaFJVVUFBRVFNQUFENENBQUFUakV3WlcxelkzSnBjSFJsYmpFeGJXVnRiM0o1WDNacFpYZEphRVZGQUFCRURBQUFJQWtBQUU0eE1HVnRjMk55YVhCMFpXNHhNVzFsYlc5eWVWOTJhV1YzU1hORlJRQUFSQXdBQUVnSkFBQk9NVEJsYlhOamNtbHdkR1Z1TVRGdFpXMXZjbmxmZG1sbGQwbDBSVVVBQUVRTUFBQndDUUFBVGpFd1pXMXpZM0pwY0hSbGJqRXhiV1Z0YjNKNVgzWnBaWGRKYVVWRkFBQkVEQUFBbUFrQUFFNHhNR1Z0YzJOeWFYQjBaVzR4TVcxbGJXOXllVjkyYVdWM1NXcEZSUUFBUkF3QUFNQUpBQUJPTVRCbGJYTmpjbWx3ZEdWdU1URnRaVzF2Y25sZmRtbGxkMGxzUlVVQUFFUU1BQURvQ1FBQVRqRXdaVzF6WTNKcGNIUmxiakV4YldWdGIzSjVYM1pwWlhkSmJVVkZBQUJFREFBQUVBb0FBRTR4TUdWdGMyTnlhWEIwWlc0eE1XMWxiVzl5ZVY5MmFXVjNTWGhGUlFBQVJBd0FBRGdLQUFCT01UQmxiWE5qY21sd2RHVnVNVEZ0WlcxdmNubGZkbWxsZDBsNVJVVUFBRVFNQUFCZ0NnQUFUakV3WlcxelkzSnBjSFJsYmpFeGJXVnRiM0o1WDNacFpYZEpaa1ZGQUFCRURBQUFpQW9BQUU0eE1HVnRjMk55YVhCMFpXNHhNVzFsYlc5eWVWOTJhV1YzU1dSRlJRQUFSQXdBQUxBS0FBQk9NVEJmWDJONGVHRmlhWFl4TVRaZlgzTm9hVzFmZEhsd1pWOXBibVp2UlFBQUFBQnNEQUFBMkFvQUFOQU1BQUJPTVRCZlgyTjRlR0ZpYVhZeE1UZGZYMk5zWVhOelgzUjVjR1ZmYVc1bWIwVUFBQUJzREFBQUNBc0FBUHdLQUFBQUFBQUFmQXNBQUFJQUFBQURBQUFBQkFBQUFBVUFBQUFHQUFBQVRqRXdYMTlqZUhoaFltbDJNVEl6WDE5bWRXNWtZVzFsYm5SaGJGOTBlWEJsWDJsdVptOUZBR3dNQUFCVUN3QUEvQW9BQUhZQUFBQkFDd0FBaUFzQUFHSUFBQUJBQ3dBQWxBc0FBR01BQUFCQUN3QUFvQXNBQUdnQUFBQkFDd0FBckFzQUFHRUFBQUJBQ3dBQXVBc0FBSE1BQUFCQUN3QUF4QXNBQUhRQUFBQkFDd0FBMEFzQUFHa0FBQUJBQ3dBQTNBc0FBR29BQUFCQUN3QUE2QXNBQUd3QUFBQkFDd0FBOUFzQUFHMEFBQUJBQ3dBQUFBd0FBSGdBQUFCQUN3QUFEQXdBQUhrQUFBQkFDd0FBR0F3QUFHWUFBQUJBQ3dBQUpBd0FBR1FBQUFCQUN3QUFNQXdBQUFBQUFBQXNDd0FBQWdBQUFBY0FBQUFFQUFBQUJRQUFBQWdBQUFBSkFBQUFDZ0FBQUFzQUFBQUFBQUFBdEF3QUFBSUFBQUFNQUFBQUJBQUFBQVVBQUFBSUFBQUFEUUFBQUE0QUFBQVBBQUFBVGpFd1gxOWplSGhoWW1sMk1USXdYMTl6YVY5amJHRnpjMTkwZVhCbFgybHVabTlGQUFBQUFHd01BQUNNREFBQUxBc0FBRk4wT1hSNWNHVmZhVzVtYndBQUFBQkVEQUFBd0F3QVFkZ1pDd1BnRGdFPSI7aWYoIWlzRGF0YVVSSSh3YXNtQmluYXJ5RmlsZSkpe3dhc21CaW5hcnlGaWxlPWxvY2F0ZUZpbGUod2FzbUJpbmFyeUZpbGUpO31mdW5jdGlvbiBnZXRCaW5hcnlTeW5jKGZpbGUpe2lmKGZpbGU9PXdhc21CaW5hcnlGaWxlJiZ3YXNtQmluYXJ5KXtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkod2FzbUJpbmFyeSl9dmFyIGJpbmFyeT10cnlQYXJzZUFzRGF0YVVSSShmaWxlKTtpZihiaW5hcnkpe3JldHVybiBiaW5hcnl9aWYocmVhZEJpbmFyeSl7cmV0dXJuIHJlYWRCaW5hcnkoZmlsZSl9dGhyb3cgImJvdGggYXN5bmMgYW5kIHN5bmMgZmV0Y2hpbmcgb2YgdGhlIHdhc20gZmFpbGVkIn1mdW5jdGlvbiBnZXRCaW5hcnlQcm9taXNlKGJpbmFyeUZpbGUpe3JldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpPT5nZXRCaW5hcnlTeW5jKGJpbmFyeUZpbGUpKX1mdW5jdGlvbiBpbnN0YW50aWF0ZUFycmF5QnVmZmVyKGJpbmFyeUZpbGUsaW1wb3J0cyxyZWNlaXZlcil7cmV0dXJuIGdldEJpbmFyeVByb21pc2UoYmluYXJ5RmlsZSkudGhlbihiaW5hcnk9PldlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGJpbmFyeSxpbXBvcnRzKSkudGhlbihpbnN0YW5jZT0+aW5zdGFuY2UpLnRoZW4ocmVjZWl2ZXIscmVhc29uPT57ZXJyKGBmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiAke3JlYXNvbn1gKTthYm9ydChyZWFzb24pO30pfWZ1bmN0aW9uIGluc3RhbnRpYXRlQXN5bmMoYmluYXJ5LGJpbmFyeUZpbGUsaW1wb3J0cyxjYWxsYmFjayl7cmV0dXJuIGluc3RhbnRpYXRlQXJyYXlCdWZmZXIoYmluYXJ5RmlsZSxpbXBvcnRzLGNhbGxiYWNrKX1mdW5jdGlvbiBjcmVhdGVXYXNtKCl7dmFyIGluZm89eyJhIjp3YXNtSW1wb3J0c307ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbmNlKGluc3RhbmNlLG1vZHVsZSl7d2FzbUV4cG9ydHM9aW5zdGFuY2UuZXhwb3J0czt3YXNtTWVtb3J5PXdhc21FeHBvcnRzWyJrIl07dXBkYXRlTWVtb3J5Vmlld3MoKTthZGRPbkluaXQod2FzbUV4cG9ydHNbImwiXSk7cmVtb3ZlUnVuRGVwZW5kZW5jeSgpO3JldHVybiB3YXNtRXhwb3J0c31hZGRSdW5EZXBlbmRlbmN5KCk7ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbnRpYXRpb25SZXN1bHQocmVzdWx0KXtyZWNlaXZlSW5zdGFuY2UocmVzdWx0WyJpbnN0YW5jZSJdKTt9aWYoTW9kdWxlWyJpbnN0YW50aWF0ZVdhc20iXSl7dHJ5e3JldHVybiBNb2R1bGVbImluc3RhbnRpYXRlV2FzbSJdKGluZm8scmVjZWl2ZUluc3RhbmNlKX1jYXRjaChlKXtlcnIoYE1vZHVsZS5pbnN0YW50aWF0ZVdhc20gY2FsbGJhY2sgZmFpbGVkIHdpdGggZXJyb3I6ICR7ZX1gKTtyZWFkeVByb21pc2VSZWplY3QoZSk7fX1pbnN0YW50aWF0ZUFzeW5jKHdhc21CaW5hcnksd2FzbUJpbmFyeUZpbGUsaW5mbyxyZWNlaXZlSW5zdGFudGlhdGlvblJlc3VsdCkuY2F0Y2gocmVhZHlQcm9taXNlUmVqZWN0KTtyZXR1cm4ge319dmFyIGNhbGxSdW50aW1lQ2FsbGJhY2tzPWNhbGxiYWNrcz0+e3doaWxlKGNhbGxiYWNrcy5sZW5ndGg+MCl7Y2FsbGJhY2tzLnNoaWZ0KCkoTW9kdWxlKTt9fTtNb2R1bGVbIm5vRXhpdFJ1bnRpbWUiXXx8dHJ1ZTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfYmlnaW50PShwcmltaXRpdmVUeXBlLG5hbWUsc2l6ZSxtaW5SYW5nZSxtYXhSYW5nZSk9Pnt9O3ZhciBlbWJpbmRfaW5pdF9jaGFyQ29kZXM9KCk9Pnt2YXIgY29kZXM9bmV3IEFycmF5KDI1Nik7Zm9yKHZhciBpPTA7aTwyNTY7KytpKXtjb2Rlc1tpXT1TdHJpbmcuZnJvbUNoYXJDb2RlKGkpO31lbWJpbmRfY2hhckNvZGVzPWNvZGVzO307dmFyIGVtYmluZF9jaGFyQ29kZXM7dmFyIHJlYWRMYXRpbjFTdHJpbmc9cHRyPT57dmFyIHJldD0iIjt2YXIgYz1wdHI7d2hpbGUoSEVBUFU4W2NdKXtyZXQrPWVtYmluZF9jaGFyQ29kZXNbSEVBUFU4W2MrK11dO31yZXR1cm4gcmV0fTt2YXIgYXdhaXRpbmdEZXBlbmRlbmNpZXM9e307dmFyIHJlZ2lzdGVyZWRUeXBlcz17fTt2YXIgQmluZGluZ0Vycm9yO3ZhciB0aHJvd0JpbmRpbmdFcnJvcj1tZXNzYWdlPT57dGhyb3cgbmV3IEJpbmRpbmdFcnJvcihtZXNzYWdlKX07ZnVuY3Rpb24gc2hhcmVkUmVnaXN0ZXJUeXBlKHJhd1R5cGUscmVnaXN0ZXJlZEluc3RhbmNlLG9wdGlvbnM9e30pe3ZhciBuYW1lPXJlZ2lzdGVyZWRJbnN0YW5jZS5uYW1lO2lmKCFyYXdUeXBlKXt0aHJvd0JpbmRpbmdFcnJvcihgdHlwZSAiJHtuYW1lfSIgbXVzdCBoYXZlIGEgcG9zaXRpdmUgaW50ZWdlciB0eXBlaWQgcG9pbnRlcmApO31pZihyZWdpc3RlcmVkVHlwZXMuaGFzT3duUHJvcGVydHkocmF3VHlwZSkpe2lmKG9wdGlvbnMuaWdub3JlRHVwbGljYXRlUmVnaXN0cmF0aW9ucyl7cmV0dXJufWVsc2Uge3Rocm93QmluZGluZ0Vycm9yKGBDYW5ub3QgcmVnaXN0ZXIgdHlwZSAnJHtuYW1lfScgdHdpY2VgKTt9fXJlZ2lzdGVyZWRUeXBlc1tyYXdUeXBlXT1yZWdpc3RlcmVkSW5zdGFuY2U7aWYoYXdhaXRpbmdEZXBlbmRlbmNpZXMuaGFzT3duUHJvcGVydHkocmF3VHlwZSkpe3ZhciBjYWxsYmFja3M9YXdhaXRpbmdEZXBlbmRlbmNpZXNbcmF3VHlwZV07ZGVsZXRlIGF3YWl0aW5nRGVwZW5kZW5jaWVzW3Jhd1R5cGVdO2NhbGxiYWNrcy5mb3JFYWNoKGNiPT5jYigpKTt9fWZ1bmN0aW9uIHJlZ2lzdGVyVHlwZShyYXdUeXBlLHJlZ2lzdGVyZWRJbnN0YW5jZSxvcHRpb25zPXt9KXtpZighKCJhcmdQYWNrQWR2YW5jZSJpbiByZWdpc3RlcmVkSW5zdGFuY2UpKXt0aHJvdyBuZXcgVHlwZUVycm9yKCJyZWdpc3RlclR5cGUgcmVnaXN0ZXJlZEluc3RhbmNlIHJlcXVpcmVzIGFyZ1BhY2tBZHZhbmNlIil9cmV0dXJuIHNoYXJlZFJlZ2lzdGVyVHlwZShyYXdUeXBlLHJlZ2lzdGVyZWRJbnN0YW5jZSxvcHRpb25zKX12YXIgR2VuZXJpY1dpcmVUeXBlU2l6ZT04O3ZhciBfX2VtYmluZF9yZWdpc3Rlcl9ib29sPShyYXdUeXBlLG5hbWUsdHJ1ZVZhbHVlLGZhbHNlVmFsdWUpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3JlZ2lzdGVyVHlwZShyYXdUeXBlLHtuYW1lOm5hbWUsImZyb21XaXJlVHlwZSI6ZnVuY3Rpb24od3Qpe3JldHVybiAhIXd0fSwidG9XaXJlVHlwZSI6ZnVuY3Rpb24oZGVzdHJ1Y3RvcnMsbyl7cmV0dXJuIG8/dHJ1ZVZhbHVlOmZhbHNlVmFsdWV9LCJhcmdQYWNrQWR2YW5jZSI6R2VuZXJpY1dpcmVUeXBlU2l6ZSwicmVhZFZhbHVlRnJvbVBvaW50ZXIiOmZ1bmN0aW9uKHBvaW50ZXIpe3JldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShIRUFQVThbcG9pbnRlcl0pfSxkZXN0cnVjdG9yRnVuY3Rpb246bnVsbH0pO307ZnVuY3Rpb24gaGFuZGxlQWxsb2NhdG9ySW5pdCgpe09iamVjdC5hc3NpZ24oSGFuZGxlQWxsb2NhdG9yLnByb3RvdHlwZSx7Z2V0KGlkKXtyZXR1cm4gdGhpcy5hbGxvY2F0ZWRbaWRdfSxoYXMoaWQpe3JldHVybiB0aGlzLmFsbG9jYXRlZFtpZF0hPT11bmRlZmluZWR9LGFsbG9jYXRlKGhhbmRsZSl7dmFyIGlkPXRoaXMuZnJlZWxpc3QucG9wKCl8fHRoaXMuYWxsb2NhdGVkLmxlbmd0aDt0aGlzLmFsbG9jYXRlZFtpZF09aGFuZGxlO3JldHVybiBpZH0sZnJlZShpZCl7dGhpcy5hbGxvY2F0ZWRbaWRdPXVuZGVmaW5lZDt0aGlzLmZyZWVsaXN0LnB1c2goaWQpO319KTt9ZnVuY3Rpb24gSGFuZGxlQWxsb2NhdG9yKCl7dGhpcy5hbGxvY2F0ZWQ9W3VuZGVmaW5lZF07dGhpcy5mcmVlbGlzdD1bXTt9dmFyIGVtdmFsX2hhbmRsZXM9bmV3IEhhbmRsZUFsbG9jYXRvcjt2YXIgX19lbXZhbF9kZWNyZWY9aGFuZGxlPT57aWYoaGFuZGxlPj1lbXZhbF9oYW5kbGVzLnJlc2VydmVkJiYwPT09LS1lbXZhbF9oYW5kbGVzLmdldChoYW5kbGUpLnJlZmNvdW50KXtlbXZhbF9oYW5kbGVzLmZyZWUoaGFuZGxlKTt9fTt2YXIgY291bnRfZW12YWxfaGFuZGxlcz0oKT0+e3ZhciBjb3VudD0wO2Zvcih2YXIgaT1lbXZhbF9oYW5kbGVzLnJlc2VydmVkO2k8ZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWQubGVuZ3RoOysraSl7aWYoZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWRbaV0hPT11bmRlZmluZWQpeysrY291bnQ7fX1yZXR1cm4gY291bnR9O3ZhciBpbml0X2VtdmFsPSgpPT57ZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWQucHVzaCh7dmFsdWU6dW5kZWZpbmVkfSx7dmFsdWU6bnVsbH0se3ZhbHVlOnRydWV9LHt2YWx1ZTpmYWxzZX0pO2VtdmFsX2hhbmRsZXMucmVzZXJ2ZWQ9ZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWQubGVuZ3RoO01vZHVsZVsiY291bnRfZW12YWxfaGFuZGxlcyJdPWNvdW50X2VtdmFsX2hhbmRsZXM7fTt2YXIgRW12YWw9e3RvVmFsdWU6aGFuZGxlPT57aWYoIWhhbmRsZSl7dGhyb3dCaW5kaW5nRXJyb3IoIkNhbm5vdCB1c2UgZGVsZXRlZCB2YWwuIGhhbmRsZSA9ICIraGFuZGxlKTt9cmV0dXJuIGVtdmFsX2hhbmRsZXMuZ2V0KGhhbmRsZSkudmFsdWV9LHRvSGFuZGxlOnZhbHVlPT57c3dpdGNoKHZhbHVlKXtjYXNlIHVuZGVmaW5lZDpyZXR1cm4gMTtjYXNlIG51bGw6cmV0dXJuIDI7Y2FzZSB0cnVlOnJldHVybiAzO2Nhc2UgZmFsc2U6cmV0dXJuIDQ7ZGVmYXVsdDp7cmV0dXJuIGVtdmFsX2hhbmRsZXMuYWxsb2NhdGUoe3JlZmNvdW50OjEsdmFsdWU6dmFsdWV9KX19fX07ZnVuY3Rpb24gc2ltcGxlUmVhZFZhbHVlRnJvbVBvaW50ZXIocG9pbnRlcil7cmV0dXJuIHRoaXNbImZyb21XaXJlVHlwZSJdKEhFQVAzMltwb2ludGVyPj4yXSl9dmFyIF9fZW1iaW5kX3JlZ2lzdGVyX2VtdmFsPShyYXdUeXBlLG5hbWUpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3JlZ2lzdGVyVHlwZShyYXdUeXBlLHtuYW1lOm5hbWUsImZyb21XaXJlVHlwZSI6aGFuZGxlPT57dmFyIHJ2PUVtdmFsLnRvVmFsdWUoaGFuZGxlKTtfX2VtdmFsX2RlY3JlZihoYW5kbGUpO3JldHVybiBydn0sInRvV2lyZVR5cGUiOihkZXN0cnVjdG9ycyx2YWx1ZSk9PkVtdmFsLnRvSGFuZGxlKHZhbHVlKSwiYXJnUGFja0FkdmFuY2UiOkdlbmVyaWNXaXJlVHlwZVNpemUsInJlYWRWYWx1ZUZyb21Qb2ludGVyIjpzaW1wbGVSZWFkVmFsdWVGcm9tUG9pbnRlcixkZXN0cnVjdG9yRnVuY3Rpb246bnVsbH0pO307dmFyIGZsb2F0UmVhZFZhbHVlRnJvbVBvaW50ZXI9KG5hbWUsd2lkdGgpPT57c3dpdGNoKHdpZHRoKXtjYXNlIDQ6cmV0dXJuIGZ1bmN0aW9uKHBvaW50ZXIpe3JldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShIRUFQRjMyW3BvaW50ZXI+PjJdKX07Y2FzZSA4OnJldHVybiBmdW5jdGlvbihwb2ludGVyKXtyZXR1cm4gdGhpc1siZnJvbVdpcmVUeXBlIl0oSEVBUEY2NFtwb2ludGVyPj4zXSl9O2RlZmF1bHQ6dGhyb3cgbmV3IFR5cGVFcnJvcihgaW52YWxpZCBmbG9hdCB3aWR0aCAoJHt3aWR0aH0pOiAke25hbWV9YCl9fTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfZmxvYXQ9KHJhd1R5cGUsbmFtZSxzaXplKT0+e25hbWU9cmVhZExhdGluMVN0cmluZyhuYW1lKTtyZWdpc3RlclR5cGUocmF3VHlwZSx7bmFtZTpuYW1lLCJmcm9tV2lyZVR5cGUiOnZhbHVlPT52YWx1ZSwidG9XaXJlVHlwZSI6KGRlc3RydWN0b3JzLHZhbHVlKT0+dmFsdWUsImFyZ1BhY2tBZHZhbmNlIjpHZW5lcmljV2lyZVR5cGVTaXplLCJyZWFkVmFsdWVGcm9tUG9pbnRlciI6ZmxvYXRSZWFkVmFsdWVGcm9tUG9pbnRlcihuYW1lLHNpemUpLGRlc3RydWN0b3JGdW5jdGlvbjpudWxsfSk7fTt2YXIgaW50ZWdlclJlYWRWYWx1ZUZyb21Qb2ludGVyPShuYW1lLHdpZHRoLHNpZ25lZCk9Pntzd2l0Y2god2lkdGgpe2Nhc2UgMTpyZXR1cm4gc2lnbmVkP3BvaW50ZXI9PkhFQVA4W3BvaW50ZXI+PjBdOnBvaW50ZXI9PkhFQVBVOFtwb2ludGVyPj4wXTtjYXNlIDI6cmV0dXJuIHNpZ25lZD9wb2ludGVyPT5IRUFQMTZbcG9pbnRlcj4+MV06cG9pbnRlcj0+SEVBUFUxNltwb2ludGVyPj4xXTtjYXNlIDQ6cmV0dXJuIHNpZ25lZD9wb2ludGVyPT5IRUFQMzJbcG9pbnRlcj4+Ml06cG9pbnRlcj0+SEVBUFUzMltwb2ludGVyPj4yXTtkZWZhdWx0OnRocm93IG5ldyBUeXBlRXJyb3IoYGludmFsaWQgaW50ZWdlciB3aWR0aCAoJHt3aWR0aH0pOiAke25hbWV9YCl9fTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfaW50ZWdlcj0ocHJpbWl0aXZlVHlwZSxuYW1lLHNpemUsbWluUmFuZ2UsbWF4UmFuZ2UpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3ZhciBmcm9tV2lyZVR5cGU9dmFsdWU9PnZhbHVlO2lmKG1pblJhbmdlPT09MCl7dmFyIGJpdHNoaWZ0PTMyLTgqc2l6ZTtmcm9tV2lyZVR5cGU9dmFsdWU9PnZhbHVlPDxiaXRzaGlmdD4+PmJpdHNoaWZ0O312YXIgaXNVbnNpZ25lZFR5cGU9bmFtZS5pbmNsdWRlcygidW5zaWduZWQiKTt2YXIgY2hlY2tBc3NlcnRpb25zPSh2YWx1ZSx0b1R5cGVOYW1lKT0+e307dmFyIHRvV2lyZVR5cGU7aWYoaXNVbnNpZ25lZFR5cGUpe3RvV2lyZVR5cGU9ZnVuY3Rpb24oZGVzdHJ1Y3RvcnMsdmFsdWUpe2NoZWNrQXNzZXJ0aW9ucyh2YWx1ZSx0aGlzLm5hbWUpO3JldHVybiB2YWx1ZT4+PjB9O31lbHNlIHt0b1dpcmVUeXBlPWZ1bmN0aW9uKGRlc3RydWN0b3JzLHZhbHVlKXtjaGVja0Fzc2VydGlvbnModmFsdWUsdGhpcy5uYW1lKTtyZXR1cm4gdmFsdWV9O31yZWdpc3RlclR5cGUocHJpbWl0aXZlVHlwZSx7bmFtZTpuYW1lLCJmcm9tV2lyZVR5cGUiOmZyb21XaXJlVHlwZSwidG9XaXJlVHlwZSI6dG9XaXJlVHlwZSwiYXJnUGFja0FkdmFuY2UiOkdlbmVyaWNXaXJlVHlwZVNpemUsInJlYWRWYWx1ZUZyb21Qb2ludGVyIjppbnRlZ2VyUmVhZFZhbHVlRnJvbVBvaW50ZXIobmFtZSxzaXplLG1pblJhbmdlIT09MCksZGVzdHJ1Y3RvckZ1bmN0aW9uOm51bGx9KTt9O3ZhciBfX2VtYmluZF9yZWdpc3Rlcl9tZW1vcnlfdmlldz0ocmF3VHlwZSxkYXRhVHlwZUluZGV4LG5hbWUpPT57dmFyIHR5cGVNYXBwaW5nPVtJbnQ4QXJyYXksVWludDhBcnJheSxJbnQxNkFycmF5LFVpbnQxNkFycmF5LEludDMyQXJyYXksVWludDMyQXJyYXksRmxvYXQzMkFycmF5LEZsb2F0NjRBcnJheV07dmFyIFRBPXR5cGVNYXBwaW5nW2RhdGFUeXBlSW5kZXhdO2Z1bmN0aW9uIGRlY29kZU1lbW9yeVZpZXcoaGFuZGxlKXt2YXIgc2l6ZT1IRUFQVTMyW2hhbmRsZT4+Ml07dmFyIGRhdGE9SEVBUFUzMltoYW5kbGUrND4+Ml07cmV0dXJuIG5ldyBUQShIRUFQOC5idWZmZXIsZGF0YSxzaXplKX1uYW1lPXJlYWRMYXRpbjFTdHJpbmcobmFtZSk7cmVnaXN0ZXJUeXBlKHJhd1R5cGUse25hbWU6bmFtZSwiZnJvbVdpcmVUeXBlIjpkZWNvZGVNZW1vcnlWaWV3LCJhcmdQYWNrQWR2YW5jZSI6R2VuZXJpY1dpcmVUeXBlU2l6ZSwicmVhZFZhbHVlRnJvbVBvaW50ZXIiOmRlY29kZU1lbW9yeVZpZXd9LHtpZ25vcmVEdXBsaWNhdGVSZWdpc3RyYXRpb25zOnRydWV9KTt9O2Z1bmN0aW9uIHJlYWRQb2ludGVyKHBvaW50ZXIpe3JldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShIRUFQVTMyW3BvaW50ZXI+PjJdKX12YXIgc3RyaW5nVG9VVEY4QXJyYXk9KHN0cixoZWFwLG91dElkeCxtYXhCeXRlc1RvV3JpdGUpPT57aWYoIShtYXhCeXRlc1RvV3JpdGU+MCkpcmV0dXJuIDA7dmFyIHN0YXJ0SWR4PW91dElkeDt2YXIgZW5kSWR4PW91dElkeCttYXhCeXRlc1RvV3JpdGUtMTtmb3IodmFyIGk9MDtpPHN0ci5sZW5ndGg7KytpKXt2YXIgdT1zdHIuY2hhckNvZGVBdChpKTtpZih1Pj01NTI5NiYmdTw9NTczNDMpe3ZhciB1MT1zdHIuY2hhckNvZGVBdCgrK2kpO3U9NjU1MzYrKCh1JjEwMjMpPDwxMCl8dTEmMTAyMzt9aWYodTw9MTI3KXtpZihvdXRJZHg+PWVuZElkeClicmVhaztoZWFwW291dElkeCsrXT11O31lbHNlIGlmKHU8PTIwNDcpe2lmKG91dElkeCsxPj1lbmRJZHgpYnJlYWs7aGVhcFtvdXRJZHgrK109MTkyfHU+PjY7aGVhcFtvdXRJZHgrK109MTI4fHUmNjM7fWVsc2UgaWYodTw9NjU1MzUpe2lmKG91dElkeCsyPj1lbmRJZHgpYnJlYWs7aGVhcFtvdXRJZHgrK109MjI0fHU+PjEyO2hlYXBbb3V0SWR4KytdPTEyOHx1Pj42JjYzO2hlYXBbb3V0SWR4KytdPTEyOHx1JjYzO31lbHNlIHtpZihvdXRJZHgrMz49ZW5kSWR4KWJyZWFrO2hlYXBbb3V0SWR4KytdPTI0MHx1Pj4xODtoZWFwW291dElkeCsrXT0xMjh8dT4+MTImNjM7aGVhcFtvdXRJZHgrK109MTI4fHU+PjYmNjM7aGVhcFtvdXRJZHgrK109MTI4fHUmNjM7fX1oZWFwW291dElkeF09MDtyZXR1cm4gb3V0SWR4LXN0YXJ0SWR4fTt2YXIgc3RyaW5nVG9VVEY4PShzdHIsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk9PnN0cmluZ1RvVVRGOEFycmF5KHN0cixIRUFQVTgsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk7dmFyIGxlbmd0aEJ5dGVzVVRGOD1zdHI9Pnt2YXIgbGVuPTA7Zm9yKHZhciBpPTA7aTxzdHIubGVuZ3RoOysraSl7dmFyIGM9c3RyLmNoYXJDb2RlQXQoaSk7aWYoYzw9MTI3KXtsZW4rKzt9ZWxzZSBpZihjPD0yMDQ3KXtsZW4rPTI7fWVsc2UgaWYoYz49NTUyOTYmJmM8PTU3MzQzKXtsZW4rPTQ7KytpO31lbHNlIHtsZW4rPTM7fX1yZXR1cm4gbGVufTt2YXIgVVRGOERlY29kZXI9dHlwZW9mIFRleHREZWNvZGVyIT0idW5kZWZpbmVkIj9uZXcgVGV4dERlY29kZXIoInV0ZjgiKTp1bmRlZmluZWQ7dmFyIFVURjhBcnJheVRvU3RyaW5nPShoZWFwT3JBcnJheSxpZHgsbWF4Qnl0ZXNUb1JlYWQpPT57dmFyIGVuZElkeD1pZHgrbWF4Qnl0ZXNUb1JlYWQ7dmFyIGVuZFB0cj1pZHg7d2hpbGUoaGVhcE9yQXJyYXlbZW5kUHRyXSYmIShlbmRQdHI+PWVuZElkeCkpKytlbmRQdHI7aWYoZW5kUHRyLWlkeD4xNiYmaGVhcE9yQXJyYXkuYnVmZmVyJiZVVEY4RGVjb2Rlcil7cmV0dXJuIFVURjhEZWNvZGVyLmRlY29kZShoZWFwT3JBcnJheS5zdWJhcnJheShpZHgsZW5kUHRyKSl9dmFyIHN0cj0iIjt3aGlsZShpZHg8ZW5kUHRyKXt2YXIgdTA9aGVhcE9yQXJyYXlbaWR4KytdO2lmKCEodTAmMTI4KSl7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHUwKTtjb250aW51ZX12YXIgdTE9aGVhcE9yQXJyYXlbaWR4KytdJjYzO2lmKCh1MCYyMjQpPT0xOTIpe3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZSgodTAmMzEpPDw2fHUxKTtjb250aW51ZX12YXIgdTI9aGVhcE9yQXJyYXlbaWR4KytdJjYzO2lmKCh1MCYyNDApPT0yMjQpe3UwPSh1MCYxNSk8PDEyfHUxPDw2fHUyO31lbHNlIHt1MD0odTAmNyk8PDE4fHUxPDwxMnx1Mjw8NnxoZWFwT3JBcnJheVtpZHgrK10mNjM7fWlmKHUwPDY1NTM2KXtzdHIrPVN0cmluZy5mcm9tQ2hhckNvZGUodTApO31lbHNlIHt2YXIgY2g9dTAtNjU1MzY7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGNoPj4xMCw1NjMyMHxjaCYxMDIzKTt9fXJldHVybiBzdHJ9O3ZhciBVVEY4VG9TdHJpbmc9KHB0cixtYXhCeXRlc1RvUmVhZCk9PnB0cj9VVEY4QXJyYXlUb1N0cmluZyhIRUFQVTgscHRyLG1heEJ5dGVzVG9SZWFkKToiIjt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfc3RkX3N0cmluZz0ocmF3VHlwZSxuYW1lKT0+e25hbWU9cmVhZExhdGluMVN0cmluZyhuYW1lKTt2YXIgc3RkU3RyaW5nSXNVVEY4PW5hbWU9PT0ic3RkOjpzdHJpbmciO3JlZ2lzdGVyVHlwZShyYXdUeXBlLHtuYW1lOm5hbWUsImZyb21XaXJlVHlwZSIodmFsdWUpe3ZhciBsZW5ndGg9SEVBUFUzMlt2YWx1ZT4+Ml07dmFyIHBheWxvYWQ9dmFsdWUrNDt2YXIgc3RyO2lmKHN0ZFN0cmluZ0lzVVRGOCl7dmFyIGRlY29kZVN0YXJ0UHRyPXBheWxvYWQ7Zm9yKHZhciBpPTA7aTw9bGVuZ3RoOysraSl7dmFyIGN1cnJlbnRCeXRlUHRyPXBheWxvYWQraTtpZihpPT1sZW5ndGh8fEhFQVBVOFtjdXJyZW50Qnl0ZVB0cl09PTApe3ZhciBtYXhSZWFkPWN1cnJlbnRCeXRlUHRyLWRlY29kZVN0YXJ0UHRyO3ZhciBzdHJpbmdTZWdtZW50PVVURjhUb1N0cmluZyhkZWNvZGVTdGFydFB0cixtYXhSZWFkKTtpZihzdHI9PT11bmRlZmluZWQpe3N0cj1zdHJpbmdTZWdtZW50O31lbHNlIHtzdHIrPVN0cmluZy5mcm9tQ2hhckNvZGUoMCk7c3RyKz1zdHJpbmdTZWdtZW50O31kZWNvZGVTdGFydFB0cj1jdXJyZW50Qnl0ZVB0cisxO319fWVsc2Uge3ZhciBhPW5ldyBBcnJheShsZW5ndGgpO2Zvcih2YXIgaT0wO2k8bGVuZ3RoOysraSl7YVtpXT1TdHJpbmcuZnJvbUNoYXJDb2RlKEhFQVBVOFtwYXlsb2FkK2ldKTt9c3RyPWEuam9pbigiIik7fV9mcmVlKHZhbHVlKTtyZXR1cm4gc3RyfSwidG9XaXJlVHlwZSIoZGVzdHJ1Y3RvcnMsdmFsdWUpe2lmKHZhbHVlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpe3ZhbHVlPW5ldyBVaW50OEFycmF5KHZhbHVlKTt9dmFyIGxlbmd0aDt2YXIgdmFsdWVJc09mVHlwZVN0cmluZz10eXBlb2YgdmFsdWU9PSJzdHJpbmciO2lmKCEodmFsdWVJc09mVHlwZVN0cmluZ3x8dmFsdWUgaW5zdGFuY2VvZiBVaW50OEFycmF5fHx2YWx1ZSBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5fHx2YWx1ZSBpbnN0YW5jZW9mIEludDhBcnJheSkpe3Rocm93QmluZGluZ0Vycm9yKCJDYW5ub3QgcGFzcyBub24tc3RyaW5nIHRvIHN0ZDo6c3RyaW5nIik7fWlmKHN0ZFN0cmluZ0lzVVRGOCYmdmFsdWVJc09mVHlwZVN0cmluZyl7bGVuZ3RoPWxlbmd0aEJ5dGVzVVRGOCh2YWx1ZSk7fWVsc2Uge2xlbmd0aD12YWx1ZS5sZW5ndGg7fXZhciBiYXNlPV9tYWxsb2MoNCtsZW5ndGgrMSk7dmFyIHB0cj1iYXNlKzQ7SEVBUFUzMltiYXNlPj4yXT1sZW5ndGg7aWYoc3RkU3RyaW5nSXNVVEY4JiZ2YWx1ZUlzT2ZUeXBlU3RyaW5nKXtzdHJpbmdUb1VURjgodmFsdWUscHRyLGxlbmd0aCsxKTt9ZWxzZSB7aWYodmFsdWVJc09mVHlwZVN0cmluZyl7Zm9yKHZhciBpPTA7aTxsZW5ndGg7KytpKXt2YXIgY2hhckNvZGU9dmFsdWUuY2hhckNvZGVBdChpKTtpZihjaGFyQ29kZT4yNTUpe19mcmVlKHB0cik7dGhyb3dCaW5kaW5nRXJyb3IoIlN0cmluZyBoYXMgVVRGLTE2IGNvZGUgdW5pdHMgdGhhdCBkbyBub3QgZml0IGluIDggYml0cyIpO31IRUFQVThbcHRyK2ldPWNoYXJDb2RlO319ZWxzZSB7Zm9yKHZhciBpPTA7aTxsZW5ndGg7KytpKXtIRUFQVThbcHRyK2ldPXZhbHVlW2ldO319fWlmKGRlc3RydWN0b3JzIT09bnVsbCl7ZGVzdHJ1Y3RvcnMucHVzaChfZnJlZSxiYXNlKTt9cmV0dXJuIGJhc2V9LCJhcmdQYWNrQWR2YW5jZSI6R2VuZXJpY1dpcmVUeXBlU2l6ZSwicmVhZFZhbHVlRnJvbVBvaW50ZXIiOnJlYWRQb2ludGVyLGRlc3RydWN0b3JGdW5jdGlvbihwdHIpe19mcmVlKHB0cik7fX0pO307dmFyIFVURjE2RGVjb2Rlcj10eXBlb2YgVGV4dERlY29kZXIhPSJ1bmRlZmluZWQiP25ldyBUZXh0RGVjb2RlcigidXRmLTE2bGUiKTp1bmRlZmluZWQ7dmFyIFVURjE2VG9TdHJpbmc9KHB0cixtYXhCeXRlc1RvUmVhZCk9Pnt2YXIgZW5kUHRyPXB0cjt2YXIgaWR4PWVuZFB0cj4+MTt2YXIgbWF4SWR4PWlkeCttYXhCeXRlc1RvUmVhZC8yO3doaWxlKCEoaWR4Pj1tYXhJZHgpJiZIRUFQVTE2W2lkeF0pKytpZHg7ZW5kUHRyPWlkeDw8MTtpZihlbmRQdHItcHRyPjMyJiZVVEYxNkRlY29kZXIpcmV0dXJuIFVURjE2RGVjb2Rlci5kZWNvZGUoSEVBUFU4LnN1YmFycmF5KHB0cixlbmRQdHIpKTt2YXIgc3RyPSIiO2Zvcih2YXIgaT0wOyEoaT49bWF4Qnl0ZXNUb1JlYWQvMik7KytpKXt2YXIgY29kZVVuaXQ9SEVBUDE2W3B0citpKjI+PjFdO2lmKGNvZGVVbml0PT0wKWJyZWFrO3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZShjb2RlVW5pdCk7fXJldHVybiBzdHJ9O3ZhciBzdHJpbmdUb1VURjE2PShzdHIsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk9PntpZihtYXhCeXRlc1RvV3JpdGU9PT11bmRlZmluZWQpe21heEJ5dGVzVG9Xcml0ZT0yMTQ3NDgzNjQ3O31pZihtYXhCeXRlc1RvV3JpdGU8MilyZXR1cm4gMDttYXhCeXRlc1RvV3JpdGUtPTI7dmFyIHN0YXJ0UHRyPW91dFB0cjt2YXIgbnVtQ2hhcnNUb1dyaXRlPW1heEJ5dGVzVG9Xcml0ZTxzdHIubGVuZ3RoKjI/bWF4Qnl0ZXNUb1dyaXRlLzI6c3RyLmxlbmd0aDtmb3IodmFyIGk9MDtpPG51bUNoYXJzVG9Xcml0ZTsrK2kpe3ZhciBjb2RlVW5pdD1zdHIuY2hhckNvZGVBdChpKTtIRUFQMTZbb3V0UHRyPj4xXT1jb2RlVW5pdDtvdXRQdHIrPTI7fUhFQVAxNltvdXRQdHI+PjFdPTA7cmV0dXJuIG91dFB0ci1zdGFydFB0cn07dmFyIGxlbmd0aEJ5dGVzVVRGMTY9c3RyPT5zdHIubGVuZ3RoKjI7dmFyIFVURjMyVG9TdHJpbmc9KHB0cixtYXhCeXRlc1RvUmVhZCk9Pnt2YXIgaT0wO3ZhciBzdHI9IiI7d2hpbGUoIShpPj1tYXhCeXRlc1RvUmVhZC80KSl7dmFyIHV0ZjMyPUhFQVAzMltwdHIraSo0Pj4yXTtpZih1dGYzMj09MClicmVhazsrK2k7aWYodXRmMzI+PTY1NTM2KXt2YXIgY2g9dXRmMzItNjU1MzY7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGNoPj4xMCw1NjMyMHxjaCYxMDIzKTt9ZWxzZSB7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHV0ZjMyKTt9fXJldHVybiBzdHJ9O3ZhciBzdHJpbmdUb1VURjMyPShzdHIsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk9PntpZihtYXhCeXRlc1RvV3JpdGU9PT11bmRlZmluZWQpe21heEJ5dGVzVG9Xcml0ZT0yMTQ3NDgzNjQ3O31pZihtYXhCeXRlc1RvV3JpdGU8NClyZXR1cm4gMDt2YXIgc3RhcnRQdHI9b3V0UHRyO3ZhciBlbmRQdHI9c3RhcnRQdHIrbWF4Qnl0ZXNUb1dyaXRlLTQ7Zm9yKHZhciBpPTA7aTxzdHIubGVuZ3RoOysraSl7dmFyIGNvZGVVbml0PXN0ci5jaGFyQ29kZUF0KGkpO2lmKGNvZGVVbml0Pj01NTI5NiYmY29kZVVuaXQ8PTU3MzQzKXt2YXIgdHJhaWxTdXJyb2dhdGU9c3RyLmNoYXJDb2RlQXQoKytpKTtjb2RlVW5pdD02NTUzNisoKGNvZGVVbml0JjEwMjMpPDwxMCl8dHJhaWxTdXJyb2dhdGUmMTAyMzt9SEVBUDMyW291dFB0cj4+Ml09Y29kZVVuaXQ7b3V0UHRyKz00O2lmKG91dFB0cis0PmVuZFB0cilicmVha31IRUFQMzJbb3V0UHRyPj4yXT0wO3JldHVybiBvdXRQdHItc3RhcnRQdHJ9O3ZhciBsZW5ndGhCeXRlc1VURjMyPXN0cj0+e3ZhciBsZW49MDtmb3IodmFyIGk9MDtpPHN0ci5sZW5ndGg7KytpKXt2YXIgY29kZVVuaXQ9c3RyLmNoYXJDb2RlQXQoaSk7aWYoY29kZVVuaXQ+PTU1Mjk2JiZjb2RlVW5pdDw9NTczNDMpKytpO2xlbis9NDt9cmV0dXJuIGxlbn07dmFyIF9fZW1iaW5kX3JlZ2lzdGVyX3N0ZF93c3RyaW5nPShyYXdUeXBlLGNoYXJTaXplLG5hbWUpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3ZhciBkZWNvZGVTdHJpbmcsZW5jb2RlU3RyaW5nLGdldEhlYXAsbGVuZ3RoQnl0ZXNVVEYsc2hpZnQ7aWYoY2hhclNpemU9PT0yKXtkZWNvZGVTdHJpbmc9VVRGMTZUb1N0cmluZztlbmNvZGVTdHJpbmc9c3RyaW5nVG9VVEYxNjtsZW5ndGhCeXRlc1VURj1sZW5ndGhCeXRlc1VURjE2O2dldEhlYXA9KCk9PkhFQVBVMTY7c2hpZnQ9MTt9ZWxzZSBpZihjaGFyU2l6ZT09PTQpe2RlY29kZVN0cmluZz1VVEYzMlRvU3RyaW5nO2VuY29kZVN0cmluZz1zdHJpbmdUb1VURjMyO2xlbmd0aEJ5dGVzVVRGPWxlbmd0aEJ5dGVzVVRGMzI7Z2V0SGVhcD0oKT0+SEVBUFUzMjtzaGlmdD0yO31yZWdpc3RlclR5cGUocmF3VHlwZSx7bmFtZTpuYW1lLCJmcm9tV2lyZVR5cGUiOnZhbHVlPT57dmFyIGxlbmd0aD1IRUFQVTMyW3ZhbHVlPj4yXTt2YXIgSEVBUD1nZXRIZWFwKCk7dmFyIHN0cjt2YXIgZGVjb2RlU3RhcnRQdHI9dmFsdWUrNDtmb3IodmFyIGk9MDtpPD1sZW5ndGg7KytpKXt2YXIgY3VycmVudEJ5dGVQdHI9dmFsdWUrNCtpKmNoYXJTaXplO2lmKGk9PWxlbmd0aHx8SEVBUFtjdXJyZW50Qnl0ZVB0cj4+c2hpZnRdPT0wKXt2YXIgbWF4UmVhZEJ5dGVzPWN1cnJlbnRCeXRlUHRyLWRlY29kZVN0YXJ0UHRyO3ZhciBzdHJpbmdTZWdtZW50PWRlY29kZVN0cmluZyhkZWNvZGVTdGFydFB0cixtYXhSZWFkQnl0ZXMpO2lmKHN0cj09PXVuZGVmaW5lZCl7c3RyPXN0cmluZ1NlZ21lbnQ7fWVsc2Uge3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZSgwKTtzdHIrPXN0cmluZ1NlZ21lbnQ7fWRlY29kZVN0YXJ0UHRyPWN1cnJlbnRCeXRlUHRyK2NoYXJTaXplO319X2ZyZWUodmFsdWUpO3JldHVybiBzdHJ9LCJ0b1dpcmVUeXBlIjooZGVzdHJ1Y3RvcnMsdmFsdWUpPT57aWYoISh0eXBlb2YgdmFsdWU9PSJzdHJpbmciKSl7dGhyb3dCaW5kaW5nRXJyb3IoYENhbm5vdCBwYXNzIG5vbi1zdHJpbmcgdG8gQysrIHN0cmluZyB0eXBlICR7bmFtZX1gKTt9dmFyIGxlbmd0aD1sZW5ndGhCeXRlc1VURih2YWx1ZSk7dmFyIHB0cj1fbWFsbG9jKDQrbGVuZ3RoK2NoYXJTaXplKTtIRUFQVTMyW3B0cj4+Ml09bGVuZ3RoPj5zaGlmdDtlbmNvZGVTdHJpbmcodmFsdWUscHRyKzQsbGVuZ3RoK2NoYXJTaXplKTtpZihkZXN0cnVjdG9ycyE9PW51bGwpe2Rlc3RydWN0b3JzLnB1c2goX2ZyZWUscHRyKTt9cmV0dXJuIHB0cn0sImFyZ1BhY2tBZHZhbmNlIjpHZW5lcmljV2lyZVR5cGVTaXplLCJyZWFkVmFsdWVGcm9tUG9pbnRlciI6c2ltcGxlUmVhZFZhbHVlRnJvbVBvaW50ZXIsZGVzdHJ1Y3RvckZ1bmN0aW9uKHB0cil7X2ZyZWUocHRyKTt9fSk7fTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfdm9pZD0ocmF3VHlwZSxuYW1lKT0+e25hbWU9cmVhZExhdGluMVN0cmluZyhuYW1lKTtyZWdpc3RlclR5cGUocmF3VHlwZSx7aXNWb2lkOnRydWUsbmFtZTpuYW1lLCJhcmdQYWNrQWR2YW5jZSI6MCwiZnJvbVdpcmVUeXBlIjooKT0+dW5kZWZpbmVkLCJ0b1dpcmVUeXBlIjooZGVzdHJ1Y3RvcnMsbyk9PnVuZGVmaW5lZH0pO307dmFyIGdldEhlYXBNYXg9KCk9PjIxNDc0ODM2NDg7dmFyIGdyb3dNZW1vcnk9c2l6ZT0+e3ZhciBiPXdhc21NZW1vcnkuYnVmZmVyO3ZhciBwYWdlcz0oc2l6ZS1iLmJ5dGVMZW5ndGgrNjU1MzUpLzY1NTM2O3RyeXt3YXNtTWVtb3J5Lmdyb3cocGFnZXMpO3VwZGF0ZU1lbW9yeVZpZXdzKCk7cmV0dXJuIDF9Y2F0Y2goZSl7fX07dmFyIF9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwPXJlcXVlc3RlZFNpemU9Pnt2YXIgb2xkU2l6ZT1IRUFQVTgubGVuZ3RoO3JlcXVlc3RlZFNpemU+Pj49MDt2YXIgbWF4SGVhcFNpemU9Z2V0SGVhcE1heCgpO2lmKHJlcXVlc3RlZFNpemU+bWF4SGVhcFNpemUpe3JldHVybiBmYWxzZX12YXIgYWxpZ25VcD0oeCxtdWx0aXBsZSk9PngrKG11bHRpcGxlLXglbXVsdGlwbGUpJW11bHRpcGxlO2Zvcih2YXIgY3V0RG93bj0xO2N1dERvd248PTQ7Y3V0RG93bio9Mil7dmFyIG92ZXJHcm93bkhlYXBTaXplPW9sZFNpemUqKDErLjIvY3V0RG93bik7b3Zlckdyb3duSGVhcFNpemU9TWF0aC5taW4ob3Zlckdyb3duSGVhcFNpemUscmVxdWVzdGVkU2l6ZSsxMDA2NjMyOTYpO3ZhciBuZXdTaXplPU1hdGgubWluKG1heEhlYXBTaXplLGFsaWduVXAoTWF0aC5tYXgocmVxdWVzdGVkU2l6ZSxvdmVyR3Jvd25IZWFwU2l6ZSksNjU1MzYpKTt2YXIgcmVwbGFjZW1lbnQ9Z3Jvd01lbW9yeShuZXdTaXplKTtpZihyZXBsYWNlbWVudCl7cmV0dXJuIHRydWV9fXJldHVybiBmYWxzZX07ZW1iaW5kX2luaXRfY2hhckNvZGVzKCk7QmluZGluZ0Vycm9yPU1vZHVsZVsiQmluZGluZ0Vycm9yIl09Y2xhc3MgQmluZGluZ0Vycm9yIGV4dGVuZHMgRXJyb3J7Y29uc3RydWN0b3IobWVzc2FnZSl7c3VwZXIobWVzc2FnZSk7dGhpcy5uYW1lPSJCaW5kaW5nRXJyb3IiO319O01vZHVsZVsiSW50ZXJuYWxFcnJvciJdPWNsYXNzIEludGVybmFsRXJyb3IgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3RvcihtZXNzYWdlKXtzdXBlcihtZXNzYWdlKTt0aGlzLm5hbWU9IkludGVybmFsRXJyb3IiO319O2hhbmRsZUFsbG9jYXRvckluaXQoKTtpbml0X2VtdmFsKCk7dmFyIHdhc21JbXBvcnRzPXtmOl9fZW1iaW5kX3JlZ2lzdGVyX2JpZ2ludCxpOl9fZW1iaW5kX3JlZ2lzdGVyX2Jvb2wsaDpfX2VtYmluZF9yZWdpc3Rlcl9lbXZhbCxlOl9fZW1iaW5kX3JlZ2lzdGVyX2Zsb2F0LGI6X19lbWJpbmRfcmVnaXN0ZXJfaW50ZWdlcixhOl9fZW1iaW5kX3JlZ2lzdGVyX21lbW9yeV92aWV3LGQ6X19lbWJpbmRfcmVnaXN0ZXJfc3RkX3N0cmluZyxjOl9fZW1iaW5kX3JlZ2lzdGVyX3N0ZF93c3RyaW5nLGo6X19lbWJpbmRfcmVnaXN0ZXJfdm9pZCxnOl9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwfTt2YXIgd2FzbUV4cG9ydHM9Y3JlYXRlV2FzbSgpO01vZHVsZVsiX3BhY2siXT0oYTAsYTEsYTIsYTMsYTQsYTUsYTYsYTcsYTgsYTksYTEwKT0+KE1vZHVsZVsiX3BhY2siXT13YXNtRXhwb3J0c1sibSJdKShhMCxhMSxhMixhMyxhNCxhNSxhNixhNyxhOCxhOSxhMTApO01vZHVsZVsiX19lbWJpbmRfaW5pdGlhbGl6ZV9iaW5kaW5ncyJdPSgpPT4oTW9kdWxlWyJfX2VtYmluZF9pbml0aWFsaXplX2JpbmRpbmdzIl09d2FzbUV4cG9ydHNbIm4iXSkoKTt2YXIgX21hbGxvYz1Nb2R1bGVbIl9tYWxsb2MiXT1hMD0+KF9tYWxsb2M9TW9kdWxlWyJfbWFsbG9jIl09d2FzbUV4cG9ydHNbInAiXSkoYTApO3ZhciBfZnJlZT1Nb2R1bGVbIl9mcmVlIl09YTA9PihfZnJlZT1Nb2R1bGVbIl9mcmVlIl09d2FzbUV4cG9ydHNbInEiXSkoYTApO2Z1bmN0aW9uIGludEFycmF5RnJvbUJhc2U2NChzKXt2YXIgZGVjb2RlZD1hdG9iKHMpO3ZhciBieXRlcz1uZXcgVWludDhBcnJheShkZWNvZGVkLmxlbmd0aCk7Zm9yKHZhciBpPTA7aTxkZWNvZGVkLmxlbmd0aDsrK2kpe2J5dGVzW2ldPWRlY29kZWQuY2hhckNvZGVBdChpKTt9cmV0dXJuIGJ5dGVzfWZ1bmN0aW9uIHRyeVBhcnNlQXNEYXRhVVJJKGZpbGVuYW1lKXtpZighaXNEYXRhVVJJKGZpbGVuYW1lKSl7cmV0dXJufXJldHVybiBpbnRBcnJheUZyb21CYXNlNjQoZmlsZW5hbWUuc2xpY2UoZGF0YVVSSVByZWZpeC5sZW5ndGgpKX12YXIgY2FsbGVkUnVuO2RlcGVuZGVuY2llc0Z1bGZpbGxlZD1mdW5jdGlvbiBydW5DYWxsZXIoKXtpZighY2FsbGVkUnVuKXJ1bigpO2lmKCFjYWxsZWRSdW4pZGVwZW5kZW5jaWVzRnVsZmlsbGVkPXJ1bkNhbGxlcjt9O2Z1bmN0aW9uIHJ1bigpe2lmKHJ1bkRlcGVuZGVuY2llcz4wKXtyZXR1cm59cHJlUnVuKCk7aWYocnVuRGVwZW5kZW5jaWVzPjApe3JldHVybn1mdW5jdGlvbiBkb1J1bigpe2lmKGNhbGxlZFJ1bilyZXR1cm47Y2FsbGVkUnVuPXRydWU7TW9kdWxlWyJjYWxsZWRSdW4iXT10cnVlO2lmKEFCT1JUKXJldHVybjtpbml0UnVudGltZSgpO3JlYWR5UHJvbWlzZVJlc29sdmUoTW9kdWxlKTtpZihNb2R1bGVbIm9uUnVudGltZUluaXRpYWxpemVkIl0pTW9kdWxlWyJvblJ1bnRpbWVJbml0aWFsaXplZCJdKCk7cG9zdFJ1bigpO31pZihNb2R1bGVbInNldFN0YXR1cyJdKXtNb2R1bGVbInNldFN0YXR1cyJdKCJSdW5uaW5nLi4uIik7c2V0VGltZW91dChmdW5jdGlvbigpe3NldFRpbWVvdXQoZnVuY3Rpb24oKXtNb2R1bGVbInNldFN0YXR1cyJdKCIiKTt9LDEpO2RvUnVuKCk7fSwxKTt9ZWxzZSB7ZG9SdW4oKTt9fWlmKE1vZHVsZVsicHJlSW5pdCJdKXtpZih0eXBlb2YgTW9kdWxlWyJwcmVJbml0Il09PSJmdW5jdGlvbiIpTW9kdWxlWyJwcmVJbml0Il09W01vZHVsZVsicHJlSW5pdCJdXTt3aGlsZShNb2R1bGVbInByZUluaXQiXS5sZW5ndGg+MCl7TW9kdWxlWyJwcmVJbml0Il0ucG9wKCkoKTt9fXJ1bigpOwoKCiAgICByZXR1cm4gbW9kdWxlQXJnLnJlYWR5CiAgfQoKICApOwogIH0pKCk7CgogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55CiAgbGV0IHdhc21Nb2R1bGU7CiAgYXN5bmMgZnVuY3Rpb24gaW5pdFdhc20oKSB7CiAgICAgIHdhc21Nb2R1bGUgPSBhd2FpdCBsb2FkV2FzbSgpOwogIH0KICBsZXQgYWxsb2NhdGVkVmVydGV4Q291bnQgPSAwOwogIGNvbnN0IHVwZGF0ZVF1ZXVlID0gbmV3IEFycmF5KCk7CiAgbGV0IHJ1bm5pbmcgPSBmYWxzZTsKICBsZXQgbG9hZGluZyA9IGZhbHNlOwogIGxldCBwb3NpdGlvbnNQdHI7CiAgbGV0IHJvdGF0aW9uc1B0cjsKICBsZXQgc2NhbGVzUHRyOwogIGxldCBjb2xvcnNQdHI7CiAgbGV0IHNlbGVjdGlvblB0cjsKICBsZXQgZGF0YVB0cjsKICBsZXQgd29ybGRQb3NpdGlvbnNQdHI7CiAgbGV0IHdvcmxkUm90YXRpb25zUHRyOwogIGxldCB3b3JsZFNjYWxlc1B0cjsKICBjb25zdCBwYWNrID0gYXN5bmMgKHNwbGF0KSA9PiB7CiAgICAgIHdoaWxlIChsb2FkaW5nKSB7CiAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAwKSk7CiAgICAgIH0KICAgICAgaWYgKCF3YXNtTW9kdWxlKSB7CiAgICAgICAgICBsb2FkaW5nID0gdHJ1ZTsKICAgICAgICAgIGF3YWl0IGluaXRXYXNtKCk7CiAgICAgICAgICBsb2FkaW5nID0gZmFsc2U7CiAgICAgIH0KICAgICAgY29uc3QgdGFyZ2V0QWxsb2NhdGVkVmVydGV4Q291bnQgPSBNYXRoLnBvdygyLCBNYXRoLmNlaWwoTWF0aC5sb2cyKHNwbGF0LnZlcnRleENvdW50KSkpOwogICAgICBpZiAodGFyZ2V0QWxsb2NhdGVkVmVydGV4Q291bnQgPiBhbGxvY2F0ZWRWZXJ0ZXhDb3VudCkgewogICAgICAgICAgaWYgKGFsbG9jYXRlZFZlcnRleENvdW50ID4gMCkgewogICAgICAgICAgICAgIHdhc21Nb2R1bGUuX2ZyZWUocG9zaXRpb25zUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHJvdGF0aW9uc1B0cik7CiAgICAgICAgICAgICAgd2FzbU1vZHVsZS5fZnJlZShzY2FsZXNQdHIpOwogICAgICAgICAgICAgIHdhc21Nb2R1bGUuX2ZyZWUoY29sb3JzUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHNlbGVjdGlvblB0cik7CiAgICAgICAgICAgICAgd2FzbU1vZHVsZS5fZnJlZShkYXRhUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHdvcmxkUG9zaXRpb25zUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHdvcmxkUm90YXRpb25zUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHdvcmxkU2NhbGVzUHRyKTsKICAgICAgICAgIH0KICAgICAgICAgIGFsbG9jYXRlZFZlcnRleENvdW50ID0gdGFyZ2V0QWxsb2NhdGVkVmVydGV4Q291bnQ7CiAgICAgICAgICBwb3NpdGlvbnNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoMyAqIGFsbG9jYXRlZFZlcnRleENvdW50ICogNCk7CiAgICAgICAgICByb3RhdGlvbnNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoNCAqIGFsbG9jYXRlZFZlcnRleENvdW50ICogNCk7CiAgICAgICAgICBzY2FsZXNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoMyAqIGFsbG9jYXRlZFZlcnRleENvdW50ICogNCk7CiAgICAgICAgICBjb2xvcnNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoNCAqIGFsbG9jYXRlZFZlcnRleENvdW50KTsKICAgICAgICAgIHNlbGVjdGlvblB0ciA9IHdhc21Nb2R1bGUuX21hbGxvYyhhbGxvY2F0ZWRWZXJ0ZXhDb3VudCk7CiAgICAgICAgICBkYXRhUHRyID0gd2FzbU1vZHVsZS5fbWFsbG9jKDggKiBhbGxvY2F0ZWRWZXJ0ZXhDb3VudCAqIDQpOwogICAgICAgICAgd29ybGRQb3NpdGlvbnNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoMyAqIGFsbG9jYXRlZFZlcnRleENvdW50ICogNCk7CiAgICAgICAgICB3b3JsZFJvdGF0aW9uc1B0ciA9IHdhc21Nb2R1bGUuX21hbGxvYyg0ICogYWxsb2NhdGVkVmVydGV4Q291bnQgKiA0KTsKICAgICAgICAgIHdvcmxkU2NhbGVzUHRyID0gd2FzbU1vZHVsZS5fbWFsbG9jKDMgKiBhbGxvY2F0ZWRWZXJ0ZXhDb3VudCAqIDQpOwogICAgICB9CiAgICAgIHdhc21Nb2R1bGUuSEVBUEYzMi5zZXQoc3BsYXQucG9zaXRpb25zLCBwb3NpdGlvbnNQdHIgLyA0KTsKICAgICAgd2FzbU1vZHVsZS5IRUFQRjMyLnNldChzcGxhdC5yb3RhdGlvbnMsIHJvdGF0aW9uc1B0ciAvIDQpOwogICAgICB3YXNtTW9kdWxlLkhFQVBGMzIuc2V0KHNwbGF0LnNjYWxlcywgc2NhbGVzUHRyIC8gNCk7CiAgICAgIHdhc21Nb2R1bGUuSEVBUFU4LnNldChzcGxhdC5jb2xvcnMsIGNvbG9yc1B0cik7CiAgICAgIHdhc21Nb2R1bGUuSEVBUFU4LnNldChzcGxhdC5zZWxlY3Rpb24sIHNlbGVjdGlvblB0cik7CiAgICAgIHdhc21Nb2R1bGUuX3BhY2soc3BsYXQuc2VsZWN0ZWQsIHNwbGF0LnZlcnRleENvdW50LCBwb3NpdGlvbnNQdHIsIHJvdGF0aW9uc1B0ciwgc2NhbGVzUHRyLCBjb2xvcnNQdHIsIHNlbGVjdGlvblB0ciwgZGF0YVB0ciwgd29ybGRQb3NpdGlvbnNQdHIsIHdvcmxkUm90YXRpb25zUHRyLCB3b3JsZFNjYWxlc1B0cik7CiAgICAgIGNvbnN0IG91dERhdGEgPSBuZXcgVWludDMyQXJyYXkod2FzbU1vZHVsZS5IRUFQVTMyLmJ1ZmZlciwgZGF0YVB0ciwgc3BsYXQudmVydGV4Q291bnQgKiA4KTsKICAgICAgY29uc3QgZGV0YWNoZWREYXRhID0gbmV3IFVpbnQzMkFycmF5KG91dERhdGEuc2xpY2UoKS5idWZmZXIpOwogICAgICBjb25zdCB3b3JsZFBvc2l0aW9ucyA9IG5ldyBGbG9hdDMyQXJyYXkod2FzbU1vZHVsZS5IRUFQRjMyLmJ1ZmZlciwgd29ybGRQb3NpdGlvbnNQdHIsIHNwbGF0LnZlcnRleENvdW50ICogMyk7CiAgICAgIGNvbnN0IGRldGFjaGVkV29ybGRQb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KHdvcmxkUG9zaXRpb25zLnNsaWNlKCkuYnVmZmVyKTsKICAgICAgY29uc3Qgd29ybGRSb3RhdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KHdhc21Nb2R1bGUuSEVBUEYzMi5idWZmZXIsIHdvcmxkUm90YXRpb25zUHRyLCBzcGxhdC52ZXJ0ZXhDb3VudCAqIDQpOwogICAgICBjb25zdCBkZXRhY2hlZFdvcmxkUm90YXRpb25zID0gbmV3IEZsb2F0MzJBcnJheSh3b3JsZFJvdGF0aW9ucy5zbGljZSgpLmJ1ZmZlcik7CiAgICAgIGNvbnN0IHdvcmxkU2NhbGVzID0gbmV3IEZsb2F0MzJBcnJheSh3YXNtTW9kdWxlLkhFQVBGMzIuYnVmZmVyLCB3b3JsZFNjYWxlc1B0ciwgc3BsYXQudmVydGV4Q291bnQgKiAzKTsKICAgICAgY29uc3QgZGV0YWNoZWRXb3JsZFNjYWxlcyA9IG5ldyBGbG9hdDMyQXJyYXkod29ybGRTY2FsZXMuc2xpY2UoKS5idWZmZXIpOwogICAgICBjb25zdCByZXNwb25zZSA9IHsKICAgICAgICAgIGRhdGE6IGRldGFjaGVkRGF0YSwKICAgICAgICAgIHdvcmxkUG9zaXRpb25zOiBkZXRhY2hlZFdvcmxkUG9zaXRpb25zLAogICAgICAgICAgd29ybGRSb3RhdGlvbnM6IGRldGFjaGVkV29ybGRSb3RhdGlvbnMsCiAgICAgICAgICB3b3JsZFNjYWxlczogZGV0YWNoZWRXb3JsZFNjYWxlcywKICAgICAgICAgIG9mZnNldDogc3BsYXQub2Zmc2V0LAogICAgICAgICAgdmVydGV4Q291bnQ6IHNwbGF0LnZlcnRleENvdW50LAogICAgICAgICAgcG9zaXRpb25zOiBzcGxhdC5wb3NpdGlvbnMuYnVmZmVyLAogICAgICAgICAgcm90YXRpb25zOiBzcGxhdC5yb3RhdGlvbnMuYnVmZmVyLAogICAgICAgICAgc2NhbGVzOiBzcGxhdC5zY2FsZXMuYnVmZmVyLAogICAgICAgICAgY29sb3JzOiBzcGxhdC5jb2xvcnMuYnVmZmVyLAogICAgICAgICAgc2VsZWN0aW9uOiBzcGxhdC5zZWxlY3Rpb24uYnVmZmVyLAogICAgICB9OwogICAgICBzZWxmLnBvc3RNZXNzYWdlKHsgcmVzcG9uc2U6IHJlc3BvbnNlIH0sIFsKICAgICAgICAgIHJlc3BvbnNlLmRhdGEuYnVmZmVyLAogICAgICAgICAgcmVzcG9uc2Uud29ybGRQb3NpdGlvbnMuYnVmZmVyLAogICAgICAgICAgcmVzcG9uc2Uud29ybGRSb3RhdGlvbnMuYnVmZmVyLAogICAgICAgICAgcmVzcG9uc2Uud29ybGRTY2FsZXMuYnVmZmVyLAogICAgICAgICAgcmVzcG9uc2UucG9zaXRpb25zLAogICAgICAgICAgcmVzcG9uc2Uucm90YXRpb25zLAogICAgICAgICAgcmVzcG9uc2Uuc2NhbGVzLAogICAgICAgICAgcmVzcG9uc2UuY29sb3JzLAogICAgICAgICAgcmVzcG9uc2Uuc2VsZWN0aW9uLAogICAgICBdKTsKICAgICAgcnVubmluZyA9IGZhbHNlOwogIH07CiAgY29uc3QgcGFja1Rocm90dGxlZCA9ICgpID0+IHsKICAgICAgaWYgKHVwZGF0ZVF1ZXVlLmxlbmd0aCA9PT0gMCkKICAgICAgICAgIHJldHVybjsKICAgICAgaWYgKCFydW5uaW5nKSB7CiAgICAgICAgICBydW5uaW5nID0gdHJ1ZTsKICAgICAgICAgIGNvbnN0IHNwbGF0ID0gdXBkYXRlUXVldWUuc2hpZnQoKTsKICAgICAgICAgIHBhY2soc3BsYXQpOwogICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7CiAgICAgICAgICAgICAgcnVubmluZyA9IGZhbHNlOwogICAgICAgICAgICAgIHBhY2tUaHJvdHRsZWQoKTsKICAgICAgICAgIH0sIDApOwogICAgICB9CiAgfTsKICBzZWxmLm9ubWVzc2FnZSA9IChlKSA9PiB7CiAgICAgIGlmIChlLmRhdGEuc3BsYXQpIHsKICAgICAgICAgIGNvbnN0IHNwbGF0ID0gZS5kYXRhLnNwbGF0OwogICAgICAgICAgZm9yIChjb25zdCBbaW5kZXgsIGV4aXN0aW5nXSBvZiB1cGRhdGVRdWV1ZS5lbnRyaWVzKCkpIHsKICAgICAgICAgICAgICBpZiAoZXhpc3Rpbmcub2Zmc2V0ID09PSBzcGxhdC5vZmZzZXQpIHsKICAgICAgICAgICAgICAgICAgdXBkYXRlUXVldWVbaW5kZXhdID0gc3BsYXQ7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB1cGRhdGVRdWV1ZS5wdXNoKHNwbGF0KTsKICAgICAgICAgIHBhY2tUaHJvdHRsZWQoKTsKICAgICAgfQogIH07Cgp9KSgpOwovLyMgc291cmNlTWFwcGluZ1VSTD1EYXRhV29ya2VyLmpzLm1hcAoK",null),Al=function(G={}){var t,F,U=G;U.ready=new Promise((V,s)=>{t=V,F=s});var l,a=Object.assign({},U),n="";n=(n=self.location.href).indexOf("blob:")!==0?n.substr(0,n.replace(/[?#].*/,"").lastIndexOf("/")+1):"",l=V=>{var s=new XMLHttpRequest;return s.open("GET",V,!1),s.responseType="arraybuffer",s.send(null),new Uint8Array(s.response)},U.print||console.log.bind(console);var e,Q,d=U.printErr||console.error.bind(console);Object.assign(U,a),a=null,U.arguments&&U.arguments,U.thisProgram&&U.thisProgram,U.quit&&U.quit,U.wasmBinary&&(e=U.wasmBinary),typeof WebAssembly!="object"&&E("no native wasm support detected");var A,i,r,c,B,W,J,h,C=!1;function k(){var V=Q.buffer;U.HEAP8=A=new Int8Array(V),U.HEAP16=r=new Int16Array(V),U.HEAPU8=i=new Uint8Array(V),U.HEAPU16=c=new Uint16Array(V),U.HEAP32=B=new Int32Array(V),U.HEAPU32=W=new Uint32Array(V),U.HEAPF32=J=new Float32Array(V),U.HEAPF64=h=new Float64Array(V)}var p=[],X=[],D=[],u=0,M=null;function E(V){U.onAbort&&U.onAbort(V),d(V="Aborted("+V+")"),C=!0,V+=". Build with -sASSERTIONS for more info.";var s=new WebAssembly.RuntimeError(V);throw F(s),s}var w,et,Y="data:application/octet-stream;base64,",H=V=>V.startsWith(Y);function at(V){if(V==w&&e)return new Uint8Array(e);var s=function(R){if(H(R))return function(Z){for(var m=atob(Z),b=new Uint8Array(m.length),g=0;g<m.length;++g)b[g]=m.charCodeAt(g);return b}(R.slice(Y.length))}(V);if(s)return s;if(l)return l(V);throw"both async and sync fetching of the wasm failed"}function L(V,s,R){return function(Z){return Promise.resolve().then(()=>at(Z))}(V).then(Z=>WebAssembly.instantiate(Z,s)).then(Z=>Z).then(R,Z=>{d(`failed to asynchronously prepare wasm: ${Z}`),E(Z)})}H(w="data:application/octet-stream;base64,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aWduZWQgc2hvcnQ+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGludD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dW5zaWduZWQgaW50PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxmbG9hdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dWludDhfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8aW50OF90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1aW50MTZfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8aW50MTZfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dWludDY0X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGludDY0X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVpbnQzMl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxpbnQzMl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxjaGFyPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBjaGFyPgBzdGQ6OmJhc2ljX3N0cmluZzx1bnNpZ25lZCBjaGFyPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxzaWduZWQgY2hhcj4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8bG9uZz4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dW5zaWduZWQgbG9uZz4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8ZG91YmxlPgBOU3QzX18yMTJiYXNpY19zdHJpbmdJY05TXzExY2hhcl90cmFpdHNJY0VFTlNfOWFsbG9jYXRvckljRUVFRQAAAABEDAAAQgcAAE5TdDNfXzIxMmJhc2ljX3N0cmluZ0loTlNfMTFjaGFyX3RyYWl0c0loRUVOU185YWxsb2NhdG9ySWhFRUVFAABEDAAAjAcAAE5TdDNfXzIxMmJhc2ljX3N0cmluZ0l3TlNfMTFjaGFyX3RyYWl0c0l3RUVOU185YWxsb2NhdG9ySXdFRUVFAABEDAAA1AcAAE5TdDNfXzIxMmJhc2ljX3N0cmluZ0lEc05TXzExY2hhcl90cmFpdHNJRHNFRU5TXzlhbGxvY2F0b3JJRHNFRUVFAAAARAwAABwIAABOU3QzX18yMTJiYXNpY19zdHJpbmdJRGlOU18xMWNoYXJfdHJhaXRzSURpRUVOU185YWxsb2NhdG9ySURpRUVFRQAAAEQMAABoCAAATjEwZW1zY3JpcHRlbjN2YWxFAABEDAAAtAgAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWNFRQAARAwAANAIAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lhRUUAAEQMAAD4CAAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJaEVFAABEDAAAIAkAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SXNFRQAARAwAAEgJAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0l0RUUAAEQMAABwCQAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJaUVFAABEDAAAmAkAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWpFRQAARAwAAMAJAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lsRUUAAEQMAADoCQAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJbUVFAABEDAAAEAoAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SXhFRQAARAwAADgKAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0l5RUUAAEQMAABgCgAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJZkVFAABEDAAAiAoAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWRFRQAARAwAALAKAABOMTBfX2N4eGFiaXYxMTZfX3NoaW1fdHlwZV9pbmZvRQAAAABsDAAA2AoAANAMAABOMTBfX2N4eGFiaXYxMTdfX2NsYXNzX3R5cGVfaW5mb0UAAABsDAAACAsAAPwKAAAAAAAAfAsAAAIAAAADAAAABAAAAAUAAAAGAAAATjEwX19jeHhhYml2MTIzX19mdW5kYW1lbnRhbF90eXBlX2luZm9FAGwMAABUCwAA/AoAAHYAAABACwAAiAsAAGIAAABACwAAlAsAAGMAAABACwAAoAsAAGgAAABACwAArAsAAGEAAABACwAAuAsAAHMAAABACwAAxAsAAHQAAABACwAA0AsAAGkAAABACwAA3AsAAGoAAABACwAA6AsAAGwAAABACwAA9AsAAG0AAABACwAAAAwAAHgAAABACwAADAwAAHkAAABACwAAGAwAAGYAAABACwAAJAwAAGQAAABACwAAMAwAAAAAAAAsCwAAAgAAAAcAAAAEAAAABQAAAAgAAAAJAAAACgAAAAsAAAAAAAAAtAwAAAIAAAAMAAAABAAAAAUAAAAIAAAADQAAAA4AAAAPAAAATjEwX19jeHhhYml2MTIwX19zaV9jbGFzc190eXBlX2luZm9FAAAAAGwMAACMDAAALAsAAFN0OXR5cGVfaW5mbwAAAABEDAAAwAwAQdgZCwPgDgE=")||(et=w,w=U.locateFile?U.locateFile(et,n):n+et);var o=V=>{for(;V.length>0;)V.shift()(U)};U.noExitRuntime;var T,v,x=V=>{for(var s="",R=V;i[R];)s+=T[i[R++]];return s},At={},Vt={},K=V=>{throw new v(V)};function _(V,s,R={}){if(!("argPackAdvance"in s))throw new TypeError("registerType registeredInstance requires argPackAdvance");return function(Z,m,b={}){var g=m.name;if(Z||K(`type "${g}" must have a positive integer typeid pointer`),Vt.hasOwnProperty(Z)){if(b.ignoreDuplicateRegistrations)return;K(`Cannot register type '${g}' twice`)}if(Vt[Z]=m,At.hasOwnProperty(Z)){var y=At[Z];delete At[Z],y.forEach(N=>N())}}(V,s,R)}function nt(){this.allocated=[void 0],this.freelist=[]}var j=new nt,ct=()=>{for(var V=0,s=j.reserved;s<j.allocated.length;++s)j.allocated[s]!==void 0&&++V;return V},Jt=V=>(V||K("Cannot use deleted val. handle = "+V),j.get(V).value),xt=V=>{switch(V){case void 0:return 1;case null:return 2;case!0:return 3;case!1:return 4;default:return j.allocate({refcount:1,value:V})}};function Xt(V){return this.fromWireType(B[V>>2])}var ft=(V,s)=>{switch(s){case 4:return function(R){return this.fromWireType(J[R>>2])};case 8:return function(R){return this.fromWireType(h[R>>3])};default:throw new TypeError(`invalid float width (${s}): ${V}`)}},Dt=(V,s,R)=>{switch(s){case 1:return R?Z=>A[Z>>0]:Z=>i[Z>>0];case 2:return R?Z=>r[Z>>1]:Z=>c[Z>>1];case 4:return R?Z=>B[Z>>2]:Z=>W[Z>>2];default:throw new TypeError(`invalid integer width (${s}): ${V}`)}};function wt(V){return this.fromWireType(W[V>>2])}var Et=typeof TextDecoder<"u"?new TextDecoder("utf8"):void 0,vt=(V,s)=>V?((R,Z,m)=>{for(var b=Z+m,g=Z;R[g]&&!(g>=b);)++g;if(g-Z>16&&R.buffer&&Et)return Et.decode(R.subarray(Z,g));for(var y="";Z<g;){var N=R[Z++];if(128&N){var S=63&R[Z++];if((224&N)!=192){var q=63&R[Z++];if((N=(240&N)==224?(15&N)<<12|S<<6|q:(7&N)<<18|S<<12|q<<6|63&R[Z++])<65536)y+=String.fromCharCode(N);else{var P=N-65536;y+=String.fromCharCode(55296|P>>10,56320|1023&P)}}else y+=String.fromCharCode((31&N)<<6|S)}else y+=String.fromCharCode(N)}return y})(i,V,s):"",yt=typeof TextDecoder<"u"?new TextDecoder("utf-16le"):void 0,zt=(V,s)=>{for(var R=V,Z=R>>1,m=Z+s/2;!(Z>=m)&&c[Z];)++Z;if((R=Z<<1)-V>32&&yt)return yt.decode(i.subarray(V,R));for(var b="",g=0;!(g>=s/2);++g){var y=r[V+2*g>>1];if(y==0)break;b+=String.fromCharCode(y)}return b},Mt=(V,s,R)=>{if(R===void 0&&(R=2147483647),R<2)return 0;for(var Z=s,m=(R-=2)<2*V.length?R/2:V.length,b=0;b<m;++b){var g=V.charCodeAt(b);r[s>>1]=g,s+=2}return r[s>>1]=0,s-Z},Kt=V=>2*V.length,jt=(V,s)=>{for(var R=0,Z="";!(R>=s/4);){var m=B[V+4*R>>2];if(m==0)break;if(++R,m>=65536){var b=m-65536;Z+=String.fromCharCode(55296|b>>10,56320|1023&b)}else Z+=String.fromCharCode(m)}return Z},Ot=(V,s,R)=>{if(R===void 0&&(R=2147483647),R<4)return 0;for(var Z=s,m=Z+R-4,b=0;b<V.length;++b){var g=V.charCodeAt(b);if(g>=55296&&g<=57343&&(g=65536+((1023&g)<<10)|1023&V.charCodeAt(++b)),B[s>>2]=g,(s+=4)+4>m)break}return B[s>>2]=0,s-Z},Lt=V=>{for(var s=0,R=0;R<V.length;++R){var Z=V.charCodeAt(R);Z>=55296&&Z<=57343&&++R,s+=4}return s},Pt=V=>{var s=(V-Q.buffer.byteLength+65535)/65536;try{return Q.grow(s),k(),1}catch{}};(()=>{for(var V=new Array(256),s=0;s<256;++s)V[s]=String.fromCharCode(s);T=V})(),v=U.BindingError=class extends Error{constructor(V){super(V),this.name="BindingError"}},U.InternalError=class extends Error{constructor(V){super(V),this.name="InternalError"}},Object.assign(nt.prototype,{get(V){return this.allocated[V]},has(V){return this.allocated[V]!==void 0},allocate(V){var s=this.freelist.pop()||this.allocated.length;return this.allocated[s]=V,s},free(V){this.allocated[V]=void 0,this.freelist.push(V)}}),j.allocated.push({value:void 0},{value:null},{value:!0},{value:!1}),j.reserved=j.allocated.length,U.count_emval_handles=ct;var _t={f:(V,s,R,Z,m)=>{},i:(V,s,R,Z)=>{_(V,{name:s=x(s),fromWireType:function(m){return!!m},toWireType:function(m,b){return b?R:Z},argPackAdvance:8,readValueFromPointer:function(m){return this.fromWireType(i[m])},destructorFunction:null})},h:(V,s)=>{_(V,{name:s=x(s),fromWireType:R=>{var Z=Jt(R);return(m=>{m>=j.reserved&&--j.get(m).refcount==0&&j.free(m)})(R),Z},toWireType:(R,Z)=>xt(Z),argPackAdvance:8,readValueFromPointer:Xt,destructorFunction:null})},e:(V,s,R)=>{_(V,{name:s=x(s),fromWireType:Z=>Z,toWireType:(Z,m)=>m,argPackAdvance:8,readValueFromPointer:ft(s,R),destructorFunction:null})},b:(V,s,R,Z,m)=>{s=x(s);var b=N=>N;if(Z===0){var g=32-8*R;b=N=>N<<g>>>g}var y=s.includes("unsigned");_(V,{name:s,fromWireType:b,toWireType:y?function(N,S){return this.name,S>>>0}:function(N,S){return this.name,S},argPackAdvance:8,readValueFromPointer:Dt(s,R,Z!==0),destructorFunction:null})},a:(V,s,R)=>{var Z=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][s];function m(b){var g=W[b>>2],y=W[b+4>>2];return new Z(A.buffer,y,g)}_(V,{name:R=x(R),fromWireType:m,argPackAdvance:8,readValueFromPointer:m},{ignoreDuplicateRegistrations:!0})},d:(V,s)=>{var R=(s=x(s))==="std::string";_(V,{name:s,fromWireType(Z){var m,b=W[Z>>2],g=Z+4;if(R)for(var y=g,N=0;N<=b;++N){var S=g+N;if(N==b||i[S]==0){var q=vt(y,S-y);m===void 0?m=q:(m+="\0",m+=q),y=S+1}}else{var P=new Array(b);for(N=0;N<b;++N)P[N]=String.fromCharCode(i[g+N]);m=P.join("")}return it(Z),m},toWireType(Z,m){var b;m instanceof ArrayBuffer&&(m=new Uint8Array(m));var g=typeof m=="string";g||m instanceof Uint8Array||m instanceof Uint8ClampedArray||m instanceof Int8Array||K("Cannot pass non-string to std::string"),b=R&&g?(P=>{for(var O=0,f=0;f<P.length;++f){var dt=P.charCodeAt(f);dt<=127?O++:dt<=2047?O+=2:dt>=55296&&dt<=57343?(O+=4,++f):O+=3}return O})(m):m.length;var y=bt(4+b+1),N=y+4;if(W[y>>2]=b,R&&g)((P,O,f,dt)=>{if(!(dt>0))return 0;for(var st=f+dt-1,ht=0;ht<P.length;++ht){var $=P.charCodeAt(ht);if($>=55296&&$<=57343&&($=65536+((1023&$)<<10)|1023&P.charCodeAt(++ht)),$<=127){if(f>=st)break;O[f++]=$}else if($<=2047){if(f+1>=st)break;O[f++]=192|$>>6,O[f++]=128|63&$}else if($<=65535){if(f+2>=st)break;O[f++]=224|$>>12,O[f++]=128|$>>6&63,O[f++]=128|63&$}else{if(f+3>=st)break;O[f++]=240|$>>18,O[f++]=128|$>>12&63,O[f++]=128|$>>6&63,O[f++]=128|63&$}}O[f]=0})(m,i,N,b+1);else if(g)for(var S=0;S<b;++S){var q=m.charCodeAt(S);q>255&&(it(N),K("String has UTF-16 code units that do not fit in 8 bits")),i[N+S]=q}else for(S=0;S<b;++S)i[N+S]=m[S];return Z!==null&&Z.push(it,y),y},argPackAdvance:8,readValueFromPointer:wt,destructorFunction(Z){it(Z)}})},c:(V,s,R)=>{var Z,m,b,g,y;R=x(R),s===2?(Z=zt,m=Mt,g=Kt,b=()=>c,y=1):s===4&&(Z=jt,m=Ot,g=Lt,b=()=>W,y=2),_(V,{name:R,fromWireType:N=>{for(var S,q=W[N>>2],P=b(),O=N+4,f=0;f<=q;++f){var dt=N+4+f*s;if(f==q||P[dt>>y]==0){var st=Z(O,dt-O);S===void 0?S=st:(S+="\0",S+=st),O=dt+s}}return it(N),S},toWireType:(N,S)=>{typeof S!="string"&&K(`Cannot pass non-string to C++ string type ${R}`);var q=g(S),P=bt(4+q+s);return W[P>>2]=q>>y,m(S,P+4,q+s),N!==null&&N.push(it,P),P},argPackAdvance:8,readValueFromPointer:Xt,destructorFunction(N){it(N)}})},j:(V,s)=>{_(V,{isVoid:!0,name:s=x(s),argPackAdvance:0,fromWireType:()=>{},toWireType:(R,Z)=>{}})},g:V=>{var s=i.length,R=2147483648;if((V>>>=0)>R)return!1;for(var Z,m,b=1;b<=4;b*=2){var g=s*(1+.2/b);g=Math.min(g,V+100663296);var y=Math.min(R,(Z=Math.max(V,g))+((m=65536)-Z%m)%m);if(Pt(y))return!0}return!1}},Bt=function(){var V,s,R,Z={a:_t};function m(b,g){var y;return Bt=b.exports,Q=Bt.k,k(),y=Bt.l,X.unshift(y),function(N){if(u--,U.monitorRunDependencies&&U.monitorRunDependencies(u),u==0&&M){var S=M;M=null,S()}}(),Bt}if(u++,U.monitorRunDependencies&&U.monitorRunDependencies(u),U.instantiateWasm)try{return U.instantiateWasm(Z,m)}catch(b){d(`Module.instantiateWasm callback failed with error: ${b}`),F(b)}return(V=w,s=Z,R=function(b){m(b.instance)},L(V,s,R)).catch(F),{}}();U._pack=(V,s,R,Z,m,b,g,y,N,S,q)=>(U._pack=Bt.m)(V,s,R,Z,m,b,g,y,N,S,q),U.__embind_initialize_bindings=()=>(U.__embind_initialize_bindings=Bt.n)();var Wt,bt=U._malloc=V=>(bt=U._malloc=Bt.p)(V),it=U._free=V=>(it=U._free=Bt.q)(V);function St(){function V(){Wt||(Wt=!0,U.calledRun=!0,C||(o(X),t(U),U.onRuntimeInitialized&&U.onRuntimeInitialized(),function(){if(U.postRun)for(typeof U.postRun=="function"&&(U.postRun=[U.postRun]);U.postRun.length;)s=U.postRun.shift(),D.unshift(s);var s;o(D)}()))}u>0||(function(){if(U.preRun)for(typeof U.preRun=="function"&&(U.preRun=[U.preRun]);U.preRun.length;)s=U.preRun.shift(),p.unshift(s);var s;o(p)}(),u>0||(U.setStatus?(U.setStatus("Running..."),setTimeout(function(){setTimeout(function(){U.setStatus("")},1),V()},1)):V()))}if(M=function V(){Wt||St(),Wt||(M=V)},U.preInit)for(typeof U.preInit=="function"&&(U.preInit=[U.preInit]);U.preInit.length>0;)U.preInit.pop()();return St(),G.ready};class Tt{constructor(t){this.dataChanged=!1,this.transformsChanged=!1,this.colorTransformsChanged=!1,this._updating=new Set,this._dirty=new Set;let F=0,U=0;this._splatIndices=new Map,this._offsets=new Map;const l=new Map;for(const A of t.objects)A instanceof Qt&&(this._splatIndices.set(A,U),this._offsets.set(A,F),l.set(F,A),F+=A.data.vertexCount,U++);this._vertexCount=F,this._width=2048,this._height=Math.ceil(2*this.vertexCount/this.width),this._data=new Uint32Array(this.width*this.height*4),this._transformsWidth=5,this._transformsHeight=l.size,this._transforms=new Float32Array(this._transformsWidth*this._transformsHeight*4),this._transformIndicesWidth=1024,this._transformIndicesHeight=Math.ceil(this.vertexCount/this._transformIndicesWidth),this._transformIndices=new Uint32Array(this._transformIndicesWidth*this._transformIndicesHeight),this._colorTransformsWidth=4,this._colorTransformsHeight=64,this._colorTransforms=new Float32Array(this._colorTransformsWidth*this._colorTransformsHeight*4),this._colorTransforms.fill(0),this._colorTransforms[0]=1,this._colorTransforms[5]=1,this._colorTransforms[10]=1,this._colorTransforms[15]=1,this._colorTransformIndicesWidth=1024,this._colorTransformIndicesHeight=Math.ceil(this.vertexCount/this._colorTransformIndicesWidth),this._colorTransformIndices=new Uint32Array(this._colorTransformIndicesWidth*this._colorTransformIndicesHeight),this.colorTransformIndices.fill(0),this._positions=new Float32Array(3*this.vertexCount),this._rotations=new Float32Array(4*this.vertexCount),this._scales=new Float32Array(3*this.vertexCount),this._worker=new al;const a=A=>{const i=this._splatIndices.get(A);this._transforms.set(A.transform.buffer,20*i),this._transforms[20*i+16]=A.selected?1:0,A.positionChanged=!1,A.rotationChanged=!1,A.scaleChanged=!1,A.selectedChanged=!1,this.transformsChanged=!0},n=()=>{let A=!1;for(const c of this._splatIndices.keys())if(c.colorTransformChanged){A=!0;break}if(!A)return;const i=[new Ut];this._colorTransformIndices.fill(0);let r=1;for(const c of this._splatIndices.keys()){const B=this._offsets.get(c);for(const W of c.colorTransforms)i.includes(W)||(i.push(W),r++);for(const W of c.colorTransformsMap.keys()){const J=c.colorTransformsMap.get(W);this._colorTransformIndices[W+B]=J+r-1}c.colorTransformChanged=!1}for(let c=0;c<i.length;c++){const B=i[c];this._colorTransforms.set(B.buffer,16*c)}this.colorTransformsChanged=!0};let e;this._worker.onmessage=A=>{if(A.data.response){const i=A.data.response,r=l.get(i.offset);a(r),n();const c=this._splatIndices.get(r);for(let B=0;B<r.data.vertexCount;B++)this._transformIndices[i.offset+B]=c;this._data.set(i.data,8*i.offset),r.data.reattach(i.positions,i.rotations,i.scales,i.colors,i.selection),this._positions.set(i.worldPositions,3*i.offset),this._rotations.set(i.worldRotations,4*i.offset),this._scales.set(i.worldScales,3*i.offset),this._updating.delete(r),r.selectedChanged=!1,this.dataChanged=!0}},async function(){e=await Al()}();const Q=A=>{if(!e)return void async function(){for(;!e;)await new Promise(w=>setTimeout(w,0))}().then(()=>{Q(A)});a(A);const i=e._malloc(3*A.data.vertexCount*4),r=e._malloc(4*A.data.vertexCount*4),c=e._malloc(3*A.data.vertexCount*4),B=e._malloc(4*A.data.vertexCount),W=e._malloc(A.data.vertexCount),J=e._malloc(8*A.data.vertexCount*4),h=e._malloc(3*A.data.vertexCount*4),C=e._malloc(4*A.data.vertexCount*4),k=e._malloc(3*A.data.vertexCount*4);e.HEAPF32.set(A.data.positions,i/4),e.HEAPF32.set(A.data.rotations,r/4),e.HEAPF32.set(A.data.scales,c/4),e.HEAPU8.set(A.data.colors,B),e.HEAPU8.set(A.data.selection,W),e._pack(A.selected,A.data.vertexCount,i,r,c,B,W,J,h,C,k);const p=new Uint32Array(e.HEAPU32.buffer,J,8*A.data.vertexCount),X=new Float32Array(e.HEAPF32.buffer,h,3*A.data.vertexCount),D=new Float32Array(e.HEAPF32.buffer,C,4*A.data.vertexCount),u=new Float32Array(e.HEAPF32.buffer,k,3*A.data.vertexCount),M=this._splatIndices.get(A),E=this._offsets.get(A);for(let w=0;w<A.data.vertexCount;w++)this._transformIndices[E+w]=M;this._data.set(p,8*E),this._positions.set(X,3*E),this._rotations.set(D,4*E),this._scales.set(u,3*E),e._free(i),e._free(r),e._free(c),e._free(B),e._free(W),e._free(J),e._free(h),e._free(C),e._free(k),this.dataChanged=!0,this.colorTransformsChanged=!0},d=A=>{if((A.positionChanged||A.rotationChanged||A.scaleChanged||A.selectedChanged)&&a(A),A.colorTransformChanged&&n(),!A.data.changed||A.data.detached)return;const i={position:new Float32Array(A.position.flat()),rotation:new Float32Array(A.rotation.flat()),scale:new Float32Array(A.scale.flat()),selected:A.selected,vertexCount:A.data.vertexCount,positions:A.data.positions,rotations:A.data.rotations,scales:A.data.scales,colors:A.data.colors,selection:A.data.selection,offset:this._offsets.get(A)};this._worker.postMessage({splat:i},[i.position.buffer,i.rotation.buffer,i.scale.buffer,i.positions.buffer,i.rotations.buffer,i.scales.buffer,i.colors.buffer,i.selection.buffer]),this._updating.add(A),A.data.detached=!0};this.getSplat=A=>{let i=null;for(const[r,c]of this._offsets){if(!(A>=c))break;i=r}return i},this.getLocalIndex=(A,i)=>i-this._offsets.get(A),this.markDirty=A=>{this._dirty.add(A)},this.rebuild=()=>{for(const A of this._dirty)d(A);this._dirty.clear()},this.dispose=()=>{this._worker.terminate()};for(const A of this._splatIndices.keys())Q(A);n()}get offsets(){return this._offsets}get data(){return this._data}get width(){return this._width}get height(){return this._height}get transforms(){return this._transforms}get transformsWidth(){return this._transformsWidth}get transformsHeight(){return this._transformsHeight}get transformIndices(){return this._transformIndices}get transformIndicesWidth(){return this._transformIndicesWidth}get transformIndicesHeight(){return this._transformIndicesHeight}get colorTransforms(){return this._colorTransforms}get colorTransformsWidth(){return this._colorTransformsWidth}get colorTransformsHeight(){return this._colorTransformsHeight}get colorTransformIndices(){return this._colorTransformIndices}get colorTransformIndicesWidth(){return this._colorTransformIndicesWidth}get colorTransformIndicesHeight(){return this._colorTransformIndicesHeight}get positions(){return this._positions}get rotations(){return this._rotations}get scales(){return this._scales}get vertexCount(){return this._vertexCount}get needsRebuild(){return this._dirty.size>0}get updating(){return this._updating.size>0}}class Gt{constructor(t=0,F=0,U=0,l=255){this.r=t,this.g=F,this.b=U,this.a=l}flat(){return[this.r,this.g,this.b,this.a]}flatNorm(){return[this.r/255,this.g/255,this.b/255,this.a/255]}toHexString(){return"#"+this.flat().map(t=>t.toString(16).padStart(2,"0")).join("")}toString(){return`[${this.flat().join(", ")}]`}}class pt extends Nt{constructor(t,F){super(t,F),this._outlineThickness=10,this._outlineColor=new Gt(255,165,0,255),this._renderData=null,this._depthIndex=new Uint32Array,this._splatTexture=null,this._worker=null;const U=t.canvas,l=t.gl;let a,n,e,Q,d,A,i,r,c,B,W,J,h,C,k,p,X,D,u;this._resize=()=>{this._camera&&(this._camera.data.setSize(U.width,U.height),this._camera.update(),a=l.getUniformLocation(this.program,"projection"),l.uniformMatrix4fv(a,!1,this._camera.data.projectionMatrix.buffer),n=l.getUniformLocation(this.program,"viewport"),l.uniform2fv(n,new Float32Array([U.width,U.height])))};const M=()=>{this._worker=new dl,this._worker.onmessage=Y=>{if(Y.data.depthIndex){const{depthIndex:H}=Y.data;this._depthIndex=H,l.bindBuffer(l.ARRAY_BUFFER,u),l.bufferData(l.ARRAY_BUFFER,H,l.STATIC_DRAW)}}};this._initialize=()=>{if(this._scene&&this._camera){this._resize(),this._scene.addEventListener("objectAdded",E),this._scene.addEventListener("objectRemoved",w);for(const Y of this._scene.objects)Y instanceof Qt&&Y.addEventListener("objectChanged",et);this._renderData=new Tt(this._scene),e=l.getUniformLocation(this.program,"focal"),l.uniform2fv(e,new Float32Array([this._camera.data.fx,this._camera.data.fy])),Q=l.getUniformLocation(this.program,"view"),l.uniformMatrix4fv(Q,!1,this._camera.data.viewMatrix.buffer),B=l.getUniformLocation(this.program,"outlineThickness"),l.uniform1f(B,this.outlineThickness),W=l.getUniformLocation(this.program,"outlineColor"),l.uniform4fv(W,new Float32Array(this.outlineColor.flatNorm())),this._splatTexture=l.createTexture(),d=l.getUniformLocation(this.program,"u_texture"),l.uniform1i(d,0),C=l.createTexture(),A=l.getUniformLocation(this.program,"u_transforms"),l.uniform1i(A,1),k=l.createTexture(),i=l.getUniformLocation(this.program,"u_transformIndices"),l.uniform1i(i,2),p=l.createTexture(),r=l.getUniformLocation(this.program,"u_colorTransforms"),l.uniform1i(r,3),X=l.createTexture(),c=l.getUniformLocation(this.program,"u_colorTransformIndices"),l.uniform1i(c,4),D=l.createBuffer(),l.bindBuffer(l.ARRAY_BUFFER,D),l.bufferData(l.ARRAY_BUFFER,new Float32Array([-2,-2,2,-2,2,2,-2,2]),l.STATIC_DRAW),J=l.getAttribLocation(this.program,"position"),l.enableVertexAttribArray(J),l.vertexAttribPointer(J,2,l.FLOAT,!1,0,0),u=l.createBuffer(),h=l.getAttribLocation(this.program,"index"),l.enableVertexAttribArray(h),l.bindBuffer(l.ARRAY_BUFFER,u),M()}else console.error("Cannot render without scene and camera")};const E=Y=>{const H=Y;H.object instanceof Qt&&H.object.addEventListener("objectChanged",et),this.dispose()},w=Y=>{const H=Y;H.object instanceof Qt&&H.object.removeEventListener("objectChanged",et),this.dispose()},et=Y=>{const H=Y;H.object instanceof Qt&&this._renderData&&this._renderData.markDirty(H.object)};this._render=()=>{var Y,H;if(this._scene&&this._camera&&this.renderData){if(this.renderData.needsRebuild&&this.renderData.rebuild(),this.renderData.dataChanged||this.renderData.transformsChanged||this.renderData.colorTransformsChanged){this.renderData.dataChanged&&(l.activeTexture(l.TEXTURE0),l.bindTexture(l.TEXTURE_2D,this.splatTexture),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_WRAP_S,l.CLAMP_TO_EDGE),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_WRAP_T,l.CLAMP_TO_EDGE),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_MIN_FILTER,l.NEAREST),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_MAG_FILTER,l.NEAREST),l.texImage2D(l.TEXTURE_2D,0,l.RGBA32UI,this.renderData.width,this.renderData.height,0,l.RGBA_INTEGER,l.UNSIGNED_INT,this.renderData.data)),this.renderData.transformsChanged&&(l.activeTexture(l.TEXTURE1),l.bindTexture(l.TEXTURE_2D,C),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_WRAP_S,l.CLAMP_TO_EDGE),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_WRAP_T,l.CLAMP_TO_EDGE),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_MIN_FILTER,l.NEAREST),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_MAG_FILTER,l.NEAREST),l.texImage2D(l.TEXTURE_2D,0,l.RGBA32F,this.renderData.transformsWidth,this.renderData.transformsHeight,0,l.RGBA,l.FLOAT,this.renderData.transforms),l.activeTexture(l.TEXTURE2),l.bindTexture(l.TEXTURE_2D,k),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_WRAP_S,l.CLAMP_TO_EDGE),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_WRAP_T,l.CLAMP_TO_EDGE),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_MIN_FILTER,l.NEAREST),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_MAG_FILTER,l.NEAREST),l.texImage2D(l.TEXTURE_2D,0,l.R32UI,this.renderData.transformIndicesWidth,this.renderData.transformIndicesHeight,0,l.RED_INTEGER,l.UNSIGNED_INT,this.renderData.transformIndices)),this.renderData.colorTransformsChanged&&(l.activeTexture(l.TEXTURE3),l.bindTexture(l.TEXTURE_2D,p),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_WRAP_S,l.CLAMP_TO_EDGE),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_WRAP_T,l.CLAMP_TO_EDGE),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_MIN_FILTER,l.NEAREST),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_MAG_FILTER,l.NEAREST),l.texImage2D(l.TEXTURE_2D,0,l.RGBA32F,this.renderData.colorTransformsWidth,this.renderData.colorTransformsHeight,0,l.RGBA,l.FLOAT,this.renderData.colorTransforms),l.activeTexture(l.TEXTURE4),l.bindTexture(l.TEXTURE_2D,X),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_WRAP_S,l.CLAMP_TO_EDGE),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_WRAP_T,l.CLAMP_TO_EDGE),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_MIN_FILTER,l.NEAREST),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_MAG_FILTER,l.NEAREST),l.texImage2D(l.TEXTURE_2D,0,l.R32UI,this.renderData.colorTransformIndicesWidth,this.renderData.colorTransformIndicesHeight,0,l.RED_INTEGER,l.UNSIGNED_INT,this.renderData.colorTransformIndices));const at=new Float32Array(this.renderData.positions.slice().buffer),L=new Float32Array(this.renderData.transforms.slice().buffer),o=new Uint32Array(this.renderData.transformIndices.slice().buffer);(Y=this._worker)===null||Y===void 0||Y.postMessage({sortData:{positions:at,transforms:L,transformIndices:o,vertexCount:this.renderData.vertexCount}},[at.buffer,L.buffer,o.buffer]),this.renderData.dataChanged=!1,this.renderData.transformsChanged=!1,this.renderData.colorTransformsChanged=!1}this._camera.update(),(H=this._worker)===null||H===void 0||H.postMessage({viewProj:this._camera.data.viewProj.buffer}),l.viewport(0,0,U.width,U.height),l.clearColor(0,0,0,0),l.clear(l.COLOR_BUFFER_BIT),l.disable(l.DEPTH_TEST),l.enable(l.BLEND),l.blendFuncSeparate(l.ONE_MINUS_DST_ALPHA,l.ONE,l.ONE_MINUS_DST_ALPHA,l.ONE),l.blendEquationSeparate(l.FUNC_ADD,l.FUNC_ADD),l.uniformMatrix4fv(a,!1,this._camera.data.projectionMatrix.buffer),l.uniformMatrix4fv(Q,!1,this._camera.data.viewMatrix.buffer),l.bindBuffer(l.ARRAY_BUFFER,D),l.vertexAttribPointer(J,2,l.FLOAT,!1,0,0),l.bindBuffer(l.ARRAY_BUFFER,u),l.bufferData(l.ARRAY_BUFFER,this.depthIndex,l.STATIC_DRAW),l.vertexAttribIPointer(h,1,l.INT,0,0),l.vertexAttribDivisor(h,1),l.drawArraysInstanced(l.TRIANGLE_FAN,0,4,this.renderData.vertexCount)}else console.error("Cannot render without scene and camera")},this._dispose=()=>{var Y;if(this._scene&&this._camera&&this.renderData){this._scene.removeEventListener("objectAdded",E),this._scene.removeEventListener("objectRemoved",w);for(const H of this._scene.objects)H instanceof Qt&&H.removeEventListener("objectChanged",et);(Y=this._worker)===null||Y===void 0||Y.terminate(),this.renderData.dispose(),l.deleteTexture(this.splatTexture),l.deleteTexture(C),l.deleteTexture(k),l.deleteBuffer(u),l.deleteBuffer(D)}else console.error("Cannot dispose without scene and camera")},this._setOutlineThickness=Y=>{this._outlineThickness=Y,this._initialized&&l.uniform1f(B,Y)},this._setOutlineColor=Y=>{this._outlineColor=Y,this._initialized&&l.uniform4fv(W,new Float32Array(Y.flatNorm()))}}get renderData(){return this._renderData}get depthIndex(){return this._depthIndex}get splatTexture(){return this._splatTexture}get outlineThickness(){return this._outlineThickness}set outlineThickness(t){this._setOutlineThickness(t)}get outlineColor(){return this._outlineColor}set outlineColor(t){this._setOutlineColor(t)}get worker(){return this._worker}_getVertexSource(){return`#version 300 es
|
|
10
|
-
precision highp float;
|
|
11
|
-
precision highp int;
|
|
12
|
-
|
|
13
|
-
uniform highp usampler2D u_texture;
|
|
14
|
-
uniform highp sampler2D u_transforms;
|
|
15
|
-
uniform highp usampler2D u_transformIndices;
|
|
16
|
-
uniform highp sampler2D u_colorTransforms;
|
|
17
|
-
uniform highp usampler2D u_colorTransformIndices;
|
|
18
|
-
uniform mat4 projection, view;
|
|
19
|
-
uniform vec2 focal;
|
|
20
|
-
uniform vec2 viewport;
|
|
21
|
-
|
|
22
|
-
uniform bool useDepthFade;
|
|
23
|
-
uniform float depthFade;
|
|
24
|
-
|
|
25
|
-
in vec2 position;
|
|
26
|
-
in int index;
|
|
27
|
-
|
|
28
|
-
out vec4 vColor;
|
|
29
|
-
out vec2 vPosition;
|
|
30
|
-
out float vSize;
|
|
31
|
-
out float vSelected;
|
|
32
|
-
|
|
33
|
-
void main () {
|
|
34
|
-
uvec4 cen = texelFetch(u_texture, ivec2((uint(index) & 0x3ffu) << 1, uint(index) >> 10), 0);
|
|
35
|
-
float selected = float((cen.w >> 24) & 0xffu);
|
|
36
|
-
|
|
37
|
-
uint transformIndex = texelFetch(u_transformIndices, ivec2(uint(index) & 0x3ffu, uint(index) >> 10), 0).x;
|
|
38
|
-
mat4 transform = mat4(
|
|
39
|
-
texelFetch(u_transforms, ivec2(0, transformIndex), 0),
|
|
40
|
-
texelFetch(u_transforms, ivec2(1, transformIndex), 0),
|
|
41
|
-
texelFetch(u_transforms, ivec2(2, transformIndex), 0),
|
|
42
|
-
texelFetch(u_transforms, ivec2(3, transformIndex), 0)
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
if (selected < 0.5) {
|
|
46
|
-
selected = texelFetch(u_transforms, ivec2(4, transformIndex), 0).x;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
mat4 viewTransform = view * transform;
|
|
50
|
-
|
|
51
|
-
vec4 cam = viewTransform * vec4(uintBitsToFloat(cen.xyz), 1);
|
|
52
|
-
vec4 pos2d = projection * cam;
|
|
53
|
-
|
|
54
|
-
float clip = 1.2 * pos2d.w;
|
|
55
|
-
if (pos2d.z < -pos2d.w || pos2d.z > pos2d.w || pos2d.x < -clip || pos2d.x > clip || pos2d.y < -clip || pos2d.y > clip) {
|
|
56
|
-
gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
uvec4 cov = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 1) | 1u, uint(index) >> 10), 0);
|
|
61
|
-
vec2 u1 = unpackHalf2x16(cov.x), u2 = unpackHalf2x16(cov.y), u3 = unpackHalf2x16(cov.z);
|
|
62
|
-
mat3 Vrk = mat3(u1.x, u1.y, u2.x, u1.y, u2.y, u3.x, u2.x, u3.x, u3.y);
|
|
63
|
-
|
|
64
|
-
mat3 J = mat3(
|
|
65
|
-
focal.x / cam.z, 0., -(focal.x * cam.x) / (cam.z * cam.z),
|
|
66
|
-
0., -focal.y / cam.z, (focal.y * cam.y) / (cam.z * cam.z),
|
|
67
|
-
0., 0., 0.
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
mat3 T = transpose(mat3(viewTransform)) * J;
|
|
71
|
-
mat3 cov2d = transpose(T) * Vrk * T;
|
|
72
|
-
|
|
73
|
-
//ref: https://github.com/graphdeco-inria/diff-gaussian-rasterization/blob/main/cuda_rasterizer/forward.cu#L110-L111
|
|
74
|
-
cov2d[0][0] += 0.3;
|
|
75
|
-
cov2d[1][1] += 0.3;
|
|
76
|
-
|
|
77
|
-
float mid = (cov2d[0][0] + cov2d[1][1]) / 2.0;
|
|
78
|
-
float radius = length(vec2((cov2d[0][0] - cov2d[1][1]) / 2.0, cov2d[0][1]));
|
|
79
|
-
float lambda1 = mid + radius, lambda2 = mid - radius;
|
|
80
|
-
|
|
81
|
-
if (lambda2 < 0.0) return;
|
|
82
|
-
vec2 diagonalVector = normalize(vec2(cov2d[0][1], lambda1 - cov2d[0][0]));
|
|
83
|
-
vec2 majorAxis = min(sqrt(2.0 * lambda1), 1024.0) * diagonalVector;
|
|
84
|
-
vec2 minorAxis = min(sqrt(2.0 * lambda2), 1024.0) * vec2(diagonalVector.y, -diagonalVector.x);
|
|
85
|
-
|
|
86
|
-
uint colorTransformIndex = texelFetch(u_colorTransformIndices, ivec2(uint(index) & 0x3ffu, uint(index) >> 10), 0).x;
|
|
87
|
-
mat4 colorTransform = mat4(
|
|
88
|
-
texelFetch(u_colorTransforms, ivec2(0, colorTransformIndex), 0),
|
|
89
|
-
texelFetch(u_colorTransforms, ivec2(1, colorTransformIndex), 0),
|
|
90
|
-
texelFetch(u_colorTransforms, ivec2(2, colorTransformIndex), 0),
|
|
91
|
-
texelFetch(u_colorTransforms, ivec2(3, colorTransformIndex), 0)
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
vec4 color = vec4((cov.w) & 0xffu, (cov.w >> 8) & 0xffu, (cov.w >> 16) & 0xffu, (cov.w >> 24) & 0xffu) / 255.0;
|
|
95
|
-
vColor = colorTransform * color;
|
|
96
|
-
|
|
97
|
-
vPosition = position;
|
|
98
|
-
vSize = length(majorAxis);
|
|
99
|
-
vSelected = selected;
|
|
100
|
-
|
|
101
|
-
float scalingFactor = 1.0;
|
|
102
|
-
|
|
103
|
-
if (useDepthFade) {
|
|
104
|
-
float depthNorm = (pos2d.z / pos2d.w + 1.0) / 2.0;
|
|
105
|
-
float near = 0.1; float far = 100.0;
|
|
106
|
-
float normalizedDepth = (2.0 * near) / (far + near - depthNorm * (far - near));
|
|
107
|
-
float start = max(normalizedDepth - 0.1, 0.0);
|
|
108
|
-
float end = min(normalizedDepth + 0.1, 1.0);
|
|
109
|
-
scalingFactor = clamp((depthFade - start) / (end - start), 0.0, 1.0);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
vec2 vCenter = vec2(pos2d) / pos2d.w;
|
|
113
|
-
gl_Position = vec4(
|
|
114
|
-
vCenter
|
|
115
|
-
+ position.x * majorAxis * scalingFactor / viewport
|
|
116
|
-
+ position.y * minorAxis * scalingFactor / viewport, 0.0, 1.0);
|
|
117
|
-
}
|
|
118
|
-
`}_getFragmentSource(){return`#version 300 es
|
|
119
|
-
precision highp float;
|
|
120
|
-
|
|
121
|
-
uniform float outlineThickness;
|
|
122
|
-
uniform vec4 outlineColor;
|
|
123
|
-
|
|
124
|
-
in vec4 vColor;
|
|
125
|
-
in vec2 vPosition;
|
|
126
|
-
in float vSize;
|
|
127
|
-
in float vSelected;
|
|
128
|
-
|
|
129
|
-
out vec4 fragColor;
|
|
130
|
-
|
|
131
|
-
void main () {
|
|
132
|
-
float A = -dot(vPosition, vPosition);
|
|
133
|
-
|
|
134
|
-
if (A < -4.0) discard;
|
|
135
|
-
|
|
136
|
-
if (vSelected < 0.5) {
|
|
137
|
-
float B = exp(A) * vColor.a;
|
|
138
|
-
fragColor = vec4(B * vColor.rgb, B);
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
float outlineThreshold = -4.0 + (outlineThickness / vSize);
|
|
143
|
-
|
|
144
|
-
if (A < outlineThreshold) {
|
|
145
|
-
fragColor = outlineColor;
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
float B = exp(A) * vColor.a;
|
|
149
|
-
fragColor = vec4(B * vColor.rgb, B);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
`}}class Ht{constructor(t=1){let F,U,l,a,n=0,e=!1;this.initialize=Q=>{if(!(Q instanceof pt))throw new Error("FadeInPass requires a RenderProgram");n=Q.started?1:0,e=!0,F=Q,U=Q.renderer.gl,l=U.getUniformLocation(F.program,"useDepthFade"),U.uniform1i(l,1),a=U.getUniformLocation(F.program,"depthFade"),U.uniform1f(a,n)},this.render=()=>{var Q;e&&!(!((Q=F.renderData)===null||Q===void 0)&&Q.updating)&&(U.useProgram(F.program),n=Math.min(n+.01*t,1),n>=1&&(e=!1,U.uniform1i(l,0)),U.uniform1f(a,n))}}dispose(){}}class Vl{constructor(t=null,F=null){this._backgroundColor=new Gt;const U=t||document.createElement("canvas");t||(U.style.display="block",U.style.boxSizing="border-box",U.style.width="100%",U.style.height="100%",U.style.margin="0",U.style.padding="0",document.body.appendChild(U)),U.style.background=this._backgroundColor.toHexString(),this._canvas=U,this._gl=U.getContext("webgl2",{antialias:!1});const l=F||[];F||l.push(new Ht),this._renderProgram=new pt(this,l);const a=[this._renderProgram];this.resize=()=>{const n=U.clientWidth,e=U.clientHeight;U.width===n&&U.height===e||this.setSize(n,e)},this.setSize=(n,e)=>{U.width=n,U.height=e,this._gl.viewport(0,0,U.width,U.height);for(const Q of a)Q.resize()},this.render=(n,e)=>{for(const Q of a)Q.render(n,e)},this.dispose=()=>{for(const n of a)n.dispose()},this.addProgram=n=>{a.push(n)},this.removeProgram=n=>{const e=a.indexOf(n);if(e<0)throw new Error("Program not found");a.splice(e,1)},this.resize()}get canvas(){return this._canvas}get gl(){return this._gl}get renderProgram(){return this._renderProgram}get backgroundColor(){return this._backgroundColor}set backgroundColor(t){this._backgroundColor=t,this._canvas.style.background=t.toHexString()}}class Bl{constructor(t,F,U=.5,l=.5,a=5,n=!0,e=new I){this.minAngle=-90,this.maxAngle=90,this.minZoom=.1,this.maxZoom=30,this.orbitSpeed=1,this.panSpeed=1,this.zoomSpeed=1,this.dampening=.12,this.setCameraTarget=()=>{};let Q=e.clone(),d=Q.clone(),A=U,i=l,r=a,c=!1,B=!1,W=0,J=0,h=0;const C={};let k=!1;t.addEventListener("objectChanged",()=>{if(k)return;const o=t.rotation.toEuler();A=-o.y,i=-o.x;const T=t.position.x-r*Math.sin(A)*Math.cos(i),v=t.position.y+r*Math.sin(i),x=t.position.z+r*Math.cos(A)*Math.cos(i);d=new I(T,v,x)}),this.setCameraTarget=o=>{const T=o.x-t.position.x,v=o.y-t.position.y,x=o.z-t.position.z;r=Math.sqrt(T*T+v*v+x*x),i=Math.atan2(v,Math.sqrt(T*T+x*x)),A=-Math.atan2(T,x),d=new I(o.x,o.y,o.z)};const p=()=>.1+.9*(r-this.minZoom)/(this.maxZoom-this.minZoom),X=o=>{C[o.code]=!0,o.code==="ArrowUp"&&(C.KeyW=!0),o.code==="ArrowDown"&&(C.KeyS=!0),o.code==="ArrowLeft"&&(C.KeyA=!0),o.code==="ArrowRight"&&(C.KeyD=!0)},D=o=>{C[o.code]=!1,o.code==="ArrowUp"&&(C.KeyW=!1),o.code==="ArrowDown"&&(C.KeyS=!1),o.code==="ArrowLeft"&&(C.KeyA=!1),o.code==="ArrowRight"&&(C.KeyD=!1)},u=o=>{L(o),c=!0,B=o.button===2,J=o.clientX,h=o.clientY,window.addEventListener("mouseup",M)},M=o=>{L(o),c=!1,B=!1,window.removeEventListener("mouseup",M)},E=o=>{if(L(o),!c||!t)return;const T=o.clientX-J,v=o.clientY-h;if(B){const x=p(),At=-T*this.panSpeed*.01*x,Vt=-v*this.panSpeed*.01*x,K=tt.RotationFromQuaternion(t.rotation).buffer,_=new I(K[0],K[3],K[6]),nt=new I(K[1],K[4],K[7]);d=d.add(_.multiply(At)),d=d.add(nt.multiply(Vt))}else A-=T*this.orbitSpeed*.003,i+=v*this.orbitSpeed*.003,i=Math.min(Math.max(i,this.minAngle*Math.PI/180),this.maxAngle*Math.PI/180);J=o.clientX,h=o.clientY},w=o=>{L(o);const T=p();r+=o.deltaY*this.zoomSpeed*.025*T,r=Math.min(Math.max(r,this.minZoom),this.maxZoom)},et=o=>{if(L(o),o.touches.length===1)c=!0,B=!1,J=o.touches[0].clientX,h=o.touches[0].clientY,W=0;else if(o.touches.length===2){c=!0,B=!0,J=(o.touches[0].clientX+o.touches[1].clientX)/2,h=(o.touches[0].clientY+o.touches[1].clientY)/2;const T=o.touches[0].clientX-o.touches[1].clientX,v=o.touches[0].clientY-o.touches[1].clientY;W=Math.sqrt(T*T+v*v)}},Y=o=>{L(o),c=!1,B=!1},H=o=>{if(L(o),c&&t)if(B){const T=p(),v=o.touches[0].clientX-o.touches[1].clientX,x=o.touches[0].clientY-o.touches[1].clientY,At=Math.sqrt(v*v+x*x);r+=(W-At)*this.zoomSpeed*.1*T,r=Math.min(Math.max(r,this.minZoom),this.maxZoom),W=At;const Vt=(o.touches[0].clientX+o.touches[1].clientX)/2,K=(o.touches[0].clientY+o.touches[1].clientY)/2,_=Vt-J,nt=K-h,j=tt.RotationFromQuaternion(t.rotation).buffer,ct=new I(j[0],j[3],j[6]),Jt=new I(j[1],j[4],j[7]);d=d.add(ct.multiply(-_*this.panSpeed*.025*T)),d=d.add(Jt.multiply(-nt*this.panSpeed*.025*T)),J=Vt,h=K}else{const T=o.touches[0].clientX-J,v=o.touches[0].clientY-h;A-=T*this.orbitSpeed*.003,i+=v*this.orbitSpeed*.003,i=Math.min(Math.max(i,this.minAngle*Math.PI/180),this.maxAngle*Math.PI/180),J=o.touches[0].clientX,h=o.touches[0].clientY}},at=(o,T,v)=>(1-v)*o+v*T;this.update=()=>{k=!0,U=at(U,A,this.dampening),l=at(l,i,this.dampening),a=at(a,r,this.dampening),Q=Q.lerp(d,this.dampening);const o=Q.x+a*Math.sin(U)*Math.cos(l),T=Q.y-a*Math.sin(l),v=Q.z-a*Math.cos(U)*Math.cos(l);t.position=new I(o,T,v);const x=Q.subtract(t.position).normalize(),At=Math.asin(-x.y),Vt=Math.atan2(x.x,x.z);t.rotation=z.FromEuler(new I(At,Vt,0));const K=.025,_=.01,nt=tt.RotationFromQuaternion(t.rotation).buffer,j=new I(-nt[2],-nt[5],-nt[8]),ct=new I(nt[0],nt[3],nt[6]);C.KeyS&&(d=d.add(j.multiply(K))),C.KeyW&&(d=d.subtract(j.multiply(K))),C.KeyA&&(d=d.subtract(ct.multiply(K))),C.KeyD&&(d=d.add(ct.multiply(K))),C.KeyE&&(A+=_),C.KeyQ&&(A-=_),C.KeyR&&(i+=_),C.KeyF&&(i-=_),k=!1};const L=o=>{o.preventDefault(),o.stopPropagation()};this.dispose=()=>{F.removeEventListener("dragenter",L),F.removeEventListener("dragover",L),F.removeEventListener("dragleave",L),F.removeEventListener("contextmenu",L),F.removeEventListener("mousedown",u),F.removeEventListener("mousemove",E),F.removeEventListener("wheel",w),F.removeEventListener("touchstart",et),F.removeEventListener("touchend",Y),F.removeEventListener("touchmove",H),n&&(window.removeEventListener("keydown",X),window.removeEventListener("keyup",D))},n&&(window.addEventListener("keydown",X),window.addEventListener("keyup",D)),F.addEventListener("dragenter",L),F.addEventListener("dragover",L),F.addEventListener("dragleave",L),F.addEventListener("contextmenu",L),F.addEventListener("mousedown",u),F.addEventListener("mousemove",E),F.addEventListener("wheel",w),F.addEventListener("touchstart",et),F.addEventListener("touchend",Y),F.addEventListener("touchmove",H),this.update()}}class il{constructor(t,F){this.moveSpeed=1.5,this.lookSpeed=.7,this.dampening=.5;const U={};let l=t.rotation.toEuler().x,a=t.rotation.toEuler().y,n=t.position,e=!1;const Q=()=>{F.requestPointerLock()},d=()=>{e=document.pointerLockElement===F,e?F.addEventListener("mousemove",A):F.removeEventListener("mousemove",A)},A=B=>{const W=B.movementX,J=B.movementY;a+=W*this.lookSpeed*.001,l-=J*this.lookSpeed*.001,l=Math.max(-Math.PI/2,Math.min(Math.PI/2,l))},i=B=>{U[B.code]=!0,B.code==="ArrowUp"&&(U.KeyW=!0),B.code==="ArrowDown"&&(U.KeyS=!0),B.code==="ArrowLeft"&&(U.KeyA=!0),B.code==="ArrowRight"&&(U.KeyD=!0)},r=B=>{U[B.code]=!1,B.code==="ArrowUp"&&(U.KeyW=!1),B.code==="ArrowDown"&&(U.KeyS=!1),B.code==="ArrowLeft"&&(U.KeyA=!1),B.code==="ArrowRight"&&(U.KeyD=!1),B.code==="Escape"&&document.exitPointerLock()};this.update=()=>{const B=tt.RotationFromQuaternion(t.rotation).buffer,W=new I(-B[2],-B[5],-B[8]),J=new I(B[0],B[3],B[6]);let h=new I(0,0,0);U.KeyS&&(h=h.add(W)),U.KeyW&&(h=h.subtract(W)),U.KeyA&&(h=h.subtract(J)),U.KeyD&&(h=h.add(J)),h=new I(h.x,0,h.z),h.magnitude()>0&&(h=h.normalize()),n=n.add(h.multiply(.01*this.moveSpeed)),t.position=t.position.add(n.subtract(t.position).multiply(this.dampening)),t.rotation=z.FromEuler(new I(l,a,0))};const c=B=>{B.preventDefault(),B.stopPropagation()};this.dispose=()=>{F.removeEventListener("dragenter",c),F.removeEventListener("dragover",c),F.removeEventListener("dragleave",c),F.removeEventListener("contextmenu",c),F.removeEventListener("mousedown",Q),document.removeEventListener("pointerlockchange",d),window.removeEventListener("keydown",i),window.removeEventListener("keyup",r)},window.addEventListener("keydown",i),window.addEventListener("keyup",r),F.addEventListener("dragenter",c),F.addEventListener("dragover",c),F.addEventListener("dragleave",c),F.addEventListener("contextmenu",c),F.addEventListener("mousedown",Q),document.addEventListener("pointerlockchange",d),this.update()}}class sl{constructor(t,F){this.normal=t,this.point=F}intersect(t,F){const U=this.normal.dot(F);if(Math.abs(U)<1e-4)return null;const l=this.normal.dot(this.point.subtract(t))/U;return l<0?null:t.add(F.multiply(l))}}class Zl{initialize(t){}render(){}dispose(){}}class Rl extends Nt{constructor(t,F=[]){super(t,F),this._renderData=null,this._depthIndex=new Uint32Array,this._splatTexture=null;const U=t.canvas,l=t.gl;let a,n,e,Q,d,A,i,r,c,B,W;this._resize=()=>{this._camera&&(this._camera.data.setSize(U.width,U.height),this._camera.update(),n=l.getUniformLocation(this.program,"projection"),l.uniformMatrix4fv(n,!1,this._camera.data.projectionMatrix.buffer),e=l.getUniformLocation(this.program,"viewport"),l.uniform2fv(e,new Float32Array([U.width,U.height])))};const J=()=>{t.renderProgram.worker!==null?(a=t.renderProgram.worker,a.onmessage=p=>{if(p.data.depthIndex){const{depthIndex:X}=p.data;this._depthIndex=X,l.bindBuffer(l.ARRAY_BUFFER,W),l.bufferData(l.ARRAY_BUFFER,X,l.STATIC_DRAW)}}):console.error("Render program is not initialized. Cannot render without worker")};this._initialize=()=>{if(!this._scene||!this._camera)return void console.error("Cannot render without scene and camera");this._resize(),this._scene.addEventListener("objectAdded",h),this._scene.addEventListener("objectRemoved",C);for(const u of this._scene.objects)u instanceof Zt&&(this._renderData===null?(this._renderData=u.data,u.addEventListener("objectChanged",k)):console.warn("Multiple Splatv objects are not currently supported"));if(this._renderData===null)return void console.error("Cannot render without Splatv object");Q=l.getUniformLocation(this.program,"focal"),l.uniform2fv(Q,new Float32Array([this._camera.data.fx,this._camera.data.fy])),d=l.getUniformLocation(this.program,"view"),l.uniformMatrix4fv(d,!1,this._camera.data.viewMatrix.buffer),this._splatTexture=l.createTexture(),A=l.getUniformLocation(this.program,"u_texture"),l.uniform1i(A,0),i=l.getUniformLocation(this.program,"time"),l.uniform1f(i,Math.sin(Date.now()/1e3)/2+.5),B=l.createBuffer(),l.bindBuffer(l.ARRAY_BUFFER,B),l.bufferData(l.ARRAY_BUFFER,new Float32Array([-2,-2,2,-2,2,2,-2,2]),l.STATIC_DRAW),r=l.getAttribLocation(this.program,"position"),l.enableVertexAttribArray(r),l.vertexAttribPointer(r,2,l.FLOAT,!1,0,0),W=l.createBuffer(),c=l.getAttribLocation(this.program,"index"),l.enableVertexAttribArray(c),l.bindBuffer(l.ARRAY_BUFFER,W),J(),l.activeTexture(l.TEXTURE0),l.bindTexture(l.TEXTURE_2D,this._splatTexture),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_WRAP_S,l.CLAMP_TO_EDGE),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_WRAP_T,l.CLAMP_TO_EDGE),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_MIN_FILTER,l.NEAREST),l.texParameteri(l.TEXTURE_2D,l.TEXTURE_MAG_FILTER,l.NEAREST),l.texImage2D(l.TEXTURE_2D,0,l.RGBA32UI,this._renderData.width,this._renderData.height,0,l.RGBA_INTEGER,l.UNSIGNED_INT,this._renderData.data);const p=this._renderData.positions,X=new Float32Array(new Ut().buffer),D=new Uint32Array(this._renderData.vertexCount);D.fill(0),a.postMessage({sortData:{positions:p,transforms:X,transformIndices:D,vertexCount:this._renderData.vertexCount}},[p.buffer,X.buffer,D.buffer])};const h=p=>{const X=p;X.object instanceof Zt&&(this._renderData===null?(this._renderData=X.object.data,X.object.addEventListener("objectChanged",k)):console.warn("Splatv not supported by default RenderProgram. Use VideoRenderProgram instead.")),this.dispose()},C=p=>{const X=p;X.object instanceof Zt&&this._renderData===X.object.data&&(this._renderData=null,X.object.removeEventListener("objectChanged",k)),this.dispose()},k=p=>{const X=p;X.object instanceof Zt&&this._renderData===X.object.data&&this.dispose()};this._render=()=>{this._scene&&this._camera?this._renderData?(this._camera.update(),a.postMessage({viewProj:this._camera.data.viewProj.buffer}),l.viewport(0,0,U.width,U.height),l.clearColor(0,0,0,0),l.clear(l.COLOR_BUFFER_BIT),l.disable(l.DEPTH_TEST),l.enable(l.BLEND),l.blendFuncSeparate(l.ONE_MINUS_DST_ALPHA,l.ONE,l.ONE_MINUS_DST_ALPHA,l.ONE),l.blendEquationSeparate(l.FUNC_ADD,l.FUNC_ADD),l.uniformMatrix4fv(n,!1,this._camera.data.projectionMatrix.buffer),l.uniformMatrix4fv(d,!1,this._camera.data.viewMatrix.buffer),l.uniform1f(i,Math.sin(Date.now()/1e3)/2+.5),l.bindBuffer(l.ARRAY_BUFFER,B),l.vertexAttribPointer(r,2,l.FLOAT,!1,0,0),l.bindBuffer(l.ARRAY_BUFFER,W),l.bufferData(l.ARRAY_BUFFER,this._depthIndex,l.STATIC_DRAW),l.vertexAttribIPointer(c,1,l.INT,0,0),l.vertexAttribDivisor(c,1),l.drawArraysInstanced(l.TRIANGLE_FAN,0,4,this._renderData.vertexCount)):console.warn("Cannot render without Splatv object"):console.error("Cannot render without scene and camera")},this._dispose=()=>{if(this._scene&&this._camera){this._scene.removeEventListener("objectAdded",h),this._scene.removeEventListener("objectRemoved",C);for(const p of this._scene.objects)p instanceof Zt&&this._renderData===p.data&&(this._renderData=null,p.removeEventListener("objectChanged",k));a==null||a.terminate(),l.deleteTexture(this._splatTexture),l.deleteBuffer(W),l.deleteBuffer(B)}else console.error("Cannot dispose without scene and camera")}}get renderData(){return this._renderData}_getVertexSource(){return`#version 300 es
|
|
153
|
-
precision highp float;
|
|
154
|
-
precision highp int;
|
|
155
|
-
|
|
156
|
-
uniform highp usampler2D u_texture;
|
|
157
|
-
uniform mat4 projection, view;
|
|
158
|
-
uniform vec2 focal;
|
|
159
|
-
uniform vec2 viewport;
|
|
160
|
-
uniform float time;
|
|
161
|
-
|
|
162
|
-
in vec2 position;
|
|
163
|
-
in int index;
|
|
164
|
-
|
|
165
|
-
out vec4 vColor;
|
|
166
|
-
out vec2 vPosition;
|
|
167
|
-
|
|
168
|
-
void main () {
|
|
169
|
-
gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
|
|
170
|
-
|
|
171
|
-
uvec4 motion1 = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 2) | 3u, uint(index) >> 10), 0);
|
|
172
|
-
vec2 trbf = unpackHalf2x16(motion1.w);
|
|
173
|
-
float dt = time - trbf.x;
|
|
174
|
-
|
|
175
|
-
float topacity = exp(-1.0 * pow(dt / trbf.y, 2.0));
|
|
176
|
-
if(topacity < 0.02) return;
|
|
177
|
-
|
|
178
|
-
uvec4 motion0 = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 2) | 2u, uint(index) >> 10), 0);
|
|
179
|
-
uvec4 static0 = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 2), uint(index) >> 10), 0);
|
|
180
|
-
|
|
181
|
-
vec2 m0 = unpackHalf2x16(motion0.x), m1 = unpackHalf2x16(motion0.y), m2 = unpackHalf2x16(motion0.z),
|
|
182
|
-
m3 = unpackHalf2x16(motion0.w), m4 = unpackHalf2x16(motion1.x);
|
|
183
|
-
|
|
184
|
-
vec4 trot = vec4(unpackHalf2x16(motion1.y).xy, unpackHalf2x16(motion1.z).xy) * dt;
|
|
185
|
-
vec3 tpos = (vec3(m0.xy, m1.x) * dt + vec3(m1.y, m2.xy) * dt*dt + vec3(m3.xy, m4.x) * dt*dt*dt);
|
|
186
|
-
|
|
187
|
-
vec4 cam = view * vec4(uintBitsToFloat(static0.xyz) + tpos, 1);
|
|
188
|
-
vec4 pos = projection * cam;
|
|
189
|
-
|
|
190
|
-
float clip = 1.2 * pos.w;
|
|
191
|
-
if (pos.z < -clip || pos.x < -clip || pos.x > clip || pos.y < -clip || pos.y > clip) return;
|
|
192
|
-
uvec4 static1 = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 2) | 1u, uint(index) >> 10), 0);
|
|
193
|
-
|
|
194
|
-
vec4 rot = vec4(unpackHalf2x16(static0.w).xy, unpackHalf2x16(static1.x).xy) + trot;
|
|
195
|
-
vec3 scale = vec3(unpackHalf2x16(static1.y).xy, unpackHalf2x16(static1.z).x);
|
|
196
|
-
rot /= sqrt(dot(rot, rot));
|
|
197
|
-
|
|
198
|
-
mat3 S = mat3(scale.x, 0.0, 0.0, 0.0, scale.y, 0.0, 0.0, 0.0, scale.z);
|
|
199
|
-
mat3 R = mat3(
|
|
200
|
-
1.0 - 2.0 * (rot.z * rot.z + rot.w * rot.w), 2.0 * (rot.y * rot.z - rot.x * rot.w), 2.0 * (rot.y * rot.w + rot.x * rot.z),
|
|
201
|
-
2.0 * (rot.y * rot.z + rot.x * rot.w), 1.0 - 2.0 * (rot.y * rot.y + rot.w * rot.w), 2.0 * (rot.z * rot.w - rot.x * rot.y),
|
|
202
|
-
2.0 * (rot.y * rot.w - rot.x * rot.z), 2.0 * (rot.z * rot.w + rot.x * rot.y), 1.0 - 2.0 * (rot.y * rot.y + rot.z * rot.z));
|
|
203
|
-
mat3 M = S * R;
|
|
204
|
-
mat3 Vrk = 4.0 * transpose(M) * M;
|
|
205
|
-
mat3 J = mat3(
|
|
206
|
-
focal.x / cam.z, 0., -(focal.x * cam.x) / (cam.z * cam.z),
|
|
207
|
-
0., -focal.y / cam.z, (focal.y * cam.y) / (cam.z * cam.z),
|
|
208
|
-
0., 0., 0.
|
|
209
|
-
);
|
|
210
|
-
|
|
211
|
-
mat3 T = transpose(mat3(view)) * J;
|
|
212
|
-
mat3 cov2d = transpose(T) * Vrk * T;
|
|
213
|
-
|
|
214
|
-
float mid = (cov2d[0][0] + cov2d[1][1]) / 2.0;
|
|
215
|
-
float radius = length(vec2((cov2d[0][0] - cov2d[1][1]) / 2.0, cov2d[0][1]));
|
|
216
|
-
float lambda1 = mid + radius, lambda2 = mid - radius;
|
|
217
|
-
|
|
218
|
-
if(lambda2 < 0.0) return;
|
|
219
|
-
vec2 diagonalVector = normalize(vec2(cov2d[0][1], lambda1 - cov2d[0][0]));
|
|
220
|
-
vec2 majorAxis = min(sqrt(2.0 * lambda1), 1024.0) * diagonalVector;
|
|
221
|
-
vec2 minorAxis = min(sqrt(2.0 * lambda2), 1024.0) * vec2(diagonalVector.y, -diagonalVector.x);
|
|
222
|
-
|
|
223
|
-
uint rgba = static1.w;
|
|
224
|
-
vColor =
|
|
225
|
-
clamp(pos.z/pos.w+1.0, 0.0, 1.0) *
|
|
226
|
-
vec4(1.0, 1.0, 1.0, topacity) *
|
|
227
|
-
vec4(
|
|
228
|
-
(rgba) & 0xffu,
|
|
229
|
-
(rgba >> 8) & 0xffu,
|
|
230
|
-
(rgba >> 16) & 0xffu,
|
|
231
|
-
(rgba >> 24) & 0xffu) / 255.0;
|
|
232
|
-
|
|
233
|
-
vec2 vCenter = vec2(pos) / pos.w;
|
|
234
|
-
gl_Position = vec4(
|
|
235
|
-
vCenter
|
|
236
|
-
+ position.x * majorAxis / viewport
|
|
237
|
-
+ position.y * minorAxis / viewport, 0.0, 1.0);
|
|
238
|
-
|
|
239
|
-
vPosition = position;
|
|
240
|
-
}
|
|
241
|
-
`}_getFragmentSource(){return`#version 300 es
|
|
242
|
-
precision highp float;
|
|
243
|
-
|
|
244
|
-
in vec4 vColor;
|
|
245
|
-
in vec2 vPosition;
|
|
246
|
-
|
|
247
|
-
out vec4 fragColor;
|
|
248
|
-
|
|
249
|
-
void main () {
|
|
250
|
-
float A = -dot(vPosition, vPosition);
|
|
251
|
-
if (A < -4.0) discard;
|
|
252
|
-
float B = exp(A) * vColor.a;
|
|
253
|
-
fragColor = vec4(B * vColor.rgb, B);
|
|
254
|
-
}
|
|
255
|
-
`}}class mt{constructor(t,F,U){this.bounds=t,this.boxes=F,this.left=null,this.right=null,this.pointIndices=[],U.length>1?this.split(t,F,U):U.length>0&&(this.pointIndices=U)}split(t,F,U){const l=t.size().maxComponent();U.sort((Q,d)=>F[Q].center().getComponent(l)-F[d].center().getComponent(l));const a=Math.floor(U.length/2),n=U.slice(0,a),e=U.slice(a);this.left=new mt(t,F,n),this.right=new mt(t,F,e)}queryRange(t){return this.bounds.intersects(t)?this.left!==null&&this.right!==null?this.left.queryRange(t).concat(this.right.queryRange(t)):this.pointIndices.filter(F=>t.intersects(this.boxes[F])):[]}}class cl{constructor(t,F){const U=F.map((l,a)=>a);this.root=new mt(t,F,U)}queryRange(t){return this.root.queryRange(t)}}class ol{constructor(t,F=100,U=1){let l=0,a=null,n=[];this.testPoint=(e,Q)=>{if(t.renderData===null||t.camera===null)return console.error("IntersectionTester cannot be called before renderProgram has been initialized"),null;if((()=>{if(t.renderData===null)return void console.error("IntersectionTester cannot be called before renderProgram has been initialized");n=[];const r=t.renderData,c=new Array(r.offsets.size);let B=0;const W=new ot(new I(1/0,1/0,1/0),new I(-1/0,-1/0,-1/0));for(const J of r.offsets.keys()){const h=J.bounds;c[B++]=h,W.expand(h.min),W.expand(h.max),n.push(J)}W.permute(),a=new cl(W,c),l=r.vertexCount})(),a===null)return console.error("Failed to build octree for IntersectionTester"),null;const d=t.renderData,A=t.camera;l!==d.vertexCount&&console.warn("IntersectionTester has not been rebuilt since the last render");const i=A.screenPointToRay(e,Q);for(let r=0;r<F;r+=U){const c=A.position.add(i.multiply(r)),B=new I(c.x-U/2,c.y-U/2,c.z-U/2),W=new I(c.x+U/2,c.y+U/2,c.z+U/2),J=new ot(B,W),h=a.queryRange(J);if(h.length>0)return n[h[0]]}return null}}}exports.Camera=ll;exports.CameraData=Yt;exports.Color32=Gt;exports.FPSControls=il;exports.FadeInPass=Ht;exports.IntersectionTester=ol;exports.Loader=Fl;exports.Matrix3=tt;exports.Matrix4=Ut;exports.Object3D=It;exports.OrbitControls=Bl;exports.PLYLoader=el;exports.Plane=sl;exports.Quaternion=z;exports.RenderData=Tt;exports.RenderProgram=pt;exports.Scene=Ul;exports.ShaderPass=Zl;exports.ShaderProgram=Nt;exports.Splat=Qt;exports.SplatData=lt;exports.Splatv=Zt;exports.SplatvData=rt;exports.SplatvLoader=nl;exports.Vector3=I;exports.Vector4=Ft;exports.VideoRenderProgram=Rl;exports.WebGLRenderer=Vl;
|