@onirix/ar-engine-sdk 1.10.0 → 1.11.0
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 +10 -0
- package/dist/onirix_native_sdk.js +1 -1
- package/dist/ox-sdk.esm.js +3 -3
- package/package.json +3 -3
package/dist/ox-sdk.esm.js
CHANGED
@@ -38,7 +38,7 @@ class Euler{constructor(t=0,a=0,h=0,s="XYZ"){this.x=t,this.y=a,this.z=h,this.ord
|
|
38
38
|
|
39
39
|
const mat4RotationZ90CCW=(new Matrix4).set(0,1,0,0,-1,0,0,0,0,0,1,0,0,0,0,1),mat4RotationZ90CW=(new Matrix4).set(0,-1,0,0,1,0,0,0,0,0,1,0,0,0,0,1),mat4RotationX90CW=(new Matrix4).set(1,0,0,0,0,0,1,0,0,-1,0,0,0,0,0,1),mat3RotationX90CCW=(new Matrix3).set(1,0,0,0,0,1,0,-1,0),mat3RotationZ90CW=(new Matrix3).set(0,-1,0,1,0,0,0,0,1);
|
40
40
|
|
41
|
-
class NativeManager{constructor(t,i,e,a){this.uiManager=t,this.deviceManager=i,this.workerManager=e,this.indexedDBManager=a,this.webXRRelocationListener=null,this.osfStrBuffer=null;}async init(t,i){try{let e=new URL("./onirix_native_sdk.js",import.meta.url),a=await this.indexedDBManager.getFromCacheOrFetch("SDK_1.10.0",e),r=URL.createObjectURL(new Blob([a],{type:"text/javascript"}));const{default:s}=await import(/* webpackIgnore: true, webpackMode: "lazy" */r);let n,o,h;if(this.useVocabulary=i.useVocabulary,this.host=i.host??"https://studio.onirix.com",this.useVocabulary&&(n=await this.indexedDBManager.getFromCacheOrFetch("orb.fbow","https://cdn.onirix.com/onirix-engine-sdk/orb.fbow")),i.mode===TrackingMode.Spatial){if(o=await fetch(`${this.host}/api/projects/self/targets/${i.sceneOid}/osf?token=${t}`),!o.ok)throw new ReconstructionPendingError(`Could not get Onirix Spatial File. Server responded with ${o.status}`);const e=await o.arrayBuffer();h=new Uint8Array(e),await this.workerManager.createWorkers();}this.nativeSDK=await s({preRun:e=>{i.mode==TrackingMode.Spatial?e.FS_createDataFile("/","scene.osf",h,!0,!0,!0):i.mode===TrackingMode.Curved||i.mode===TrackingMode.Image?(this.useVocabulary&&e.FS_createDataFile("/","orb.fbow",n,!0,!0,!0),e.FS_createPreloadedFile("/","classifier.otf",`${this.host}/api/projects/self/targets/otf?token=${t}`,!0,!1)):i.mode===TrackingMode.Surface&&this.useVocabulary&&e.FS_createDataFile("/","orb.fbow",n,!0,!0,!0);}}),this.spatialBufferSize=this.getBufferSize(),this.buffer=this.nativeSDK._malloc(1228800),this.imageBuffer=this.nativeSDK._malloc(1228800),this.imuAccData=this.nativeSDK._malloc(32),this.imuRotData=this.nativeSDK._malloc(72),this.cameraParamsStruct=this.nativeSDK._malloc(40),this.frameLayoutStruct=this.nativeSDK._malloc(28),this.nativeSDK.HEAPU32[this.cameraParamsStruct/4+0]=640,this.nativeSDK.HEAPU32[this.cameraParamsStruct/4+1]=480,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+1]=468,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+2]=468,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+3]=320,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+4]=240,i.debug&&this.nativeSDK._OX_SetLogCallback(this.nativeSDK.addFunction((t=>{console.log(`[OnirixEngineSDK] ${this.nativeSDK.UTF8ToString(t)}`);}),"vi"));}catch(t){throw console.log(t),t instanceof ReconstructionPendingError?t:new InternalError(t)}await this.checkLicense(t,i);}getBufferSize(){return this.nativeSDK._OX_GetBufferSize()}getIntrinsics(){return [this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+2],this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+3],this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+4]]}setIntrinsics(t,i,e){this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+1]=t,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+2]=t,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+3]=i,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+4]=e,this.nativeSDK._OX_UpdateIntrinsics(t,i,e);}async checkLicense(t,i){try{const e=this.getStringBuffer(this.host),a=this.getStringBuffer(t),r=this.getStringBuffer(window.location.hostname),s=this.getStringBuffer(this.deviceManager.platform),n=this.getStringBuffer(this.deviceManager.device),o=this.getStringBuffer(JSON.stringify(i)),h=await new Promise(((t,i)=>{this.nativeSDK._OX_SetLicense([e],[a],[r],[s],[n],[o],this.nativeSDK.addFunction(((i,e)=>t({ivl:i,oxError:this.nativeSDK.UTF8ToString(e)})),"vii"));}));if(this.releaseStringBuffer(e),this.releaseStringBuffer(a),this.releaseStringBuffer(r),this.releaseStringBuffer(s),this.releaseStringBuffer(n),this.releaseStringBuffer(o),!h.ivl)throw new LicenseError("Invalid license",h.oxError)}catch(t){throw new LicenseError(t,t.oxError)}}startImageTracking(t,i,e,a,r=!1){if(this.onDetected=t,this.onPose=i,this.onLost=e,this.useVocabulary){const t=this.getStringBuffer("orb.fbow");this.nativeSDK._OX_Initialize(this.cameraParamsStruct,[t]),this.releaseStringBuffer(t);}else this.nativeSDK._OX_Initialize(this.cameraParamsStruct,"");let s=this.getStringBuffer("classifier.otf");this.nativeSDK._OX_LoadImageClassifier([s]),this.releaseStringBuffer(s),this.nativeSDK._OX_StartImageDetection(2,r?1:a,this.nativeSDK.addFunction((t=>this.onDetected(this.nativeSDK.UTF8ToString(t))),"vi"),this.nativeSDK.addFunction((t=>{const i=this.nativeSDK.HEAPF64.subarray(t/8,t/8+16);let e=(new Matrix4).fromArray(i);e.multiply(mat4RotationX90CW),e.invert(),this.uiManager.isPortrait()?(e.multiply(r?mat4RotationZ90CW:mat4RotationZ90CCW),this.onPose(e.toArray())):this.onPose(e.toArray());}),"vi"),this.nativeSDK.addFunction((t=>this.onLost(this.nativeSDK.UTF8ToString(t))),"vi"));}startCurvedImageTracking(t,i,e){if(this.onDetected=t,this.onPose=i,this.onLost=e,this.useVocabulary){const t=this.getStringBuffer("orb.fbow");this.nativeSDK._OX_Initialize(this.cameraParamsStruct,[t]),this.releaseStringBuffer(t);}else this.nativeSDK._OX_Initialize(this.cameraParamsStruct,"");let a=this.getStringBuffer("classifier.otf");this.nativeSDK._OX_LoadImageClassifier([a]),this.releaseStringBuffer(a),this.nativeSDK._OX_StartCurvedImageDetection(2,1,this.nativeSDK.addFunction((t=>this.onDetected(this.nativeSDK.UTF8ToString(t))),"vi"),this.nativeSDK.addFunction((t=>{const i=this.nativeSDK.HEAPF64.subarray(t/8,t/8+16);let e=(new Matrix4).fromArray(i);e.multiply(mat4RotationX90CW),e.invert(),this.uiManager.isPortrait()?(e.multiply(mat4RotationZ90CCW),this.onPose(e.toArray())):this.onPose(e.toArray());}),"vi"),this.nativeSDK.addFunction((t=>this.onLost(this.nativeSDK.UTF8ToString(t))),"vi"));}startQRCodeTracking(t,i,e){this.onDetected=t,this.onPose=i,this.onLost=e,this.nativeSDK._OX_Initialize(this.cameraParamsStruct,""),this.nativeSDK._OX_StartQRCodeDetection(2,this.nativeSDK.addFunction((t=>this.onDetected(this.nativeSDK.UTF8ToString(t))),"vi"),this.nativeSDK.addFunction((t=>{const i=this.nativeSDK.HEAPF64.subarray(t/8,t/8+16);let e=(new Matrix4).fromArray(i);e.multiply(mat4RotationX90CW),e.invert(),this.uiManager.isPortrait()?(e.multiply(mat4RotationZ90CCW),this.onPose(e.toArray())):this.onPose(e.toArray());}),"vi"),this.nativeSDK.addFunction((t=>this.onLost(this.nativeSDK.UTF8ToString(t))),"vi"));}startSLAM(t,i,e){if(this.onPose=t,this.onKeyFrame=i,this.onStatusChange=e,this.useVocabulary){const t=this.getStringBuffer("orb.fbow");this.nativeSDK._OX_Initialize(this.cameraParamsStruct,[t]),this.releaseStringBuffer(t);}else this.nativeSDK._OX_Initialize(this.cameraParamsStruct,"");this.nativeSDK._OX_StartSLAM(this.nativeSDK.addFunction((t=>{const i=this.nativeSDK.HEAPF64.subarray(t/8,t/8+16);let e=(new Matrix4).fromArray(i);e.invert(),this.uiManager.isPortrait()?(e.multiply(mat4RotationZ90CCW),this.onPose(e.toArray())):this.onPose(e.toArray());}),"vi"),null!=this.onKeyFrame?this.nativeSDK.addFunction((()=>this.onKeyFrame()),"v"):null,this.nativeSDK.addFunction(((t,i)=>{this.onStatusChange([this.nativeSDK.UTF8ToString(t),this.nativeSDK.UTF8ToString(i)]);}),"vii"));}startSpatialTracking(t,i,e){if(this.onDetected=t,e||(this.onPose=i),this.nativeSDK._OX_Initialize(this.cameraParamsStruct,""),this.nativeSDK._OX_StartSpatialTracking(this.nativeSDK.addFunction((t=>{e||(this.spatialLocated=!0),this.onDetected("");}),"vi"),this.nativeSDK.addFunction((t=>{const i=this.nativeSDK.HEAPF64.subarray(t/8,t/8+16);let a=(new Matrix4).fromArray(i);a.invert(),this.uiManager.isPortrait()&&a.multiply(e?mat4RotationZ90CW:mat4RotationZ90CCW),e?(this.webXRRelocationListener(a),this.onDetected("")):this.onPose(a.toArray());}),"vi"),!e),this.osfStrBuffer=this.getStringBuffer("scene.osf"),this.nativeSDK._OX_LoadOSF(this.osfStrBuffer),!e&&2==this.extractionType())throw new InternalError("Onirix compatibility mode for WorldTracking is not supported for Spatial scenes.")}processFrame(t,i=null,e=480,a=640,r=0,s=0){let n=i||this.buffer;this.nativeSDK.HEAPU8.set(t,n),this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+0]=a,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+1]=e,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+2]=4*a,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+3]=!1,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+4]=5,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+5]=s,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+6]=r,this.nativeSDK._OX_ProcessFrame(n,this.frameLayoutStruct);}getXRFrameBuffer(t,i){return this.xrBuffer||(this.xrBuffer=this.nativeSDK._malloc(t*i*4)),this.xrBuffer}initExtractionBuffers(){this.extractionBuffer=this.nativeSDK._malloc(4*this.spatialBufferSize),this.matchBuffer=this.nativeSDK._malloc(14e3),this.coarseLocationBuffer=this.nativeSDK._malloc(32768);}loadExtractionData(t,i=-1){return this.extractionBuffer&&this.coarseLocationBuffer?(this.nativeSDK.HEAPF32.set(t.extraction,this.extractionBuffer/4),this.nativeSDK.HEAPF32.set(t.descriptor,this.coarseLocationBuffer/4),this.nativeSDK._OX_LoadExtractionData(this.extractionBuffer,this.coarseLocationBuffer,i)):0}coarseLocationCheck(t){return this.coarseLocationBuffer?(this.nativeSDK.HEAPF32.set(t.descriptor,this.coarseLocationBuffer/4),this.nativeSDK._OX_CoarseLocationCheck(this.coarseLocationBuffer)):0}getCandidateData(t){let i=this.nativeSDK._OX_GetCandidateData(t);return new Float32Array(this.nativeSDK.HEAPF32.buffer,i,this.spatialBufferSize)}loadMatch(t){this.matchBuffer&&(this.nativeSDK.HEAPF32.set(t,this.matchBuffer/4),this.nativeSDK._OX_LoadMatch(this.matchBuffer));}spatialLocalize(){return this.nativeSDK._OX_SpatialLocalize()}setSpatialQualityLevel(t){return this.nativeSDK._OX_SetSpatialQualityLevel(t)}loadKeyframePose(t){this.nativeSDK._OX_LoadKfPose(t);}numSLAMKeyframes(){return this.nativeSDK._OX_GetSLAMNumKfs()}getSLAMKeyframe(t){let i=this.nativeSDK._OX_GetSLAMKf(t),e=[];for(let t=0;t<1228800;t++)e.push(this.nativeSDK.HEAPU8[i+t]);return new Uint8Array(e)}stopImageTracking(){this.nativeSDK._OX_StopImageDetection();}stopQRCodeTracking(){this.nativeSDK._OX_StopQRCodeDetection();}stopSLAM(){this.nativeSDK._OX_StopSLAM();}stopSpatialTracking(){this.nativeSDK._OX_StopSpatialTracking();}addImage(t,i){this.nativeSDK.HEAPU8.set(i,this.imageBuffer),this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+0]=640,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+1]=480,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+2]=2560,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+3]=!1,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+4]=5,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+5]=0,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+6]=0;const e=this.getStringBuffer(t);this.nativeSDK._OX_AddImage([e],this.imageBuffer,this.frameLayoutStruct),this.releaseStringBuffer(e);}destroy(){this.nativeSDK._OX_Destroy(),this.osfStrBuffer&&this.releaseStringBuffer(this.osfStrBuffer);}extractionType(){return this.nativeSDK._OX_ExtractionType()}getStringBuffer(t){const i=this.nativeSDK.lengthBytesUTF8(t)+1;let e=this.nativeSDK._malloc(i);return this.nativeSDK.stringToUTF8(t,e,i),e}releaseStringBuffer(t){this.nativeSDK._free(t);}parseNativeJSON(t){let i;try{i=JSON.parse(t);}catch(i){console.error(`Could not parse ${t}`);}return i}getSLAMMap(){return this.parseNativeJSON(this.nativeSDK.UTF8ToString(this.nativeSDK._OX_GetSLAMMap()))}getSLAMTrackingPoints(){return this.parseNativeJSON(this.nativeSDK.UTF8ToString(this.nativeSDK._OX_GetSLAMTrackingPoints()))}raycast(t,i,e,a,r,s){return this.parseNativeJSON(this.nativeSDK.UTF8ToString(this.nativeSDK._OX_Raycast(t,i,e,a,r,s)))}getSpatialMap(){return this.parseNativeJSON(this.nativeSDK.UTF8ToString(this.nativeSDK._OX_GetSpatialMap()))}setWebXRRelocationListener(t){this.webXRRelocationListener=t;}}
|
41
|
+
class NativeManager{constructor(t,i,e,a){this.uiManager=t,this.deviceManager=i,this.workerManager=e,this.indexedDBManager=a,this.webXRRelocationListener=null,this.osfStrBuffer=null;}async init(t,i){try{let e=new URL("./onirix_native_sdk.js",import.meta.url),a=await this.indexedDBManager.getFromCacheOrFetch("SDK_1.11.0",e),r=URL.createObjectURL(new Blob([a],{type:"text/javascript"}));const{default:s}=await import(/* webpackIgnore: true, webpackMode: "lazy" */r);let n,o,h;if(this.useVocabulary=i.useVocabulary,this.host=i.host??"https://studio.onirix.com",this.useVocabulary&&(n=await this.indexedDBManager.getFromCacheOrFetch("orb.fbow","https://cdn.onirix.com/onirix-engine-sdk/orb.fbow")),i.mode===TrackingMode.Spatial){if(o=await fetch(`${this.host}/api/projects/self/targets/${i.sceneOid}/osf?token=${t}`),!o.ok)throw new ReconstructionPendingError(`Could not get Onirix Spatial File. Server responded with ${o.status}`);const e=await o.arrayBuffer();h=new Uint8Array(e),await this.workerManager.createWorkers();}this.nativeSDK=await s({preRun:e=>{i.mode==TrackingMode.Spatial?e.FS_createDataFile("/","scene.osf",h,!0,!0,!0):i.mode===TrackingMode.Curved||i.mode===TrackingMode.Image?(this.useVocabulary&&e.FS_createDataFile("/","orb.fbow",n,!0,!0,!0),e.FS_createPreloadedFile("/","classifier.otf",`${this.host}/api/projects/self/targets/otf?token=${t}`,!0,!1)):i.mode===TrackingMode.Surface&&this.useVocabulary&&e.FS_createDataFile("/","orb.fbow",n,!0,!0,!0);}}),this.spatialBufferSize=this.getBufferSize(),this.lastPoseBuffer=this.nativeSDK._malloc(64),this.buffer=this.nativeSDK._malloc(1228800),this.imageBuffer=this.nativeSDK._malloc(1228800),this.imuAccData=this.nativeSDK._malloc(32),this.imuRotData=this.nativeSDK._malloc(72),this.cameraParamsStruct=this.nativeSDK._malloc(40),this.frameLayoutStruct=this.nativeSDK._malloc(28),this.nativeSDK.HEAPU32[this.cameraParamsStruct/4+0]=640,this.nativeSDK.HEAPU32[this.cameraParamsStruct/4+1]=480,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+1]=468,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+2]=468,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+3]=320,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+4]=240,i.debug&&this.nativeSDK._OX_SetLogCallback(this.nativeSDK.addFunction((t=>{console.log(`[OnirixEngineSDK] ${this.nativeSDK.UTF8ToString(t)}`);}),"vi"));}catch(t){throw console.log(t),t instanceof ReconstructionPendingError?t:new InternalError(t)}await this.checkLicense(t,i);}getBufferSize(){return this.nativeSDK._OX_GetBufferSize()}getIntrinsics(){return [this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+2],this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+3],this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+4]]}setIntrinsics(t,i,e){this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+1]=t,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+2]=t,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+3]=i,this.nativeSDK.HEAPF64[this.cameraParamsStruct/8+4]=e,this.nativeSDK._OX_UpdateIntrinsics(t,i,e);}async checkLicense(t,i){try{const e=this.getStringBuffer(this.host),a=this.getStringBuffer(t),r=this.getStringBuffer(window.location.hostname),s=this.getStringBuffer(this.deviceManager.platform),n=this.getStringBuffer(this.deviceManager.device),o=this.getStringBuffer(JSON.stringify(i)),h=await new Promise(((t,i)=>{this.nativeSDK._OX_SetLicense([e],[a],[r],[s],[n],[o],this.nativeSDK.addFunction(((i,e)=>t({ivl:i,oxError:this.nativeSDK.UTF8ToString(e)})),"vii"));}));if(this.releaseStringBuffer(e),this.releaseStringBuffer(a),this.releaseStringBuffer(r),this.releaseStringBuffer(s),this.releaseStringBuffer(n),this.releaseStringBuffer(o),!h.ivl)throw new LicenseError("Invalid license",h.oxError)}catch(t){throw new LicenseError(t,t.oxError)}}startImageTracking(t,i,e,a,r=!1){if(this.onDetected=t,this.onPose=i,this.onLost=e,this.useVocabulary){const t=this.getStringBuffer("orb.fbow");this.nativeSDK._OX_Initialize(this.cameraParamsStruct,[t]),this.releaseStringBuffer(t);}else this.nativeSDK._OX_Initialize(this.cameraParamsStruct,"");let s=this.getStringBuffer("classifier.otf");this.nativeSDK._OX_LoadImageClassifier([s]),this.releaseStringBuffer(s),this.nativeSDK._OX_StartImageDetection(2,r?1:a,this.nativeSDK.addFunction((t=>this.onDetected(this.nativeSDK.UTF8ToString(t))),"vi"),this.nativeSDK.addFunction((t=>{const i=this.nativeSDK.HEAPF64.subarray(t/8,t/8+16);let e=(new Matrix4).fromArray(i);e.multiply(mat4RotationX90CW),e.invert(),this.uiManager.isPortrait()?(e.multiply(r?mat4RotationZ90CW:mat4RotationZ90CCW),this.onPose(e.toArray())):this.onPose(e.toArray());}),"vi"),this.nativeSDK.addFunction((t=>this.onLost(this.nativeSDK.UTF8ToString(t))),"vi"));}startCurvedImageTracking(t,i,e){if(this.onDetected=t,this.onPose=i,this.onLost=e,this.useVocabulary){const t=this.getStringBuffer("orb.fbow");this.nativeSDK._OX_Initialize(this.cameraParamsStruct,[t]),this.releaseStringBuffer(t);}else this.nativeSDK._OX_Initialize(this.cameraParamsStruct,"");let a=this.getStringBuffer("classifier.otf");this.nativeSDK._OX_LoadImageClassifier([a]),this.releaseStringBuffer(a),this.nativeSDK._OX_StartCurvedImageDetection(2,1,this.nativeSDK.addFunction((t=>this.onDetected(this.nativeSDK.UTF8ToString(t))),"vi"),this.nativeSDK.addFunction((t=>{const i=this.nativeSDK.HEAPF64.subarray(t/8,t/8+16);let e=(new Matrix4).fromArray(i);e.multiply(mat4RotationX90CW),e.invert(),this.uiManager.isPortrait()?(e.multiply(mat4RotationZ90CCW),this.onPose(e.toArray())):this.onPose(e.toArray());}),"vi"),this.nativeSDK.addFunction((t=>this.onLost(this.nativeSDK.UTF8ToString(t))),"vi"));}startQRCodeTracking(t,i,e){this.onDetected=t,this.onPose=i,this.onLost=e,this.nativeSDK._OX_Initialize(this.cameraParamsStruct,""),this.nativeSDK._OX_StartQRCodeDetection(2,this.nativeSDK.addFunction((t=>this.onDetected(this.nativeSDK.UTF8ToString(t))),"vi"),this.nativeSDK.addFunction((t=>{const i=this.nativeSDK.HEAPF64.subarray(t/8,t/8+16);let e=(new Matrix4).fromArray(i);e.multiply(mat4RotationX90CW),e.invert(),this.uiManager.isPortrait()?(e.multiply(mat4RotationZ90CCW),this.onPose(e.toArray())):this.onPose(e.toArray());}),"vi"),this.nativeSDK.addFunction((t=>this.onLost(this.nativeSDK.UTF8ToString(t))),"vi"));}startSLAM(t,i,e){if(this.onPose=t,this.onKeyFrame=i,this.onStatusChange=e,this.useVocabulary){const t=this.getStringBuffer("orb.fbow");this.nativeSDK._OX_Initialize(this.cameraParamsStruct,[t]),this.releaseStringBuffer(t);}else this.nativeSDK._OX_Initialize(this.cameraParamsStruct,"");this.nativeSDK._OX_StartSLAM(this.nativeSDK.addFunction((t=>{const i=this.nativeSDK.HEAPF64.subarray(t/8,t/8+16);let e=(new Matrix4).fromArray(i);e.invert(),this.uiManager.isPortrait()?(e.multiply(mat4RotationZ90CCW),this.onPose(e.toArray())):this.onPose(e.toArray());}),"vi"),null!=this.onKeyFrame?this.nativeSDK.addFunction((()=>this.onKeyFrame()),"v"):null,this.nativeSDK.addFunction(((t,i)=>{this.onStatusChange([this.nativeSDK.UTF8ToString(t),this.nativeSDK.UTF8ToString(i)]);}),"vii"));}startSpatialTracking(t,i,e){if(this.onDetected=t,e||(this.onPose=i),this.nativeSDK._OX_Initialize(this.cameraParamsStruct,""),this.nativeSDK._OX_StartSpatialTracking(this.nativeSDK.addFunction((t=>{e||(this.spatialLocated=!0),this.onDetected("");}),"vi"),this.nativeSDK.addFunction((t=>{const i=this.nativeSDK.HEAPF64.subarray(t/8,t/8+16);let a=(new Matrix4).fromArray(i);e?(this.webXRRelocationListener(a),this.onDetected("")):this.onPose(a.toArray());}),"vi"),!e),this.osfStrBuffer=this.getStringBuffer("scene.osf"),this.nativeSDK._OX_LoadOSF(this.osfStrBuffer),!e&&2==this.extractionType())throw new InternalError("Onirix compatibility mode for WorldTracking is not supported for Spatial scenes.")}processFrame(t,i=null,e=480,a=640,r=0,s=0){let n=i||this.buffer;this.nativeSDK.HEAPU8.set(t,n),this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+0]=a,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+1]=e,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+2]=4*a,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+3]=!1,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+4]=5,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+5]=s,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+6]=r,this.nativeSDK._OX_ProcessFrame(n,this.frameLayoutStruct);}getXRFrameBuffer(t,i){return this.xrBuffer||(this.xrBuffer=this.nativeSDK._malloc(t*i*4)),this.xrBuffer}initExtractionBuffers(){this.extractionBuffer=this.nativeSDK._malloc(4*this.spatialBufferSize),this.matchBuffer=this.nativeSDK._malloc(14e3),this.coarseLocationBuffer=this.nativeSDK._malloc(32768);}loadExtractionData(t,i=-1){return this.extractionBuffer&&this.coarseLocationBuffer?(this.nativeSDK.HEAPF32.set(t.extraction,this.extractionBuffer/4),this.nativeSDK.HEAPF32.set(t.descriptor,this.coarseLocationBuffer/4),this.nativeSDK._OX_LoadExtractionData(this.extractionBuffer,this.coarseLocationBuffer,i)):0}coarseLocationCheck(t){return this.coarseLocationBuffer?(this.nativeSDK.HEAPF32.set(t.descriptor,this.coarseLocationBuffer/4),this.nativeSDK._OX_CoarseLocationCheck(this.coarseLocationBuffer)):0}getCandidateData(t){let i=this.nativeSDK._OX_GetCandidateData(t);return new Float32Array(this.nativeSDK.HEAPF32.buffer,i,this.spatialBufferSize)}loadMatch(t){this.matchBuffer&&(this.nativeSDK.HEAPF32.set(t,this.matchBuffer/4),this.nativeSDK._OX_LoadMatch(this.matchBuffer));}spatialLocalize(t){return this.nativeSDK.HEAPF32.set(t.elements,this.lastPoseBuffer/4),this.nativeSDK._OX_SpatialLocalize(this.lastPoseBuffer)}setSpatialQualityLevel(t){return this.nativeSDK._OX_SetSpatialQualityLevel(t)}loadKeyframePose(t){this.nativeSDK._OX_LoadKfPose(t);}numSLAMKeyframes(){return this.nativeSDK._OX_GetSLAMNumKfs()}getSLAMKeyframe(t){let i=this.nativeSDK._OX_GetSLAMKf(t),e=[];for(let t=0;t<1228800;t++)e.push(this.nativeSDK.HEAPU8[i+t]);return new Uint8Array(e)}stopImageTracking(){this.nativeSDK._OX_StopImageDetection();}stopQRCodeTracking(){this.nativeSDK._OX_StopQRCodeDetection();}stopSLAM(){this.nativeSDK._OX_StopSLAM();}stopSpatialTracking(){this.nativeSDK._OX_StopSpatialTracking();}addImage(t,i){this.nativeSDK.HEAPU8.set(i,this.imageBuffer),this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+0]=640,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+1]=480,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+2]=2560,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+3]=!1,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+4]=5,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+5]=0,this.nativeSDK.HEAPU32[this.frameLayoutStruct/4+6]=0;const e=this.getStringBuffer(t);this.nativeSDK._OX_AddImage([e],this.imageBuffer,this.frameLayoutStruct),this.releaseStringBuffer(e);}destroy(){this.nativeSDK._OX_Destroy(),this.osfStrBuffer&&this.releaseStringBuffer(this.osfStrBuffer);}extractionType(){return this.nativeSDK._OX_ExtractionType()}getStringBuffer(t){const i=this.nativeSDK.lengthBytesUTF8(t)+1;let e=this.nativeSDK._malloc(i);return this.nativeSDK.stringToUTF8(t,e,i),e}releaseStringBuffer(t){this.nativeSDK._free(t);}parseNativeJSON(t){let i;try{i=JSON.parse(t);}catch(i){console.error(`Could not parse ${t}`);}return i}getSLAMMap(){return this.parseNativeJSON(this.nativeSDK.UTF8ToString(this.nativeSDK._OX_GetSLAMMap()))}getSLAMTrackingPoints(){return this.parseNativeJSON(this.nativeSDK.UTF8ToString(this.nativeSDK._OX_GetSLAMTrackingPoints()))}raycast(t,i,e,a,r,s){return this.parseNativeJSON(this.nativeSDK.UTF8ToString(this.nativeSDK._OX_Raycast(t,i,e,a,r,s)))}getSpatialMap(){return this.parseNativeJSON(this.nativeSDK.UTF8ToString(this.nativeSDK._OX_GetSpatialMap()))}setWebXRRelocationListener(t){this.webXRRelocationListener=t;}}
|
42
42
|
|
43
43
|
class UIManager{constructor(){this.onFocus=this.onFocus.bind(this);}createRenderCanvas(){this.renderCanvas=document.createElement("canvas"),this.renderCanvas.id="renderer",this.renderCanvas.style.position="absolute",document.body.prepend(this.renderCanvas),this.addTouchListeners();}setRenderCanvas(e){this.renderCanvas=e,this.addTouchListeners();}addTouchListeners(){this.renderCanvas.addEventListener("click",(e=>{this.onCanvasTouch(e);})),this.renderCanvas.addEventListener("touchstart",(e=>{this.onCanvasTouchStart(e);})),this.renderCanvas.addEventListener("touchmove",(e=>{this.onCanvasTouchMove(e);})),this.renderCanvas.addEventListener("touchend",(e=>{this.onCanvasTouchEnd(e);}));}removeRenderCanvas(){this.renderCanvas&&(this.renderCanvas.remove(),this.renderCanvas=null);}createVideoElement(e,t,i){let o=document.createElement("video");o.setAttribute("playsinline","true"),o.setAttribute("autoplay","true"),o.setAttribute("muted",""),this.videoCanvas=document.createElement("canvas"),this.videoCanvas.width=t,this.videoCanvas.height=i,this.videoContext=this.videoCanvas.getContext("2d"),o.srcObject=e,document.body.appendChild(o),this.videoElement=o;const s=this.videoElement.srcObject.getVideoTracks()[0].getSettings();this.videoSizeHorizontal=[Math.max(s.width,s.height),Math.min(s.width,s.height)],this.videoSizeVertical=[Math.min(s.width,s.height),Math.max(s.width,s.height)],window.addEventListener("focus",this.onFocus);}onFocus(){this.videoElement.play();}removeVideoElement(){this.videoElement&&(window.removeEventListener("focus",this.onFocus),this.videoElement.remove(),this.videoElement=null);}fitVideoToScreen(){if(!this.videoSizeHorizontal||!this.videoSizeVertical)return;this.videoSize=window.innerWidth>window.innerHeight?this.videoSizeHorizontal:this.videoSizeVertical;let e=[],t=[];this.videoSize[0]/this.videoSize[1]>window.innerWidth/window.innerHeight?(t=[Math.floor(this.videoSize[0]*(window.innerHeight/this.videoSize[1])),window.innerHeight],e=[-(t[0]-window.innerWidth)/2,0]):(t=[window.innerWidth,Math.floor(this.videoSize[1]*(window.innerWidth/this.videoSize[0]))],e=[0,-(t[1]-window.innerHeight)/2]),document.body.style.setProperty("overflow","hidden"),this.videoElement.width=t[0],this.videoElement.height=t[1],this.videoElement.style.setProperty("position","fixed"),this.videoElement.style.setProperty("z-index","-1"),this.videoElement.style.setProperty("width",`${t[0]}px`),this.videoElement.style.setProperty("height",`${t[1]}px`),this.videoElement.style.setProperty("left",`${e[0]}px`),this.videoElement.style.setProperty("top",`${e[1]}px`),this.videoElement.style.setProperty("touch-action","none"),this.renderCanvas.width=t[0],this.renderCanvas.height=t[1],this.renderCanvas.style.setProperty("position","fixed","important"),this.renderCanvas.style.setProperty("width",`${t[0]}px`,"important"),this.renderCanvas.style.setProperty("height",`${t[1]}px`,"important"),this.renderCanvas.style.setProperty("left",`${e[0]}px`,"important"),this.renderCanvas.style.setProperty("top",`${e[1]}px`,"important"),this.renderCanvas.style.setProperty("touch-action","none","important");}async displayPermissionsDialog(e){return new Promise(((t,i)=>{let o,s,n,r;o=document.createElement("div"),o.id="ox-permissions-dialog",o.style.setProperty("position","fixed"),o.style.setProperty("z-index","999999"),o.style.setProperty("max-width","360px"),o.style.setProperty("width","calc(100% - 140px"),o.style.setProperty("left","50vw"),o.style.setProperty("top","50vh"),o.style.setProperty("transform","translate(-50%, -50%)"),o.style.setProperty("background-color","#FFFFFF"),o.style.setProperty("border-radius","10px"),o.style.setProperty("font-family","'Open Sans', Arial, sans-serif"),o.style.setProperty("text-align","center"),o.style.setProperty("padding","30px"),document.body.appendChild(o),s=document.createElement("h1"),s.id="ox-permissions-dialog-title",s.innerText="Access to motion sensors required",s.style.setProperty("font-size","20px"),o.appendChild(s),n=document.createElement("span"),n.id="ox-permissions-dialog-message",n.innerText="This augmented reality experience requires access to your phone motion sensors. The browser may ask you for permissions.",n.style.setProperty("display","block"),n.style.setProperty("padding","10px 0"),o.appendChild(n),r=document.createElement("button"),r.id="ox-permissions-dialog-ok-button",r.innerText="Okay!",r.style.setProperty("display","block"),r.style.setProperty("margin","auto"),r.style.setProperty("background","#000000"),r.style.setProperty("color","#FFFFFF"),r.style.setProperty("border","none"),r.style.setProperty("border-radius","12px"),r.style.setProperty("padding","20px 0"),r.style.setProperty("width","100%"),r.style.setProperty("font-size","18px"),r.style.setProperty("font-weight","bold"),r.style.setProperty("margin-top","20px"),r.style.setProperty("background-image","linear-gradient(to left, #f6414b, #ee0979)"),o.appendChild(r),r.addEventListener("click",(async s=>{s.stopPropagation(),o.remove();try{await e(),t();}catch(e){i(e);}}));}))}getVideoData(){let e;if(this.videoElement){if(this.isPortrait()){let[e,i]=this.videoSizeVertical;var t=Math.PI/2;this.videoContext.translate(480,0),this.videoContext.rotate(t),this.videoContext.drawImage(this.videoElement,0,0,i,i,0,-160,640,640),this.videoContext.rotate(-t),this.videoContext.translate(-480,0);}else this.videoContext.drawImage(this.videoElement,0,0,640,480);e=this.videoContext.getImageData(0,0,640,480).data;}return e}getVideoElement(){return this.videoElement}getCameraParameters(){let e=640,t=480;return this.isPortrait()||([e,t]=[t,e]),{fov:radToDeg(2*Math.atan(e/936)),aspect:t/e}}isPortrait(){return window.innerWidth<window.innerHeight}setTouchListener(e){this.onTouch=e;}setTouchStartListener(e){this.onTouchStart=e;}setTouchMoveListener(e){this.onTouchMove=e;}setTouchEndListener(e){this.onTouchEnd=e;}getNormalizedTouchCoords(e){const t=new Vector2,i=this.renderCanvas.getBoundingClientRect();return null!=e.clientX?(t.x=(e.clientX-i.left)/i.width*2-1,t.y=-(e.clientY-i.top)/i.height*2+1):e.touches[0]?(t.x=e.touches[0].clientX/window.innerWidth*2-1,t.y=-e.touches[0].clientY/window.innerHeight*2+1):(t.x=e.changedTouches[0].clientX/window.innerWidth*2-1,t.y=-e.changedTouches[0].clientY/window.innerHeight*2+1),t}onCanvasTouch(e){const t=this.getNormalizedTouchCoords(e);this.onTouch&&this.onTouch(t);}onCanvasTouchStart(e){const t=this.getNormalizedTouchCoords(e);this.onTouchStart&&this.onTouchStart(t);}onCanvasTouchMove(e){const t=this.getNormalizedTouchCoords(e);this.onTouchMove&&this.onTouchMove(t);}onCanvasTouchEnd(e){const t=this.getNormalizedTouchCoords(e);this.onTouchEnd&&this.onTouchEnd(t);}}
|
44
44
|
|
@@ -48,9 +48,9 @@ class IMUManager{constructor(e,t){this.uiManager=e,this.deviceManager=t,this.sta
|
|
48
48
|
|
49
49
|
class IndexedDBManager{constructor(e,r){this.dbName=e,this.storeName=r;}async getFromCacheOrFetch(e,r){let t=null;try{t=await this.getFileFromIndexedDB(e);}catch(e){console.log("An error occurred while trying to get element from indexedDB.");}return t||(t=await this.fetchAndCacheFile(r,e)),new Uint8Array(t)}async getFileFromIndexedDB(e){return new Promise(((r,t)=>{const o=indexedDB.open(this.dbName);o.onerror=()=>t(o.error),o.onsuccess=()=>{const s=o.result.transaction(this.storeName,"readonly").objectStore(this.storeName).get(e);s.onsuccess=()=>r(s.result),s.onerror=()=>t(s.error);},o.onupgradeneeded=e=>{e.target.result.createObjectStore(this.storeName);};}))}async saveFileToIndexedDB(e,r){return new Promise(((t,o)=>{const s=indexedDB.open(this.dbName);s.onerror=()=>o(s.error),s.onupgradeneeded=e=>{e.target.result.createObjectStore(this.storeName);},s.onsuccess=()=>{try{const n=s.result.transaction(this.storeName,"readwrite"),a=n.objectStore(this.storeName).put(r,e);a.onsuccess=()=>t(a.result),a.onerror=()=>o(a.error);}catch(e){o(e);}};}))}async fetchAndCacheFile(e,r){const t=await fetch(e),o=await t.arrayBuffer();return await this.saveFileToIndexedDB(r,o),o}}
|
50
50
|
|
51
|
-
class WorkerExtractionData{constructor(Z,l,d,b,c,m,G=5,X=!1){this.data=Z,this.width=l,this.height=d,this.rotate=b,this.flip=c,this.colorSpace=G,this.onlyCoarse=X,this.dtype=m;}}class WorkerMatchingData{constructor(Z,l,d,b){this.idx=Z,this.from=l,this.to=d,this.dtype=b;}}class WorkerManager{constructor(){this.workers={},this.callbacks={};this.indexedDBManager=new IndexedDBManager("onirix-sdk","files");}workerExists(Z){return void 0!==this.workers[Z]&&void 0!==this.callbacks[Z]}createExtractionWorker(Z,l){if(!this.workerExists(Z)){let d=atob("Y2xhc3MgSW5kZXhlZERCTWFuYWdlcntjb25zdHJ1Y3RvcihlLHIpe3RoaXMuZGJOYW1lPWUsdGhpcy5zdG9yZU5hbWU9cjt9YXN5bmMgZ2V0RnJvbUNhY2hlT3JGZXRjaChlLHIpe2xldCB0PW51bGw7dHJ5e3Q9YXdhaXQgdGhpcy5nZXRGaWxlRnJvbUluZGV4ZWREQihlKTt9Y2F0Y2goZSl7Y29uc29sZS5sb2coIkFuIGVycm9yIG9jY3VycmVkIHdoaWxlIHRyeWluZyB0byBnZXQgZWxlbWVudCBmcm9tIGluZGV4ZWREQi4iKTt9cmV0dXJuIHR8fCh0PWF3YWl0IHRoaXMuZmV0Y2hBbmRDYWNoZUZpbGUocixlKSksbmV3IFVpbnQ4QXJyYXkodCl9YXN5bmMgZ2V0RmlsZUZyb21JbmRleGVkREIoZSl7cmV0dXJuIG5ldyBQcm9taXNlKCgocix0KT0+e2NvbnN0IG89aW5kZXhlZERCLm9wZW4odGhpcy5kYk5hbWUpO28ub25lcnJvcj0oKT0+dChvLmVycm9yKSxvLm9uc3VjY2Vzcz0oKT0+e2NvbnN0IHM9by5yZXN1bHQudHJhbnNhY3Rpb24odGhpcy5zdG9yZU5hbWUsInJlYWRvbmx5Iikub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpLmdldChlKTtzLm9uc3VjY2Vzcz0oKT0+cihzLnJlc3VsdCkscy5vbmVycm9yPSgpPT50KHMuZXJyb3IpO30sby5vbnVwZ3JhZGVuZWVkZWQ9ZT0+e2UudGFyZ2V0LnJlc3VsdC5jcmVhdGVPYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7fTt9KSl9YXN5bmMgc2F2ZUZpbGVUb0luZGV4ZWREQihlLHIpe3JldHVybiBuZXcgUHJvbWlzZSgoKHQsbyk9Pntjb25zdCBzPWluZGV4ZWREQi5vcGVuKHRoaXMuZGJOYW1lKTtzLm9uZXJyb3I9KCk9Pm8ocy5lcnJvcikscy5vbnVwZ3JhZGVuZWVkZWQ9ZT0+e2UudGFyZ2V0LnJlc3VsdC5jcmVhdGVPYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7fSxzLm9uc3VjY2Vzcz0oKT0+e3RyeXtjb25zdCBuPXMucmVzdWx0LnRyYW5zYWN0aW9uKHRoaXMuc3RvcmVOYW1lLCJyZWFkd3JpdGUiKSxhPW4ub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpLnB1dChyLGUpO2Eub25zdWNjZXNzPSgpPT50KGEucmVzdWx0KSxhLm9uZXJyb3I9KCk9Pm8oYS5lcnJvcik7fWNhdGNoKGUpe28oZSk7fX07fSkpfWFzeW5jIGZldGNoQW5kQ2FjaGVGaWxlKGUscil7Y29uc3QgdD1hd2FpdCBmZXRjaChlKSxvPWF3YWl0IHQuYXJyYXlCdWZmZXIoKTtyZXR1cm4gYXdhaXQgdGhpcy5zYXZlRmlsZVRvSW5kZXhlZERCKHIsbyksb319Cgp2YXIgaGUsaixpZSxBcix1dCxjdCxkdCxfLEEsbXQsaHQsSGUseXQsYnQsZ3QsRXQsVHQsSCxhZSxBdCxPdCxMdCxJdCx2LFIsdnQsQnQsVixZLHllLE9yLFdlPU9iamVjdC5kZWZpbmVQcm9wZXJ0eSxncj1PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLEVyPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzLFRyPU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHksJGU9KGU9PnR5cGVvZiByZXF1aXJlPCJ1Ij9yZXF1aXJlOnR5cGVvZiBQcm94eTwidSI/bmV3IFByb3h5KGUse2dldDooZSx0KT0+KHR5cGVvZiByZXF1aXJlPCJ1Ij9yZXF1aXJlOmUpW3RdfSk6ZSkoKGZ1bmN0aW9uKGUpe2lmKHR5cGVvZiByZXF1aXJlPCJ1IilyZXR1cm4gcmVxdWlyZS5hcHBseSh0aGlzLGFyZ3VtZW50cyk7dGhyb3cgRXJyb3IoJ0R5bmFtaWMgcmVxdWlyZSBvZiAiJytlKyciIGlzIG5vdCBzdXBwb3J0ZWQnKX0pKSxUPShlLHQpPT4oKT0+KGUmJih0PWUoZT0wKSksdCksR2U9KGUsdCk9Pntmb3IodmFyIHIgaW4gdClXZShlLHIse2dldDp0W3JdLGVudW1lcmFibGU6ITB9KTt9LFNyPShlLHQscixuKT0+e2lmKHQmJiJvYmplY3QiPT10eXBlb2YgdHx8ImZ1bmN0aW9uIj09dHlwZW9mIHQpZm9yKGxldCBvIG9mIEVyKHQpKSFUci5jYWxsKGUsbykmJm8hPT1yJiZXZShlLG8se2dldDooKT0+dFtvXSxlbnVtZXJhYmxlOiEobj1ncih0LG8pKXx8bi5lbnVtZXJhYmxlfSk7cmV0dXJuIGV9LGF0PWU9PlNyKFdlKHt9LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KSxlKSx6ZT1UKCgoKT0+e2hlPW5ldyBNYXAsaj1bXSxpZT0oZSx0LHIpPT57aWYoIXR8fCJmdW5jdGlvbiIhPXR5cGVvZiB0LmluaXR8fCJmdW5jdGlvbiIhPXR5cGVvZiB0LmNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKXRocm93IG5ldyBUeXBlRXJyb3IoIm5vdCBhIHZhbGlkIGJhY2tlbmQiKTt7bGV0IG49aGUuZ2V0KGUpO2lmKHZvaWQgMD09PW4paGUuc2V0KGUse2JhY2tlbmQ6dCxwcmlvcml0eTpyfSk7ZWxzZSB7aWYobi5wcmlvcml0eT5yKXJldHVybjtpZihuLnByaW9yaXR5PT09ciYmbi5iYWNrZW5kIT09dCl0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCByZWdpc3RlciBiYWNrZW5kICIke2V9IiB1c2luZyBwcmlvcml0eSAke3J9YCl9aWYocj49MCl7bGV0IHQ9ai5pbmRleE9mKGUpOy0xIT09dCYmai5zcGxpY2UodCwxKTtmb3IobGV0IHQ9MDt0PGoubGVuZ3RoO3QrKylpZihoZS5nZXQoalt0XSkucHJpb3JpdHk8PXIpcmV0dXJuIHZvaWQgai5zcGxpY2UodCwwLGUpO2oucHVzaChlKTt9fX0sQXI9YXN5bmMgZT0+e2xldCB0PWhlLmdldChlKTtpZighdClyZXR1cm4gImJhY2tlbmQgbm90IGZvdW5kLiI7aWYodC5pbml0aWFsaXplZClyZXR1cm4gdC5iYWNrZW5kO2lmKHQuYWJvcnRlZClyZXR1cm4gdC5lcnJvcjt7bGV0IHI9ISF0LmluaXRQcm9taXNlO3RyeXtyZXR1cm4gcnx8KHQuaW5pdFByb21pc2U9dC5iYWNrZW5kLmluaXQoZSkpLGF3YWl0IHQuaW5pdFByb21pc2UsdC5pbml0aWFsaXplZD0hMCx0LmJhY2tlbmR9Y2F0Y2goZSl7cmV0dXJuIHJ8fCh0LmVycm9yPWAke2V9YCx0LmFib3J0ZWQ9ITApLHQuZXJyb3J9ZmluYWxseXtkZWxldGUgdC5pbml0UHJvbWlzZTt9fX0sdXQ9YXN5bmMgZT0+e2xldCB0LHI9ZS5leGVjdXRpb25Qcm92aWRlcnN8fFtdLG49ci5tYXAoKGU9PiJzdHJpbmciPT10eXBlb2YgZT9lOmUubmFtZSkpLG89MD09PW4ubGVuZ3RoP2o6bixhPVtdLGk9bmV3IFNldDtmb3IobGV0IGUgb2Ygbyl7bGV0IHI9YXdhaXQgQXIoZSk7InN0cmluZyI9PXR5cGVvZiByP2EucHVzaCh7bmFtZTplLGVycjpyfSk6KHR8fCh0PXIpLHQ9PT1yJiZpLmFkZChlKSk7fWlmKCF0KXRocm93IG5ldyBFcnJvcihgbm8gYXZhaWxhYmxlIGJhY2tlbmQgZm91bmQuIEVSUjogJHthLm1hcCgoZT0+YFske2UubmFtZX1dICR7ZS5lcnJ9YCkpLmpvaW4oIiwgIil9YCk7Zm9yKGxldHtuYW1lOmUsZXJyOnR9b2YgYSluLmluY2x1ZGVzKGUpJiZjb25zb2xlLndhcm4oYHJlbW92aW5nIHJlcXVlc3RlZCBleGVjdXRpb24gcHJvdmlkZXIgIiR7ZX0iIGZyb20gc2Vzc2lvbiBvcHRpb25zIGJlY2F1c2UgaXQgaXMgbm90IGF2YWlsYWJsZTogJHt0fWApO2xldCBzPXIuZmlsdGVyKChlPT5pLmhhcygic3RyaW5nIj09dHlwZW9mIGU/ZTplLm5hbWUpKSk7cmV0dXJuIFt0LG5ldyBQcm94eShlLHtnZXQ6KGUsdCk9PiJleGVjdXRpb25Qcm92aWRlcnMiPT09dD9zOlJlZmxlY3QuZ2V0KGUsdCl9KV19O30pKSxmdD1UKCgoKT0+e3plKCk7fSkpLGx0PVQoKCgpPT57Y3Q9IjEuMjEuMCI7fSkpLGplPVQoKCgpPT57bHQoKSxkdD0id2FybmluZyIsXz17d2FzbTp7fSx3ZWJnbDp7fSx3ZWJncHU6e30sdmVyc2lvbnM6e2NvbW1vbjpjdH0sc2V0IGxvZ0xldmVsKGUpe2lmKHZvaWQgMCE9PWUpe2lmKCJzdHJpbmciIT10eXBlb2YgZXx8LTE9PT1bInZlcmJvc2UiLCJpbmZvIiwid2FybmluZyIsImVycm9yIiwiZmF0YWwiXS5pbmRleE9mKGUpKXRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgbG9nZ2luZyBsZXZlbDogJHtlfWApO2R0PWU7fX0sZ2V0IGxvZ0xldmVsKCl7cmV0dXJuIGR0fX0sT2JqZWN0LmRlZmluZVByb3BlcnR5KF8sImxvZ0xldmVsIix7ZW51bWVyYWJsZTohMH0pO30pKSxwdD1UKCgoKT0+e2plKCksQT1fO30pKSx3dD1UKCgoKT0+e210PShlLHQpPT57bGV0IHI9dHlwZW9mIGRvY3VtZW50PCJ1Ij9kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJjYW52YXMiKTpuZXcgT2Zmc2NyZWVuQ2FudmFzKDEsMSk7ci53aWR0aD1lLmRpbXNbM10sci5oZWlnaHQ9ZS5kaW1zWzJdO2xldCBuPXIuZ2V0Q29udGV4dCgiMmQiKTtpZihudWxsIT1uKXtsZXQgbyxhO3ZvaWQgMCE9PXQ/LnRlbnNvckxheW91dCYmIk5IV0MiPT09dC50ZW5zb3JMYXlvdXQ/KG89ZS5kaW1zWzJdLGE9ZS5kaW1zWzNdKToobz1lLmRpbXNbM10sYT1lLmRpbXNbMl0pO2xldCBpLHMsbD12b2lkIDAhPT10Py5mb3JtYXQ/dC5mb3JtYXQ6IlJHQiIsdT10Py5ub3JtO3ZvaWQgMD09PXV8fHZvaWQgMD09PXUubWVhbj9pPVsyNTUsMjU1LDI1NSwyNTVdOiJudW1iZXIiPT10eXBlb2YgdS5tZWFuP2k9W3UubWVhbix1Lm1lYW4sdS5tZWFuLHUubWVhbl06KGk9W3UubWVhblswXSx1Lm1lYW5bMV0sdS5tZWFuWzJdLDBdLHZvaWQgMCE9PXUubWVhblszXSYmKGlbM109dS5tZWFuWzNdKSksdm9pZCAwPT09dXx8dm9pZCAwPT09dS5iaWFzP3M9WzAsMCwwLDBdOiJudW1iZXIiPT10eXBlb2YgdS5iaWFzP3M9W3UuYmlhcyx1LmJpYXMsdS5iaWFzLHUuYmlhc106KHM9W3UuYmlhc1swXSx1LmJpYXNbMV0sdS5iaWFzWzJdLDBdLHZvaWQgMCE9PXUuYmlhc1szXSYmKHNbM109dS5iaWFzWzNdKSk7bGV0IGY9YSpvLGQ9MCxwPWYsYz0yKmYsaD0tMTsiUkdCQSI9PT1sPyhkPTAscD1mLGM9MipmLGg9MypmKToiUkdCIj09PWw/KGQ9MCxwPWYsYz0yKmYpOiJSQkciPT09bCYmKGQ9MCxjPWYscD0yKmYpO2ZvcihsZXQgdD0wO3Q8YTt0KyspZm9yKGxldCByPTA7cjxvO3IrKyl7bGV0IG89KGUuZGF0YVtkKytdLXNbMF0pKmlbMF0sYT0oZS5kYXRhW3ArK10tc1sxXSkqaVsxXSxsPShlLmRhdGFbYysrXS1zWzJdKSppWzJdLHU9LTE9PT1oPzI1NTooZS5kYXRhW2grK10tc1szXSkqaVszXTtuLmZpbGxTdHlsZT0icmdiYSgiK28rIiwiK2ErIiwiK2wrIiwiK3UrIikiLG4uZmlsbFJlY3Qocix0LDEsMSk7fWlmKCJ0b0RhdGFVUkwiaW4gcilyZXR1cm4gci50b0RhdGFVUkwoKTt0aHJvdyBuZXcgRXJyb3IoInRvRGF0YVVSTCBpcyBub3Qgc3VwcG9ydGVkIil9dGhyb3cgbmV3IEVycm9yKCJDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhIil9LGh0PShlLHQpPT57bGV0IHIsbj10eXBlb2YgZG9jdW1lbnQ8InUiP2RvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImNhbnZhcyIpLmdldENvbnRleHQoIjJkIik6bmV3IE9mZnNjcmVlbkNhbnZhcygxLDEpLmdldENvbnRleHQoIjJkIik7aWYobnVsbD09bil0aHJvdyBuZXcgRXJyb3IoIkNhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEiKTt7bGV0IG8sYSxpO3ZvaWQgMCE9PXQ/LnRlbnNvckxheW91dCYmIk5IV0MiPT09dC50ZW5zb3JMYXlvdXQ/KG89ZS5kaW1zWzJdLGE9ZS5kaW1zWzFdLGk9ZS5kaW1zWzNdKToobz1lLmRpbXNbM10sYT1lLmRpbXNbMl0saT1lLmRpbXNbMV0pO2xldCBzLGwsdT12b2lkIDAhPT10JiZ2b2lkIDAhPT10LmZvcm1hdD90LmZvcm1hdDoiUkdCIixmPXQ/Lm5vcm07dm9pZCAwPT09Znx8dm9pZCAwPT09Zi5tZWFuP3M9WzI1NSwyNTUsMjU1LDI1NV06Im51bWJlciI9PXR5cGVvZiBmLm1lYW4/cz1bZi5tZWFuLGYubWVhbixmLm1lYW4sZi5tZWFuXToocz1bZi5tZWFuWzBdLGYubWVhblsxXSxmLm1lYW5bMl0sMjU1XSx2b2lkIDAhPT1mLm1lYW5bM10mJihzWzNdPWYubWVhblszXSkpLHZvaWQgMD09PWZ8fHZvaWQgMD09PWYuYmlhcz9sPVswLDAsMCwwXToibnVtYmVyIj09dHlwZW9mIGYuYmlhcz9sPVtmLmJpYXMsZi5iaWFzLGYuYmlhcyxmLmJpYXNdOihsPVtmLmJpYXNbMF0sZi5iaWFzWzFdLGYuYmlhc1syXSwwXSx2b2lkIDAhPT1mLmJpYXNbM10mJihsWzNdPWYuYmlhc1szXSkpO2xldCBkPWEqbztpZih2b2lkIDAhPT10JiYodm9pZCAwIT09dC5mb3JtYXQmJjQ9PT1pJiYiUkdCQSIhPT10LmZvcm1hdHx8Mz09PWkmJiJSR0IiIT09dC5mb3JtYXQmJiJCR1IiIT09dC5mb3JtYXQpKXRocm93IG5ldyBFcnJvcigiVGVuc29yIGZvcm1hdCBkb2Vzbid0IG1hdGNoIGlucHV0IHRlbnNvciBkaW1zIik7bGV0IHA9NCxjPTAsaD0xLHc9Mix5PTMsbT0wLGc9ZCxiPTIqZCx2PS0xOyJSR0JBIj09PXU/KG09MCxnPWQsYj0yKmQsdj0zKmQpOiJSR0IiPT09dT8obT0wLGc9ZCxiPTIqZCk6IlJCRyI9PT11JiYobT0wLGI9ZCxnPTIqZCkscj1uLmNyZWF0ZUltYWdlRGF0YShvLGEpO2ZvcihsZXQgdD0wO3Q8YSpvO2MrPXAsaCs9cCx3Kz1wLHkrPXAsdCsrKXIuZGF0YVtjXT0oZS5kYXRhW20rK10tbFswXSkqc1swXSxyLmRhdGFbaF09KGUuZGF0YVtnKytdLWxbMV0pKnNbMV0sci5kYXRhW3ddPShlLmRhdGFbYisrXS1sWzJdKSpzWzJdLHIuZGF0YVt5XT0tMT09PXY/MjU1OihlLmRhdGFbdisrXS1sWzNdKSpzWzNdO31yZXR1cm4gcn07fSkpLFN0PVQoKCgpPT57d2UoKSxIZT0oZSx0KT0+e2lmKHZvaWQgMD09PWUpdGhyb3cgbmV3IEVycm9yKCJJbWFnZSBidWZmZXIgbXVzdCBiZSBkZWZpbmVkIik7aWYodm9pZCAwPT09dC5oZWlnaHR8fHZvaWQgMD09PXQud2lkdGgpdGhyb3cgbmV3IEVycm9yKCJJbWFnZSBoZWlnaHQgYW5kIHdpZHRoIG11c3QgYmUgZGVmaW5lZCIpO2lmKCJOSFdDIj09PXQudGVuc29yTGF5b3V0KXRocm93IG5ldyBFcnJvcigiTkhXQyBUZW5zb3IgbGF5b3V0IGlzIG5vdCBzdXBwb3J0ZWQgeWV0Iik7bGV0IHIsbix7aGVpZ2h0Om8sd2lkdGg6YX09dCxpPXQubm9ybT8/e21lYW46MjU1LGJpYXM6MH07cj0ibnVtYmVyIj09dHlwZW9mIGkubWVhbj9baS5tZWFuLGkubWVhbixpLm1lYW4saS5tZWFuXTpbaS5tZWFuWzBdLGkubWVhblsxXSxpLm1lYW5bMl0saS5tZWFuWzNdPz8yNTVdLG49Im51bWJlciI9PXR5cGVvZiBpLmJpYXM/W2kuYmlhcyxpLmJpYXMsaS5iaWFzLGkuYmlhc106W2kuYmlhc1swXSxpLmJpYXNbMV0saS5iaWFzWzJdLGkuYmlhc1szXT8/MF07bGV0IHM9dm9pZCAwIT09dC5mb3JtYXQ/dC5mb3JtYXQ6IlJHQkEiLGw9dm9pZCAwIT09dC50ZW5zb3JGb3JtYXQmJnZvaWQgMCE9PXQudGVuc29yRm9ybWF0P3QudGVuc29yRm9ybWF0OiJSR0IiLHU9byphLGY9IlJHQkEiPT09bD9uZXcgRmxvYXQzMkFycmF5KDQqdSk6bmV3IEZsb2F0MzJBcnJheSgzKnUpLGQ9NCxwPTAsYz0xLGg9Mix3PTMseT0wLG09dSxnPTIqdSxiPS0xOyJSR0IiPT09cyYmKGQ9MyxwPTAsYz0xLGg9Mix3PS0xKSwiUkdCQSI9PT1sP2I9Myp1OiJSQkciPT09bD8oeT0wLGc9dSxtPTIqdSk6IkJHUiI9PT1sJiYoZz0wLG09dSx5PTIqdSk7Zm9yKGxldCB0PTA7dDx1O3QrKyxwKz1kLGgrPWQsYys9ZCx3Kz1kKWZbeSsrXT0oZVtwXStuWzBdKS9yWzBdLGZbbSsrXT0oZVtjXStuWzFdKS9yWzFdLGZbZysrXT0oZVtoXStuWzJdKS9yWzJdLC0xIT09YiYmLTEhPT13JiYoZltiKytdPShlW3ddK25bM10pL3JbM10pO3JldHVybiBuZXcgdigiZmxvYXQzMiIsZiwiUkdCQSI9PT1sP1sxLDQsbyxhXTpbMSwzLG8sYV0pfSx5dD1hc3luYyhlLHQpPT57bGV0IHIsbj10eXBlb2YgSFRNTEltYWdlRWxlbWVudDwidSImJmUgaW5zdGFuY2VvZiBIVE1MSW1hZ2VFbGVtZW50LG89dHlwZW9mIEltYWdlRGF0YTwidSImJmUgaW5zdGFuY2VvZiBJbWFnZURhdGEsYT10eXBlb2YgSW1hZ2VCaXRtYXA8InUiJiZlIGluc3RhbmNlb2YgSW1hZ2VCaXRtYXAsaT0ic3RyaW5nIj09dHlwZW9mIGUscz10Pz97fSxsPSgpPT57aWYodHlwZW9mIGRvY3VtZW50PCJ1IilyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiY2FudmFzIik7aWYodHlwZW9mIE9mZnNjcmVlbkNhbnZhczwidSIpcmV0dXJuIG5ldyBPZmZzY3JlZW5DYW52YXMoMSwxKTt0aHJvdyBuZXcgRXJyb3IoIkNhbnZhcyBpcyBub3Qgc3VwcG9ydGVkIil9LHU9ZT0+dHlwZW9mIEhUTUxDYW52YXNFbGVtZW50PCJ1IiYmZSBpbnN0YW5jZW9mIEhUTUxDYW52YXNFbGVtZW50fHxlIGluc3RhbmNlb2YgT2Zmc2NyZWVuQ2FudmFzP2UuZ2V0Q29udGV4dCgiMmQiKTpudWxsO2lmKG4pe2xldCBuPWwoKTtuLndpZHRoPWUud2lkdGgsbi5oZWlnaHQ9ZS5oZWlnaHQ7bGV0IG89dShuKTtpZihudWxsPT1vKXRocm93IG5ldyBFcnJvcigiQ2FuIG5vdCBhY2Nlc3MgaW1hZ2UgZGF0YSIpO3tsZXQgbj1lLmhlaWdodCxhPWUud2lkdGg7aWYodm9pZCAwIT09dCYmdm9pZCAwIT09dC5yZXNpemVkSGVpZ2h0JiZ2b2lkIDAhPT10LnJlc2l6ZWRXaWR0aCYmKG49dC5yZXNpemVkSGVpZ2h0LGE9dC5yZXNpemVkV2lkdGgpLHZvaWQgMCE9PXQpe2lmKHM9dCx2b2lkIDAhPT10LnRlbnNvckZvcm1hdCl0aHJvdyBuZXcgRXJyb3IoIkltYWdlIGlucHV0IGNvbmZpZyBmb3JtYXQgbXVzdCBiZSBSR0JBIGZvciBIVE1MSW1hZ2VFbGVtZW50Iik7cy50ZW5zb3JGb3JtYXQ9IlJHQkEiLHMuaGVpZ2h0PW4scy53aWR0aD1hO31lbHNlIHMudGVuc29yRm9ybWF0PSJSR0JBIixzLmhlaWdodD1uLHMud2lkdGg9YTtvLmRyYXdJbWFnZShlLDAsMCkscj1vLmdldEltYWdlRGF0YSgwLDAsYSxuKS5kYXRhO319ZWxzZSB7aWYoIW8pe2lmKGEpe2lmKHZvaWQgMD09PXQpdGhyb3cgbmV3IEVycm9yKCJQbGVhc2UgcHJvdmlkZSBpbWFnZSBjb25maWcgd2l0aCBmb3JtYXQgZm9yIEltYWdlYml0bWFwIik7bGV0IG49bCgpO24ud2lkdGg9ZS53aWR0aCxuLmhlaWdodD1lLmhlaWdodDtsZXQgbz11KG4pO2lmKG51bGwhPW8pe2xldCB0PWUuaGVpZ2h0LG49ZS53aWR0aDtyZXR1cm4gby5kcmF3SW1hZ2UoZSwwLDAsbix0KSxyPW8uZ2V0SW1hZ2VEYXRhKDAsMCxuLHQpLmRhdGEscy5oZWlnaHQ9dCxzLndpZHRoPW4sSGUocixzKX10aHJvdyBuZXcgRXJyb3IoIkNhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEiKX1pZihpKXJldHVybiBuZXcgUHJvbWlzZSgoKHQscik9PntsZXQgbj1sKCksbz11KG4pO2lmKCFlfHwhbylyZXR1cm4gcigpO2xldCBhPW5ldyBJbWFnZTthLmNyb3NzT3JpZ2luPSJBbm9ueW1vdXMiLGEuc3JjPWUsYS5vbmxvYWQ9KCk9PntuLndpZHRoPWEud2lkdGgsbi5oZWlnaHQ9YS5oZWlnaHQsby5kcmF3SW1hZ2UoYSwwLDAsbi53aWR0aCxuLmhlaWdodCk7bGV0IGU9by5nZXRJbWFnZURhdGEoMCwwLG4ud2lkdGgsbi5oZWlnaHQpO3MuaGVpZ2h0PW4uaGVpZ2h0LHMud2lkdGg9bi53aWR0aCx0KEhlKGUuZGF0YSxzKSk7fTt9KSk7dGhyb3cgbmV3IEVycm9yKCJJbnB1dCBkYXRhIHByb3ZpZGVkIGlzIG5vdCBzdXBwb3J0ZWQgLSBhYm9ydGVkIHRlbnNvciBjcmVhdGlvbiIpfXtsZXQgbixvO2lmKHZvaWQgMCE9PXQmJnZvaWQgMCE9PXQucmVzaXplZFdpZHRoJiZ2b2lkIDAhPT10LnJlc2l6ZWRIZWlnaHQ/KG49dC5yZXNpemVkSGVpZ2h0LG89dC5yZXNpemVkV2lkdGgpOihuPWUuaGVpZ2h0LG89ZS53aWR0aCksdm9pZCAwIT09dCYmKHM9dCkscy5mb3JtYXQ9IlJHQkEiLHMuaGVpZ2h0PW4scy53aWR0aD1vLHZvaWQgMCE9PXQpe2xldCB0PWwoKTt0LndpZHRoPW8sdC5oZWlnaHQ9bjtsZXQgYT11KHQpO2lmKG51bGw9PWEpdGhyb3cgbmV3IEVycm9yKCJDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhIik7YS5wdXRJbWFnZURhdGEoZSwwLDApLHI9YS5nZXRJbWFnZURhdGEoMCwwLG8sbikuZGF0YTt9ZWxzZSByPWUuZGF0YTt9fWlmKHZvaWQgMCE9PXIpcmV0dXJuIEhlKHIscyk7dGhyb3cgbmV3IEVycm9yKCJJbnB1dCBkYXRhIHByb3ZpZGVkIGlzIG5vdCBzdXBwb3J0ZWQgLSBhYm9ydGVkIHRlbnNvciBjcmVhdGlvbiIpfSxidD0oZSx0KT0+e2xldHt3aWR0aDpyLGhlaWdodDpuLGRvd25sb2FkOm8sZGlzcG9zZTphfT10O3JldHVybiBuZXcgdih7bG9jYXRpb246InRleHR1cmUiLHR5cGU6ImZsb2F0MzIiLHRleHR1cmU6ZSxkaW1zOlsxLG4sciw0XSxkb3dubG9hZDpvLGRpc3Bvc2U6YX0pfSxndD0oZSx0KT0+e2xldHtkYXRhVHlwZTpyLGRpbXM6bixkb3dubG9hZDpvLGRpc3Bvc2U6YX09dDtyZXR1cm4gbmV3IHYoe2xvY2F0aW9uOiJncHUtYnVmZmVyIix0eXBlOnI/PyJmbG9hdDMyIixncHVCdWZmZXI6ZSxkaW1zOm4sZG93bmxvYWQ6byxkaXNwb3NlOmF9KX0sRXQ9KGUsdCk9PntsZXR7ZGF0YVR5cGU6cixkaW1zOm4sZG93bmxvYWQ6byxkaXNwb3NlOmF9PXQ7cmV0dXJuIG5ldyB2KHtsb2NhdGlvbjoibWwtdGVuc29yIix0eXBlOnI/PyJmbG9hdDMyIixtbFRlbnNvcjplLGRpbXM6bixkb3dubG9hZDpvLGRpc3Bvc2U6YX0pfSxUdD0oZSx0LHIpPT5uZXcgdih7bG9jYXRpb246ImNwdS1waW5uZWQiLHR5cGU6ZSxkYXRhOnQsZGltczpyPz9bdC5sZW5ndGhdfSk7fSkpLHh0PVQoKCgpPT57SD1uZXcgTWFwKFtbImZsb2F0MzIiLEZsb2F0MzJBcnJheV0sWyJ1aW50OCIsVWludDhBcnJheV0sWyJpbnQ4IixJbnQ4QXJyYXldLFsidWludDE2IixVaW50MTZBcnJheV0sWyJpbnQxNiIsSW50MTZBcnJheV0sWyJpbnQzMiIsSW50MzJBcnJheV0sWyJib29sIixVaW50OEFycmF5XSxbImZsb2F0NjQiLEZsb2F0NjRBcnJheV0sWyJ1aW50MzIiLFVpbnQzMkFycmF5XSxbImludDQiLFVpbnQ4QXJyYXldLFsidWludDQiLFVpbnQ4QXJyYXldXSksYWU9bmV3IE1hcChbW0Zsb2F0MzJBcnJheSwiZmxvYXQzMiJdLFtVaW50OEFycmF5LCJ1aW50OCJdLFtJbnQ4QXJyYXksImludDgiXSxbVWludDE2QXJyYXksInVpbnQxNiJdLFtJbnQxNkFycmF5LCJpbnQxNiJdLFtJbnQzMkFycmF5LCJpbnQzMiJdLFtGbG9hdDY0QXJyYXksImZsb2F0NjQiXSxbVWludDMyQXJyYXksInVpbnQzMiJdXSksQXQ9ITEsT3Q9KCk9PntpZighQXQpe0F0PSEwO2xldCBlPXR5cGVvZiBCaWdJbnQ2NEFycmF5PCJ1IiYmQmlnSW50NjRBcnJheS5mcm9tLHQ9dHlwZW9mIEJpZ1VpbnQ2NEFycmF5PCJ1IiYmQmlnVWludDY0QXJyYXkuZnJvbSxyPWdsb2JhbFRoaXMuRmxvYXQxNkFycmF5LG49dHlwZW9mIHI8InUiJiZyLmZyb207ZSYmKEguc2V0KCJpbnQ2NCIsQmlnSW50NjRBcnJheSksYWUuc2V0KEJpZ0ludDY0QXJyYXksImludDY0IikpLHQmJihILnNldCgidWludDY0IixCaWdVaW50NjRBcnJheSksYWUuc2V0KEJpZ1VpbnQ2NEFycmF5LCJ1aW50NjQiKSksbj8oSC5zZXQoImZsb2F0MTYiLHIpLGFlLnNldChyLCJmbG9hdDE2IikpOkguc2V0KCJmbG9hdDE2IixVaW50MTZBcnJheSk7fX07fSkpLFB0PVQoKCgpPT57d2UoKSxMdD1lPT57bGV0IHQ9MTtmb3IobGV0IHI9MDtyPGUubGVuZ3RoO3IrKyl7bGV0IG49ZVtyXTtpZigibnVtYmVyIiE9dHlwZW9mIG58fCFOdW1iZXIuaXNTYWZlSW50ZWdlcihuKSl0aHJvdyBuZXcgVHlwZUVycm9yKGBkaW1zWyR7cn1dIG11c3QgYmUgYW4gaW50ZWdlciwgZ290OiAke259YCk7aWYobjwwKXRocm93IG5ldyBSYW5nZUVycm9yKGBkaW1zWyR7cn1dIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlciwgZ290OiAke259YCk7dCo9bjt9cmV0dXJuIHR9LEl0PShlLHQpPT57c3dpdGNoKGUubG9jYXRpb24pe2Nhc2UiY3B1IjpyZXR1cm4gbmV3IHYoZS50eXBlLGUuZGF0YSx0KTtjYXNlImNwdS1waW5uZWQiOnJldHVybiBuZXcgdih7bG9jYXRpb246ImNwdS1waW5uZWQiLGRhdGE6ZS5kYXRhLHR5cGU6ZS50eXBlLGRpbXM6dH0pO2Nhc2UidGV4dHVyZSI6cmV0dXJuIG5ldyB2KHtsb2NhdGlvbjoidGV4dHVyZSIsdGV4dHVyZTplLnRleHR1cmUsdHlwZTplLnR5cGUsZGltczp0fSk7Y2FzZSJncHUtYnVmZmVyIjpyZXR1cm4gbmV3IHYoe2xvY2F0aW9uOiJncHUtYnVmZmVyIixncHVCdWZmZXI6ZS5ncHVCdWZmZXIsdHlwZTplLnR5cGUsZGltczp0fSk7Y2FzZSJtbC10ZW5zb3IiOnJldHVybiBuZXcgdih7bG9jYXRpb246Im1sLXRlbnNvciIsbWxUZW5zb3I6ZS5tbFRlbnNvcix0eXBlOmUudHlwZSxkaW1zOnR9KTtkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgdGVuc29yUmVzaGFwZTogdGVuc29yIGxvY2F0aW9uICR7ZS5sb2NhdGlvbn0gaXMgbm90IHN1cHBvcnRlZGApfX07fSkpLHdlPVQoKCgpPT57d3QoKSxTdCgpLHh0KCksUHQoKSx2PWNsYXNze2NvbnN0cnVjdG9yKGUsdCxyKXtsZXQgbixvO2lmKE90KCksIm9iamVjdCI9PXR5cGVvZiBlJiYibG9jYXRpb24iaW4gZSlzd2l0Y2godGhpcy5kYXRhTG9jYXRpb249ZS5sb2NhdGlvbixuPWUudHlwZSxvPWUuZGltcyxlLmxvY2F0aW9uKXtjYXNlImNwdS1waW5uZWQiOntsZXQgdD1ILmdldChuKTtpZighdCl0aHJvdyBuZXcgVHlwZUVycm9yKGB1bnN1cHBvcnRlZCB0eXBlICIke259IiB0byBjcmVhdGUgdGVuc29yIGZyb20gcGlubmVkIGJ1ZmZlcmApO2lmKCEoZS5kYXRhIGluc3RhbmNlb2YgdCkpdGhyb3cgbmV3IFR5cGVFcnJvcihgYnVmZmVyIHNob3VsZCBiZSBvZiB0eXBlICR7dC5uYW1lfWApO3RoaXMuY3B1RGF0YT1lLmRhdGE7YnJlYWt9Y2FzZSJ0ZXh0dXJlIjppZigiZmxvYXQzMiIhPT1uKXRocm93IG5ldyBUeXBlRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGUgIiR7bn0iIHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbSB0ZXh0dXJlYCk7dGhpcy5ncHVUZXh0dXJlRGF0YT1lLnRleHR1cmUsdGhpcy5kb3dubG9hZGVyPWUuZG93bmxvYWQsdGhpcy5kaXNwb3Nlcj1lLmRpc3Bvc2U7YnJlYWs7Y2FzZSJncHUtYnVmZmVyIjppZigiZmxvYXQzMiIhPT1uJiYiZmxvYXQxNiIhPT1uJiYiaW50MzIiIT09biYmImludDY0IiE9PW4mJiJ1aW50MzIiIT09biYmInVpbnQ4IiE9PW4mJiJib29sIiE9PW4mJiJ1aW50NCIhPT1uJiYiaW50NCIhPT1uKXRocm93IG5ldyBUeXBlRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGUgIiR7bn0iIHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbSBncHUgYnVmZmVyYCk7dGhpcy5ncHVCdWZmZXJEYXRhPWUuZ3B1QnVmZmVyLHRoaXMuZG93bmxvYWRlcj1lLmRvd25sb2FkLHRoaXMuZGlzcG9zZXI9ZS5kaXNwb3NlO2JyZWFrO2Nhc2UibWwtdGVuc29yIjppZigiZmxvYXQzMiIhPT1uJiYiZmxvYXQxNiIhPT1uJiYiaW50MzIiIT09biYmImludDY0IiE9PW4mJiJ1aW50MzIiIT09biYmInVpbnQ2NCIhPT1uJiYiaW50OCIhPT1uJiYidWludDgiIT09biYmImJvb2wiIT09biYmInVpbnQ0IiE9PW4mJiJpbnQ0IiE9PW4pdGhyb3cgbmV3IFR5cGVFcnJvcihgdW5zdXBwb3J0ZWQgdHlwZSAiJHtufSIgdG8gY3JlYXRlIHRlbnNvciBmcm9tIE1MVGVuc29yYCk7dGhpcy5tbFRlbnNvckRhdGE9ZS5tbFRlbnNvcix0aGlzLmRvd25sb2FkZXI9ZS5kb3dubG9hZCx0aGlzLmRpc3Bvc2VyPWUuZGlzcG9zZTticmVhaztkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgVGVuc29yIGNvbnN0cnVjdG9yOiB1bnN1cHBvcnRlZCBsb2NhdGlvbiAnJHt0aGlzLmRhdGFMb2NhdGlvbn0nYCl9ZWxzZSB7bGV0IGEsaTtpZigic3RyaW5nIj09dHlwZW9mIGUpaWYobj1lLGk9ciwic3RyaW5nIj09PWUpe2lmKCFBcnJheS5pc0FycmF5KHQpKXRocm93IG5ldyBUeXBlRXJyb3IoIkEgc3RyaW5nIHRlbnNvcidzIGRhdGEgbXVzdCBiZSBhIHN0cmluZyBhcnJheS4iKTthPXQ7fWVsc2Uge2xldCByPUguZ2V0KGUpO2lmKHZvaWQgMD09PXIpdGhyb3cgbmV3IFR5cGVFcnJvcihgVW5zdXBwb3J0ZWQgdGVuc29yIHR5cGU6ICR7ZX0uYCk7aWYoQXJyYXkuaXNBcnJheSh0KSl7aWYoImZsb2F0MTYiPT09ZSYmcj09PVVpbnQxNkFycmF5fHwidWludDQiPT09ZXx8ImludDQiPT09ZSl0aHJvdyBuZXcgVHlwZUVycm9yKGBDcmVhdGluZyBhICR7ZX0gdGVuc29yIGZyb20gbnVtYmVyIGFycmF5IGlzIG5vdCBzdXBwb3J0ZWQuIFBsZWFzZSB1c2UgJHtyLm5hbWV9IGFzIGRhdGEuYCk7YT0idWludDY0Ij09PWV8fCJpbnQ2NCI9PT1lP3IuZnJvbSh0LEJpZ0ludCk6ci5mcm9tKHQpO31lbHNlIGlmKHQgaW5zdGFuY2VvZiByKWE9dDtlbHNlIGlmKHQgaW5zdGFuY2VvZiBVaW50OENsYW1wZWRBcnJheSl7aWYoInVpbnQ4IiE9PWUpdGhyb3cgbmV3IFR5cGVFcnJvcigiQSBVaW50OENsYW1wZWRBcnJheSB0ZW5zb3IncyBkYXRhIG11c3QgYmUgdHlwZSBvZiB1aW50OCIpO2E9VWludDhBcnJheS5mcm9tKHQpO31lbHNlIHtpZighKCJmbG9hdDE2Ij09PWUmJnQgaW5zdGFuY2VvZiBVaW50MTZBcnJheSYmciE9PVVpbnQxNkFycmF5KSl0aHJvdyBuZXcgVHlwZUVycm9yKGBBICR7bn0gdGVuc29yJ3MgZGF0YSBtdXN0IGJlIHR5cGUgb2YgJHtyfWApO2E9bmV3IGdsb2JhbFRoaXMuRmxvYXQxNkFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0Lmxlbmd0aCk7fX1lbHNlIGlmKGk9dCxBcnJheS5pc0FycmF5KGUpKXtpZigwPT09ZS5sZW5ndGgpdGhyb3cgbmV3IFR5cGVFcnJvcigiVGVuc29yIHR5cGUgY2Fubm90IGJlIGluZmVycmVkIGZyb20gYW4gZW1wdHkgYXJyYXkuIik7bGV0IHQ9dHlwZW9mIGVbMF07aWYoInN0cmluZyI9PT10KW49InN0cmluZyIsYT1lO2Vsc2Uge2lmKCJib29sZWFuIiE9PXQpdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBlbGVtZW50IHR5cGUgb2YgZGF0YSBhcnJheTogJHt0fS5gKTtuPSJib29sIixhPVVpbnQ4QXJyYXkuZnJvbShlKTt9fWVsc2UgaWYoZSBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5KW49InVpbnQ4IixhPVVpbnQ4QXJyYXkuZnJvbShlKTtlbHNlIHtsZXQgdD1hZS5nZXQoZS5jb25zdHJ1Y3Rvcik7aWYodm9pZCAwPT09dCl0aHJvdyBuZXcgVHlwZUVycm9yKGBVbnN1cHBvcnRlZCB0eXBlIGZvciB0ZW5zb3IgZGF0YTogJHtlLmNvbnN0cnVjdG9yfS5gKTtuPXQsYT1lO31pZih2b2lkIDA9PT1pKWk9W2EubGVuZ3RoXTtlbHNlIGlmKCFBcnJheS5pc0FycmF5KGkpKXRocm93IG5ldyBUeXBlRXJyb3IoIkEgdGVuc29yJ3MgZGltcyBtdXN0IGJlIGEgbnVtYmVyIGFycmF5Iik7bz1pLHRoaXMuY3B1RGF0YT1hLHRoaXMuZGF0YUxvY2F0aW9uPSJjcHUiO31sZXQgYT1MdChvKTtpZih0aGlzLmNwdURhdGEmJmEhPT10aGlzLmNwdURhdGEubGVuZ3RoJiYoInVpbnQ0IiE9PW4mJiJpbnQ0IiE9PW58fE1hdGguY2VpbChhLzIpIT09dGhpcy5jcHVEYXRhLmxlbmd0aCkpdGhyb3cgbmV3IEVycm9yKGBUZW5zb3IncyBzaXplKCR7YX0pIGRvZXMgbm90IG1hdGNoIGRhdGEgbGVuZ3RoKCR7dGhpcy5jcHVEYXRhLmxlbmd0aH0pLmApO3RoaXMudHlwZT1uLHRoaXMuZGltcz1vLHRoaXMuc2l6ZT1hO31zdGF0aWMgYXN5bmMgZnJvbUltYWdlKGUsdCl7cmV0dXJuIHl0KGUsdCl9c3RhdGljIGZyb21UZXh0dXJlKGUsdCl7cmV0dXJuIGJ0KGUsdCl9c3RhdGljIGZyb21HcHVCdWZmZXIoZSx0KXtyZXR1cm4gZ3QoZSx0KX1zdGF0aWMgZnJvbU1MVGVuc29yKGUsdCl7cmV0dXJuIEV0KGUsdCl9c3RhdGljIGZyb21QaW5uZWRCdWZmZXIoZSx0LHIpe3JldHVybiBUdChlLHQscil9dG9EYXRhVVJMKGUpe3JldHVybiBtdCh0aGlzLGUpfXRvSW1hZ2VEYXRhKGUpe3JldHVybiBodCh0aGlzLGUpfWdldCBkYXRhKCl7aWYodGhpcy5lbnN1cmVWYWxpZCgpLCF0aGlzLmNwdURhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgb24gQ1BVLiBVc2UgYGdldERhdGEoKWAgdG8gZG93bmxvYWQgR1BVIGRhdGEgdG8gQ1BVLCBvciB1c2UgYHRleHR1cmVgIG9yIGBncHVCdWZmZXJgIHByb3BlcnR5IHRvIGFjY2VzcyB0aGUgR1BVIGRhdGEgZGlyZWN0bHkuIik7cmV0dXJuIHRoaXMuY3B1RGF0YX1nZXQgbG9jYXRpb24oKXtyZXR1cm4gdGhpcy5kYXRhTG9jYXRpb259Z2V0IHRleHR1cmUoKXtpZih0aGlzLmVuc3VyZVZhbGlkKCksIXRoaXMuZ3B1VGV4dHVyZURhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViR0wgdGV4dHVyZS4iKTtyZXR1cm4gdGhpcy5ncHVUZXh0dXJlRGF0YX1nZXQgZ3B1QnVmZmVyKCl7aWYodGhpcy5lbnN1cmVWYWxpZCgpLCF0aGlzLmdwdUJ1ZmZlckRhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViR1BVIGJ1ZmZlci4iKTtyZXR1cm4gdGhpcy5ncHVCdWZmZXJEYXRhfWdldCBtbFRlbnNvcigpe2lmKHRoaXMuZW5zdXJlVmFsaWQoKSwhdGhpcy5tbFRlbnNvckRhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViTk4gTUxUZW5zb3IuIik7cmV0dXJuIHRoaXMubWxUZW5zb3JEYXRhfWFzeW5jIGdldERhdGEoZSl7c3dpdGNoKHRoaXMuZW5zdXJlVmFsaWQoKSx0aGlzLmRhdGFMb2NhdGlvbil7Y2FzZSJjcHUiOmNhc2UiY3B1LXBpbm5lZCI6cmV0dXJuIHRoaXMuZGF0YTtjYXNlInRleHR1cmUiOmNhc2UiZ3B1LWJ1ZmZlciI6Y2FzZSJtbC10ZW5zb3IiOmlmKCF0aGlzLmRvd25sb2FkZXIpdGhyb3cgbmV3IEVycm9yKCJUaGUgY3VycmVudCB0ZW5zb3IgaXMgbm90IGNyZWF0ZWQgd2l0aCBhIHNwZWNpZmllZCBkYXRhIGRvd25sb2FkZXIuIik7aWYodGhpcy5pc0Rvd25sb2FkaW5nKXRocm93IG5ldyBFcnJvcigiVGhlIGN1cnJlbnQgdGVuc29yIGlzIGJlaW5nIGRvd25sb2FkZWQuIik7dHJ5e3RoaXMuaXNEb3dubG9hZGluZz0hMDtsZXQgdD1hd2FpdCB0aGlzLmRvd25sb2FkZXIoKTtyZXR1cm4gdGhpcy5kb3dubG9hZGVyPXZvaWQgMCx0aGlzLmRhdGFMb2NhdGlvbj0iY3B1Iix0aGlzLmNwdURhdGE9dCxlJiZ0aGlzLmRpc3Bvc2VyJiYodGhpcy5kaXNwb3NlcigpLHRoaXMuZGlzcG9zZXI9dm9pZCAwKSx0fWZpbmFsbHl7dGhpcy5pc0Rvd25sb2FkaW5nPSExO31kZWZhdWx0OnRocm93IG5ldyBFcnJvcihgY2Fubm90IGdldCBkYXRhIGZyb20gbG9jYXRpb246ICR7dGhpcy5kYXRhTG9jYXRpb259YCl9fWRpc3Bvc2UoKXtpZih0aGlzLmlzRG93bmxvYWRpbmcpdGhyb3cgbmV3IEVycm9yKCJUaGUgY3VycmVudCB0ZW5zb3IgaXMgYmVpbmcgZG93bmxvYWRlZC4iKTt0aGlzLmRpc3Bvc2VyJiYodGhpcy5kaXNwb3NlcigpLHRoaXMuZGlzcG9zZXI9dm9pZCAwKSx0aGlzLmNwdURhdGE9dm9pZCAwLHRoaXMuZ3B1VGV4dHVyZURhdGE9dm9pZCAwLHRoaXMuZ3B1QnVmZmVyRGF0YT12b2lkIDAsdGhpcy5tbFRlbnNvckRhdGE9dm9pZCAwLHRoaXMuZG93bmxvYWRlcj12b2lkIDAsdGhpcy5pc0Rvd25sb2FkaW5nPXZvaWQgMCx0aGlzLmRhdGFMb2NhdGlvbj0ibm9uZSI7fWVuc3VyZVZhbGlkKCl7aWYoIm5vbmUiPT09dGhpcy5kYXRhTG9jYXRpb24pdGhyb3cgbmV3IEVycm9yKCJUaGUgdGVuc29yIGlzIGRpc3Bvc2VkLiIpfXJlc2hhcGUoZSl7aWYodGhpcy5lbnN1cmVWYWxpZCgpLHRoaXMuZG93bmxvYWRlcnx8dGhpcy5kaXNwb3Nlcil0aHJvdyBuZXcgRXJyb3IoIkNhbm5vdCByZXNoYXBlIGEgdGVuc29yIHRoYXQgb3ducyBHUFUgcmVzb3VyY2UuIik7cmV0dXJuIEl0KHRoaXMsZSl9fTt9KSksVmU9VCgoKCk9Pnt3ZSgpLFI9djt9KSksWWU9VCgoKCk9PntqZSgpLHZ0PShlLHQpPT57KHR5cGVvZiBfLnRyYWNlPiJ1Ij8hXy53YXNtLnRyYWNlOiFfLnRyYWNlKXx8Y29uc29sZS50aW1lU3RhbXAoYCR7ZX06Ok9SVDo6JHt0fWApO30sQnQ9KGUsdCk9PntsZXQgcj0obmV3IEVycm9yKS5zdGFjaz8uc3BsaXQoL1xyXG58XHJ8XG4vZyl8fFtdLG49ITE7Zm9yKGxldCBvPTA7bzxyLmxlbmd0aDtvKyspe2lmKG4mJiFyW29dLmluY2x1ZGVzKCJUUkFDRV9GVU5DIikpe2xldCBuPWBGVU5DXyR7ZX06OiR7cltvXS50cmltKCkuc3BsaXQoIiAiKVsxXX1gO3JldHVybiB0JiYobis9YDo6JHt0fWApLHZvaWQgdnQoIkNQVSIsbil9cltvXS5pbmNsdWRlcygiVFJBQ0VfRlVOQyIpJiYobj0hMCk7fX0sVj1lPT57KHR5cGVvZiBfLnRyYWNlPiJ1Ij8hXy53YXNtLnRyYWNlOiFfLnRyYWNlKXx8QnQoIkJFR0lOIixlKTt9LFk9ZT0+eyh0eXBlb2YgXy50cmFjZT4idSI/IV8ud2FzbS50cmFjZTohXy50cmFjZSl8fEJ0KCJFTkQiLGUpO307fSkpLEN0PVQoKCgpPT57emUoKSxWZSgpLFllKCkseWU9Y2xhc3MgZXtjb25zdHJ1Y3RvcihlKXt0aGlzLmhhbmRsZXI9ZTt9YXN5bmMgcnVuKGUsdCxyKXtWKCk7bGV0IG49e30sbz17fTtpZigib2JqZWN0IiE9dHlwZW9mIGV8fG51bGw9PT1lfHxlIGluc3RhbmNlb2YgUnx8QXJyYXkuaXNBcnJheShlKSl0aHJvdyBuZXcgVHlwZUVycm9yKCInZmVlZHMnIG11c3QgYmUgYW4gb2JqZWN0IHRoYXQgdXNlIGlucHV0IG5hbWVzIGFzIGtleXMgYW5kIE9ubnhWYWx1ZSBhcyBjb3JyZXNwb25kaW5nIHZhbHVlcy4iKTtsZXQgYT0hMDtpZigib2JqZWN0Ij09dHlwZW9mIHQpe2lmKG51bGw9PT10KXRocm93IG5ldyBUeXBlRXJyb3IoIlVuZXhwZWN0ZWQgYXJndW1lbnRbMV06IGNhbm5vdCBiZSBudWxsLiIpO2lmKHQgaW5zdGFuY2VvZiBSKXRocm93IG5ldyBUeXBlRXJyb3IoIidmZXRjaGVzJyBjYW5ub3QgYmUgYSBUZW5zb3IiKTtpZihBcnJheS5pc0FycmF5KHQpKXtpZigwPT09dC5sZW5ndGgpdGhyb3cgbmV3IFR5cGVFcnJvcigiJ2ZldGNoZXMnIGNhbm5vdCBiZSBhbiBlbXB0eSBhcnJheS4iKTthPSExO2ZvcihsZXQgZSBvZiB0KXtpZigic3RyaW5nIiE9dHlwZW9mIGUpdGhyb3cgbmV3IFR5cGVFcnJvcigiJ2ZldGNoZXMnIG11c3QgYmUgYSBzdHJpbmcgYXJyYXkgb3IgYW4gb2JqZWN0LiIpO2lmKC0xPT09dGhpcy5vdXRwdXROYW1lcy5pbmRleE9mKGUpKXRocm93IG5ldyBSYW5nZUVycm9yKGAnZmV0Y2hlcycgY29udGFpbnMgaW52YWxpZCBvdXRwdXQgbmFtZTogJHtlfS5gKTtuW2VdPW51bGw7fWlmKCJvYmplY3QiPT10eXBlb2YgciYmbnVsbCE9PXIpbz1yO2Vsc2UgaWYodHlwZW9mIHI8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIHtsZXQgZT0hMSxpPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHQpO2ZvcihsZXQgciBvZiB0aGlzLm91dHB1dE5hbWVzKWlmKC0xIT09aS5pbmRleE9mKHIpKXtsZXQgbz10W3JdOyhudWxsPT09b3x8byBpbnN0YW5jZW9mIFIpJiYoZT0hMCxhPSExLG5bcl09byk7fWlmKGUpe2lmKCJvYmplY3QiPT10eXBlb2YgciYmbnVsbCE9PXIpbz1yO2Vsc2UgaWYodHlwZW9mIHI8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIG89dDt9fWVsc2UgaWYodHlwZW9mIHQ8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIlVuZXhwZWN0ZWQgYXJndW1lbnRbMV06IG11c3QgYmUgJ2ZldGNoZXMnIG9yICdvcHRpb25zJy4iKTtmb3IobGV0IHQgb2YgdGhpcy5pbnB1dE5hbWVzKWlmKHR5cGVvZiBlW3RdPiJ1Iil0aHJvdyBuZXcgRXJyb3IoYGlucHV0ICcke3R9JyBpcyBtaXNzaW5nIGluICdmZWVkcycuYCk7aWYoYSlmb3IobGV0IGUgb2YgdGhpcy5vdXRwdXROYW1lcyluW2VdPW51bGw7bGV0IGk9YXdhaXQgdGhpcy5oYW5kbGVyLnJ1bihlLG4sbykscz17fTtmb3IobGV0IGUgaW4gaSlpZihPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChpLGUpKXtsZXQgdD1pW2VdO3NbZV09dCBpbnN0YW5jZW9mIFI/dDpuZXcgUih0LnR5cGUsdC5kYXRhLHQuZGltcyk7fXJldHVybiBZKCksc31hc3luYyByZWxlYXNlKCl7cmV0dXJuIHRoaXMuaGFuZGxlci5kaXNwb3NlKCl9c3RhdGljIGFzeW5jIGNyZWF0ZSh0LHIsbixvKXtWKCk7bGV0IGEsaT17fTtpZigic3RyaW5nIj09dHlwZW9mIHQpe2lmKGE9dCwib2JqZWN0Ij09dHlwZW9mIHImJm51bGwhPT1yKWk9cjtlbHNlIGlmKHR5cGVvZiByPCJ1Iil0aHJvdyBuZXcgVHlwZUVycm9yKCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuIil9ZWxzZSBpZih0IGluc3RhbmNlb2YgVWludDhBcnJheSl7aWYoYT10LCJvYmplY3QiPT10eXBlb2YgciYmbnVsbCE9PXIpaT1yO2Vsc2UgaWYodHlwZW9mIHI8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIHtpZighKHQgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcnx8dHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyPCJ1IiYmdCBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyKSl0aHJvdyBuZXcgVHlwZUVycm9yKCJVbmV4cGVjdGVkIGFyZ3VtZW50WzBdOiBtdXN0IGJlICdwYXRoJyBvciAnYnVmZmVyJy4iKTt7bGV0IGU9dCxzPTAsbD10LmJ5dGVMZW5ndGg7aWYoIm9iamVjdCI9PXR5cGVvZiByJiZudWxsIT09cilpPXI7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIHIpe2lmKHM9ciwhTnVtYmVyLmlzU2FmZUludGVnZXIocykpdGhyb3cgbmV3IFJhbmdlRXJyb3IoIidieXRlT2Zmc2V0JyBtdXN0IGJlIGFuIGludGVnZXIuIik7aWYoczwwfHxzPj1lLmJ5dGVMZW5ndGgpdGhyb3cgbmV3IFJhbmdlRXJyb3IoYCdieXRlT2Zmc2V0JyBpcyBvdXQgb2YgcmFuZ2UgWzAsICR7ZS5ieXRlTGVuZ3RofSkuYCk7aWYobD10LmJ5dGVMZW5ndGgtcywibnVtYmVyIj09dHlwZW9mIG4pe2lmKGw9biwhTnVtYmVyLmlzU2FmZUludGVnZXIobCkpdGhyb3cgbmV3IFJhbmdlRXJyb3IoIidieXRlTGVuZ3RoJyBtdXN0IGJlIGFuIGludGVnZXIuIik7aWYobDw9MHx8cytsPmUuYnl0ZUxlbmd0aCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihgJ2J5dGVMZW5ndGgnIGlzIG91dCBvZiByYW5nZSAoMCwgJHtlLmJ5dGVMZW5ndGgtc31dLmApO2lmKCJvYmplY3QiPT10eXBlb2YgbyYmbnVsbCE9PW8paT1vO2Vsc2UgaWYodHlwZW9mIG88InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIGlmKHR5cGVvZiBuPCJ1Iil0aHJvdyBuZXcgVHlwZUVycm9yKCInYnl0ZUxlbmd0aCcgbXVzdCBiZSBhIG51bWJlci4iKX1lbHNlIGlmKHR5cGVvZiByPCJ1Iil0aHJvdyBuZXcgVHlwZUVycm9yKCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuIik7YT1uZXcgVWludDhBcnJheShlLHMsbCk7fX1sZXRbcyxsXT1hd2FpdCB1dChpKSx1PWF3YWl0IHMuY3JlYXRlSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIoYSxsKTtyZXR1cm4gWSgpLG5ldyBlKHUpfXN0YXJ0UHJvZmlsaW5nKCl7dGhpcy5oYW5kbGVyLnN0YXJ0UHJvZmlsaW5nKCk7fWVuZFByb2ZpbGluZygpe3RoaXMuaGFuZGxlci5lbmRQcm9maWxpbmcoKTt9Z2V0IGlucHV0TmFtZXMoKXtyZXR1cm4gdGhpcy5oYW5kbGVyLmlucHV0TmFtZXN9Z2V0IG91dHB1dE5hbWVzKCl7cmV0dXJuIHRoaXMuaGFuZGxlci5vdXRwdXROYW1lc319O30pKSxVdD1UKCgoKT0+e0N0KCksT3I9eWU7fSkpLF90PVQoKCgpPT57fSkpLE10PVQoKCgpPT57fSkpLER0PVQoKCgpPT57fSkpLFJ0PVQoKCgpPT57fSkpLHFlPXt9O0dlKHFlLHtJbmZlcmVuY2VTZXNzaW9uOigpPT5PcixUUkFDRTooKT0+dnQsVFJBQ0VfRlVOQ19CRUdJTjooKT0+VixUUkFDRV9GVU5DX0VORDooKT0+WSxUZW5zb3I6KCk9PlIsZW52OigpPT5BLHJlZ2lzdGVyQmFja2VuZDooKT0+aWV9KTt2YXIgcT1UKCgoKT0+e2Z0KCkscHQoKSxVdCgpLFZlKCksX3QoKSxNdCgpLFllKCksRHQoKSxSdCgpO30pKSxiZT1UKCgoKT0+e30pKSxXdD17fTtHZShXdCx7ZGVmYXVsdDooKT0+eHJ9KTt2YXIga3QsTnQseHIsanQsTSxQZSxYZSxJcixQcixIdCx2cixHdCxWdCx6dCxZdCxaZSxLZSx2ZSxxdCxCcixDcixFZSx4LEwsZmUsUyxKdCxVcixfcixNcixEcixadCxlZSxRdCx0ZSxlcix0cixDZSxVZSxycixjZSxScixUZSxTZSxyZSxGcix1ZSxBZSxPZSxucix4ZSxMZSxJZSxaLEQsbGUsTWUsRGUsX2UsdHQscnQsbmUsb2UsTnIsb3Isc3IsaXIsYXIsdXIsZnIsY3IsbHIsV3IsUmUsJHQ9VCgoKCk9PntKZSgpLEooKSxnZSgpLGt0PSJvcnQtd2FzbS1wcm94eS13b3JrZXIiLChOdD1nbG9iYWxUaGlzLnNlbGY/Lm5hbWU9PT1rdCkmJihzZWxmLm9ubWVzc2FnZT1lPT57bGV0e3R5cGU6dCxpbjpyfT1lLmRhdGE7dHJ5e3N3aXRjaCh0KXtjYXNlImluaXQtd2FzbSI6RWUoci53YXNtKS50aGVuKCgoKT0+e1RlKHIpLnRoZW4oKCgpPT57cG9zdE1lc3NhZ2Uoe3R5cGU6dH0pO30pLChlPT57cG9zdE1lc3NhZ2Uoe3R5cGU6dCxlcnI6ZX0pO30pKTt9KSwoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsZXJyOmV9KTt9KSk7YnJlYWs7Y2FzZSJpbml0LWVwIjp7bGV0e2VwTmFtZTplLGVudjpufT1yO1NlKG4sZSkudGhlbigoKCk9Pntwb3N0TWVzc2FnZSh7dHlwZTp0fSk7fSksKGU9Pntwb3N0TWVzc2FnZSh7dHlwZTp0LGVycjplfSk7fSkpO2JyZWFrfWNhc2UiY29weS1mcm9tIjp7bGV0e2J1ZmZlcjplfT1yLG49dWUoZSk7cG9zdE1lc3NhZ2Uoe3R5cGU6dCxvdXQ6bn0pO2JyZWFrfWNhc2UiY3JlYXRlIjp7bGV0e21vZGVsOmUsb3B0aW9uczpufT1yO0FlKGUsbikudGhlbigoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsb3V0OmV9KTt9KSwoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsZXJyOmV9KTt9KSk7YnJlYWt9Y2FzZSJyZWxlYXNlIjpPZShyKSxwb3N0TWVzc2FnZSh7dHlwZTp0fSk7YnJlYWs7Y2FzZSJydW4iOntsZXR7c2Vzc2lvbklkOmUsaW5wdXRJbmRpY2VzOm4saW5wdXRzOm8sb3V0cHV0SW5kaWNlczphLG9wdGlvbnM6aX09cjt4ZShlLG4sbyxhLG5ldyBBcnJheShhLmxlbmd0aCkuZmlsbChudWxsKSxpKS50aGVuKChlPT57ZS5zb21lKChlPT4iY3B1IiE9PWVbM10pKT9wb3N0TWVzc2FnZSh7dHlwZTp0LGVycjoiUHJveHkgZG9lcyBub3Qgc3VwcG9ydCBub24tY3B1IHRlbnNvciBsb2NhdGlvbi4ifSk6cG9zdE1lc3NhZ2Uoe3R5cGU6dCxvdXQ6ZX0sSWUoWy4uLm8sLi4uZV0pKTt9KSwoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsZXJyOmV9KTt9KSk7YnJlYWt9Y2FzZSJlbmQtcHJvZmlsaW5nIjpMZShyKSxwb3N0TWVzc2FnZSh7dHlwZTp0fSk7fX1jYXRjaChlKXtwb3N0TWVzc2FnZSh7dHlwZTp0LGVycjplfSk7fX0pLHhyPU50P251bGw6ZT0+bmV3IFdvcmtlcihlPz9NLHt0eXBlOiJtb2R1bGUiLG5hbWU6a3R9KTt9KSksZ2U9VCgoKCk9PntiZSgpLGp0PXR5cGVvZiBsb2NhdGlvbj4idSI/dm9pZCAwOmxvY2F0aW9uLm9yaWdpbixNPSgoKT0+aW1wb3J0Lm1ldGEudXJsPy5zdGFydHNXaXRoKCJmaWxlOiIpP25ldyBVUkwobmV3IFVSTCgib3J0Lndhc20uYnVuZGxlLm1pbi5tanMiLGltcG9ydC5tZXRhLnVybCkuaHJlZixqdCkuaHJlZjppbXBvcnQubWV0YS51cmwpKCksUGU9KCk9PntpZihNJiYhTS5zdGFydHNXaXRoKCJibG9iOiIpKXJldHVybiBNLnN1YnN0cmluZygwLE0ubGFzdEluZGV4T2YoIi8iKSsxKX0sWGU9KGUsdCk9Pnt0cnl7bGV0IHI9dD8/TTtyZXR1cm4gKHI/bmV3IFVSTChlLHIpOm5ldyBVUkwoZSkpLm9yaWdpbj09PWp0fWNhdGNoe3JldHVybiAhMX19LElyPShlLHQpPT57bGV0IHI9dD8/TTt0cnl7cmV0dXJuIChyP25ldyBVUkwoZSxyKTpuZXcgVVJMKGUpKS5ocmVmfWNhdGNoe3JldHVybn19LFByPShlLHQpPT5gJHt0Pz8iLi8ifSR7ZX1gLEh0PWFzeW5jIGU9PntsZXQgdD1hd2FpdChhd2FpdCBmZXRjaChlLHtjcmVkZW50aWFsczoic2FtZS1vcmlnaW4ifSkpLmJsb2IoKTtyZXR1cm4gVVJMLmNyZWF0ZU9iamVjdFVSTCh0KX0sdnI9YXN5bmMgZT0+KGF3YWl0IGltcG9ydChlKSkuZGVmYXVsdCxHdD0oJHQoKSxhdChXdCkpLmRlZmF1bHQsVnQ9YXN5bmMoKT0+e2lmKCFNKXRocm93IG5ldyBFcnJvcigiRmFpbGVkIHRvIGxvYWQgcHJveHkgd29ya2VyOiBjYW5ub3QgZGV0ZXJtaW5lIHRoZSBzY3JpcHQgc291cmNlIFVSTC4iKTtpZihYZShNKSlyZXR1cm4gW3ZvaWQgMCxHdCgpXTtsZXQgZT1hd2FpdCBIdChNKTtyZXR1cm4gW2UsR3QoZSldfSx6dD12b2lkIDAsWXQ9YXN5bmMoZSx0LHIpPT57aWYoIWUmJiF0JiZ6dCYmTSYmWGUoTSkpcmV0dXJuIFt2b2lkIDAsenRdO3tsZXQgbj0ib3J0LXdhc20tc2ltZC10aHJlYWRlZC5tanMiLG89ZT8/SXIobix0KSxhPXImJm8mJiFYZShvLHQpLGk9YT9hd2FpdCBIdChvKTpvPz9QcihuLHQpO3JldHVybiBbYT9pOnZvaWQgMCxhd2FpdCB2cihpKV19fTt9KSksSj1UKCgoKT0+e2dlKCksS2U9ITEsdmU9ITEscXQ9ITEsQnI9KCk9PntpZih0eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXI+InUiKXJldHVybiAhMTt0cnl7cmV0dXJuIHR5cGVvZiBNZXNzYWdlQ2hhbm5lbDwidSImJihuZXcgTWVzc2FnZUNoYW5uZWwpLnBvcnQxLnBvc3RNZXNzYWdlKG5ldyBTaGFyZWRBcnJheUJ1ZmZlcigxKSksV2ViQXNzZW1ibHkudmFsaWRhdGUobmV3IFVpbnQ4QXJyYXkoWzAsOTcsMTE1LDEwOSwxLDAsMCwwLDEsNCwxLDk2LDAsMCwzLDIsMSwwLDUsNCwxLDMsMSwxLDEwLDExLDEsOSwwLDY1LDAsMjU0LDE2LDIsMCwyNiwxMV0pKX1jYXRjaHtyZXR1cm4gITF9fSxDcj0oKT0+e3RyeXtyZXR1cm4gV2ViQXNzZW1ibHkudmFsaWRhdGUobmV3IFVpbnQ4QXJyYXkoWzAsOTcsMTE1LDEwOSwxLDAsMCwwLDEsNCwxLDk2LDAsMCwzLDIsMSwwLDEwLDMwLDEsMjgsMCw2NSwwLDI1MywxNSwyNTMsMTIsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwyNTMsMTg2LDEsMjYsMTFdKSl9Y2F0Y2h7cmV0dXJuICExfX0sRWU9YXN5bmMgZT0+e2lmKEtlKXJldHVybiBQcm9taXNlLnJlc29sdmUoKTtpZih2ZSl0aHJvdyBuZXcgRXJyb3IoIm11bHRpcGxlIGNhbGxzIHRvICdpbml0aWFsaXplV2ViQXNzZW1ibHkoKScgZGV0ZWN0ZWQuIik7aWYocXQpdGhyb3cgbmV3IEVycm9yKCJwcmV2aW91cyBjYWxsIHRvICdpbml0aWFsaXplV2ViQXNzZW1ibHkoKScgZmFpbGVkLiIpO3ZlPSEwO2xldCB0PWUuaW5pdFRpbWVvdXQscj1lLm51bVRocmVhZHM7aWYoIUNyKCkpdGhyb3cgbmV3IEVycm9yKCJXZWJBc3NlbWJseSBTSU1EIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuIik7bGV0IG49QnIoKTtyPjEmJiFuJiYodHlwZW9mIHNlbGY8InUiJiYhc2VsZi5jcm9zc09yaWdpbklzb2xhdGVkJiZjb25zb2xlLndhcm4oImVudi53YXNtLm51bVRocmVhZHMgaXMgc2V0IHRvICIrcisiLCBidXQgdGhpcyB3aWxsIG5vdCB3b3JrIHVubGVzcyB5b3UgZW5hYmxlIGNyb3NzT3JpZ2luSXNvbGF0ZWQgbW9kZS4gU2VlIGh0dHBzOi8vd2ViLmRldi9jcm9zcy1vcmlnaW4taXNvbGF0aW9uLWd1aWRlLyBmb3IgbW9yZSBpbmZvLiIpLGNvbnNvbGUud2FybigiV2ViQXNzZW1ibHkgbXVsdGktdGhyZWFkaW5nIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuIEZhbGxpbmcgYmFjayB0byBzaW5nbGUtdGhyZWFkaW5nLiIpLGUubnVtVGhyZWFkcz1yPTEpO2xldCBvPWUud2FzbVBhdGhzLGE9InN0cmluZyI9PXR5cGVvZiBvP286dm9pZCAwLGk9bz8ubWpzLHM9aT8uaHJlZj8/aSxsPW8/Lndhc20sdT1sPy5ocmVmPz9sLGY9ZS53YXNtQmluYXJ5LFtkLHBdPWF3YWl0IFl0KHMsYSxyPjEpLGM9ITEsaD1bXTtpZih0PjAmJmgucHVzaChuZXcgUHJvbWlzZSgoZT0+e3NldFRpbWVvdXQoKCgpPT57Yz0hMCxlKCk7fSksdCk7fSkpKSxoLnB1c2gobmV3IFByb21pc2UoKChlLHQpPT57bGV0IG49e251bVRocmVhZHM6cn07aWYoZiluLndhc21CaW5hcnk9ZjtlbHNlIGlmKHV8fGEpbi5sb2NhdGVGaWxlPWU9PnU/P2ErZTtlbHNlIGlmKHMmJjAhPT1zLmluZGV4T2YoImJsb2I6Iikpbi5sb2NhdGVGaWxlPWU9Pm5ldyBVUkwoZSxzKS5ocmVmO2Vsc2UgaWYoZCl7bGV0IGU9UGUoKTtlJiYobi5sb2NhdGVGaWxlPXQ9PmUrdCk7fXAobikudGhlbigodD0+e3ZlPSExLEtlPSEwLFplPXQsZSgpLGQmJlVSTC5yZXZva2VPYmplY3RVUkwoZCk7fSksKGU9Pnt2ZT0hMSxxdD0hMCx0KGUpO30pKTt9KSkpLGF3YWl0IFByb21pc2UucmFjZShoKSxjKXRocm93IG5ldyBFcnJvcihgV2ViQXNzZW1ibHkgYmFja2VuZCBpbml0aWFsaXppbmcgZmFpbGVkIGR1ZSB0byB0aW1lb3V0OiAke3R9bXNgKX0seD0oKT0+e2lmKEtlJiZaZSlyZXR1cm4gWmU7dGhyb3cgbmV3IEVycm9yKCJXZWJBc3NlbWJseSBpcyBub3QgaW5pdGlhbGl6ZWQgeWV0LiIpfTt9KSksQmU9VCgoKCk9PntKKCksTD0oZSx0KT0+e2xldCByPXgoKSxuPXIubGVuZ3RoQnl0ZXNVVEY4KGUpKzEsbz1yLl9tYWxsb2Mobik7cmV0dXJuIHIuc3RyaW5nVG9VVEY4KGUsbyxuKSx0LnB1c2gobyksb30sZmU9KGUsdCxyLG4pPT57aWYoIm9iamVjdCI9PXR5cGVvZiBlJiZudWxsIT09ZSl7aWYoci5oYXMoZSkpdGhyb3cgbmV3IEVycm9yKCJDaXJjdWxhciByZWZlcmVuY2UgaW4gb3B0aW9ucyIpO3IuYWRkKGUpO31PYmplY3QuZW50cmllcyhlKS5mb3JFYWNoKCgoW2Usb10pPT57bGV0IGE9dD90K2U6ZTtpZigib2JqZWN0Ij09dHlwZW9mIG8pZmUobyxhKyIuIixyLG4pO2Vsc2UgaWYoInN0cmluZyI9PXR5cGVvZiBvfHwibnVtYmVyIj09dHlwZW9mIG8pbihhLG8udG9TdHJpbmcoKSk7ZWxzZSB7aWYoImJvb2xlYW4iIT10eXBlb2Ygbyl0aHJvdyBuZXcgRXJyb3IoIkNhbid0IGhhbmRsZSBleHRyYSBjb25maWcgdHlwZTogIit0eXBlb2Ygbyk7bihhLG8/IjEiOiIwIik7fX0pKTt9LFM9ZT0+e2xldCB0PXgoKSxyPXQuc3RhY2tTYXZlKCk7dHJ5e2xldCByPXQuUFRSX1NJWkUsbj10LnN0YWNrQWxsb2MoMipyKTt0Ll9PcnRHZXRMYXN0RXJyb3IobixuK3IpO2xldCBvPU51bWJlcih0LmdldFZhbHVlKG4sND09PXI/ImkzMiI6Imk2NCIpKSxhPXQuZ2V0VmFsdWUobityLCIqIiksaT1hP3QuVVRGOFRvU3RyaW5nKGEpOiIiO3Rocm93IG5ldyBFcnJvcihgJHtlfSBFUlJPUl9DT0RFOiAke299LCBFUlJPUl9NRVNTQUdFOiAke2l9YCl9ZmluYWxseXt0LnN0YWNrUmVzdG9yZShyKTt9fTt9KSksWHQ9VCgoKCk9PntKKCksQmUoKSxKdD1lPT57bGV0IHQ9eCgpLHI9MCxuPVtdLG89ZXx8e307dHJ5e2lmKHZvaWQgMD09PWU/LmxvZ1NldmVyaXR5TGV2ZWwpby5sb2dTZXZlcml0eUxldmVsPTI7ZWxzZSBpZigibnVtYmVyIiE9dHlwZW9mIGUubG9nU2V2ZXJpdHlMZXZlbHx8IU51bWJlci5pc0ludGVnZXIoZS5sb2dTZXZlcml0eUxldmVsKXx8ZS5sb2dTZXZlcml0eUxldmVsPDB8fGUubG9nU2V2ZXJpdHlMZXZlbD40KXRocm93IG5ldyBFcnJvcihgbG9nIHNlcnZlcml0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7ZS5sb2dTZXZlcml0eUxldmVsfWApO2lmKHZvaWQgMD09PWU/LmxvZ1ZlcmJvc2l0eUxldmVsKW8ubG9nVmVyYm9zaXR5TGV2ZWw9MDtlbHNlIGlmKCJudW1iZXIiIT10eXBlb2YgZS5sb2dWZXJib3NpdHlMZXZlbHx8IU51bWJlci5pc0ludGVnZXIoZS5sb2dWZXJib3NpdHlMZXZlbCkpdGhyb3cgbmV3IEVycm9yKGBsb2cgdmVyYm9zaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtlLmxvZ1ZlcmJvc2l0eUxldmVsfWApO3ZvaWQgMD09PWU/LnRlcm1pbmF0ZSYmKG8udGVybWluYXRlPSExKTtsZXQgYT0wO3JldHVybiB2b2lkIDAhPT1lPy50YWcmJihhPUwoZS50YWcsbikpLHI9dC5fT3J0Q3JlYXRlUnVuT3B0aW9ucyhvLmxvZ1NldmVyaXR5TGV2ZWwsby5sb2dWZXJib3NpdHlMZXZlbCwhIW8udGVybWluYXRlLGEpLDA9PT1yJiZTKCJDYW4ndCBjcmVhdGUgcnVuIG9wdGlvbnMuIiksdm9pZCAwIT09ZT8uZXh0cmEmJmZlKGUuZXh0cmEsIiIsbmV3IFdlYWtTZXQsKChlLG8pPT57bGV0IGE9TChlLG4pLGk9TChvLG4pOzAhPT10Ll9PcnRBZGRSdW5Db25maWdFbnRyeShyLGEsaSkmJlMoYENhbid0IHNldCBhIHJ1biBjb25maWcgZW50cnk6ICR7ZX0gLSAke299LmApO30pKSxbcixuXX1jYXRjaChlKXt0aHJvdyAwIT09ciYmdC5fT3J0UmVsZWFzZVJ1bk9wdGlvbnMociksbi5mb3JFYWNoKChlPT50Ll9mcmVlKGUpKSksZX19O30pKSxLdD1UKCgoKT0+e0ooKSxCZSgpLFVyPWU9Pntzd2l0Y2goZSl7Y2FzZSJkaXNhYmxlZCI6cmV0dXJuIDA7Y2FzZSJiYXNpYyI6cmV0dXJuIDE7Y2FzZSJleHRlbmRlZCI6cmV0dXJuIDI7Y2FzZSJhbGwiOnJldHVybiA5OTtkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZ3JhcGggb3B0aW1pemF0aW9uIGxldmVsOiAke2V9YCl9fSxfcj1lPT57c3dpdGNoKGUpe2Nhc2Uic2VxdWVudGlhbCI6cmV0dXJuIDA7Y2FzZSJwYXJhbGxlbCI6cmV0dXJuIDE7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGV4ZWN1dGlvbiBtb2RlOiAke2V9YCl9fSxNcj1lPT57ZS5leHRyYXx8KGUuZXh0cmE9e30pLGUuZXh0cmEuc2Vzc2lvbnx8KGUuZXh0cmEuc2Vzc2lvbj17fSk7bGV0IHQ9ZS5leHRyYS5zZXNzaW9uO3QudXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseXx8KHQudXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseT0iMSIpLGUuZXhlY3V0aW9uUHJvdmlkZXJzJiZlLmV4ZWN1dGlvblByb3ZpZGVycy5zb21lKChlPT4id2ViZ3B1Ij09PSgic3RyaW5nIj09dHlwZW9mIGU/ZTplLm5hbWUpKSkmJihlLmVuYWJsZU1lbVBhdHRlcm49ITEpO30sRHI9KGUsdCxyKT0+e2ZvcihsZXQgbiBvZiB0KXtsZXQgdD0ic3RyaW5nIj09dHlwZW9mIG4/bjpuLm5hbWU7c3dpdGNoKHQpe2Nhc2Uid2Vibm4iOmlmKHQ9IldFQk5OIiwic3RyaW5nIiE9dHlwZW9mIG4pe2xldCB0PW4/LmRldmljZVR5cGU7aWYodCl7bGV0IG49TCgiZGV2aWNlVHlwZSIsciksbz1MKHQscik7MCE9PXgoKS5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5KGUsbixvKSYmUyhgQ2FuJ3Qgc2V0IGEgc2Vzc2lvbiBjb25maWcgZW50cnk6ICdkZXZpY2VUeXBlJyAtICR7dH0uYCk7fX1icmVhaztjYXNlIndlYmdwdSI6aWYodD0iSlMiLCJzdHJpbmciIT10eXBlb2Ygbil7bGV0IHQ9bjtpZih0Py5wcmVmZXJyZWRMYXlvdXQpe2lmKCJOQ0hXIiE9PXQucHJlZmVycmVkTGF5b3V0JiYiTkhXQyIhPT10LnByZWZlcnJlZExheW91dCl0aHJvdyBuZXcgRXJyb3IoYHByZWZlcnJlZExheW91dCBtdXN0IGJlIGVpdGhlciAnTkNIVycgb3IgJ05IV0MnOiAke3QucHJlZmVycmVkTGF5b3V0fWApO2xldCBuPUwoInByZWZlcnJlZExheW91dCIsciksbz1MKHQucHJlZmVycmVkTGF5b3V0LHIpOzAhPT14KCkuX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShlLG4sbykmJlMoYENhbid0IHNldCBhIHNlc3Npb24gY29uZmlnIGVudHJ5OiAncHJlZmVycmVkTGF5b3V0JyAtICR7dC5wcmVmZXJyZWRMYXlvdXR9LmApO319YnJlYWs7Y2FzZSJ3YXNtIjpjYXNlImNwdSI6Y29udGludWU7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYG5vdCBzdXBwb3J0ZWQgZXhlY3V0aW9uIHByb3ZpZGVyOiAke3R9YCl9bGV0IG89TCh0LHIpOzAhPT14KCkuX09ydEFwcGVuZEV4ZWN1dGlvblByb3ZpZGVyKGUsbykmJlMoYENhbid0IGFwcGVuZCBleGVjdXRpb24gcHJvdmlkZXI6ICR7dH0uYCk7fX0sWnQ9ZT0+e2xldCB0PXgoKSxyPTAsbj1bXSxvPWV8fHt9O01yKG8pO3RyeXtsZXQgZT1VcihvLmdyYXBoT3B0aW1pemF0aW9uTGV2ZWw/PyJhbGwiKSxhPV9yKG8uZXhlY3V0aW9uTW9kZT8/InNlcXVlbnRpYWwiKSxpPSJzdHJpbmciPT10eXBlb2Ygby5sb2dJZD9MKG8ubG9nSWQsbik6MCxzPW8ubG9nU2V2ZXJpdHlMZXZlbD8/MjtpZighTnVtYmVyLmlzSW50ZWdlcihzKXx8czwwfHxzPjQpdGhyb3cgbmV3IEVycm9yKGBsb2cgc2VydmVyaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtzfWApO2xldCBsPW8ubG9nVmVyYm9zaXR5TGV2ZWw/PzA7aWYoIU51bWJlci5pc0ludGVnZXIobCl8fGw8MHx8bD40KXRocm93IG5ldyBFcnJvcihgbG9nIHZlcmJvc2l0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7bH1gKTtsZXQgdT0ic3RyaW5nIj09dHlwZW9mIG8ub3B0aW1pemVkTW9kZWxGaWxlUGF0aD9MKG8ub3B0aW1pemVkTW9kZWxGaWxlUGF0aCxuKTowO2lmKHI9dC5fT3J0Q3JlYXRlU2Vzc2lvbk9wdGlvbnMoZSwhIW8uZW5hYmxlQ3B1TWVtQXJlbmEsISFvLmVuYWJsZU1lbVBhdHRlcm4sYSwhIW8uZW5hYmxlUHJvZmlsaW5nLDAsaSxzLGwsdSksMD09PXImJlMoIkNhbid0IGNyZWF0ZSBzZXNzaW9uIG9wdGlvbnMuIiksby5leGVjdXRpb25Qcm92aWRlcnMmJkRyKHIsby5leGVjdXRpb25Qcm92aWRlcnMsbiksdm9pZCAwIT09by5lbmFibGVHcmFwaENhcHR1cmUpe2lmKCJib29sZWFuIiE9dHlwZW9mIG8uZW5hYmxlR3JhcGhDYXB0dXJlKXRocm93IG5ldyBFcnJvcihgZW5hYmxlR3JhcGhDYXB0dXJlIG11c3QgYmUgYSBib29sZWFuIHZhbHVlOiAke28uZW5hYmxlR3JhcGhDYXB0dXJlfWApO2xldCBlPUwoImVuYWJsZUdyYXBoQ2FwdHVyZSIsbiksYT1MKG8uZW5hYmxlR3JhcGhDYXB0dXJlLnRvU3RyaW5nKCksbik7MCE9PXQuX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShyLGUsYSkmJlMoYENhbid0IHNldCBhIHNlc3Npb24gY29uZmlnIGVudHJ5OiAnZW5hYmxlR3JhcGhDYXB0dXJlJyAtICR7by5lbmFibGVHcmFwaENhcHR1cmV9LmApO31pZihvLmZyZWVEaW1lbnNpb25PdmVycmlkZXMpZm9yKGxldFtlLGFdb2YgT2JqZWN0LmVudHJpZXMoby5mcmVlRGltZW5zaW9uT3ZlcnJpZGVzKSl7aWYoInN0cmluZyIhPXR5cGVvZiBlKXRocm93IG5ldyBFcnJvcihgZnJlZSBkaW1lbnNpb24gb3ZlcnJpZGUgbmFtZSBtdXN0IGJlIGEgc3RyaW5nOiAke2V9YCk7aWYoIm51bWJlciIhPXR5cGVvZiBhfHwhTnVtYmVyLmlzSW50ZWdlcihhKXx8YTwwKXRocm93IG5ldyBFcnJvcihgZnJlZSBkaW1lbnNpb24gb3ZlcnJpZGUgdmFsdWUgbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyOiAke2F9YCk7bGV0IG89TChlLG4pOzAhPT10Ll9PcnRBZGRGcmVlRGltZW5zaW9uT3ZlcnJpZGUocixvLGEpJiZTKGBDYW4ndCBzZXQgYSBmcmVlIGRpbWVuc2lvbiBvdmVycmlkZTogJHtlfSAtICR7YX0uYCk7fXJldHVybiB2b2lkIDAhPT1vLmV4dHJhJiZmZShvLmV4dHJhLCIiLG5ldyBXZWFrU2V0LCgoZSxvKT0+e2xldCBhPUwoZSxuKSxpPUwobyxuKTswIT09dC5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5KHIsYSxpKSYmUyhgQ2FuJ3Qgc2V0IGEgc2Vzc2lvbiBjb25maWcgZW50cnk6ICR7ZX0gLSAke299LmApO30pKSxbcixuXX1jYXRjaChlKXt0aHJvdyAwIT09ciYmMCE9PXQuX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucyhyKSYmUygiQ2FuJ3QgcmVsZWFzZSBzZXNzaW9uIG9wdGlvbnMuIiksbi5mb3JFYWNoKChlPT50Ll9mcmVlKGUpKSksZX19O30pKSxRZT1UKCgoKT0+e2VlPWU9Pntzd2l0Y2goZSl7Y2FzZSJpbnQ4IjpyZXR1cm4gMztjYXNlInVpbnQ4IjpyZXR1cm4gMjtjYXNlImJvb2wiOnJldHVybiA5O2Nhc2UiaW50MTYiOnJldHVybiA1O2Nhc2UidWludDE2IjpyZXR1cm4gNDtjYXNlImludDMyIjpyZXR1cm4gNjtjYXNlInVpbnQzMiI6cmV0dXJuIDEyO2Nhc2UiZmxvYXQxNiI6cmV0dXJuIDEwO2Nhc2UiZmxvYXQzMiI6cmV0dXJuIDE7Y2FzZSJmbG9hdDY0IjpyZXR1cm4gMTE7Y2FzZSJzdHJpbmciOnJldHVybiA4O2Nhc2UiaW50NjQiOnJldHVybiA3O2Nhc2UidWludDY0IjpyZXR1cm4gMTM7Y2FzZSJpbnQ0IjpyZXR1cm4gMjI7Y2FzZSJ1aW50NCI6cmV0dXJuIDIxO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZX1gKX19LFF0PWU9Pntzd2l0Y2goZSl7Y2FzZSAzOnJldHVybiAiaW50OCI7Y2FzZSAyOnJldHVybiAidWludDgiO2Nhc2UgOTpyZXR1cm4gImJvb2wiO2Nhc2UgNTpyZXR1cm4gImludDE2IjtjYXNlIDQ6cmV0dXJuICJ1aW50MTYiO2Nhc2UgNjpyZXR1cm4gImludDMyIjtjYXNlIDEyOnJldHVybiAidWludDMyIjtjYXNlIDEwOnJldHVybiAiZmxvYXQxNiI7Y2FzZSAxOnJldHVybiAiZmxvYXQzMiI7Y2FzZSAxMTpyZXR1cm4gImZsb2F0NjQiO2Nhc2UgODpyZXR1cm4gInN0cmluZyI7Y2FzZSA3OnJldHVybiAiaW50NjQiO2Nhc2UgMTM6cmV0dXJuICJ1aW50NjQiO2Nhc2UgMjI6cmV0dXJuICJpbnQ0IjtjYXNlIDIxOnJldHVybiAidWludDQiO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZX1gKX19LHRlPShlLHQpPT57bGV0IHI9Wy0xLDQsMSwxLDIsMiw0LDgsLTEsMSwyLDgsNCw4LC0xLC0xLC0xLC0xLC0xLC0xLC0xLC41LC41XVtlXSxuPSJudW1iZXIiPT10eXBlb2YgdD90OnQucmVkdWNlKCgoZSx0KT0+ZSp0KSwxKTtyZXR1cm4gcj4wP01hdGguY2VpbChuKnIpOnZvaWQgMH0sZXI9ZT0+e3N3aXRjaChlKXtjYXNlImZsb2F0MTYiOnJldHVybiB0eXBlb2YgRmxvYXQxNkFycmF5PCJ1IiYmRmxvYXQxNkFycmF5LmZyb20/RmxvYXQxNkFycmF5OlVpbnQxNkFycmF5O2Nhc2UiZmxvYXQzMiI6cmV0dXJuIEZsb2F0MzJBcnJheTtjYXNlInVpbnQ4IjpjYXNlImJvb2wiOnJldHVybiBVaW50OEFycmF5O2Nhc2UiaW50OCI6cmV0dXJuIEludDhBcnJheTtjYXNlInVpbnQxNiI6cmV0dXJuIFVpbnQxNkFycmF5O2Nhc2UiaW50MTYiOnJldHVybiBJbnQxNkFycmF5O2Nhc2UiaW50MzIiOnJldHVybiBJbnQzMkFycmF5O2Nhc2UiZmxvYXQ2NCI6cmV0dXJuIEZsb2F0NjRBcnJheTtjYXNlInVpbnQzMiI6cmV0dXJuIFVpbnQzMkFycmF5O2Nhc2UiaW50NjQiOnJldHVybiBCaWdJbnQ2NEFycmF5O2Nhc2UidWludDY0IjpyZXR1cm4gQmlnVWludDY0QXJyYXk7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGU6ICR7ZX1gKX19LHRyPWU9Pntzd2l0Y2goZSl7Y2FzZSJ2ZXJib3NlIjpyZXR1cm4gMDtjYXNlImluZm8iOnJldHVybiAxO2Nhc2Uid2FybmluZyI6cmV0dXJuIDI7Y2FzZSJlcnJvciI6cmV0dXJuIDM7Y2FzZSJmYXRhbCI6cmV0dXJuIDQ7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGxvZ2dpbmcgbGV2ZWw6ICR7ZX1gKX19LENlPWU9PiJmbG9hdDMyIj09PWV8fCJmbG9hdDE2Ij09PWV8fCJpbnQzMiI9PT1lfHwiaW50NjQiPT09ZXx8InVpbnQzMiI9PT1lfHwidWludDgiPT09ZXx8ImJvb2wiPT09ZXx8InVpbnQ0Ij09PWV8fCJpbnQ0Ij09PWUsVWU9ZT0+ImZsb2F0MzIiPT09ZXx8ImZsb2F0MTYiPT09ZXx8ImludDMyIj09PWV8fCJpbnQ2NCI9PT1lfHwidWludDMyIj09PWV8fCJ1aW50NjQiPT09ZXx8ImludDgiPT09ZXx8InVpbnQ4Ij09PWV8fCJib29sIj09PWV8fCJ1aW50NCI9PT1lfHwiaW50NCI9PT1lLHJyPWU9Pntzd2l0Y2goZSl7Y2FzZSJub25lIjpyZXR1cm4gMDtjYXNlImNwdSI6cmV0dXJuIDE7Y2FzZSJjcHUtcGlubmVkIjpyZXR1cm4gMjtjYXNlInRleHR1cmUiOnJldHVybiAzO2Nhc2UiZ3B1LWJ1ZmZlciI6cmV0dXJuIDQ7Y2FzZSJtbC10ZW5zb3IiOnJldHVybiA1O2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIGxvY2F0aW9uOiAke2V9YCl9fTt9KSksZXQ9VCgoKCk9PntiZSgpLGNlPWFzeW5jIGU9PntpZigic3RyaW5nIj09dHlwZW9mIGUpe3tsZXQgdD1hd2FpdCBmZXRjaChlKTtpZighdC5vayl0aHJvdyBuZXcgRXJyb3IoYGZhaWxlZCB0byBsb2FkIGV4dGVybmFsIGRhdGEgZmlsZTogJHtlfWApO2xldCByPXQuaGVhZGVycy5nZXQoIkNvbnRlbnQtTGVuZ3RoIiksbj1yP3BhcnNlSW50KHIsMTApOjA7aWYobjwxMDczNzQxODI0KXJldHVybiBuZXcgVWludDhBcnJheShhd2FpdCB0LmFycmF5QnVmZmVyKCkpO3tpZighdC5ib2R5KXRocm93IG5ldyBFcnJvcihgZmFpbGVkIHRvIGxvYWQgZXh0ZXJuYWwgZGF0YSBmaWxlOiAke2V9LCBubyByZXNwb25zZSBib2R5LmApO2xldCByLG89dC5ib2R5LmdldFJlYWRlcigpO3RyeXtyPW5ldyBBcnJheUJ1ZmZlcihuKTt9Y2F0Y2goZSl7aWYoIShlIGluc3RhbmNlb2YgUmFuZ2VFcnJvcikpdGhyb3cgZTt7bGV0IGU9TWF0aC5jZWlsKG4vNjU1MzYpO3I9bmV3IFdlYkFzc2VtYmx5Lk1lbW9yeSh7aW5pdGlhbDplLG1heGltdW06ZX0pLmJ1ZmZlcjt9fWxldCBhPTA7Zm9yKDs7KXtsZXR7ZG9uZTplLHZhbHVlOnR9PWF3YWl0IG8ucmVhZCgpO2lmKGUpYnJlYWs7bGV0IG49dC5ieXRlTGVuZ3RoO25ldyBVaW50OEFycmF5KHIsYSxuKS5zZXQodCksYSs9bjt9cmV0dXJuIG5ldyBVaW50OEFycmF5KHIsMCxuKX19fXJldHVybiBlIGluc3RhbmNlb2YgQmxvYj9uZXcgVWludDhBcnJheShhd2FpdCBlLmFycmF5QnVmZmVyKCkpOmUgaW5zdGFuY2VvZiBVaW50OEFycmF5P2U6bmV3IFVpbnQ4QXJyYXkoZSl9O30pKSxKZT1UKCgoKT0+e1h0KCksS3QoKSxRZSgpLEooKSxCZSgpLGV0KCksUnI9KGUsdCk9PnswIT09eCgpLl9PcnRJbml0KGUsdCkmJlMoIkNhbid0IGluaXRpYWxpemUgb25ueHJ1bnRpbWUuIik7fSxUZT1hc3luYyBlPT57UnIoZS53YXNtLm51bVRocmVhZHMsdHIoZS5sb2dMZXZlbCkpO30sU2U9YXN5bmMoZSx0KT0+e30scmU9bmV3IE1hcCxGcj1lPT57bGV0IHQ9eCgpLHI9dC5zdGFja1NhdmUoKTt0cnl7bGV0IHI9dC5QVFJfU0laRSxuPXQuc3RhY2tBbGxvYygyKnIpOzAhPT10Ll9PcnRHZXRJbnB1dE91dHB1dENvdW50KGUsbixuK3IpJiZTKCJDYW4ndCBnZXQgc2Vzc2lvbiBpbnB1dC9vdXRwdXQgY291bnQuIik7bGV0IG89ND09PXI/ImkzMiI6Imk2NCI7cmV0dXJuIFtOdW1iZXIodC5nZXRWYWx1ZShuLG8pKSxOdW1iZXIodC5nZXRWYWx1ZShuK3IsbykpXX1maW5hbGx5e3Quc3RhY2tSZXN0b3JlKHIpO319LHVlPWU9PntsZXQgdD14KCkscj10Ll9tYWxsb2MoZS5ieXRlTGVuZ3RoKTtpZigwPT09cil0aHJvdyBuZXcgRXJyb3IoYENhbid0IGNyZWF0ZSBhIHNlc3Npb24uIGZhaWxlZCB0byBhbGxvY2F0ZSBhIGJ1ZmZlciBvZiBzaXplICR7ZS5ieXRlTGVuZ3RofS5gKTtyZXR1cm4gdC5IRUFQVTguc2V0KGUsciksW3IsZS5ieXRlTGVuZ3RoXX0sQWU9YXN5bmMoZSx0KT0+e2xldCByLG4sbz14KCk7QXJyYXkuaXNBcnJheShlKT9bcixuXT1lOmUuYnVmZmVyPT09by5IRUFQVTguYnVmZmVyP1tyLG5dPVtlLmJ5dGVPZmZzZXQsZS5ieXRlTGVuZ3RoXTpbcixuXT11ZShlKTtsZXQgYT0wLGk9MCxzPVtdLGw9W10sdT1bXTt0cnl7aWYoW2ksc109WnQodCksdD8uZXh0ZXJuYWxEYXRhJiZvLm1vdW50RXh0ZXJuYWxEYXRhKXtsZXQgZT1bXTtmb3IobGV0IHIgb2YgdC5leHRlcm5hbERhdGEpe2xldCB0PSJzdHJpbmciPT10eXBlb2Ygcj9yOnIucGF0aDtlLnB1c2goY2UoInN0cmluZyI9PXR5cGVvZiByP3I6ci5kYXRhKS50aGVuKChlPT57by5tb3VudEV4dGVybmFsRGF0YSh0LGUpO30pKSk7fWF3YWl0IFByb21pc2UuYWxsKGUpO31mb3IobGV0IGUgb2YgdD8uZXhlY3V0aW9uUHJvdmlkZXJzPz9bXSlpZigid2Vibm4iPT09KCJzdHJpbmciPT10eXBlb2YgZT9lOmUubmFtZSkpe2lmKG8uc2hvdWxkVHJhbnNmZXJUb01MVGVuc29yPSExLCJzdHJpbmciIT10eXBlb2YgZSl7bGV0IHQ9ZSxyPXQ/LmNvbnRleHQsbj10Py5ncHVEZXZpY2UsYT10Py5kZXZpY2VUeXBlLGk9dD8ucG93ZXJQcmVmZXJlbmNlO28uY3VycmVudENvbnRleHQ9cnx8KG4/YXdhaXQgby5qc2VwQ3JlYXRlTUxDb250ZXh0KG4pOmF3YWl0IG8uanNlcENyZWF0ZU1MQ29udGV4dCh7ZGV2aWNlVHlwZTphLHBvd2VyUHJlZmVyZW5jZTppfSkpO31lbHNlIG8uY3VycmVudENvbnRleHQ9YXdhaXQgby5qc2VwQ3JlYXRlTUxDb250ZXh0KCk7YnJlYWt9YT1hd2FpdCBvLl9PcnRDcmVhdGVTZXNzaW9uKHIsbixpKSwwPT09YSYmUygiQ2FuJ3QgY3JlYXRlIGEgc2Vzc2lvbi4iKSxvLmpzZXBPbkNyZWF0ZVNlc3Npb24/LigpLG8uY3VycmVudENvbnRleHQmJihvLmpzZXBSZWdpc3Rlck1MQ29udGV4dChhLG8uY3VycmVudENvbnRleHQpLG8uY3VycmVudENvbnRleHQ9dm9pZCAwLG8uc2hvdWxkVHJhbnNmZXJUb01MVGVuc29yPSEwKTtsZXRbZSxmXT1GcihhKSxkPSEhdD8uZW5hYmxlR3JhcGhDYXB0dXJlLHA9W10sYz1bXTtmb3IobGV0IHQ9MDt0PGU7dCsrKXtsZXQgZT1vLl9PcnRHZXRJbnB1dE5hbWUoYSx0KTswPT09ZSYmUygiQ2FuJ3QgZ2V0IGFuIGlucHV0IG5hbWUuIiksbC5wdXNoKGUpLHAucHVzaChvLlVURjhUb1N0cmluZyhlKSk7fWZvcihsZXQgZT0wO2U8ZjtlKyspe2xldCB0PW8uX09ydEdldE91dHB1dE5hbWUoYSxlKTswPT09dCYmUygiQ2FuJ3QgZ2V0IGFuIG91dHB1dCBuYW1lLiIpLHUucHVzaCh0KTtsZXQgcj1vLlVURjhUb1N0cmluZyh0KTtjLnB1c2gocik7fXJldHVybiByZS5zZXQoYSxbYSxsLHUsbnVsbCxkLCExXSksW2EscCxjXX1jYXRjaChlKXt0aHJvdyBsLmZvckVhY2goKGU9Pm8uX09ydEZyZWUoZSkpKSx1LmZvckVhY2goKGU9Pm8uX09ydEZyZWUoZSkpKSwwIT09YSYmMCE9PW8uX09ydFJlbGVhc2VTZXNzaW9uKGEpJiZTKCJDYW4ndCByZWxlYXNlIHNlc3Npb24uIiksZX1maW5hbGx5e28uX2ZyZWUociksMCE9PWkmJjAhPT1vLl9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnMoaSkmJlMoIkNhbid0IHJlbGVhc2Ugc2Vzc2lvbiBvcHRpb25zLiIpLHMuZm9yRWFjaCgoZT0+by5fZnJlZShlKSkpLG8udW5tb3VudEV4dGVybmFsRGF0YT8uKCk7fX0sT2U9ZT0+e2xldCB0PXgoKSxyPXJlLmdldChlKTtpZighcil0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCByZWxlYXNlIHNlc3Npb24uIGludmFsaWQgc2Vzc2lvbiBpZDogJHtlfWApO2xldFtuLG8sYSxpLHNdPXI7aSYmKHMmJjAhPT10Ll9PcnRDbGVhckJvdW5kT3V0cHV0cyhpLmhhbmRsZSkmJlMoIkNhbid0IGNsZWFyIGJvdW5kIG91dHB1dHMuIiksMCE9PXQuX09ydFJlbGVhc2VCaW5kaW5nKGkuaGFuZGxlKSYmUygiQ2FuJ3QgcmVsZWFzZSBJTyBiaW5kaW5nLiIpKSx0LmpzZXBPblJlbGVhc2VTZXNzaW9uPy4oZSksby5mb3JFYWNoKChlPT50Ll9PcnRGcmVlKGUpKSksYS5mb3JFYWNoKChlPT50Ll9PcnRGcmVlKGUpKSksMCE9PXQuX09ydFJlbGVhc2VTZXNzaW9uKG4pJiZTKCJDYW4ndCByZWxlYXNlIHNlc3Npb24uIikscmUuZGVsZXRlKGUpO30sbnI9YXN5bmMoZSx0LHIsbixvLGE9ITEpPT57aWYoIWUpcmV0dXJuIHZvaWQgdC5wdXNoKDApO2xldCBpLHMsbD14KCksdT1sLlBUUl9TSVpFLGY9ZVswXSxkPWVbMV0scD1lWzNdLGM9cDtpZigic3RyaW5nIj09PWYmJigiZ3B1LWJ1ZmZlciI9PT1wfHwibWwtdGVuc29yIj09PXApKXRocm93IG5ldyBFcnJvcigiU3RyaW5nIHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkIG9uIEdQVS4iKTtpZihhJiYiZ3B1LWJ1ZmZlciIhPT1wKXRocm93IG5ldyBFcnJvcihgRXh0ZXJuYWwgYnVmZmVyIG11c3QgYmUgcHJvdmlkZWQgZm9yIGlucHV0L291dHB1dCBpbmRleCAke299IHdoZW4gZW5hYmxlR3JhcGhDYXB0dXJlIGlzIHRydWUuYCk7aWYoImdwdS1idWZmZXIiPT09cCl7bGV0IHQ9ZVsyXS5ncHVCdWZmZXI7cz10ZShlZShmKSxkKTtsZXQgcj1sLmpzZXBSZWdpc3RlckJ1ZmZlcjtpZighcil0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiAiZ3B1LWJ1ZmZlciIgaXMgbm90IHN1cHBvcnRlZCB3aXRob3V0IHVzaW5nIFdlYkdQVS4nKTtpPXIobixvLHQscyk7fWVsc2UgaWYoIm1sLXRlbnNvciI9PT1wKXtsZXQgdD1lWzJdLm1sVGVuc29yO3M9dGUoZWUoZiksZCk7bGV0IHI9bC5qc2VwUmVnaXN0ZXJNTFRlbnNvcjtpZighcil0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiAibWwtdGVuc29yIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViTk4uJyk7aT1yKG4sdCxlZShmKSxkKTt9ZWxzZSB7bGV0IHQ9ZVsyXTtpZihBcnJheS5pc0FycmF5KHQpKXtzPXUqdC5sZW5ndGgsaT1sLl9tYWxsb2Mocyksci5wdXNoKGkpO2ZvcihsZXQgZT0wO2U8dC5sZW5ndGg7ZSsrKXtpZigic3RyaW5nIiE9dHlwZW9mIHRbZV0pdGhyb3cgbmV3IFR5cGVFcnJvcihgdGVuc29yIGRhdGEgYXQgaW5kZXggJHtlfSBpcyBub3QgYSBzdHJpbmdgKTtsLnNldFZhbHVlKGkrZSp1LEwodFtlXSxyKSwiKiIpO319ZWxzZSB7bGV0IGU9bC5qc2VwSXNHcmFwaElucHV0O2lmKCJzdHJpbmciIT09ZiYmZSl7bGV0IGE9bC5fT3J0R2V0SW5wdXROYW1lKG4sbyk7aWYoZShuLGwuVVRGOFRvU3RyaW5nKGEpKSl7bGV0IGU9ZWUoZik7cz10ZShlLGQpLGM9Im1sLXRlbnNvciI7bGV0IHI9bC5qc2VwQ3JlYXRlVGVtcG9yYXJ5VGVuc29yLG89bC5qc2VwVXBsb2FkVGVuc29yO2lmKCFyfHwhbyl0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiAibWwtdGVuc29yIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViTk4uJyk7bGV0IGE9YXdhaXQgcihuLGUsZCk7byhhLG5ldyBVaW50OEFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0LmJ5dGVMZW5ndGgpKSxpPWE7fWVsc2Ugcz10LmJ5dGVMZW5ndGgsaT1sLl9tYWxsb2Mocyksci5wdXNoKGkpLGwuSEVBUFU4LnNldChuZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQscyksaSk7fWVsc2Ugcz10LmJ5dGVMZW5ndGgsaT1sLl9tYWxsb2Mocyksci5wdXNoKGkpLGwuSEVBUFU4LnNldChuZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQscyksaSk7fX1sZXQgaD1sLnN0YWNrU2F2ZSgpLHc9bC5zdGFja0FsbG9jKDQqZC5sZW5ndGgpO3RyeXtkLmZvckVhY2goKChlLHQpPT5sLnNldFZhbHVlKHcrdCp1LGUsND09PXU/ImkzMiI6Imk2NCIpKSk7bGV0IGU9bC5fT3J0Q3JlYXRlVGVuc29yKGVlKGYpLGkscyx3LGQubGVuZ3RoLHJyKGMpKTswPT09ZSYmUyhgQ2FuJ3QgY3JlYXRlIHRlbnNvciBmb3IgaW5wdXQvb3V0cHV0LiBzZXNzaW9uPSR7bn0sIGluZGV4PSR7b30uYCksdC5wdXNoKGUpO31maW5hbGx5e2wuc3RhY2tSZXN0b3JlKGgpO319LHhlPWFzeW5jKGUsdCxyLG4sbyxhKT0+e2xldCBpPXgoKSxzPWkuUFRSX1NJWkUsbD1yZS5nZXQoZSk7aWYoIWwpdGhyb3cgbmV3IEVycm9yKGBjYW5ub3QgcnVuIGluZmVyZW5jZS4gaW52YWxpZCBzZXNzaW9uIGlkOiAke2V9YCk7bGV0IHU9bFswXSxmPWxbMV0sZD1sWzJdLHA9bFszXSxjPWxbNF0saD0obFs1XSx0Lmxlbmd0aCksdz1uLmxlbmd0aCx5PTAsbT1bXSxnPVtdLGI9W10sdj1bXSxFPWkuc3RhY2tTYXZlKCksVD1pLnN0YWNrQWxsb2MoaCpzKSxBPWkuc3RhY2tBbGxvYyhoKnMpLEw9aS5zdGFja0FsbG9jKHcqcyksQz1pLnN0YWNrQWxsb2ModypzKTt0cnl7W3ksbV09SnQoYSk7Zm9yKGxldCBuPTA7bjxoO24rKylhd2FpdCBucihyW25dLGcsdixlLHRbbl0sYyk7Zm9yKGxldCB0PTA7dDx3O3QrKylhd2FpdCBucihvW3RdLGIsdixlLGgrblt0XSxjKTtmb3IobGV0IGU9MDtlPGg7ZSsrKWkuc2V0VmFsdWUoVCtlKnMsZ1tlXSwiKiIpLGkuc2V0VmFsdWUoQStlKnMsZlt0W2VdXSwiKiIpO2ZvcihsZXQgZT0wO2U8dztlKyspaS5zZXRWYWx1ZShMK2UqcyxiW2VdLCIqIiksaS5zZXRWYWx1ZShDK2UqcyxkW25bZV1dLCIqIik7bGV0IGw7aS5qc2VwT25SdW5TdGFydD8uKHUpLGw9YXdhaXQgaS5fT3J0UnVuKHUsQSxULGgsQyx3LEwseSksMCE9PWwmJlMoImZhaWxlZCB0byBjYWxsIE9ydFJ1bigpLiIpO2xldCBFPVtdO2ZvcihsZXQgdD0wO3Q8dzt0Kyspe2xldCByPU51bWJlcihpLmdldFZhbHVlKEwrdCpzLCIqIikpO2lmKHI9PT1iW3RdKXtFLnB1c2gob1t0XSk7Y29udGludWV9bGV0IGEsbD1pLnN0YWNrU2F2ZSgpLGY9aS5zdGFja0FsbG9jKDQqcyksZD0hMSxjPTA7dHJ5ezAhPT1pLl9PcnRHZXRUZW5zb3JEYXRhKHIsZixmK3MsZisyKnMsZiszKnMpJiZTKGBDYW4ndCBhY2Nlc3Mgb3V0cHV0IHRlbnNvciBkYXRhIG9uIGluZGV4ICR7dH0uYCk7bGV0IG89ND09PXM/ImkzMiI6Imk2NCIsbD1OdW1iZXIoaS5nZXRWYWx1ZShmLG8pKTtjPWkuZ2V0VmFsdWUoZitzLCIqIik7bGV0IHU9aS5nZXRWYWx1ZShmKzIqcywiKiIpLGg9TnVtYmVyKGkuZ2V0VmFsdWUoZiszKnMsbykpLHc9W107Zm9yKGxldCBlPTA7ZTxoO2UrKyl3LnB1c2goTnVtYmVyKGkuZ2V0VmFsdWUodStlKnMsbykpKTswIT09aS5fT3J0RnJlZSh1KSYmUygiQ2FuJ3QgZnJlZSBtZW1vcnkgZm9yIHRlbnNvciBkaW1zLiIpO2xldCB5PXcucmVkdWNlKCgoZSx0KT0+ZSp0KSwxKTthPVF0KGwpO2xldCBtPXA/Lm91dHB1dFByZWZlcnJlZExvY2F0aW9uc1tuW3RdXTtpZigic3RyaW5nIj09PWEpe2lmKCJncHUtYnVmZmVyIj09PW18fCJtbC10ZW5zb3IiPT09bSl0aHJvdyBuZXcgRXJyb3IoIlN0cmluZyB0ZW5zb3IgaXMgbm90IHN1cHBvcnRlZCBvbiBHUFUuIik7bGV0IGU9W107Zm9yKGxldCB0PTA7dDx5O3QrKyl7bGV0IHI9aS5nZXRWYWx1ZShjK3QqcywiKiIpLG49aS5nZXRWYWx1ZShjKyh0KzEpKnMsIioiKSxvPXQ9PT15LTE/dm9pZCAwOm4tcjtlLnB1c2goaS5VVEY4VG9TdHJpbmcocixvKSk7fUUucHVzaChbYSx3LGUsImNwdSJdKTt9ZWxzZSBpZigiZ3B1LWJ1ZmZlciI9PT1tJiZ5PjApe2xldCBlPWkuanNlcEdldEJ1ZmZlcjtpZighZSl0aHJvdyBuZXcgRXJyb3IoJ3ByZWZlcnJlZExvY2F0aW9uICJncHUtYnVmZmVyIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViR1BVLicpO2xldCB0PWUoYyksbj10ZShsLHkpO2lmKHZvaWQgMD09PW58fCFDZShhKSl0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGRhdGEgdHlwZTogJHthfWApO2Q9ITAsRS5wdXNoKFthLHcse2dwdUJ1ZmZlcjp0LGRvd25sb2FkOmkuanNlcENyZWF0ZURvd25sb2FkZXIodCxuLGEpLGRpc3Bvc2U6KCk9PnswIT09aS5fT3J0UmVsZWFzZVRlbnNvcihyKSYmUygiQ2FuJ3QgcmVsZWFzZSB0ZW5zb3IuIik7fX0sImdwdS1idWZmZXIiXSk7fWVsc2UgaWYoIm1sLXRlbnNvciI9PT1tJiZ5PjApe2xldCB0PWkuanNlcEVuc3VyZVRlbnNvcjtpZighdCl0aHJvdyBuZXcgRXJyb3IoJ3ByZWZlcnJlZExvY2F0aW9uICJtbC10ZW5zb3IiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJOTi4nKTtpZih2b2lkIDA9PT10ZShsLHkpfHwhVWUoYSkpdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7YX1gKTtsZXQgbj1hd2FpdCB0KGUsYyxsLHcsITEpO2Q9ITAsRS5wdXNoKFthLHcse21sVGVuc29yOm4sZG93bmxvYWQ6aS5qc2VwQ3JlYXRlTUxUZW5zb3JEb3dubG9hZGVyKGMsYSksZGlzcG9zZTooKT0+e2kuanNlcFJlbGVhc2VUZW5zb3JJZChjKSxpLl9PcnRSZWxlYXNlVGVuc29yKHIpO319LCJtbC10ZW5zb3IiXSk7fWVsc2Uge2xldCBlPW5ldyhlcihhKSkoeSk7bmV3IFVpbnQ4QXJyYXkoZS5idWZmZXIsZS5ieXRlT2Zmc2V0LGUuYnl0ZUxlbmd0aCkuc2V0KGkuSEVBUFU4LnN1YmFycmF5KGMsYytlLmJ5dGVMZW5ndGgpKSxFLnB1c2goW2EsdyxlLCJjcHUiXSk7fX1maW5hbGx5e2kuc3RhY2tSZXN0b3JlKGwpLCJzdHJpbmciPT09YSYmYyYmaS5fZnJlZShjKSxkfHxpLl9PcnRSZWxlYXNlVGVuc29yKHIpLGkuanNlcE9uUnVuRW5kPy4odSk7fX1yZXR1cm4gcCYmIWMmJigwIT09aS5fT3J0Q2xlYXJCb3VuZE91dHB1dHMocC5oYW5kbGUpJiZTKCJDYW4ndCBjbGVhciBib3VuZCBvdXRwdXRzLiIpLHJlLnNldChlLFt1LGYsZCxwLGMsITFdKSksRX1maW5hbGx5e2kuc3RhY2tSZXN0b3JlKEUpLGcuZm9yRWFjaCgoZT0+aS5fT3J0UmVsZWFzZVRlbnNvcihlKSkpLGIuZm9yRWFjaCgoZT0+aS5fT3J0UmVsZWFzZVRlbnNvcihlKSkpLHYuZm9yRWFjaCgoZT0+aS5fZnJlZShlKSkpLDAhPT15JiZpLl9PcnRSZWxlYXNlUnVuT3B0aW9ucyh5KSxtLmZvckVhY2goKGU9PmkuX2ZyZWUoZSkpKTt9fSxMZT1lPT57bGV0IHQ9eCgpLHI9cmUuZ2V0KGUpO2lmKCFyKXRocm93IG5ldyBFcnJvcigiaW52YWxpZCBzZXNzaW9uIGlkIik7bGV0IG49clswXSxvPXQuX09ydEVuZFByb2ZpbGluZyhuKTswPT09byYmUygiQ2FuJ3QgZ2V0IGFuIHByb2ZpbGUgZmlsZSBuYW1lLiIpLHQuX09ydEZyZWUobyk7fSxJZT1lPT57bGV0IHQ9W107Zm9yKGxldCByIG9mIGUpe2xldCBlPXJbMl07IUFycmF5LmlzQXJyYXkoZSkmJiJidWZmZXIiaW4gZSYmdC5wdXNoKGUuYnVmZmVyKTt9cmV0dXJuIHR9O30pKSxudD1UKCgoKT0+e3EoKSxKZSgpLEooKSxnZSgpLFo9KCk9PiEhQS53YXNtLnByb3h5JiZ0eXBlb2YgZG9jdW1lbnQ8InUiLGxlPSExLE1lPSExLERlPSExLHJ0PW5ldyBNYXAsbmU9KGUsdCk9PntsZXQgcj1ydC5nZXQoZSk7cj9yLnB1c2godCk6cnQuc2V0KGUsW3RdKTt9LG9lPSgpPT57aWYobGV8fCFNZXx8RGV8fCFEKXRocm93IG5ldyBFcnJvcigid29ya2VyIG5vdCByZWFkeSIpfSxOcj1lPT57c3dpdGNoKGUuZGF0YS50eXBlKXtjYXNlImluaXQtd2FzbSI6bGU9ITEsZS5kYXRhLmVycj8oRGU9ITAsdHRbMV0oZS5kYXRhLmVycikpOihNZT0hMCx0dFswXSgpKSxfZSYmKFVSTC5yZXZva2VPYmplY3RVUkwoX2UpLF9lPXZvaWQgMCk7YnJlYWs7Y2FzZSJpbml0LWVwIjpjYXNlImNvcHktZnJvbSI6Y2FzZSJjcmVhdGUiOmNhc2UicmVsZWFzZSI6Y2FzZSJydW4iOmNhc2UiZW5kLXByb2ZpbGluZyI6e2xldCB0PXJ0LmdldChlLmRhdGEudHlwZSk7ZS5kYXRhLmVycj90LnNoaWZ0KClbMV0oZS5kYXRhLmVycik6dC5zaGlmdCgpWzBdKGUuZGF0YS5vdXQpO2JyZWFrfX19LG9yPWFzeW5jKCk9PntpZighTWUpe2lmKGxlKXRocm93IG5ldyBFcnJvcigibXVsdGlwbGUgY2FsbHMgdG8gJ2luaXRXYXNtKCknIGRldGVjdGVkLiIpO2lmKERlKXRocm93IG5ldyBFcnJvcigicHJldmlvdXMgY2FsbCB0byAnaW5pdFdhc20oKScgZmFpbGVkLiIpO2lmKGxlPSEwLFooKSlyZXR1cm4gbmV3IFByb21pc2UoKChlLHQpPT57RD8udGVybWluYXRlKCksVnQoKS50aGVuKCgoW3Isbl0pPT57dHJ5eyhEPW4pLm9uZXJyb3I9ZT0+dChlKSxELm9ubWVzc2FnZT1Ocix0dD1bZSx0XTtsZXQgbz17dHlwZToiaW5pdC13YXNtIixpbjpBfTtpZighby5pbi53YXNtLndhc21QYXRocyYmcil7bGV0IGU9UGUoKTtlJiYoby5pbi53YXNtLndhc21QYXRocz1lKTt9RC5wb3N0TWVzc2FnZShvKSxfZT1yO31jYXRjaChlKXt0KGUpO319KSx0KTt9KSk7dHJ5e2F3YWl0IEVlKEEud2FzbSksYXdhaXQgVGUoQSksTWU9ITA7fWNhdGNoKGUpe3Rocm93IERlPSEwLGV9ZmluYWxseXtsZT0hMTt9fX0sc3I9YXN5bmMgZT0+e2lmKFooKSlyZXR1cm4gb2UoKSxuZXcgUHJvbWlzZSgoKHQscik9PntuZSgiaW5pdC1lcCIsW3Qscl0pO2xldCBuPXt0eXBlOiJpbml0LWVwIixpbjp7ZXBOYW1lOmUsZW52OkF9fTtELnBvc3RNZXNzYWdlKG4pO30pKTthd2FpdCBTZShBLGUpO30saXI9YXN5bmMgZT0+WigpPyhvZSgpLG5ldyBQcm9taXNlKCgodCxyKT0+e25lKCJjb3B5LWZyb20iLFt0LHJdKTtsZXQgbj17dHlwZToiY29weS1mcm9tIixpbjp7YnVmZmVyOmV9fTtELnBvc3RNZXNzYWdlKG4sW2UuYnVmZmVyXSk7fSkpKTp1ZShlKSxhcj1hc3luYyhlLHQpPT57aWYoWigpKXtpZih0Py5wcmVmZXJyZWRPdXRwdXRMb2NhdGlvbil0aHJvdyBuZXcgRXJyb3IoJ3Nlc3Npb24gb3B0aW9uICJwcmVmZXJyZWRPdXRwdXRMb2NhdGlvbiIgaXMgbm90IHN1cHBvcnRlZCBmb3IgcHJveHkuJyk7cmV0dXJuIG9lKCksbmV3IFByb21pc2UoKChyLG4pPT57bmUoImNyZWF0ZSIsW3Isbl0pO2xldCBvPXt0eXBlOiJjcmVhdGUiLGluOnttb2RlbDplLG9wdGlvbnM6ey4uLnR9fX0sYT1bXTtlIGluc3RhbmNlb2YgVWludDhBcnJheSYmYS5wdXNoKGUuYnVmZmVyKSxELnBvc3RNZXNzYWdlKG8sYSk7fSkpfXJldHVybiBBZShlLHQpfSx1cj1hc3luYyBlPT57aWYoWigpKXJldHVybiBvZSgpLG5ldyBQcm9taXNlKCgodCxyKT0+e25lKCJyZWxlYXNlIixbdCxyXSk7bGV0IG49e3R5cGU6InJlbGVhc2UiLGluOmV9O0QucG9zdE1lc3NhZ2Uobik7fSkpO09lKGUpO30sZnI9YXN5bmMoZSx0LHIsbixvLGEpPT57aWYoWigpKXtpZihyLnNvbWUoKGU9PiJjcHUiIT09ZVszXSkpKXRocm93IG5ldyBFcnJvcigiaW5wdXQgdGVuc29yIG9uIEdQVSBpcyBub3Qgc3VwcG9ydGVkIGZvciBwcm94eS4iKTtpZihvLnNvbWUoKGU9PmUpKSl0aHJvdyBuZXcgRXJyb3IoInByZS1hbGxvY2F0ZWQgb3V0cHV0IHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkIGZvciBwcm94eS4iKTtyZXR1cm4gb2UoKSxuZXcgUHJvbWlzZSgoKG8saSk9PntuZSgicnVuIixbbyxpXSk7bGV0IHM9cixsPXt0eXBlOiJydW4iLGluOntzZXNzaW9uSWQ6ZSxpbnB1dEluZGljZXM6dCxpbnB1dHM6cyxvdXRwdXRJbmRpY2VzOm4sb3B0aW9uczphfX07RC5wb3N0TWVzc2FnZShsLEllKHMpKTt9KSl9cmV0dXJuIHhlKGUsdCxyLG4sbyxhKX0sY3I9YXN5bmMgZT0+e2lmKFooKSlyZXR1cm4gb2UoKSxuZXcgUHJvbWlzZSgoKHQscik9PntuZSgiZW5kLXByb2ZpbGluZyIsW3Qscl0pO2xldCBuPXt0eXBlOiJlbmQtcHJvZmlsaW5nIixpbjplfTtELnBvc3RNZXNzYWdlKG4pO30pKTtMZShlKTt9O30pKSxkcj1UKCgoKT0+e3EoKSxudCgpLFFlKCksYmUoKSxldCgpLGxyPShlLHQpPT57c3dpdGNoKGUubG9jYXRpb24pe2Nhc2UiY3B1IjpyZXR1cm4gW2UudHlwZSxlLmRpbXMsZS5kYXRhLCJjcHUiXTtjYXNlImdwdS1idWZmZXIiOnJldHVybiBbZS50eXBlLGUuZGltcyx7Z3B1QnVmZmVyOmUuZ3B1QnVmZmVyfSwiZ3B1LWJ1ZmZlciJdO2Nhc2UibWwtdGVuc29yIjpyZXR1cm4gW2UudHlwZSxlLmRpbXMse21sVGVuc29yOmUubWxUZW5zb3J9LCJtbC10ZW5zb3IiXTtkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgaW52YWxpZCBkYXRhIGxvY2F0aW9uOiAke2UubG9jYXRpb259IGZvciAke3QoKX1gKX19LFdyPWU9Pntzd2l0Y2goZVszXSl7Y2FzZSJjcHUiOnJldHVybiBuZXcgUihlWzBdLGVbMl0sZVsxXSk7Y2FzZSJncHUtYnVmZmVyIjp7bGV0IHQ9ZVswXTtpZighQ2UodCkpdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIGRhdGEgdHlwZTogJHt0fSBmb3IgZGVzZXJpYWxpemluZyBHUFUgdGVuc29yYCk7bGV0e2dwdUJ1ZmZlcjpyLGRvd25sb2FkOm4sZGlzcG9zZTpvfT1lWzJdO3JldHVybiBSLmZyb21HcHVCdWZmZXIocix7ZGF0YVR5cGU6dCxkaW1zOmVbMV0sZG93bmxvYWQ6bixkaXNwb3NlOm99KX1jYXNlIm1sLXRlbnNvciI6e2xldCB0PWVbMF07aWYoIVVlKHQpKXRocm93IG5ldyBFcnJvcihgbm90IHN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7dH0gZm9yIGRlc2VyaWFsaXppbmcgTUxUZW5zb3IgdGVuc29yYCk7bGV0e21sVGVuc29yOnIsZG93bmxvYWQ6bixkaXNwb3NlOm99PWVbMl07cmV0dXJuIFIuZnJvbU1MVGVuc29yKHIse2RhdGFUeXBlOnQsZGltczplWzFdLGRvd25sb2FkOm4sZGlzcG9zZTpvfSl9ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgZGF0YSBsb2NhdGlvbjogJHtlWzNdfWApfX0sUmU9Y2xhc3N7YXN5bmMgZmV0Y2hNb2RlbEFuZENvcHlUb1dhc21NZW1vcnkoZSl7cmV0dXJuIGlyKGF3YWl0IGNlKGUpKX1hc3luYyBsb2FkTW9kZWwoZSx0KXtsZXQgcjtWKCkscj0ic3RyaW5nIj09dHlwZW9mIGU/YXdhaXQgdGhpcy5mZXRjaE1vZGVsQW5kQ29weVRvV2FzbU1lbW9yeShlKTplLFt0aGlzLnNlc3Npb25JZCx0aGlzLmlucHV0TmFtZXMsdGhpcy5vdXRwdXROYW1lc109YXdhaXQgYXIocix0KSxZKCk7fWFzeW5jIGRpc3Bvc2UoKXtyZXR1cm4gdXIodGhpcy5zZXNzaW9uSWQpfWFzeW5jIHJ1bihlLHQscil7VigpO2xldCBuPVtdLG89W107T2JqZWN0LmVudHJpZXMoZSkuZm9yRWFjaCgoZT0+e2xldCB0PWVbMF0scj1lWzFdLGE9dGhpcy5pbnB1dE5hbWVzLmluZGV4T2YodCk7aWYoLTE9PT1hKXRocm93IG5ldyBFcnJvcihgaW52YWxpZCBpbnB1dCAnJHt0fSdgKTtuLnB1c2gociksby5wdXNoKGEpO30pKTtsZXQgYT1bXSxpPVtdO09iamVjdC5lbnRyaWVzKHQpLmZvckVhY2goKGU9PntsZXQgdD1lWzBdLHI9ZVsxXSxuPXRoaXMub3V0cHV0TmFtZXMuaW5kZXhPZih0KTtpZigtMT09PW4pdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIG91dHB1dCAnJHt0fSdgKTthLnB1c2gociksaS5wdXNoKG4pO30pKTtsZXQgcz1uLm1hcCgoKGUsdCk9PmxyKGUsKCgpPT5gaW5wdXQgIiR7dGhpcy5pbnB1dE5hbWVzW29bdF1dfSJgKSkpKSxsPWEubWFwKCgoZSx0KT0+ZT9scihlLCgoKT0+YG91dHB1dCAiJHt0aGlzLm91dHB1dE5hbWVzW2lbdF1dfSJgKSk6bnVsbCkpLHU9YXdhaXQgZnIodGhpcy5zZXNzaW9uSWQsbyxzLGksbCxyKSxmPXt9O2ZvcihsZXQgZT0wO2U8dS5sZW5ndGg7ZSsrKWZbdGhpcy5vdXRwdXROYW1lc1tpW2VdXV09YVtlXT8/V3IodVtlXSk7cmV0dXJuIFkoKSxmfXN0YXJ0UHJvZmlsaW5nKCl7fWVuZFByb2ZpbGluZygpe2NyKHRoaXMuc2Vzc2lvbklkKTt9fTt9KSksbXI9e307R2UobXIse09ubnhydW50aW1lV2ViQXNzZW1ibHlCYWNrZW5kOigpPT5GZSxpbml0aWFsaXplRmxhZ3M6KCk9PnByLHdhc21CYWNrZW5kOigpPT4kcn0pO3ZhciBwcixGZSwkcixocj1UKCgoKT0+e3EoKSxudCgpLGRyKCkscHI9KCk9PntpZigoIm51bWJlciIhPXR5cGVvZiBBLndhc20uaW5pdFRpbWVvdXR8fEEud2FzbS5pbml0VGltZW91dDwwKSYmKEEud2FzbS5pbml0VGltZW91dD0wKSwhMT09PUEud2FzbS5zaW1kJiZjb25zb2xlLndhcm4oJ0RlcHJlY2F0ZWQgcHJvcGVydHkgImVudi53YXNtLnNpbWQiIGlzIHNldCB0byBmYWxzZS4gbm9uLVNJTUQgYnVpbGQgaXMgbm8gbG9uZ2VyIHByb3ZpZGVkLCBhbmQgdGhpcyBzZXR0aW5nIHdpbGwgYmUgaWdub3JlZC4nKSwiYm9vbGVhbiIhPXR5cGVvZiBBLndhc20ucHJveHkmJihBLndhc20ucHJveHk9ITEpLCJib29sZWFuIiE9dHlwZW9mIEEud2FzbS50cmFjZSYmKEEud2FzbS50cmFjZT0hMSksIm51bWJlciIhPXR5cGVvZiBBLndhc20ubnVtVGhyZWFkc3x8IU51bWJlci5pc0ludGVnZXIoQS53YXNtLm51bVRocmVhZHMpfHxBLndhc20ubnVtVGhyZWFkczw9MClpZih0eXBlb2Ygc2VsZjwidSImJiFzZWxmLmNyb3NzT3JpZ2luSXNvbGF0ZWQpQS53YXNtLm51bVRocmVhZHM9MTtlbHNlIHtsZXQgZT10eXBlb2YgbmF2aWdhdG9yPiJ1Ij8kZSgibm9kZTpvcyIpLmNwdXMoKS5sZW5ndGg6bmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3k7QS53YXNtLm51bVRocmVhZHM9TWF0aC5taW4oNCxNYXRoLmNlaWwoKGV8fDEpLzIpKTt9fSwkcj1uZXcoRmU9Y2xhc3N7YXN5bmMgaW5pdChlKXtwcigpLGF3YWl0IG9yKCksYXdhaXQgc3IoZSk7fWFzeW5jIGNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKGUsdCl7bGV0IHI9bmV3IFJlO3JldHVybiBhd2FpdCByLmxvYWRNb2RlbChlLHQpLFByb21pc2UucmVzb2x2ZShyKX19KTt9KSk7cSgpLHEoKSxxKCk7dmFyIEZ0PSIxLjIxLjAiO3tsZXQgZT0oaHIoKSxhdChtcikpLndhc21CYWNrZW5kO2llKCJjcHUiLGUsMTApLGllKCJ3YXNtIixlLDEwKTt9T2JqZWN0LmRlZmluZVByb3BlcnR5KEEudmVyc2lvbnMsIndlYiIse3ZhbHVlOkZ0LGVudW1lcmFibGU6ITB9KTsKCmNsYXNzIFdvcmtlck5hdGl2ZXtjb25zdHJ1Y3Rvcigpe3RoaXMucmVhZHk9ITE7dGhpcy5pbmRleGVkREJNYW5hZ2VyPW5ldyBJbmRleGVkREJNYW5hZ2VyKCJvbmlyaXgtc2RrIiwiZmlsZXMiKSx0aGlzLmluZGV4ZWREQk1hbmFnZXIuZ2V0RmlsZUZyb21JbmRleGVkREIoIlNES18xLjEwLjAiKS50aGVuKChhc3luYyB0PT57bGV0IGU9VVJMLmNyZWF0ZU9iamVjdFVSTChuZXcgQmxvYihbdF0se3R5cGU6InRleHQvamF2YXNjcmlwdCJ9KSk7Y29uc3R7ZGVmYXVsdDphfT1hd2FpdCBpbXBvcnQoLyogd2VicGFja0lnbm9yZTogdHJ1ZSwgd2VicGFja01vZGU6ICJsYXp5IiAqL2UpLGk9YXdhaXQgYSgpO3RoaXMubmF0aXZlU0RLPWksdGhpcy5jb2Fyc2VGcmFtZT10aGlzLm5hdGl2ZVNESy5fbWFsbG9jKDM2ODY0MDApLHRoaXMuZXh0cmFjdGlvbkZyYW1lPXRoaXMubmF0aXZlU0RLLl9tYWxsb2MoMzY4NjQwMCksdGhpcy5idWZmZXJMZW5ndGg9MCx0aGlzLmZyYW1lTGF5b3V0U3RydWN0PXRoaXMubmF0aXZlU0RLLl9tYWxsb2MoMjgpLEEud2FzbS5udW1UaHJlYWRzPTE7Y29uc3Qgcz1hd2FpdCB0aGlzLmluZGV4ZWREQk1hbmFnZXIuZ2V0RmlsZUZyb21JbmRleGVkREIoIm9ydC53YXNtIikscj1VUkwuY3JlYXRlT2JqZWN0VVJMKG5ldyBCbG9iKFtzXSx7dHlwZToiYXBwbGljYXRpb24vd2FzbSJ9KSk7QS53YXNtLndhc21QYXRocz17d2FzbTpyLG1qczoiaHR0cHM6Ly9jZG4ub25pcml4LmNvbS9vbmlyaXgtZW5naW5lLXNkay9vcnRfdjEuMjEuMF9taW4vb3J0LXdhc20tc2ltZC5tanMifTtsZXQgbj1hd2FpdCB0aGlzLmluZGV4ZWREQk1hbmFnZXIuZ2V0RnJvbUNhY2hlT3JGZXRjaCgiY29hcnNlbG9jLm9ydCIsImh0dHBzOi8vY2RuLm9uaXJpeC5jb20vb25pcml4LWVuZ2luZS1zZGsvY29hcnNlbG9jLm9ydCIpO2NvbnN0IG89YXdhaXQgT3IuY3JlYXRlKG4se2V4ZWN1dGlvblByb3ZpZGVyczpbIndhc20iXX0pO2xldCBoPWF3YWl0IHRoaXMuaW5kZXhlZERCTWFuYWdlci5nZXRGcm9tQ2FjaGVPckZldGNoKCJzcGFyc2VfZXh0cmFjdC5vcnQiLCJodHRwczovL2Nkbi5vbmlyaXguY29tL29uaXJpeC1lbmdpbmUtc2RrL3NwYXJzZV9leHRyYWN0Lm9ydCIpO2NvbnN0IGM9YXdhaXQgT3IuY3JlYXRlKGgse2V4ZWN1dGlvblByb3ZpZGVyczpbIndhc20iXX0pO3RoaXMuc2Vzc2lvbj1vLHRoaXMuc2Vzc2lvbkV4dHJhY3Rpb249Yyxhd2FpdCB0aGlzLnNlc3Npb24ucnVuKHtpbnB1dDpuZXcgUihuZXcgRmxvYXQzMkFycmF5KEFycmF5KDkyMTYwMCkuZmlsbCgwKSksWzEsMyw2NDAsNDgwXSl9KSx0aGlzLnJlYWR5PSEwLHBvc3RNZXNzYWdlKCJyZWFkeSIpO30pKTt9c3RhcnQoKXthZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwoYXN5bmMgdD0+e2lmKCF0aGlzLnJlYWR5KXJldHVybiB2b2lkIHBvc3RNZXNzYWdlKCExKTt0aGlzLnJlYWR5PSExO2NvbnN0IGU9dC5kYXRhLGE9ZS53aWR0aCplLmhlaWdodCo0OzAhPXRoaXMuYnVmZmVyTGVuZ3RoJiZ0aGlzLmJ1ZmZlckxlbmd0aD09YXx8KDAhPXRoaXMuYnVmZmVyTGVuZ3RoJiZ0aGlzLm5hdGl2ZVNESy5fZnJlZSh0aGlzLmJ1ZmZlciksdGhpcy5idWZmZXJMZW5ndGg9YSx0aGlzLmJ1ZmZlcj10aGlzLm5hdGl2ZVNESy5fbWFsbG9jKHRoaXMuYnVmZmVyTGVuZ3RoKSksdGhpcy5uYXRpdmVTREsuSEVBUFU4LnNldChlLmRhdGEsdGhpcy5idWZmZXIpLHRoaXMubmF0aXZlU0RLLkhFQVBVMzJbdGhpcy5mcmFtZUxheW91dFN0cnVjdC80KzBdPWUud2lkdGgsdGhpcy5uYXRpdmVTREsuSEVBUFUzMlt0aGlzLmZyYW1lTGF5b3V0U3RydWN0LzQrMV09ZS5oZWlnaHQsdGhpcy5uYXRpdmVTREsuSEVBUFUzMlt0aGlzLmZyYW1lTGF5b3V0U3RydWN0LzQrMl09NCplLndpZHRoLHRoaXMubmF0aXZlU0RLLkhFQVBVMzJbdGhpcy5mcmFtZUxheW91dFN0cnVjdC80KzNdPSExLHRoaXMubmF0aXZlU0RLLkhFQVBVMzJbdGhpcy5mcmFtZUxheW91dFN0cnVjdC80KzRdPWUuY29sb3JTcGFjZSx0aGlzLm5hdGl2ZVNESy5IRUFQVTMyW3RoaXMuZnJhbWVMYXlvdXRTdHJ1Y3QvNCs1XT1lLnJvdGF0ZSx0aGlzLm5hdGl2ZVNESy5IRUFQVTMyW3RoaXMuZnJhbWVMYXlvdXRTdHJ1Y3QvNCs2XT1lLmZsaXA7bGV0IGk9dGhpcy5uYXRpdmVTREsuX09YX0V4dHJhY3QodGhpcy5idWZmZXIsdGhpcy5jb2Fyc2VGcmFtZSx0aGlzLmV4dHJhY3Rpb25GcmFtZSx0aGlzLmZyYW1lTGF5b3V0U3RydWN0LGUuZHR5cGUpLHM9W107aWYoZS5vbmx5Q29hcnNlfHwyIT1lLmR0eXBlKXM9bmV3IEZsb2F0MzJBcnJheSh0aGlzLnJlYWRFeHRyYWN0aW9uRGF0YSh0aGlzLm5hdGl2ZVNESy5IRUFQRjMyLGkvNCkpO2Vsc2Uge2xldCB0PVtdO2ZvcihsZXQgZT0wO2U8OTIxNjAwO2UrKyl0LnB1c2godGhpcy5uYXRpdmVTREsuSEVBUEYzMlt0aGlzLmV4dHJhY3Rpb25GcmFtZS80K2VdKTtsZXR7a2V5cG9pbnRzOmUsZGVzY3JpcHRvcnM6YX09YXdhaXQgdGhpcy5zZXNzaW9uRXh0cmFjdGlvbi5ydW4oe2ltYWdlOm5ldyBSKG5ldyBGbG9hdDMyQXJyYXkodCksWzEsMyw0ODAsNjQwXSl9KSxpPVtlLmRpbXNbMF0sLi4uZS5kYXRhLC4uLmEuZGF0YV07cz1uZXcgRmxvYXQzMkFycmF5KGkpO31sZXQgcj1bXTtmb3IobGV0IHQ9MDt0PDkyMTYwMDt0Kyspci5wdXNoKHRoaXMubmF0aXZlU0RLLkhFQVBGMzJbdGhpcy5jb2Fyc2VGcmFtZS80K3RdKTtsZXQgbj1hd2FpdCB0aGlzLnNlc3Npb24ucnVuKHtpbnB1dDpuZXcgUihuZXcgRmxvYXQzMkFycmF5KHIpLFsxLDMsNjQwLDQ4MF0pfSk7cG9zdE1lc3NhZ2Uoe2V4dHJhY3Rpb246cyxkZXNjcmlwdG9yOm4ub3V0cHV0LmRhdGEsb25seUNvYXJzZTplLm9ubHlDb2Fyc2V9KSx0aGlzLnJlYWR5PSEwO30pKTt9cmVhZEV4dHJhY3Rpb25EYXRhKHQsZSl7bGV0IGE9ZSxpPVtdLHM9dFthXTtpLnB1c2gocyksYSsrO2ZvcihsZXQgZT0wO2U8cztlKyspaS5wdXNoKHRbYV0pLGkucHVzaCh0W2ErMV0pLGErPTI7Zm9yKGxldCBlPTA7ZTwxMjgqcztlKyspaS5wdXNoKHRbYV0pLGErKztyZXR1cm4gaX19Y29uc3Qgd29ya2VyPW5ldyBXb3JrZXJOYXRpdmU7d29ya2VyLnN0YXJ0KCk7Cg=="),b=new Blob([d],{type:"application/javascript"});this.workers[Z]=new Worker(/* webpackIgnore: true, webpackMode: "lazy" */URL.createObjectURL(b),{type:"module"}),this.callbacks[Z]=l,this.workers[Z].addEventListener("message",(l=>{this.callbacks[Z](l.data);}));}}createMatchingWorker(Z,l){if(!this.workerExists(Z)){let d=atob("Y2xhc3MgSW5kZXhlZERCTWFuYWdlcntjb25zdHJ1Y3RvcihlLHIpe3RoaXMuZGJOYW1lPWUsdGhpcy5zdG9yZU5hbWU9cjt9YXN5bmMgZ2V0RnJvbUNhY2hlT3JGZXRjaChlLHIpe2xldCB0PW51bGw7dHJ5e3Q9YXdhaXQgdGhpcy5nZXRGaWxlRnJvbUluZGV4ZWREQihlKTt9Y2F0Y2goZSl7Y29uc29sZS5sb2coIkFuIGVycm9yIG9jY3VycmVkIHdoaWxlIHRyeWluZyB0byBnZXQgZWxlbWVudCBmcm9tIGluZGV4ZWREQi4iKTt9cmV0dXJuIHR8fCh0PWF3YWl0IHRoaXMuZmV0Y2hBbmRDYWNoZUZpbGUocixlKSksbmV3IFVpbnQ4QXJyYXkodCl9YXN5bmMgZ2V0RmlsZUZyb21JbmRleGVkREIoZSl7cmV0dXJuIG5ldyBQcm9taXNlKCgocix0KT0+e2NvbnN0IG89aW5kZXhlZERCLm9wZW4odGhpcy5kYk5hbWUpO28ub25lcnJvcj0oKT0+dChvLmVycm9yKSxvLm9uc3VjY2Vzcz0oKT0+e2NvbnN0IHM9by5yZXN1bHQudHJhbnNhY3Rpb24odGhpcy5zdG9yZU5hbWUsInJlYWRvbmx5Iikub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpLmdldChlKTtzLm9uc3VjY2Vzcz0oKT0+cihzLnJlc3VsdCkscy5vbmVycm9yPSgpPT50KHMuZXJyb3IpO30sby5vbnVwZ3JhZGVuZWVkZWQ9ZT0+e2UudGFyZ2V0LnJlc3VsdC5jcmVhdGVPYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7fTt9KSl9YXN5bmMgc2F2ZUZpbGVUb0luZGV4ZWREQihlLHIpe3JldHVybiBuZXcgUHJvbWlzZSgoKHQsbyk9Pntjb25zdCBzPWluZGV4ZWREQi5vcGVuKHRoaXMuZGJOYW1lKTtzLm9uZXJyb3I9KCk9Pm8ocy5lcnJvcikscy5vbnVwZ3JhZGVuZWVkZWQ9ZT0+e2UudGFyZ2V0LnJlc3VsdC5jcmVhdGVPYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7fSxzLm9uc3VjY2Vzcz0oKT0+e3RyeXtjb25zdCBuPXMucmVzdWx0LnRyYW5zYWN0aW9uKHRoaXMuc3RvcmVOYW1lLCJyZWFkd3JpdGUiKSxhPW4ub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpLnB1dChyLGUpO2Eub25zdWNjZXNzPSgpPT50KGEucmVzdWx0KSxhLm9uZXJyb3I9KCk9Pm8oYS5lcnJvcik7fWNhdGNoKGUpe28oZSk7fX07fSkpfWFzeW5jIGZldGNoQW5kQ2FjaGVGaWxlKGUscil7Y29uc3QgdD1hd2FpdCBmZXRjaChlKSxvPWF3YWl0IHQuYXJyYXlCdWZmZXIoKTtyZXR1cm4gYXdhaXQgdGhpcy5zYXZlRmlsZVRvSW5kZXhlZERCKHIsbyksb319Cgp2YXIgaGUsaixpZSxBcix1dCxjdCxkdCxfLEEsbXQsaHQsSGUseXQsYnQsZ3QsRXQsVHQsSCxhZSxBdCxPdCxMdCxJdCx2LFIsdnQsQnQsVixZLHllLE9yLFdlPU9iamVjdC5kZWZpbmVQcm9wZXJ0eSxncj1PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLEVyPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzLFRyPU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHksJGU9KGU9PnR5cGVvZiByZXF1aXJlPCJ1Ij9yZXF1aXJlOnR5cGVvZiBQcm94eTwidSI/bmV3IFByb3h5KGUse2dldDooZSx0KT0+KHR5cGVvZiByZXF1aXJlPCJ1Ij9yZXF1aXJlOmUpW3RdfSk6ZSkoKGZ1bmN0aW9uKGUpe2lmKHR5cGVvZiByZXF1aXJlPCJ1IilyZXR1cm4gcmVxdWlyZS5hcHBseSh0aGlzLGFyZ3VtZW50cyk7dGhyb3cgRXJyb3IoJ0R5bmFtaWMgcmVxdWlyZSBvZiAiJytlKyciIGlzIG5vdCBzdXBwb3J0ZWQnKX0pKSxUPShlLHQpPT4oKT0+KGUmJih0PWUoZT0wKSksdCksR2U9KGUsdCk9Pntmb3IodmFyIHIgaW4gdClXZShlLHIse2dldDp0W3JdLGVudW1lcmFibGU6ITB9KTt9LFNyPShlLHQscixuKT0+e2lmKHQmJiJvYmplY3QiPT10eXBlb2YgdHx8ImZ1bmN0aW9uIj09dHlwZW9mIHQpZm9yKGxldCBvIG9mIEVyKHQpKSFUci5jYWxsKGUsbykmJm8hPT1yJiZXZShlLG8se2dldDooKT0+dFtvXSxlbnVtZXJhYmxlOiEobj1ncih0LG8pKXx8bi5lbnVtZXJhYmxlfSk7cmV0dXJuIGV9LGF0PWU9PlNyKFdlKHt9LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KSxlKSx6ZT1UKCgoKT0+e2hlPW5ldyBNYXAsaj1bXSxpZT0oZSx0LHIpPT57aWYoIXR8fCJmdW5jdGlvbiIhPXR5cGVvZiB0LmluaXR8fCJmdW5jdGlvbiIhPXR5cGVvZiB0LmNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKXRocm93IG5ldyBUeXBlRXJyb3IoIm5vdCBhIHZhbGlkIGJhY2tlbmQiKTt7bGV0IG49aGUuZ2V0KGUpO2lmKHZvaWQgMD09PW4paGUuc2V0KGUse2JhY2tlbmQ6dCxwcmlvcml0eTpyfSk7ZWxzZSB7aWYobi5wcmlvcml0eT5yKXJldHVybjtpZihuLnByaW9yaXR5PT09ciYmbi5iYWNrZW5kIT09dCl0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCByZWdpc3RlciBiYWNrZW5kICIke2V9IiB1c2luZyBwcmlvcml0eSAke3J9YCl9aWYocj49MCl7bGV0IHQ9ai5pbmRleE9mKGUpOy0xIT09dCYmai5zcGxpY2UodCwxKTtmb3IobGV0IHQ9MDt0PGoubGVuZ3RoO3QrKylpZihoZS5nZXQoalt0XSkucHJpb3JpdHk8PXIpcmV0dXJuIHZvaWQgai5zcGxpY2UodCwwLGUpO2oucHVzaChlKTt9fX0sQXI9YXN5bmMgZT0+e2xldCB0PWhlLmdldChlKTtpZighdClyZXR1cm4gImJhY2tlbmQgbm90IGZvdW5kLiI7aWYodC5pbml0aWFsaXplZClyZXR1cm4gdC5iYWNrZW5kO2lmKHQuYWJvcnRlZClyZXR1cm4gdC5lcnJvcjt7bGV0IHI9ISF0LmluaXRQcm9taXNlO3RyeXtyZXR1cm4gcnx8KHQuaW5pdFByb21pc2U9dC5iYWNrZW5kLmluaXQoZSkpLGF3YWl0IHQuaW5pdFByb21pc2UsdC5pbml0aWFsaXplZD0hMCx0LmJhY2tlbmR9Y2F0Y2goZSl7cmV0dXJuIHJ8fCh0LmVycm9yPWAke2V9YCx0LmFib3J0ZWQ9ITApLHQuZXJyb3J9ZmluYWxseXtkZWxldGUgdC5pbml0UHJvbWlzZTt9fX0sdXQ9YXN5bmMgZT0+e2xldCB0LHI9ZS5leGVjdXRpb25Qcm92aWRlcnN8fFtdLG49ci5tYXAoKGU9PiJzdHJpbmciPT10eXBlb2YgZT9lOmUubmFtZSkpLG89MD09PW4ubGVuZ3RoP2o6bixhPVtdLGk9bmV3IFNldDtmb3IobGV0IGUgb2Ygbyl7bGV0IHI9YXdhaXQgQXIoZSk7InN0cmluZyI9PXR5cGVvZiByP2EucHVzaCh7bmFtZTplLGVycjpyfSk6KHR8fCh0PXIpLHQ9PT1yJiZpLmFkZChlKSk7fWlmKCF0KXRocm93IG5ldyBFcnJvcihgbm8gYXZhaWxhYmxlIGJhY2tlbmQgZm91bmQuIEVSUjogJHthLm1hcCgoZT0+YFske2UubmFtZX1dICR7ZS5lcnJ9YCkpLmpvaW4oIiwgIil9YCk7Zm9yKGxldHtuYW1lOmUsZXJyOnR9b2YgYSluLmluY2x1ZGVzKGUpJiZjb25zb2xlLndhcm4oYHJlbW92aW5nIHJlcXVlc3RlZCBleGVjdXRpb24gcHJvdmlkZXIgIiR7ZX0iIGZyb20gc2Vzc2lvbiBvcHRpb25zIGJlY2F1c2UgaXQgaXMgbm90IGF2YWlsYWJsZTogJHt0fWApO2xldCBzPXIuZmlsdGVyKChlPT5pLmhhcygic3RyaW5nIj09dHlwZW9mIGU/ZTplLm5hbWUpKSk7cmV0dXJuIFt0LG5ldyBQcm94eShlLHtnZXQ6KGUsdCk9PiJleGVjdXRpb25Qcm92aWRlcnMiPT09dD9zOlJlZmxlY3QuZ2V0KGUsdCl9KV19O30pKSxmdD1UKCgoKT0+e3plKCk7fSkpLGx0PVQoKCgpPT57Y3Q9IjEuMjEuMCI7fSkpLGplPVQoKCgpPT57bHQoKSxkdD0id2FybmluZyIsXz17d2FzbTp7fSx3ZWJnbDp7fSx3ZWJncHU6e30sdmVyc2lvbnM6e2NvbW1vbjpjdH0sc2V0IGxvZ0xldmVsKGUpe2lmKHZvaWQgMCE9PWUpe2lmKCJzdHJpbmciIT10eXBlb2YgZXx8LTE9PT1bInZlcmJvc2UiLCJpbmZvIiwid2FybmluZyIsImVycm9yIiwiZmF0YWwiXS5pbmRleE9mKGUpKXRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgbG9nZ2luZyBsZXZlbDogJHtlfWApO2R0PWU7fX0sZ2V0IGxvZ0xldmVsKCl7cmV0dXJuIGR0fX0sT2JqZWN0LmRlZmluZVByb3BlcnR5KF8sImxvZ0xldmVsIix7ZW51bWVyYWJsZTohMH0pO30pKSxwdD1UKCgoKT0+e2plKCksQT1fO30pKSx3dD1UKCgoKT0+e210PShlLHQpPT57bGV0IHI9dHlwZW9mIGRvY3VtZW50PCJ1Ij9kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJjYW52YXMiKTpuZXcgT2Zmc2NyZWVuQ2FudmFzKDEsMSk7ci53aWR0aD1lLmRpbXNbM10sci5oZWlnaHQ9ZS5kaW1zWzJdO2xldCBuPXIuZ2V0Q29udGV4dCgiMmQiKTtpZihudWxsIT1uKXtsZXQgbyxhO3ZvaWQgMCE9PXQ/LnRlbnNvckxheW91dCYmIk5IV0MiPT09dC50ZW5zb3JMYXlvdXQ/KG89ZS5kaW1zWzJdLGE9ZS5kaW1zWzNdKToobz1lLmRpbXNbM10sYT1lLmRpbXNbMl0pO2xldCBpLHMsbD12b2lkIDAhPT10Py5mb3JtYXQ/dC5mb3JtYXQ6IlJHQiIsdT10Py5ub3JtO3ZvaWQgMD09PXV8fHZvaWQgMD09PXUubWVhbj9pPVsyNTUsMjU1LDI1NSwyNTVdOiJudW1iZXIiPT10eXBlb2YgdS5tZWFuP2k9W3UubWVhbix1Lm1lYW4sdS5tZWFuLHUubWVhbl06KGk9W3UubWVhblswXSx1Lm1lYW5bMV0sdS5tZWFuWzJdLDBdLHZvaWQgMCE9PXUubWVhblszXSYmKGlbM109dS5tZWFuWzNdKSksdm9pZCAwPT09dXx8dm9pZCAwPT09dS5iaWFzP3M9WzAsMCwwLDBdOiJudW1iZXIiPT10eXBlb2YgdS5iaWFzP3M9W3UuYmlhcyx1LmJpYXMsdS5iaWFzLHUuYmlhc106KHM9W3UuYmlhc1swXSx1LmJpYXNbMV0sdS5iaWFzWzJdLDBdLHZvaWQgMCE9PXUuYmlhc1szXSYmKHNbM109dS5iaWFzWzNdKSk7bGV0IGY9YSpvLGQ9MCxwPWYsYz0yKmYsaD0tMTsiUkdCQSI9PT1sPyhkPTAscD1mLGM9MipmLGg9MypmKToiUkdCIj09PWw/KGQ9MCxwPWYsYz0yKmYpOiJSQkciPT09bCYmKGQ9MCxjPWYscD0yKmYpO2ZvcihsZXQgdD0wO3Q8YTt0KyspZm9yKGxldCByPTA7cjxvO3IrKyl7bGV0IG89KGUuZGF0YVtkKytdLXNbMF0pKmlbMF0sYT0oZS5kYXRhW3ArK10tc1sxXSkqaVsxXSxsPShlLmRhdGFbYysrXS1zWzJdKSppWzJdLHU9LTE9PT1oPzI1NTooZS5kYXRhW2grK10tc1szXSkqaVszXTtuLmZpbGxTdHlsZT0icmdiYSgiK28rIiwiK2ErIiwiK2wrIiwiK3UrIikiLG4uZmlsbFJlY3Qocix0LDEsMSk7fWlmKCJ0b0RhdGFVUkwiaW4gcilyZXR1cm4gci50b0RhdGFVUkwoKTt0aHJvdyBuZXcgRXJyb3IoInRvRGF0YVVSTCBpcyBub3Qgc3VwcG9ydGVkIil9dGhyb3cgbmV3IEVycm9yKCJDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhIil9LGh0PShlLHQpPT57bGV0IHIsbj10eXBlb2YgZG9jdW1lbnQ8InUiP2RvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImNhbnZhcyIpLmdldENvbnRleHQoIjJkIik6bmV3IE9mZnNjcmVlbkNhbnZhcygxLDEpLmdldENvbnRleHQoIjJkIik7aWYobnVsbD09bil0aHJvdyBuZXcgRXJyb3IoIkNhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEiKTt7bGV0IG8sYSxpO3ZvaWQgMCE9PXQ/LnRlbnNvckxheW91dCYmIk5IV0MiPT09dC50ZW5zb3JMYXlvdXQ/KG89ZS5kaW1zWzJdLGE9ZS5kaW1zWzFdLGk9ZS5kaW1zWzNdKToobz1lLmRpbXNbM10sYT1lLmRpbXNbMl0saT1lLmRpbXNbMV0pO2xldCBzLGwsdT12b2lkIDAhPT10JiZ2b2lkIDAhPT10LmZvcm1hdD90LmZvcm1hdDoiUkdCIixmPXQ/Lm5vcm07dm9pZCAwPT09Znx8dm9pZCAwPT09Zi5tZWFuP3M9WzI1NSwyNTUsMjU1LDI1NV06Im51bWJlciI9PXR5cGVvZiBmLm1lYW4/cz1bZi5tZWFuLGYubWVhbixmLm1lYW4sZi5tZWFuXToocz1bZi5tZWFuWzBdLGYubWVhblsxXSxmLm1lYW5bMl0sMjU1XSx2b2lkIDAhPT1mLm1lYW5bM10mJihzWzNdPWYubWVhblszXSkpLHZvaWQgMD09PWZ8fHZvaWQgMD09PWYuYmlhcz9sPVswLDAsMCwwXToibnVtYmVyIj09dHlwZW9mIGYuYmlhcz9sPVtmLmJpYXMsZi5iaWFzLGYuYmlhcyxmLmJpYXNdOihsPVtmLmJpYXNbMF0sZi5iaWFzWzFdLGYuYmlhc1syXSwwXSx2b2lkIDAhPT1mLmJpYXNbM10mJihsWzNdPWYuYmlhc1szXSkpO2xldCBkPWEqbztpZih2b2lkIDAhPT10JiYodm9pZCAwIT09dC5mb3JtYXQmJjQ9PT1pJiYiUkdCQSIhPT10LmZvcm1hdHx8Mz09PWkmJiJSR0IiIT09dC5mb3JtYXQmJiJCR1IiIT09dC5mb3JtYXQpKXRocm93IG5ldyBFcnJvcigiVGVuc29yIGZvcm1hdCBkb2Vzbid0IG1hdGNoIGlucHV0IHRlbnNvciBkaW1zIik7bGV0IHA9NCxjPTAsaD0xLHc9Mix5PTMsbT0wLGc9ZCxiPTIqZCx2PS0xOyJSR0JBIj09PXU/KG09MCxnPWQsYj0yKmQsdj0zKmQpOiJSR0IiPT09dT8obT0wLGc9ZCxiPTIqZCk6IlJCRyI9PT11JiYobT0wLGI9ZCxnPTIqZCkscj1uLmNyZWF0ZUltYWdlRGF0YShvLGEpO2ZvcihsZXQgdD0wO3Q8YSpvO2MrPXAsaCs9cCx3Kz1wLHkrPXAsdCsrKXIuZGF0YVtjXT0oZS5kYXRhW20rK10tbFswXSkqc1swXSxyLmRhdGFbaF09KGUuZGF0YVtnKytdLWxbMV0pKnNbMV0sci5kYXRhW3ddPShlLmRhdGFbYisrXS1sWzJdKSpzWzJdLHIuZGF0YVt5XT0tMT09PXY/MjU1OihlLmRhdGFbdisrXS1sWzNdKSpzWzNdO31yZXR1cm4gcn07fSkpLFN0PVQoKCgpPT57d2UoKSxIZT0oZSx0KT0+e2lmKHZvaWQgMD09PWUpdGhyb3cgbmV3IEVycm9yKCJJbWFnZSBidWZmZXIgbXVzdCBiZSBkZWZpbmVkIik7aWYodm9pZCAwPT09dC5oZWlnaHR8fHZvaWQgMD09PXQud2lkdGgpdGhyb3cgbmV3IEVycm9yKCJJbWFnZSBoZWlnaHQgYW5kIHdpZHRoIG11c3QgYmUgZGVmaW5lZCIpO2lmKCJOSFdDIj09PXQudGVuc29yTGF5b3V0KXRocm93IG5ldyBFcnJvcigiTkhXQyBUZW5zb3IgbGF5b3V0IGlzIG5vdCBzdXBwb3J0ZWQgeWV0Iik7bGV0IHIsbix7aGVpZ2h0Om8sd2lkdGg6YX09dCxpPXQubm9ybT8/e21lYW46MjU1LGJpYXM6MH07cj0ibnVtYmVyIj09dHlwZW9mIGkubWVhbj9baS5tZWFuLGkubWVhbixpLm1lYW4saS5tZWFuXTpbaS5tZWFuWzBdLGkubWVhblsxXSxpLm1lYW5bMl0saS5tZWFuWzNdPz8yNTVdLG49Im51bWJlciI9PXR5cGVvZiBpLmJpYXM/W2kuYmlhcyxpLmJpYXMsaS5iaWFzLGkuYmlhc106W2kuYmlhc1swXSxpLmJpYXNbMV0saS5iaWFzWzJdLGkuYmlhc1szXT8/MF07bGV0IHM9dm9pZCAwIT09dC5mb3JtYXQ/dC5mb3JtYXQ6IlJHQkEiLGw9dm9pZCAwIT09dC50ZW5zb3JGb3JtYXQmJnZvaWQgMCE9PXQudGVuc29yRm9ybWF0P3QudGVuc29yRm9ybWF0OiJSR0IiLHU9byphLGY9IlJHQkEiPT09bD9uZXcgRmxvYXQzMkFycmF5KDQqdSk6bmV3IEZsb2F0MzJBcnJheSgzKnUpLGQ9NCxwPTAsYz0xLGg9Mix3PTMseT0wLG09dSxnPTIqdSxiPS0xOyJSR0IiPT09cyYmKGQ9MyxwPTAsYz0xLGg9Mix3PS0xKSwiUkdCQSI9PT1sP2I9Myp1OiJSQkciPT09bD8oeT0wLGc9dSxtPTIqdSk6IkJHUiI9PT1sJiYoZz0wLG09dSx5PTIqdSk7Zm9yKGxldCB0PTA7dDx1O3QrKyxwKz1kLGgrPWQsYys9ZCx3Kz1kKWZbeSsrXT0oZVtwXStuWzBdKS9yWzBdLGZbbSsrXT0oZVtjXStuWzFdKS9yWzFdLGZbZysrXT0oZVtoXStuWzJdKS9yWzJdLC0xIT09YiYmLTEhPT13JiYoZltiKytdPShlW3ddK25bM10pL3JbM10pO3JldHVybiBuZXcgdigiZmxvYXQzMiIsZiwiUkdCQSI9PT1sP1sxLDQsbyxhXTpbMSwzLG8sYV0pfSx5dD1hc3luYyhlLHQpPT57bGV0IHIsbj10eXBlb2YgSFRNTEltYWdlRWxlbWVudDwidSImJmUgaW5zdGFuY2VvZiBIVE1MSW1hZ2VFbGVtZW50LG89dHlwZW9mIEltYWdlRGF0YTwidSImJmUgaW5zdGFuY2VvZiBJbWFnZURhdGEsYT10eXBlb2YgSW1hZ2VCaXRtYXA8InUiJiZlIGluc3RhbmNlb2YgSW1hZ2VCaXRtYXAsaT0ic3RyaW5nIj09dHlwZW9mIGUscz10Pz97fSxsPSgpPT57aWYodHlwZW9mIGRvY3VtZW50PCJ1IilyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiY2FudmFzIik7aWYodHlwZW9mIE9mZnNjcmVlbkNhbnZhczwidSIpcmV0dXJuIG5ldyBPZmZzY3JlZW5DYW52YXMoMSwxKTt0aHJvdyBuZXcgRXJyb3IoIkNhbnZhcyBpcyBub3Qgc3VwcG9ydGVkIil9LHU9ZT0+dHlwZW9mIEhUTUxDYW52YXNFbGVtZW50PCJ1IiYmZSBpbnN0YW5jZW9mIEhUTUxDYW52YXNFbGVtZW50fHxlIGluc3RhbmNlb2YgT2Zmc2NyZWVuQ2FudmFzP2UuZ2V0Q29udGV4dCgiMmQiKTpudWxsO2lmKG4pe2xldCBuPWwoKTtuLndpZHRoPWUud2lkdGgsbi5oZWlnaHQ9ZS5oZWlnaHQ7bGV0IG89dShuKTtpZihudWxsPT1vKXRocm93IG5ldyBFcnJvcigiQ2FuIG5vdCBhY2Nlc3MgaW1hZ2UgZGF0YSIpO3tsZXQgbj1lLmhlaWdodCxhPWUud2lkdGg7aWYodm9pZCAwIT09dCYmdm9pZCAwIT09dC5yZXNpemVkSGVpZ2h0JiZ2b2lkIDAhPT10LnJlc2l6ZWRXaWR0aCYmKG49dC5yZXNpemVkSGVpZ2h0LGE9dC5yZXNpemVkV2lkdGgpLHZvaWQgMCE9PXQpe2lmKHM9dCx2b2lkIDAhPT10LnRlbnNvckZvcm1hdCl0aHJvdyBuZXcgRXJyb3IoIkltYWdlIGlucHV0IGNvbmZpZyBmb3JtYXQgbXVzdCBiZSBSR0JBIGZvciBIVE1MSW1hZ2VFbGVtZW50Iik7cy50ZW5zb3JGb3JtYXQ9IlJHQkEiLHMuaGVpZ2h0PW4scy53aWR0aD1hO31lbHNlIHMudGVuc29yRm9ybWF0PSJSR0JBIixzLmhlaWdodD1uLHMud2lkdGg9YTtvLmRyYXdJbWFnZShlLDAsMCkscj1vLmdldEltYWdlRGF0YSgwLDAsYSxuKS5kYXRhO319ZWxzZSB7aWYoIW8pe2lmKGEpe2lmKHZvaWQgMD09PXQpdGhyb3cgbmV3IEVycm9yKCJQbGVhc2UgcHJvdmlkZSBpbWFnZSBjb25maWcgd2l0aCBmb3JtYXQgZm9yIEltYWdlYml0bWFwIik7bGV0IG49bCgpO24ud2lkdGg9ZS53aWR0aCxuLmhlaWdodD1lLmhlaWdodDtsZXQgbz11KG4pO2lmKG51bGwhPW8pe2xldCB0PWUuaGVpZ2h0LG49ZS53aWR0aDtyZXR1cm4gby5kcmF3SW1hZ2UoZSwwLDAsbix0KSxyPW8uZ2V0SW1hZ2VEYXRhKDAsMCxuLHQpLmRhdGEscy5oZWlnaHQ9dCxzLndpZHRoPW4sSGUocixzKX10aHJvdyBuZXcgRXJyb3IoIkNhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEiKX1pZihpKXJldHVybiBuZXcgUHJvbWlzZSgoKHQscik9PntsZXQgbj1sKCksbz11KG4pO2lmKCFlfHwhbylyZXR1cm4gcigpO2xldCBhPW5ldyBJbWFnZTthLmNyb3NzT3JpZ2luPSJBbm9ueW1vdXMiLGEuc3JjPWUsYS5vbmxvYWQ9KCk9PntuLndpZHRoPWEud2lkdGgsbi5oZWlnaHQ9YS5oZWlnaHQsby5kcmF3SW1hZ2UoYSwwLDAsbi53aWR0aCxuLmhlaWdodCk7bGV0IGU9by5nZXRJbWFnZURhdGEoMCwwLG4ud2lkdGgsbi5oZWlnaHQpO3MuaGVpZ2h0PW4uaGVpZ2h0LHMud2lkdGg9bi53aWR0aCx0KEhlKGUuZGF0YSxzKSk7fTt9KSk7dGhyb3cgbmV3IEVycm9yKCJJbnB1dCBkYXRhIHByb3ZpZGVkIGlzIG5vdCBzdXBwb3J0ZWQgLSBhYm9ydGVkIHRlbnNvciBjcmVhdGlvbiIpfXtsZXQgbixvO2lmKHZvaWQgMCE9PXQmJnZvaWQgMCE9PXQucmVzaXplZFdpZHRoJiZ2b2lkIDAhPT10LnJlc2l6ZWRIZWlnaHQ/KG49dC5yZXNpemVkSGVpZ2h0LG89dC5yZXNpemVkV2lkdGgpOihuPWUuaGVpZ2h0LG89ZS53aWR0aCksdm9pZCAwIT09dCYmKHM9dCkscy5mb3JtYXQ9IlJHQkEiLHMuaGVpZ2h0PW4scy53aWR0aD1vLHZvaWQgMCE9PXQpe2xldCB0PWwoKTt0LndpZHRoPW8sdC5oZWlnaHQ9bjtsZXQgYT11KHQpO2lmKG51bGw9PWEpdGhyb3cgbmV3IEVycm9yKCJDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhIik7YS5wdXRJbWFnZURhdGEoZSwwLDApLHI9YS5nZXRJbWFnZURhdGEoMCwwLG8sbikuZGF0YTt9ZWxzZSByPWUuZGF0YTt9fWlmKHZvaWQgMCE9PXIpcmV0dXJuIEhlKHIscyk7dGhyb3cgbmV3IEVycm9yKCJJbnB1dCBkYXRhIHByb3ZpZGVkIGlzIG5vdCBzdXBwb3J0ZWQgLSBhYm9ydGVkIHRlbnNvciBjcmVhdGlvbiIpfSxidD0oZSx0KT0+e2xldHt3aWR0aDpyLGhlaWdodDpuLGRvd25sb2FkOm8sZGlzcG9zZTphfT10O3JldHVybiBuZXcgdih7bG9jYXRpb246InRleHR1cmUiLHR5cGU6ImZsb2F0MzIiLHRleHR1cmU6ZSxkaW1zOlsxLG4sciw0XSxkb3dubG9hZDpvLGRpc3Bvc2U6YX0pfSxndD0oZSx0KT0+e2xldHtkYXRhVHlwZTpyLGRpbXM6bixkb3dubG9hZDpvLGRpc3Bvc2U6YX09dDtyZXR1cm4gbmV3IHYoe2xvY2F0aW9uOiJncHUtYnVmZmVyIix0eXBlOnI/PyJmbG9hdDMyIixncHVCdWZmZXI6ZSxkaW1zOm4sZG93bmxvYWQ6byxkaXNwb3NlOmF9KX0sRXQ9KGUsdCk9PntsZXR7ZGF0YVR5cGU6cixkaW1zOm4sZG93bmxvYWQ6byxkaXNwb3NlOmF9PXQ7cmV0dXJuIG5ldyB2KHtsb2NhdGlvbjoibWwtdGVuc29yIix0eXBlOnI/PyJmbG9hdDMyIixtbFRlbnNvcjplLGRpbXM6bixkb3dubG9hZDpvLGRpc3Bvc2U6YX0pfSxUdD0oZSx0LHIpPT5uZXcgdih7bG9jYXRpb246ImNwdS1waW5uZWQiLHR5cGU6ZSxkYXRhOnQsZGltczpyPz9bdC5sZW5ndGhdfSk7fSkpLHh0PVQoKCgpPT57SD1uZXcgTWFwKFtbImZsb2F0MzIiLEZsb2F0MzJBcnJheV0sWyJ1aW50OCIsVWludDhBcnJheV0sWyJpbnQ4IixJbnQ4QXJyYXldLFsidWludDE2IixVaW50MTZBcnJheV0sWyJpbnQxNiIsSW50MTZBcnJheV0sWyJpbnQzMiIsSW50MzJBcnJheV0sWyJib29sIixVaW50OEFycmF5XSxbImZsb2F0NjQiLEZsb2F0NjRBcnJheV0sWyJ1aW50MzIiLFVpbnQzMkFycmF5XSxbImludDQiLFVpbnQ4QXJyYXldLFsidWludDQiLFVpbnQ4QXJyYXldXSksYWU9bmV3IE1hcChbW0Zsb2F0MzJBcnJheSwiZmxvYXQzMiJdLFtVaW50OEFycmF5LCJ1aW50OCJdLFtJbnQ4QXJyYXksImludDgiXSxbVWludDE2QXJyYXksInVpbnQxNiJdLFtJbnQxNkFycmF5LCJpbnQxNiJdLFtJbnQzMkFycmF5LCJpbnQzMiJdLFtGbG9hdDY0QXJyYXksImZsb2F0NjQiXSxbVWludDMyQXJyYXksInVpbnQzMiJdXSksQXQ9ITEsT3Q9KCk9PntpZighQXQpe0F0PSEwO2xldCBlPXR5cGVvZiBCaWdJbnQ2NEFycmF5PCJ1IiYmQmlnSW50NjRBcnJheS5mcm9tLHQ9dHlwZW9mIEJpZ1VpbnQ2NEFycmF5PCJ1IiYmQmlnVWludDY0QXJyYXkuZnJvbSxyPWdsb2JhbFRoaXMuRmxvYXQxNkFycmF5LG49dHlwZW9mIHI8InUiJiZyLmZyb207ZSYmKEguc2V0KCJpbnQ2NCIsQmlnSW50NjRBcnJheSksYWUuc2V0KEJpZ0ludDY0QXJyYXksImludDY0IikpLHQmJihILnNldCgidWludDY0IixCaWdVaW50NjRBcnJheSksYWUuc2V0KEJpZ1VpbnQ2NEFycmF5LCJ1aW50NjQiKSksbj8oSC5zZXQoImZsb2F0MTYiLHIpLGFlLnNldChyLCJmbG9hdDE2IikpOkguc2V0KCJmbG9hdDE2IixVaW50MTZBcnJheSk7fX07fSkpLFB0PVQoKCgpPT57d2UoKSxMdD1lPT57bGV0IHQ9MTtmb3IobGV0IHI9MDtyPGUubGVuZ3RoO3IrKyl7bGV0IG49ZVtyXTtpZigibnVtYmVyIiE9dHlwZW9mIG58fCFOdW1iZXIuaXNTYWZlSW50ZWdlcihuKSl0aHJvdyBuZXcgVHlwZUVycm9yKGBkaW1zWyR7cn1dIG11c3QgYmUgYW4gaW50ZWdlciwgZ290OiAke259YCk7aWYobjwwKXRocm93IG5ldyBSYW5nZUVycm9yKGBkaW1zWyR7cn1dIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlciwgZ290OiAke259YCk7dCo9bjt9cmV0dXJuIHR9LEl0PShlLHQpPT57c3dpdGNoKGUubG9jYXRpb24pe2Nhc2UiY3B1IjpyZXR1cm4gbmV3IHYoZS50eXBlLGUuZGF0YSx0KTtjYXNlImNwdS1waW5uZWQiOnJldHVybiBuZXcgdih7bG9jYXRpb246ImNwdS1waW5uZWQiLGRhdGE6ZS5kYXRhLHR5cGU6ZS50eXBlLGRpbXM6dH0pO2Nhc2UidGV4dHVyZSI6cmV0dXJuIG5ldyB2KHtsb2NhdGlvbjoidGV4dHVyZSIsdGV4dHVyZTplLnRleHR1cmUsdHlwZTplLnR5cGUsZGltczp0fSk7Y2FzZSJncHUtYnVmZmVyIjpyZXR1cm4gbmV3IHYoe2xvY2F0aW9uOiJncHUtYnVmZmVyIixncHVCdWZmZXI6ZS5ncHVCdWZmZXIsdHlwZTplLnR5cGUsZGltczp0fSk7Y2FzZSJtbC10ZW5zb3IiOnJldHVybiBuZXcgdih7bG9jYXRpb246Im1sLXRlbnNvciIsbWxUZW5zb3I6ZS5tbFRlbnNvcix0eXBlOmUudHlwZSxkaW1zOnR9KTtkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgdGVuc29yUmVzaGFwZTogdGVuc29yIGxvY2F0aW9uICR7ZS5sb2NhdGlvbn0gaXMgbm90IHN1cHBvcnRlZGApfX07fSkpLHdlPVQoKCgpPT57d3QoKSxTdCgpLHh0KCksUHQoKSx2PWNsYXNze2NvbnN0cnVjdG9yKGUsdCxyKXtsZXQgbixvO2lmKE90KCksIm9iamVjdCI9PXR5cGVvZiBlJiYibG9jYXRpb24iaW4gZSlzd2l0Y2godGhpcy5kYXRhTG9jYXRpb249ZS5sb2NhdGlvbixuPWUudHlwZSxvPWUuZGltcyxlLmxvY2F0aW9uKXtjYXNlImNwdS1waW5uZWQiOntsZXQgdD1ILmdldChuKTtpZighdCl0aHJvdyBuZXcgVHlwZUVycm9yKGB1bnN1cHBvcnRlZCB0eXBlICIke259IiB0byBjcmVhdGUgdGVuc29yIGZyb20gcGlubmVkIGJ1ZmZlcmApO2lmKCEoZS5kYXRhIGluc3RhbmNlb2YgdCkpdGhyb3cgbmV3IFR5cGVFcnJvcihgYnVmZmVyIHNob3VsZCBiZSBvZiB0eXBlICR7dC5uYW1lfWApO3RoaXMuY3B1RGF0YT1lLmRhdGE7YnJlYWt9Y2FzZSJ0ZXh0dXJlIjppZigiZmxvYXQzMiIhPT1uKXRocm93IG5ldyBUeXBlRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGUgIiR7bn0iIHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbSB0ZXh0dXJlYCk7dGhpcy5ncHVUZXh0dXJlRGF0YT1lLnRleHR1cmUsdGhpcy5kb3dubG9hZGVyPWUuZG93bmxvYWQsdGhpcy5kaXNwb3Nlcj1lLmRpc3Bvc2U7YnJlYWs7Y2FzZSJncHUtYnVmZmVyIjppZigiZmxvYXQzMiIhPT1uJiYiZmxvYXQxNiIhPT1uJiYiaW50MzIiIT09biYmImludDY0IiE9PW4mJiJ1aW50MzIiIT09biYmInVpbnQ4IiE9PW4mJiJib29sIiE9PW4mJiJ1aW50NCIhPT1uJiYiaW50NCIhPT1uKXRocm93IG5ldyBUeXBlRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGUgIiR7bn0iIHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbSBncHUgYnVmZmVyYCk7dGhpcy5ncHVCdWZmZXJEYXRhPWUuZ3B1QnVmZmVyLHRoaXMuZG93bmxvYWRlcj1lLmRvd25sb2FkLHRoaXMuZGlzcG9zZXI9ZS5kaXNwb3NlO2JyZWFrO2Nhc2UibWwtdGVuc29yIjppZigiZmxvYXQzMiIhPT1uJiYiZmxvYXQxNiIhPT1uJiYiaW50MzIiIT09biYmImludDY0IiE9PW4mJiJ1aW50MzIiIT09biYmInVpbnQ2NCIhPT1uJiYiaW50OCIhPT1uJiYidWludDgiIT09biYmImJvb2wiIT09biYmInVpbnQ0IiE9PW4mJiJpbnQ0IiE9PW4pdGhyb3cgbmV3IFR5cGVFcnJvcihgdW5zdXBwb3J0ZWQgdHlwZSAiJHtufSIgdG8gY3JlYXRlIHRlbnNvciBmcm9tIE1MVGVuc29yYCk7dGhpcy5tbFRlbnNvckRhdGE9ZS5tbFRlbnNvcix0aGlzLmRvd25sb2FkZXI9ZS5kb3dubG9hZCx0aGlzLmRpc3Bvc2VyPWUuZGlzcG9zZTticmVhaztkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgVGVuc29yIGNvbnN0cnVjdG9yOiB1bnN1cHBvcnRlZCBsb2NhdGlvbiAnJHt0aGlzLmRhdGFMb2NhdGlvbn0nYCl9ZWxzZSB7bGV0IGEsaTtpZigic3RyaW5nIj09dHlwZW9mIGUpaWYobj1lLGk9ciwic3RyaW5nIj09PWUpe2lmKCFBcnJheS5pc0FycmF5KHQpKXRocm93IG5ldyBUeXBlRXJyb3IoIkEgc3RyaW5nIHRlbnNvcidzIGRhdGEgbXVzdCBiZSBhIHN0cmluZyBhcnJheS4iKTthPXQ7fWVsc2Uge2xldCByPUguZ2V0KGUpO2lmKHZvaWQgMD09PXIpdGhyb3cgbmV3IFR5cGVFcnJvcihgVW5zdXBwb3J0ZWQgdGVuc29yIHR5cGU6ICR7ZX0uYCk7aWYoQXJyYXkuaXNBcnJheSh0KSl7aWYoImZsb2F0MTYiPT09ZSYmcj09PVVpbnQxNkFycmF5fHwidWludDQiPT09ZXx8ImludDQiPT09ZSl0aHJvdyBuZXcgVHlwZUVycm9yKGBDcmVhdGluZyBhICR7ZX0gdGVuc29yIGZyb20gbnVtYmVyIGFycmF5IGlzIG5vdCBzdXBwb3J0ZWQuIFBsZWFzZSB1c2UgJHtyLm5hbWV9IGFzIGRhdGEuYCk7YT0idWludDY0Ij09PWV8fCJpbnQ2NCI9PT1lP3IuZnJvbSh0LEJpZ0ludCk6ci5mcm9tKHQpO31lbHNlIGlmKHQgaW5zdGFuY2VvZiByKWE9dDtlbHNlIGlmKHQgaW5zdGFuY2VvZiBVaW50OENsYW1wZWRBcnJheSl7aWYoInVpbnQ4IiE9PWUpdGhyb3cgbmV3IFR5cGVFcnJvcigiQSBVaW50OENsYW1wZWRBcnJheSB0ZW5zb3IncyBkYXRhIG11c3QgYmUgdHlwZSBvZiB1aW50OCIpO2E9VWludDhBcnJheS5mcm9tKHQpO31lbHNlIHtpZighKCJmbG9hdDE2Ij09PWUmJnQgaW5zdGFuY2VvZiBVaW50MTZBcnJheSYmciE9PVVpbnQxNkFycmF5KSl0aHJvdyBuZXcgVHlwZUVycm9yKGBBICR7bn0gdGVuc29yJ3MgZGF0YSBtdXN0IGJlIHR5cGUgb2YgJHtyfWApO2E9bmV3IGdsb2JhbFRoaXMuRmxvYXQxNkFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0Lmxlbmd0aCk7fX1lbHNlIGlmKGk9dCxBcnJheS5pc0FycmF5KGUpKXtpZigwPT09ZS5sZW5ndGgpdGhyb3cgbmV3IFR5cGVFcnJvcigiVGVuc29yIHR5cGUgY2Fubm90IGJlIGluZmVycmVkIGZyb20gYW4gZW1wdHkgYXJyYXkuIik7bGV0IHQ9dHlwZW9mIGVbMF07aWYoInN0cmluZyI9PT10KW49InN0cmluZyIsYT1lO2Vsc2Uge2lmKCJib29sZWFuIiE9PXQpdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBlbGVtZW50IHR5cGUgb2YgZGF0YSBhcnJheTogJHt0fS5gKTtuPSJib29sIixhPVVpbnQ4QXJyYXkuZnJvbShlKTt9fWVsc2UgaWYoZSBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5KW49InVpbnQ4IixhPVVpbnQ4QXJyYXkuZnJvbShlKTtlbHNlIHtsZXQgdD1hZS5nZXQoZS5jb25zdHJ1Y3Rvcik7aWYodm9pZCAwPT09dCl0aHJvdyBuZXcgVHlwZUVycm9yKGBVbnN1cHBvcnRlZCB0eXBlIGZvciB0ZW5zb3IgZGF0YTogJHtlLmNvbnN0cnVjdG9yfS5gKTtuPXQsYT1lO31pZih2b2lkIDA9PT1pKWk9W2EubGVuZ3RoXTtlbHNlIGlmKCFBcnJheS5pc0FycmF5KGkpKXRocm93IG5ldyBUeXBlRXJyb3IoIkEgdGVuc29yJ3MgZGltcyBtdXN0IGJlIGEgbnVtYmVyIGFycmF5Iik7bz1pLHRoaXMuY3B1RGF0YT1hLHRoaXMuZGF0YUxvY2F0aW9uPSJjcHUiO31sZXQgYT1MdChvKTtpZih0aGlzLmNwdURhdGEmJmEhPT10aGlzLmNwdURhdGEubGVuZ3RoJiYoInVpbnQ0IiE9PW4mJiJpbnQ0IiE9PW58fE1hdGguY2VpbChhLzIpIT09dGhpcy5jcHVEYXRhLmxlbmd0aCkpdGhyb3cgbmV3IEVycm9yKGBUZW5zb3IncyBzaXplKCR7YX0pIGRvZXMgbm90IG1hdGNoIGRhdGEgbGVuZ3RoKCR7dGhpcy5jcHVEYXRhLmxlbmd0aH0pLmApO3RoaXMudHlwZT1uLHRoaXMuZGltcz1vLHRoaXMuc2l6ZT1hO31zdGF0aWMgYXN5bmMgZnJvbUltYWdlKGUsdCl7cmV0dXJuIHl0KGUsdCl9c3RhdGljIGZyb21UZXh0dXJlKGUsdCl7cmV0dXJuIGJ0KGUsdCl9c3RhdGljIGZyb21HcHVCdWZmZXIoZSx0KXtyZXR1cm4gZ3QoZSx0KX1zdGF0aWMgZnJvbU1MVGVuc29yKGUsdCl7cmV0dXJuIEV0KGUsdCl9c3RhdGljIGZyb21QaW5uZWRCdWZmZXIoZSx0LHIpe3JldHVybiBUdChlLHQscil9dG9EYXRhVVJMKGUpe3JldHVybiBtdCh0aGlzLGUpfXRvSW1hZ2VEYXRhKGUpe3JldHVybiBodCh0aGlzLGUpfWdldCBkYXRhKCl7aWYodGhpcy5lbnN1cmVWYWxpZCgpLCF0aGlzLmNwdURhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgb24gQ1BVLiBVc2UgYGdldERhdGEoKWAgdG8gZG93bmxvYWQgR1BVIGRhdGEgdG8gQ1BVLCBvciB1c2UgYHRleHR1cmVgIG9yIGBncHVCdWZmZXJgIHByb3BlcnR5IHRvIGFjY2VzcyB0aGUgR1BVIGRhdGEgZGlyZWN0bHkuIik7cmV0dXJuIHRoaXMuY3B1RGF0YX1nZXQgbG9jYXRpb24oKXtyZXR1cm4gdGhpcy5kYXRhTG9jYXRpb259Z2V0IHRleHR1cmUoKXtpZih0aGlzLmVuc3VyZVZhbGlkKCksIXRoaXMuZ3B1VGV4dHVyZURhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViR0wgdGV4dHVyZS4iKTtyZXR1cm4gdGhpcy5ncHVUZXh0dXJlRGF0YX1nZXQgZ3B1QnVmZmVyKCl7aWYodGhpcy5lbnN1cmVWYWxpZCgpLCF0aGlzLmdwdUJ1ZmZlckRhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViR1BVIGJ1ZmZlci4iKTtyZXR1cm4gdGhpcy5ncHVCdWZmZXJEYXRhfWdldCBtbFRlbnNvcigpe2lmKHRoaXMuZW5zdXJlVmFsaWQoKSwhdGhpcy5tbFRlbnNvckRhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViTk4gTUxUZW5zb3IuIik7cmV0dXJuIHRoaXMubWxUZW5zb3JEYXRhfWFzeW5jIGdldERhdGEoZSl7c3dpdGNoKHRoaXMuZW5zdXJlVmFsaWQoKSx0aGlzLmRhdGFMb2NhdGlvbil7Y2FzZSJjcHUiOmNhc2UiY3B1LXBpbm5lZCI6cmV0dXJuIHRoaXMuZGF0YTtjYXNlInRleHR1cmUiOmNhc2UiZ3B1LWJ1ZmZlciI6Y2FzZSJtbC10ZW5zb3IiOmlmKCF0aGlzLmRvd25sb2FkZXIpdGhyb3cgbmV3IEVycm9yKCJUaGUgY3VycmVudCB0ZW5zb3IgaXMgbm90IGNyZWF0ZWQgd2l0aCBhIHNwZWNpZmllZCBkYXRhIGRvd25sb2FkZXIuIik7aWYodGhpcy5pc0Rvd25sb2FkaW5nKXRocm93IG5ldyBFcnJvcigiVGhlIGN1cnJlbnQgdGVuc29yIGlzIGJlaW5nIGRvd25sb2FkZWQuIik7dHJ5e3RoaXMuaXNEb3dubG9hZGluZz0hMDtsZXQgdD1hd2FpdCB0aGlzLmRvd25sb2FkZXIoKTtyZXR1cm4gdGhpcy5kb3dubG9hZGVyPXZvaWQgMCx0aGlzLmRhdGFMb2NhdGlvbj0iY3B1Iix0aGlzLmNwdURhdGE9dCxlJiZ0aGlzLmRpc3Bvc2VyJiYodGhpcy5kaXNwb3NlcigpLHRoaXMuZGlzcG9zZXI9dm9pZCAwKSx0fWZpbmFsbHl7dGhpcy5pc0Rvd25sb2FkaW5nPSExO31kZWZhdWx0OnRocm93IG5ldyBFcnJvcihgY2Fubm90IGdldCBkYXRhIGZyb20gbG9jYXRpb246ICR7dGhpcy5kYXRhTG9jYXRpb259YCl9fWRpc3Bvc2UoKXtpZih0aGlzLmlzRG93bmxvYWRpbmcpdGhyb3cgbmV3IEVycm9yKCJUaGUgY3VycmVudCB0ZW5zb3IgaXMgYmVpbmcgZG93bmxvYWRlZC4iKTt0aGlzLmRpc3Bvc2VyJiYodGhpcy5kaXNwb3NlcigpLHRoaXMuZGlzcG9zZXI9dm9pZCAwKSx0aGlzLmNwdURhdGE9dm9pZCAwLHRoaXMuZ3B1VGV4dHVyZURhdGE9dm9pZCAwLHRoaXMuZ3B1QnVmZmVyRGF0YT12b2lkIDAsdGhpcy5tbFRlbnNvckRhdGE9dm9pZCAwLHRoaXMuZG93bmxvYWRlcj12b2lkIDAsdGhpcy5pc0Rvd25sb2FkaW5nPXZvaWQgMCx0aGlzLmRhdGFMb2NhdGlvbj0ibm9uZSI7fWVuc3VyZVZhbGlkKCl7aWYoIm5vbmUiPT09dGhpcy5kYXRhTG9jYXRpb24pdGhyb3cgbmV3IEVycm9yKCJUaGUgdGVuc29yIGlzIGRpc3Bvc2VkLiIpfXJlc2hhcGUoZSl7aWYodGhpcy5lbnN1cmVWYWxpZCgpLHRoaXMuZG93bmxvYWRlcnx8dGhpcy5kaXNwb3Nlcil0aHJvdyBuZXcgRXJyb3IoIkNhbm5vdCByZXNoYXBlIGEgdGVuc29yIHRoYXQgb3ducyBHUFUgcmVzb3VyY2UuIik7cmV0dXJuIEl0KHRoaXMsZSl9fTt9KSksVmU9VCgoKCk9Pnt3ZSgpLFI9djt9KSksWWU9VCgoKCk9PntqZSgpLHZ0PShlLHQpPT57KHR5cGVvZiBfLnRyYWNlPiJ1Ij8hXy53YXNtLnRyYWNlOiFfLnRyYWNlKXx8Y29uc29sZS50aW1lU3RhbXAoYCR7ZX06Ok9SVDo6JHt0fWApO30sQnQ9KGUsdCk9PntsZXQgcj0obmV3IEVycm9yKS5zdGFjaz8uc3BsaXQoL1xyXG58XHJ8XG4vZyl8fFtdLG49ITE7Zm9yKGxldCBvPTA7bzxyLmxlbmd0aDtvKyspe2lmKG4mJiFyW29dLmluY2x1ZGVzKCJUUkFDRV9GVU5DIikpe2xldCBuPWBGVU5DXyR7ZX06OiR7cltvXS50cmltKCkuc3BsaXQoIiAiKVsxXX1gO3JldHVybiB0JiYobis9YDo6JHt0fWApLHZvaWQgdnQoIkNQVSIsbil9cltvXS5pbmNsdWRlcygiVFJBQ0VfRlVOQyIpJiYobj0hMCk7fX0sVj1lPT57KHR5cGVvZiBfLnRyYWNlPiJ1Ij8hXy53YXNtLnRyYWNlOiFfLnRyYWNlKXx8QnQoIkJFR0lOIixlKTt9LFk9ZT0+eyh0eXBlb2YgXy50cmFjZT4idSI/IV8ud2FzbS50cmFjZTohXy50cmFjZSl8fEJ0KCJFTkQiLGUpO307fSkpLEN0PVQoKCgpPT57emUoKSxWZSgpLFllKCkseWU9Y2xhc3MgZXtjb25zdHJ1Y3RvcihlKXt0aGlzLmhhbmRsZXI9ZTt9YXN5bmMgcnVuKGUsdCxyKXtWKCk7bGV0IG49e30sbz17fTtpZigib2JqZWN0IiE9dHlwZW9mIGV8fG51bGw9PT1lfHxlIGluc3RhbmNlb2YgUnx8QXJyYXkuaXNBcnJheShlKSl0aHJvdyBuZXcgVHlwZUVycm9yKCInZmVlZHMnIG11c3QgYmUgYW4gb2JqZWN0IHRoYXQgdXNlIGlucHV0IG5hbWVzIGFzIGtleXMgYW5kIE9ubnhWYWx1ZSBhcyBjb3JyZXNwb25kaW5nIHZhbHVlcy4iKTtsZXQgYT0hMDtpZigib2JqZWN0Ij09dHlwZW9mIHQpe2lmKG51bGw9PT10KXRocm93IG5ldyBUeXBlRXJyb3IoIlVuZXhwZWN0ZWQgYXJndW1lbnRbMV06IGNhbm5vdCBiZSBudWxsLiIpO2lmKHQgaW5zdGFuY2VvZiBSKXRocm93IG5ldyBUeXBlRXJyb3IoIidmZXRjaGVzJyBjYW5ub3QgYmUgYSBUZW5zb3IiKTtpZihBcnJheS5pc0FycmF5KHQpKXtpZigwPT09dC5sZW5ndGgpdGhyb3cgbmV3IFR5cGVFcnJvcigiJ2ZldGNoZXMnIGNhbm5vdCBiZSBhbiBlbXB0eSBhcnJheS4iKTthPSExO2ZvcihsZXQgZSBvZiB0KXtpZigic3RyaW5nIiE9dHlwZW9mIGUpdGhyb3cgbmV3IFR5cGVFcnJvcigiJ2ZldGNoZXMnIG11c3QgYmUgYSBzdHJpbmcgYXJyYXkgb3IgYW4gb2JqZWN0LiIpO2lmKC0xPT09dGhpcy5vdXRwdXROYW1lcy5pbmRleE9mKGUpKXRocm93IG5ldyBSYW5nZUVycm9yKGAnZmV0Y2hlcycgY29udGFpbnMgaW52YWxpZCBvdXRwdXQgbmFtZTogJHtlfS5gKTtuW2VdPW51bGw7fWlmKCJvYmplY3QiPT10eXBlb2YgciYmbnVsbCE9PXIpbz1yO2Vsc2UgaWYodHlwZW9mIHI8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIHtsZXQgZT0hMSxpPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHQpO2ZvcihsZXQgciBvZiB0aGlzLm91dHB1dE5hbWVzKWlmKC0xIT09aS5pbmRleE9mKHIpKXtsZXQgbz10W3JdOyhudWxsPT09b3x8byBpbnN0YW5jZW9mIFIpJiYoZT0hMCxhPSExLG5bcl09byk7fWlmKGUpe2lmKCJvYmplY3QiPT10eXBlb2YgciYmbnVsbCE9PXIpbz1yO2Vsc2UgaWYodHlwZW9mIHI8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIG89dDt9fWVsc2UgaWYodHlwZW9mIHQ8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIlVuZXhwZWN0ZWQgYXJndW1lbnRbMV06IG11c3QgYmUgJ2ZldGNoZXMnIG9yICdvcHRpb25zJy4iKTtmb3IobGV0IHQgb2YgdGhpcy5pbnB1dE5hbWVzKWlmKHR5cGVvZiBlW3RdPiJ1Iil0aHJvdyBuZXcgRXJyb3IoYGlucHV0ICcke3R9JyBpcyBtaXNzaW5nIGluICdmZWVkcycuYCk7aWYoYSlmb3IobGV0IGUgb2YgdGhpcy5vdXRwdXROYW1lcyluW2VdPW51bGw7bGV0IGk9YXdhaXQgdGhpcy5oYW5kbGVyLnJ1bihlLG4sbykscz17fTtmb3IobGV0IGUgaW4gaSlpZihPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChpLGUpKXtsZXQgdD1pW2VdO3NbZV09dCBpbnN0YW5jZW9mIFI/dDpuZXcgUih0LnR5cGUsdC5kYXRhLHQuZGltcyk7fXJldHVybiBZKCksc31hc3luYyByZWxlYXNlKCl7cmV0dXJuIHRoaXMuaGFuZGxlci5kaXNwb3NlKCl9c3RhdGljIGFzeW5jIGNyZWF0ZSh0LHIsbixvKXtWKCk7bGV0IGEsaT17fTtpZigic3RyaW5nIj09dHlwZW9mIHQpe2lmKGE9dCwib2JqZWN0Ij09dHlwZW9mIHImJm51bGwhPT1yKWk9cjtlbHNlIGlmKHR5cGVvZiByPCJ1Iil0aHJvdyBuZXcgVHlwZUVycm9yKCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuIil9ZWxzZSBpZih0IGluc3RhbmNlb2YgVWludDhBcnJheSl7aWYoYT10LCJvYmplY3QiPT10eXBlb2YgciYmbnVsbCE9PXIpaT1yO2Vsc2UgaWYodHlwZW9mIHI8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIHtpZighKHQgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcnx8dHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyPCJ1IiYmdCBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyKSl0aHJvdyBuZXcgVHlwZUVycm9yKCJVbmV4cGVjdGVkIGFyZ3VtZW50WzBdOiBtdXN0IGJlICdwYXRoJyBvciAnYnVmZmVyJy4iKTt7bGV0IGU9dCxzPTAsbD10LmJ5dGVMZW5ndGg7aWYoIm9iamVjdCI9PXR5cGVvZiByJiZudWxsIT09cilpPXI7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIHIpe2lmKHM9ciwhTnVtYmVyLmlzU2FmZUludGVnZXIocykpdGhyb3cgbmV3IFJhbmdlRXJyb3IoIidieXRlT2Zmc2V0JyBtdXN0IGJlIGFuIGludGVnZXIuIik7aWYoczwwfHxzPj1lLmJ5dGVMZW5ndGgpdGhyb3cgbmV3IFJhbmdlRXJyb3IoYCdieXRlT2Zmc2V0JyBpcyBvdXQgb2YgcmFuZ2UgWzAsICR7ZS5ieXRlTGVuZ3RofSkuYCk7aWYobD10LmJ5dGVMZW5ndGgtcywibnVtYmVyIj09dHlwZW9mIG4pe2lmKGw9biwhTnVtYmVyLmlzU2FmZUludGVnZXIobCkpdGhyb3cgbmV3IFJhbmdlRXJyb3IoIidieXRlTGVuZ3RoJyBtdXN0IGJlIGFuIGludGVnZXIuIik7aWYobDw9MHx8cytsPmUuYnl0ZUxlbmd0aCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihgJ2J5dGVMZW5ndGgnIGlzIG91dCBvZiByYW5nZSAoMCwgJHtlLmJ5dGVMZW5ndGgtc31dLmApO2lmKCJvYmplY3QiPT10eXBlb2YgbyYmbnVsbCE9PW8paT1vO2Vsc2UgaWYodHlwZW9mIG88InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIGlmKHR5cGVvZiBuPCJ1Iil0aHJvdyBuZXcgVHlwZUVycm9yKCInYnl0ZUxlbmd0aCcgbXVzdCBiZSBhIG51bWJlci4iKX1lbHNlIGlmKHR5cGVvZiByPCJ1Iil0aHJvdyBuZXcgVHlwZUVycm9yKCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuIik7YT1uZXcgVWludDhBcnJheShlLHMsbCk7fX1sZXRbcyxsXT1hd2FpdCB1dChpKSx1PWF3YWl0IHMuY3JlYXRlSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIoYSxsKTtyZXR1cm4gWSgpLG5ldyBlKHUpfXN0YXJ0UHJvZmlsaW5nKCl7dGhpcy5oYW5kbGVyLnN0YXJ0UHJvZmlsaW5nKCk7fWVuZFByb2ZpbGluZygpe3RoaXMuaGFuZGxlci5lbmRQcm9maWxpbmcoKTt9Z2V0IGlucHV0TmFtZXMoKXtyZXR1cm4gdGhpcy5oYW5kbGVyLmlucHV0TmFtZXN9Z2V0IG91dHB1dE5hbWVzKCl7cmV0dXJuIHRoaXMuaGFuZGxlci5vdXRwdXROYW1lc319O30pKSxVdD1UKCgoKT0+e0N0KCksT3I9eWU7fSkpLF90PVQoKCgpPT57fSkpLE10PVQoKCgpPT57fSkpLER0PVQoKCgpPT57fSkpLFJ0PVQoKCgpPT57fSkpLHFlPXt9O0dlKHFlLHtJbmZlcmVuY2VTZXNzaW9uOigpPT5PcixUUkFDRTooKT0+dnQsVFJBQ0VfRlVOQ19CRUdJTjooKT0+VixUUkFDRV9GVU5DX0VORDooKT0+WSxUZW5zb3I6KCk9PlIsZW52OigpPT5BLHJlZ2lzdGVyQmFja2VuZDooKT0+aWV9KTt2YXIgcT1UKCgoKT0+e2Z0KCkscHQoKSxVdCgpLFZlKCksX3QoKSxNdCgpLFllKCksRHQoKSxSdCgpO30pKSxiZT1UKCgoKT0+e30pKSxXdD17fTtHZShXdCx7ZGVmYXVsdDooKT0+eHJ9KTt2YXIga3QsTnQseHIsanQsTSxQZSxYZSxJcixQcixIdCx2cixHdCxWdCx6dCxZdCxaZSxLZSx2ZSxxdCxCcixDcixFZSx4LEwsZmUsUyxKdCxVcixfcixNcixEcixadCxlZSxRdCx0ZSxlcix0cixDZSxVZSxycixjZSxScixUZSxTZSxyZSxGcix1ZSxBZSxPZSxucix4ZSxMZSxJZSxaLEQsbGUsTWUsRGUsX2UsdHQscnQsbmUsb2UsTnIsb3Isc3IsaXIsYXIsdXIsZnIsY3IsbHIsV3IsUmUsJHQ9VCgoKCk9PntKZSgpLEooKSxnZSgpLGt0PSJvcnQtd2FzbS1wcm94eS13b3JrZXIiLChOdD1nbG9iYWxUaGlzLnNlbGY/Lm5hbWU9PT1rdCkmJihzZWxmLm9ubWVzc2FnZT1lPT57bGV0e3R5cGU6dCxpbjpyfT1lLmRhdGE7dHJ5e3N3aXRjaCh0KXtjYXNlImluaXQtd2FzbSI6RWUoci53YXNtKS50aGVuKCgoKT0+e1RlKHIpLnRoZW4oKCgpPT57cG9zdE1lc3NhZ2Uoe3R5cGU6dH0pO30pLChlPT57cG9zdE1lc3NhZ2Uoe3R5cGU6dCxlcnI6ZX0pO30pKTt9KSwoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsZXJyOmV9KTt9KSk7YnJlYWs7Y2FzZSJpbml0LWVwIjp7bGV0e2VwTmFtZTplLGVudjpufT1yO1NlKG4sZSkudGhlbigoKCk9Pntwb3N0TWVzc2FnZSh7dHlwZTp0fSk7fSksKGU9Pntwb3N0TWVzc2FnZSh7dHlwZTp0LGVycjplfSk7fSkpO2JyZWFrfWNhc2UiY29weS1mcm9tIjp7bGV0e2J1ZmZlcjplfT1yLG49dWUoZSk7cG9zdE1lc3NhZ2Uoe3R5cGU6dCxvdXQ6bn0pO2JyZWFrfWNhc2UiY3JlYXRlIjp7bGV0e21vZGVsOmUsb3B0aW9uczpufT1yO0FlKGUsbikudGhlbigoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsb3V0OmV9KTt9KSwoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsZXJyOmV9KTt9KSk7YnJlYWt9Y2FzZSJyZWxlYXNlIjpPZShyKSxwb3N0TWVzc2FnZSh7dHlwZTp0fSk7YnJlYWs7Y2FzZSJydW4iOntsZXR7c2Vzc2lvbklkOmUsaW5wdXRJbmRpY2VzOm4saW5wdXRzOm8sb3V0cHV0SW5kaWNlczphLG9wdGlvbnM6aX09cjt4ZShlLG4sbyxhLG5ldyBBcnJheShhLmxlbmd0aCkuZmlsbChudWxsKSxpKS50aGVuKChlPT57ZS5zb21lKChlPT4iY3B1IiE9PWVbM10pKT9wb3N0TWVzc2FnZSh7dHlwZTp0LGVycjoiUHJveHkgZG9lcyBub3Qgc3VwcG9ydCBub24tY3B1IHRlbnNvciBsb2NhdGlvbi4ifSk6cG9zdE1lc3NhZ2Uoe3R5cGU6dCxvdXQ6ZX0sSWUoWy4uLm8sLi4uZV0pKTt9KSwoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsZXJyOmV9KTt9KSk7YnJlYWt9Y2FzZSJlbmQtcHJvZmlsaW5nIjpMZShyKSxwb3N0TWVzc2FnZSh7dHlwZTp0fSk7fX1jYXRjaChlKXtwb3N0TWVzc2FnZSh7dHlwZTp0LGVycjplfSk7fX0pLHhyPU50P251bGw6ZT0+bmV3IFdvcmtlcihlPz9NLHt0eXBlOiJtb2R1bGUiLG5hbWU6a3R9KTt9KSksZ2U9VCgoKCk9PntiZSgpLGp0PXR5cGVvZiBsb2NhdGlvbj4idSI/dm9pZCAwOmxvY2F0aW9uLm9yaWdpbixNPSgoKT0+aW1wb3J0Lm1ldGEudXJsPy5zdGFydHNXaXRoKCJmaWxlOiIpP25ldyBVUkwobmV3IFVSTCgib3J0Lndhc20uYnVuZGxlLm1pbi5tanMiLGltcG9ydC5tZXRhLnVybCkuaHJlZixqdCkuaHJlZjppbXBvcnQubWV0YS51cmwpKCksUGU9KCk9PntpZihNJiYhTS5zdGFydHNXaXRoKCJibG9iOiIpKXJldHVybiBNLnN1YnN0cmluZygwLE0ubGFzdEluZGV4T2YoIi8iKSsxKX0sWGU9KGUsdCk9Pnt0cnl7bGV0IHI9dD8/TTtyZXR1cm4gKHI/bmV3IFVSTChlLHIpOm5ldyBVUkwoZSkpLm9yaWdpbj09PWp0fWNhdGNoe3JldHVybiAhMX19LElyPShlLHQpPT57bGV0IHI9dD8/TTt0cnl7cmV0dXJuIChyP25ldyBVUkwoZSxyKTpuZXcgVVJMKGUpKS5ocmVmfWNhdGNoe3JldHVybn19LFByPShlLHQpPT5gJHt0Pz8iLi8ifSR7ZX1gLEh0PWFzeW5jIGU9PntsZXQgdD1hd2FpdChhd2FpdCBmZXRjaChlLHtjcmVkZW50aWFsczoic2FtZS1vcmlnaW4ifSkpLmJsb2IoKTtyZXR1cm4gVVJMLmNyZWF0ZU9iamVjdFVSTCh0KX0sdnI9YXN5bmMgZT0+KGF3YWl0IGltcG9ydChlKSkuZGVmYXVsdCxHdD0oJHQoKSxhdChXdCkpLmRlZmF1bHQsVnQ9YXN5bmMoKT0+e2lmKCFNKXRocm93IG5ldyBFcnJvcigiRmFpbGVkIHRvIGxvYWQgcHJveHkgd29ya2VyOiBjYW5ub3QgZGV0ZXJtaW5lIHRoZSBzY3JpcHQgc291cmNlIFVSTC4iKTtpZihYZShNKSlyZXR1cm4gW3ZvaWQgMCxHdCgpXTtsZXQgZT1hd2FpdCBIdChNKTtyZXR1cm4gW2UsR3QoZSldfSx6dD12b2lkIDAsWXQ9YXN5bmMoZSx0LHIpPT57aWYoIWUmJiF0JiZ6dCYmTSYmWGUoTSkpcmV0dXJuIFt2b2lkIDAsenRdO3tsZXQgbj0ib3J0LXdhc20tc2ltZC10aHJlYWRlZC5tanMiLG89ZT8/SXIobix0KSxhPXImJm8mJiFYZShvLHQpLGk9YT9hd2FpdCBIdChvKTpvPz9QcihuLHQpO3JldHVybiBbYT9pOnZvaWQgMCxhd2FpdCB2cihpKV19fTt9KSksSj1UKCgoKT0+e2dlKCksS2U9ITEsdmU9ITEscXQ9ITEsQnI9KCk9PntpZih0eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXI+InUiKXJldHVybiAhMTt0cnl7cmV0dXJuIHR5cGVvZiBNZXNzYWdlQ2hhbm5lbDwidSImJihuZXcgTWVzc2FnZUNoYW5uZWwpLnBvcnQxLnBvc3RNZXNzYWdlKG5ldyBTaGFyZWRBcnJheUJ1ZmZlcigxKSksV2ViQXNzZW1ibHkudmFsaWRhdGUobmV3IFVpbnQ4QXJyYXkoWzAsOTcsMTE1LDEwOSwxLDAsMCwwLDEsNCwxLDk2LDAsMCwzLDIsMSwwLDUsNCwxLDMsMSwxLDEwLDExLDEsOSwwLDY1LDAsMjU0LDE2LDIsMCwyNiwxMV0pKX1jYXRjaHtyZXR1cm4gITF9fSxDcj0oKT0+e3RyeXtyZXR1cm4gV2ViQXNzZW1ibHkudmFsaWRhdGUobmV3IFVpbnQ4QXJyYXkoWzAsOTcsMTE1LDEwOSwxLDAsMCwwLDEsNCwxLDk2LDAsMCwzLDIsMSwwLDEwLDMwLDEsMjgsMCw2NSwwLDI1MywxNSwyNTMsMTIsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwyNTMsMTg2LDEsMjYsMTFdKSl9Y2F0Y2h7cmV0dXJuICExfX0sRWU9YXN5bmMgZT0+e2lmKEtlKXJldHVybiBQcm9taXNlLnJlc29sdmUoKTtpZih2ZSl0aHJvdyBuZXcgRXJyb3IoIm11bHRpcGxlIGNhbGxzIHRvICdpbml0aWFsaXplV2ViQXNzZW1ibHkoKScgZGV0ZWN0ZWQuIik7aWYocXQpdGhyb3cgbmV3IEVycm9yKCJwcmV2aW91cyBjYWxsIHRvICdpbml0aWFsaXplV2ViQXNzZW1ibHkoKScgZmFpbGVkLiIpO3ZlPSEwO2xldCB0PWUuaW5pdFRpbWVvdXQscj1lLm51bVRocmVhZHM7aWYoIUNyKCkpdGhyb3cgbmV3IEVycm9yKCJXZWJBc3NlbWJseSBTSU1EIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuIik7bGV0IG49QnIoKTtyPjEmJiFuJiYodHlwZW9mIHNlbGY8InUiJiYhc2VsZi5jcm9zc09yaWdpbklzb2xhdGVkJiZjb25zb2xlLndhcm4oImVudi53YXNtLm51bVRocmVhZHMgaXMgc2V0IHRvICIrcisiLCBidXQgdGhpcyB3aWxsIG5vdCB3b3JrIHVubGVzcyB5b3UgZW5hYmxlIGNyb3NzT3JpZ2luSXNvbGF0ZWQgbW9kZS4gU2VlIGh0dHBzOi8vd2ViLmRldi9jcm9zcy1vcmlnaW4taXNvbGF0aW9uLWd1aWRlLyBmb3IgbW9yZSBpbmZvLiIpLGNvbnNvbGUud2FybigiV2ViQXNzZW1ibHkgbXVsdGktdGhyZWFkaW5nIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuIEZhbGxpbmcgYmFjayB0byBzaW5nbGUtdGhyZWFkaW5nLiIpLGUubnVtVGhyZWFkcz1yPTEpO2xldCBvPWUud2FzbVBhdGhzLGE9InN0cmluZyI9PXR5cGVvZiBvP286dm9pZCAwLGk9bz8ubWpzLHM9aT8uaHJlZj8/aSxsPW8/Lndhc20sdT1sPy5ocmVmPz9sLGY9ZS53YXNtQmluYXJ5LFtkLHBdPWF3YWl0IFl0KHMsYSxyPjEpLGM9ITEsaD1bXTtpZih0PjAmJmgucHVzaChuZXcgUHJvbWlzZSgoZT0+e3NldFRpbWVvdXQoKCgpPT57Yz0hMCxlKCk7fSksdCk7fSkpKSxoLnB1c2gobmV3IFByb21pc2UoKChlLHQpPT57bGV0IG49e251bVRocmVhZHM6cn07aWYoZiluLndhc21CaW5hcnk9ZjtlbHNlIGlmKHV8fGEpbi5sb2NhdGVGaWxlPWU9PnU/P2ErZTtlbHNlIGlmKHMmJjAhPT1zLmluZGV4T2YoImJsb2I6Iikpbi5sb2NhdGVGaWxlPWU9Pm5ldyBVUkwoZSxzKS5ocmVmO2Vsc2UgaWYoZCl7bGV0IGU9UGUoKTtlJiYobi5sb2NhdGVGaWxlPXQ9PmUrdCk7fXAobikudGhlbigodD0+e3ZlPSExLEtlPSEwLFplPXQsZSgpLGQmJlVSTC5yZXZva2VPYmplY3RVUkwoZCk7fSksKGU9Pnt2ZT0hMSxxdD0hMCx0KGUpO30pKTt9KSkpLGF3YWl0IFByb21pc2UucmFjZShoKSxjKXRocm93IG5ldyBFcnJvcihgV2ViQXNzZW1ibHkgYmFja2VuZCBpbml0aWFsaXppbmcgZmFpbGVkIGR1ZSB0byB0aW1lb3V0OiAke3R9bXNgKX0seD0oKT0+e2lmKEtlJiZaZSlyZXR1cm4gWmU7dGhyb3cgbmV3IEVycm9yKCJXZWJBc3NlbWJseSBpcyBub3QgaW5pdGlhbGl6ZWQgeWV0LiIpfTt9KSksQmU9VCgoKCk9PntKKCksTD0oZSx0KT0+e2xldCByPXgoKSxuPXIubGVuZ3RoQnl0ZXNVVEY4KGUpKzEsbz1yLl9tYWxsb2Mobik7cmV0dXJuIHIuc3RyaW5nVG9VVEY4KGUsbyxuKSx0LnB1c2gobyksb30sZmU9KGUsdCxyLG4pPT57aWYoIm9iamVjdCI9PXR5cGVvZiBlJiZudWxsIT09ZSl7aWYoci5oYXMoZSkpdGhyb3cgbmV3IEVycm9yKCJDaXJjdWxhciByZWZlcmVuY2UgaW4gb3B0aW9ucyIpO3IuYWRkKGUpO31PYmplY3QuZW50cmllcyhlKS5mb3JFYWNoKCgoW2Usb10pPT57bGV0IGE9dD90K2U6ZTtpZigib2JqZWN0Ij09dHlwZW9mIG8pZmUobyxhKyIuIixyLG4pO2Vsc2UgaWYoInN0cmluZyI9PXR5cGVvZiBvfHwibnVtYmVyIj09dHlwZW9mIG8pbihhLG8udG9TdHJpbmcoKSk7ZWxzZSB7aWYoImJvb2xlYW4iIT10eXBlb2Ygbyl0aHJvdyBuZXcgRXJyb3IoIkNhbid0IGhhbmRsZSBleHRyYSBjb25maWcgdHlwZTogIit0eXBlb2Ygbyk7bihhLG8/IjEiOiIwIik7fX0pKTt9LFM9ZT0+e2xldCB0PXgoKSxyPXQuc3RhY2tTYXZlKCk7dHJ5e2xldCByPXQuUFRSX1NJWkUsbj10LnN0YWNrQWxsb2MoMipyKTt0Ll9PcnRHZXRMYXN0RXJyb3IobixuK3IpO2xldCBvPU51bWJlcih0LmdldFZhbHVlKG4sND09PXI/ImkzMiI6Imk2NCIpKSxhPXQuZ2V0VmFsdWUobityLCIqIiksaT1hP3QuVVRGOFRvU3RyaW5nKGEpOiIiO3Rocm93IG5ldyBFcnJvcihgJHtlfSBFUlJPUl9DT0RFOiAke299LCBFUlJPUl9NRVNTQUdFOiAke2l9YCl9ZmluYWxseXt0LnN0YWNrUmVzdG9yZShyKTt9fTt9KSksWHQ9VCgoKCk9PntKKCksQmUoKSxKdD1lPT57bGV0IHQ9eCgpLHI9MCxuPVtdLG89ZXx8e307dHJ5e2lmKHZvaWQgMD09PWU/LmxvZ1NldmVyaXR5TGV2ZWwpby5sb2dTZXZlcml0eUxldmVsPTI7ZWxzZSBpZigibnVtYmVyIiE9dHlwZW9mIGUubG9nU2V2ZXJpdHlMZXZlbHx8IU51bWJlci5pc0ludGVnZXIoZS5sb2dTZXZlcml0eUxldmVsKXx8ZS5sb2dTZXZlcml0eUxldmVsPDB8fGUubG9nU2V2ZXJpdHlMZXZlbD40KXRocm93IG5ldyBFcnJvcihgbG9nIHNlcnZlcml0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7ZS5sb2dTZXZlcml0eUxldmVsfWApO2lmKHZvaWQgMD09PWU/LmxvZ1ZlcmJvc2l0eUxldmVsKW8ubG9nVmVyYm9zaXR5TGV2ZWw9MDtlbHNlIGlmKCJudW1iZXIiIT10eXBlb2YgZS5sb2dWZXJib3NpdHlMZXZlbHx8IU51bWJlci5pc0ludGVnZXIoZS5sb2dWZXJib3NpdHlMZXZlbCkpdGhyb3cgbmV3IEVycm9yKGBsb2cgdmVyYm9zaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtlLmxvZ1ZlcmJvc2l0eUxldmVsfWApO3ZvaWQgMD09PWU/LnRlcm1pbmF0ZSYmKG8udGVybWluYXRlPSExKTtsZXQgYT0wO3JldHVybiB2b2lkIDAhPT1lPy50YWcmJihhPUwoZS50YWcsbikpLHI9dC5fT3J0Q3JlYXRlUnVuT3B0aW9ucyhvLmxvZ1NldmVyaXR5TGV2ZWwsby5sb2dWZXJib3NpdHlMZXZlbCwhIW8udGVybWluYXRlLGEpLDA9PT1yJiZTKCJDYW4ndCBjcmVhdGUgcnVuIG9wdGlvbnMuIiksdm9pZCAwIT09ZT8uZXh0cmEmJmZlKGUuZXh0cmEsIiIsbmV3IFdlYWtTZXQsKChlLG8pPT57bGV0IGE9TChlLG4pLGk9TChvLG4pOzAhPT10Ll9PcnRBZGRSdW5Db25maWdFbnRyeShyLGEsaSkmJlMoYENhbid0IHNldCBhIHJ1biBjb25maWcgZW50cnk6ICR7ZX0gLSAke299LmApO30pKSxbcixuXX1jYXRjaChlKXt0aHJvdyAwIT09ciYmdC5fT3J0UmVsZWFzZVJ1bk9wdGlvbnMociksbi5mb3JFYWNoKChlPT50Ll9mcmVlKGUpKSksZX19O30pKSxLdD1UKCgoKT0+e0ooKSxCZSgpLFVyPWU9Pntzd2l0Y2goZSl7Y2FzZSJkaXNhYmxlZCI6cmV0dXJuIDA7Y2FzZSJiYXNpYyI6cmV0dXJuIDE7Y2FzZSJleHRlbmRlZCI6cmV0dXJuIDI7Y2FzZSJhbGwiOnJldHVybiA5OTtkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZ3JhcGggb3B0aW1pemF0aW9uIGxldmVsOiAke2V9YCl9fSxfcj1lPT57c3dpdGNoKGUpe2Nhc2Uic2VxdWVudGlhbCI6cmV0dXJuIDA7Y2FzZSJwYXJhbGxlbCI6cmV0dXJuIDE7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGV4ZWN1dGlvbiBtb2RlOiAke2V9YCl9fSxNcj1lPT57ZS5leHRyYXx8KGUuZXh0cmE9e30pLGUuZXh0cmEuc2Vzc2lvbnx8KGUuZXh0cmEuc2Vzc2lvbj17fSk7bGV0IHQ9ZS5leHRyYS5zZXNzaW9uO3QudXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseXx8KHQudXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseT0iMSIpLGUuZXhlY3V0aW9uUHJvdmlkZXJzJiZlLmV4ZWN1dGlvblByb3ZpZGVycy5zb21lKChlPT4id2ViZ3B1Ij09PSgic3RyaW5nIj09dHlwZW9mIGU/ZTplLm5hbWUpKSkmJihlLmVuYWJsZU1lbVBhdHRlcm49ITEpO30sRHI9KGUsdCxyKT0+e2ZvcihsZXQgbiBvZiB0KXtsZXQgdD0ic3RyaW5nIj09dHlwZW9mIG4/bjpuLm5hbWU7c3dpdGNoKHQpe2Nhc2Uid2Vibm4iOmlmKHQ9IldFQk5OIiwic3RyaW5nIiE9dHlwZW9mIG4pe2xldCB0PW4/LmRldmljZVR5cGU7aWYodCl7bGV0IG49TCgiZGV2aWNlVHlwZSIsciksbz1MKHQscik7MCE9PXgoKS5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5KGUsbixvKSYmUyhgQ2FuJ3Qgc2V0IGEgc2Vzc2lvbiBjb25maWcgZW50cnk6ICdkZXZpY2VUeXBlJyAtICR7dH0uYCk7fX1icmVhaztjYXNlIndlYmdwdSI6aWYodD0iSlMiLCJzdHJpbmciIT10eXBlb2Ygbil7bGV0IHQ9bjtpZih0Py5wcmVmZXJyZWRMYXlvdXQpe2lmKCJOQ0hXIiE9PXQucHJlZmVycmVkTGF5b3V0JiYiTkhXQyIhPT10LnByZWZlcnJlZExheW91dCl0aHJvdyBuZXcgRXJyb3IoYHByZWZlcnJlZExheW91dCBtdXN0IGJlIGVpdGhlciAnTkNIVycgb3IgJ05IV0MnOiAke3QucHJlZmVycmVkTGF5b3V0fWApO2xldCBuPUwoInByZWZlcnJlZExheW91dCIsciksbz1MKHQucHJlZmVycmVkTGF5b3V0LHIpOzAhPT14KCkuX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShlLG4sbykmJlMoYENhbid0IHNldCBhIHNlc3Npb24gY29uZmlnIGVudHJ5OiAncHJlZmVycmVkTGF5b3V0JyAtICR7dC5wcmVmZXJyZWRMYXlvdXR9LmApO319YnJlYWs7Y2FzZSJ3YXNtIjpjYXNlImNwdSI6Y29udGludWU7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYG5vdCBzdXBwb3J0ZWQgZXhlY3V0aW9uIHByb3ZpZGVyOiAke3R9YCl9bGV0IG89TCh0LHIpOzAhPT14KCkuX09ydEFwcGVuZEV4ZWN1dGlvblByb3ZpZGVyKGUsbykmJlMoYENhbid0IGFwcGVuZCBleGVjdXRpb24gcHJvdmlkZXI6ICR7dH0uYCk7fX0sWnQ9ZT0+e2xldCB0PXgoKSxyPTAsbj1bXSxvPWV8fHt9O01yKG8pO3RyeXtsZXQgZT1VcihvLmdyYXBoT3B0aW1pemF0aW9uTGV2ZWw/PyJhbGwiKSxhPV9yKG8uZXhlY3V0aW9uTW9kZT8/InNlcXVlbnRpYWwiKSxpPSJzdHJpbmciPT10eXBlb2Ygby5sb2dJZD9MKG8ubG9nSWQsbik6MCxzPW8ubG9nU2V2ZXJpdHlMZXZlbD8/MjtpZighTnVtYmVyLmlzSW50ZWdlcihzKXx8czwwfHxzPjQpdGhyb3cgbmV3IEVycm9yKGBsb2cgc2VydmVyaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtzfWApO2xldCBsPW8ubG9nVmVyYm9zaXR5TGV2ZWw/PzA7aWYoIU51bWJlci5pc0ludGVnZXIobCl8fGw8MHx8bD40KXRocm93IG5ldyBFcnJvcihgbG9nIHZlcmJvc2l0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7bH1gKTtsZXQgdT0ic3RyaW5nIj09dHlwZW9mIG8ub3B0aW1pemVkTW9kZWxGaWxlUGF0aD9MKG8ub3B0aW1pemVkTW9kZWxGaWxlUGF0aCxuKTowO2lmKHI9dC5fT3J0Q3JlYXRlU2Vzc2lvbk9wdGlvbnMoZSwhIW8uZW5hYmxlQ3B1TWVtQXJlbmEsISFvLmVuYWJsZU1lbVBhdHRlcm4sYSwhIW8uZW5hYmxlUHJvZmlsaW5nLDAsaSxzLGwsdSksMD09PXImJlMoIkNhbid0IGNyZWF0ZSBzZXNzaW9uIG9wdGlvbnMuIiksby5leGVjdXRpb25Qcm92aWRlcnMmJkRyKHIsby5leGVjdXRpb25Qcm92aWRlcnMsbiksdm9pZCAwIT09by5lbmFibGVHcmFwaENhcHR1cmUpe2lmKCJib29sZWFuIiE9dHlwZW9mIG8uZW5hYmxlR3JhcGhDYXB0dXJlKXRocm93IG5ldyBFcnJvcihgZW5hYmxlR3JhcGhDYXB0dXJlIG11c3QgYmUgYSBib29sZWFuIHZhbHVlOiAke28uZW5hYmxlR3JhcGhDYXB0dXJlfWApO2xldCBlPUwoImVuYWJsZUdyYXBoQ2FwdHVyZSIsbiksYT1MKG8uZW5hYmxlR3JhcGhDYXB0dXJlLnRvU3RyaW5nKCksbik7MCE9PXQuX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShyLGUsYSkmJlMoYENhbid0IHNldCBhIHNlc3Npb24gY29uZmlnIGVudHJ5OiAnZW5hYmxlR3JhcGhDYXB0dXJlJyAtICR7by5lbmFibGVHcmFwaENhcHR1cmV9LmApO31pZihvLmZyZWVEaW1lbnNpb25PdmVycmlkZXMpZm9yKGxldFtlLGFdb2YgT2JqZWN0LmVudHJpZXMoby5mcmVlRGltZW5zaW9uT3ZlcnJpZGVzKSl7aWYoInN0cmluZyIhPXR5cGVvZiBlKXRocm93IG5ldyBFcnJvcihgZnJlZSBkaW1lbnNpb24gb3ZlcnJpZGUgbmFtZSBtdXN0IGJlIGEgc3RyaW5nOiAke2V9YCk7aWYoIm51bWJlciIhPXR5cGVvZiBhfHwhTnVtYmVyLmlzSW50ZWdlcihhKXx8YTwwKXRocm93IG5ldyBFcnJvcihgZnJlZSBkaW1lbnNpb24gb3ZlcnJpZGUgdmFsdWUgbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyOiAke2F9YCk7bGV0IG89TChlLG4pOzAhPT10Ll9PcnRBZGRGcmVlRGltZW5zaW9uT3ZlcnJpZGUocixvLGEpJiZTKGBDYW4ndCBzZXQgYSBmcmVlIGRpbWVuc2lvbiBvdmVycmlkZTogJHtlfSAtICR7YX0uYCk7fXJldHVybiB2b2lkIDAhPT1vLmV4dHJhJiZmZShvLmV4dHJhLCIiLG5ldyBXZWFrU2V0LCgoZSxvKT0+e2xldCBhPUwoZSxuKSxpPUwobyxuKTswIT09dC5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5KHIsYSxpKSYmUyhgQ2FuJ3Qgc2V0IGEgc2Vzc2lvbiBjb25maWcgZW50cnk6ICR7ZX0gLSAke299LmApO30pKSxbcixuXX1jYXRjaChlKXt0aHJvdyAwIT09ciYmMCE9PXQuX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucyhyKSYmUygiQ2FuJ3QgcmVsZWFzZSBzZXNzaW9uIG9wdGlvbnMuIiksbi5mb3JFYWNoKChlPT50Ll9mcmVlKGUpKSksZX19O30pKSxRZT1UKCgoKT0+e2VlPWU9Pntzd2l0Y2goZSl7Y2FzZSJpbnQ4IjpyZXR1cm4gMztjYXNlInVpbnQ4IjpyZXR1cm4gMjtjYXNlImJvb2wiOnJldHVybiA5O2Nhc2UiaW50MTYiOnJldHVybiA1O2Nhc2UidWludDE2IjpyZXR1cm4gNDtjYXNlImludDMyIjpyZXR1cm4gNjtjYXNlInVpbnQzMiI6cmV0dXJuIDEyO2Nhc2UiZmxvYXQxNiI6cmV0dXJuIDEwO2Nhc2UiZmxvYXQzMiI6cmV0dXJuIDE7Y2FzZSJmbG9hdDY0IjpyZXR1cm4gMTE7Y2FzZSJzdHJpbmciOnJldHVybiA4O2Nhc2UiaW50NjQiOnJldHVybiA3O2Nhc2UidWludDY0IjpyZXR1cm4gMTM7Y2FzZSJpbnQ0IjpyZXR1cm4gMjI7Y2FzZSJ1aW50NCI6cmV0dXJuIDIxO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZX1gKX19LFF0PWU9Pntzd2l0Y2goZSl7Y2FzZSAzOnJldHVybiAiaW50OCI7Y2FzZSAyOnJldHVybiAidWludDgiO2Nhc2UgOTpyZXR1cm4gImJvb2wiO2Nhc2UgNTpyZXR1cm4gImludDE2IjtjYXNlIDQ6cmV0dXJuICJ1aW50MTYiO2Nhc2UgNjpyZXR1cm4gImludDMyIjtjYXNlIDEyOnJldHVybiAidWludDMyIjtjYXNlIDEwOnJldHVybiAiZmxvYXQxNiI7Y2FzZSAxOnJldHVybiAiZmxvYXQzMiI7Y2FzZSAxMTpyZXR1cm4gImZsb2F0NjQiO2Nhc2UgODpyZXR1cm4gInN0cmluZyI7Y2FzZSA3OnJldHVybiAiaW50NjQiO2Nhc2UgMTM6cmV0dXJuICJ1aW50NjQiO2Nhc2UgMjI6cmV0dXJuICJpbnQ0IjtjYXNlIDIxOnJldHVybiAidWludDQiO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZX1gKX19LHRlPShlLHQpPT57bGV0IHI9Wy0xLDQsMSwxLDIsMiw0LDgsLTEsMSwyLDgsNCw4LC0xLC0xLC0xLC0xLC0xLC0xLC0xLC41LC41XVtlXSxuPSJudW1iZXIiPT10eXBlb2YgdD90OnQucmVkdWNlKCgoZSx0KT0+ZSp0KSwxKTtyZXR1cm4gcj4wP01hdGguY2VpbChuKnIpOnZvaWQgMH0sZXI9ZT0+e3N3aXRjaChlKXtjYXNlImZsb2F0MTYiOnJldHVybiB0eXBlb2YgRmxvYXQxNkFycmF5PCJ1IiYmRmxvYXQxNkFycmF5LmZyb20/RmxvYXQxNkFycmF5OlVpbnQxNkFycmF5O2Nhc2UiZmxvYXQzMiI6cmV0dXJuIEZsb2F0MzJBcnJheTtjYXNlInVpbnQ4IjpjYXNlImJvb2wiOnJldHVybiBVaW50OEFycmF5O2Nhc2UiaW50OCI6cmV0dXJuIEludDhBcnJheTtjYXNlInVpbnQxNiI6cmV0dXJuIFVpbnQxNkFycmF5O2Nhc2UiaW50MTYiOnJldHVybiBJbnQxNkFycmF5O2Nhc2UiaW50MzIiOnJldHVybiBJbnQzMkFycmF5O2Nhc2UiZmxvYXQ2NCI6cmV0dXJuIEZsb2F0NjRBcnJheTtjYXNlInVpbnQzMiI6cmV0dXJuIFVpbnQzMkFycmF5O2Nhc2UiaW50NjQiOnJldHVybiBCaWdJbnQ2NEFycmF5O2Nhc2UidWludDY0IjpyZXR1cm4gQmlnVWludDY0QXJyYXk7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGU6ICR7ZX1gKX19LHRyPWU9Pntzd2l0Y2goZSl7Y2FzZSJ2ZXJib3NlIjpyZXR1cm4gMDtjYXNlImluZm8iOnJldHVybiAxO2Nhc2Uid2FybmluZyI6cmV0dXJuIDI7Y2FzZSJlcnJvciI6cmV0dXJuIDM7Y2FzZSJmYXRhbCI6cmV0dXJuIDQ7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGxvZ2dpbmcgbGV2ZWw6ICR7ZX1gKX19LENlPWU9PiJmbG9hdDMyIj09PWV8fCJmbG9hdDE2Ij09PWV8fCJpbnQzMiI9PT1lfHwiaW50NjQiPT09ZXx8InVpbnQzMiI9PT1lfHwidWludDgiPT09ZXx8ImJvb2wiPT09ZXx8InVpbnQ0Ij09PWV8fCJpbnQ0Ij09PWUsVWU9ZT0+ImZsb2F0MzIiPT09ZXx8ImZsb2F0MTYiPT09ZXx8ImludDMyIj09PWV8fCJpbnQ2NCI9PT1lfHwidWludDMyIj09PWV8fCJ1aW50NjQiPT09ZXx8ImludDgiPT09ZXx8InVpbnQ4Ij09PWV8fCJib29sIj09PWV8fCJ1aW50NCI9PT1lfHwiaW50NCI9PT1lLHJyPWU9Pntzd2l0Y2goZSl7Y2FzZSJub25lIjpyZXR1cm4gMDtjYXNlImNwdSI6cmV0dXJuIDE7Y2FzZSJjcHUtcGlubmVkIjpyZXR1cm4gMjtjYXNlInRleHR1cmUiOnJldHVybiAzO2Nhc2UiZ3B1LWJ1ZmZlciI6cmV0dXJuIDQ7Y2FzZSJtbC10ZW5zb3IiOnJldHVybiA1O2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIGxvY2F0aW9uOiAke2V9YCl9fTt9KSksZXQ9VCgoKCk9PntiZSgpLGNlPWFzeW5jIGU9PntpZigic3RyaW5nIj09dHlwZW9mIGUpe3tsZXQgdD1hd2FpdCBmZXRjaChlKTtpZighdC5vayl0aHJvdyBuZXcgRXJyb3IoYGZhaWxlZCB0byBsb2FkIGV4dGVybmFsIGRhdGEgZmlsZTogJHtlfWApO2xldCByPXQuaGVhZGVycy5nZXQoIkNvbnRlbnQtTGVuZ3RoIiksbj1yP3BhcnNlSW50KHIsMTApOjA7aWYobjwxMDczNzQxODI0KXJldHVybiBuZXcgVWludDhBcnJheShhd2FpdCB0LmFycmF5QnVmZmVyKCkpO3tpZighdC5ib2R5KXRocm93IG5ldyBFcnJvcihgZmFpbGVkIHRvIGxvYWQgZXh0ZXJuYWwgZGF0YSBmaWxlOiAke2V9LCBubyByZXNwb25zZSBib2R5LmApO2xldCByLG89dC5ib2R5LmdldFJlYWRlcigpO3RyeXtyPW5ldyBBcnJheUJ1ZmZlcihuKTt9Y2F0Y2goZSl7aWYoIShlIGluc3RhbmNlb2YgUmFuZ2VFcnJvcikpdGhyb3cgZTt7bGV0IGU9TWF0aC5jZWlsKG4vNjU1MzYpO3I9bmV3IFdlYkFzc2VtYmx5Lk1lbW9yeSh7aW5pdGlhbDplLG1heGltdW06ZX0pLmJ1ZmZlcjt9fWxldCBhPTA7Zm9yKDs7KXtsZXR7ZG9uZTplLHZhbHVlOnR9PWF3YWl0IG8ucmVhZCgpO2lmKGUpYnJlYWs7bGV0IG49dC5ieXRlTGVuZ3RoO25ldyBVaW50OEFycmF5KHIsYSxuKS5zZXQodCksYSs9bjt9cmV0dXJuIG5ldyBVaW50OEFycmF5KHIsMCxuKX19fXJldHVybiBlIGluc3RhbmNlb2YgQmxvYj9uZXcgVWludDhBcnJheShhd2FpdCBlLmFycmF5QnVmZmVyKCkpOmUgaW5zdGFuY2VvZiBVaW50OEFycmF5P2U6bmV3IFVpbnQ4QXJyYXkoZSl9O30pKSxKZT1UKCgoKT0+e1h0KCksS3QoKSxRZSgpLEooKSxCZSgpLGV0KCksUnI9KGUsdCk9PnswIT09eCgpLl9PcnRJbml0KGUsdCkmJlMoIkNhbid0IGluaXRpYWxpemUgb25ueHJ1bnRpbWUuIik7fSxUZT1hc3luYyBlPT57UnIoZS53YXNtLm51bVRocmVhZHMsdHIoZS5sb2dMZXZlbCkpO30sU2U9YXN5bmMoZSx0KT0+e30scmU9bmV3IE1hcCxGcj1lPT57bGV0IHQ9eCgpLHI9dC5zdGFja1NhdmUoKTt0cnl7bGV0IHI9dC5QVFJfU0laRSxuPXQuc3RhY2tBbGxvYygyKnIpOzAhPT10Ll9PcnRHZXRJbnB1dE91dHB1dENvdW50KGUsbixuK3IpJiZTKCJDYW4ndCBnZXQgc2Vzc2lvbiBpbnB1dC9vdXRwdXQgY291bnQuIik7bGV0IG89ND09PXI/ImkzMiI6Imk2NCI7cmV0dXJuIFtOdW1iZXIodC5nZXRWYWx1ZShuLG8pKSxOdW1iZXIodC5nZXRWYWx1ZShuK3IsbykpXX1maW5hbGx5e3Quc3RhY2tSZXN0b3JlKHIpO319LHVlPWU9PntsZXQgdD14KCkscj10Ll9tYWxsb2MoZS5ieXRlTGVuZ3RoKTtpZigwPT09cil0aHJvdyBuZXcgRXJyb3IoYENhbid0IGNyZWF0ZSBhIHNlc3Npb24uIGZhaWxlZCB0byBhbGxvY2F0ZSBhIGJ1ZmZlciBvZiBzaXplICR7ZS5ieXRlTGVuZ3RofS5gKTtyZXR1cm4gdC5IRUFQVTguc2V0KGUsciksW3IsZS5ieXRlTGVuZ3RoXX0sQWU9YXN5bmMoZSx0KT0+e2xldCByLG4sbz14KCk7QXJyYXkuaXNBcnJheShlKT9bcixuXT1lOmUuYnVmZmVyPT09by5IRUFQVTguYnVmZmVyP1tyLG5dPVtlLmJ5dGVPZmZzZXQsZS5ieXRlTGVuZ3RoXTpbcixuXT11ZShlKTtsZXQgYT0wLGk9MCxzPVtdLGw9W10sdT1bXTt0cnl7aWYoW2ksc109WnQodCksdD8uZXh0ZXJuYWxEYXRhJiZvLm1vdW50RXh0ZXJuYWxEYXRhKXtsZXQgZT1bXTtmb3IobGV0IHIgb2YgdC5leHRlcm5hbERhdGEpe2xldCB0PSJzdHJpbmciPT10eXBlb2Ygcj9yOnIucGF0aDtlLnB1c2goY2UoInN0cmluZyI9PXR5cGVvZiByP3I6ci5kYXRhKS50aGVuKChlPT57by5tb3VudEV4dGVybmFsRGF0YSh0LGUpO30pKSk7fWF3YWl0IFByb21pc2UuYWxsKGUpO31mb3IobGV0IGUgb2YgdD8uZXhlY3V0aW9uUHJvdmlkZXJzPz9bXSlpZigid2Vibm4iPT09KCJzdHJpbmciPT10eXBlb2YgZT9lOmUubmFtZSkpe2lmKG8uc2hvdWxkVHJhbnNmZXJUb01MVGVuc29yPSExLCJzdHJpbmciIT10eXBlb2YgZSl7bGV0IHQ9ZSxyPXQ/LmNvbnRleHQsbj10Py5ncHVEZXZpY2UsYT10Py5kZXZpY2VUeXBlLGk9dD8ucG93ZXJQcmVmZXJlbmNlO28uY3VycmVudENvbnRleHQ9cnx8KG4/YXdhaXQgby5qc2VwQ3JlYXRlTUxDb250ZXh0KG4pOmF3YWl0IG8uanNlcENyZWF0ZU1MQ29udGV4dCh7ZGV2aWNlVHlwZTphLHBvd2VyUHJlZmVyZW5jZTppfSkpO31lbHNlIG8uY3VycmVudENvbnRleHQ9YXdhaXQgby5qc2VwQ3JlYXRlTUxDb250ZXh0KCk7YnJlYWt9YT1hd2FpdCBvLl9PcnRDcmVhdGVTZXNzaW9uKHIsbixpKSwwPT09YSYmUygiQ2FuJ3QgY3JlYXRlIGEgc2Vzc2lvbi4iKSxvLmpzZXBPbkNyZWF0ZVNlc3Npb24/LigpLG8uY3VycmVudENvbnRleHQmJihvLmpzZXBSZWdpc3Rlck1MQ29udGV4dChhLG8uY3VycmVudENvbnRleHQpLG8uY3VycmVudENvbnRleHQ9dm9pZCAwLG8uc2hvdWxkVHJhbnNmZXJUb01MVGVuc29yPSEwKTtsZXRbZSxmXT1GcihhKSxkPSEhdD8uZW5hYmxlR3JhcGhDYXB0dXJlLHA9W10sYz1bXTtmb3IobGV0IHQ9MDt0PGU7dCsrKXtsZXQgZT1vLl9PcnRHZXRJbnB1dE5hbWUoYSx0KTswPT09ZSYmUygiQ2FuJ3QgZ2V0IGFuIGlucHV0IG5hbWUuIiksbC5wdXNoKGUpLHAucHVzaChvLlVURjhUb1N0cmluZyhlKSk7fWZvcihsZXQgZT0wO2U8ZjtlKyspe2xldCB0PW8uX09ydEdldE91dHB1dE5hbWUoYSxlKTswPT09dCYmUygiQ2FuJ3QgZ2V0IGFuIG91dHB1dCBuYW1lLiIpLHUucHVzaCh0KTtsZXQgcj1vLlVURjhUb1N0cmluZyh0KTtjLnB1c2gocik7fXJldHVybiByZS5zZXQoYSxbYSxsLHUsbnVsbCxkLCExXSksW2EscCxjXX1jYXRjaChlKXt0aHJvdyBsLmZvckVhY2goKGU9Pm8uX09ydEZyZWUoZSkpKSx1LmZvckVhY2goKGU9Pm8uX09ydEZyZWUoZSkpKSwwIT09YSYmMCE9PW8uX09ydFJlbGVhc2VTZXNzaW9uKGEpJiZTKCJDYW4ndCByZWxlYXNlIHNlc3Npb24uIiksZX1maW5hbGx5e28uX2ZyZWUociksMCE9PWkmJjAhPT1vLl9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnMoaSkmJlMoIkNhbid0IHJlbGVhc2Ugc2Vzc2lvbiBvcHRpb25zLiIpLHMuZm9yRWFjaCgoZT0+by5fZnJlZShlKSkpLG8udW5tb3VudEV4dGVybmFsRGF0YT8uKCk7fX0sT2U9ZT0+e2xldCB0PXgoKSxyPXJlLmdldChlKTtpZighcil0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCByZWxlYXNlIHNlc3Npb24uIGludmFsaWQgc2Vzc2lvbiBpZDogJHtlfWApO2xldFtuLG8sYSxpLHNdPXI7aSYmKHMmJjAhPT10Ll9PcnRDbGVhckJvdW5kT3V0cHV0cyhpLmhhbmRsZSkmJlMoIkNhbid0IGNsZWFyIGJvdW5kIG91dHB1dHMuIiksMCE9PXQuX09ydFJlbGVhc2VCaW5kaW5nKGkuaGFuZGxlKSYmUygiQ2FuJ3QgcmVsZWFzZSBJTyBiaW5kaW5nLiIpKSx0LmpzZXBPblJlbGVhc2VTZXNzaW9uPy4oZSksby5mb3JFYWNoKChlPT50Ll9PcnRGcmVlKGUpKSksYS5mb3JFYWNoKChlPT50Ll9PcnRGcmVlKGUpKSksMCE9PXQuX09ydFJlbGVhc2VTZXNzaW9uKG4pJiZTKCJDYW4ndCByZWxlYXNlIHNlc3Npb24uIikscmUuZGVsZXRlKGUpO30sbnI9YXN5bmMoZSx0LHIsbixvLGE9ITEpPT57aWYoIWUpcmV0dXJuIHZvaWQgdC5wdXNoKDApO2xldCBpLHMsbD14KCksdT1sLlBUUl9TSVpFLGY9ZVswXSxkPWVbMV0scD1lWzNdLGM9cDtpZigic3RyaW5nIj09PWYmJigiZ3B1LWJ1ZmZlciI9PT1wfHwibWwtdGVuc29yIj09PXApKXRocm93IG5ldyBFcnJvcigiU3RyaW5nIHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkIG9uIEdQVS4iKTtpZihhJiYiZ3B1LWJ1ZmZlciIhPT1wKXRocm93IG5ldyBFcnJvcihgRXh0ZXJuYWwgYnVmZmVyIG11c3QgYmUgcHJvdmlkZWQgZm9yIGlucHV0L291dHB1dCBpbmRleCAke299IHdoZW4gZW5hYmxlR3JhcGhDYXB0dXJlIGlzIHRydWUuYCk7aWYoImdwdS1idWZmZXIiPT09cCl7bGV0IHQ9ZVsyXS5ncHVCdWZmZXI7cz10ZShlZShmKSxkKTtsZXQgcj1sLmpzZXBSZWdpc3RlckJ1ZmZlcjtpZighcil0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiAiZ3B1LWJ1ZmZlciIgaXMgbm90IHN1cHBvcnRlZCB3aXRob3V0IHVzaW5nIFdlYkdQVS4nKTtpPXIobixvLHQscyk7fWVsc2UgaWYoIm1sLXRlbnNvciI9PT1wKXtsZXQgdD1lWzJdLm1sVGVuc29yO3M9dGUoZWUoZiksZCk7bGV0IHI9bC5qc2VwUmVnaXN0ZXJNTFRlbnNvcjtpZighcil0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiAibWwtdGVuc29yIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViTk4uJyk7aT1yKG4sdCxlZShmKSxkKTt9ZWxzZSB7bGV0IHQ9ZVsyXTtpZihBcnJheS5pc0FycmF5KHQpKXtzPXUqdC5sZW5ndGgsaT1sLl9tYWxsb2Mocyksci5wdXNoKGkpO2ZvcihsZXQgZT0wO2U8dC5sZW5ndGg7ZSsrKXtpZigic3RyaW5nIiE9dHlwZW9mIHRbZV0pdGhyb3cgbmV3IFR5cGVFcnJvcihgdGVuc29yIGRhdGEgYXQgaW5kZXggJHtlfSBpcyBub3QgYSBzdHJpbmdgKTtsLnNldFZhbHVlKGkrZSp1LEwodFtlXSxyKSwiKiIpO319ZWxzZSB7bGV0IGU9bC5qc2VwSXNHcmFwaElucHV0O2lmKCJzdHJpbmciIT09ZiYmZSl7bGV0IGE9bC5fT3J0R2V0SW5wdXROYW1lKG4sbyk7aWYoZShuLGwuVVRGOFRvU3RyaW5nKGEpKSl7bGV0IGU9ZWUoZik7cz10ZShlLGQpLGM9Im1sLXRlbnNvciI7bGV0IHI9bC5qc2VwQ3JlYXRlVGVtcG9yYXJ5VGVuc29yLG89bC5qc2VwVXBsb2FkVGVuc29yO2lmKCFyfHwhbyl0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiAibWwtdGVuc29yIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViTk4uJyk7bGV0IGE9YXdhaXQgcihuLGUsZCk7byhhLG5ldyBVaW50OEFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0LmJ5dGVMZW5ndGgpKSxpPWE7fWVsc2Ugcz10LmJ5dGVMZW5ndGgsaT1sLl9tYWxsb2Mocyksci5wdXNoKGkpLGwuSEVBUFU4LnNldChuZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQscyksaSk7fWVsc2Ugcz10LmJ5dGVMZW5ndGgsaT1sLl9tYWxsb2Mocyksci5wdXNoKGkpLGwuSEVBUFU4LnNldChuZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQscyksaSk7fX1sZXQgaD1sLnN0YWNrU2F2ZSgpLHc9bC5zdGFja0FsbG9jKDQqZC5sZW5ndGgpO3RyeXtkLmZvckVhY2goKChlLHQpPT5sLnNldFZhbHVlKHcrdCp1LGUsND09PXU/ImkzMiI6Imk2NCIpKSk7bGV0IGU9bC5fT3J0Q3JlYXRlVGVuc29yKGVlKGYpLGkscyx3LGQubGVuZ3RoLHJyKGMpKTswPT09ZSYmUyhgQ2FuJ3QgY3JlYXRlIHRlbnNvciBmb3IgaW5wdXQvb3V0cHV0LiBzZXNzaW9uPSR7bn0sIGluZGV4PSR7b30uYCksdC5wdXNoKGUpO31maW5hbGx5e2wuc3RhY2tSZXN0b3JlKGgpO319LHhlPWFzeW5jKGUsdCxyLG4sbyxhKT0+e2xldCBpPXgoKSxzPWkuUFRSX1NJWkUsbD1yZS5nZXQoZSk7aWYoIWwpdGhyb3cgbmV3IEVycm9yKGBjYW5ub3QgcnVuIGluZmVyZW5jZS4gaW52YWxpZCBzZXNzaW9uIGlkOiAke2V9YCk7bGV0IHU9bFswXSxmPWxbMV0sZD1sWzJdLHA9bFszXSxjPWxbNF0saD0obFs1XSx0Lmxlbmd0aCksdz1uLmxlbmd0aCx5PTAsbT1bXSxnPVtdLGI9W10sdj1bXSxFPWkuc3RhY2tTYXZlKCksVD1pLnN0YWNrQWxsb2MoaCpzKSxBPWkuc3RhY2tBbGxvYyhoKnMpLEw9aS5zdGFja0FsbG9jKHcqcyksQz1pLnN0YWNrQWxsb2ModypzKTt0cnl7W3ksbV09SnQoYSk7Zm9yKGxldCBuPTA7bjxoO24rKylhd2FpdCBucihyW25dLGcsdixlLHRbbl0sYyk7Zm9yKGxldCB0PTA7dDx3O3QrKylhd2FpdCBucihvW3RdLGIsdixlLGgrblt0XSxjKTtmb3IobGV0IGU9MDtlPGg7ZSsrKWkuc2V0VmFsdWUoVCtlKnMsZ1tlXSwiKiIpLGkuc2V0VmFsdWUoQStlKnMsZlt0W2VdXSwiKiIpO2ZvcihsZXQgZT0wO2U8dztlKyspaS5zZXRWYWx1ZShMK2UqcyxiW2VdLCIqIiksaS5zZXRWYWx1ZShDK2UqcyxkW25bZV1dLCIqIik7bGV0IGw7aS5qc2VwT25SdW5TdGFydD8uKHUpLGw9YXdhaXQgaS5fT3J0UnVuKHUsQSxULGgsQyx3LEwseSksMCE9PWwmJlMoImZhaWxlZCB0byBjYWxsIE9ydFJ1bigpLiIpO2xldCBFPVtdO2ZvcihsZXQgdD0wO3Q8dzt0Kyspe2xldCByPU51bWJlcihpLmdldFZhbHVlKEwrdCpzLCIqIikpO2lmKHI9PT1iW3RdKXtFLnB1c2gob1t0XSk7Y29udGludWV9bGV0IGEsbD1pLnN0YWNrU2F2ZSgpLGY9aS5zdGFja0FsbG9jKDQqcyksZD0hMSxjPTA7dHJ5ezAhPT1pLl9PcnRHZXRUZW5zb3JEYXRhKHIsZixmK3MsZisyKnMsZiszKnMpJiZTKGBDYW4ndCBhY2Nlc3Mgb3V0cHV0IHRlbnNvciBkYXRhIG9uIGluZGV4ICR7dH0uYCk7bGV0IG89ND09PXM/ImkzMiI6Imk2NCIsbD1OdW1iZXIoaS5nZXRWYWx1ZShmLG8pKTtjPWkuZ2V0VmFsdWUoZitzLCIqIik7bGV0IHU9aS5nZXRWYWx1ZShmKzIqcywiKiIpLGg9TnVtYmVyKGkuZ2V0VmFsdWUoZiszKnMsbykpLHc9W107Zm9yKGxldCBlPTA7ZTxoO2UrKyl3LnB1c2goTnVtYmVyKGkuZ2V0VmFsdWUodStlKnMsbykpKTswIT09aS5fT3J0RnJlZSh1KSYmUygiQ2FuJ3QgZnJlZSBtZW1vcnkgZm9yIHRlbnNvciBkaW1zLiIpO2xldCB5PXcucmVkdWNlKCgoZSx0KT0+ZSp0KSwxKTthPVF0KGwpO2xldCBtPXA/Lm91dHB1dFByZWZlcnJlZExvY2F0aW9uc1tuW3RdXTtpZigic3RyaW5nIj09PWEpe2lmKCJncHUtYnVmZmVyIj09PW18fCJtbC10ZW5zb3IiPT09bSl0aHJvdyBuZXcgRXJyb3IoIlN0cmluZyB0ZW5zb3IgaXMgbm90IHN1cHBvcnRlZCBvbiBHUFUuIik7bGV0IGU9W107Zm9yKGxldCB0PTA7dDx5O3QrKyl7bGV0IHI9aS5nZXRWYWx1ZShjK3QqcywiKiIpLG49aS5nZXRWYWx1ZShjKyh0KzEpKnMsIioiKSxvPXQ9PT15LTE/dm9pZCAwOm4tcjtlLnB1c2goaS5VVEY4VG9TdHJpbmcocixvKSk7fUUucHVzaChbYSx3LGUsImNwdSJdKTt9ZWxzZSBpZigiZ3B1LWJ1ZmZlciI9PT1tJiZ5PjApe2xldCBlPWkuanNlcEdldEJ1ZmZlcjtpZighZSl0aHJvdyBuZXcgRXJyb3IoJ3ByZWZlcnJlZExvY2F0aW9uICJncHUtYnVmZmVyIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViR1BVLicpO2xldCB0PWUoYyksbj10ZShsLHkpO2lmKHZvaWQgMD09PW58fCFDZShhKSl0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGRhdGEgdHlwZTogJHthfWApO2Q9ITAsRS5wdXNoKFthLHcse2dwdUJ1ZmZlcjp0LGRvd25sb2FkOmkuanNlcENyZWF0ZURvd25sb2FkZXIodCxuLGEpLGRpc3Bvc2U6KCk9PnswIT09aS5fT3J0UmVsZWFzZVRlbnNvcihyKSYmUygiQ2FuJ3QgcmVsZWFzZSB0ZW5zb3IuIik7fX0sImdwdS1idWZmZXIiXSk7fWVsc2UgaWYoIm1sLXRlbnNvciI9PT1tJiZ5PjApe2xldCB0PWkuanNlcEVuc3VyZVRlbnNvcjtpZighdCl0aHJvdyBuZXcgRXJyb3IoJ3ByZWZlcnJlZExvY2F0aW9uICJtbC10ZW5zb3IiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJOTi4nKTtpZih2b2lkIDA9PT10ZShsLHkpfHwhVWUoYSkpdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7YX1gKTtsZXQgbj1hd2FpdCB0KGUsYyxsLHcsITEpO2Q9ITAsRS5wdXNoKFthLHcse21sVGVuc29yOm4sZG93bmxvYWQ6aS5qc2VwQ3JlYXRlTUxUZW5zb3JEb3dubG9hZGVyKGMsYSksZGlzcG9zZTooKT0+e2kuanNlcFJlbGVhc2VUZW5zb3JJZChjKSxpLl9PcnRSZWxlYXNlVGVuc29yKHIpO319LCJtbC10ZW5zb3IiXSk7fWVsc2Uge2xldCBlPW5ldyhlcihhKSkoeSk7bmV3IFVpbnQ4QXJyYXkoZS5idWZmZXIsZS5ieXRlT2Zmc2V0LGUuYnl0ZUxlbmd0aCkuc2V0KGkuSEVBUFU4LnN1YmFycmF5KGMsYytlLmJ5dGVMZW5ndGgpKSxFLnB1c2goW2EsdyxlLCJjcHUiXSk7fX1maW5hbGx5e2kuc3RhY2tSZXN0b3JlKGwpLCJzdHJpbmciPT09YSYmYyYmaS5fZnJlZShjKSxkfHxpLl9PcnRSZWxlYXNlVGVuc29yKHIpLGkuanNlcE9uUnVuRW5kPy4odSk7fX1yZXR1cm4gcCYmIWMmJigwIT09aS5fT3J0Q2xlYXJCb3VuZE91dHB1dHMocC5oYW5kbGUpJiZTKCJDYW4ndCBjbGVhciBib3VuZCBvdXRwdXRzLiIpLHJlLnNldChlLFt1LGYsZCxwLGMsITFdKSksRX1maW5hbGx5e2kuc3RhY2tSZXN0b3JlKEUpLGcuZm9yRWFjaCgoZT0+aS5fT3J0UmVsZWFzZVRlbnNvcihlKSkpLGIuZm9yRWFjaCgoZT0+aS5fT3J0UmVsZWFzZVRlbnNvcihlKSkpLHYuZm9yRWFjaCgoZT0+aS5fZnJlZShlKSkpLDAhPT15JiZpLl9PcnRSZWxlYXNlUnVuT3B0aW9ucyh5KSxtLmZvckVhY2goKGU9PmkuX2ZyZWUoZSkpKTt9fSxMZT1lPT57bGV0IHQ9eCgpLHI9cmUuZ2V0KGUpO2lmKCFyKXRocm93IG5ldyBFcnJvcigiaW52YWxpZCBzZXNzaW9uIGlkIik7bGV0IG49clswXSxvPXQuX09ydEVuZFByb2ZpbGluZyhuKTswPT09byYmUygiQ2FuJ3QgZ2V0IGFuIHByb2ZpbGUgZmlsZSBuYW1lLiIpLHQuX09ydEZyZWUobyk7fSxJZT1lPT57bGV0IHQ9W107Zm9yKGxldCByIG9mIGUpe2xldCBlPXJbMl07IUFycmF5LmlzQXJyYXkoZSkmJiJidWZmZXIiaW4gZSYmdC5wdXNoKGUuYnVmZmVyKTt9cmV0dXJuIHR9O30pKSxudD1UKCgoKT0+e3EoKSxKZSgpLEooKSxnZSgpLFo9KCk9PiEhQS53YXNtLnByb3h5JiZ0eXBlb2YgZG9jdW1lbnQ8InUiLGxlPSExLE1lPSExLERlPSExLHJ0PW5ldyBNYXAsbmU9KGUsdCk9PntsZXQgcj1ydC5nZXQoZSk7cj9yLnB1c2godCk6cnQuc2V0KGUsW3RdKTt9LG9lPSgpPT57aWYobGV8fCFNZXx8RGV8fCFEKXRocm93IG5ldyBFcnJvcigid29ya2VyIG5vdCByZWFkeSIpfSxOcj1lPT57c3dpdGNoKGUuZGF0YS50eXBlKXtjYXNlImluaXQtd2FzbSI6bGU9ITEsZS5kYXRhLmVycj8oRGU9ITAsdHRbMV0oZS5kYXRhLmVycikpOihNZT0hMCx0dFswXSgpKSxfZSYmKFVSTC5yZXZva2VPYmplY3RVUkwoX2UpLF9lPXZvaWQgMCk7YnJlYWs7Y2FzZSJpbml0LWVwIjpjYXNlImNvcHktZnJvbSI6Y2FzZSJjcmVhdGUiOmNhc2UicmVsZWFzZSI6Y2FzZSJydW4iOmNhc2UiZW5kLXByb2ZpbGluZyI6e2xldCB0PXJ0LmdldChlLmRhdGEudHlwZSk7ZS5kYXRhLmVycj90LnNoaWZ0KClbMV0oZS5kYXRhLmVycik6dC5zaGlmdCgpWzBdKGUuZGF0YS5vdXQpO2JyZWFrfX19LG9yPWFzeW5jKCk9PntpZighTWUpe2lmKGxlKXRocm93IG5ldyBFcnJvcigibXVsdGlwbGUgY2FsbHMgdG8gJ2luaXRXYXNtKCknIGRldGVjdGVkLiIpO2lmKERlKXRocm93IG5ldyBFcnJvcigicHJldmlvdXMgY2FsbCB0byAnaW5pdFdhc20oKScgZmFpbGVkLiIpO2lmKGxlPSEwLFooKSlyZXR1cm4gbmV3IFByb21pc2UoKChlLHQpPT57RD8udGVybWluYXRlKCksVnQoKS50aGVuKCgoW3Isbl0pPT57dHJ5eyhEPW4pLm9uZXJyb3I9ZT0+dChlKSxELm9ubWVzc2FnZT1Ocix0dD1bZSx0XTtsZXQgbz17dHlwZToiaW5pdC13YXNtIixpbjpBfTtpZighby5pbi53YXNtLndhc21QYXRocyYmcil7bGV0IGU9UGUoKTtlJiYoby5pbi53YXNtLndhc21QYXRocz1lKTt9RC5wb3N0TWVzc2FnZShvKSxfZT1yO31jYXRjaChlKXt0KGUpO319KSx0KTt9KSk7dHJ5e2F3YWl0IEVlKEEud2FzbSksYXdhaXQgVGUoQSksTWU9ITA7fWNhdGNoKGUpe3Rocm93IERlPSEwLGV9ZmluYWxseXtsZT0hMTt9fX0sc3I9YXN5bmMgZT0+e2lmKFooKSlyZXR1cm4gb2UoKSxuZXcgUHJvbWlzZSgoKHQscik9PntuZSgiaW5pdC1lcCIsW3Qscl0pO2xldCBuPXt0eXBlOiJpbml0LWVwIixpbjp7ZXBOYW1lOmUsZW52OkF9fTtELnBvc3RNZXNzYWdlKG4pO30pKTthd2FpdCBTZShBLGUpO30saXI9YXN5bmMgZT0+WigpPyhvZSgpLG5ldyBQcm9taXNlKCgodCxyKT0+e25lKCJjb3B5LWZyb20iLFt0LHJdKTtsZXQgbj17dHlwZToiY29weS1mcm9tIixpbjp7YnVmZmVyOmV9fTtELnBvc3RNZXNzYWdlKG4sW2UuYnVmZmVyXSk7fSkpKTp1ZShlKSxhcj1hc3luYyhlLHQpPT57aWYoWigpKXtpZih0Py5wcmVmZXJyZWRPdXRwdXRMb2NhdGlvbil0aHJvdyBuZXcgRXJyb3IoJ3Nlc3Npb24gb3B0aW9uICJwcmVmZXJyZWRPdXRwdXRMb2NhdGlvbiIgaXMgbm90IHN1cHBvcnRlZCBmb3IgcHJveHkuJyk7cmV0dXJuIG9lKCksbmV3IFByb21pc2UoKChyLG4pPT57bmUoImNyZWF0ZSIsW3Isbl0pO2xldCBvPXt0eXBlOiJjcmVhdGUiLGluOnttb2RlbDplLG9wdGlvbnM6ey4uLnR9fX0sYT1bXTtlIGluc3RhbmNlb2YgVWludDhBcnJheSYmYS5wdXNoKGUuYnVmZmVyKSxELnBvc3RNZXNzYWdlKG8sYSk7fSkpfXJldHVybiBBZShlLHQpfSx1cj1hc3luYyBlPT57aWYoWigpKXJldHVybiBvZSgpLG5ldyBQcm9taXNlKCgodCxyKT0+e25lKCJyZWxlYXNlIixbdCxyXSk7bGV0IG49e3R5cGU6InJlbGVhc2UiLGluOmV9O0QucG9zdE1lc3NhZ2Uobik7fSkpO09lKGUpO30sZnI9YXN5bmMoZSx0LHIsbixvLGEpPT57aWYoWigpKXtpZihyLnNvbWUoKGU9PiJjcHUiIT09ZVszXSkpKXRocm93IG5ldyBFcnJvcigiaW5wdXQgdGVuc29yIG9uIEdQVSBpcyBub3Qgc3VwcG9ydGVkIGZvciBwcm94eS4iKTtpZihvLnNvbWUoKGU9PmUpKSl0aHJvdyBuZXcgRXJyb3IoInByZS1hbGxvY2F0ZWQgb3V0cHV0IHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkIGZvciBwcm94eS4iKTtyZXR1cm4gb2UoKSxuZXcgUHJvbWlzZSgoKG8saSk9PntuZSgicnVuIixbbyxpXSk7bGV0IHM9cixsPXt0eXBlOiJydW4iLGluOntzZXNzaW9uSWQ6ZSxpbnB1dEluZGljZXM6dCxpbnB1dHM6cyxvdXRwdXRJbmRpY2VzOm4sb3B0aW9uczphfX07RC5wb3N0TWVzc2FnZShsLEllKHMpKTt9KSl9cmV0dXJuIHhlKGUsdCxyLG4sbyxhKX0sY3I9YXN5bmMgZT0+e2lmKFooKSlyZXR1cm4gb2UoKSxuZXcgUHJvbWlzZSgoKHQscik9PntuZSgiZW5kLXByb2ZpbGluZyIsW3Qscl0pO2xldCBuPXt0eXBlOiJlbmQtcHJvZmlsaW5nIixpbjplfTtELnBvc3RNZXNzYWdlKG4pO30pKTtMZShlKTt9O30pKSxkcj1UKCgoKT0+e3EoKSxudCgpLFFlKCksYmUoKSxldCgpLGxyPShlLHQpPT57c3dpdGNoKGUubG9jYXRpb24pe2Nhc2UiY3B1IjpyZXR1cm4gW2UudHlwZSxlLmRpbXMsZS5kYXRhLCJjcHUiXTtjYXNlImdwdS1idWZmZXIiOnJldHVybiBbZS50eXBlLGUuZGltcyx7Z3B1QnVmZmVyOmUuZ3B1QnVmZmVyfSwiZ3B1LWJ1ZmZlciJdO2Nhc2UibWwtdGVuc29yIjpyZXR1cm4gW2UudHlwZSxlLmRpbXMse21sVGVuc29yOmUubWxUZW5zb3J9LCJtbC10ZW5zb3IiXTtkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgaW52YWxpZCBkYXRhIGxvY2F0aW9uOiAke2UubG9jYXRpb259IGZvciAke3QoKX1gKX19LFdyPWU9Pntzd2l0Y2goZVszXSl7Y2FzZSJjcHUiOnJldHVybiBuZXcgUihlWzBdLGVbMl0sZVsxXSk7Y2FzZSJncHUtYnVmZmVyIjp7bGV0IHQ9ZVswXTtpZighQ2UodCkpdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIGRhdGEgdHlwZTogJHt0fSBmb3IgZGVzZXJpYWxpemluZyBHUFUgdGVuc29yYCk7bGV0e2dwdUJ1ZmZlcjpyLGRvd25sb2FkOm4sZGlzcG9zZTpvfT1lWzJdO3JldHVybiBSLmZyb21HcHVCdWZmZXIocix7ZGF0YVR5cGU6dCxkaW1zOmVbMV0sZG93bmxvYWQ6bixkaXNwb3NlOm99KX1jYXNlIm1sLXRlbnNvciI6e2xldCB0PWVbMF07aWYoIVVlKHQpKXRocm93IG5ldyBFcnJvcihgbm90IHN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7dH0gZm9yIGRlc2VyaWFsaXppbmcgTUxUZW5zb3IgdGVuc29yYCk7bGV0e21sVGVuc29yOnIsZG93bmxvYWQ6bixkaXNwb3NlOm99PWVbMl07cmV0dXJuIFIuZnJvbU1MVGVuc29yKHIse2RhdGFUeXBlOnQsZGltczplWzFdLGRvd25sb2FkOm4sZGlzcG9zZTpvfSl9ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgZGF0YSBsb2NhdGlvbjogJHtlWzNdfWApfX0sUmU9Y2xhc3N7YXN5bmMgZmV0Y2hNb2RlbEFuZENvcHlUb1dhc21NZW1vcnkoZSl7cmV0dXJuIGlyKGF3YWl0IGNlKGUpKX1hc3luYyBsb2FkTW9kZWwoZSx0KXtsZXQgcjtWKCkscj0ic3RyaW5nIj09dHlwZW9mIGU/YXdhaXQgdGhpcy5mZXRjaE1vZGVsQW5kQ29weVRvV2FzbU1lbW9yeShlKTplLFt0aGlzLnNlc3Npb25JZCx0aGlzLmlucHV0TmFtZXMsdGhpcy5vdXRwdXROYW1lc109YXdhaXQgYXIocix0KSxZKCk7fWFzeW5jIGRpc3Bvc2UoKXtyZXR1cm4gdXIodGhpcy5zZXNzaW9uSWQpfWFzeW5jIHJ1bihlLHQscil7VigpO2xldCBuPVtdLG89W107T2JqZWN0LmVudHJpZXMoZSkuZm9yRWFjaCgoZT0+e2xldCB0PWVbMF0scj1lWzFdLGE9dGhpcy5pbnB1dE5hbWVzLmluZGV4T2YodCk7aWYoLTE9PT1hKXRocm93IG5ldyBFcnJvcihgaW52YWxpZCBpbnB1dCAnJHt0fSdgKTtuLnB1c2gociksby5wdXNoKGEpO30pKTtsZXQgYT1bXSxpPVtdO09iamVjdC5lbnRyaWVzKHQpLmZvckVhY2goKGU9PntsZXQgdD1lWzBdLHI9ZVsxXSxuPXRoaXMub3V0cHV0TmFtZXMuaW5kZXhPZih0KTtpZigtMT09PW4pdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIG91dHB1dCAnJHt0fSdgKTthLnB1c2gociksaS5wdXNoKG4pO30pKTtsZXQgcz1uLm1hcCgoKGUsdCk9PmxyKGUsKCgpPT5gaW5wdXQgIiR7dGhpcy5pbnB1dE5hbWVzW29bdF1dfSJgKSkpKSxsPWEubWFwKCgoZSx0KT0+ZT9scihlLCgoKT0+YG91dHB1dCAiJHt0aGlzLm91dHB1dE5hbWVzW2lbdF1dfSJgKSk6bnVsbCkpLHU9YXdhaXQgZnIodGhpcy5zZXNzaW9uSWQsbyxzLGksbCxyKSxmPXt9O2ZvcihsZXQgZT0wO2U8dS5sZW5ndGg7ZSsrKWZbdGhpcy5vdXRwdXROYW1lc1tpW2VdXV09YVtlXT8/V3IodVtlXSk7cmV0dXJuIFkoKSxmfXN0YXJ0UHJvZmlsaW5nKCl7fWVuZFByb2ZpbGluZygpe2NyKHRoaXMuc2Vzc2lvbklkKTt9fTt9KSksbXI9e307R2UobXIse09ubnhydW50aW1lV2ViQXNzZW1ibHlCYWNrZW5kOigpPT5GZSxpbml0aWFsaXplRmxhZ3M6KCk9PnByLHdhc21CYWNrZW5kOigpPT4kcn0pO3ZhciBwcixGZSwkcixocj1UKCgoKT0+e3EoKSxudCgpLGRyKCkscHI9KCk9PntpZigoIm51bWJlciIhPXR5cGVvZiBBLndhc20uaW5pdFRpbWVvdXR8fEEud2FzbS5pbml0VGltZW91dDwwKSYmKEEud2FzbS5pbml0VGltZW91dD0wKSwhMT09PUEud2FzbS5zaW1kJiZjb25zb2xlLndhcm4oJ0RlcHJlY2F0ZWQgcHJvcGVydHkgImVudi53YXNtLnNpbWQiIGlzIHNldCB0byBmYWxzZS4gbm9uLVNJTUQgYnVpbGQgaXMgbm8gbG9uZ2VyIHByb3ZpZGVkLCBhbmQgdGhpcyBzZXR0aW5nIHdpbGwgYmUgaWdub3JlZC4nKSwiYm9vbGVhbiIhPXR5cGVvZiBBLndhc20ucHJveHkmJihBLndhc20ucHJveHk9ITEpLCJib29sZWFuIiE9dHlwZW9mIEEud2FzbS50cmFjZSYmKEEud2FzbS50cmFjZT0hMSksIm51bWJlciIhPXR5cGVvZiBBLndhc20ubnVtVGhyZWFkc3x8IU51bWJlci5pc0ludGVnZXIoQS53YXNtLm51bVRocmVhZHMpfHxBLndhc20ubnVtVGhyZWFkczw9MClpZih0eXBlb2Ygc2VsZjwidSImJiFzZWxmLmNyb3NzT3JpZ2luSXNvbGF0ZWQpQS53YXNtLm51bVRocmVhZHM9MTtlbHNlIHtsZXQgZT10eXBlb2YgbmF2aWdhdG9yPiJ1Ij8kZSgibm9kZTpvcyIpLmNwdXMoKS5sZW5ndGg6bmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3k7QS53YXNtLm51bVRocmVhZHM9TWF0aC5taW4oNCxNYXRoLmNlaWwoKGV8fDEpLzIpKTt9fSwkcj1uZXcoRmU9Y2xhc3N7YXN5bmMgaW5pdChlKXtwcigpLGF3YWl0IG9yKCksYXdhaXQgc3IoZSk7fWFzeW5jIGNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKGUsdCl7bGV0IHI9bmV3IFJlO3JldHVybiBhd2FpdCByLmxvYWRNb2RlbChlLHQpLFByb21pc2UucmVzb2x2ZShyKX19KTt9KSk7cSgpLHEoKSxxKCk7dmFyIEZ0PSIxLjIxLjAiO3tsZXQgZT0oaHIoKSxhdChtcikpLndhc21CYWNrZW5kO2llKCJjcHUiLGUsMTApLGllKCJ3YXNtIixlLDEwKTt9T2JqZWN0LmRlZmluZVByb3BlcnR5KEEudmVyc2lvbnMsIndlYiIse3ZhbHVlOkZ0LGVudW1lcmFibGU6ITB9KTsKCmNsYXNzIFdvcmtlck5hdGl2ZXtjb25zdHJ1Y3Rvcigpe3RoaXMucmVhZHk9ITE7dGhpcy5pbmRleGVkREJNYW5hZ2VyPW5ldyBJbmRleGVkREJNYW5hZ2VyKCJvbmlyaXgtc2RrIiwiZmlsZXMiKSx0aGlzLmluZGV4ZWREQk1hbmFnZXIuZ2V0RmlsZUZyb21JbmRleGVkREIoIlNES18xLjEwLjAiKS50aGVuKChhc3luYyBlPT57bGV0IHQ9VVJMLmNyZWF0ZU9iamVjdFVSTChuZXcgQmxvYihbZV0se3R5cGU6InRleHQvamF2YXNjcmlwdCJ9KSk7Y29uc3R7ZGVmYXVsdDphfT1hd2FpdCBpbXBvcnQoLyogd2VicGFja0lnbm9yZTogdHJ1ZSwgd2VicGFja01vZGU6ICJsYXp5IiAqL3QpLHM9YXdhaXQgYSgpO3RoaXMubmF0aXZlU0RLPXMsdGhpcy5zcGF0aWFsQnVmZmVyU2l6ZT10aGlzLm5hdGl2ZVNESy5fT1hfR2V0QnVmZmVyU2l6ZSgpLHRoaXMuZnJvbUJ1ZmZlcj10aGlzLm5hdGl2ZVNESy5fbWFsbG9jKDQqdGhpcy5zcGF0aWFsQnVmZmVyU2l6ZSksdGhpcy50b0J1ZmZlcj10aGlzLm5hdGl2ZVNESy5fbWFsbG9jKDQqdGhpcy5zcGF0aWFsQnVmZmVyU2l6ZSksQS53YXNtLm51bVRocmVhZHM9MTtjb25zdCByPWF3YWl0IHRoaXMuaW5kZXhlZERCTWFuYWdlci5nZXRGaWxlRnJvbUluZGV4ZWREQigib3J0Lndhc20iKSxpPVVSTC5jcmVhdGVPYmplY3RVUkwobmV3IEJsb2IoW3JdLHt0eXBlOiJhcHBsaWNhdGlvbi93YXNtIn0pKTtBLndhc20ud2FzbVBhdGhzPXt3YXNtOmksbWpzOiJodHRwczovL2Nkbi5vbmlyaXguY29tL29uaXJpeC1lbmdpbmUtc2RrL29ydF92MS4yMS4wX21pbi9vcnQtd2FzbS1zaW1kLm1qcyJ9O2xldCBuPWF3YWl0IHRoaXMuaW5kZXhlZERCTWFuYWdlci5nZXRGcm9tQ2FjaGVPckZldGNoKCJzcGFyc2VfbWF0Y2hpbmcub3J0IiwiaHR0cHM6Ly9jZG4ub25pcml4LmNvbS9vbmlyaXgtZW5naW5lLXNkay9zcGFyc2VfbWF0Y2hpbmcub3J0Iik7Y29uc3Qgbz1hd2FpdCBPci5jcmVhdGUobix7ZXhlY3V0aW9uUHJvdmlkZXJzOlsid2FzbSJdfSk7dGhpcy5zZXNzaW9uTWF0Y2hpbmc9byxhd2FpdCB0aGlzLnNlc3Npb25NYXRjaGluZy5ydW4oe2ZlYXRzMDpuZXcgUihuZXcgRmxvYXQzMkFycmF5KEFycmF5KDY0ZTMpLmZpbGwoMCkpLFsxZTMsNjRdKSxmZWF0czE6bmV3IFIobmV3IEZsb2F0MzJBcnJheShBcnJheSg2NGUzKS5maWxsKDApKSxbMWUzLDY0XSl9KSx0aGlzLnJlYWR5PSEwLHBvc3RNZXNzYWdlKCJyZWFkeSIpO30pKTt9c3RhcnQoKXthZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwoYXN5bmMgZT0+e2lmKCF0aGlzLnJlYWR5KXJldHVybjtjb25zdCB0PWUuZGF0YSxhPXQuZnJvbSxzPXQudG87bGV0IHI7aWYoMj09dC5kdHlwZSl7bGV0IGU9dGhpcy5yZWFkRGVzY3JpcHRvcnMoYSksdD10aGlzLnJlYWREZXNjcmlwdG9ycyhzKSxpPWF3YWl0IHRoaXMuc2Vzc2lvbk1hdGNoaW5nLnJ1bih7ZmVhdHMwOmUsZmVhdHMxOnR9KSx7aWR4MDpuLGlkeDE6b309aSxoPVtuLmRpbXNbMF1dO2ZvcihsZXQgZT0wO2U8bi5kaW1zWzBdO2UrKyloLnB1c2goTnVtYmVyKG4uZGF0YVtlXSkpLGgucHVzaChOdW1iZXIoby5kYXRhW2VdKSk7cj1uZXcgRmxvYXQzMkFycmF5KGgpO31lbHNlIHt0aGlzLm5hdGl2ZVNESy5IRUFQRjMyLnNldChhLHRoaXMuZnJvbUJ1ZmZlci80KSx0aGlzLm5hdGl2ZVNESy5IRUFQRjMyLnNldChzLHRoaXMudG9CdWZmZXIvNCk7bGV0IGU9dGhpcy5uYXRpdmVTREsuX09YX01hdGNoKHRoaXMuZnJvbUJ1ZmZlcix0aGlzLnRvQnVmZmVyLHQuZHR5cGUpO3I9bmV3IEZsb2F0MzJBcnJheSh0aGlzLnJlYWRNYXRjaGluZ0RhdGEodGhpcy5uYXRpdmVTREsuSEVBUEYzMixlLzQpKTt9cG9zdE1lc3NhZ2Uocik7fSkpO31yZWFkRGVzY3JpcHRvcnMoZSl7bGV0IHQ9ZVswXSxhPTErMip0O3JldHVybiBuZXcgUihuZXcgRmxvYXQzMkFycmF5KGUuc2xpY2UoYSxhKzY0KnQpKSxbdCw2NF0pfXJlYWRNYXRjaGluZ0RhdGEoZSx0KXtsZXQgYT10LHM9W10scj1lW2FdO3MucHVzaChyKSxhKys7Zm9yKGxldCB0PTA7dDxyO3QrKylzLnB1c2goZVthXSkscy5wdXNoKGVbYSsxXSksYSs9MjtyZXR1cm4gc319Y29uc3Qgd29ya2VyPW5ldyBXb3JrZXJOYXRpdmU7d29ya2VyLnN0YXJ0KCk7Cg=="),b=new Blob([d],{type:"application/javascript"});this.workers[Z]=new Worker(/* webpackIgnore: true, webpackMode: "lazy" */URL.createObjectURL(b),{type:"module"}),this.callbacks[Z]=l,this.workers[Z].addEventListener("message",(l=>{this.callbacks[Z](l.data);}));}}replaceCallback(Z,l){this.workerExists(Z)&&(this.callbacks[Z]=l);}sendDataToWorker(Z,l){this.workers[Z].postMessage(l);}async createWorkers(){return await this.indexedDBManager.getFromCacheOrFetch("ort.wasm","https://cdn.onirix.com/onirix-engine-sdk/ort_v1.21.0_min/ort-wasm-simd.wasm"),Promise.all([new Promise(((Z,l)=>{this.createExtractionWorker("extraction",(l=>{"ready"===l&&Z();}));})),new Promise(((Z,l)=>{this.createMatchingWorker("matching",(l=>{"ready"===l&&Z();}));}))])}}
|
51
|
+
class WorkerExtractionData{constructor(Z,l,d,b,c,m,G=5,X=!1){this.data=Z,this.width=l,this.height=d,this.rotate=b,this.flip=c,this.colorSpace=G,this.onlyCoarse=X,this.dtype=m;}}class WorkerMatchingData{constructor(Z,l,d,b){this.idx=Z,this.from=l,this.to=d,this.dtype=b;}}class WorkerManager{constructor(){this.workers={},this.callbacks={};this.indexedDBManager=new IndexedDBManager("onirix-sdk","files");}workerExists(Z){return void 0!==this.workers[Z]&&void 0!==this.callbacks[Z]}createExtractionWorker(Z,l){if(!this.workerExists(Z)){let d=atob("Y2xhc3MgSW5kZXhlZERCTWFuYWdlcntjb25zdHJ1Y3RvcihlLHIpe3RoaXMuZGJOYW1lPWUsdGhpcy5zdG9yZU5hbWU9cjt9YXN5bmMgZ2V0RnJvbUNhY2hlT3JGZXRjaChlLHIpe2xldCB0PW51bGw7dHJ5e3Q9YXdhaXQgdGhpcy5nZXRGaWxlRnJvbUluZGV4ZWREQihlKTt9Y2F0Y2goZSl7Y29uc29sZS5sb2coIkFuIGVycm9yIG9jY3VycmVkIHdoaWxlIHRyeWluZyB0byBnZXQgZWxlbWVudCBmcm9tIGluZGV4ZWREQi4iKTt9cmV0dXJuIHR8fCh0PWF3YWl0IHRoaXMuZmV0Y2hBbmRDYWNoZUZpbGUocixlKSksbmV3IFVpbnQ4QXJyYXkodCl9YXN5bmMgZ2V0RmlsZUZyb21JbmRleGVkREIoZSl7cmV0dXJuIG5ldyBQcm9taXNlKCgocix0KT0+e2NvbnN0IG89aW5kZXhlZERCLm9wZW4odGhpcy5kYk5hbWUpO28ub25lcnJvcj0oKT0+dChvLmVycm9yKSxvLm9uc3VjY2Vzcz0oKT0+e2NvbnN0IHM9by5yZXN1bHQudHJhbnNhY3Rpb24odGhpcy5zdG9yZU5hbWUsInJlYWRvbmx5Iikub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpLmdldChlKTtzLm9uc3VjY2Vzcz0oKT0+cihzLnJlc3VsdCkscy5vbmVycm9yPSgpPT50KHMuZXJyb3IpO30sby5vbnVwZ3JhZGVuZWVkZWQ9ZT0+e2UudGFyZ2V0LnJlc3VsdC5jcmVhdGVPYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7fTt9KSl9YXN5bmMgc2F2ZUZpbGVUb0luZGV4ZWREQihlLHIpe3JldHVybiBuZXcgUHJvbWlzZSgoKHQsbyk9Pntjb25zdCBzPWluZGV4ZWREQi5vcGVuKHRoaXMuZGJOYW1lKTtzLm9uZXJyb3I9KCk9Pm8ocy5lcnJvcikscy5vbnVwZ3JhZGVuZWVkZWQ9ZT0+e2UudGFyZ2V0LnJlc3VsdC5jcmVhdGVPYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7fSxzLm9uc3VjY2Vzcz0oKT0+e3RyeXtjb25zdCBuPXMucmVzdWx0LnRyYW5zYWN0aW9uKHRoaXMuc3RvcmVOYW1lLCJyZWFkd3JpdGUiKSxhPW4ub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpLnB1dChyLGUpO2Eub25zdWNjZXNzPSgpPT50KGEucmVzdWx0KSxhLm9uZXJyb3I9KCk9Pm8oYS5lcnJvcik7fWNhdGNoKGUpe28oZSk7fX07fSkpfWFzeW5jIGZldGNoQW5kQ2FjaGVGaWxlKGUscil7Y29uc3QgdD1hd2FpdCBmZXRjaChlKSxvPWF3YWl0IHQuYXJyYXlCdWZmZXIoKTtyZXR1cm4gYXdhaXQgdGhpcy5zYXZlRmlsZVRvSW5kZXhlZERCKHIsbyksb319Cgp2YXIgaGUsaixpZSxBcix1dCxjdCxkdCxfLEEsbXQsaHQsSGUseXQsYnQsZ3QsRXQsVHQsSCxhZSxBdCxPdCxMdCxJdCx2LFIsdnQsQnQsVixZLHllLE9yLFdlPU9iamVjdC5kZWZpbmVQcm9wZXJ0eSxncj1PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLEVyPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzLFRyPU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHksJGU9KGU9PnR5cGVvZiByZXF1aXJlPCJ1Ij9yZXF1aXJlOnR5cGVvZiBQcm94eTwidSI/bmV3IFByb3h5KGUse2dldDooZSx0KT0+KHR5cGVvZiByZXF1aXJlPCJ1Ij9yZXF1aXJlOmUpW3RdfSk6ZSkoKGZ1bmN0aW9uKGUpe2lmKHR5cGVvZiByZXF1aXJlPCJ1IilyZXR1cm4gcmVxdWlyZS5hcHBseSh0aGlzLGFyZ3VtZW50cyk7dGhyb3cgRXJyb3IoJ0R5bmFtaWMgcmVxdWlyZSBvZiAiJytlKyciIGlzIG5vdCBzdXBwb3J0ZWQnKX0pKSxUPShlLHQpPT4oKT0+KGUmJih0PWUoZT0wKSksdCksR2U9KGUsdCk9Pntmb3IodmFyIHIgaW4gdClXZShlLHIse2dldDp0W3JdLGVudW1lcmFibGU6ITB9KTt9LFNyPShlLHQscixuKT0+e2lmKHQmJiJvYmplY3QiPT10eXBlb2YgdHx8ImZ1bmN0aW9uIj09dHlwZW9mIHQpZm9yKGxldCBvIG9mIEVyKHQpKSFUci5jYWxsKGUsbykmJm8hPT1yJiZXZShlLG8se2dldDooKT0+dFtvXSxlbnVtZXJhYmxlOiEobj1ncih0LG8pKXx8bi5lbnVtZXJhYmxlfSk7cmV0dXJuIGV9LGF0PWU9PlNyKFdlKHt9LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KSxlKSx6ZT1UKCgoKT0+e2hlPW5ldyBNYXAsaj1bXSxpZT0oZSx0LHIpPT57aWYoIXR8fCJmdW5jdGlvbiIhPXR5cGVvZiB0LmluaXR8fCJmdW5jdGlvbiIhPXR5cGVvZiB0LmNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKXRocm93IG5ldyBUeXBlRXJyb3IoIm5vdCBhIHZhbGlkIGJhY2tlbmQiKTt7bGV0IG49aGUuZ2V0KGUpO2lmKHZvaWQgMD09PW4paGUuc2V0KGUse2JhY2tlbmQ6dCxwcmlvcml0eTpyfSk7ZWxzZSB7aWYobi5wcmlvcml0eT5yKXJldHVybjtpZihuLnByaW9yaXR5PT09ciYmbi5iYWNrZW5kIT09dCl0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCByZWdpc3RlciBiYWNrZW5kICIke2V9IiB1c2luZyBwcmlvcml0eSAke3J9YCl9aWYocj49MCl7bGV0IHQ9ai5pbmRleE9mKGUpOy0xIT09dCYmai5zcGxpY2UodCwxKTtmb3IobGV0IHQ9MDt0PGoubGVuZ3RoO3QrKylpZihoZS5nZXQoalt0XSkucHJpb3JpdHk8PXIpcmV0dXJuIHZvaWQgai5zcGxpY2UodCwwLGUpO2oucHVzaChlKTt9fX0sQXI9YXN5bmMgZT0+e2xldCB0PWhlLmdldChlKTtpZighdClyZXR1cm4gImJhY2tlbmQgbm90IGZvdW5kLiI7aWYodC5pbml0aWFsaXplZClyZXR1cm4gdC5iYWNrZW5kO2lmKHQuYWJvcnRlZClyZXR1cm4gdC5lcnJvcjt7bGV0IHI9ISF0LmluaXRQcm9taXNlO3RyeXtyZXR1cm4gcnx8KHQuaW5pdFByb21pc2U9dC5iYWNrZW5kLmluaXQoZSkpLGF3YWl0IHQuaW5pdFByb21pc2UsdC5pbml0aWFsaXplZD0hMCx0LmJhY2tlbmR9Y2F0Y2goZSl7cmV0dXJuIHJ8fCh0LmVycm9yPWAke2V9YCx0LmFib3J0ZWQ9ITApLHQuZXJyb3J9ZmluYWxseXtkZWxldGUgdC5pbml0UHJvbWlzZTt9fX0sdXQ9YXN5bmMgZT0+e2xldCB0LHI9ZS5leGVjdXRpb25Qcm92aWRlcnN8fFtdLG49ci5tYXAoKGU9PiJzdHJpbmciPT10eXBlb2YgZT9lOmUubmFtZSkpLG89MD09PW4ubGVuZ3RoP2o6bixhPVtdLGk9bmV3IFNldDtmb3IobGV0IGUgb2Ygbyl7bGV0IHI9YXdhaXQgQXIoZSk7InN0cmluZyI9PXR5cGVvZiByP2EucHVzaCh7bmFtZTplLGVycjpyfSk6KHR8fCh0PXIpLHQ9PT1yJiZpLmFkZChlKSk7fWlmKCF0KXRocm93IG5ldyBFcnJvcihgbm8gYXZhaWxhYmxlIGJhY2tlbmQgZm91bmQuIEVSUjogJHthLm1hcCgoZT0+YFske2UubmFtZX1dICR7ZS5lcnJ9YCkpLmpvaW4oIiwgIil9YCk7Zm9yKGxldHtuYW1lOmUsZXJyOnR9b2YgYSluLmluY2x1ZGVzKGUpJiZjb25zb2xlLndhcm4oYHJlbW92aW5nIHJlcXVlc3RlZCBleGVjdXRpb24gcHJvdmlkZXIgIiR7ZX0iIGZyb20gc2Vzc2lvbiBvcHRpb25zIGJlY2F1c2UgaXQgaXMgbm90IGF2YWlsYWJsZTogJHt0fWApO2xldCBzPXIuZmlsdGVyKChlPT5pLmhhcygic3RyaW5nIj09dHlwZW9mIGU/ZTplLm5hbWUpKSk7cmV0dXJuIFt0LG5ldyBQcm94eShlLHtnZXQ6KGUsdCk9PiJleGVjdXRpb25Qcm92aWRlcnMiPT09dD9zOlJlZmxlY3QuZ2V0KGUsdCl9KV19O30pKSxmdD1UKCgoKT0+e3plKCk7fSkpLGx0PVQoKCgpPT57Y3Q9IjEuMjEuMCI7fSkpLGplPVQoKCgpPT57bHQoKSxkdD0id2FybmluZyIsXz17d2FzbTp7fSx3ZWJnbDp7fSx3ZWJncHU6e30sdmVyc2lvbnM6e2NvbW1vbjpjdH0sc2V0IGxvZ0xldmVsKGUpe2lmKHZvaWQgMCE9PWUpe2lmKCJzdHJpbmciIT10eXBlb2YgZXx8LTE9PT1bInZlcmJvc2UiLCJpbmZvIiwid2FybmluZyIsImVycm9yIiwiZmF0YWwiXS5pbmRleE9mKGUpKXRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgbG9nZ2luZyBsZXZlbDogJHtlfWApO2R0PWU7fX0sZ2V0IGxvZ0xldmVsKCl7cmV0dXJuIGR0fX0sT2JqZWN0LmRlZmluZVByb3BlcnR5KF8sImxvZ0xldmVsIix7ZW51bWVyYWJsZTohMH0pO30pKSxwdD1UKCgoKT0+e2plKCksQT1fO30pKSx3dD1UKCgoKT0+e210PShlLHQpPT57bGV0IHI9dHlwZW9mIGRvY3VtZW50PCJ1Ij9kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJjYW52YXMiKTpuZXcgT2Zmc2NyZWVuQ2FudmFzKDEsMSk7ci53aWR0aD1lLmRpbXNbM10sci5oZWlnaHQ9ZS5kaW1zWzJdO2xldCBuPXIuZ2V0Q29udGV4dCgiMmQiKTtpZihudWxsIT1uKXtsZXQgbyxhO3ZvaWQgMCE9PXQ/LnRlbnNvckxheW91dCYmIk5IV0MiPT09dC50ZW5zb3JMYXlvdXQ/KG89ZS5kaW1zWzJdLGE9ZS5kaW1zWzNdKToobz1lLmRpbXNbM10sYT1lLmRpbXNbMl0pO2xldCBpLHMsbD12b2lkIDAhPT10Py5mb3JtYXQ/dC5mb3JtYXQ6IlJHQiIsdT10Py5ub3JtO3ZvaWQgMD09PXV8fHZvaWQgMD09PXUubWVhbj9pPVsyNTUsMjU1LDI1NSwyNTVdOiJudW1iZXIiPT10eXBlb2YgdS5tZWFuP2k9W3UubWVhbix1Lm1lYW4sdS5tZWFuLHUubWVhbl06KGk9W3UubWVhblswXSx1Lm1lYW5bMV0sdS5tZWFuWzJdLDBdLHZvaWQgMCE9PXUubWVhblszXSYmKGlbM109dS5tZWFuWzNdKSksdm9pZCAwPT09dXx8dm9pZCAwPT09dS5iaWFzP3M9WzAsMCwwLDBdOiJudW1iZXIiPT10eXBlb2YgdS5iaWFzP3M9W3UuYmlhcyx1LmJpYXMsdS5iaWFzLHUuYmlhc106KHM9W3UuYmlhc1swXSx1LmJpYXNbMV0sdS5iaWFzWzJdLDBdLHZvaWQgMCE9PXUuYmlhc1szXSYmKHNbM109dS5iaWFzWzNdKSk7bGV0IGY9YSpvLGQ9MCxwPWYsYz0yKmYsaD0tMTsiUkdCQSI9PT1sPyhkPTAscD1mLGM9MipmLGg9MypmKToiUkdCIj09PWw/KGQ9MCxwPWYsYz0yKmYpOiJSQkciPT09bCYmKGQ9MCxjPWYscD0yKmYpO2ZvcihsZXQgdD0wO3Q8YTt0KyspZm9yKGxldCByPTA7cjxvO3IrKyl7bGV0IG89KGUuZGF0YVtkKytdLXNbMF0pKmlbMF0sYT0oZS5kYXRhW3ArK10tc1sxXSkqaVsxXSxsPShlLmRhdGFbYysrXS1zWzJdKSppWzJdLHU9LTE9PT1oPzI1NTooZS5kYXRhW2grK10tc1szXSkqaVszXTtuLmZpbGxTdHlsZT0icmdiYSgiK28rIiwiK2ErIiwiK2wrIiwiK3UrIikiLG4uZmlsbFJlY3Qocix0LDEsMSk7fWlmKCJ0b0RhdGFVUkwiaW4gcilyZXR1cm4gci50b0RhdGFVUkwoKTt0aHJvdyBuZXcgRXJyb3IoInRvRGF0YVVSTCBpcyBub3Qgc3VwcG9ydGVkIil9dGhyb3cgbmV3IEVycm9yKCJDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhIil9LGh0PShlLHQpPT57bGV0IHIsbj10eXBlb2YgZG9jdW1lbnQ8InUiP2RvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImNhbnZhcyIpLmdldENvbnRleHQoIjJkIik6bmV3IE9mZnNjcmVlbkNhbnZhcygxLDEpLmdldENvbnRleHQoIjJkIik7aWYobnVsbD09bil0aHJvdyBuZXcgRXJyb3IoIkNhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEiKTt7bGV0IG8sYSxpO3ZvaWQgMCE9PXQ/LnRlbnNvckxheW91dCYmIk5IV0MiPT09dC50ZW5zb3JMYXlvdXQ/KG89ZS5kaW1zWzJdLGE9ZS5kaW1zWzFdLGk9ZS5kaW1zWzNdKToobz1lLmRpbXNbM10sYT1lLmRpbXNbMl0saT1lLmRpbXNbMV0pO2xldCBzLGwsdT12b2lkIDAhPT10JiZ2b2lkIDAhPT10LmZvcm1hdD90LmZvcm1hdDoiUkdCIixmPXQ/Lm5vcm07dm9pZCAwPT09Znx8dm9pZCAwPT09Zi5tZWFuP3M9WzI1NSwyNTUsMjU1LDI1NV06Im51bWJlciI9PXR5cGVvZiBmLm1lYW4/cz1bZi5tZWFuLGYubWVhbixmLm1lYW4sZi5tZWFuXToocz1bZi5tZWFuWzBdLGYubWVhblsxXSxmLm1lYW5bMl0sMjU1XSx2b2lkIDAhPT1mLm1lYW5bM10mJihzWzNdPWYubWVhblszXSkpLHZvaWQgMD09PWZ8fHZvaWQgMD09PWYuYmlhcz9sPVswLDAsMCwwXToibnVtYmVyIj09dHlwZW9mIGYuYmlhcz9sPVtmLmJpYXMsZi5iaWFzLGYuYmlhcyxmLmJpYXNdOihsPVtmLmJpYXNbMF0sZi5iaWFzWzFdLGYuYmlhc1syXSwwXSx2b2lkIDAhPT1mLmJpYXNbM10mJihsWzNdPWYuYmlhc1szXSkpO2xldCBkPWEqbztpZih2b2lkIDAhPT10JiYodm9pZCAwIT09dC5mb3JtYXQmJjQ9PT1pJiYiUkdCQSIhPT10LmZvcm1hdHx8Mz09PWkmJiJSR0IiIT09dC5mb3JtYXQmJiJCR1IiIT09dC5mb3JtYXQpKXRocm93IG5ldyBFcnJvcigiVGVuc29yIGZvcm1hdCBkb2Vzbid0IG1hdGNoIGlucHV0IHRlbnNvciBkaW1zIik7bGV0IHA9NCxjPTAsaD0xLHc9Mix5PTMsbT0wLGc9ZCxiPTIqZCx2PS0xOyJSR0JBIj09PXU/KG09MCxnPWQsYj0yKmQsdj0zKmQpOiJSR0IiPT09dT8obT0wLGc9ZCxiPTIqZCk6IlJCRyI9PT11JiYobT0wLGI9ZCxnPTIqZCkscj1uLmNyZWF0ZUltYWdlRGF0YShvLGEpO2ZvcihsZXQgdD0wO3Q8YSpvO2MrPXAsaCs9cCx3Kz1wLHkrPXAsdCsrKXIuZGF0YVtjXT0oZS5kYXRhW20rK10tbFswXSkqc1swXSxyLmRhdGFbaF09KGUuZGF0YVtnKytdLWxbMV0pKnNbMV0sci5kYXRhW3ddPShlLmRhdGFbYisrXS1sWzJdKSpzWzJdLHIuZGF0YVt5XT0tMT09PXY/MjU1OihlLmRhdGFbdisrXS1sWzNdKSpzWzNdO31yZXR1cm4gcn07fSkpLFN0PVQoKCgpPT57d2UoKSxIZT0oZSx0KT0+e2lmKHZvaWQgMD09PWUpdGhyb3cgbmV3IEVycm9yKCJJbWFnZSBidWZmZXIgbXVzdCBiZSBkZWZpbmVkIik7aWYodm9pZCAwPT09dC5oZWlnaHR8fHZvaWQgMD09PXQud2lkdGgpdGhyb3cgbmV3IEVycm9yKCJJbWFnZSBoZWlnaHQgYW5kIHdpZHRoIG11c3QgYmUgZGVmaW5lZCIpO2lmKCJOSFdDIj09PXQudGVuc29yTGF5b3V0KXRocm93IG5ldyBFcnJvcigiTkhXQyBUZW5zb3IgbGF5b3V0IGlzIG5vdCBzdXBwb3J0ZWQgeWV0Iik7bGV0IHIsbix7aGVpZ2h0Om8sd2lkdGg6YX09dCxpPXQubm9ybT8/e21lYW46MjU1LGJpYXM6MH07cj0ibnVtYmVyIj09dHlwZW9mIGkubWVhbj9baS5tZWFuLGkubWVhbixpLm1lYW4saS5tZWFuXTpbaS5tZWFuWzBdLGkubWVhblsxXSxpLm1lYW5bMl0saS5tZWFuWzNdPz8yNTVdLG49Im51bWJlciI9PXR5cGVvZiBpLmJpYXM/W2kuYmlhcyxpLmJpYXMsaS5iaWFzLGkuYmlhc106W2kuYmlhc1swXSxpLmJpYXNbMV0saS5iaWFzWzJdLGkuYmlhc1szXT8/MF07bGV0IHM9dm9pZCAwIT09dC5mb3JtYXQ/dC5mb3JtYXQ6IlJHQkEiLGw9dm9pZCAwIT09dC50ZW5zb3JGb3JtYXQmJnZvaWQgMCE9PXQudGVuc29yRm9ybWF0P3QudGVuc29yRm9ybWF0OiJSR0IiLHU9byphLGY9IlJHQkEiPT09bD9uZXcgRmxvYXQzMkFycmF5KDQqdSk6bmV3IEZsb2F0MzJBcnJheSgzKnUpLGQ9NCxwPTAsYz0xLGg9Mix3PTMseT0wLG09dSxnPTIqdSxiPS0xOyJSR0IiPT09cyYmKGQ9MyxwPTAsYz0xLGg9Mix3PS0xKSwiUkdCQSI9PT1sP2I9Myp1OiJSQkciPT09bD8oeT0wLGc9dSxtPTIqdSk6IkJHUiI9PT1sJiYoZz0wLG09dSx5PTIqdSk7Zm9yKGxldCB0PTA7dDx1O3QrKyxwKz1kLGgrPWQsYys9ZCx3Kz1kKWZbeSsrXT0oZVtwXStuWzBdKS9yWzBdLGZbbSsrXT0oZVtjXStuWzFdKS9yWzFdLGZbZysrXT0oZVtoXStuWzJdKS9yWzJdLC0xIT09YiYmLTEhPT13JiYoZltiKytdPShlW3ddK25bM10pL3JbM10pO3JldHVybiBuZXcgdigiZmxvYXQzMiIsZiwiUkdCQSI9PT1sP1sxLDQsbyxhXTpbMSwzLG8sYV0pfSx5dD1hc3luYyhlLHQpPT57bGV0IHIsbj10eXBlb2YgSFRNTEltYWdlRWxlbWVudDwidSImJmUgaW5zdGFuY2VvZiBIVE1MSW1hZ2VFbGVtZW50LG89dHlwZW9mIEltYWdlRGF0YTwidSImJmUgaW5zdGFuY2VvZiBJbWFnZURhdGEsYT10eXBlb2YgSW1hZ2VCaXRtYXA8InUiJiZlIGluc3RhbmNlb2YgSW1hZ2VCaXRtYXAsaT0ic3RyaW5nIj09dHlwZW9mIGUscz10Pz97fSxsPSgpPT57aWYodHlwZW9mIGRvY3VtZW50PCJ1IilyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiY2FudmFzIik7aWYodHlwZW9mIE9mZnNjcmVlbkNhbnZhczwidSIpcmV0dXJuIG5ldyBPZmZzY3JlZW5DYW52YXMoMSwxKTt0aHJvdyBuZXcgRXJyb3IoIkNhbnZhcyBpcyBub3Qgc3VwcG9ydGVkIil9LHU9ZT0+dHlwZW9mIEhUTUxDYW52YXNFbGVtZW50PCJ1IiYmZSBpbnN0YW5jZW9mIEhUTUxDYW52YXNFbGVtZW50fHxlIGluc3RhbmNlb2YgT2Zmc2NyZWVuQ2FudmFzP2UuZ2V0Q29udGV4dCgiMmQiKTpudWxsO2lmKG4pe2xldCBuPWwoKTtuLndpZHRoPWUud2lkdGgsbi5oZWlnaHQ9ZS5oZWlnaHQ7bGV0IG89dShuKTtpZihudWxsPT1vKXRocm93IG5ldyBFcnJvcigiQ2FuIG5vdCBhY2Nlc3MgaW1hZ2UgZGF0YSIpO3tsZXQgbj1lLmhlaWdodCxhPWUud2lkdGg7aWYodm9pZCAwIT09dCYmdm9pZCAwIT09dC5yZXNpemVkSGVpZ2h0JiZ2b2lkIDAhPT10LnJlc2l6ZWRXaWR0aCYmKG49dC5yZXNpemVkSGVpZ2h0LGE9dC5yZXNpemVkV2lkdGgpLHZvaWQgMCE9PXQpe2lmKHM9dCx2b2lkIDAhPT10LnRlbnNvckZvcm1hdCl0aHJvdyBuZXcgRXJyb3IoIkltYWdlIGlucHV0IGNvbmZpZyBmb3JtYXQgbXVzdCBiZSBSR0JBIGZvciBIVE1MSW1hZ2VFbGVtZW50Iik7cy50ZW5zb3JGb3JtYXQ9IlJHQkEiLHMuaGVpZ2h0PW4scy53aWR0aD1hO31lbHNlIHMudGVuc29yRm9ybWF0PSJSR0JBIixzLmhlaWdodD1uLHMud2lkdGg9YTtvLmRyYXdJbWFnZShlLDAsMCkscj1vLmdldEltYWdlRGF0YSgwLDAsYSxuKS5kYXRhO319ZWxzZSB7aWYoIW8pe2lmKGEpe2lmKHZvaWQgMD09PXQpdGhyb3cgbmV3IEVycm9yKCJQbGVhc2UgcHJvdmlkZSBpbWFnZSBjb25maWcgd2l0aCBmb3JtYXQgZm9yIEltYWdlYml0bWFwIik7bGV0IG49bCgpO24ud2lkdGg9ZS53aWR0aCxuLmhlaWdodD1lLmhlaWdodDtsZXQgbz11KG4pO2lmKG51bGwhPW8pe2xldCB0PWUuaGVpZ2h0LG49ZS53aWR0aDtyZXR1cm4gby5kcmF3SW1hZ2UoZSwwLDAsbix0KSxyPW8uZ2V0SW1hZ2VEYXRhKDAsMCxuLHQpLmRhdGEscy5oZWlnaHQ9dCxzLndpZHRoPW4sSGUocixzKX10aHJvdyBuZXcgRXJyb3IoIkNhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEiKX1pZihpKXJldHVybiBuZXcgUHJvbWlzZSgoKHQscik9PntsZXQgbj1sKCksbz11KG4pO2lmKCFlfHwhbylyZXR1cm4gcigpO2xldCBhPW5ldyBJbWFnZTthLmNyb3NzT3JpZ2luPSJBbm9ueW1vdXMiLGEuc3JjPWUsYS5vbmxvYWQ9KCk9PntuLndpZHRoPWEud2lkdGgsbi5oZWlnaHQ9YS5oZWlnaHQsby5kcmF3SW1hZ2UoYSwwLDAsbi53aWR0aCxuLmhlaWdodCk7bGV0IGU9by5nZXRJbWFnZURhdGEoMCwwLG4ud2lkdGgsbi5oZWlnaHQpO3MuaGVpZ2h0PW4uaGVpZ2h0LHMud2lkdGg9bi53aWR0aCx0KEhlKGUuZGF0YSxzKSk7fTt9KSk7dGhyb3cgbmV3IEVycm9yKCJJbnB1dCBkYXRhIHByb3ZpZGVkIGlzIG5vdCBzdXBwb3J0ZWQgLSBhYm9ydGVkIHRlbnNvciBjcmVhdGlvbiIpfXtsZXQgbixvO2lmKHZvaWQgMCE9PXQmJnZvaWQgMCE9PXQucmVzaXplZFdpZHRoJiZ2b2lkIDAhPT10LnJlc2l6ZWRIZWlnaHQ/KG49dC5yZXNpemVkSGVpZ2h0LG89dC5yZXNpemVkV2lkdGgpOihuPWUuaGVpZ2h0LG89ZS53aWR0aCksdm9pZCAwIT09dCYmKHM9dCkscy5mb3JtYXQ9IlJHQkEiLHMuaGVpZ2h0PW4scy53aWR0aD1vLHZvaWQgMCE9PXQpe2xldCB0PWwoKTt0LndpZHRoPW8sdC5oZWlnaHQ9bjtsZXQgYT11KHQpO2lmKG51bGw9PWEpdGhyb3cgbmV3IEVycm9yKCJDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhIik7YS5wdXRJbWFnZURhdGEoZSwwLDApLHI9YS5nZXRJbWFnZURhdGEoMCwwLG8sbikuZGF0YTt9ZWxzZSByPWUuZGF0YTt9fWlmKHZvaWQgMCE9PXIpcmV0dXJuIEhlKHIscyk7dGhyb3cgbmV3IEVycm9yKCJJbnB1dCBkYXRhIHByb3ZpZGVkIGlzIG5vdCBzdXBwb3J0ZWQgLSBhYm9ydGVkIHRlbnNvciBjcmVhdGlvbiIpfSxidD0oZSx0KT0+e2xldHt3aWR0aDpyLGhlaWdodDpuLGRvd25sb2FkOm8sZGlzcG9zZTphfT10O3JldHVybiBuZXcgdih7bG9jYXRpb246InRleHR1cmUiLHR5cGU6ImZsb2F0MzIiLHRleHR1cmU6ZSxkaW1zOlsxLG4sciw0XSxkb3dubG9hZDpvLGRpc3Bvc2U6YX0pfSxndD0oZSx0KT0+e2xldHtkYXRhVHlwZTpyLGRpbXM6bixkb3dubG9hZDpvLGRpc3Bvc2U6YX09dDtyZXR1cm4gbmV3IHYoe2xvY2F0aW9uOiJncHUtYnVmZmVyIix0eXBlOnI/PyJmbG9hdDMyIixncHVCdWZmZXI6ZSxkaW1zOm4sZG93bmxvYWQ6byxkaXNwb3NlOmF9KX0sRXQ9KGUsdCk9PntsZXR7ZGF0YVR5cGU6cixkaW1zOm4sZG93bmxvYWQ6byxkaXNwb3NlOmF9PXQ7cmV0dXJuIG5ldyB2KHtsb2NhdGlvbjoibWwtdGVuc29yIix0eXBlOnI/PyJmbG9hdDMyIixtbFRlbnNvcjplLGRpbXM6bixkb3dubG9hZDpvLGRpc3Bvc2U6YX0pfSxUdD0oZSx0LHIpPT5uZXcgdih7bG9jYXRpb246ImNwdS1waW5uZWQiLHR5cGU6ZSxkYXRhOnQsZGltczpyPz9bdC5sZW5ndGhdfSk7fSkpLHh0PVQoKCgpPT57SD1uZXcgTWFwKFtbImZsb2F0MzIiLEZsb2F0MzJBcnJheV0sWyJ1aW50OCIsVWludDhBcnJheV0sWyJpbnQ4IixJbnQ4QXJyYXldLFsidWludDE2IixVaW50MTZBcnJheV0sWyJpbnQxNiIsSW50MTZBcnJheV0sWyJpbnQzMiIsSW50MzJBcnJheV0sWyJib29sIixVaW50OEFycmF5XSxbImZsb2F0NjQiLEZsb2F0NjRBcnJheV0sWyJ1aW50MzIiLFVpbnQzMkFycmF5XSxbImludDQiLFVpbnQ4QXJyYXldLFsidWludDQiLFVpbnQ4QXJyYXldXSksYWU9bmV3IE1hcChbW0Zsb2F0MzJBcnJheSwiZmxvYXQzMiJdLFtVaW50OEFycmF5LCJ1aW50OCJdLFtJbnQ4QXJyYXksImludDgiXSxbVWludDE2QXJyYXksInVpbnQxNiJdLFtJbnQxNkFycmF5LCJpbnQxNiJdLFtJbnQzMkFycmF5LCJpbnQzMiJdLFtGbG9hdDY0QXJyYXksImZsb2F0NjQiXSxbVWludDMyQXJyYXksInVpbnQzMiJdXSksQXQ9ITEsT3Q9KCk9PntpZighQXQpe0F0PSEwO2xldCBlPXR5cGVvZiBCaWdJbnQ2NEFycmF5PCJ1IiYmQmlnSW50NjRBcnJheS5mcm9tLHQ9dHlwZW9mIEJpZ1VpbnQ2NEFycmF5PCJ1IiYmQmlnVWludDY0QXJyYXkuZnJvbSxyPWdsb2JhbFRoaXMuRmxvYXQxNkFycmF5LG49dHlwZW9mIHI8InUiJiZyLmZyb207ZSYmKEguc2V0KCJpbnQ2NCIsQmlnSW50NjRBcnJheSksYWUuc2V0KEJpZ0ludDY0QXJyYXksImludDY0IikpLHQmJihILnNldCgidWludDY0IixCaWdVaW50NjRBcnJheSksYWUuc2V0KEJpZ1VpbnQ2NEFycmF5LCJ1aW50NjQiKSksbj8oSC5zZXQoImZsb2F0MTYiLHIpLGFlLnNldChyLCJmbG9hdDE2IikpOkguc2V0KCJmbG9hdDE2IixVaW50MTZBcnJheSk7fX07fSkpLFB0PVQoKCgpPT57d2UoKSxMdD1lPT57bGV0IHQ9MTtmb3IobGV0IHI9MDtyPGUubGVuZ3RoO3IrKyl7bGV0IG49ZVtyXTtpZigibnVtYmVyIiE9dHlwZW9mIG58fCFOdW1iZXIuaXNTYWZlSW50ZWdlcihuKSl0aHJvdyBuZXcgVHlwZUVycm9yKGBkaW1zWyR7cn1dIG11c3QgYmUgYW4gaW50ZWdlciwgZ290OiAke259YCk7aWYobjwwKXRocm93IG5ldyBSYW5nZUVycm9yKGBkaW1zWyR7cn1dIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlciwgZ290OiAke259YCk7dCo9bjt9cmV0dXJuIHR9LEl0PShlLHQpPT57c3dpdGNoKGUubG9jYXRpb24pe2Nhc2UiY3B1IjpyZXR1cm4gbmV3IHYoZS50eXBlLGUuZGF0YSx0KTtjYXNlImNwdS1waW5uZWQiOnJldHVybiBuZXcgdih7bG9jYXRpb246ImNwdS1waW5uZWQiLGRhdGE6ZS5kYXRhLHR5cGU6ZS50eXBlLGRpbXM6dH0pO2Nhc2UidGV4dHVyZSI6cmV0dXJuIG5ldyB2KHtsb2NhdGlvbjoidGV4dHVyZSIsdGV4dHVyZTplLnRleHR1cmUsdHlwZTplLnR5cGUsZGltczp0fSk7Y2FzZSJncHUtYnVmZmVyIjpyZXR1cm4gbmV3IHYoe2xvY2F0aW9uOiJncHUtYnVmZmVyIixncHVCdWZmZXI6ZS5ncHVCdWZmZXIsdHlwZTplLnR5cGUsZGltczp0fSk7Y2FzZSJtbC10ZW5zb3IiOnJldHVybiBuZXcgdih7bG9jYXRpb246Im1sLXRlbnNvciIsbWxUZW5zb3I6ZS5tbFRlbnNvcix0eXBlOmUudHlwZSxkaW1zOnR9KTtkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgdGVuc29yUmVzaGFwZTogdGVuc29yIGxvY2F0aW9uICR7ZS5sb2NhdGlvbn0gaXMgbm90IHN1cHBvcnRlZGApfX07fSkpLHdlPVQoKCgpPT57d3QoKSxTdCgpLHh0KCksUHQoKSx2PWNsYXNze2NvbnN0cnVjdG9yKGUsdCxyKXtsZXQgbixvO2lmKE90KCksIm9iamVjdCI9PXR5cGVvZiBlJiYibG9jYXRpb24iaW4gZSlzd2l0Y2godGhpcy5kYXRhTG9jYXRpb249ZS5sb2NhdGlvbixuPWUudHlwZSxvPWUuZGltcyxlLmxvY2F0aW9uKXtjYXNlImNwdS1waW5uZWQiOntsZXQgdD1ILmdldChuKTtpZighdCl0aHJvdyBuZXcgVHlwZUVycm9yKGB1bnN1cHBvcnRlZCB0eXBlICIke259IiB0byBjcmVhdGUgdGVuc29yIGZyb20gcGlubmVkIGJ1ZmZlcmApO2lmKCEoZS5kYXRhIGluc3RhbmNlb2YgdCkpdGhyb3cgbmV3IFR5cGVFcnJvcihgYnVmZmVyIHNob3VsZCBiZSBvZiB0eXBlICR7dC5uYW1lfWApO3RoaXMuY3B1RGF0YT1lLmRhdGE7YnJlYWt9Y2FzZSJ0ZXh0dXJlIjppZigiZmxvYXQzMiIhPT1uKXRocm93IG5ldyBUeXBlRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGUgIiR7bn0iIHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbSB0ZXh0dXJlYCk7dGhpcy5ncHVUZXh0dXJlRGF0YT1lLnRleHR1cmUsdGhpcy5kb3dubG9hZGVyPWUuZG93bmxvYWQsdGhpcy5kaXNwb3Nlcj1lLmRpc3Bvc2U7YnJlYWs7Y2FzZSJncHUtYnVmZmVyIjppZigiZmxvYXQzMiIhPT1uJiYiZmxvYXQxNiIhPT1uJiYiaW50MzIiIT09biYmImludDY0IiE9PW4mJiJ1aW50MzIiIT09biYmInVpbnQ4IiE9PW4mJiJib29sIiE9PW4mJiJ1aW50NCIhPT1uJiYiaW50NCIhPT1uKXRocm93IG5ldyBUeXBlRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGUgIiR7bn0iIHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbSBncHUgYnVmZmVyYCk7dGhpcy5ncHVCdWZmZXJEYXRhPWUuZ3B1QnVmZmVyLHRoaXMuZG93bmxvYWRlcj1lLmRvd25sb2FkLHRoaXMuZGlzcG9zZXI9ZS5kaXNwb3NlO2JyZWFrO2Nhc2UibWwtdGVuc29yIjppZigiZmxvYXQzMiIhPT1uJiYiZmxvYXQxNiIhPT1uJiYiaW50MzIiIT09biYmImludDY0IiE9PW4mJiJ1aW50MzIiIT09biYmInVpbnQ2NCIhPT1uJiYiaW50OCIhPT1uJiYidWludDgiIT09biYmImJvb2wiIT09biYmInVpbnQ0IiE9PW4mJiJpbnQ0IiE9PW4pdGhyb3cgbmV3IFR5cGVFcnJvcihgdW5zdXBwb3J0ZWQgdHlwZSAiJHtufSIgdG8gY3JlYXRlIHRlbnNvciBmcm9tIE1MVGVuc29yYCk7dGhpcy5tbFRlbnNvckRhdGE9ZS5tbFRlbnNvcix0aGlzLmRvd25sb2FkZXI9ZS5kb3dubG9hZCx0aGlzLmRpc3Bvc2VyPWUuZGlzcG9zZTticmVhaztkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgVGVuc29yIGNvbnN0cnVjdG9yOiB1bnN1cHBvcnRlZCBsb2NhdGlvbiAnJHt0aGlzLmRhdGFMb2NhdGlvbn0nYCl9ZWxzZSB7bGV0IGEsaTtpZigic3RyaW5nIj09dHlwZW9mIGUpaWYobj1lLGk9ciwic3RyaW5nIj09PWUpe2lmKCFBcnJheS5pc0FycmF5KHQpKXRocm93IG5ldyBUeXBlRXJyb3IoIkEgc3RyaW5nIHRlbnNvcidzIGRhdGEgbXVzdCBiZSBhIHN0cmluZyBhcnJheS4iKTthPXQ7fWVsc2Uge2xldCByPUguZ2V0KGUpO2lmKHZvaWQgMD09PXIpdGhyb3cgbmV3IFR5cGVFcnJvcihgVW5zdXBwb3J0ZWQgdGVuc29yIHR5cGU6ICR7ZX0uYCk7aWYoQXJyYXkuaXNBcnJheSh0KSl7aWYoImZsb2F0MTYiPT09ZSYmcj09PVVpbnQxNkFycmF5fHwidWludDQiPT09ZXx8ImludDQiPT09ZSl0aHJvdyBuZXcgVHlwZUVycm9yKGBDcmVhdGluZyBhICR7ZX0gdGVuc29yIGZyb20gbnVtYmVyIGFycmF5IGlzIG5vdCBzdXBwb3J0ZWQuIFBsZWFzZSB1c2UgJHtyLm5hbWV9IGFzIGRhdGEuYCk7YT0idWludDY0Ij09PWV8fCJpbnQ2NCI9PT1lP3IuZnJvbSh0LEJpZ0ludCk6ci5mcm9tKHQpO31lbHNlIGlmKHQgaW5zdGFuY2VvZiByKWE9dDtlbHNlIGlmKHQgaW5zdGFuY2VvZiBVaW50OENsYW1wZWRBcnJheSl7aWYoInVpbnQ4IiE9PWUpdGhyb3cgbmV3IFR5cGVFcnJvcigiQSBVaW50OENsYW1wZWRBcnJheSB0ZW5zb3IncyBkYXRhIG11c3QgYmUgdHlwZSBvZiB1aW50OCIpO2E9VWludDhBcnJheS5mcm9tKHQpO31lbHNlIHtpZighKCJmbG9hdDE2Ij09PWUmJnQgaW5zdGFuY2VvZiBVaW50MTZBcnJheSYmciE9PVVpbnQxNkFycmF5KSl0aHJvdyBuZXcgVHlwZUVycm9yKGBBICR7bn0gdGVuc29yJ3MgZGF0YSBtdXN0IGJlIHR5cGUgb2YgJHtyfWApO2E9bmV3IGdsb2JhbFRoaXMuRmxvYXQxNkFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0Lmxlbmd0aCk7fX1lbHNlIGlmKGk9dCxBcnJheS5pc0FycmF5KGUpKXtpZigwPT09ZS5sZW5ndGgpdGhyb3cgbmV3IFR5cGVFcnJvcigiVGVuc29yIHR5cGUgY2Fubm90IGJlIGluZmVycmVkIGZyb20gYW4gZW1wdHkgYXJyYXkuIik7bGV0IHQ9dHlwZW9mIGVbMF07aWYoInN0cmluZyI9PT10KW49InN0cmluZyIsYT1lO2Vsc2Uge2lmKCJib29sZWFuIiE9PXQpdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBlbGVtZW50IHR5cGUgb2YgZGF0YSBhcnJheTogJHt0fS5gKTtuPSJib29sIixhPVVpbnQ4QXJyYXkuZnJvbShlKTt9fWVsc2UgaWYoZSBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5KW49InVpbnQ4IixhPVVpbnQ4QXJyYXkuZnJvbShlKTtlbHNlIHtsZXQgdD1hZS5nZXQoZS5jb25zdHJ1Y3Rvcik7aWYodm9pZCAwPT09dCl0aHJvdyBuZXcgVHlwZUVycm9yKGBVbnN1cHBvcnRlZCB0eXBlIGZvciB0ZW5zb3IgZGF0YTogJHtlLmNvbnN0cnVjdG9yfS5gKTtuPXQsYT1lO31pZih2b2lkIDA9PT1pKWk9W2EubGVuZ3RoXTtlbHNlIGlmKCFBcnJheS5pc0FycmF5KGkpKXRocm93IG5ldyBUeXBlRXJyb3IoIkEgdGVuc29yJ3MgZGltcyBtdXN0IGJlIGEgbnVtYmVyIGFycmF5Iik7bz1pLHRoaXMuY3B1RGF0YT1hLHRoaXMuZGF0YUxvY2F0aW9uPSJjcHUiO31sZXQgYT1MdChvKTtpZih0aGlzLmNwdURhdGEmJmEhPT10aGlzLmNwdURhdGEubGVuZ3RoJiYoInVpbnQ0IiE9PW4mJiJpbnQ0IiE9PW58fE1hdGguY2VpbChhLzIpIT09dGhpcy5jcHVEYXRhLmxlbmd0aCkpdGhyb3cgbmV3IEVycm9yKGBUZW5zb3IncyBzaXplKCR7YX0pIGRvZXMgbm90IG1hdGNoIGRhdGEgbGVuZ3RoKCR7dGhpcy5jcHVEYXRhLmxlbmd0aH0pLmApO3RoaXMudHlwZT1uLHRoaXMuZGltcz1vLHRoaXMuc2l6ZT1hO31zdGF0aWMgYXN5bmMgZnJvbUltYWdlKGUsdCl7cmV0dXJuIHl0KGUsdCl9c3RhdGljIGZyb21UZXh0dXJlKGUsdCl7cmV0dXJuIGJ0KGUsdCl9c3RhdGljIGZyb21HcHVCdWZmZXIoZSx0KXtyZXR1cm4gZ3QoZSx0KX1zdGF0aWMgZnJvbU1MVGVuc29yKGUsdCl7cmV0dXJuIEV0KGUsdCl9c3RhdGljIGZyb21QaW5uZWRCdWZmZXIoZSx0LHIpe3JldHVybiBUdChlLHQscil9dG9EYXRhVVJMKGUpe3JldHVybiBtdCh0aGlzLGUpfXRvSW1hZ2VEYXRhKGUpe3JldHVybiBodCh0aGlzLGUpfWdldCBkYXRhKCl7aWYodGhpcy5lbnN1cmVWYWxpZCgpLCF0aGlzLmNwdURhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgb24gQ1BVLiBVc2UgYGdldERhdGEoKWAgdG8gZG93bmxvYWQgR1BVIGRhdGEgdG8gQ1BVLCBvciB1c2UgYHRleHR1cmVgIG9yIGBncHVCdWZmZXJgIHByb3BlcnR5IHRvIGFjY2VzcyB0aGUgR1BVIGRhdGEgZGlyZWN0bHkuIik7cmV0dXJuIHRoaXMuY3B1RGF0YX1nZXQgbG9jYXRpb24oKXtyZXR1cm4gdGhpcy5kYXRhTG9jYXRpb259Z2V0IHRleHR1cmUoKXtpZih0aGlzLmVuc3VyZVZhbGlkKCksIXRoaXMuZ3B1VGV4dHVyZURhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViR0wgdGV4dHVyZS4iKTtyZXR1cm4gdGhpcy5ncHVUZXh0dXJlRGF0YX1nZXQgZ3B1QnVmZmVyKCl7aWYodGhpcy5lbnN1cmVWYWxpZCgpLCF0aGlzLmdwdUJ1ZmZlckRhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViR1BVIGJ1ZmZlci4iKTtyZXR1cm4gdGhpcy5ncHVCdWZmZXJEYXRhfWdldCBtbFRlbnNvcigpe2lmKHRoaXMuZW5zdXJlVmFsaWQoKSwhdGhpcy5tbFRlbnNvckRhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViTk4gTUxUZW5zb3IuIik7cmV0dXJuIHRoaXMubWxUZW5zb3JEYXRhfWFzeW5jIGdldERhdGEoZSl7c3dpdGNoKHRoaXMuZW5zdXJlVmFsaWQoKSx0aGlzLmRhdGFMb2NhdGlvbil7Y2FzZSJjcHUiOmNhc2UiY3B1LXBpbm5lZCI6cmV0dXJuIHRoaXMuZGF0YTtjYXNlInRleHR1cmUiOmNhc2UiZ3B1LWJ1ZmZlciI6Y2FzZSJtbC10ZW5zb3IiOmlmKCF0aGlzLmRvd25sb2FkZXIpdGhyb3cgbmV3IEVycm9yKCJUaGUgY3VycmVudCB0ZW5zb3IgaXMgbm90IGNyZWF0ZWQgd2l0aCBhIHNwZWNpZmllZCBkYXRhIGRvd25sb2FkZXIuIik7aWYodGhpcy5pc0Rvd25sb2FkaW5nKXRocm93IG5ldyBFcnJvcigiVGhlIGN1cnJlbnQgdGVuc29yIGlzIGJlaW5nIGRvd25sb2FkZWQuIik7dHJ5e3RoaXMuaXNEb3dubG9hZGluZz0hMDtsZXQgdD1hd2FpdCB0aGlzLmRvd25sb2FkZXIoKTtyZXR1cm4gdGhpcy5kb3dubG9hZGVyPXZvaWQgMCx0aGlzLmRhdGFMb2NhdGlvbj0iY3B1Iix0aGlzLmNwdURhdGE9dCxlJiZ0aGlzLmRpc3Bvc2VyJiYodGhpcy5kaXNwb3NlcigpLHRoaXMuZGlzcG9zZXI9dm9pZCAwKSx0fWZpbmFsbHl7dGhpcy5pc0Rvd25sb2FkaW5nPSExO31kZWZhdWx0OnRocm93IG5ldyBFcnJvcihgY2Fubm90IGdldCBkYXRhIGZyb20gbG9jYXRpb246ICR7dGhpcy5kYXRhTG9jYXRpb259YCl9fWRpc3Bvc2UoKXtpZih0aGlzLmlzRG93bmxvYWRpbmcpdGhyb3cgbmV3IEVycm9yKCJUaGUgY3VycmVudCB0ZW5zb3IgaXMgYmVpbmcgZG93bmxvYWRlZC4iKTt0aGlzLmRpc3Bvc2VyJiYodGhpcy5kaXNwb3NlcigpLHRoaXMuZGlzcG9zZXI9dm9pZCAwKSx0aGlzLmNwdURhdGE9dm9pZCAwLHRoaXMuZ3B1VGV4dHVyZURhdGE9dm9pZCAwLHRoaXMuZ3B1QnVmZmVyRGF0YT12b2lkIDAsdGhpcy5tbFRlbnNvckRhdGE9dm9pZCAwLHRoaXMuZG93bmxvYWRlcj12b2lkIDAsdGhpcy5pc0Rvd25sb2FkaW5nPXZvaWQgMCx0aGlzLmRhdGFMb2NhdGlvbj0ibm9uZSI7fWVuc3VyZVZhbGlkKCl7aWYoIm5vbmUiPT09dGhpcy5kYXRhTG9jYXRpb24pdGhyb3cgbmV3IEVycm9yKCJUaGUgdGVuc29yIGlzIGRpc3Bvc2VkLiIpfXJlc2hhcGUoZSl7aWYodGhpcy5lbnN1cmVWYWxpZCgpLHRoaXMuZG93bmxvYWRlcnx8dGhpcy5kaXNwb3Nlcil0aHJvdyBuZXcgRXJyb3IoIkNhbm5vdCByZXNoYXBlIGEgdGVuc29yIHRoYXQgb3ducyBHUFUgcmVzb3VyY2UuIik7cmV0dXJuIEl0KHRoaXMsZSl9fTt9KSksVmU9VCgoKCk9Pnt3ZSgpLFI9djt9KSksWWU9VCgoKCk9PntqZSgpLHZ0PShlLHQpPT57KHR5cGVvZiBfLnRyYWNlPiJ1Ij8hXy53YXNtLnRyYWNlOiFfLnRyYWNlKXx8Y29uc29sZS50aW1lU3RhbXAoYCR7ZX06Ok9SVDo6JHt0fWApO30sQnQ9KGUsdCk9PntsZXQgcj0obmV3IEVycm9yKS5zdGFjaz8uc3BsaXQoL1xyXG58XHJ8XG4vZyl8fFtdLG49ITE7Zm9yKGxldCBvPTA7bzxyLmxlbmd0aDtvKyspe2lmKG4mJiFyW29dLmluY2x1ZGVzKCJUUkFDRV9GVU5DIikpe2xldCBuPWBGVU5DXyR7ZX06OiR7cltvXS50cmltKCkuc3BsaXQoIiAiKVsxXX1gO3JldHVybiB0JiYobis9YDo6JHt0fWApLHZvaWQgdnQoIkNQVSIsbil9cltvXS5pbmNsdWRlcygiVFJBQ0VfRlVOQyIpJiYobj0hMCk7fX0sVj1lPT57KHR5cGVvZiBfLnRyYWNlPiJ1Ij8hXy53YXNtLnRyYWNlOiFfLnRyYWNlKXx8QnQoIkJFR0lOIixlKTt9LFk9ZT0+eyh0eXBlb2YgXy50cmFjZT4idSI/IV8ud2FzbS50cmFjZTohXy50cmFjZSl8fEJ0KCJFTkQiLGUpO307fSkpLEN0PVQoKCgpPT57emUoKSxWZSgpLFllKCkseWU9Y2xhc3MgZXtjb25zdHJ1Y3RvcihlKXt0aGlzLmhhbmRsZXI9ZTt9YXN5bmMgcnVuKGUsdCxyKXtWKCk7bGV0IG49e30sbz17fTtpZigib2JqZWN0IiE9dHlwZW9mIGV8fG51bGw9PT1lfHxlIGluc3RhbmNlb2YgUnx8QXJyYXkuaXNBcnJheShlKSl0aHJvdyBuZXcgVHlwZUVycm9yKCInZmVlZHMnIG11c3QgYmUgYW4gb2JqZWN0IHRoYXQgdXNlIGlucHV0IG5hbWVzIGFzIGtleXMgYW5kIE9ubnhWYWx1ZSBhcyBjb3JyZXNwb25kaW5nIHZhbHVlcy4iKTtsZXQgYT0hMDtpZigib2JqZWN0Ij09dHlwZW9mIHQpe2lmKG51bGw9PT10KXRocm93IG5ldyBUeXBlRXJyb3IoIlVuZXhwZWN0ZWQgYXJndW1lbnRbMV06IGNhbm5vdCBiZSBudWxsLiIpO2lmKHQgaW5zdGFuY2VvZiBSKXRocm93IG5ldyBUeXBlRXJyb3IoIidmZXRjaGVzJyBjYW5ub3QgYmUgYSBUZW5zb3IiKTtpZihBcnJheS5pc0FycmF5KHQpKXtpZigwPT09dC5sZW5ndGgpdGhyb3cgbmV3IFR5cGVFcnJvcigiJ2ZldGNoZXMnIGNhbm5vdCBiZSBhbiBlbXB0eSBhcnJheS4iKTthPSExO2ZvcihsZXQgZSBvZiB0KXtpZigic3RyaW5nIiE9dHlwZW9mIGUpdGhyb3cgbmV3IFR5cGVFcnJvcigiJ2ZldGNoZXMnIG11c3QgYmUgYSBzdHJpbmcgYXJyYXkgb3IgYW4gb2JqZWN0LiIpO2lmKC0xPT09dGhpcy5vdXRwdXROYW1lcy5pbmRleE9mKGUpKXRocm93IG5ldyBSYW5nZUVycm9yKGAnZmV0Y2hlcycgY29udGFpbnMgaW52YWxpZCBvdXRwdXQgbmFtZTogJHtlfS5gKTtuW2VdPW51bGw7fWlmKCJvYmplY3QiPT10eXBlb2YgciYmbnVsbCE9PXIpbz1yO2Vsc2UgaWYodHlwZW9mIHI8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIHtsZXQgZT0hMSxpPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHQpO2ZvcihsZXQgciBvZiB0aGlzLm91dHB1dE5hbWVzKWlmKC0xIT09aS5pbmRleE9mKHIpKXtsZXQgbz10W3JdOyhudWxsPT09b3x8byBpbnN0YW5jZW9mIFIpJiYoZT0hMCxhPSExLG5bcl09byk7fWlmKGUpe2lmKCJvYmplY3QiPT10eXBlb2YgciYmbnVsbCE9PXIpbz1yO2Vsc2UgaWYodHlwZW9mIHI8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIG89dDt9fWVsc2UgaWYodHlwZW9mIHQ8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIlVuZXhwZWN0ZWQgYXJndW1lbnRbMV06IG11c3QgYmUgJ2ZldGNoZXMnIG9yICdvcHRpb25zJy4iKTtmb3IobGV0IHQgb2YgdGhpcy5pbnB1dE5hbWVzKWlmKHR5cGVvZiBlW3RdPiJ1Iil0aHJvdyBuZXcgRXJyb3IoYGlucHV0ICcke3R9JyBpcyBtaXNzaW5nIGluICdmZWVkcycuYCk7aWYoYSlmb3IobGV0IGUgb2YgdGhpcy5vdXRwdXROYW1lcyluW2VdPW51bGw7bGV0IGk9YXdhaXQgdGhpcy5oYW5kbGVyLnJ1bihlLG4sbykscz17fTtmb3IobGV0IGUgaW4gaSlpZihPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChpLGUpKXtsZXQgdD1pW2VdO3NbZV09dCBpbnN0YW5jZW9mIFI/dDpuZXcgUih0LnR5cGUsdC5kYXRhLHQuZGltcyk7fXJldHVybiBZKCksc31hc3luYyByZWxlYXNlKCl7cmV0dXJuIHRoaXMuaGFuZGxlci5kaXNwb3NlKCl9c3RhdGljIGFzeW5jIGNyZWF0ZSh0LHIsbixvKXtWKCk7bGV0IGEsaT17fTtpZigic3RyaW5nIj09dHlwZW9mIHQpe2lmKGE9dCwib2JqZWN0Ij09dHlwZW9mIHImJm51bGwhPT1yKWk9cjtlbHNlIGlmKHR5cGVvZiByPCJ1Iil0aHJvdyBuZXcgVHlwZUVycm9yKCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuIil9ZWxzZSBpZih0IGluc3RhbmNlb2YgVWludDhBcnJheSl7aWYoYT10LCJvYmplY3QiPT10eXBlb2YgciYmbnVsbCE9PXIpaT1yO2Vsc2UgaWYodHlwZW9mIHI8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIHtpZighKHQgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcnx8dHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyPCJ1IiYmdCBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyKSl0aHJvdyBuZXcgVHlwZUVycm9yKCJVbmV4cGVjdGVkIGFyZ3VtZW50WzBdOiBtdXN0IGJlICdwYXRoJyBvciAnYnVmZmVyJy4iKTt7bGV0IGU9dCxzPTAsbD10LmJ5dGVMZW5ndGg7aWYoIm9iamVjdCI9PXR5cGVvZiByJiZudWxsIT09cilpPXI7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIHIpe2lmKHM9ciwhTnVtYmVyLmlzU2FmZUludGVnZXIocykpdGhyb3cgbmV3IFJhbmdlRXJyb3IoIidieXRlT2Zmc2V0JyBtdXN0IGJlIGFuIGludGVnZXIuIik7aWYoczwwfHxzPj1lLmJ5dGVMZW5ndGgpdGhyb3cgbmV3IFJhbmdlRXJyb3IoYCdieXRlT2Zmc2V0JyBpcyBvdXQgb2YgcmFuZ2UgWzAsICR7ZS5ieXRlTGVuZ3RofSkuYCk7aWYobD10LmJ5dGVMZW5ndGgtcywibnVtYmVyIj09dHlwZW9mIG4pe2lmKGw9biwhTnVtYmVyLmlzU2FmZUludGVnZXIobCkpdGhyb3cgbmV3IFJhbmdlRXJyb3IoIidieXRlTGVuZ3RoJyBtdXN0IGJlIGFuIGludGVnZXIuIik7aWYobDw9MHx8cytsPmUuYnl0ZUxlbmd0aCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihgJ2J5dGVMZW5ndGgnIGlzIG91dCBvZiByYW5nZSAoMCwgJHtlLmJ5dGVMZW5ndGgtc31dLmApO2lmKCJvYmplY3QiPT10eXBlb2YgbyYmbnVsbCE9PW8paT1vO2Vsc2UgaWYodHlwZW9mIG88InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIGlmKHR5cGVvZiBuPCJ1Iil0aHJvdyBuZXcgVHlwZUVycm9yKCInYnl0ZUxlbmd0aCcgbXVzdCBiZSBhIG51bWJlci4iKX1lbHNlIGlmKHR5cGVvZiByPCJ1Iil0aHJvdyBuZXcgVHlwZUVycm9yKCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuIik7YT1uZXcgVWludDhBcnJheShlLHMsbCk7fX1sZXRbcyxsXT1hd2FpdCB1dChpKSx1PWF3YWl0IHMuY3JlYXRlSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIoYSxsKTtyZXR1cm4gWSgpLG5ldyBlKHUpfXN0YXJ0UHJvZmlsaW5nKCl7dGhpcy5oYW5kbGVyLnN0YXJ0UHJvZmlsaW5nKCk7fWVuZFByb2ZpbGluZygpe3RoaXMuaGFuZGxlci5lbmRQcm9maWxpbmcoKTt9Z2V0IGlucHV0TmFtZXMoKXtyZXR1cm4gdGhpcy5oYW5kbGVyLmlucHV0TmFtZXN9Z2V0IG91dHB1dE5hbWVzKCl7cmV0dXJuIHRoaXMuaGFuZGxlci5vdXRwdXROYW1lc319O30pKSxVdD1UKCgoKT0+e0N0KCksT3I9eWU7fSkpLF90PVQoKCgpPT57fSkpLE10PVQoKCgpPT57fSkpLER0PVQoKCgpPT57fSkpLFJ0PVQoKCgpPT57fSkpLHFlPXt9O0dlKHFlLHtJbmZlcmVuY2VTZXNzaW9uOigpPT5PcixUUkFDRTooKT0+dnQsVFJBQ0VfRlVOQ19CRUdJTjooKT0+VixUUkFDRV9GVU5DX0VORDooKT0+WSxUZW5zb3I6KCk9PlIsZW52OigpPT5BLHJlZ2lzdGVyQmFja2VuZDooKT0+aWV9KTt2YXIgcT1UKCgoKT0+e2Z0KCkscHQoKSxVdCgpLFZlKCksX3QoKSxNdCgpLFllKCksRHQoKSxSdCgpO30pKSxiZT1UKCgoKT0+e30pKSxXdD17fTtHZShXdCx7ZGVmYXVsdDooKT0+eHJ9KTt2YXIga3QsTnQseHIsanQsTSxQZSxYZSxJcixQcixIdCx2cixHdCxWdCx6dCxZdCxaZSxLZSx2ZSxxdCxCcixDcixFZSx4LEwsZmUsUyxKdCxVcixfcixNcixEcixadCxlZSxRdCx0ZSxlcix0cixDZSxVZSxycixjZSxScixUZSxTZSxyZSxGcix1ZSxBZSxPZSxucix4ZSxMZSxJZSxaLEQsbGUsTWUsRGUsX2UsdHQscnQsbmUsb2UsTnIsb3Isc3IsaXIsYXIsdXIsZnIsY3IsbHIsV3IsUmUsJHQ9VCgoKCk9PntKZSgpLEooKSxnZSgpLGt0PSJvcnQtd2FzbS1wcm94eS13b3JrZXIiLChOdD1nbG9iYWxUaGlzLnNlbGY/Lm5hbWU9PT1rdCkmJihzZWxmLm9ubWVzc2FnZT1lPT57bGV0e3R5cGU6dCxpbjpyfT1lLmRhdGE7dHJ5e3N3aXRjaCh0KXtjYXNlImluaXQtd2FzbSI6RWUoci53YXNtKS50aGVuKCgoKT0+e1RlKHIpLnRoZW4oKCgpPT57cG9zdE1lc3NhZ2Uoe3R5cGU6dH0pO30pLChlPT57cG9zdE1lc3NhZ2Uoe3R5cGU6dCxlcnI6ZX0pO30pKTt9KSwoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsZXJyOmV9KTt9KSk7YnJlYWs7Y2FzZSJpbml0LWVwIjp7bGV0e2VwTmFtZTplLGVudjpufT1yO1NlKG4sZSkudGhlbigoKCk9Pntwb3N0TWVzc2FnZSh7dHlwZTp0fSk7fSksKGU9Pntwb3N0TWVzc2FnZSh7dHlwZTp0LGVycjplfSk7fSkpO2JyZWFrfWNhc2UiY29weS1mcm9tIjp7bGV0e2J1ZmZlcjplfT1yLG49dWUoZSk7cG9zdE1lc3NhZ2Uoe3R5cGU6dCxvdXQ6bn0pO2JyZWFrfWNhc2UiY3JlYXRlIjp7bGV0e21vZGVsOmUsb3B0aW9uczpufT1yO0FlKGUsbikudGhlbigoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsb3V0OmV9KTt9KSwoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsZXJyOmV9KTt9KSk7YnJlYWt9Y2FzZSJyZWxlYXNlIjpPZShyKSxwb3N0TWVzc2FnZSh7dHlwZTp0fSk7YnJlYWs7Y2FzZSJydW4iOntsZXR7c2Vzc2lvbklkOmUsaW5wdXRJbmRpY2VzOm4saW5wdXRzOm8sb3V0cHV0SW5kaWNlczphLG9wdGlvbnM6aX09cjt4ZShlLG4sbyxhLG5ldyBBcnJheShhLmxlbmd0aCkuZmlsbChudWxsKSxpKS50aGVuKChlPT57ZS5zb21lKChlPT4iY3B1IiE9PWVbM10pKT9wb3N0TWVzc2FnZSh7dHlwZTp0LGVycjoiUHJveHkgZG9lcyBub3Qgc3VwcG9ydCBub24tY3B1IHRlbnNvciBsb2NhdGlvbi4ifSk6cG9zdE1lc3NhZ2Uoe3R5cGU6dCxvdXQ6ZX0sSWUoWy4uLm8sLi4uZV0pKTt9KSwoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsZXJyOmV9KTt9KSk7YnJlYWt9Y2FzZSJlbmQtcHJvZmlsaW5nIjpMZShyKSxwb3N0TWVzc2FnZSh7dHlwZTp0fSk7fX1jYXRjaChlKXtwb3N0TWVzc2FnZSh7dHlwZTp0LGVycjplfSk7fX0pLHhyPU50P251bGw6ZT0+bmV3IFdvcmtlcihlPz9NLHt0eXBlOiJtb2R1bGUiLG5hbWU6a3R9KTt9KSksZ2U9VCgoKCk9PntiZSgpLGp0PXR5cGVvZiBsb2NhdGlvbj4idSI/dm9pZCAwOmxvY2F0aW9uLm9yaWdpbixNPSgoKT0+aW1wb3J0Lm1ldGEudXJsPy5zdGFydHNXaXRoKCJmaWxlOiIpP25ldyBVUkwobmV3IFVSTCgib3J0Lndhc20uYnVuZGxlLm1pbi5tanMiLGltcG9ydC5tZXRhLnVybCkuaHJlZixqdCkuaHJlZjppbXBvcnQubWV0YS51cmwpKCksUGU9KCk9PntpZihNJiYhTS5zdGFydHNXaXRoKCJibG9iOiIpKXJldHVybiBNLnN1YnN0cmluZygwLE0ubGFzdEluZGV4T2YoIi8iKSsxKX0sWGU9KGUsdCk9Pnt0cnl7bGV0IHI9dD8/TTtyZXR1cm4gKHI/bmV3IFVSTChlLHIpOm5ldyBVUkwoZSkpLm9yaWdpbj09PWp0fWNhdGNoe3JldHVybiAhMX19LElyPShlLHQpPT57bGV0IHI9dD8/TTt0cnl7cmV0dXJuIChyP25ldyBVUkwoZSxyKTpuZXcgVVJMKGUpKS5ocmVmfWNhdGNoe3JldHVybn19LFByPShlLHQpPT5gJHt0Pz8iLi8ifSR7ZX1gLEh0PWFzeW5jIGU9PntsZXQgdD1hd2FpdChhd2FpdCBmZXRjaChlLHtjcmVkZW50aWFsczoic2FtZS1vcmlnaW4ifSkpLmJsb2IoKTtyZXR1cm4gVVJMLmNyZWF0ZU9iamVjdFVSTCh0KX0sdnI9YXN5bmMgZT0+KGF3YWl0IGltcG9ydChlKSkuZGVmYXVsdCxHdD0oJHQoKSxhdChXdCkpLmRlZmF1bHQsVnQ9YXN5bmMoKT0+e2lmKCFNKXRocm93IG5ldyBFcnJvcigiRmFpbGVkIHRvIGxvYWQgcHJveHkgd29ya2VyOiBjYW5ub3QgZGV0ZXJtaW5lIHRoZSBzY3JpcHQgc291cmNlIFVSTC4iKTtpZihYZShNKSlyZXR1cm4gW3ZvaWQgMCxHdCgpXTtsZXQgZT1hd2FpdCBIdChNKTtyZXR1cm4gW2UsR3QoZSldfSx6dD12b2lkIDAsWXQ9YXN5bmMoZSx0LHIpPT57aWYoIWUmJiF0JiZ6dCYmTSYmWGUoTSkpcmV0dXJuIFt2b2lkIDAsenRdO3tsZXQgbj0ib3J0LXdhc20tc2ltZC10aHJlYWRlZC5tanMiLG89ZT8/SXIobix0KSxhPXImJm8mJiFYZShvLHQpLGk9YT9hd2FpdCBIdChvKTpvPz9QcihuLHQpO3JldHVybiBbYT9pOnZvaWQgMCxhd2FpdCB2cihpKV19fTt9KSksSj1UKCgoKT0+e2dlKCksS2U9ITEsdmU9ITEscXQ9ITEsQnI9KCk9PntpZih0eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXI+InUiKXJldHVybiAhMTt0cnl7cmV0dXJuIHR5cGVvZiBNZXNzYWdlQ2hhbm5lbDwidSImJihuZXcgTWVzc2FnZUNoYW5uZWwpLnBvcnQxLnBvc3RNZXNzYWdlKG5ldyBTaGFyZWRBcnJheUJ1ZmZlcigxKSksV2ViQXNzZW1ibHkudmFsaWRhdGUobmV3IFVpbnQ4QXJyYXkoWzAsOTcsMTE1LDEwOSwxLDAsMCwwLDEsNCwxLDk2LDAsMCwzLDIsMSwwLDUsNCwxLDMsMSwxLDEwLDExLDEsOSwwLDY1LDAsMjU0LDE2LDIsMCwyNiwxMV0pKX1jYXRjaHtyZXR1cm4gITF9fSxDcj0oKT0+e3RyeXtyZXR1cm4gV2ViQXNzZW1ibHkudmFsaWRhdGUobmV3IFVpbnQ4QXJyYXkoWzAsOTcsMTE1LDEwOSwxLDAsMCwwLDEsNCwxLDk2LDAsMCwzLDIsMSwwLDEwLDMwLDEsMjgsMCw2NSwwLDI1MywxNSwyNTMsMTIsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwyNTMsMTg2LDEsMjYsMTFdKSl9Y2F0Y2h7cmV0dXJuICExfX0sRWU9YXN5bmMgZT0+e2lmKEtlKXJldHVybiBQcm9taXNlLnJlc29sdmUoKTtpZih2ZSl0aHJvdyBuZXcgRXJyb3IoIm11bHRpcGxlIGNhbGxzIHRvICdpbml0aWFsaXplV2ViQXNzZW1ibHkoKScgZGV0ZWN0ZWQuIik7aWYocXQpdGhyb3cgbmV3IEVycm9yKCJwcmV2aW91cyBjYWxsIHRvICdpbml0aWFsaXplV2ViQXNzZW1ibHkoKScgZmFpbGVkLiIpO3ZlPSEwO2xldCB0PWUuaW5pdFRpbWVvdXQscj1lLm51bVRocmVhZHM7aWYoIUNyKCkpdGhyb3cgbmV3IEVycm9yKCJXZWJBc3NlbWJseSBTSU1EIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuIik7bGV0IG49QnIoKTtyPjEmJiFuJiYodHlwZW9mIHNlbGY8InUiJiYhc2VsZi5jcm9zc09yaWdpbklzb2xhdGVkJiZjb25zb2xlLndhcm4oImVudi53YXNtLm51bVRocmVhZHMgaXMgc2V0IHRvICIrcisiLCBidXQgdGhpcyB3aWxsIG5vdCB3b3JrIHVubGVzcyB5b3UgZW5hYmxlIGNyb3NzT3JpZ2luSXNvbGF0ZWQgbW9kZS4gU2VlIGh0dHBzOi8vd2ViLmRldi9jcm9zcy1vcmlnaW4taXNvbGF0aW9uLWd1aWRlLyBmb3IgbW9yZSBpbmZvLiIpLGNvbnNvbGUud2FybigiV2ViQXNzZW1ibHkgbXVsdGktdGhyZWFkaW5nIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuIEZhbGxpbmcgYmFjayB0byBzaW5nbGUtdGhyZWFkaW5nLiIpLGUubnVtVGhyZWFkcz1yPTEpO2xldCBvPWUud2FzbVBhdGhzLGE9InN0cmluZyI9PXR5cGVvZiBvP286dm9pZCAwLGk9bz8ubWpzLHM9aT8uaHJlZj8/aSxsPW8/Lndhc20sdT1sPy5ocmVmPz9sLGY9ZS53YXNtQmluYXJ5LFtkLHBdPWF3YWl0IFl0KHMsYSxyPjEpLGM9ITEsaD1bXTtpZih0PjAmJmgucHVzaChuZXcgUHJvbWlzZSgoZT0+e3NldFRpbWVvdXQoKCgpPT57Yz0hMCxlKCk7fSksdCk7fSkpKSxoLnB1c2gobmV3IFByb21pc2UoKChlLHQpPT57bGV0IG49e251bVRocmVhZHM6cn07aWYoZiluLndhc21CaW5hcnk9ZjtlbHNlIGlmKHV8fGEpbi5sb2NhdGVGaWxlPWU9PnU/P2ErZTtlbHNlIGlmKHMmJjAhPT1zLmluZGV4T2YoImJsb2I6Iikpbi5sb2NhdGVGaWxlPWU9Pm5ldyBVUkwoZSxzKS5ocmVmO2Vsc2UgaWYoZCl7bGV0IGU9UGUoKTtlJiYobi5sb2NhdGVGaWxlPXQ9PmUrdCk7fXAobikudGhlbigodD0+e3ZlPSExLEtlPSEwLFplPXQsZSgpLGQmJlVSTC5yZXZva2VPYmplY3RVUkwoZCk7fSksKGU9Pnt2ZT0hMSxxdD0hMCx0KGUpO30pKTt9KSkpLGF3YWl0IFByb21pc2UucmFjZShoKSxjKXRocm93IG5ldyBFcnJvcihgV2ViQXNzZW1ibHkgYmFja2VuZCBpbml0aWFsaXppbmcgZmFpbGVkIGR1ZSB0byB0aW1lb3V0OiAke3R9bXNgKX0seD0oKT0+e2lmKEtlJiZaZSlyZXR1cm4gWmU7dGhyb3cgbmV3IEVycm9yKCJXZWJBc3NlbWJseSBpcyBub3QgaW5pdGlhbGl6ZWQgeWV0LiIpfTt9KSksQmU9VCgoKCk9PntKKCksTD0oZSx0KT0+e2xldCByPXgoKSxuPXIubGVuZ3RoQnl0ZXNVVEY4KGUpKzEsbz1yLl9tYWxsb2Mobik7cmV0dXJuIHIuc3RyaW5nVG9VVEY4KGUsbyxuKSx0LnB1c2gobyksb30sZmU9KGUsdCxyLG4pPT57aWYoIm9iamVjdCI9PXR5cGVvZiBlJiZudWxsIT09ZSl7aWYoci5oYXMoZSkpdGhyb3cgbmV3IEVycm9yKCJDaXJjdWxhciByZWZlcmVuY2UgaW4gb3B0aW9ucyIpO3IuYWRkKGUpO31PYmplY3QuZW50cmllcyhlKS5mb3JFYWNoKCgoW2Usb10pPT57bGV0IGE9dD90K2U6ZTtpZigib2JqZWN0Ij09dHlwZW9mIG8pZmUobyxhKyIuIixyLG4pO2Vsc2UgaWYoInN0cmluZyI9PXR5cGVvZiBvfHwibnVtYmVyIj09dHlwZW9mIG8pbihhLG8udG9TdHJpbmcoKSk7ZWxzZSB7aWYoImJvb2xlYW4iIT10eXBlb2Ygbyl0aHJvdyBuZXcgRXJyb3IoIkNhbid0IGhhbmRsZSBleHRyYSBjb25maWcgdHlwZTogIit0eXBlb2Ygbyk7bihhLG8/IjEiOiIwIik7fX0pKTt9LFM9ZT0+e2xldCB0PXgoKSxyPXQuc3RhY2tTYXZlKCk7dHJ5e2xldCByPXQuUFRSX1NJWkUsbj10LnN0YWNrQWxsb2MoMipyKTt0Ll9PcnRHZXRMYXN0RXJyb3IobixuK3IpO2xldCBvPU51bWJlcih0LmdldFZhbHVlKG4sND09PXI/ImkzMiI6Imk2NCIpKSxhPXQuZ2V0VmFsdWUobityLCIqIiksaT1hP3QuVVRGOFRvU3RyaW5nKGEpOiIiO3Rocm93IG5ldyBFcnJvcihgJHtlfSBFUlJPUl9DT0RFOiAke299LCBFUlJPUl9NRVNTQUdFOiAke2l9YCl9ZmluYWxseXt0LnN0YWNrUmVzdG9yZShyKTt9fTt9KSksWHQ9VCgoKCk9PntKKCksQmUoKSxKdD1lPT57bGV0IHQ9eCgpLHI9MCxuPVtdLG89ZXx8e307dHJ5e2lmKHZvaWQgMD09PWU/LmxvZ1NldmVyaXR5TGV2ZWwpby5sb2dTZXZlcml0eUxldmVsPTI7ZWxzZSBpZigibnVtYmVyIiE9dHlwZW9mIGUubG9nU2V2ZXJpdHlMZXZlbHx8IU51bWJlci5pc0ludGVnZXIoZS5sb2dTZXZlcml0eUxldmVsKXx8ZS5sb2dTZXZlcml0eUxldmVsPDB8fGUubG9nU2V2ZXJpdHlMZXZlbD40KXRocm93IG5ldyBFcnJvcihgbG9nIHNlcnZlcml0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7ZS5sb2dTZXZlcml0eUxldmVsfWApO2lmKHZvaWQgMD09PWU/LmxvZ1ZlcmJvc2l0eUxldmVsKW8ubG9nVmVyYm9zaXR5TGV2ZWw9MDtlbHNlIGlmKCJudW1iZXIiIT10eXBlb2YgZS5sb2dWZXJib3NpdHlMZXZlbHx8IU51bWJlci5pc0ludGVnZXIoZS5sb2dWZXJib3NpdHlMZXZlbCkpdGhyb3cgbmV3IEVycm9yKGBsb2cgdmVyYm9zaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtlLmxvZ1ZlcmJvc2l0eUxldmVsfWApO3ZvaWQgMD09PWU/LnRlcm1pbmF0ZSYmKG8udGVybWluYXRlPSExKTtsZXQgYT0wO3JldHVybiB2b2lkIDAhPT1lPy50YWcmJihhPUwoZS50YWcsbikpLHI9dC5fT3J0Q3JlYXRlUnVuT3B0aW9ucyhvLmxvZ1NldmVyaXR5TGV2ZWwsby5sb2dWZXJib3NpdHlMZXZlbCwhIW8udGVybWluYXRlLGEpLDA9PT1yJiZTKCJDYW4ndCBjcmVhdGUgcnVuIG9wdGlvbnMuIiksdm9pZCAwIT09ZT8uZXh0cmEmJmZlKGUuZXh0cmEsIiIsbmV3IFdlYWtTZXQsKChlLG8pPT57bGV0IGE9TChlLG4pLGk9TChvLG4pOzAhPT10Ll9PcnRBZGRSdW5Db25maWdFbnRyeShyLGEsaSkmJlMoYENhbid0IHNldCBhIHJ1biBjb25maWcgZW50cnk6ICR7ZX0gLSAke299LmApO30pKSxbcixuXX1jYXRjaChlKXt0aHJvdyAwIT09ciYmdC5fT3J0UmVsZWFzZVJ1bk9wdGlvbnMociksbi5mb3JFYWNoKChlPT50Ll9mcmVlKGUpKSksZX19O30pKSxLdD1UKCgoKT0+e0ooKSxCZSgpLFVyPWU9Pntzd2l0Y2goZSl7Y2FzZSJkaXNhYmxlZCI6cmV0dXJuIDA7Y2FzZSJiYXNpYyI6cmV0dXJuIDE7Y2FzZSJleHRlbmRlZCI6cmV0dXJuIDI7Y2FzZSJhbGwiOnJldHVybiA5OTtkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZ3JhcGggb3B0aW1pemF0aW9uIGxldmVsOiAke2V9YCl9fSxfcj1lPT57c3dpdGNoKGUpe2Nhc2Uic2VxdWVudGlhbCI6cmV0dXJuIDA7Y2FzZSJwYXJhbGxlbCI6cmV0dXJuIDE7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGV4ZWN1dGlvbiBtb2RlOiAke2V9YCl9fSxNcj1lPT57ZS5leHRyYXx8KGUuZXh0cmE9e30pLGUuZXh0cmEuc2Vzc2lvbnx8KGUuZXh0cmEuc2Vzc2lvbj17fSk7bGV0IHQ9ZS5leHRyYS5zZXNzaW9uO3QudXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseXx8KHQudXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseT0iMSIpLGUuZXhlY3V0aW9uUHJvdmlkZXJzJiZlLmV4ZWN1dGlvblByb3ZpZGVycy5zb21lKChlPT4id2ViZ3B1Ij09PSgic3RyaW5nIj09dHlwZW9mIGU/ZTplLm5hbWUpKSkmJihlLmVuYWJsZU1lbVBhdHRlcm49ITEpO30sRHI9KGUsdCxyKT0+e2ZvcihsZXQgbiBvZiB0KXtsZXQgdD0ic3RyaW5nIj09dHlwZW9mIG4/bjpuLm5hbWU7c3dpdGNoKHQpe2Nhc2Uid2Vibm4iOmlmKHQ9IldFQk5OIiwic3RyaW5nIiE9dHlwZW9mIG4pe2xldCB0PW4/LmRldmljZVR5cGU7aWYodCl7bGV0IG49TCgiZGV2aWNlVHlwZSIsciksbz1MKHQscik7MCE9PXgoKS5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5KGUsbixvKSYmUyhgQ2FuJ3Qgc2V0IGEgc2Vzc2lvbiBjb25maWcgZW50cnk6ICdkZXZpY2VUeXBlJyAtICR7dH0uYCk7fX1icmVhaztjYXNlIndlYmdwdSI6aWYodD0iSlMiLCJzdHJpbmciIT10eXBlb2Ygbil7bGV0IHQ9bjtpZih0Py5wcmVmZXJyZWRMYXlvdXQpe2lmKCJOQ0hXIiE9PXQucHJlZmVycmVkTGF5b3V0JiYiTkhXQyIhPT10LnByZWZlcnJlZExheW91dCl0aHJvdyBuZXcgRXJyb3IoYHByZWZlcnJlZExheW91dCBtdXN0IGJlIGVpdGhlciAnTkNIVycgb3IgJ05IV0MnOiAke3QucHJlZmVycmVkTGF5b3V0fWApO2xldCBuPUwoInByZWZlcnJlZExheW91dCIsciksbz1MKHQucHJlZmVycmVkTGF5b3V0LHIpOzAhPT14KCkuX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShlLG4sbykmJlMoYENhbid0IHNldCBhIHNlc3Npb24gY29uZmlnIGVudHJ5OiAncHJlZmVycmVkTGF5b3V0JyAtICR7dC5wcmVmZXJyZWRMYXlvdXR9LmApO319YnJlYWs7Y2FzZSJ3YXNtIjpjYXNlImNwdSI6Y29udGludWU7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYG5vdCBzdXBwb3J0ZWQgZXhlY3V0aW9uIHByb3ZpZGVyOiAke3R9YCl9bGV0IG89TCh0LHIpOzAhPT14KCkuX09ydEFwcGVuZEV4ZWN1dGlvblByb3ZpZGVyKGUsbykmJlMoYENhbid0IGFwcGVuZCBleGVjdXRpb24gcHJvdmlkZXI6ICR7dH0uYCk7fX0sWnQ9ZT0+e2xldCB0PXgoKSxyPTAsbj1bXSxvPWV8fHt9O01yKG8pO3RyeXtsZXQgZT1VcihvLmdyYXBoT3B0aW1pemF0aW9uTGV2ZWw/PyJhbGwiKSxhPV9yKG8uZXhlY3V0aW9uTW9kZT8/InNlcXVlbnRpYWwiKSxpPSJzdHJpbmciPT10eXBlb2Ygby5sb2dJZD9MKG8ubG9nSWQsbik6MCxzPW8ubG9nU2V2ZXJpdHlMZXZlbD8/MjtpZighTnVtYmVyLmlzSW50ZWdlcihzKXx8czwwfHxzPjQpdGhyb3cgbmV3IEVycm9yKGBsb2cgc2VydmVyaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtzfWApO2xldCBsPW8ubG9nVmVyYm9zaXR5TGV2ZWw/PzA7aWYoIU51bWJlci5pc0ludGVnZXIobCl8fGw8MHx8bD40KXRocm93IG5ldyBFcnJvcihgbG9nIHZlcmJvc2l0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7bH1gKTtsZXQgdT0ic3RyaW5nIj09dHlwZW9mIG8ub3B0aW1pemVkTW9kZWxGaWxlUGF0aD9MKG8ub3B0aW1pemVkTW9kZWxGaWxlUGF0aCxuKTowO2lmKHI9dC5fT3J0Q3JlYXRlU2Vzc2lvbk9wdGlvbnMoZSwhIW8uZW5hYmxlQ3B1TWVtQXJlbmEsISFvLmVuYWJsZU1lbVBhdHRlcm4sYSwhIW8uZW5hYmxlUHJvZmlsaW5nLDAsaSxzLGwsdSksMD09PXImJlMoIkNhbid0IGNyZWF0ZSBzZXNzaW9uIG9wdGlvbnMuIiksby5leGVjdXRpb25Qcm92aWRlcnMmJkRyKHIsby5leGVjdXRpb25Qcm92aWRlcnMsbiksdm9pZCAwIT09by5lbmFibGVHcmFwaENhcHR1cmUpe2lmKCJib29sZWFuIiE9dHlwZW9mIG8uZW5hYmxlR3JhcGhDYXB0dXJlKXRocm93IG5ldyBFcnJvcihgZW5hYmxlR3JhcGhDYXB0dXJlIG11c3QgYmUgYSBib29sZWFuIHZhbHVlOiAke28uZW5hYmxlR3JhcGhDYXB0dXJlfWApO2xldCBlPUwoImVuYWJsZUdyYXBoQ2FwdHVyZSIsbiksYT1MKG8uZW5hYmxlR3JhcGhDYXB0dXJlLnRvU3RyaW5nKCksbik7MCE9PXQuX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShyLGUsYSkmJlMoYENhbid0IHNldCBhIHNlc3Npb24gY29uZmlnIGVudHJ5OiAnZW5hYmxlR3JhcGhDYXB0dXJlJyAtICR7by5lbmFibGVHcmFwaENhcHR1cmV9LmApO31pZihvLmZyZWVEaW1lbnNpb25PdmVycmlkZXMpZm9yKGxldFtlLGFdb2YgT2JqZWN0LmVudHJpZXMoby5mcmVlRGltZW5zaW9uT3ZlcnJpZGVzKSl7aWYoInN0cmluZyIhPXR5cGVvZiBlKXRocm93IG5ldyBFcnJvcihgZnJlZSBkaW1lbnNpb24gb3ZlcnJpZGUgbmFtZSBtdXN0IGJlIGEgc3RyaW5nOiAke2V9YCk7aWYoIm51bWJlciIhPXR5cGVvZiBhfHwhTnVtYmVyLmlzSW50ZWdlcihhKXx8YTwwKXRocm93IG5ldyBFcnJvcihgZnJlZSBkaW1lbnNpb24gb3ZlcnJpZGUgdmFsdWUgbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyOiAke2F9YCk7bGV0IG89TChlLG4pOzAhPT10Ll9PcnRBZGRGcmVlRGltZW5zaW9uT3ZlcnJpZGUocixvLGEpJiZTKGBDYW4ndCBzZXQgYSBmcmVlIGRpbWVuc2lvbiBvdmVycmlkZTogJHtlfSAtICR7YX0uYCk7fXJldHVybiB2b2lkIDAhPT1vLmV4dHJhJiZmZShvLmV4dHJhLCIiLG5ldyBXZWFrU2V0LCgoZSxvKT0+e2xldCBhPUwoZSxuKSxpPUwobyxuKTswIT09dC5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5KHIsYSxpKSYmUyhgQ2FuJ3Qgc2V0IGEgc2Vzc2lvbiBjb25maWcgZW50cnk6ICR7ZX0gLSAke299LmApO30pKSxbcixuXX1jYXRjaChlKXt0aHJvdyAwIT09ciYmMCE9PXQuX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucyhyKSYmUygiQ2FuJ3QgcmVsZWFzZSBzZXNzaW9uIG9wdGlvbnMuIiksbi5mb3JFYWNoKChlPT50Ll9mcmVlKGUpKSksZX19O30pKSxRZT1UKCgoKT0+e2VlPWU9Pntzd2l0Y2goZSl7Y2FzZSJpbnQ4IjpyZXR1cm4gMztjYXNlInVpbnQ4IjpyZXR1cm4gMjtjYXNlImJvb2wiOnJldHVybiA5O2Nhc2UiaW50MTYiOnJldHVybiA1O2Nhc2UidWludDE2IjpyZXR1cm4gNDtjYXNlImludDMyIjpyZXR1cm4gNjtjYXNlInVpbnQzMiI6cmV0dXJuIDEyO2Nhc2UiZmxvYXQxNiI6cmV0dXJuIDEwO2Nhc2UiZmxvYXQzMiI6cmV0dXJuIDE7Y2FzZSJmbG9hdDY0IjpyZXR1cm4gMTE7Y2FzZSJzdHJpbmciOnJldHVybiA4O2Nhc2UiaW50NjQiOnJldHVybiA3O2Nhc2UidWludDY0IjpyZXR1cm4gMTM7Y2FzZSJpbnQ0IjpyZXR1cm4gMjI7Y2FzZSJ1aW50NCI6cmV0dXJuIDIxO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZX1gKX19LFF0PWU9Pntzd2l0Y2goZSl7Y2FzZSAzOnJldHVybiAiaW50OCI7Y2FzZSAyOnJldHVybiAidWludDgiO2Nhc2UgOTpyZXR1cm4gImJvb2wiO2Nhc2UgNTpyZXR1cm4gImludDE2IjtjYXNlIDQ6cmV0dXJuICJ1aW50MTYiO2Nhc2UgNjpyZXR1cm4gImludDMyIjtjYXNlIDEyOnJldHVybiAidWludDMyIjtjYXNlIDEwOnJldHVybiAiZmxvYXQxNiI7Y2FzZSAxOnJldHVybiAiZmxvYXQzMiI7Y2FzZSAxMTpyZXR1cm4gImZsb2F0NjQiO2Nhc2UgODpyZXR1cm4gInN0cmluZyI7Y2FzZSA3OnJldHVybiAiaW50NjQiO2Nhc2UgMTM6cmV0dXJuICJ1aW50NjQiO2Nhc2UgMjI6cmV0dXJuICJpbnQ0IjtjYXNlIDIxOnJldHVybiAidWludDQiO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZX1gKX19LHRlPShlLHQpPT57bGV0IHI9Wy0xLDQsMSwxLDIsMiw0LDgsLTEsMSwyLDgsNCw4LC0xLC0xLC0xLC0xLC0xLC0xLC0xLC41LC41XVtlXSxuPSJudW1iZXIiPT10eXBlb2YgdD90OnQucmVkdWNlKCgoZSx0KT0+ZSp0KSwxKTtyZXR1cm4gcj4wP01hdGguY2VpbChuKnIpOnZvaWQgMH0sZXI9ZT0+e3N3aXRjaChlKXtjYXNlImZsb2F0MTYiOnJldHVybiB0eXBlb2YgRmxvYXQxNkFycmF5PCJ1IiYmRmxvYXQxNkFycmF5LmZyb20/RmxvYXQxNkFycmF5OlVpbnQxNkFycmF5O2Nhc2UiZmxvYXQzMiI6cmV0dXJuIEZsb2F0MzJBcnJheTtjYXNlInVpbnQ4IjpjYXNlImJvb2wiOnJldHVybiBVaW50OEFycmF5O2Nhc2UiaW50OCI6cmV0dXJuIEludDhBcnJheTtjYXNlInVpbnQxNiI6cmV0dXJuIFVpbnQxNkFycmF5O2Nhc2UiaW50MTYiOnJldHVybiBJbnQxNkFycmF5O2Nhc2UiaW50MzIiOnJldHVybiBJbnQzMkFycmF5O2Nhc2UiZmxvYXQ2NCI6cmV0dXJuIEZsb2F0NjRBcnJheTtjYXNlInVpbnQzMiI6cmV0dXJuIFVpbnQzMkFycmF5O2Nhc2UiaW50NjQiOnJldHVybiBCaWdJbnQ2NEFycmF5O2Nhc2UidWludDY0IjpyZXR1cm4gQmlnVWludDY0QXJyYXk7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGU6ICR7ZX1gKX19LHRyPWU9Pntzd2l0Y2goZSl7Y2FzZSJ2ZXJib3NlIjpyZXR1cm4gMDtjYXNlImluZm8iOnJldHVybiAxO2Nhc2Uid2FybmluZyI6cmV0dXJuIDI7Y2FzZSJlcnJvciI6cmV0dXJuIDM7Y2FzZSJmYXRhbCI6cmV0dXJuIDQ7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGxvZ2dpbmcgbGV2ZWw6ICR7ZX1gKX19LENlPWU9PiJmbG9hdDMyIj09PWV8fCJmbG9hdDE2Ij09PWV8fCJpbnQzMiI9PT1lfHwiaW50NjQiPT09ZXx8InVpbnQzMiI9PT1lfHwidWludDgiPT09ZXx8ImJvb2wiPT09ZXx8InVpbnQ0Ij09PWV8fCJpbnQ0Ij09PWUsVWU9ZT0+ImZsb2F0MzIiPT09ZXx8ImZsb2F0MTYiPT09ZXx8ImludDMyIj09PWV8fCJpbnQ2NCI9PT1lfHwidWludDMyIj09PWV8fCJ1aW50NjQiPT09ZXx8ImludDgiPT09ZXx8InVpbnQ4Ij09PWV8fCJib29sIj09PWV8fCJ1aW50NCI9PT1lfHwiaW50NCI9PT1lLHJyPWU9Pntzd2l0Y2goZSl7Y2FzZSJub25lIjpyZXR1cm4gMDtjYXNlImNwdSI6cmV0dXJuIDE7Y2FzZSJjcHUtcGlubmVkIjpyZXR1cm4gMjtjYXNlInRleHR1cmUiOnJldHVybiAzO2Nhc2UiZ3B1LWJ1ZmZlciI6cmV0dXJuIDQ7Y2FzZSJtbC10ZW5zb3IiOnJldHVybiA1O2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIGxvY2F0aW9uOiAke2V9YCl9fTt9KSksZXQ9VCgoKCk9PntiZSgpLGNlPWFzeW5jIGU9PntpZigic3RyaW5nIj09dHlwZW9mIGUpe3tsZXQgdD1hd2FpdCBmZXRjaChlKTtpZighdC5vayl0aHJvdyBuZXcgRXJyb3IoYGZhaWxlZCB0byBsb2FkIGV4dGVybmFsIGRhdGEgZmlsZTogJHtlfWApO2xldCByPXQuaGVhZGVycy5nZXQoIkNvbnRlbnQtTGVuZ3RoIiksbj1yP3BhcnNlSW50KHIsMTApOjA7aWYobjwxMDczNzQxODI0KXJldHVybiBuZXcgVWludDhBcnJheShhd2FpdCB0LmFycmF5QnVmZmVyKCkpO3tpZighdC5ib2R5KXRocm93IG5ldyBFcnJvcihgZmFpbGVkIHRvIGxvYWQgZXh0ZXJuYWwgZGF0YSBmaWxlOiAke2V9LCBubyByZXNwb25zZSBib2R5LmApO2xldCByLG89dC5ib2R5LmdldFJlYWRlcigpO3RyeXtyPW5ldyBBcnJheUJ1ZmZlcihuKTt9Y2F0Y2goZSl7aWYoIShlIGluc3RhbmNlb2YgUmFuZ2VFcnJvcikpdGhyb3cgZTt7bGV0IGU9TWF0aC5jZWlsKG4vNjU1MzYpO3I9bmV3IFdlYkFzc2VtYmx5Lk1lbW9yeSh7aW5pdGlhbDplLG1heGltdW06ZX0pLmJ1ZmZlcjt9fWxldCBhPTA7Zm9yKDs7KXtsZXR7ZG9uZTplLHZhbHVlOnR9PWF3YWl0IG8ucmVhZCgpO2lmKGUpYnJlYWs7bGV0IG49dC5ieXRlTGVuZ3RoO25ldyBVaW50OEFycmF5KHIsYSxuKS5zZXQodCksYSs9bjt9cmV0dXJuIG5ldyBVaW50OEFycmF5KHIsMCxuKX19fXJldHVybiBlIGluc3RhbmNlb2YgQmxvYj9uZXcgVWludDhBcnJheShhd2FpdCBlLmFycmF5QnVmZmVyKCkpOmUgaW5zdGFuY2VvZiBVaW50OEFycmF5P2U6bmV3IFVpbnQ4QXJyYXkoZSl9O30pKSxKZT1UKCgoKT0+e1h0KCksS3QoKSxRZSgpLEooKSxCZSgpLGV0KCksUnI9KGUsdCk9PnswIT09eCgpLl9PcnRJbml0KGUsdCkmJlMoIkNhbid0IGluaXRpYWxpemUgb25ueHJ1bnRpbWUuIik7fSxUZT1hc3luYyBlPT57UnIoZS53YXNtLm51bVRocmVhZHMsdHIoZS5sb2dMZXZlbCkpO30sU2U9YXN5bmMoZSx0KT0+e30scmU9bmV3IE1hcCxGcj1lPT57bGV0IHQ9eCgpLHI9dC5zdGFja1NhdmUoKTt0cnl7bGV0IHI9dC5QVFJfU0laRSxuPXQuc3RhY2tBbGxvYygyKnIpOzAhPT10Ll9PcnRHZXRJbnB1dE91dHB1dENvdW50KGUsbixuK3IpJiZTKCJDYW4ndCBnZXQgc2Vzc2lvbiBpbnB1dC9vdXRwdXQgY291bnQuIik7bGV0IG89ND09PXI/ImkzMiI6Imk2NCI7cmV0dXJuIFtOdW1iZXIodC5nZXRWYWx1ZShuLG8pKSxOdW1iZXIodC5nZXRWYWx1ZShuK3IsbykpXX1maW5hbGx5e3Quc3RhY2tSZXN0b3JlKHIpO319LHVlPWU9PntsZXQgdD14KCkscj10Ll9tYWxsb2MoZS5ieXRlTGVuZ3RoKTtpZigwPT09cil0aHJvdyBuZXcgRXJyb3IoYENhbid0IGNyZWF0ZSBhIHNlc3Npb24uIGZhaWxlZCB0byBhbGxvY2F0ZSBhIGJ1ZmZlciBvZiBzaXplICR7ZS5ieXRlTGVuZ3RofS5gKTtyZXR1cm4gdC5IRUFQVTguc2V0KGUsciksW3IsZS5ieXRlTGVuZ3RoXX0sQWU9YXN5bmMoZSx0KT0+e2xldCByLG4sbz14KCk7QXJyYXkuaXNBcnJheShlKT9bcixuXT1lOmUuYnVmZmVyPT09by5IRUFQVTguYnVmZmVyP1tyLG5dPVtlLmJ5dGVPZmZzZXQsZS5ieXRlTGVuZ3RoXTpbcixuXT11ZShlKTtsZXQgYT0wLGk9MCxzPVtdLGw9W10sdT1bXTt0cnl7aWYoW2ksc109WnQodCksdD8uZXh0ZXJuYWxEYXRhJiZvLm1vdW50RXh0ZXJuYWxEYXRhKXtsZXQgZT1bXTtmb3IobGV0IHIgb2YgdC5leHRlcm5hbERhdGEpe2xldCB0PSJzdHJpbmciPT10eXBlb2Ygcj9yOnIucGF0aDtlLnB1c2goY2UoInN0cmluZyI9PXR5cGVvZiByP3I6ci5kYXRhKS50aGVuKChlPT57by5tb3VudEV4dGVybmFsRGF0YSh0LGUpO30pKSk7fWF3YWl0IFByb21pc2UuYWxsKGUpO31mb3IobGV0IGUgb2YgdD8uZXhlY3V0aW9uUHJvdmlkZXJzPz9bXSlpZigid2Vibm4iPT09KCJzdHJpbmciPT10eXBlb2YgZT9lOmUubmFtZSkpe2lmKG8uc2hvdWxkVHJhbnNmZXJUb01MVGVuc29yPSExLCJzdHJpbmciIT10eXBlb2YgZSl7bGV0IHQ9ZSxyPXQ/LmNvbnRleHQsbj10Py5ncHVEZXZpY2UsYT10Py5kZXZpY2VUeXBlLGk9dD8ucG93ZXJQcmVmZXJlbmNlO28uY3VycmVudENvbnRleHQ9cnx8KG4/YXdhaXQgby5qc2VwQ3JlYXRlTUxDb250ZXh0KG4pOmF3YWl0IG8uanNlcENyZWF0ZU1MQ29udGV4dCh7ZGV2aWNlVHlwZTphLHBvd2VyUHJlZmVyZW5jZTppfSkpO31lbHNlIG8uY3VycmVudENvbnRleHQ9YXdhaXQgby5qc2VwQ3JlYXRlTUxDb250ZXh0KCk7YnJlYWt9YT1hd2FpdCBvLl9PcnRDcmVhdGVTZXNzaW9uKHIsbixpKSwwPT09YSYmUygiQ2FuJ3QgY3JlYXRlIGEgc2Vzc2lvbi4iKSxvLmpzZXBPbkNyZWF0ZVNlc3Npb24/LigpLG8uY3VycmVudENvbnRleHQmJihvLmpzZXBSZWdpc3Rlck1MQ29udGV4dChhLG8uY3VycmVudENvbnRleHQpLG8uY3VycmVudENvbnRleHQ9dm9pZCAwLG8uc2hvdWxkVHJhbnNmZXJUb01MVGVuc29yPSEwKTtsZXRbZSxmXT1GcihhKSxkPSEhdD8uZW5hYmxlR3JhcGhDYXB0dXJlLHA9W10sYz1bXTtmb3IobGV0IHQ9MDt0PGU7dCsrKXtsZXQgZT1vLl9PcnRHZXRJbnB1dE5hbWUoYSx0KTswPT09ZSYmUygiQ2FuJ3QgZ2V0IGFuIGlucHV0IG5hbWUuIiksbC5wdXNoKGUpLHAucHVzaChvLlVURjhUb1N0cmluZyhlKSk7fWZvcihsZXQgZT0wO2U8ZjtlKyspe2xldCB0PW8uX09ydEdldE91dHB1dE5hbWUoYSxlKTswPT09dCYmUygiQ2FuJ3QgZ2V0IGFuIG91dHB1dCBuYW1lLiIpLHUucHVzaCh0KTtsZXQgcj1vLlVURjhUb1N0cmluZyh0KTtjLnB1c2gocik7fXJldHVybiByZS5zZXQoYSxbYSxsLHUsbnVsbCxkLCExXSksW2EscCxjXX1jYXRjaChlKXt0aHJvdyBsLmZvckVhY2goKGU9Pm8uX09ydEZyZWUoZSkpKSx1LmZvckVhY2goKGU9Pm8uX09ydEZyZWUoZSkpKSwwIT09YSYmMCE9PW8uX09ydFJlbGVhc2VTZXNzaW9uKGEpJiZTKCJDYW4ndCByZWxlYXNlIHNlc3Npb24uIiksZX1maW5hbGx5e28uX2ZyZWUociksMCE9PWkmJjAhPT1vLl9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnMoaSkmJlMoIkNhbid0IHJlbGVhc2Ugc2Vzc2lvbiBvcHRpb25zLiIpLHMuZm9yRWFjaCgoZT0+by5fZnJlZShlKSkpLG8udW5tb3VudEV4dGVybmFsRGF0YT8uKCk7fX0sT2U9ZT0+e2xldCB0PXgoKSxyPXJlLmdldChlKTtpZighcil0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCByZWxlYXNlIHNlc3Npb24uIGludmFsaWQgc2Vzc2lvbiBpZDogJHtlfWApO2xldFtuLG8sYSxpLHNdPXI7aSYmKHMmJjAhPT10Ll9PcnRDbGVhckJvdW5kT3V0cHV0cyhpLmhhbmRsZSkmJlMoIkNhbid0IGNsZWFyIGJvdW5kIG91dHB1dHMuIiksMCE9PXQuX09ydFJlbGVhc2VCaW5kaW5nKGkuaGFuZGxlKSYmUygiQ2FuJ3QgcmVsZWFzZSBJTyBiaW5kaW5nLiIpKSx0LmpzZXBPblJlbGVhc2VTZXNzaW9uPy4oZSksby5mb3JFYWNoKChlPT50Ll9PcnRGcmVlKGUpKSksYS5mb3JFYWNoKChlPT50Ll9PcnRGcmVlKGUpKSksMCE9PXQuX09ydFJlbGVhc2VTZXNzaW9uKG4pJiZTKCJDYW4ndCByZWxlYXNlIHNlc3Npb24uIikscmUuZGVsZXRlKGUpO30sbnI9YXN5bmMoZSx0LHIsbixvLGE9ITEpPT57aWYoIWUpcmV0dXJuIHZvaWQgdC5wdXNoKDApO2xldCBpLHMsbD14KCksdT1sLlBUUl9TSVpFLGY9ZVswXSxkPWVbMV0scD1lWzNdLGM9cDtpZigic3RyaW5nIj09PWYmJigiZ3B1LWJ1ZmZlciI9PT1wfHwibWwtdGVuc29yIj09PXApKXRocm93IG5ldyBFcnJvcigiU3RyaW5nIHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkIG9uIEdQVS4iKTtpZihhJiYiZ3B1LWJ1ZmZlciIhPT1wKXRocm93IG5ldyBFcnJvcihgRXh0ZXJuYWwgYnVmZmVyIG11c3QgYmUgcHJvdmlkZWQgZm9yIGlucHV0L291dHB1dCBpbmRleCAke299IHdoZW4gZW5hYmxlR3JhcGhDYXB0dXJlIGlzIHRydWUuYCk7aWYoImdwdS1idWZmZXIiPT09cCl7bGV0IHQ9ZVsyXS5ncHVCdWZmZXI7cz10ZShlZShmKSxkKTtsZXQgcj1sLmpzZXBSZWdpc3RlckJ1ZmZlcjtpZighcil0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiAiZ3B1LWJ1ZmZlciIgaXMgbm90IHN1cHBvcnRlZCB3aXRob3V0IHVzaW5nIFdlYkdQVS4nKTtpPXIobixvLHQscyk7fWVsc2UgaWYoIm1sLXRlbnNvciI9PT1wKXtsZXQgdD1lWzJdLm1sVGVuc29yO3M9dGUoZWUoZiksZCk7bGV0IHI9bC5qc2VwUmVnaXN0ZXJNTFRlbnNvcjtpZighcil0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiAibWwtdGVuc29yIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViTk4uJyk7aT1yKG4sdCxlZShmKSxkKTt9ZWxzZSB7bGV0IHQ9ZVsyXTtpZihBcnJheS5pc0FycmF5KHQpKXtzPXUqdC5sZW5ndGgsaT1sLl9tYWxsb2Mocyksci5wdXNoKGkpO2ZvcihsZXQgZT0wO2U8dC5sZW5ndGg7ZSsrKXtpZigic3RyaW5nIiE9dHlwZW9mIHRbZV0pdGhyb3cgbmV3IFR5cGVFcnJvcihgdGVuc29yIGRhdGEgYXQgaW5kZXggJHtlfSBpcyBub3QgYSBzdHJpbmdgKTtsLnNldFZhbHVlKGkrZSp1LEwodFtlXSxyKSwiKiIpO319ZWxzZSB7bGV0IGU9bC5qc2VwSXNHcmFwaElucHV0O2lmKCJzdHJpbmciIT09ZiYmZSl7bGV0IGE9bC5fT3J0R2V0SW5wdXROYW1lKG4sbyk7aWYoZShuLGwuVVRGOFRvU3RyaW5nKGEpKSl7bGV0IGU9ZWUoZik7cz10ZShlLGQpLGM9Im1sLXRlbnNvciI7bGV0IHI9bC5qc2VwQ3JlYXRlVGVtcG9yYXJ5VGVuc29yLG89bC5qc2VwVXBsb2FkVGVuc29yO2lmKCFyfHwhbyl0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiAibWwtdGVuc29yIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViTk4uJyk7bGV0IGE9YXdhaXQgcihuLGUsZCk7byhhLG5ldyBVaW50OEFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0LmJ5dGVMZW5ndGgpKSxpPWE7fWVsc2Ugcz10LmJ5dGVMZW5ndGgsaT1sLl9tYWxsb2Mocyksci5wdXNoKGkpLGwuSEVBUFU4LnNldChuZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQscyksaSk7fWVsc2Ugcz10LmJ5dGVMZW5ndGgsaT1sLl9tYWxsb2Mocyksci5wdXNoKGkpLGwuSEVBUFU4LnNldChuZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQscyksaSk7fX1sZXQgaD1sLnN0YWNrU2F2ZSgpLHc9bC5zdGFja0FsbG9jKDQqZC5sZW5ndGgpO3RyeXtkLmZvckVhY2goKChlLHQpPT5sLnNldFZhbHVlKHcrdCp1LGUsND09PXU/ImkzMiI6Imk2NCIpKSk7bGV0IGU9bC5fT3J0Q3JlYXRlVGVuc29yKGVlKGYpLGkscyx3LGQubGVuZ3RoLHJyKGMpKTswPT09ZSYmUyhgQ2FuJ3QgY3JlYXRlIHRlbnNvciBmb3IgaW5wdXQvb3V0cHV0LiBzZXNzaW9uPSR7bn0sIGluZGV4PSR7b30uYCksdC5wdXNoKGUpO31maW5hbGx5e2wuc3RhY2tSZXN0b3JlKGgpO319LHhlPWFzeW5jKGUsdCxyLG4sbyxhKT0+e2xldCBpPXgoKSxzPWkuUFRSX1NJWkUsbD1yZS5nZXQoZSk7aWYoIWwpdGhyb3cgbmV3IEVycm9yKGBjYW5ub3QgcnVuIGluZmVyZW5jZS4gaW52YWxpZCBzZXNzaW9uIGlkOiAke2V9YCk7bGV0IHU9bFswXSxmPWxbMV0sZD1sWzJdLHA9bFszXSxjPWxbNF0saD0obFs1XSx0Lmxlbmd0aCksdz1uLmxlbmd0aCx5PTAsbT1bXSxnPVtdLGI9W10sdj1bXSxFPWkuc3RhY2tTYXZlKCksVD1pLnN0YWNrQWxsb2MoaCpzKSxBPWkuc3RhY2tBbGxvYyhoKnMpLEw9aS5zdGFja0FsbG9jKHcqcyksQz1pLnN0YWNrQWxsb2ModypzKTt0cnl7W3ksbV09SnQoYSk7Zm9yKGxldCBuPTA7bjxoO24rKylhd2FpdCBucihyW25dLGcsdixlLHRbbl0sYyk7Zm9yKGxldCB0PTA7dDx3O3QrKylhd2FpdCBucihvW3RdLGIsdixlLGgrblt0XSxjKTtmb3IobGV0IGU9MDtlPGg7ZSsrKWkuc2V0VmFsdWUoVCtlKnMsZ1tlXSwiKiIpLGkuc2V0VmFsdWUoQStlKnMsZlt0W2VdXSwiKiIpO2ZvcihsZXQgZT0wO2U8dztlKyspaS5zZXRWYWx1ZShMK2UqcyxiW2VdLCIqIiksaS5zZXRWYWx1ZShDK2UqcyxkW25bZV1dLCIqIik7bGV0IGw7aS5qc2VwT25SdW5TdGFydD8uKHUpLGw9YXdhaXQgaS5fT3J0UnVuKHUsQSxULGgsQyx3LEwseSksMCE9PWwmJlMoImZhaWxlZCB0byBjYWxsIE9ydFJ1bigpLiIpO2xldCBFPVtdO2ZvcihsZXQgdD0wO3Q8dzt0Kyspe2xldCByPU51bWJlcihpLmdldFZhbHVlKEwrdCpzLCIqIikpO2lmKHI9PT1iW3RdKXtFLnB1c2gob1t0XSk7Y29udGludWV9bGV0IGEsbD1pLnN0YWNrU2F2ZSgpLGY9aS5zdGFja0FsbG9jKDQqcyksZD0hMSxjPTA7dHJ5ezAhPT1pLl9PcnRHZXRUZW5zb3JEYXRhKHIsZixmK3MsZisyKnMsZiszKnMpJiZTKGBDYW4ndCBhY2Nlc3Mgb3V0cHV0IHRlbnNvciBkYXRhIG9uIGluZGV4ICR7dH0uYCk7bGV0IG89ND09PXM/ImkzMiI6Imk2NCIsbD1OdW1iZXIoaS5nZXRWYWx1ZShmLG8pKTtjPWkuZ2V0VmFsdWUoZitzLCIqIik7bGV0IHU9aS5nZXRWYWx1ZShmKzIqcywiKiIpLGg9TnVtYmVyKGkuZ2V0VmFsdWUoZiszKnMsbykpLHc9W107Zm9yKGxldCBlPTA7ZTxoO2UrKyl3LnB1c2goTnVtYmVyKGkuZ2V0VmFsdWUodStlKnMsbykpKTswIT09aS5fT3J0RnJlZSh1KSYmUygiQ2FuJ3QgZnJlZSBtZW1vcnkgZm9yIHRlbnNvciBkaW1zLiIpO2xldCB5PXcucmVkdWNlKCgoZSx0KT0+ZSp0KSwxKTthPVF0KGwpO2xldCBtPXA/Lm91dHB1dFByZWZlcnJlZExvY2F0aW9uc1tuW3RdXTtpZigic3RyaW5nIj09PWEpe2lmKCJncHUtYnVmZmVyIj09PW18fCJtbC10ZW5zb3IiPT09bSl0aHJvdyBuZXcgRXJyb3IoIlN0cmluZyB0ZW5zb3IgaXMgbm90IHN1cHBvcnRlZCBvbiBHUFUuIik7bGV0IGU9W107Zm9yKGxldCB0PTA7dDx5O3QrKyl7bGV0IHI9aS5nZXRWYWx1ZShjK3QqcywiKiIpLG49aS5nZXRWYWx1ZShjKyh0KzEpKnMsIioiKSxvPXQ9PT15LTE/dm9pZCAwOm4tcjtlLnB1c2goaS5VVEY4VG9TdHJpbmcocixvKSk7fUUucHVzaChbYSx3LGUsImNwdSJdKTt9ZWxzZSBpZigiZ3B1LWJ1ZmZlciI9PT1tJiZ5PjApe2xldCBlPWkuanNlcEdldEJ1ZmZlcjtpZighZSl0aHJvdyBuZXcgRXJyb3IoJ3ByZWZlcnJlZExvY2F0aW9uICJncHUtYnVmZmVyIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViR1BVLicpO2xldCB0PWUoYyksbj10ZShsLHkpO2lmKHZvaWQgMD09PW58fCFDZShhKSl0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGRhdGEgdHlwZTogJHthfWApO2Q9ITAsRS5wdXNoKFthLHcse2dwdUJ1ZmZlcjp0LGRvd25sb2FkOmkuanNlcENyZWF0ZURvd25sb2FkZXIodCxuLGEpLGRpc3Bvc2U6KCk9PnswIT09aS5fT3J0UmVsZWFzZVRlbnNvcihyKSYmUygiQ2FuJ3QgcmVsZWFzZSB0ZW5zb3IuIik7fX0sImdwdS1idWZmZXIiXSk7fWVsc2UgaWYoIm1sLXRlbnNvciI9PT1tJiZ5PjApe2xldCB0PWkuanNlcEVuc3VyZVRlbnNvcjtpZighdCl0aHJvdyBuZXcgRXJyb3IoJ3ByZWZlcnJlZExvY2F0aW9uICJtbC10ZW5zb3IiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJOTi4nKTtpZih2b2lkIDA9PT10ZShsLHkpfHwhVWUoYSkpdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7YX1gKTtsZXQgbj1hd2FpdCB0KGUsYyxsLHcsITEpO2Q9ITAsRS5wdXNoKFthLHcse21sVGVuc29yOm4sZG93bmxvYWQ6aS5qc2VwQ3JlYXRlTUxUZW5zb3JEb3dubG9hZGVyKGMsYSksZGlzcG9zZTooKT0+e2kuanNlcFJlbGVhc2VUZW5zb3JJZChjKSxpLl9PcnRSZWxlYXNlVGVuc29yKHIpO319LCJtbC10ZW5zb3IiXSk7fWVsc2Uge2xldCBlPW5ldyhlcihhKSkoeSk7bmV3IFVpbnQ4QXJyYXkoZS5idWZmZXIsZS5ieXRlT2Zmc2V0LGUuYnl0ZUxlbmd0aCkuc2V0KGkuSEVBUFU4LnN1YmFycmF5KGMsYytlLmJ5dGVMZW5ndGgpKSxFLnB1c2goW2EsdyxlLCJjcHUiXSk7fX1maW5hbGx5e2kuc3RhY2tSZXN0b3JlKGwpLCJzdHJpbmciPT09YSYmYyYmaS5fZnJlZShjKSxkfHxpLl9PcnRSZWxlYXNlVGVuc29yKHIpLGkuanNlcE9uUnVuRW5kPy4odSk7fX1yZXR1cm4gcCYmIWMmJigwIT09aS5fT3J0Q2xlYXJCb3VuZE91dHB1dHMocC5oYW5kbGUpJiZTKCJDYW4ndCBjbGVhciBib3VuZCBvdXRwdXRzLiIpLHJlLnNldChlLFt1LGYsZCxwLGMsITFdKSksRX1maW5hbGx5e2kuc3RhY2tSZXN0b3JlKEUpLGcuZm9yRWFjaCgoZT0+aS5fT3J0UmVsZWFzZVRlbnNvcihlKSkpLGIuZm9yRWFjaCgoZT0+aS5fT3J0UmVsZWFzZVRlbnNvcihlKSkpLHYuZm9yRWFjaCgoZT0+aS5fZnJlZShlKSkpLDAhPT15JiZpLl9PcnRSZWxlYXNlUnVuT3B0aW9ucyh5KSxtLmZvckVhY2goKGU9PmkuX2ZyZWUoZSkpKTt9fSxMZT1lPT57bGV0IHQ9eCgpLHI9cmUuZ2V0KGUpO2lmKCFyKXRocm93IG5ldyBFcnJvcigiaW52YWxpZCBzZXNzaW9uIGlkIik7bGV0IG49clswXSxvPXQuX09ydEVuZFByb2ZpbGluZyhuKTswPT09byYmUygiQ2FuJ3QgZ2V0IGFuIHByb2ZpbGUgZmlsZSBuYW1lLiIpLHQuX09ydEZyZWUobyk7fSxJZT1lPT57bGV0IHQ9W107Zm9yKGxldCByIG9mIGUpe2xldCBlPXJbMl07IUFycmF5LmlzQXJyYXkoZSkmJiJidWZmZXIiaW4gZSYmdC5wdXNoKGUuYnVmZmVyKTt9cmV0dXJuIHR9O30pKSxudD1UKCgoKT0+e3EoKSxKZSgpLEooKSxnZSgpLFo9KCk9PiEhQS53YXNtLnByb3h5JiZ0eXBlb2YgZG9jdW1lbnQ8InUiLGxlPSExLE1lPSExLERlPSExLHJ0PW5ldyBNYXAsbmU9KGUsdCk9PntsZXQgcj1ydC5nZXQoZSk7cj9yLnB1c2godCk6cnQuc2V0KGUsW3RdKTt9LG9lPSgpPT57aWYobGV8fCFNZXx8RGV8fCFEKXRocm93IG5ldyBFcnJvcigid29ya2VyIG5vdCByZWFkeSIpfSxOcj1lPT57c3dpdGNoKGUuZGF0YS50eXBlKXtjYXNlImluaXQtd2FzbSI6bGU9ITEsZS5kYXRhLmVycj8oRGU9ITAsdHRbMV0oZS5kYXRhLmVycikpOihNZT0hMCx0dFswXSgpKSxfZSYmKFVSTC5yZXZva2VPYmplY3RVUkwoX2UpLF9lPXZvaWQgMCk7YnJlYWs7Y2FzZSJpbml0LWVwIjpjYXNlImNvcHktZnJvbSI6Y2FzZSJjcmVhdGUiOmNhc2UicmVsZWFzZSI6Y2FzZSJydW4iOmNhc2UiZW5kLXByb2ZpbGluZyI6e2xldCB0PXJ0LmdldChlLmRhdGEudHlwZSk7ZS5kYXRhLmVycj90LnNoaWZ0KClbMV0oZS5kYXRhLmVycik6dC5zaGlmdCgpWzBdKGUuZGF0YS5vdXQpO2JyZWFrfX19LG9yPWFzeW5jKCk9PntpZighTWUpe2lmKGxlKXRocm93IG5ldyBFcnJvcigibXVsdGlwbGUgY2FsbHMgdG8gJ2luaXRXYXNtKCknIGRldGVjdGVkLiIpO2lmKERlKXRocm93IG5ldyBFcnJvcigicHJldmlvdXMgY2FsbCB0byAnaW5pdFdhc20oKScgZmFpbGVkLiIpO2lmKGxlPSEwLFooKSlyZXR1cm4gbmV3IFByb21pc2UoKChlLHQpPT57RD8udGVybWluYXRlKCksVnQoKS50aGVuKCgoW3Isbl0pPT57dHJ5eyhEPW4pLm9uZXJyb3I9ZT0+dChlKSxELm9ubWVzc2FnZT1Ocix0dD1bZSx0XTtsZXQgbz17dHlwZToiaW5pdC13YXNtIixpbjpBfTtpZighby5pbi53YXNtLndhc21QYXRocyYmcil7bGV0IGU9UGUoKTtlJiYoby5pbi53YXNtLndhc21QYXRocz1lKTt9RC5wb3N0TWVzc2FnZShvKSxfZT1yO31jYXRjaChlKXt0KGUpO319KSx0KTt9KSk7dHJ5e2F3YWl0IEVlKEEud2FzbSksYXdhaXQgVGUoQSksTWU9ITA7fWNhdGNoKGUpe3Rocm93IERlPSEwLGV9ZmluYWxseXtsZT0hMTt9fX0sc3I9YXN5bmMgZT0+e2lmKFooKSlyZXR1cm4gb2UoKSxuZXcgUHJvbWlzZSgoKHQscik9PntuZSgiaW5pdC1lcCIsW3Qscl0pO2xldCBuPXt0eXBlOiJpbml0LWVwIixpbjp7ZXBOYW1lOmUsZW52OkF9fTtELnBvc3RNZXNzYWdlKG4pO30pKTthd2FpdCBTZShBLGUpO30saXI9YXN5bmMgZT0+WigpPyhvZSgpLG5ldyBQcm9taXNlKCgodCxyKT0+e25lKCJjb3B5LWZyb20iLFt0LHJdKTtsZXQgbj17dHlwZToiY29weS1mcm9tIixpbjp7YnVmZmVyOmV9fTtELnBvc3RNZXNzYWdlKG4sW2UuYnVmZmVyXSk7fSkpKTp1ZShlKSxhcj1hc3luYyhlLHQpPT57aWYoWigpKXtpZih0Py5wcmVmZXJyZWRPdXRwdXRMb2NhdGlvbil0aHJvdyBuZXcgRXJyb3IoJ3Nlc3Npb24gb3B0aW9uICJwcmVmZXJyZWRPdXRwdXRMb2NhdGlvbiIgaXMgbm90IHN1cHBvcnRlZCBmb3IgcHJveHkuJyk7cmV0dXJuIG9lKCksbmV3IFByb21pc2UoKChyLG4pPT57bmUoImNyZWF0ZSIsW3Isbl0pO2xldCBvPXt0eXBlOiJjcmVhdGUiLGluOnttb2RlbDplLG9wdGlvbnM6ey4uLnR9fX0sYT1bXTtlIGluc3RhbmNlb2YgVWludDhBcnJheSYmYS5wdXNoKGUuYnVmZmVyKSxELnBvc3RNZXNzYWdlKG8sYSk7fSkpfXJldHVybiBBZShlLHQpfSx1cj1hc3luYyBlPT57aWYoWigpKXJldHVybiBvZSgpLG5ldyBQcm9taXNlKCgodCxyKT0+e25lKCJyZWxlYXNlIixbdCxyXSk7bGV0IG49e3R5cGU6InJlbGVhc2UiLGluOmV9O0QucG9zdE1lc3NhZ2Uobik7fSkpO09lKGUpO30sZnI9YXN5bmMoZSx0LHIsbixvLGEpPT57aWYoWigpKXtpZihyLnNvbWUoKGU9PiJjcHUiIT09ZVszXSkpKXRocm93IG5ldyBFcnJvcigiaW5wdXQgdGVuc29yIG9uIEdQVSBpcyBub3Qgc3VwcG9ydGVkIGZvciBwcm94eS4iKTtpZihvLnNvbWUoKGU9PmUpKSl0aHJvdyBuZXcgRXJyb3IoInByZS1hbGxvY2F0ZWQgb3V0cHV0IHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkIGZvciBwcm94eS4iKTtyZXR1cm4gb2UoKSxuZXcgUHJvbWlzZSgoKG8saSk9PntuZSgicnVuIixbbyxpXSk7bGV0IHM9cixsPXt0eXBlOiJydW4iLGluOntzZXNzaW9uSWQ6ZSxpbnB1dEluZGljZXM6dCxpbnB1dHM6cyxvdXRwdXRJbmRpY2VzOm4sb3B0aW9uczphfX07RC5wb3N0TWVzc2FnZShsLEllKHMpKTt9KSl9cmV0dXJuIHhlKGUsdCxyLG4sbyxhKX0sY3I9YXN5bmMgZT0+e2lmKFooKSlyZXR1cm4gb2UoKSxuZXcgUHJvbWlzZSgoKHQscik9PntuZSgiZW5kLXByb2ZpbGluZyIsW3Qscl0pO2xldCBuPXt0eXBlOiJlbmQtcHJvZmlsaW5nIixpbjplfTtELnBvc3RNZXNzYWdlKG4pO30pKTtMZShlKTt9O30pKSxkcj1UKCgoKT0+e3EoKSxudCgpLFFlKCksYmUoKSxldCgpLGxyPShlLHQpPT57c3dpdGNoKGUubG9jYXRpb24pe2Nhc2UiY3B1IjpyZXR1cm4gW2UudHlwZSxlLmRpbXMsZS5kYXRhLCJjcHUiXTtjYXNlImdwdS1idWZmZXIiOnJldHVybiBbZS50eXBlLGUuZGltcyx7Z3B1QnVmZmVyOmUuZ3B1QnVmZmVyfSwiZ3B1LWJ1ZmZlciJdO2Nhc2UibWwtdGVuc29yIjpyZXR1cm4gW2UudHlwZSxlLmRpbXMse21sVGVuc29yOmUubWxUZW5zb3J9LCJtbC10ZW5zb3IiXTtkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgaW52YWxpZCBkYXRhIGxvY2F0aW9uOiAke2UubG9jYXRpb259IGZvciAke3QoKX1gKX19LFdyPWU9Pntzd2l0Y2goZVszXSl7Y2FzZSJjcHUiOnJldHVybiBuZXcgUihlWzBdLGVbMl0sZVsxXSk7Y2FzZSJncHUtYnVmZmVyIjp7bGV0IHQ9ZVswXTtpZighQ2UodCkpdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIGRhdGEgdHlwZTogJHt0fSBmb3IgZGVzZXJpYWxpemluZyBHUFUgdGVuc29yYCk7bGV0e2dwdUJ1ZmZlcjpyLGRvd25sb2FkOm4sZGlzcG9zZTpvfT1lWzJdO3JldHVybiBSLmZyb21HcHVCdWZmZXIocix7ZGF0YVR5cGU6dCxkaW1zOmVbMV0sZG93bmxvYWQ6bixkaXNwb3NlOm99KX1jYXNlIm1sLXRlbnNvciI6e2xldCB0PWVbMF07aWYoIVVlKHQpKXRocm93IG5ldyBFcnJvcihgbm90IHN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7dH0gZm9yIGRlc2VyaWFsaXppbmcgTUxUZW5zb3IgdGVuc29yYCk7bGV0e21sVGVuc29yOnIsZG93bmxvYWQ6bixkaXNwb3NlOm99PWVbMl07cmV0dXJuIFIuZnJvbU1MVGVuc29yKHIse2RhdGFUeXBlOnQsZGltczplWzFdLGRvd25sb2FkOm4sZGlzcG9zZTpvfSl9ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgZGF0YSBsb2NhdGlvbjogJHtlWzNdfWApfX0sUmU9Y2xhc3N7YXN5bmMgZmV0Y2hNb2RlbEFuZENvcHlUb1dhc21NZW1vcnkoZSl7cmV0dXJuIGlyKGF3YWl0IGNlKGUpKX1hc3luYyBsb2FkTW9kZWwoZSx0KXtsZXQgcjtWKCkscj0ic3RyaW5nIj09dHlwZW9mIGU/YXdhaXQgdGhpcy5mZXRjaE1vZGVsQW5kQ29weVRvV2FzbU1lbW9yeShlKTplLFt0aGlzLnNlc3Npb25JZCx0aGlzLmlucHV0TmFtZXMsdGhpcy5vdXRwdXROYW1lc109YXdhaXQgYXIocix0KSxZKCk7fWFzeW5jIGRpc3Bvc2UoKXtyZXR1cm4gdXIodGhpcy5zZXNzaW9uSWQpfWFzeW5jIHJ1bihlLHQscil7VigpO2xldCBuPVtdLG89W107T2JqZWN0LmVudHJpZXMoZSkuZm9yRWFjaCgoZT0+e2xldCB0PWVbMF0scj1lWzFdLGE9dGhpcy5pbnB1dE5hbWVzLmluZGV4T2YodCk7aWYoLTE9PT1hKXRocm93IG5ldyBFcnJvcihgaW52YWxpZCBpbnB1dCAnJHt0fSdgKTtuLnB1c2gociksby5wdXNoKGEpO30pKTtsZXQgYT1bXSxpPVtdO09iamVjdC5lbnRyaWVzKHQpLmZvckVhY2goKGU9PntsZXQgdD1lWzBdLHI9ZVsxXSxuPXRoaXMub3V0cHV0TmFtZXMuaW5kZXhPZih0KTtpZigtMT09PW4pdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIG91dHB1dCAnJHt0fSdgKTthLnB1c2gociksaS5wdXNoKG4pO30pKTtsZXQgcz1uLm1hcCgoKGUsdCk9PmxyKGUsKCgpPT5gaW5wdXQgIiR7dGhpcy5pbnB1dE5hbWVzW29bdF1dfSJgKSkpKSxsPWEubWFwKCgoZSx0KT0+ZT9scihlLCgoKT0+YG91dHB1dCAiJHt0aGlzLm91dHB1dE5hbWVzW2lbdF1dfSJgKSk6bnVsbCkpLHU9YXdhaXQgZnIodGhpcy5zZXNzaW9uSWQsbyxzLGksbCxyKSxmPXt9O2ZvcihsZXQgZT0wO2U8dS5sZW5ndGg7ZSsrKWZbdGhpcy5vdXRwdXROYW1lc1tpW2VdXV09YVtlXT8/V3IodVtlXSk7cmV0dXJuIFkoKSxmfXN0YXJ0UHJvZmlsaW5nKCl7fWVuZFByb2ZpbGluZygpe2NyKHRoaXMuc2Vzc2lvbklkKTt9fTt9KSksbXI9e307R2UobXIse09ubnhydW50aW1lV2ViQXNzZW1ibHlCYWNrZW5kOigpPT5GZSxpbml0aWFsaXplRmxhZ3M6KCk9PnByLHdhc21CYWNrZW5kOigpPT4kcn0pO3ZhciBwcixGZSwkcixocj1UKCgoKT0+e3EoKSxudCgpLGRyKCkscHI9KCk9PntpZigoIm51bWJlciIhPXR5cGVvZiBBLndhc20uaW5pdFRpbWVvdXR8fEEud2FzbS5pbml0VGltZW91dDwwKSYmKEEud2FzbS5pbml0VGltZW91dD0wKSwhMT09PUEud2FzbS5zaW1kJiZjb25zb2xlLndhcm4oJ0RlcHJlY2F0ZWQgcHJvcGVydHkgImVudi53YXNtLnNpbWQiIGlzIHNldCB0byBmYWxzZS4gbm9uLVNJTUQgYnVpbGQgaXMgbm8gbG9uZ2VyIHByb3ZpZGVkLCBhbmQgdGhpcyBzZXR0aW5nIHdpbGwgYmUgaWdub3JlZC4nKSwiYm9vbGVhbiIhPXR5cGVvZiBBLndhc20ucHJveHkmJihBLndhc20ucHJveHk9ITEpLCJib29sZWFuIiE9dHlwZW9mIEEud2FzbS50cmFjZSYmKEEud2FzbS50cmFjZT0hMSksIm51bWJlciIhPXR5cGVvZiBBLndhc20ubnVtVGhyZWFkc3x8IU51bWJlci5pc0ludGVnZXIoQS53YXNtLm51bVRocmVhZHMpfHxBLndhc20ubnVtVGhyZWFkczw9MClpZih0eXBlb2Ygc2VsZjwidSImJiFzZWxmLmNyb3NzT3JpZ2luSXNvbGF0ZWQpQS53YXNtLm51bVRocmVhZHM9MTtlbHNlIHtsZXQgZT10eXBlb2YgbmF2aWdhdG9yPiJ1Ij8kZSgibm9kZTpvcyIpLmNwdXMoKS5sZW5ndGg6bmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3k7QS53YXNtLm51bVRocmVhZHM9TWF0aC5taW4oNCxNYXRoLmNlaWwoKGV8fDEpLzIpKTt9fSwkcj1uZXcoRmU9Y2xhc3N7YXN5bmMgaW5pdChlKXtwcigpLGF3YWl0IG9yKCksYXdhaXQgc3IoZSk7fWFzeW5jIGNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKGUsdCl7bGV0IHI9bmV3IFJlO3JldHVybiBhd2FpdCByLmxvYWRNb2RlbChlLHQpLFByb21pc2UucmVzb2x2ZShyKX19KTt9KSk7cSgpLHEoKSxxKCk7dmFyIEZ0PSIxLjIxLjAiO3tsZXQgZT0oaHIoKSxhdChtcikpLndhc21CYWNrZW5kO2llKCJjcHUiLGUsMTApLGllKCJ3YXNtIixlLDEwKTt9T2JqZWN0LmRlZmluZVByb3BlcnR5KEEudmVyc2lvbnMsIndlYiIse3ZhbHVlOkZ0LGVudW1lcmFibGU6ITB9KTsKCmNsYXNzIFdvcmtlck5hdGl2ZXtjb25zdHJ1Y3Rvcigpe3RoaXMucmVhZHk9ITE7dGhpcy5pbmRleGVkREJNYW5hZ2VyPW5ldyBJbmRleGVkREJNYW5hZ2VyKCJvbmlyaXgtc2RrIiwiZmlsZXMiKSx0aGlzLmluZGV4ZWREQk1hbmFnZXIuZ2V0RmlsZUZyb21JbmRleGVkREIoIlNES18xLjExLjAiKS50aGVuKChhc3luYyB0PT57bGV0IGU9VVJMLmNyZWF0ZU9iamVjdFVSTChuZXcgQmxvYihbdF0se3R5cGU6InRleHQvamF2YXNjcmlwdCJ9KSk7Y29uc3R7ZGVmYXVsdDphfT1hd2FpdCBpbXBvcnQoLyogd2VicGFja0lnbm9yZTogdHJ1ZSwgd2VicGFja01vZGU6ICJsYXp5IiAqL2UpLGk9YXdhaXQgYSgpO3RoaXMubmF0aXZlU0RLPWksdGhpcy5jb2Fyc2VGcmFtZT10aGlzLm5hdGl2ZVNESy5fbWFsbG9jKDM2ODY0MDApLHRoaXMuZXh0cmFjdGlvbkZyYW1lPXRoaXMubmF0aXZlU0RLLl9tYWxsb2MoMzY4NjQwMCksdGhpcy5idWZmZXJMZW5ndGg9MCx0aGlzLmZyYW1lTGF5b3V0U3RydWN0PXRoaXMubmF0aXZlU0RLLl9tYWxsb2MoMjgpLEEud2FzbS5udW1UaHJlYWRzPTE7Y29uc3Qgcz1hd2FpdCB0aGlzLmluZGV4ZWREQk1hbmFnZXIuZ2V0RmlsZUZyb21JbmRleGVkREIoIm9ydC53YXNtIikscj1VUkwuY3JlYXRlT2JqZWN0VVJMKG5ldyBCbG9iKFtzXSx7dHlwZToiYXBwbGljYXRpb24vd2FzbSJ9KSk7QS53YXNtLndhc21QYXRocz17d2FzbTpyLG1qczoiaHR0cHM6Ly9jZG4ub25pcml4LmNvbS9vbmlyaXgtZW5naW5lLXNkay9vcnRfdjEuMjEuMF9taW4vb3J0LXdhc20tc2ltZC5tanMifTtsZXQgbj1hd2FpdCB0aGlzLmluZGV4ZWREQk1hbmFnZXIuZ2V0RnJvbUNhY2hlT3JGZXRjaCgiY29hcnNlbG9jLm9ydCIsImh0dHBzOi8vY2RuLm9uaXJpeC5jb20vb25pcml4LWVuZ2luZS1zZGsvY29hcnNlbG9jLm9ydCIpO2NvbnN0IG89YXdhaXQgT3IuY3JlYXRlKG4se2V4ZWN1dGlvblByb3ZpZGVyczpbIndhc20iXX0pO2xldCBoPWF3YWl0IHRoaXMuaW5kZXhlZERCTWFuYWdlci5nZXRGcm9tQ2FjaGVPckZldGNoKCJzcGFyc2VfZXh0cmFjdC5vcnQiLCJodHRwczovL2Nkbi5vbmlyaXguY29tL29uaXJpeC1lbmdpbmUtc2RrL3NwYXJzZV9leHRyYWN0Lm9ydCIpO2NvbnN0IGM9YXdhaXQgT3IuY3JlYXRlKGgse2V4ZWN1dGlvblByb3ZpZGVyczpbIndhc20iXX0pO3RoaXMuc2Vzc2lvbj1vLHRoaXMuc2Vzc2lvbkV4dHJhY3Rpb249Yyxhd2FpdCB0aGlzLnNlc3Npb24ucnVuKHtpbnB1dDpuZXcgUihuZXcgRmxvYXQzMkFycmF5KEFycmF5KDkyMTYwMCkuZmlsbCgwKSksWzEsMyw2NDAsNDgwXSl9KSx0aGlzLnJlYWR5PSEwLHBvc3RNZXNzYWdlKCJyZWFkeSIpO30pKTt9c3RhcnQoKXthZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwoYXN5bmMgdD0+e2lmKCF0aGlzLnJlYWR5KXJldHVybiB2b2lkIHBvc3RNZXNzYWdlKCExKTt0aGlzLnJlYWR5PSExO2NvbnN0IGU9dC5kYXRhLGE9ZS53aWR0aCplLmhlaWdodCo0OzAhPXRoaXMuYnVmZmVyTGVuZ3RoJiZ0aGlzLmJ1ZmZlckxlbmd0aD09YXx8KDAhPXRoaXMuYnVmZmVyTGVuZ3RoJiZ0aGlzLm5hdGl2ZVNESy5fZnJlZSh0aGlzLmJ1ZmZlciksdGhpcy5idWZmZXJMZW5ndGg9YSx0aGlzLmJ1ZmZlcj10aGlzLm5hdGl2ZVNESy5fbWFsbG9jKHRoaXMuYnVmZmVyTGVuZ3RoKSksdGhpcy5uYXRpdmVTREsuSEVBUFU4LnNldChlLmRhdGEsdGhpcy5idWZmZXIpLHRoaXMubmF0aXZlU0RLLkhFQVBVMzJbdGhpcy5mcmFtZUxheW91dFN0cnVjdC80KzBdPWUud2lkdGgsdGhpcy5uYXRpdmVTREsuSEVBUFUzMlt0aGlzLmZyYW1lTGF5b3V0U3RydWN0LzQrMV09ZS5oZWlnaHQsdGhpcy5uYXRpdmVTREsuSEVBUFUzMlt0aGlzLmZyYW1lTGF5b3V0U3RydWN0LzQrMl09NCplLndpZHRoLHRoaXMubmF0aXZlU0RLLkhFQVBVMzJbdGhpcy5mcmFtZUxheW91dFN0cnVjdC80KzNdPSExLHRoaXMubmF0aXZlU0RLLkhFQVBVMzJbdGhpcy5mcmFtZUxheW91dFN0cnVjdC80KzRdPWUuY29sb3JTcGFjZSx0aGlzLm5hdGl2ZVNESy5IRUFQVTMyW3RoaXMuZnJhbWVMYXlvdXRTdHJ1Y3QvNCs1XT1lLnJvdGF0ZSx0aGlzLm5hdGl2ZVNESy5IRUFQVTMyW3RoaXMuZnJhbWVMYXlvdXRTdHJ1Y3QvNCs2XT1lLmZsaXA7bGV0IGk9dGhpcy5uYXRpdmVTREsuX09YX0V4dHJhY3QodGhpcy5idWZmZXIsdGhpcy5jb2Fyc2VGcmFtZSx0aGlzLmV4dHJhY3Rpb25GcmFtZSx0aGlzLmZyYW1lTGF5b3V0U3RydWN0LGUuZHR5cGUpLHM9W107aWYoZS5vbmx5Q29hcnNlfHwyIT1lLmR0eXBlKXM9bmV3IEZsb2F0MzJBcnJheSh0aGlzLnJlYWRFeHRyYWN0aW9uRGF0YSh0aGlzLm5hdGl2ZVNESy5IRUFQRjMyLGkvNCkpO2Vsc2Uge2xldCB0PVtdO2ZvcihsZXQgZT0wO2U8OTIxNjAwO2UrKyl0LnB1c2godGhpcy5uYXRpdmVTREsuSEVBUEYzMlt0aGlzLmV4dHJhY3Rpb25GcmFtZS80K2VdKTtsZXR7a2V5cG9pbnRzOmUsZGVzY3JpcHRvcnM6YX09YXdhaXQgdGhpcy5zZXNzaW9uRXh0cmFjdGlvbi5ydW4oe2ltYWdlOm5ldyBSKG5ldyBGbG9hdDMyQXJyYXkodCksWzEsMyw0ODAsNjQwXSl9KSxpPVtlLmRpbXNbMF0sLi4uZS5kYXRhLC4uLmEuZGF0YV07cz1uZXcgRmxvYXQzMkFycmF5KGkpO31sZXQgcj1bXTtmb3IobGV0IHQ9MDt0PDkyMTYwMDt0Kyspci5wdXNoKHRoaXMubmF0aXZlU0RLLkhFQVBGMzJbdGhpcy5jb2Fyc2VGcmFtZS80K3RdKTtsZXQgbj1hd2FpdCB0aGlzLnNlc3Npb24ucnVuKHtpbnB1dDpuZXcgUihuZXcgRmxvYXQzMkFycmF5KHIpLFsxLDMsNjQwLDQ4MF0pfSk7cG9zdE1lc3NhZ2Uoe2V4dHJhY3Rpb246cyxkZXNjcmlwdG9yOm4ub3V0cHV0LmRhdGEsb25seUNvYXJzZTplLm9ubHlDb2Fyc2V9KSx0aGlzLnJlYWR5PSEwO30pKTt9cmVhZEV4dHJhY3Rpb25EYXRhKHQsZSl7bGV0IGE9ZSxpPVtdLHM9dFthXTtpLnB1c2gocyksYSsrO2ZvcihsZXQgZT0wO2U8cztlKyspaS5wdXNoKHRbYV0pLGkucHVzaCh0W2ErMV0pLGErPTI7Zm9yKGxldCBlPTA7ZTwxMjgqcztlKyspaS5wdXNoKHRbYV0pLGErKztyZXR1cm4gaX19Y29uc3Qgd29ya2VyPW5ldyBXb3JrZXJOYXRpdmU7d29ya2VyLnN0YXJ0KCk7Cg=="),b=new Blob([d],{type:"application/javascript"});this.workers[Z]=new Worker(/* webpackIgnore: true, webpackMode: "lazy" */URL.createObjectURL(b),{type:"module"}),this.callbacks[Z]=l,this.workers[Z].addEventListener("message",(l=>{this.callbacks[Z](l.data);}));}}createMatchingWorker(Z,l){if(!this.workerExists(Z)){let d=atob("Y2xhc3MgSW5kZXhlZERCTWFuYWdlcntjb25zdHJ1Y3RvcihlLHIpe3RoaXMuZGJOYW1lPWUsdGhpcy5zdG9yZU5hbWU9cjt9YXN5bmMgZ2V0RnJvbUNhY2hlT3JGZXRjaChlLHIpe2xldCB0PW51bGw7dHJ5e3Q9YXdhaXQgdGhpcy5nZXRGaWxlRnJvbUluZGV4ZWREQihlKTt9Y2F0Y2goZSl7Y29uc29sZS5sb2coIkFuIGVycm9yIG9jY3VycmVkIHdoaWxlIHRyeWluZyB0byBnZXQgZWxlbWVudCBmcm9tIGluZGV4ZWREQi4iKTt9cmV0dXJuIHR8fCh0PWF3YWl0IHRoaXMuZmV0Y2hBbmRDYWNoZUZpbGUocixlKSksbmV3IFVpbnQ4QXJyYXkodCl9YXN5bmMgZ2V0RmlsZUZyb21JbmRleGVkREIoZSl7cmV0dXJuIG5ldyBQcm9taXNlKCgocix0KT0+e2NvbnN0IG89aW5kZXhlZERCLm9wZW4odGhpcy5kYk5hbWUpO28ub25lcnJvcj0oKT0+dChvLmVycm9yKSxvLm9uc3VjY2Vzcz0oKT0+e2NvbnN0IHM9by5yZXN1bHQudHJhbnNhY3Rpb24odGhpcy5zdG9yZU5hbWUsInJlYWRvbmx5Iikub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpLmdldChlKTtzLm9uc3VjY2Vzcz0oKT0+cihzLnJlc3VsdCkscy5vbmVycm9yPSgpPT50KHMuZXJyb3IpO30sby5vbnVwZ3JhZGVuZWVkZWQ9ZT0+e2UudGFyZ2V0LnJlc3VsdC5jcmVhdGVPYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7fTt9KSl9YXN5bmMgc2F2ZUZpbGVUb0luZGV4ZWREQihlLHIpe3JldHVybiBuZXcgUHJvbWlzZSgoKHQsbyk9Pntjb25zdCBzPWluZGV4ZWREQi5vcGVuKHRoaXMuZGJOYW1lKTtzLm9uZXJyb3I9KCk9Pm8ocy5lcnJvcikscy5vbnVwZ3JhZGVuZWVkZWQ9ZT0+e2UudGFyZ2V0LnJlc3VsdC5jcmVhdGVPYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7fSxzLm9uc3VjY2Vzcz0oKT0+e3RyeXtjb25zdCBuPXMucmVzdWx0LnRyYW5zYWN0aW9uKHRoaXMuc3RvcmVOYW1lLCJyZWFkd3JpdGUiKSxhPW4ub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpLnB1dChyLGUpO2Eub25zdWNjZXNzPSgpPT50KGEucmVzdWx0KSxhLm9uZXJyb3I9KCk9Pm8oYS5lcnJvcik7fWNhdGNoKGUpe28oZSk7fX07fSkpfWFzeW5jIGZldGNoQW5kQ2FjaGVGaWxlKGUscil7Y29uc3QgdD1hd2FpdCBmZXRjaChlKSxvPWF3YWl0IHQuYXJyYXlCdWZmZXIoKTtyZXR1cm4gYXdhaXQgdGhpcy5zYXZlRmlsZVRvSW5kZXhlZERCKHIsbyksb319Cgp2YXIgaGUsaixpZSxBcix1dCxjdCxkdCxfLEEsbXQsaHQsSGUseXQsYnQsZ3QsRXQsVHQsSCxhZSxBdCxPdCxMdCxJdCx2LFIsdnQsQnQsVixZLHllLE9yLFdlPU9iamVjdC5kZWZpbmVQcm9wZXJ0eSxncj1PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLEVyPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzLFRyPU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHksJGU9KGU9PnR5cGVvZiByZXF1aXJlPCJ1Ij9yZXF1aXJlOnR5cGVvZiBQcm94eTwidSI/bmV3IFByb3h5KGUse2dldDooZSx0KT0+KHR5cGVvZiByZXF1aXJlPCJ1Ij9yZXF1aXJlOmUpW3RdfSk6ZSkoKGZ1bmN0aW9uKGUpe2lmKHR5cGVvZiByZXF1aXJlPCJ1IilyZXR1cm4gcmVxdWlyZS5hcHBseSh0aGlzLGFyZ3VtZW50cyk7dGhyb3cgRXJyb3IoJ0R5bmFtaWMgcmVxdWlyZSBvZiAiJytlKyciIGlzIG5vdCBzdXBwb3J0ZWQnKX0pKSxUPShlLHQpPT4oKT0+KGUmJih0PWUoZT0wKSksdCksR2U9KGUsdCk9Pntmb3IodmFyIHIgaW4gdClXZShlLHIse2dldDp0W3JdLGVudW1lcmFibGU6ITB9KTt9LFNyPShlLHQscixuKT0+e2lmKHQmJiJvYmplY3QiPT10eXBlb2YgdHx8ImZ1bmN0aW9uIj09dHlwZW9mIHQpZm9yKGxldCBvIG9mIEVyKHQpKSFUci5jYWxsKGUsbykmJm8hPT1yJiZXZShlLG8se2dldDooKT0+dFtvXSxlbnVtZXJhYmxlOiEobj1ncih0LG8pKXx8bi5lbnVtZXJhYmxlfSk7cmV0dXJuIGV9LGF0PWU9PlNyKFdlKHt9LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KSxlKSx6ZT1UKCgoKT0+e2hlPW5ldyBNYXAsaj1bXSxpZT0oZSx0LHIpPT57aWYoIXR8fCJmdW5jdGlvbiIhPXR5cGVvZiB0LmluaXR8fCJmdW5jdGlvbiIhPXR5cGVvZiB0LmNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKXRocm93IG5ldyBUeXBlRXJyb3IoIm5vdCBhIHZhbGlkIGJhY2tlbmQiKTt7bGV0IG49aGUuZ2V0KGUpO2lmKHZvaWQgMD09PW4paGUuc2V0KGUse2JhY2tlbmQ6dCxwcmlvcml0eTpyfSk7ZWxzZSB7aWYobi5wcmlvcml0eT5yKXJldHVybjtpZihuLnByaW9yaXR5PT09ciYmbi5iYWNrZW5kIT09dCl0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCByZWdpc3RlciBiYWNrZW5kICIke2V9IiB1c2luZyBwcmlvcml0eSAke3J9YCl9aWYocj49MCl7bGV0IHQ9ai5pbmRleE9mKGUpOy0xIT09dCYmai5zcGxpY2UodCwxKTtmb3IobGV0IHQ9MDt0PGoubGVuZ3RoO3QrKylpZihoZS5nZXQoalt0XSkucHJpb3JpdHk8PXIpcmV0dXJuIHZvaWQgai5zcGxpY2UodCwwLGUpO2oucHVzaChlKTt9fX0sQXI9YXN5bmMgZT0+e2xldCB0PWhlLmdldChlKTtpZighdClyZXR1cm4gImJhY2tlbmQgbm90IGZvdW5kLiI7aWYodC5pbml0aWFsaXplZClyZXR1cm4gdC5iYWNrZW5kO2lmKHQuYWJvcnRlZClyZXR1cm4gdC5lcnJvcjt7bGV0IHI9ISF0LmluaXRQcm9taXNlO3RyeXtyZXR1cm4gcnx8KHQuaW5pdFByb21pc2U9dC5iYWNrZW5kLmluaXQoZSkpLGF3YWl0IHQuaW5pdFByb21pc2UsdC5pbml0aWFsaXplZD0hMCx0LmJhY2tlbmR9Y2F0Y2goZSl7cmV0dXJuIHJ8fCh0LmVycm9yPWAke2V9YCx0LmFib3J0ZWQ9ITApLHQuZXJyb3J9ZmluYWxseXtkZWxldGUgdC5pbml0UHJvbWlzZTt9fX0sdXQ9YXN5bmMgZT0+e2xldCB0LHI9ZS5leGVjdXRpb25Qcm92aWRlcnN8fFtdLG49ci5tYXAoKGU9PiJzdHJpbmciPT10eXBlb2YgZT9lOmUubmFtZSkpLG89MD09PW4ubGVuZ3RoP2o6bixhPVtdLGk9bmV3IFNldDtmb3IobGV0IGUgb2Ygbyl7bGV0IHI9YXdhaXQgQXIoZSk7InN0cmluZyI9PXR5cGVvZiByP2EucHVzaCh7bmFtZTplLGVycjpyfSk6KHR8fCh0PXIpLHQ9PT1yJiZpLmFkZChlKSk7fWlmKCF0KXRocm93IG5ldyBFcnJvcihgbm8gYXZhaWxhYmxlIGJhY2tlbmQgZm91bmQuIEVSUjogJHthLm1hcCgoZT0+YFske2UubmFtZX1dICR7ZS5lcnJ9YCkpLmpvaW4oIiwgIil9YCk7Zm9yKGxldHtuYW1lOmUsZXJyOnR9b2YgYSluLmluY2x1ZGVzKGUpJiZjb25zb2xlLndhcm4oYHJlbW92aW5nIHJlcXVlc3RlZCBleGVjdXRpb24gcHJvdmlkZXIgIiR7ZX0iIGZyb20gc2Vzc2lvbiBvcHRpb25zIGJlY2F1c2UgaXQgaXMgbm90IGF2YWlsYWJsZTogJHt0fWApO2xldCBzPXIuZmlsdGVyKChlPT5pLmhhcygic3RyaW5nIj09dHlwZW9mIGU/ZTplLm5hbWUpKSk7cmV0dXJuIFt0LG5ldyBQcm94eShlLHtnZXQ6KGUsdCk9PiJleGVjdXRpb25Qcm92aWRlcnMiPT09dD9zOlJlZmxlY3QuZ2V0KGUsdCl9KV19O30pKSxmdD1UKCgoKT0+e3plKCk7fSkpLGx0PVQoKCgpPT57Y3Q9IjEuMjEuMCI7fSkpLGplPVQoKCgpPT57bHQoKSxkdD0id2FybmluZyIsXz17d2FzbTp7fSx3ZWJnbDp7fSx3ZWJncHU6e30sdmVyc2lvbnM6e2NvbW1vbjpjdH0sc2V0IGxvZ0xldmVsKGUpe2lmKHZvaWQgMCE9PWUpe2lmKCJzdHJpbmciIT10eXBlb2YgZXx8LTE9PT1bInZlcmJvc2UiLCJpbmZvIiwid2FybmluZyIsImVycm9yIiwiZmF0YWwiXS5pbmRleE9mKGUpKXRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgbG9nZ2luZyBsZXZlbDogJHtlfWApO2R0PWU7fX0sZ2V0IGxvZ0xldmVsKCl7cmV0dXJuIGR0fX0sT2JqZWN0LmRlZmluZVByb3BlcnR5KF8sImxvZ0xldmVsIix7ZW51bWVyYWJsZTohMH0pO30pKSxwdD1UKCgoKT0+e2plKCksQT1fO30pKSx3dD1UKCgoKT0+e210PShlLHQpPT57bGV0IHI9dHlwZW9mIGRvY3VtZW50PCJ1Ij9kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJjYW52YXMiKTpuZXcgT2Zmc2NyZWVuQ2FudmFzKDEsMSk7ci53aWR0aD1lLmRpbXNbM10sci5oZWlnaHQ9ZS5kaW1zWzJdO2xldCBuPXIuZ2V0Q29udGV4dCgiMmQiKTtpZihudWxsIT1uKXtsZXQgbyxhO3ZvaWQgMCE9PXQ/LnRlbnNvckxheW91dCYmIk5IV0MiPT09dC50ZW5zb3JMYXlvdXQ/KG89ZS5kaW1zWzJdLGE9ZS5kaW1zWzNdKToobz1lLmRpbXNbM10sYT1lLmRpbXNbMl0pO2xldCBpLHMsbD12b2lkIDAhPT10Py5mb3JtYXQ/dC5mb3JtYXQ6IlJHQiIsdT10Py5ub3JtO3ZvaWQgMD09PXV8fHZvaWQgMD09PXUubWVhbj9pPVsyNTUsMjU1LDI1NSwyNTVdOiJudW1iZXIiPT10eXBlb2YgdS5tZWFuP2k9W3UubWVhbix1Lm1lYW4sdS5tZWFuLHUubWVhbl06KGk9W3UubWVhblswXSx1Lm1lYW5bMV0sdS5tZWFuWzJdLDBdLHZvaWQgMCE9PXUubWVhblszXSYmKGlbM109dS5tZWFuWzNdKSksdm9pZCAwPT09dXx8dm9pZCAwPT09dS5iaWFzP3M9WzAsMCwwLDBdOiJudW1iZXIiPT10eXBlb2YgdS5iaWFzP3M9W3UuYmlhcyx1LmJpYXMsdS5iaWFzLHUuYmlhc106KHM9W3UuYmlhc1swXSx1LmJpYXNbMV0sdS5iaWFzWzJdLDBdLHZvaWQgMCE9PXUuYmlhc1szXSYmKHNbM109dS5iaWFzWzNdKSk7bGV0IGY9YSpvLGQ9MCxwPWYsYz0yKmYsaD0tMTsiUkdCQSI9PT1sPyhkPTAscD1mLGM9MipmLGg9MypmKToiUkdCIj09PWw/KGQ9MCxwPWYsYz0yKmYpOiJSQkciPT09bCYmKGQ9MCxjPWYscD0yKmYpO2ZvcihsZXQgdD0wO3Q8YTt0KyspZm9yKGxldCByPTA7cjxvO3IrKyl7bGV0IG89KGUuZGF0YVtkKytdLXNbMF0pKmlbMF0sYT0oZS5kYXRhW3ArK10tc1sxXSkqaVsxXSxsPShlLmRhdGFbYysrXS1zWzJdKSppWzJdLHU9LTE9PT1oPzI1NTooZS5kYXRhW2grK10tc1szXSkqaVszXTtuLmZpbGxTdHlsZT0icmdiYSgiK28rIiwiK2ErIiwiK2wrIiwiK3UrIikiLG4uZmlsbFJlY3Qocix0LDEsMSk7fWlmKCJ0b0RhdGFVUkwiaW4gcilyZXR1cm4gci50b0RhdGFVUkwoKTt0aHJvdyBuZXcgRXJyb3IoInRvRGF0YVVSTCBpcyBub3Qgc3VwcG9ydGVkIil9dGhyb3cgbmV3IEVycm9yKCJDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhIil9LGh0PShlLHQpPT57bGV0IHIsbj10eXBlb2YgZG9jdW1lbnQ8InUiP2RvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImNhbnZhcyIpLmdldENvbnRleHQoIjJkIik6bmV3IE9mZnNjcmVlbkNhbnZhcygxLDEpLmdldENvbnRleHQoIjJkIik7aWYobnVsbD09bil0aHJvdyBuZXcgRXJyb3IoIkNhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEiKTt7bGV0IG8sYSxpO3ZvaWQgMCE9PXQ/LnRlbnNvckxheW91dCYmIk5IV0MiPT09dC50ZW5zb3JMYXlvdXQ/KG89ZS5kaW1zWzJdLGE9ZS5kaW1zWzFdLGk9ZS5kaW1zWzNdKToobz1lLmRpbXNbM10sYT1lLmRpbXNbMl0saT1lLmRpbXNbMV0pO2xldCBzLGwsdT12b2lkIDAhPT10JiZ2b2lkIDAhPT10LmZvcm1hdD90LmZvcm1hdDoiUkdCIixmPXQ/Lm5vcm07dm9pZCAwPT09Znx8dm9pZCAwPT09Zi5tZWFuP3M9WzI1NSwyNTUsMjU1LDI1NV06Im51bWJlciI9PXR5cGVvZiBmLm1lYW4/cz1bZi5tZWFuLGYubWVhbixmLm1lYW4sZi5tZWFuXToocz1bZi5tZWFuWzBdLGYubWVhblsxXSxmLm1lYW5bMl0sMjU1XSx2b2lkIDAhPT1mLm1lYW5bM10mJihzWzNdPWYubWVhblszXSkpLHZvaWQgMD09PWZ8fHZvaWQgMD09PWYuYmlhcz9sPVswLDAsMCwwXToibnVtYmVyIj09dHlwZW9mIGYuYmlhcz9sPVtmLmJpYXMsZi5iaWFzLGYuYmlhcyxmLmJpYXNdOihsPVtmLmJpYXNbMF0sZi5iaWFzWzFdLGYuYmlhc1syXSwwXSx2b2lkIDAhPT1mLmJpYXNbM10mJihsWzNdPWYuYmlhc1szXSkpO2xldCBkPWEqbztpZih2b2lkIDAhPT10JiYodm9pZCAwIT09dC5mb3JtYXQmJjQ9PT1pJiYiUkdCQSIhPT10LmZvcm1hdHx8Mz09PWkmJiJSR0IiIT09dC5mb3JtYXQmJiJCR1IiIT09dC5mb3JtYXQpKXRocm93IG5ldyBFcnJvcigiVGVuc29yIGZvcm1hdCBkb2Vzbid0IG1hdGNoIGlucHV0IHRlbnNvciBkaW1zIik7bGV0IHA9NCxjPTAsaD0xLHc9Mix5PTMsbT0wLGc9ZCxiPTIqZCx2PS0xOyJSR0JBIj09PXU/KG09MCxnPWQsYj0yKmQsdj0zKmQpOiJSR0IiPT09dT8obT0wLGc9ZCxiPTIqZCk6IlJCRyI9PT11JiYobT0wLGI9ZCxnPTIqZCkscj1uLmNyZWF0ZUltYWdlRGF0YShvLGEpO2ZvcihsZXQgdD0wO3Q8YSpvO2MrPXAsaCs9cCx3Kz1wLHkrPXAsdCsrKXIuZGF0YVtjXT0oZS5kYXRhW20rK10tbFswXSkqc1swXSxyLmRhdGFbaF09KGUuZGF0YVtnKytdLWxbMV0pKnNbMV0sci5kYXRhW3ddPShlLmRhdGFbYisrXS1sWzJdKSpzWzJdLHIuZGF0YVt5XT0tMT09PXY/MjU1OihlLmRhdGFbdisrXS1sWzNdKSpzWzNdO31yZXR1cm4gcn07fSkpLFN0PVQoKCgpPT57d2UoKSxIZT0oZSx0KT0+e2lmKHZvaWQgMD09PWUpdGhyb3cgbmV3IEVycm9yKCJJbWFnZSBidWZmZXIgbXVzdCBiZSBkZWZpbmVkIik7aWYodm9pZCAwPT09dC5oZWlnaHR8fHZvaWQgMD09PXQud2lkdGgpdGhyb3cgbmV3IEVycm9yKCJJbWFnZSBoZWlnaHQgYW5kIHdpZHRoIG11c3QgYmUgZGVmaW5lZCIpO2lmKCJOSFdDIj09PXQudGVuc29yTGF5b3V0KXRocm93IG5ldyBFcnJvcigiTkhXQyBUZW5zb3IgbGF5b3V0IGlzIG5vdCBzdXBwb3J0ZWQgeWV0Iik7bGV0IHIsbix7aGVpZ2h0Om8sd2lkdGg6YX09dCxpPXQubm9ybT8/e21lYW46MjU1LGJpYXM6MH07cj0ibnVtYmVyIj09dHlwZW9mIGkubWVhbj9baS5tZWFuLGkubWVhbixpLm1lYW4saS5tZWFuXTpbaS5tZWFuWzBdLGkubWVhblsxXSxpLm1lYW5bMl0saS5tZWFuWzNdPz8yNTVdLG49Im51bWJlciI9PXR5cGVvZiBpLmJpYXM/W2kuYmlhcyxpLmJpYXMsaS5iaWFzLGkuYmlhc106W2kuYmlhc1swXSxpLmJpYXNbMV0saS5iaWFzWzJdLGkuYmlhc1szXT8/MF07bGV0IHM9dm9pZCAwIT09dC5mb3JtYXQ/dC5mb3JtYXQ6IlJHQkEiLGw9dm9pZCAwIT09dC50ZW5zb3JGb3JtYXQmJnZvaWQgMCE9PXQudGVuc29yRm9ybWF0P3QudGVuc29yRm9ybWF0OiJSR0IiLHU9byphLGY9IlJHQkEiPT09bD9uZXcgRmxvYXQzMkFycmF5KDQqdSk6bmV3IEZsb2F0MzJBcnJheSgzKnUpLGQ9NCxwPTAsYz0xLGg9Mix3PTMseT0wLG09dSxnPTIqdSxiPS0xOyJSR0IiPT09cyYmKGQ9MyxwPTAsYz0xLGg9Mix3PS0xKSwiUkdCQSI9PT1sP2I9Myp1OiJSQkciPT09bD8oeT0wLGc9dSxtPTIqdSk6IkJHUiI9PT1sJiYoZz0wLG09dSx5PTIqdSk7Zm9yKGxldCB0PTA7dDx1O3QrKyxwKz1kLGgrPWQsYys9ZCx3Kz1kKWZbeSsrXT0oZVtwXStuWzBdKS9yWzBdLGZbbSsrXT0oZVtjXStuWzFdKS9yWzFdLGZbZysrXT0oZVtoXStuWzJdKS9yWzJdLC0xIT09YiYmLTEhPT13JiYoZltiKytdPShlW3ddK25bM10pL3JbM10pO3JldHVybiBuZXcgdigiZmxvYXQzMiIsZiwiUkdCQSI9PT1sP1sxLDQsbyxhXTpbMSwzLG8sYV0pfSx5dD1hc3luYyhlLHQpPT57bGV0IHIsbj10eXBlb2YgSFRNTEltYWdlRWxlbWVudDwidSImJmUgaW5zdGFuY2VvZiBIVE1MSW1hZ2VFbGVtZW50LG89dHlwZW9mIEltYWdlRGF0YTwidSImJmUgaW5zdGFuY2VvZiBJbWFnZURhdGEsYT10eXBlb2YgSW1hZ2VCaXRtYXA8InUiJiZlIGluc3RhbmNlb2YgSW1hZ2VCaXRtYXAsaT0ic3RyaW5nIj09dHlwZW9mIGUscz10Pz97fSxsPSgpPT57aWYodHlwZW9mIGRvY3VtZW50PCJ1IilyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiY2FudmFzIik7aWYodHlwZW9mIE9mZnNjcmVlbkNhbnZhczwidSIpcmV0dXJuIG5ldyBPZmZzY3JlZW5DYW52YXMoMSwxKTt0aHJvdyBuZXcgRXJyb3IoIkNhbnZhcyBpcyBub3Qgc3VwcG9ydGVkIil9LHU9ZT0+dHlwZW9mIEhUTUxDYW52YXNFbGVtZW50PCJ1IiYmZSBpbnN0YW5jZW9mIEhUTUxDYW52YXNFbGVtZW50fHxlIGluc3RhbmNlb2YgT2Zmc2NyZWVuQ2FudmFzP2UuZ2V0Q29udGV4dCgiMmQiKTpudWxsO2lmKG4pe2xldCBuPWwoKTtuLndpZHRoPWUud2lkdGgsbi5oZWlnaHQ9ZS5oZWlnaHQ7bGV0IG89dShuKTtpZihudWxsPT1vKXRocm93IG5ldyBFcnJvcigiQ2FuIG5vdCBhY2Nlc3MgaW1hZ2UgZGF0YSIpO3tsZXQgbj1lLmhlaWdodCxhPWUud2lkdGg7aWYodm9pZCAwIT09dCYmdm9pZCAwIT09dC5yZXNpemVkSGVpZ2h0JiZ2b2lkIDAhPT10LnJlc2l6ZWRXaWR0aCYmKG49dC5yZXNpemVkSGVpZ2h0LGE9dC5yZXNpemVkV2lkdGgpLHZvaWQgMCE9PXQpe2lmKHM9dCx2b2lkIDAhPT10LnRlbnNvckZvcm1hdCl0aHJvdyBuZXcgRXJyb3IoIkltYWdlIGlucHV0IGNvbmZpZyBmb3JtYXQgbXVzdCBiZSBSR0JBIGZvciBIVE1MSW1hZ2VFbGVtZW50Iik7cy50ZW5zb3JGb3JtYXQ9IlJHQkEiLHMuaGVpZ2h0PW4scy53aWR0aD1hO31lbHNlIHMudGVuc29yRm9ybWF0PSJSR0JBIixzLmhlaWdodD1uLHMud2lkdGg9YTtvLmRyYXdJbWFnZShlLDAsMCkscj1vLmdldEltYWdlRGF0YSgwLDAsYSxuKS5kYXRhO319ZWxzZSB7aWYoIW8pe2lmKGEpe2lmKHZvaWQgMD09PXQpdGhyb3cgbmV3IEVycm9yKCJQbGVhc2UgcHJvdmlkZSBpbWFnZSBjb25maWcgd2l0aCBmb3JtYXQgZm9yIEltYWdlYml0bWFwIik7bGV0IG49bCgpO24ud2lkdGg9ZS53aWR0aCxuLmhlaWdodD1lLmhlaWdodDtsZXQgbz11KG4pO2lmKG51bGwhPW8pe2xldCB0PWUuaGVpZ2h0LG49ZS53aWR0aDtyZXR1cm4gby5kcmF3SW1hZ2UoZSwwLDAsbix0KSxyPW8uZ2V0SW1hZ2VEYXRhKDAsMCxuLHQpLmRhdGEscy5oZWlnaHQ9dCxzLndpZHRoPW4sSGUocixzKX10aHJvdyBuZXcgRXJyb3IoIkNhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEiKX1pZihpKXJldHVybiBuZXcgUHJvbWlzZSgoKHQscik9PntsZXQgbj1sKCksbz11KG4pO2lmKCFlfHwhbylyZXR1cm4gcigpO2xldCBhPW5ldyBJbWFnZTthLmNyb3NzT3JpZ2luPSJBbm9ueW1vdXMiLGEuc3JjPWUsYS5vbmxvYWQ9KCk9PntuLndpZHRoPWEud2lkdGgsbi5oZWlnaHQ9YS5oZWlnaHQsby5kcmF3SW1hZ2UoYSwwLDAsbi53aWR0aCxuLmhlaWdodCk7bGV0IGU9by5nZXRJbWFnZURhdGEoMCwwLG4ud2lkdGgsbi5oZWlnaHQpO3MuaGVpZ2h0PW4uaGVpZ2h0LHMud2lkdGg9bi53aWR0aCx0KEhlKGUuZGF0YSxzKSk7fTt9KSk7dGhyb3cgbmV3IEVycm9yKCJJbnB1dCBkYXRhIHByb3ZpZGVkIGlzIG5vdCBzdXBwb3J0ZWQgLSBhYm9ydGVkIHRlbnNvciBjcmVhdGlvbiIpfXtsZXQgbixvO2lmKHZvaWQgMCE9PXQmJnZvaWQgMCE9PXQucmVzaXplZFdpZHRoJiZ2b2lkIDAhPT10LnJlc2l6ZWRIZWlnaHQ/KG49dC5yZXNpemVkSGVpZ2h0LG89dC5yZXNpemVkV2lkdGgpOihuPWUuaGVpZ2h0LG89ZS53aWR0aCksdm9pZCAwIT09dCYmKHM9dCkscy5mb3JtYXQ9IlJHQkEiLHMuaGVpZ2h0PW4scy53aWR0aD1vLHZvaWQgMCE9PXQpe2xldCB0PWwoKTt0LndpZHRoPW8sdC5oZWlnaHQ9bjtsZXQgYT11KHQpO2lmKG51bGw9PWEpdGhyb3cgbmV3IEVycm9yKCJDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhIik7YS5wdXRJbWFnZURhdGEoZSwwLDApLHI9YS5nZXRJbWFnZURhdGEoMCwwLG8sbikuZGF0YTt9ZWxzZSByPWUuZGF0YTt9fWlmKHZvaWQgMCE9PXIpcmV0dXJuIEhlKHIscyk7dGhyb3cgbmV3IEVycm9yKCJJbnB1dCBkYXRhIHByb3ZpZGVkIGlzIG5vdCBzdXBwb3J0ZWQgLSBhYm9ydGVkIHRlbnNvciBjcmVhdGlvbiIpfSxidD0oZSx0KT0+e2xldHt3aWR0aDpyLGhlaWdodDpuLGRvd25sb2FkOm8sZGlzcG9zZTphfT10O3JldHVybiBuZXcgdih7bG9jYXRpb246InRleHR1cmUiLHR5cGU6ImZsb2F0MzIiLHRleHR1cmU6ZSxkaW1zOlsxLG4sciw0XSxkb3dubG9hZDpvLGRpc3Bvc2U6YX0pfSxndD0oZSx0KT0+e2xldHtkYXRhVHlwZTpyLGRpbXM6bixkb3dubG9hZDpvLGRpc3Bvc2U6YX09dDtyZXR1cm4gbmV3IHYoe2xvY2F0aW9uOiJncHUtYnVmZmVyIix0eXBlOnI/PyJmbG9hdDMyIixncHVCdWZmZXI6ZSxkaW1zOm4sZG93bmxvYWQ6byxkaXNwb3NlOmF9KX0sRXQ9KGUsdCk9PntsZXR7ZGF0YVR5cGU6cixkaW1zOm4sZG93bmxvYWQ6byxkaXNwb3NlOmF9PXQ7cmV0dXJuIG5ldyB2KHtsb2NhdGlvbjoibWwtdGVuc29yIix0eXBlOnI/PyJmbG9hdDMyIixtbFRlbnNvcjplLGRpbXM6bixkb3dubG9hZDpvLGRpc3Bvc2U6YX0pfSxUdD0oZSx0LHIpPT5uZXcgdih7bG9jYXRpb246ImNwdS1waW5uZWQiLHR5cGU6ZSxkYXRhOnQsZGltczpyPz9bdC5sZW5ndGhdfSk7fSkpLHh0PVQoKCgpPT57SD1uZXcgTWFwKFtbImZsb2F0MzIiLEZsb2F0MzJBcnJheV0sWyJ1aW50OCIsVWludDhBcnJheV0sWyJpbnQ4IixJbnQ4QXJyYXldLFsidWludDE2IixVaW50MTZBcnJheV0sWyJpbnQxNiIsSW50MTZBcnJheV0sWyJpbnQzMiIsSW50MzJBcnJheV0sWyJib29sIixVaW50OEFycmF5XSxbImZsb2F0NjQiLEZsb2F0NjRBcnJheV0sWyJ1aW50MzIiLFVpbnQzMkFycmF5XSxbImludDQiLFVpbnQ4QXJyYXldLFsidWludDQiLFVpbnQ4QXJyYXldXSksYWU9bmV3IE1hcChbW0Zsb2F0MzJBcnJheSwiZmxvYXQzMiJdLFtVaW50OEFycmF5LCJ1aW50OCJdLFtJbnQ4QXJyYXksImludDgiXSxbVWludDE2QXJyYXksInVpbnQxNiJdLFtJbnQxNkFycmF5LCJpbnQxNiJdLFtJbnQzMkFycmF5LCJpbnQzMiJdLFtGbG9hdDY0QXJyYXksImZsb2F0NjQiXSxbVWludDMyQXJyYXksInVpbnQzMiJdXSksQXQ9ITEsT3Q9KCk9PntpZighQXQpe0F0PSEwO2xldCBlPXR5cGVvZiBCaWdJbnQ2NEFycmF5PCJ1IiYmQmlnSW50NjRBcnJheS5mcm9tLHQ9dHlwZW9mIEJpZ1VpbnQ2NEFycmF5PCJ1IiYmQmlnVWludDY0QXJyYXkuZnJvbSxyPWdsb2JhbFRoaXMuRmxvYXQxNkFycmF5LG49dHlwZW9mIHI8InUiJiZyLmZyb207ZSYmKEguc2V0KCJpbnQ2NCIsQmlnSW50NjRBcnJheSksYWUuc2V0KEJpZ0ludDY0QXJyYXksImludDY0IikpLHQmJihILnNldCgidWludDY0IixCaWdVaW50NjRBcnJheSksYWUuc2V0KEJpZ1VpbnQ2NEFycmF5LCJ1aW50NjQiKSksbj8oSC5zZXQoImZsb2F0MTYiLHIpLGFlLnNldChyLCJmbG9hdDE2IikpOkguc2V0KCJmbG9hdDE2IixVaW50MTZBcnJheSk7fX07fSkpLFB0PVQoKCgpPT57d2UoKSxMdD1lPT57bGV0IHQ9MTtmb3IobGV0IHI9MDtyPGUubGVuZ3RoO3IrKyl7bGV0IG49ZVtyXTtpZigibnVtYmVyIiE9dHlwZW9mIG58fCFOdW1iZXIuaXNTYWZlSW50ZWdlcihuKSl0aHJvdyBuZXcgVHlwZUVycm9yKGBkaW1zWyR7cn1dIG11c3QgYmUgYW4gaW50ZWdlciwgZ290OiAke259YCk7aWYobjwwKXRocm93IG5ldyBSYW5nZUVycm9yKGBkaW1zWyR7cn1dIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlciwgZ290OiAke259YCk7dCo9bjt9cmV0dXJuIHR9LEl0PShlLHQpPT57c3dpdGNoKGUubG9jYXRpb24pe2Nhc2UiY3B1IjpyZXR1cm4gbmV3IHYoZS50eXBlLGUuZGF0YSx0KTtjYXNlImNwdS1waW5uZWQiOnJldHVybiBuZXcgdih7bG9jYXRpb246ImNwdS1waW5uZWQiLGRhdGE6ZS5kYXRhLHR5cGU6ZS50eXBlLGRpbXM6dH0pO2Nhc2UidGV4dHVyZSI6cmV0dXJuIG5ldyB2KHtsb2NhdGlvbjoidGV4dHVyZSIsdGV4dHVyZTplLnRleHR1cmUsdHlwZTplLnR5cGUsZGltczp0fSk7Y2FzZSJncHUtYnVmZmVyIjpyZXR1cm4gbmV3IHYoe2xvY2F0aW9uOiJncHUtYnVmZmVyIixncHVCdWZmZXI6ZS5ncHVCdWZmZXIsdHlwZTplLnR5cGUsZGltczp0fSk7Y2FzZSJtbC10ZW5zb3IiOnJldHVybiBuZXcgdih7bG9jYXRpb246Im1sLXRlbnNvciIsbWxUZW5zb3I6ZS5tbFRlbnNvcix0eXBlOmUudHlwZSxkaW1zOnR9KTtkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgdGVuc29yUmVzaGFwZTogdGVuc29yIGxvY2F0aW9uICR7ZS5sb2NhdGlvbn0gaXMgbm90IHN1cHBvcnRlZGApfX07fSkpLHdlPVQoKCgpPT57d3QoKSxTdCgpLHh0KCksUHQoKSx2PWNsYXNze2NvbnN0cnVjdG9yKGUsdCxyKXtsZXQgbixvO2lmKE90KCksIm9iamVjdCI9PXR5cGVvZiBlJiYibG9jYXRpb24iaW4gZSlzd2l0Y2godGhpcy5kYXRhTG9jYXRpb249ZS5sb2NhdGlvbixuPWUudHlwZSxvPWUuZGltcyxlLmxvY2F0aW9uKXtjYXNlImNwdS1waW5uZWQiOntsZXQgdD1ILmdldChuKTtpZighdCl0aHJvdyBuZXcgVHlwZUVycm9yKGB1bnN1cHBvcnRlZCB0eXBlICIke259IiB0byBjcmVhdGUgdGVuc29yIGZyb20gcGlubmVkIGJ1ZmZlcmApO2lmKCEoZS5kYXRhIGluc3RhbmNlb2YgdCkpdGhyb3cgbmV3IFR5cGVFcnJvcihgYnVmZmVyIHNob3VsZCBiZSBvZiB0eXBlICR7dC5uYW1lfWApO3RoaXMuY3B1RGF0YT1lLmRhdGE7YnJlYWt9Y2FzZSJ0ZXh0dXJlIjppZigiZmxvYXQzMiIhPT1uKXRocm93IG5ldyBUeXBlRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGUgIiR7bn0iIHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbSB0ZXh0dXJlYCk7dGhpcy5ncHVUZXh0dXJlRGF0YT1lLnRleHR1cmUsdGhpcy5kb3dubG9hZGVyPWUuZG93bmxvYWQsdGhpcy5kaXNwb3Nlcj1lLmRpc3Bvc2U7YnJlYWs7Y2FzZSJncHUtYnVmZmVyIjppZigiZmxvYXQzMiIhPT1uJiYiZmxvYXQxNiIhPT1uJiYiaW50MzIiIT09biYmImludDY0IiE9PW4mJiJ1aW50MzIiIT09biYmInVpbnQ4IiE9PW4mJiJib29sIiE9PW4mJiJ1aW50NCIhPT1uJiYiaW50NCIhPT1uKXRocm93IG5ldyBUeXBlRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGUgIiR7bn0iIHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbSBncHUgYnVmZmVyYCk7dGhpcy5ncHVCdWZmZXJEYXRhPWUuZ3B1QnVmZmVyLHRoaXMuZG93bmxvYWRlcj1lLmRvd25sb2FkLHRoaXMuZGlzcG9zZXI9ZS5kaXNwb3NlO2JyZWFrO2Nhc2UibWwtdGVuc29yIjppZigiZmxvYXQzMiIhPT1uJiYiZmxvYXQxNiIhPT1uJiYiaW50MzIiIT09biYmImludDY0IiE9PW4mJiJ1aW50MzIiIT09biYmInVpbnQ2NCIhPT1uJiYiaW50OCIhPT1uJiYidWludDgiIT09biYmImJvb2wiIT09biYmInVpbnQ0IiE9PW4mJiJpbnQ0IiE9PW4pdGhyb3cgbmV3IFR5cGVFcnJvcihgdW5zdXBwb3J0ZWQgdHlwZSAiJHtufSIgdG8gY3JlYXRlIHRlbnNvciBmcm9tIE1MVGVuc29yYCk7dGhpcy5tbFRlbnNvckRhdGE9ZS5tbFRlbnNvcix0aGlzLmRvd25sb2FkZXI9ZS5kb3dubG9hZCx0aGlzLmRpc3Bvc2VyPWUuZGlzcG9zZTticmVhaztkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgVGVuc29yIGNvbnN0cnVjdG9yOiB1bnN1cHBvcnRlZCBsb2NhdGlvbiAnJHt0aGlzLmRhdGFMb2NhdGlvbn0nYCl9ZWxzZSB7bGV0IGEsaTtpZigic3RyaW5nIj09dHlwZW9mIGUpaWYobj1lLGk9ciwic3RyaW5nIj09PWUpe2lmKCFBcnJheS5pc0FycmF5KHQpKXRocm93IG5ldyBUeXBlRXJyb3IoIkEgc3RyaW5nIHRlbnNvcidzIGRhdGEgbXVzdCBiZSBhIHN0cmluZyBhcnJheS4iKTthPXQ7fWVsc2Uge2xldCByPUguZ2V0KGUpO2lmKHZvaWQgMD09PXIpdGhyb3cgbmV3IFR5cGVFcnJvcihgVW5zdXBwb3J0ZWQgdGVuc29yIHR5cGU6ICR7ZX0uYCk7aWYoQXJyYXkuaXNBcnJheSh0KSl7aWYoImZsb2F0MTYiPT09ZSYmcj09PVVpbnQxNkFycmF5fHwidWludDQiPT09ZXx8ImludDQiPT09ZSl0aHJvdyBuZXcgVHlwZUVycm9yKGBDcmVhdGluZyBhICR7ZX0gdGVuc29yIGZyb20gbnVtYmVyIGFycmF5IGlzIG5vdCBzdXBwb3J0ZWQuIFBsZWFzZSB1c2UgJHtyLm5hbWV9IGFzIGRhdGEuYCk7YT0idWludDY0Ij09PWV8fCJpbnQ2NCI9PT1lP3IuZnJvbSh0LEJpZ0ludCk6ci5mcm9tKHQpO31lbHNlIGlmKHQgaW5zdGFuY2VvZiByKWE9dDtlbHNlIGlmKHQgaW5zdGFuY2VvZiBVaW50OENsYW1wZWRBcnJheSl7aWYoInVpbnQ4IiE9PWUpdGhyb3cgbmV3IFR5cGVFcnJvcigiQSBVaW50OENsYW1wZWRBcnJheSB0ZW5zb3IncyBkYXRhIG11c3QgYmUgdHlwZSBvZiB1aW50OCIpO2E9VWludDhBcnJheS5mcm9tKHQpO31lbHNlIHtpZighKCJmbG9hdDE2Ij09PWUmJnQgaW5zdGFuY2VvZiBVaW50MTZBcnJheSYmciE9PVVpbnQxNkFycmF5KSl0aHJvdyBuZXcgVHlwZUVycm9yKGBBICR7bn0gdGVuc29yJ3MgZGF0YSBtdXN0IGJlIHR5cGUgb2YgJHtyfWApO2E9bmV3IGdsb2JhbFRoaXMuRmxvYXQxNkFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0Lmxlbmd0aCk7fX1lbHNlIGlmKGk9dCxBcnJheS5pc0FycmF5KGUpKXtpZigwPT09ZS5sZW5ndGgpdGhyb3cgbmV3IFR5cGVFcnJvcigiVGVuc29yIHR5cGUgY2Fubm90IGJlIGluZmVycmVkIGZyb20gYW4gZW1wdHkgYXJyYXkuIik7bGV0IHQ9dHlwZW9mIGVbMF07aWYoInN0cmluZyI9PT10KW49InN0cmluZyIsYT1lO2Vsc2Uge2lmKCJib29sZWFuIiE9PXQpdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBlbGVtZW50IHR5cGUgb2YgZGF0YSBhcnJheTogJHt0fS5gKTtuPSJib29sIixhPVVpbnQ4QXJyYXkuZnJvbShlKTt9fWVsc2UgaWYoZSBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5KW49InVpbnQ4IixhPVVpbnQ4QXJyYXkuZnJvbShlKTtlbHNlIHtsZXQgdD1hZS5nZXQoZS5jb25zdHJ1Y3Rvcik7aWYodm9pZCAwPT09dCl0aHJvdyBuZXcgVHlwZUVycm9yKGBVbnN1cHBvcnRlZCB0eXBlIGZvciB0ZW5zb3IgZGF0YTogJHtlLmNvbnN0cnVjdG9yfS5gKTtuPXQsYT1lO31pZih2b2lkIDA9PT1pKWk9W2EubGVuZ3RoXTtlbHNlIGlmKCFBcnJheS5pc0FycmF5KGkpKXRocm93IG5ldyBUeXBlRXJyb3IoIkEgdGVuc29yJ3MgZGltcyBtdXN0IGJlIGEgbnVtYmVyIGFycmF5Iik7bz1pLHRoaXMuY3B1RGF0YT1hLHRoaXMuZGF0YUxvY2F0aW9uPSJjcHUiO31sZXQgYT1MdChvKTtpZih0aGlzLmNwdURhdGEmJmEhPT10aGlzLmNwdURhdGEubGVuZ3RoJiYoInVpbnQ0IiE9PW4mJiJpbnQ0IiE9PW58fE1hdGguY2VpbChhLzIpIT09dGhpcy5jcHVEYXRhLmxlbmd0aCkpdGhyb3cgbmV3IEVycm9yKGBUZW5zb3IncyBzaXplKCR7YX0pIGRvZXMgbm90IG1hdGNoIGRhdGEgbGVuZ3RoKCR7dGhpcy5jcHVEYXRhLmxlbmd0aH0pLmApO3RoaXMudHlwZT1uLHRoaXMuZGltcz1vLHRoaXMuc2l6ZT1hO31zdGF0aWMgYXN5bmMgZnJvbUltYWdlKGUsdCl7cmV0dXJuIHl0KGUsdCl9c3RhdGljIGZyb21UZXh0dXJlKGUsdCl7cmV0dXJuIGJ0KGUsdCl9c3RhdGljIGZyb21HcHVCdWZmZXIoZSx0KXtyZXR1cm4gZ3QoZSx0KX1zdGF0aWMgZnJvbU1MVGVuc29yKGUsdCl7cmV0dXJuIEV0KGUsdCl9c3RhdGljIGZyb21QaW5uZWRCdWZmZXIoZSx0LHIpe3JldHVybiBUdChlLHQscil9dG9EYXRhVVJMKGUpe3JldHVybiBtdCh0aGlzLGUpfXRvSW1hZ2VEYXRhKGUpe3JldHVybiBodCh0aGlzLGUpfWdldCBkYXRhKCl7aWYodGhpcy5lbnN1cmVWYWxpZCgpLCF0aGlzLmNwdURhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgb24gQ1BVLiBVc2UgYGdldERhdGEoKWAgdG8gZG93bmxvYWQgR1BVIGRhdGEgdG8gQ1BVLCBvciB1c2UgYHRleHR1cmVgIG9yIGBncHVCdWZmZXJgIHByb3BlcnR5IHRvIGFjY2VzcyB0aGUgR1BVIGRhdGEgZGlyZWN0bHkuIik7cmV0dXJuIHRoaXMuY3B1RGF0YX1nZXQgbG9jYXRpb24oKXtyZXR1cm4gdGhpcy5kYXRhTG9jYXRpb259Z2V0IHRleHR1cmUoKXtpZih0aGlzLmVuc3VyZVZhbGlkKCksIXRoaXMuZ3B1VGV4dHVyZURhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViR0wgdGV4dHVyZS4iKTtyZXR1cm4gdGhpcy5ncHVUZXh0dXJlRGF0YX1nZXQgZ3B1QnVmZmVyKCl7aWYodGhpcy5lbnN1cmVWYWxpZCgpLCF0aGlzLmdwdUJ1ZmZlckRhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViR1BVIGJ1ZmZlci4iKTtyZXR1cm4gdGhpcy5ncHVCdWZmZXJEYXRhfWdldCBtbFRlbnNvcigpe2lmKHRoaXMuZW5zdXJlVmFsaWQoKSwhdGhpcy5tbFRlbnNvckRhdGEpdGhyb3cgbmV3IEVycm9yKCJUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViTk4gTUxUZW5zb3IuIik7cmV0dXJuIHRoaXMubWxUZW5zb3JEYXRhfWFzeW5jIGdldERhdGEoZSl7c3dpdGNoKHRoaXMuZW5zdXJlVmFsaWQoKSx0aGlzLmRhdGFMb2NhdGlvbil7Y2FzZSJjcHUiOmNhc2UiY3B1LXBpbm5lZCI6cmV0dXJuIHRoaXMuZGF0YTtjYXNlInRleHR1cmUiOmNhc2UiZ3B1LWJ1ZmZlciI6Y2FzZSJtbC10ZW5zb3IiOmlmKCF0aGlzLmRvd25sb2FkZXIpdGhyb3cgbmV3IEVycm9yKCJUaGUgY3VycmVudCB0ZW5zb3IgaXMgbm90IGNyZWF0ZWQgd2l0aCBhIHNwZWNpZmllZCBkYXRhIGRvd25sb2FkZXIuIik7aWYodGhpcy5pc0Rvd25sb2FkaW5nKXRocm93IG5ldyBFcnJvcigiVGhlIGN1cnJlbnQgdGVuc29yIGlzIGJlaW5nIGRvd25sb2FkZWQuIik7dHJ5e3RoaXMuaXNEb3dubG9hZGluZz0hMDtsZXQgdD1hd2FpdCB0aGlzLmRvd25sb2FkZXIoKTtyZXR1cm4gdGhpcy5kb3dubG9hZGVyPXZvaWQgMCx0aGlzLmRhdGFMb2NhdGlvbj0iY3B1Iix0aGlzLmNwdURhdGE9dCxlJiZ0aGlzLmRpc3Bvc2VyJiYodGhpcy5kaXNwb3NlcigpLHRoaXMuZGlzcG9zZXI9dm9pZCAwKSx0fWZpbmFsbHl7dGhpcy5pc0Rvd25sb2FkaW5nPSExO31kZWZhdWx0OnRocm93IG5ldyBFcnJvcihgY2Fubm90IGdldCBkYXRhIGZyb20gbG9jYXRpb246ICR7dGhpcy5kYXRhTG9jYXRpb259YCl9fWRpc3Bvc2UoKXtpZih0aGlzLmlzRG93bmxvYWRpbmcpdGhyb3cgbmV3IEVycm9yKCJUaGUgY3VycmVudCB0ZW5zb3IgaXMgYmVpbmcgZG93bmxvYWRlZC4iKTt0aGlzLmRpc3Bvc2VyJiYodGhpcy5kaXNwb3NlcigpLHRoaXMuZGlzcG9zZXI9dm9pZCAwKSx0aGlzLmNwdURhdGE9dm9pZCAwLHRoaXMuZ3B1VGV4dHVyZURhdGE9dm9pZCAwLHRoaXMuZ3B1QnVmZmVyRGF0YT12b2lkIDAsdGhpcy5tbFRlbnNvckRhdGE9dm9pZCAwLHRoaXMuZG93bmxvYWRlcj12b2lkIDAsdGhpcy5pc0Rvd25sb2FkaW5nPXZvaWQgMCx0aGlzLmRhdGFMb2NhdGlvbj0ibm9uZSI7fWVuc3VyZVZhbGlkKCl7aWYoIm5vbmUiPT09dGhpcy5kYXRhTG9jYXRpb24pdGhyb3cgbmV3IEVycm9yKCJUaGUgdGVuc29yIGlzIGRpc3Bvc2VkLiIpfXJlc2hhcGUoZSl7aWYodGhpcy5lbnN1cmVWYWxpZCgpLHRoaXMuZG93bmxvYWRlcnx8dGhpcy5kaXNwb3Nlcil0aHJvdyBuZXcgRXJyb3IoIkNhbm5vdCByZXNoYXBlIGEgdGVuc29yIHRoYXQgb3ducyBHUFUgcmVzb3VyY2UuIik7cmV0dXJuIEl0KHRoaXMsZSl9fTt9KSksVmU9VCgoKCk9Pnt3ZSgpLFI9djt9KSksWWU9VCgoKCk9PntqZSgpLHZ0PShlLHQpPT57KHR5cGVvZiBfLnRyYWNlPiJ1Ij8hXy53YXNtLnRyYWNlOiFfLnRyYWNlKXx8Y29uc29sZS50aW1lU3RhbXAoYCR7ZX06Ok9SVDo6JHt0fWApO30sQnQ9KGUsdCk9PntsZXQgcj0obmV3IEVycm9yKS5zdGFjaz8uc3BsaXQoL1xyXG58XHJ8XG4vZyl8fFtdLG49ITE7Zm9yKGxldCBvPTA7bzxyLmxlbmd0aDtvKyspe2lmKG4mJiFyW29dLmluY2x1ZGVzKCJUUkFDRV9GVU5DIikpe2xldCBuPWBGVU5DXyR7ZX06OiR7cltvXS50cmltKCkuc3BsaXQoIiAiKVsxXX1gO3JldHVybiB0JiYobis9YDo6JHt0fWApLHZvaWQgdnQoIkNQVSIsbil9cltvXS5pbmNsdWRlcygiVFJBQ0VfRlVOQyIpJiYobj0hMCk7fX0sVj1lPT57KHR5cGVvZiBfLnRyYWNlPiJ1Ij8hXy53YXNtLnRyYWNlOiFfLnRyYWNlKXx8QnQoIkJFR0lOIixlKTt9LFk9ZT0+eyh0eXBlb2YgXy50cmFjZT4idSI/IV8ud2FzbS50cmFjZTohXy50cmFjZSl8fEJ0KCJFTkQiLGUpO307fSkpLEN0PVQoKCgpPT57emUoKSxWZSgpLFllKCkseWU9Y2xhc3MgZXtjb25zdHJ1Y3RvcihlKXt0aGlzLmhhbmRsZXI9ZTt9YXN5bmMgcnVuKGUsdCxyKXtWKCk7bGV0IG49e30sbz17fTtpZigib2JqZWN0IiE9dHlwZW9mIGV8fG51bGw9PT1lfHxlIGluc3RhbmNlb2YgUnx8QXJyYXkuaXNBcnJheShlKSl0aHJvdyBuZXcgVHlwZUVycm9yKCInZmVlZHMnIG11c3QgYmUgYW4gb2JqZWN0IHRoYXQgdXNlIGlucHV0IG5hbWVzIGFzIGtleXMgYW5kIE9ubnhWYWx1ZSBhcyBjb3JyZXNwb25kaW5nIHZhbHVlcy4iKTtsZXQgYT0hMDtpZigib2JqZWN0Ij09dHlwZW9mIHQpe2lmKG51bGw9PT10KXRocm93IG5ldyBUeXBlRXJyb3IoIlVuZXhwZWN0ZWQgYXJndW1lbnRbMV06IGNhbm5vdCBiZSBudWxsLiIpO2lmKHQgaW5zdGFuY2VvZiBSKXRocm93IG5ldyBUeXBlRXJyb3IoIidmZXRjaGVzJyBjYW5ub3QgYmUgYSBUZW5zb3IiKTtpZihBcnJheS5pc0FycmF5KHQpKXtpZigwPT09dC5sZW5ndGgpdGhyb3cgbmV3IFR5cGVFcnJvcigiJ2ZldGNoZXMnIGNhbm5vdCBiZSBhbiBlbXB0eSBhcnJheS4iKTthPSExO2ZvcihsZXQgZSBvZiB0KXtpZigic3RyaW5nIiE9dHlwZW9mIGUpdGhyb3cgbmV3IFR5cGVFcnJvcigiJ2ZldGNoZXMnIG11c3QgYmUgYSBzdHJpbmcgYXJyYXkgb3IgYW4gb2JqZWN0LiIpO2lmKC0xPT09dGhpcy5vdXRwdXROYW1lcy5pbmRleE9mKGUpKXRocm93IG5ldyBSYW5nZUVycm9yKGAnZmV0Y2hlcycgY29udGFpbnMgaW52YWxpZCBvdXRwdXQgbmFtZTogJHtlfS5gKTtuW2VdPW51bGw7fWlmKCJvYmplY3QiPT10eXBlb2YgciYmbnVsbCE9PXIpbz1yO2Vsc2UgaWYodHlwZW9mIHI8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIHtsZXQgZT0hMSxpPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHQpO2ZvcihsZXQgciBvZiB0aGlzLm91dHB1dE5hbWVzKWlmKC0xIT09aS5pbmRleE9mKHIpKXtsZXQgbz10W3JdOyhudWxsPT09b3x8byBpbnN0YW5jZW9mIFIpJiYoZT0hMCxhPSExLG5bcl09byk7fWlmKGUpe2lmKCJvYmplY3QiPT10eXBlb2YgciYmbnVsbCE9PXIpbz1yO2Vsc2UgaWYodHlwZW9mIHI8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIG89dDt9fWVsc2UgaWYodHlwZW9mIHQ8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIlVuZXhwZWN0ZWQgYXJndW1lbnRbMV06IG11c3QgYmUgJ2ZldGNoZXMnIG9yICdvcHRpb25zJy4iKTtmb3IobGV0IHQgb2YgdGhpcy5pbnB1dE5hbWVzKWlmKHR5cGVvZiBlW3RdPiJ1Iil0aHJvdyBuZXcgRXJyb3IoYGlucHV0ICcke3R9JyBpcyBtaXNzaW5nIGluICdmZWVkcycuYCk7aWYoYSlmb3IobGV0IGUgb2YgdGhpcy5vdXRwdXROYW1lcyluW2VdPW51bGw7bGV0IGk9YXdhaXQgdGhpcy5oYW5kbGVyLnJ1bihlLG4sbykscz17fTtmb3IobGV0IGUgaW4gaSlpZihPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChpLGUpKXtsZXQgdD1pW2VdO3NbZV09dCBpbnN0YW5jZW9mIFI/dDpuZXcgUih0LnR5cGUsdC5kYXRhLHQuZGltcyk7fXJldHVybiBZKCksc31hc3luYyByZWxlYXNlKCl7cmV0dXJuIHRoaXMuaGFuZGxlci5kaXNwb3NlKCl9c3RhdGljIGFzeW5jIGNyZWF0ZSh0LHIsbixvKXtWKCk7bGV0IGEsaT17fTtpZigic3RyaW5nIj09dHlwZW9mIHQpe2lmKGE9dCwib2JqZWN0Ij09dHlwZW9mIHImJm51bGwhPT1yKWk9cjtlbHNlIGlmKHR5cGVvZiByPCJ1Iil0aHJvdyBuZXcgVHlwZUVycm9yKCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuIil9ZWxzZSBpZih0IGluc3RhbmNlb2YgVWludDhBcnJheSl7aWYoYT10LCJvYmplY3QiPT10eXBlb2YgciYmbnVsbCE9PXIpaT1yO2Vsc2UgaWYodHlwZW9mIHI8InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIHtpZighKHQgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcnx8dHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyPCJ1IiYmdCBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyKSl0aHJvdyBuZXcgVHlwZUVycm9yKCJVbmV4cGVjdGVkIGFyZ3VtZW50WzBdOiBtdXN0IGJlICdwYXRoJyBvciAnYnVmZmVyJy4iKTt7bGV0IGU9dCxzPTAsbD10LmJ5dGVMZW5ndGg7aWYoIm9iamVjdCI9PXR5cGVvZiByJiZudWxsIT09cilpPXI7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIHIpe2lmKHM9ciwhTnVtYmVyLmlzU2FmZUludGVnZXIocykpdGhyb3cgbmV3IFJhbmdlRXJyb3IoIidieXRlT2Zmc2V0JyBtdXN0IGJlIGFuIGludGVnZXIuIik7aWYoczwwfHxzPj1lLmJ5dGVMZW5ndGgpdGhyb3cgbmV3IFJhbmdlRXJyb3IoYCdieXRlT2Zmc2V0JyBpcyBvdXQgb2YgcmFuZ2UgWzAsICR7ZS5ieXRlTGVuZ3RofSkuYCk7aWYobD10LmJ5dGVMZW5ndGgtcywibnVtYmVyIj09dHlwZW9mIG4pe2lmKGw9biwhTnVtYmVyLmlzU2FmZUludGVnZXIobCkpdGhyb3cgbmV3IFJhbmdlRXJyb3IoIidieXRlTGVuZ3RoJyBtdXN0IGJlIGFuIGludGVnZXIuIik7aWYobDw9MHx8cytsPmUuYnl0ZUxlbmd0aCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihgJ2J5dGVMZW5ndGgnIGlzIG91dCBvZiByYW5nZSAoMCwgJHtlLmJ5dGVMZW5ndGgtc31dLmApO2lmKCJvYmplY3QiPT10eXBlb2YgbyYmbnVsbCE9PW8paT1vO2Vsc2UgaWYodHlwZW9mIG88InUiKXRocm93IG5ldyBUeXBlRXJyb3IoIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC4iKX1lbHNlIGlmKHR5cGVvZiBuPCJ1Iil0aHJvdyBuZXcgVHlwZUVycm9yKCInYnl0ZUxlbmd0aCcgbXVzdCBiZSBhIG51bWJlci4iKX1lbHNlIGlmKHR5cGVvZiByPCJ1Iil0aHJvdyBuZXcgVHlwZUVycm9yKCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuIik7YT1uZXcgVWludDhBcnJheShlLHMsbCk7fX1sZXRbcyxsXT1hd2FpdCB1dChpKSx1PWF3YWl0IHMuY3JlYXRlSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIoYSxsKTtyZXR1cm4gWSgpLG5ldyBlKHUpfXN0YXJ0UHJvZmlsaW5nKCl7dGhpcy5oYW5kbGVyLnN0YXJ0UHJvZmlsaW5nKCk7fWVuZFByb2ZpbGluZygpe3RoaXMuaGFuZGxlci5lbmRQcm9maWxpbmcoKTt9Z2V0IGlucHV0TmFtZXMoKXtyZXR1cm4gdGhpcy5oYW5kbGVyLmlucHV0TmFtZXN9Z2V0IG91dHB1dE5hbWVzKCl7cmV0dXJuIHRoaXMuaGFuZGxlci5vdXRwdXROYW1lc319O30pKSxVdD1UKCgoKT0+e0N0KCksT3I9eWU7fSkpLF90PVQoKCgpPT57fSkpLE10PVQoKCgpPT57fSkpLER0PVQoKCgpPT57fSkpLFJ0PVQoKCgpPT57fSkpLHFlPXt9O0dlKHFlLHtJbmZlcmVuY2VTZXNzaW9uOigpPT5PcixUUkFDRTooKT0+dnQsVFJBQ0VfRlVOQ19CRUdJTjooKT0+VixUUkFDRV9GVU5DX0VORDooKT0+WSxUZW5zb3I6KCk9PlIsZW52OigpPT5BLHJlZ2lzdGVyQmFja2VuZDooKT0+aWV9KTt2YXIgcT1UKCgoKT0+e2Z0KCkscHQoKSxVdCgpLFZlKCksX3QoKSxNdCgpLFllKCksRHQoKSxSdCgpO30pKSxiZT1UKCgoKT0+e30pKSxXdD17fTtHZShXdCx7ZGVmYXVsdDooKT0+eHJ9KTt2YXIga3QsTnQseHIsanQsTSxQZSxYZSxJcixQcixIdCx2cixHdCxWdCx6dCxZdCxaZSxLZSx2ZSxxdCxCcixDcixFZSx4LEwsZmUsUyxKdCxVcixfcixNcixEcixadCxlZSxRdCx0ZSxlcix0cixDZSxVZSxycixjZSxScixUZSxTZSxyZSxGcix1ZSxBZSxPZSxucix4ZSxMZSxJZSxaLEQsbGUsTWUsRGUsX2UsdHQscnQsbmUsb2UsTnIsb3Isc3IsaXIsYXIsdXIsZnIsY3IsbHIsV3IsUmUsJHQ9VCgoKCk9PntKZSgpLEooKSxnZSgpLGt0PSJvcnQtd2FzbS1wcm94eS13b3JrZXIiLChOdD1nbG9iYWxUaGlzLnNlbGY/Lm5hbWU9PT1rdCkmJihzZWxmLm9ubWVzc2FnZT1lPT57bGV0e3R5cGU6dCxpbjpyfT1lLmRhdGE7dHJ5e3N3aXRjaCh0KXtjYXNlImluaXQtd2FzbSI6RWUoci53YXNtKS50aGVuKCgoKT0+e1RlKHIpLnRoZW4oKCgpPT57cG9zdE1lc3NhZ2Uoe3R5cGU6dH0pO30pLChlPT57cG9zdE1lc3NhZ2Uoe3R5cGU6dCxlcnI6ZX0pO30pKTt9KSwoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsZXJyOmV9KTt9KSk7YnJlYWs7Y2FzZSJpbml0LWVwIjp7bGV0e2VwTmFtZTplLGVudjpufT1yO1NlKG4sZSkudGhlbigoKCk9Pntwb3N0TWVzc2FnZSh7dHlwZTp0fSk7fSksKGU9Pntwb3N0TWVzc2FnZSh7dHlwZTp0LGVycjplfSk7fSkpO2JyZWFrfWNhc2UiY29weS1mcm9tIjp7bGV0e2J1ZmZlcjplfT1yLG49dWUoZSk7cG9zdE1lc3NhZ2Uoe3R5cGU6dCxvdXQ6bn0pO2JyZWFrfWNhc2UiY3JlYXRlIjp7bGV0e21vZGVsOmUsb3B0aW9uczpufT1yO0FlKGUsbikudGhlbigoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsb3V0OmV9KTt9KSwoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsZXJyOmV9KTt9KSk7YnJlYWt9Y2FzZSJyZWxlYXNlIjpPZShyKSxwb3N0TWVzc2FnZSh7dHlwZTp0fSk7YnJlYWs7Y2FzZSJydW4iOntsZXR7c2Vzc2lvbklkOmUsaW5wdXRJbmRpY2VzOm4saW5wdXRzOm8sb3V0cHV0SW5kaWNlczphLG9wdGlvbnM6aX09cjt4ZShlLG4sbyxhLG5ldyBBcnJheShhLmxlbmd0aCkuZmlsbChudWxsKSxpKS50aGVuKChlPT57ZS5zb21lKChlPT4iY3B1IiE9PWVbM10pKT9wb3N0TWVzc2FnZSh7dHlwZTp0LGVycjoiUHJveHkgZG9lcyBub3Qgc3VwcG9ydCBub24tY3B1IHRlbnNvciBsb2NhdGlvbi4ifSk6cG9zdE1lc3NhZ2Uoe3R5cGU6dCxvdXQ6ZX0sSWUoWy4uLm8sLi4uZV0pKTt9KSwoZT0+e3Bvc3RNZXNzYWdlKHt0eXBlOnQsZXJyOmV9KTt9KSk7YnJlYWt9Y2FzZSJlbmQtcHJvZmlsaW5nIjpMZShyKSxwb3N0TWVzc2FnZSh7dHlwZTp0fSk7fX1jYXRjaChlKXtwb3N0TWVzc2FnZSh7dHlwZTp0LGVycjplfSk7fX0pLHhyPU50P251bGw6ZT0+bmV3IFdvcmtlcihlPz9NLHt0eXBlOiJtb2R1bGUiLG5hbWU6a3R9KTt9KSksZ2U9VCgoKCk9PntiZSgpLGp0PXR5cGVvZiBsb2NhdGlvbj4idSI/dm9pZCAwOmxvY2F0aW9uLm9yaWdpbixNPSgoKT0+aW1wb3J0Lm1ldGEudXJsPy5zdGFydHNXaXRoKCJmaWxlOiIpP25ldyBVUkwobmV3IFVSTCgib3J0Lndhc20uYnVuZGxlLm1pbi5tanMiLGltcG9ydC5tZXRhLnVybCkuaHJlZixqdCkuaHJlZjppbXBvcnQubWV0YS51cmwpKCksUGU9KCk9PntpZihNJiYhTS5zdGFydHNXaXRoKCJibG9iOiIpKXJldHVybiBNLnN1YnN0cmluZygwLE0ubGFzdEluZGV4T2YoIi8iKSsxKX0sWGU9KGUsdCk9Pnt0cnl7bGV0IHI9dD8/TTtyZXR1cm4gKHI/bmV3IFVSTChlLHIpOm5ldyBVUkwoZSkpLm9yaWdpbj09PWp0fWNhdGNoe3JldHVybiAhMX19LElyPShlLHQpPT57bGV0IHI9dD8/TTt0cnl7cmV0dXJuIChyP25ldyBVUkwoZSxyKTpuZXcgVVJMKGUpKS5ocmVmfWNhdGNoe3JldHVybn19LFByPShlLHQpPT5gJHt0Pz8iLi8ifSR7ZX1gLEh0PWFzeW5jIGU9PntsZXQgdD1hd2FpdChhd2FpdCBmZXRjaChlLHtjcmVkZW50aWFsczoic2FtZS1vcmlnaW4ifSkpLmJsb2IoKTtyZXR1cm4gVVJMLmNyZWF0ZU9iamVjdFVSTCh0KX0sdnI9YXN5bmMgZT0+KGF3YWl0IGltcG9ydChlKSkuZGVmYXVsdCxHdD0oJHQoKSxhdChXdCkpLmRlZmF1bHQsVnQ9YXN5bmMoKT0+e2lmKCFNKXRocm93IG5ldyBFcnJvcigiRmFpbGVkIHRvIGxvYWQgcHJveHkgd29ya2VyOiBjYW5ub3QgZGV0ZXJtaW5lIHRoZSBzY3JpcHQgc291cmNlIFVSTC4iKTtpZihYZShNKSlyZXR1cm4gW3ZvaWQgMCxHdCgpXTtsZXQgZT1hd2FpdCBIdChNKTtyZXR1cm4gW2UsR3QoZSldfSx6dD12b2lkIDAsWXQ9YXN5bmMoZSx0LHIpPT57aWYoIWUmJiF0JiZ6dCYmTSYmWGUoTSkpcmV0dXJuIFt2b2lkIDAsenRdO3tsZXQgbj0ib3J0LXdhc20tc2ltZC10aHJlYWRlZC5tanMiLG89ZT8/SXIobix0KSxhPXImJm8mJiFYZShvLHQpLGk9YT9hd2FpdCBIdChvKTpvPz9QcihuLHQpO3JldHVybiBbYT9pOnZvaWQgMCxhd2FpdCB2cihpKV19fTt9KSksSj1UKCgoKT0+e2dlKCksS2U9ITEsdmU9ITEscXQ9ITEsQnI9KCk9PntpZih0eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXI+InUiKXJldHVybiAhMTt0cnl7cmV0dXJuIHR5cGVvZiBNZXNzYWdlQ2hhbm5lbDwidSImJihuZXcgTWVzc2FnZUNoYW5uZWwpLnBvcnQxLnBvc3RNZXNzYWdlKG5ldyBTaGFyZWRBcnJheUJ1ZmZlcigxKSksV2ViQXNzZW1ibHkudmFsaWRhdGUobmV3IFVpbnQ4QXJyYXkoWzAsOTcsMTE1LDEwOSwxLDAsMCwwLDEsNCwxLDk2LDAsMCwzLDIsMSwwLDUsNCwxLDMsMSwxLDEwLDExLDEsOSwwLDY1LDAsMjU0LDE2LDIsMCwyNiwxMV0pKX1jYXRjaHtyZXR1cm4gITF9fSxDcj0oKT0+e3RyeXtyZXR1cm4gV2ViQXNzZW1ibHkudmFsaWRhdGUobmV3IFVpbnQ4QXJyYXkoWzAsOTcsMTE1LDEwOSwxLDAsMCwwLDEsNCwxLDk2LDAsMCwzLDIsMSwwLDEwLDMwLDEsMjgsMCw2NSwwLDI1MywxNSwyNTMsMTIsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwyNTMsMTg2LDEsMjYsMTFdKSl9Y2F0Y2h7cmV0dXJuICExfX0sRWU9YXN5bmMgZT0+e2lmKEtlKXJldHVybiBQcm9taXNlLnJlc29sdmUoKTtpZih2ZSl0aHJvdyBuZXcgRXJyb3IoIm11bHRpcGxlIGNhbGxzIHRvICdpbml0aWFsaXplV2ViQXNzZW1ibHkoKScgZGV0ZWN0ZWQuIik7aWYocXQpdGhyb3cgbmV3IEVycm9yKCJwcmV2aW91cyBjYWxsIHRvICdpbml0aWFsaXplV2ViQXNzZW1ibHkoKScgZmFpbGVkLiIpO3ZlPSEwO2xldCB0PWUuaW5pdFRpbWVvdXQscj1lLm51bVRocmVhZHM7aWYoIUNyKCkpdGhyb3cgbmV3IEVycm9yKCJXZWJBc3NlbWJseSBTSU1EIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuIik7bGV0IG49QnIoKTtyPjEmJiFuJiYodHlwZW9mIHNlbGY8InUiJiYhc2VsZi5jcm9zc09yaWdpbklzb2xhdGVkJiZjb25zb2xlLndhcm4oImVudi53YXNtLm51bVRocmVhZHMgaXMgc2V0IHRvICIrcisiLCBidXQgdGhpcyB3aWxsIG5vdCB3b3JrIHVubGVzcyB5b3UgZW5hYmxlIGNyb3NzT3JpZ2luSXNvbGF0ZWQgbW9kZS4gU2VlIGh0dHBzOi8vd2ViLmRldi9jcm9zcy1vcmlnaW4taXNvbGF0aW9uLWd1aWRlLyBmb3IgbW9yZSBpbmZvLiIpLGNvbnNvbGUud2FybigiV2ViQXNzZW1ibHkgbXVsdGktdGhyZWFkaW5nIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuIEZhbGxpbmcgYmFjayB0byBzaW5nbGUtdGhyZWFkaW5nLiIpLGUubnVtVGhyZWFkcz1yPTEpO2xldCBvPWUud2FzbVBhdGhzLGE9InN0cmluZyI9PXR5cGVvZiBvP286dm9pZCAwLGk9bz8ubWpzLHM9aT8uaHJlZj8/aSxsPW8/Lndhc20sdT1sPy5ocmVmPz9sLGY9ZS53YXNtQmluYXJ5LFtkLHBdPWF3YWl0IFl0KHMsYSxyPjEpLGM9ITEsaD1bXTtpZih0PjAmJmgucHVzaChuZXcgUHJvbWlzZSgoZT0+e3NldFRpbWVvdXQoKCgpPT57Yz0hMCxlKCk7fSksdCk7fSkpKSxoLnB1c2gobmV3IFByb21pc2UoKChlLHQpPT57bGV0IG49e251bVRocmVhZHM6cn07aWYoZiluLndhc21CaW5hcnk9ZjtlbHNlIGlmKHV8fGEpbi5sb2NhdGVGaWxlPWU9PnU/P2ErZTtlbHNlIGlmKHMmJjAhPT1zLmluZGV4T2YoImJsb2I6Iikpbi5sb2NhdGVGaWxlPWU9Pm5ldyBVUkwoZSxzKS5ocmVmO2Vsc2UgaWYoZCl7bGV0IGU9UGUoKTtlJiYobi5sb2NhdGVGaWxlPXQ9PmUrdCk7fXAobikudGhlbigodD0+e3ZlPSExLEtlPSEwLFplPXQsZSgpLGQmJlVSTC5yZXZva2VPYmplY3RVUkwoZCk7fSksKGU9Pnt2ZT0hMSxxdD0hMCx0KGUpO30pKTt9KSkpLGF3YWl0IFByb21pc2UucmFjZShoKSxjKXRocm93IG5ldyBFcnJvcihgV2ViQXNzZW1ibHkgYmFja2VuZCBpbml0aWFsaXppbmcgZmFpbGVkIGR1ZSB0byB0aW1lb3V0OiAke3R9bXNgKX0seD0oKT0+e2lmKEtlJiZaZSlyZXR1cm4gWmU7dGhyb3cgbmV3IEVycm9yKCJXZWJBc3NlbWJseSBpcyBub3QgaW5pdGlhbGl6ZWQgeWV0LiIpfTt9KSksQmU9VCgoKCk9PntKKCksTD0oZSx0KT0+e2xldCByPXgoKSxuPXIubGVuZ3RoQnl0ZXNVVEY4KGUpKzEsbz1yLl9tYWxsb2Mobik7cmV0dXJuIHIuc3RyaW5nVG9VVEY4KGUsbyxuKSx0LnB1c2gobyksb30sZmU9KGUsdCxyLG4pPT57aWYoIm9iamVjdCI9PXR5cGVvZiBlJiZudWxsIT09ZSl7aWYoci5oYXMoZSkpdGhyb3cgbmV3IEVycm9yKCJDaXJjdWxhciByZWZlcmVuY2UgaW4gb3B0aW9ucyIpO3IuYWRkKGUpO31PYmplY3QuZW50cmllcyhlKS5mb3JFYWNoKCgoW2Usb10pPT57bGV0IGE9dD90K2U6ZTtpZigib2JqZWN0Ij09dHlwZW9mIG8pZmUobyxhKyIuIixyLG4pO2Vsc2UgaWYoInN0cmluZyI9PXR5cGVvZiBvfHwibnVtYmVyIj09dHlwZW9mIG8pbihhLG8udG9TdHJpbmcoKSk7ZWxzZSB7aWYoImJvb2xlYW4iIT10eXBlb2Ygbyl0aHJvdyBuZXcgRXJyb3IoIkNhbid0IGhhbmRsZSBleHRyYSBjb25maWcgdHlwZTogIit0eXBlb2Ygbyk7bihhLG8/IjEiOiIwIik7fX0pKTt9LFM9ZT0+e2xldCB0PXgoKSxyPXQuc3RhY2tTYXZlKCk7dHJ5e2xldCByPXQuUFRSX1NJWkUsbj10LnN0YWNrQWxsb2MoMipyKTt0Ll9PcnRHZXRMYXN0RXJyb3IobixuK3IpO2xldCBvPU51bWJlcih0LmdldFZhbHVlKG4sND09PXI/ImkzMiI6Imk2NCIpKSxhPXQuZ2V0VmFsdWUobityLCIqIiksaT1hP3QuVVRGOFRvU3RyaW5nKGEpOiIiO3Rocm93IG5ldyBFcnJvcihgJHtlfSBFUlJPUl9DT0RFOiAke299LCBFUlJPUl9NRVNTQUdFOiAke2l9YCl9ZmluYWxseXt0LnN0YWNrUmVzdG9yZShyKTt9fTt9KSksWHQ9VCgoKCk9PntKKCksQmUoKSxKdD1lPT57bGV0IHQ9eCgpLHI9MCxuPVtdLG89ZXx8e307dHJ5e2lmKHZvaWQgMD09PWU/LmxvZ1NldmVyaXR5TGV2ZWwpby5sb2dTZXZlcml0eUxldmVsPTI7ZWxzZSBpZigibnVtYmVyIiE9dHlwZW9mIGUubG9nU2V2ZXJpdHlMZXZlbHx8IU51bWJlci5pc0ludGVnZXIoZS5sb2dTZXZlcml0eUxldmVsKXx8ZS5sb2dTZXZlcml0eUxldmVsPDB8fGUubG9nU2V2ZXJpdHlMZXZlbD40KXRocm93IG5ldyBFcnJvcihgbG9nIHNlcnZlcml0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7ZS5sb2dTZXZlcml0eUxldmVsfWApO2lmKHZvaWQgMD09PWU/LmxvZ1ZlcmJvc2l0eUxldmVsKW8ubG9nVmVyYm9zaXR5TGV2ZWw9MDtlbHNlIGlmKCJudW1iZXIiIT10eXBlb2YgZS5sb2dWZXJib3NpdHlMZXZlbHx8IU51bWJlci5pc0ludGVnZXIoZS5sb2dWZXJib3NpdHlMZXZlbCkpdGhyb3cgbmV3IEVycm9yKGBsb2cgdmVyYm9zaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtlLmxvZ1ZlcmJvc2l0eUxldmVsfWApO3ZvaWQgMD09PWU/LnRlcm1pbmF0ZSYmKG8udGVybWluYXRlPSExKTtsZXQgYT0wO3JldHVybiB2b2lkIDAhPT1lPy50YWcmJihhPUwoZS50YWcsbikpLHI9dC5fT3J0Q3JlYXRlUnVuT3B0aW9ucyhvLmxvZ1NldmVyaXR5TGV2ZWwsby5sb2dWZXJib3NpdHlMZXZlbCwhIW8udGVybWluYXRlLGEpLDA9PT1yJiZTKCJDYW4ndCBjcmVhdGUgcnVuIG9wdGlvbnMuIiksdm9pZCAwIT09ZT8uZXh0cmEmJmZlKGUuZXh0cmEsIiIsbmV3IFdlYWtTZXQsKChlLG8pPT57bGV0IGE9TChlLG4pLGk9TChvLG4pOzAhPT10Ll9PcnRBZGRSdW5Db25maWdFbnRyeShyLGEsaSkmJlMoYENhbid0IHNldCBhIHJ1biBjb25maWcgZW50cnk6ICR7ZX0gLSAke299LmApO30pKSxbcixuXX1jYXRjaChlKXt0aHJvdyAwIT09ciYmdC5fT3J0UmVsZWFzZVJ1bk9wdGlvbnMociksbi5mb3JFYWNoKChlPT50Ll9mcmVlKGUpKSksZX19O30pKSxLdD1UKCgoKT0+e0ooKSxCZSgpLFVyPWU9Pntzd2l0Y2goZSl7Y2FzZSJkaXNhYmxlZCI6cmV0dXJuIDA7Y2FzZSJiYXNpYyI6cmV0dXJuIDE7Y2FzZSJleHRlbmRlZCI6cmV0dXJuIDI7Y2FzZSJhbGwiOnJldHVybiA5OTtkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZ3JhcGggb3B0aW1pemF0aW9uIGxldmVsOiAke2V9YCl9fSxfcj1lPT57c3dpdGNoKGUpe2Nhc2Uic2VxdWVudGlhbCI6cmV0dXJuIDA7Y2FzZSJwYXJhbGxlbCI6cmV0dXJuIDE7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGV4ZWN1dGlvbiBtb2RlOiAke2V9YCl9fSxNcj1lPT57ZS5leHRyYXx8KGUuZXh0cmE9e30pLGUuZXh0cmEuc2Vzc2lvbnx8KGUuZXh0cmEuc2Vzc2lvbj17fSk7bGV0IHQ9ZS5leHRyYS5zZXNzaW9uO3QudXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseXx8KHQudXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseT0iMSIpLGUuZXhlY3V0aW9uUHJvdmlkZXJzJiZlLmV4ZWN1dGlvblByb3ZpZGVycy5zb21lKChlPT4id2ViZ3B1Ij09PSgic3RyaW5nIj09dHlwZW9mIGU/ZTplLm5hbWUpKSkmJihlLmVuYWJsZU1lbVBhdHRlcm49ITEpO30sRHI9KGUsdCxyKT0+e2ZvcihsZXQgbiBvZiB0KXtsZXQgdD0ic3RyaW5nIj09dHlwZW9mIG4/bjpuLm5hbWU7c3dpdGNoKHQpe2Nhc2Uid2Vibm4iOmlmKHQ9IldFQk5OIiwic3RyaW5nIiE9dHlwZW9mIG4pe2xldCB0PW4/LmRldmljZVR5cGU7aWYodCl7bGV0IG49TCgiZGV2aWNlVHlwZSIsciksbz1MKHQscik7MCE9PXgoKS5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5KGUsbixvKSYmUyhgQ2FuJ3Qgc2V0IGEgc2Vzc2lvbiBjb25maWcgZW50cnk6ICdkZXZpY2VUeXBlJyAtICR7dH0uYCk7fX1icmVhaztjYXNlIndlYmdwdSI6aWYodD0iSlMiLCJzdHJpbmciIT10eXBlb2Ygbil7bGV0IHQ9bjtpZih0Py5wcmVmZXJyZWRMYXlvdXQpe2lmKCJOQ0hXIiE9PXQucHJlZmVycmVkTGF5b3V0JiYiTkhXQyIhPT10LnByZWZlcnJlZExheW91dCl0aHJvdyBuZXcgRXJyb3IoYHByZWZlcnJlZExheW91dCBtdXN0IGJlIGVpdGhlciAnTkNIVycgb3IgJ05IV0MnOiAke3QucHJlZmVycmVkTGF5b3V0fWApO2xldCBuPUwoInByZWZlcnJlZExheW91dCIsciksbz1MKHQucHJlZmVycmVkTGF5b3V0LHIpOzAhPT14KCkuX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShlLG4sbykmJlMoYENhbid0IHNldCBhIHNlc3Npb24gY29uZmlnIGVudHJ5OiAncHJlZmVycmVkTGF5b3V0JyAtICR7dC5wcmVmZXJyZWRMYXlvdXR9LmApO319YnJlYWs7Y2FzZSJ3YXNtIjpjYXNlImNwdSI6Y29udGludWU7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYG5vdCBzdXBwb3J0ZWQgZXhlY3V0aW9uIHByb3ZpZGVyOiAke3R9YCl9bGV0IG89TCh0LHIpOzAhPT14KCkuX09ydEFwcGVuZEV4ZWN1dGlvblByb3ZpZGVyKGUsbykmJlMoYENhbid0IGFwcGVuZCBleGVjdXRpb24gcHJvdmlkZXI6ICR7dH0uYCk7fX0sWnQ9ZT0+e2xldCB0PXgoKSxyPTAsbj1bXSxvPWV8fHt9O01yKG8pO3RyeXtsZXQgZT1VcihvLmdyYXBoT3B0aW1pemF0aW9uTGV2ZWw/PyJhbGwiKSxhPV9yKG8uZXhlY3V0aW9uTW9kZT8/InNlcXVlbnRpYWwiKSxpPSJzdHJpbmciPT10eXBlb2Ygby5sb2dJZD9MKG8ubG9nSWQsbik6MCxzPW8ubG9nU2V2ZXJpdHlMZXZlbD8/MjtpZighTnVtYmVyLmlzSW50ZWdlcihzKXx8czwwfHxzPjQpdGhyb3cgbmV3IEVycm9yKGBsb2cgc2VydmVyaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtzfWApO2xldCBsPW8ubG9nVmVyYm9zaXR5TGV2ZWw/PzA7aWYoIU51bWJlci5pc0ludGVnZXIobCl8fGw8MHx8bD40KXRocm93IG5ldyBFcnJvcihgbG9nIHZlcmJvc2l0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7bH1gKTtsZXQgdT0ic3RyaW5nIj09dHlwZW9mIG8ub3B0aW1pemVkTW9kZWxGaWxlUGF0aD9MKG8ub3B0aW1pemVkTW9kZWxGaWxlUGF0aCxuKTowO2lmKHI9dC5fT3J0Q3JlYXRlU2Vzc2lvbk9wdGlvbnMoZSwhIW8uZW5hYmxlQ3B1TWVtQXJlbmEsISFvLmVuYWJsZU1lbVBhdHRlcm4sYSwhIW8uZW5hYmxlUHJvZmlsaW5nLDAsaSxzLGwsdSksMD09PXImJlMoIkNhbid0IGNyZWF0ZSBzZXNzaW9uIG9wdGlvbnMuIiksby5leGVjdXRpb25Qcm92aWRlcnMmJkRyKHIsby5leGVjdXRpb25Qcm92aWRlcnMsbiksdm9pZCAwIT09by5lbmFibGVHcmFwaENhcHR1cmUpe2lmKCJib29sZWFuIiE9dHlwZW9mIG8uZW5hYmxlR3JhcGhDYXB0dXJlKXRocm93IG5ldyBFcnJvcihgZW5hYmxlR3JhcGhDYXB0dXJlIG11c3QgYmUgYSBib29sZWFuIHZhbHVlOiAke28uZW5hYmxlR3JhcGhDYXB0dXJlfWApO2xldCBlPUwoImVuYWJsZUdyYXBoQ2FwdHVyZSIsbiksYT1MKG8uZW5hYmxlR3JhcGhDYXB0dXJlLnRvU3RyaW5nKCksbik7MCE9PXQuX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShyLGUsYSkmJlMoYENhbid0IHNldCBhIHNlc3Npb24gY29uZmlnIGVudHJ5OiAnZW5hYmxlR3JhcGhDYXB0dXJlJyAtICR7by5lbmFibGVHcmFwaENhcHR1cmV9LmApO31pZihvLmZyZWVEaW1lbnNpb25PdmVycmlkZXMpZm9yKGxldFtlLGFdb2YgT2JqZWN0LmVudHJpZXMoby5mcmVlRGltZW5zaW9uT3ZlcnJpZGVzKSl7aWYoInN0cmluZyIhPXR5cGVvZiBlKXRocm93IG5ldyBFcnJvcihgZnJlZSBkaW1lbnNpb24gb3ZlcnJpZGUgbmFtZSBtdXN0IGJlIGEgc3RyaW5nOiAke2V9YCk7aWYoIm51bWJlciIhPXR5cGVvZiBhfHwhTnVtYmVyLmlzSW50ZWdlcihhKXx8YTwwKXRocm93IG5ldyBFcnJvcihgZnJlZSBkaW1lbnNpb24gb3ZlcnJpZGUgdmFsdWUgbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyOiAke2F9YCk7bGV0IG89TChlLG4pOzAhPT10Ll9PcnRBZGRGcmVlRGltZW5zaW9uT3ZlcnJpZGUocixvLGEpJiZTKGBDYW4ndCBzZXQgYSBmcmVlIGRpbWVuc2lvbiBvdmVycmlkZTogJHtlfSAtICR7YX0uYCk7fXJldHVybiB2b2lkIDAhPT1vLmV4dHJhJiZmZShvLmV4dHJhLCIiLG5ldyBXZWFrU2V0LCgoZSxvKT0+e2xldCBhPUwoZSxuKSxpPUwobyxuKTswIT09dC5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5KHIsYSxpKSYmUyhgQ2FuJ3Qgc2V0IGEgc2Vzc2lvbiBjb25maWcgZW50cnk6ICR7ZX0gLSAke299LmApO30pKSxbcixuXX1jYXRjaChlKXt0aHJvdyAwIT09ciYmMCE9PXQuX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucyhyKSYmUygiQ2FuJ3QgcmVsZWFzZSBzZXNzaW9uIG9wdGlvbnMuIiksbi5mb3JFYWNoKChlPT50Ll9mcmVlKGUpKSksZX19O30pKSxRZT1UKCgoKT0+e2VlPWU9Pntzd2l0Y2goZSl7Y2FzZSJpbnQ4IjpyZXR1cm4gMztjYXNlInVpbnQ4IjpyZXR1cm4gMjtjYXNlImJvb2wiOnJldHVybiA5O2Nhc2UiaW50MTYiOnJldHVybiA1O2Nhc2UidWludDE2IjpyZXR1cm4gNDtjYXNlImludDMyIjpyZXR1cm4gNjtjYXNlInVpbnQzMiI6cmV0dXJuIDEyO2Nhc2UiZmxvYXQxNiI6cmV0dXJuIDEwO2Nhc2UiZmxvYXQzMiI6cmV0dXJuIDE7Y2FzZSJmbG9hdDY0IjpyZXR1cm4gMTE7Y2FzZSJzdHJpbmciOnJldHVybiA4O2Nhc2UiaW50NjQiOnJldHVybiA3O2Nhc2UidWludDY0IjpyZXR1cm4gMTM7Y2FzZSJpbnQ0IjpyZXR1cm4gMjI7Y2FzZSJ1aW50NCI6cmV0dXJuIDIxO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZX1gKX19LFF0PWU9Pntzd2l0Y2goZSl7Y2FzZSAzOnJldHVybiAiaW50OCI7Y2FzZSAyOnJldHVybiAidWludDgiO2Nhc2UgOTpyZXR1cm4gImJvb2wiO2Nhc2UgNTpyZXR1cm4gImludDE2IjtjYXNlIDQ6cmV0dXJuICJ1aW50MTYiO2Nhc2UgNjpyZXR1cm4gImludDMyIjtjYXNlIDEyOnJldHVybiAidWludDMyIjtjYXNlIDEwOnJldHVybiAiZmxvYXQxNiI7Y2FzZSAxOnJldHVybiAiZmxvYXQzMiI7Y2FzZSAxMTpyZXR1cm4gImZsb2F0NjQiO2Nhc2UgODpyZXR1cm4gInN0cmluZyI7Y2FzZSA3OnJldHVybiAiaW50NjQiO2Nhc2UgMTM6cmV0dXJuICJ1aW50NjQiO2Nhc2UgMjI6cmV0dXJuICJpbnQ0IjtjYXNlIDIxOnJldHVybiAidWludDQiO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZX1gKX19LHRlPShlLHQpPT57bGV0IHI9Wy0xLDQsMSwxLDIsMiw0LDgsLTEsMSwyLDgsNCw4LC0xLC0xLC0xLC0xLC0xLC0xLC0xLC41LC41XVtlXSxuPSJudW1iZXIiPT10eXBlb2YgdD90OnQucmVkdWNlKCgoZSx0KT0+ZSp0KSwxKTtyZXR1cm4gcj4wP01hdGguY2VpbChuKnIpOnZvaWQgMH0sZXI9ZT0+e3N3aXRjaChlKXtjYXNlImZsb2F0MTYiOnJldHVybiB0eXBlb2YgRmxvYXQxNkFycmF5PCJ1IiYmRmxvYXQxNkFycmF5LmZyb20/RmxvYXQxNkFycmF5OlVpbnQxNkFycmF5O2Nhc2UiZmxvYXQzMiI6cmV0dXJuIEZsb2F0MzJBcnJheTtjYXNlInVpbnQ4IjpjYXNlImJvb2wiOnJldHVybiBVaW50OEFycmF5O2Nhc2UiaW50OCI6cmV0dXJuIEludDhBcnJheTtjYXNlInVpbnQxNiI6cmV0dXJuIFVpbnQxNkFycmF5O2Nhc2UiaW50MTYiOnJldHVybiBJbnQxNkFycmF5O2Nhc2UiaW50MzIiOnJldHVybiBJbnQzMkFycmF5O2Nhc2UiZmxvYXQ2NCI6cmV0dXJuIEZsb2F0NjRBcnJheTtjYXNlInVpbnQzMiI6cmV0dXJuIFVpbnQzMkFycmF5O2Nhc2UiaW50NjQiOnJldHVybiBCaWdJbnQ2NEFycmF5O2Nhc2UidWludDY0IjpyZXR1cm4gQmlnVWludDY0QXJyYXk7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGU6ICR7ZX1gKX19LHRyPWU9Pntzd2l0Y2goZSl7Y2FzZSJ2ZXJib3NlIjpyZXR1cm4gMDtjYXNlImluZm8iOnJldHVybiAxO2Nhc2Uid2FybmluZyI6cmV0dXJuIDI7Y2FzZSJlcnJvciI6cmV0dXJuIDM7Y2FzZSJmYXRhbCI6cmV0dXJuIDQ7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGxvZ2dpbmcgbGV2ZWw6ICR7ZX1gKX19LENlPWU9PiJmbG9hdDMyIj09PWV8fCJmbG9hdDE2Ij09PWV8fCJpbnQzMiI9PT1lfHwiaW50NjQiPT09ZXx8InVpbnQzMiI9PT1lfHwidWludDgiPT09ZXx8ImJvb2wiPT09ZXx8InVpbnQ0Ij09PWV8fCJpbnQ0Ij09PWUsVWU9ZT0+ImZsb2F0MzIiPT09ZXx8ImZsb2F0MTYiPT09ZXx8ImludDMyIj09PWV8fCJpbnQ2NCI9PT1lfHwidWludDMyIj09PWV8fCJ1aW50NjQiPT09ZXx8ImludDgiPT09ZXx8InVpbnQ4Ij09PWV8fCJib29sIj09PWV8fCJ1aW50NCI9PT1lfHwiaW50NCI9PT1lLHJyPWU9Pntzd2l0Y2goZSl7Y2FzZSJub25lIjpyZXR1cm4gMDtjYXNlImNwdSI6cmV0dXJuIDE7Y2FzZSJjcHUtcGlubmVkIjpyZXR1cm4gMjtjYXNlInRleHR1cmUiOnJldHVybiAzO2Nhc2UiZ3B1LWJ1ZmZlciI6cmV0dXJuIDQ7Y2FzZSJtbC10ZW5zb3IiOnJldHVybiA1O2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIGxvY2F0aW9uOiAke2V9YCl9fTt9KSksZXQ9VCgoKCk9PntiZSgpLGNlPWFzeW5jIGU9PntpZigic3RyaW5nIj09dHlwZW9mIGUpe3tsZXQgdD1hd2FpdCBmZXRjaChlKTtpZighdC5vayl0aHJvdyBuZXcgRXJyb3IoYGZhaWxlZCB0byBsb2FkIGV4dGVybmFsIGRhdGEgZmlsZTogJHtlfWApO2xldCByPXQuaGVhZGVycy5nZXQoIkNvbnRlbnQtTGVuZ3RoIiksbj1yP3BhcnNlSW50KHIsMTApOjA7aWYobjwxMDczNzQxODI0KXJldHVybiBuZXcgVWludDhBcnJheShhd2FpdCB0LmFycmF5QnVmZmVyKCkpO3tpZighdC5ib2R5KXRocm93IG5ldyBFcnJvcihgZmFpbGVkIHRvIGxvYWQgZXh0ZXJuYWwgZGF0YSBmaWxlOiAke2V9LCBubyByZXNwb25zZSBib2R5LmApO2xldCByLG89dC5ib2R5LmdldFJlYWRlcigpO3RyeXtyPW5ldyBBcnJheUJ1ZmZlcihuKTt9Y2F0Y2goZSl7aWYoIShlIGluc3RhbmNlb2YgUmFuZ2VFcnJvcikpdGhyb3cgZTt7bGV0IGU9TWF0aC5jZWlsKG4vNjU1MzYpO3I9bmV3IFdlYkFzc2VtYmx5Lk1lbW9yeSh7aW5pdGlhbDplLG1heGltdW06ZX0pLmJ1ZmZlcjt9fWxldCBhPTA7Zm9yKDs7KXtsZXR7ZG9uZTplLHZhbHVlOnR9PWF3YWl0IG8ucmVhZCgpO2lmKGUpYnJlYWs7bGV0IG49dC5ieXRlTGVuZ3RoO25ldyBVaW50OEFycmF5KHIsYSxuKS5zZXQodCksYSs9bjt9cmV0dXJuIG5ldyBVaW50OEFycmF5KHIsMCxuKX19fXJldHVybiBlIGluc3RhbmNlb2YgQmxvYj9uZXcgVWludDhBcnJheShhd2FpdCBlLmFycmF5QnVmZmVyKCkpOmUgaW5zdGFuY2VvZiBVaW50OEFycmF5P2U6bmV3IFVpbnQ4QXJyYXkoZSl9O30pKSxKZT1UKCgoKT0+e1h0KCksS3QoKSxRZSgpLEooKSxCZSgpLGV0KCksUnI9KGUsdCk9PnswIT09eCgpLl9PcnRJbml0KGUsdCkmJlMoIkNhbid0IGluaXRpYWxpemUgb25ueHJ1bnRpbWUuIik7fSxUZT1hc3luYyBlPT57UnIoZS53YXNtLm51bVRocmVhZHMsdHIoZS5sb2dMZXZlbCkpO30sU2U9YXN5bmMoZSx0KT0+e30scmU9bmV3IE1hcCxGcj1lPT57bGV0IHQ9eCgpLHI9dC5zdGFja1NhdmUoKTt0cnl7bGV0IHI9dC5QVFJfU0laRSxuPXQuc3RhY2tBbGxvYygyKnIpOzAhPT10Ll9PcnRHZXRJbnB1dE91dHB1dENvdW50KGUsbixuK3IpJiZTKCJDYW4ndCBnZXQgc2Vzc2lvbiBpbnB1dC9vdXRwdXQgY291bnQuIik7bGV0IG89ND09PXI/ImkzMiI6Imk2NCI7cmV0dXJuIFtOdW1iZXIodC5nZXRWYWx1ZShuLG8pKSxOdW1iZXIodC5nZXRWYWx1ZShuK3IsbykpXX1maW5hbGx5e3Quc3RhY2tSZXN0b3JlKHIpO319LHVlPWU9PntsZXQgdD14KCkscj10Ll9tYWxsb2MoZS5ieXRlTGVuZ3RoKTtpZigwPT09cil0aHJvdyBuZXcgRXJyb3IoYENhbid0IGNyZWF0ZSBhIHNlc3Npb24uIGZhaWxlZCB0byBhbGxvY2F0ZSBhIGJ1ZmZlciBvZiBzaXplICR7ZS5ieXRlTGVuZ3RofS5gKTtyZXR1cm4gdC5IRUFQVTguc2V0KGUsciksW3IsZS5ieXRlTGVuZ3RoXX0sQWU9YXN5bmMoZSx0KT0+e2xldCByLG4sbz14KCk7QXJyYXkuaXNBcnJheShlKT9bcixuXT1lOmUuYnVmZmVyPT09by5IRUFQVTguYnVmZmVyP1tyLG5dPVtlLmJ5dGVPZmZzZXQsZS5ieXRlTGVuZ3RoXTpbcixuXT11ZShlKTtsZXQgYT0wLGk9MCxzPVtdLGw9W10sdT1bXTt0cnl7aWYoW2ksc109WnQodCksdD8uZXh0ZXJuYWxEYXRhJiZvLm1vdW50RXh0ZXJuYWxEYXRhKXtsZXQgZT1bXTtmb3IobGV0IHIgb2YgdC5leHRlcm5hbERhdGEpe2xldCB0PSJzdHJpbmciPT10eXBlb2Ygcj9yOnIucGF0aDtlLnB1c2goY2UoInN0cmluZyI9PXR5cGVvZiByP3I6ci5kYXRhKS50aGVuKChlPT57by5tb3VudEV4dGVybmFsRGF0YSh0LGUpO30pKSk7fWF3YWl0IFByb21pc2UuYWxsKGUpO31mb3IobGV0IGUgb2YgdD8uZXhlY3V0aW9uUHJvdmlkZXJzPz9bXSlpZigid2Vibm4iPT09KCJzdHJpbmciPT10eXBlb2YgZT9lOmUubmFtZSkpe2lmKG8uc2hvdWxkVHJhbnNmZXJUb01MVGVuc29yPSExLCJzdHJpbmciIT10eXBlb2YgZSl7bGV0IHQ9ZSxyPXQ/LmNvbnRleHQsbj10Py5ncHVEZXZpY2UsYT10Py5kZXZpY2VUeXBlLGk9dD8ucG93ZXJQcmVmZXJlbmNlO28uY3VycmVudENvbnRleHQ9cnx8KG4/YXdhaXQgby5qc2VwQ3JlYXRlTUxDb250ZXh0KG4pOmF3YWl0IG8uanNlcENyZWF0ZU1MQ29udGV4dCh7ZGV2aWNlVHlwZTphLHBvd2VyUHJlZmVyZW5jZTppfSkpO31lbHNlIG8uY3VycmVudENvbnRleHQ9YXdhaXQgby5qc2VwQ3JlYXRlTUxDb250ZXh0KCk7YnJlYWt9YT1hd2FpdCBvLl9PcnRDcmVhdGVTZXNzaW9uKHIsbixpKSwwPT09YSYmUygiQ2FuJ3QgY3JlYXRlIGEgc2Vzc2lvbi4iKSxvLmpzZXBPbkNyZWF0ZVNlc3Npb24/LigpLG8uY3VycmVudENvbnRleHQmJihvLmpzZXBSZWdpc3Rlck1MQ29udGV4dChhLG8uY3VycmVudENvbnRleHQpLG8uY3VycmVudENvbnRleHQ9dm9pZCAwLG8uc2hvdWxkVHJhbnNmZXJUb01MVGVuc29yPSEwKTtsZXRbZSxmXT1GcihhKSxkPSEhdD8uZW5hYmxlR3JhcGhDYXB0dXJlLHA9W10sYz1bXTtmb3IobGV0IHQ9MDt0PGU7dCsrKXtsZXQgZT1vLl9PcnRHZXRJbnB1dE5hbWUoYSx0KTswPT09ZSYmUygiQ2FuJ3QgZ2V0IGFuIGlucHV0IG5hbWUuIiksbC5wdXNoKGUpLHAucHVzaChvLlVURjhUb1N0cmluZyhlKSk7fWZvcihsZXQgZT0wO2U8ZjtlKyspe2xldCB0PW8uX09ydEdldE91dHB1dE5hbWUoYSxlKTswPT09dCYmUygiQ2FuJ3QgZ2V0IGFuIG91dHB1dCBuYW1lLiIpLHUucHVzaCh0KTtsZXQgcj1vLlVURjhUb1N0cmluZyh0KTtjLnB1c2gocik7fXJldHVybiByZS5zZXQoYSxbYSxsLHUsbnVsbCxkLCExXSksW2EscCxjXX1jYXRjaChlKXt0aHJvdyBsLmZvckVhY2goKGU9Pm8uX09ydEZyZWUoZSkpKSx1LmZvckVhY2goKGU9Pm8uX09ydEZyZWUoZSkpKSwwIT09YSYmMCE9PW8uX09ydFJlbGVhc2VTZXNzaW9uKGEpJiZTKCJDYW4ndCByZWxlYXNlIHNlc3Npb24uIiksZX1maW5hbGx5e28uX2ZyZWUociksMCE9PWkmJjAhPT1vLl9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnMoaSkmJlMoIkNhbid0IHJlbGVhc2Ugc2Vzc2lvbiBvcHRpb25zLiIpLHMuZm9yRWFjaCgoZT0+by5fZnJlZShlKSkpLG8udW5tb3VudEV4dGVybmFsRGF0YT8uKCk7fX0sT2U9ZT0+e2xldCB0PXgoKSxyPXJlLmdldChlKTtpZighcil0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCByZWxlYXNlIHNlc3Npb24uIGludmFsaWQgc2Vzc2lvbiBpZDogJHtlfWApO2xldFtuLG8sYSxpLHNdPXI7aSYmKHMmJjAhPT10Ll9PcnRDbGVhckJvdW5kT3V0cHV0cyhpLmhhbmRsZSkmJlMoIkNhbid0IGNsZWFyIGJvdW5kIG91dHB1dHMuIiksMCE9PXQuX09ydFJlbGVhc2VCaW5kaW5nKGkuaGFuZGxlKSYmUygiQ2FuJ3QgcmVsZWFzZSBJTyBiaW5kaW5nLiIpKSx0LmpzZXBPblJlbGVhc2VTZXNzaW9uPy4oZSksby5mb3JFYWNoKChlPT50Ll9PcnRGcmVlKGUpKSksYS5mb3JFYWNoKChlPT50Ll9PcnRGcmVlKGUpKSksMCE9PXQuX09ydFJlbGVhc2VTZXNzaW9uKG4pJiZTKCJDYW4ndCByZWxlYXNlIHNlc3Npb24uIikscmUuZGVsZXRlKGUpO30sbnI9YXN5bmMoZSx0LHIsbixvLGE9ITEpPT57aWYoIWUpcmV0dXJuIHZvaWQgdC5wdXNoKDApO2xldCBpLHMsbD14KCksdT1sLlBUUl9TSVpFLGY9ZVswXSxkPWVbMV0scD1lWzNdLGM9cDtpZigic3RyaW5nIj09PWYmJigiZ3B1LWJ1ZmZlciI9PT1wfHwibWwtdGVuc29yIj09PXApKXRocm93IG5ldyBFcnJvcigiU3RyaW5nIHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkIG9uIEdQVS4iKTtpZihhJiYiZ3B1LWJ1ZmZlciIhPT1wKXRocm93IG5ldyBFcnJvcihgRXh0ZXJuYWwgYnVmZmVyIG11c3QgYmUgcHJvdmlkZWQgZm9yIGlucHV0L291dHB1dCBpbmRleCAke299IHdoZW4gZW5hYmxlR3JhcGhDYXB0dXJlIGlzIHRydWUuYCk7aWYoImdwdS1idWZmZXIiPT09cCl7bGV0IHQ9ZVsyXS5ncHVCdWZmZXI7cz10ZShlZShmKSxkKTtsZXQgcj1sLmpzZXBSZWdpc3RlckJ1ZmZlcjtpZighcil0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiAiZ3B1LWJ1ZmZlciIgaXMgbm90IHN1cHBvcnRlZCB3aXRob3V0IHVzaW5nIFdlYkdQVS4nKTtpPXIobixvLHQscyk7fWVsc2UgaWYoIm1sLXRlbnNvciI9PT1wKXtsZXQgdD1lWzJdLm1sVGVuc29yO3M9dGUoZWUoZiksZCk7bGV0IHI9bC5qc2VwUmVnaXN0ZXJNTFRlbnNvcjtpZighcil0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiAibWwtdGVuc29yIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViTk4uJyk7aT1yKG4sdCxlZShmKSxkKTt9ZWxzZSB7bGV0IHQ9ZVsyXTtpZihBcnJheS5pc0FycmF5KHQpKXtzPXUqdC5sZW5ndGgsaT1sLl9tYWxsb2Mocyksci5wdXNoKGkpO2ZvcihsZXQgZT0wO2U8dC5sZW5ndGg7ZSsrKXtpZigic3RyaW5nIiE9dHlwZW9mIHRbZV0pdGhyb3cgbmV3IFR5cGVFcnJvcihgdGVuc29yIGRhdGEgYXQgaW5kZXggJHtlfSBpcyBub3QgYSBzdHJpbmdgKTtsLnNldFZhbHVlKGkrZSp1LEwodFtlXSxyKSwiKiIpO319ZWxzZSB7bGV0IGU9bC5qc2VwSXNHcmFwaElucHV0O2lmKCJzdHJpbmciIT09ZiYmZSl7bGV0IGE9bC5fT3J0R2V0SW5wdXROYW1lKG4sbyk7aWYoZShuLGwuVVRGOFRvU3RyaW5nKGEpKSl7bGV0IGU9ZWUoZik7cz10ZShlLGQpLGM9Im1sLXRlbnNvciI7bGV0IHI9bC5qc2VwQ3JlYXRlVGVtcG9yYXJ5VGVuc29yLG89bC5qc2VwVXBsb2FkVGVuc29yO2lmKCFyfHwhbyl0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiAibWwtdGVuc29yIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViTk4uJyk7bGV0IGE9YXdhaXQgcihuLGUsZCk7byhhLG5ldyBVaW50OEFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0LmJ5dGVMZW5ndGgpKSxpPWE7fWVsc2Ugcz10LmJ5dGVMZW5ndGgsaT1sLl9tYWxsb2Mocyksci5wdXNoKGkpLGwuSEVBUFU4LnNldChuZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQscyksaSk7fWVsc2Ugcz10LmJ5dGVMZW5ndGgsaT1sLl9tYWxsb2Mocyksci5wdXNoKGkpLGwuSEVBUFU4LnNldChuZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQscyksaSk7fX1sZXQgaD1sLnN0YWNrU2F2ZSgpLHc9bC5zdGFja0FsbG9jKDQqZC5sZW5ndGgpO3RyeXtkLmZvckVhY2goKChlLHQpPT5sLnNldFZhbHVlKHcrdCp1LGUsND09PXU/ImkzMiI6Imk2NCIpKSk7bGV0IGU9bC5fT3J0Q3JlYXRlVGVuc29yKGVlKGYpLGkscyx3LGQubGVuZ3RoLHJyKGMpKTswPT09ZSYmUyhgQ2FuJ3QgY3JlYXRlIHRlbnNvciBmb3IgaW5wdXQvb3V0cHV0LiBzZXNzaW9uPSR7bn0sIGluZGV4PSR7b30uYCksdC5wdXNoKGUpO31maW5hbGx5e2wuc3RhY2tSZXN0b3JlKGgpO319LHhlPWFzeW5jKGUsdCxyLG4sbyxhKT0+e2xldCBpPXgoKSxzPWkuUFRSX1NJWkUsbD1yZS5nZXQoZSk7aWYoIWwpdGhyb3cgbmV3IEVycm9yKGBjYW5ub3QgcnVuIGluZmVyZW5jZS4gaW52YWxpZCBzZXNzaW9uIGlkOiAke2V9YCk7bGV0IHU9bFswXSxmPWxbMV0sZD1sWzJdLHA9bFszXSxjPWxbNF0saD0obFs1XSx0Lmxlbmd0aCksdz1uLmxlbmd0aCx5PTAsbT1bXSxnPVtdLGI9W10sdj1bXSxFPWkuc3RhY2tTYXZlKCksVD1pLnN0YWNrQWxsb2MoaCpzKSxBPWkuc3RhY2tBbGxvYyhoKnMpLEw9aS5zdGFja0FsbG9jKHcqcyksQz1pLnN0YWNrQWxsb2ModypzKTt0cnl7W3ksbV09SnQoYSk7Zm9yKGxldCBuPTA7bjxoO24rKylhd2FpdCBucihyW25dLGcsdixlLHRbbl0sYyk7Zm9yKGxldCB0PTA7dDx3O3QrKylhd2FpdCBucihvW3RdLGIsdixlLGgrblt0XSxjKTtmb3IobGV0IGU9MDtlPGg7ZSsrKWkuc2V0VmFsdWUoVCtlKnMsZ1tlXSwiKiIpLGkuc2V0VmFsdWUoQStlKnMsZlt0W2VdXSwiKiIpO2ZvcihsZXQgZT0wO2U8dztlKyspaS5zZXRWYWx1ZShMK2UqcyxiW2VdLCIqIiksaS5zZXRWYWx1ZShDK2UqcyxkW25bZV1dLCIqIik7bGV0IGw7aS5qc2VwT25SdW5TdGFydD8uKHUpLGw9YXdhaXQgaS5fT3J0UnVuKHUsQSxULGgsQyx3LEwseSksMCE9PWwmJlMoImZhaWxlZCB0byBjYWxsIE9ydFJ1bigpLiIpO2xldCBFPVtdO2ZvcihsZXQgdD0wO3Q8dzt0Kyspe2xldCByPU51bWJlcihpLmdldFZhbHVlKEwrdCpzLCIqIikpO2lmKHI9PT1iW3RdKXtFLnB1c2gob1t0XSk7Y29udGludWV9bGV0IGEsbD1pLnN0YWNrU2F2ZSgpLGY9aS5zdGFja0FsbG9jKDQqcyksZD0hMSxjPTA7dHJ5ezAhPT1pLl9PcnRHZXRUZW5zb3JEYXRhKHIsZixmK3MsZisyKnMsZiszKnMpJiZTKGBDYW4ndCBhY2Nlc3Mgb3V0cHV0IHRlbnNvciBkYXRhIG9uIGluZGV4ICR7dH0uYCk7bGV0IG89ND09PXM/ImkzMiI6Imk2NCIsbD1OdW1iZXIoaS5nZXRWYWx1ZShmLG8pKTtjPWkuZ2V0VmFsdWUoZitzLCIqIik7bGV0IHU9aS5nZXRWYWx1ZShmKzIqcywiKiIpLGg9TnVtYmVyKGkuZ2V0VmFsdWUoZiszKnMsbykpLHc9W107Zm9yKGxldCBlPTA7ZTxoO2UrKyl3LnB1c2goTnVtYmVyKGkuZ2V0VmFsdWUodStlKnMsbykpKTswIT09aS5fT3J0RnJlZSh1KSYmUygiQ2FuJ3QgZnJlZSBtZW1vcnkgZm9yIHRlbnNvciBkaW1zLiIpO2xldCB5PXcucmVkdWNlKCgoZSx0KT0+ZSp0KSwxKTthPVF0KGwpO2xldCBtPXA/Lm91dHB1dFByZWZlcnJlZExvY2F0aW9uc1tuW3RdXTtpZigic3RyaW5nIj09PWEpe2lmKCJncHUtYnVmZmVyIj09PW18fCJtbC10ZW5zb3IiPT09bSl0aHJvdyBuZXcgRXJyb3IoIlN0cmluZyB0ZW5zb3IgaXMgbm90IHN1cHBvcnRlZCBvbiBHUFUuIik7bGV0IGU9W107Zm9yKGxldCB0PTA7dDx5O3QrKyl7bGV0IHI9aS5nZXRWYWx1ZShjK3QqcywiKiIpLG49aS5nZXRWYWx1ZShjKyh0KzEpKnMsIioiKSxvPXQ9PT15LTE/dm9pZCAwOm4tcjtlLnB1c2goaS5VVEY4VG9TdHJpbmcocixvKSk7fUUucHVzaChbYSx3LGUsImNwdSJdKTt9ZWxzZSBpZigiZ3B1LWJ1ZmZlciI9PT1tJiZ5PjApe2xldCBlPWkuanNlcEdldEJ1ZmZlcjtpZighZSl0aHJvdyBuZXcgRXJyb3IoJ3ByZWZlcnJlZExvY2F0aW9uICJncHUtYnVmZmVyIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViR1BVLicpO2xldCB0PWUoYyksbj10ZShsLHkpO2lmKHZvaWQgMD09PW58fCFDZShhKSl0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGRhdGEgdHlwZTogJHthfWApO2Q9ITAsRS5wdXNoKFthLHcse2dwdUJ1ZmZlcjp0LGRvd25sb2FkOmkuanNlcENyZWF0ZURvd25sb2FkZXIodCxuLGEpLGRpc3Bvc2U6KCk9PnswIT09aS5fT3J0UmVsZWFzZVRlbnNvcihyKSYmUygiQ2FuJ3QgcmVsZWFzZSB0ZW5zb3IuIik7fX0sImdwdS1idWZmZXIiXSk7fWVsc2UgaWYoIm1sLXRlbnNvciI9PT1tJiZ5PjApe2xldCB0PWkuanNlcEVuc3VyZVRlbnNvcjtpZighdCl0aHJvdyBuZXcgRXJyb3IoJ3ByZWZlcnJlZExvY2F0aW9uICJtbC10ZW5zb3IiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJOTi4nKTtpZih2b2lkIDA9PT10ZShsLHkpfHwhVWUoYSkpdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7YX1gKTtsZXQgbj1hd2FpdCB0KGUsYyxsLHcsITEpO2Q9ITAsRS5wdXNoKFthLHcse21sVGVuc29yOm4sZG93bmxvYWQ6aS5qc2VwQ3JlYXRlTUxUZW5zb3JEb3dubG9hZGVyKGMsYSksZGlzcG9zZTooKT0+e2kuanNlcFJlbGVhc2VUZW5zb3JJZChjKSxpLl9PcnRSZWxlYXNlVGVuc29yKHIpO319LCJtbC10ZW5zb3IiXSk7fWVsc2Uge2xldCBlPW5ldyhlcihhKSkoeSk7bmV3IFVpbnQ4QXJyYXkoZS5idWZmZXIsZS5ieXRlT2Zmc2V0LGUuYnl0ZUxlbmd0aCkuc2V0KGkuSEVBUFU4LnN1YmFycmF5KGMsYytlLmJ5dGVMZW5ndGgpKSxFLnB1c2goW2EsdyxlLCJjcHUiXSk7fX1maW5hbGx5e2kuc3RhY2tSZXN0b3JlKGwpLCJzdHJpbmciPT09YSYmYyYmaS5fZnJlZShjKSxkfHxpLl9PcnRSZWxlYXNlVGVuc29yKHIpLGkuanNlcE9uUnVuRW5kPy4odSk7fX1yZXR1cm4gcCYmIWMmJigwIT09aS5fT3J0Q2xlYXJCb3VuZE91dHB1dHMocC5oYW5kbGUpJiZTKCJDYW4ndCBjbGVhciBib3VuZCBvdXRwdXRzLiIpLHJlLnNldChlLFt1LGYsZCxwLGMsITFdKSksRX1maW5hbGx5e2kuc3RhY2tSZXN0b3JlKEUpLGcuZm9yRWFjaCgoZT0+aS5fT3J0UmVsZWFzZVRlbnNvcihlKSkpLGIuZm9yRWFjaCgoZT0+aS5fT3J0UmVsZWFzZVRlbnNvcihlKSkpLHYuZm9yRWFjaCgoZT0+aS5fZnJlZShlKSkpLDAhPT15JiZpLl9PcnRSZWxlYXNlUnVuT3B0aW9ucyh5KSxtLmZvckVhY2goKGU9PmkuX2ZyZWUoZSkpKTt9fSxMZT1lPT57bGV0IHQ9eCgpLHI9cmUuZ2V0KGUpO2lmKCFyKXRocm93IG5ldyBFcnJvcigiaW52YWxpZCBzZXNzaW9uIGlkIik7bGV0IG49clswXSxvPXQuX09ydEVuZFByb2ZpbGluZyhuKTswPT09byYmUygiQ2FuJ3QgZ2V0IGFuIHByb2ZpbGUgZmlsZSBuYW1lLiIpLHQuX09ydEZyZWUobyk7fSxJZT1lPT57bGV0IHQ9W107Zm9yKGxldCByIG9mIGUpe2xldCBlPXJbMl07IUFycmF5LmlzQXJyYXkoZSkmJiJidWZmZXIiaW4gZSYmdC5wdXNoKGUuYnVmZmVyKTt9cmV0dXJuIHR9O30pKSxudD1UKCgoKT0+e3EoKSxKZSgpLEooKSxnZSgpLFo9KCk9PiEhQS53YXNtLnByb3h5JiZ0eXBlb2YgZG9jdW1lbnQ8InUiLGxlPSExLE1lPSExLERlPSExLHJ0PW5ldyBNYXAsbmU9KGUsdCk9PntsZXQgcj1ydC5nZXQoZSk7cj9yLnB1c2godCk6cnQuc2V0KGUsW3RdKTt9LG9lPSgpPT57aWYobGV8fCFNZXx8RGV8fCFEKXRocm93IG5ldyBFcnJvcigid29ya2VyIG5vdCByZWFkeSIpfSxOcj1lPT57c3dpdGNoKGUuZGF0YS50eXBlKXtjYXNlImluaXQtd2FzbSI6bGU9ITEsZS5kYXRhLmVycj8oRGU9ITAsdHRbMV0oZS5kYXRhLmVycikpOihNZT0hMCx0dFswXSgpKSxfZSYmKFVSTC5yZXZva2VPYmplY3RVUkwoX2UpLF9lPXZvaWQgMCk7YnJlYWs7Y2FzZSJpbml0LWVwIjpjYXNlImNvcHktZnJvbSI6Y2FzZSJjcmVhdGUiOmNhc2UicmVsZWFzZSI6Y2FzZSJydW4iOmNhc2UiZW5kLXByb2ZpbGluZyI6e2xldCB0PXJ0LmdldChlLmRhdGEudHlwZSk7ZS5kYXRhLmVycj90LnNoaWZ0KClbMV0oZS5kYXRhLmVycik6dC5zaGlmdCgpWzBdKGUuZGF0YS5vdXQpO2JyZWFrfX19LG9yPWFzeW5jKCk9PntpZighTWUpe2lmKGxlKXRocm93IG5ldyBFcnJvcigibXVsdGlwbGUgY2FsbHMgdG8gJ2luaXRXYXNtKCknIGRldGVjdGVkLiIpO2lmKERlKXRocm93IG5ldyBFcnJvcigicHJldmlvdXMgY2FsbCB0byAnaW5pdFdhc20oKScgZmFpbGVkLiIpO2lmKGxlPSEwLFooKSlyZXR1cm4gbmV3IFByb21pc2UoKChlLHQpPT57RD8udGVybWluYXRlKCksVnQoKS50aGVuKCgoW3Isbl0pPT57dHJ5eyhEPW4pLm9uZXJyb3I9ZT0+dChlKSxELm9ubWVzc2FnZT1Ocix0dD1bZSx0XTtsZXQgbz17dHlwZToiaW5pdC13YXNtIixpbjpBfTtpZighby5pbi53YXNtLndhc21QYXRocyYmcil7bGV0IGU9UGUoKTtlJiYoby5pbi53YXNtLndhc21QYXRocz1lKTt9RC5wb3N0TWVzc2FnZShvKSxfZT1yO31jYXRjaChlKXt0KGUpO319KSx0KTt9KSk7dHJ5e2F3YWl0IEVlKEEud2FzbSksYXdhaXQgVGUoQSksTWU9ITA7fWNhdGNoKGUpe3Rocm93IERlPSEwLGV9ZmluYWxseXtsZT0hMTt9fX0sc3I9YXN5bmMgZT0+e2lmKFooKSlyZXR1cm4gb2UoKSxuZXcgUHJvbWlzZSgoKHQscik9PntuZSgiaW5pdC1lcCIsW3Qscl0pO2xldCBuPXt0eXBlOiJpbml0LWVwIixpbjp7ZXBOYW1lOmUsZW52OkF9fTtELnBvc3RNZXNzYWdlKG4pO30pKTthd2FpdCBTZShBLGUpO30saXI9YXN5bmMgZT0+WigpPyhvZSgpLG5ldyBQcm9taXNlKCgodCxyKT0+e25lKCJjb3B5LWZyb20iLFt0LHJdKTtsZXQgbj17dHlwZToiY29weS1mcm9tIixpbjp7YnVmZmVyOmV9fTtELnBvc3RNZXNzYWdlKG4sW2UuYnVmZmVyXSk7fSkpKTp1ZShlKSxhcj1hc3luYyhlLHQpPT57aWYoWigpKXtpZih0Py5wcmVmZXJyZWRPdXRwdXRMb2NhdGlvbil0aHJvdyBuZXcgRXJyb3IoJ3Nlc3Npb24gb3B0aW9uICJwcmVmZXJyZWRPdXRwdXRMb2NhdGlvbiIgaXMgbm90IHN1cHBvcnRlZCBmb3IgcHJveHkuJyk7cmV0dXJuIG9lKCksbmV3IFByb21pc2UoKChyLG4pPT57bmUoImNyZWF0ZSIsW3Isbl0pO2xldCBvPXt0eXBlOiJjcmVhdGUiLGluOnttb2RlbDplLG9wdGlvbnM6ey4uLnR9fX0sYT1bXTtlIGluc3RhbmNlb2YgVWludDhBcnJheSYmYS5wdXNoKGUuYnVmZmVyKSxELnBvc3RNZXNzYWdlKG8sYSk7fSkpfXJldHVybiBBZShlLHQpfSx1cj1hc3luYyBlPT57aWYoWigpKXJldHVybiBvZSgpLG5ldyBQcm9taXNlKCgodCxyKT0+e25lKCJyZWxlYXNlIixbdCxyXSk7bGV0IG49e3R5cGU6InJlbGVhc2UiLGluOmV9O0QucG9zdE1lc3NhZ2Uobik7fSkpO09lKGUpO30sZnI9YXN5bmMoZSx0LHIsbixvLGEpPT57aWYoWigpKXtpZihyLnNvbWUoKGU9PiJjcHUiIT09ZVszXSkpKXRocm93IG5ldyBFcnJvcigiaW5wdXQgdGVuc29yIG9uIEdQVSBpcyBub3Qgc3VwcG9ydGVkIGZvciBwcm94eS4iKTtpZihvLnNvbWUoKGU9PmUpKSl0aHJvdyBuZXcgRXJyb3IoInByZS1hbGxvY2F0ZWQgb3V0cHV0IHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkIGZvciBwcm94eS4iKTtyZXR1cm4gb2UoKSxuZXcgUHJvbWlzZSgoKG8saSk9PntuZSgicnVuIixbbyxpXSk7bGV0IHM9cixsPXt0eXBlOiJydW4iLGluOntzZXNzaW9uSWQ6ZSxpbnB1dEluZGljZXM6dCxpbnB1dHM6cyxvdXRwdXRJbmRpY2VzOm4sb3B0aW9uczphfX07RC5wb3N0TWVzc2FnZShsLEllKHMpKTt9KSl9cmV0dXJuIHhlKGUsdCxyLG4sbyxhKX0sY3I9YXN5bmMgZT0+e2lmKFooKSlyZXR1cm4gb2UoKSxuZXcgUHJvbWlzZSgoKHQscik9PntuZSgiZW5kLXByb2ZpbGluZyIsW3Qscl0pO2xldCBuPXt0eXBlOiJlbmQtcHJvZmlsaW5nIixpbjplfTtELnBvc3RNZXNzYWdlKG4pO30pKTtMZShlKTt9O30pKSxkcj1UKCgoKT0+e3EoKSxudCgpLFFlKCksYmUoKSxldCgpLGxyPShlLHQpPT57c3dpdGNoKGUubG9jYXRpb24pe2Nhc2UiY3B1IjpyZXR1cm4gW2UudHlwZSxlLmRpbXMsZS5kYXRhLCJjcHUiXTtjYXNlImdwdS1idWZmZXIiOnJldHVybiBbZS50eXBlLGUuZGltcyx7Z3B1QnVmZmVyOmUuZ3B1QnVmZmVyfSwiZ3B1LWJ1ZmZlciJdO2Nhc2UibWwtdGVuc29yIjpyZXR1cm4gW2UudHlwZSxlLmRpbXMse21sVGVuc29yOmUubWxUZW5zb3J9LCJtbC10ZW5zb3IiXTtkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgaW52YWxpZCBkYXRhIGxvY2F0aW9uOiAke2UubG9jYXRpb259IGZvciAke3QoKX1gKX19LFdyPWU9Pntzd2l0Y2goZVszXSl7Y2FzZSJjcHUiOnJldHVybiBuZXcgUihlWzBdLGVbMl0sZVsxXSk7Y2FzZSJncHUtYnVmZmVyIjp7bGV0IHQ9ZVswXTtpZighQ2UodCkpdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIGRhdGEgdHlwZTogJHt0fSBmb3IgZGVzZXJpYWxpemluZyBHUFUgdGVuc29yYCk7bGV0e2dwdUJ1ZmZlcjpyLGRvd25sb2FkOm4sZGlzcG9zZTpvfT1lWzJdO3JldHVybiBSLmZyb21HcHVCdWZmZXIocix7ZGF0YVR5cGU6dCxkaW1zOmVbMV0sZG93bmxvYWQ6bixkaXNwb3NlOm99KX1jYXNlIm1sLXRlbnNvciI6e2xldCB0PWVbMF07aWYoIVVlKHQpKXRocm93IG5ldyBFcnJvcihgbm90IHN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7dH0gZm9yIGRlc2VyaWFsaXppbmcgTUxUZW5zb3IgdGVuc29yYCk7bGV0e21sVGVuc29yOnIsZG93bmxvYWQ6bixkaXNwb3NlOm99PWVbMl07cmV0dXJuIFIuZnJvbU1MVGVuc29yKHIse2RhdGFUeXBlOnQsZGltczplWzFdLGRvd25sb2FkOm4sZGlzcG9zZTpvfSl9ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgZGF0YSBsb2NhdGlvbjogJHtlWzNdfWApfX0sUmU9Y2xhc3N7YXN5bmMgZmV0Y2hNb2RlbEFuZENvcHlUb1dhc21NZW1vcnkoZSl7cmV0dXJuIGlyKGF3YWl0IGNlKGUpKX1hc3luYyBsb2FkTW9kZWwoZSx0KXtsZXQgcjtWKCkscj0ic3RyaW5nIj09dHlwZW9mIGU/YXdhaXQgdGhpcy5mZXRjaE1vZGVsQW5kQ29weVRvV2FzbU1lbW9yeShlKTplLFt0aGlzLnNlc3Npb25JZCx0aGlzLmlucHV0TmFtZXMsdGhpcy5vdXRwdXROYW1lc109YXdhaXQgYXIocix0KSxZKCk7fWFzeW5jIGRpc3Bvc2UoKXtyZXR1cm4gdXIodGhpcy5zZXNzaW9uSWQpfWFzeW5jIHJ1bihlLHQscil7VigpO2xldCBuPVtdLG89W107T2JqZWN0LmVudHJpZXMoZSkuZm9yRWFjaCgoZT0+e2xldCB0PWVbMF0scj1lWzFdLGE9dGhpcy5pbnB1dE5hbWVzLmluZGV4T2YodCk7aWYoLTE9PT1hKXRocm93IG5ldyBFcnJvcihgaW52YWxpZCBpbnB1dCAnJHt0fSdgKTtuLnB1c2gociksby5wdXNoKGEpO30pKTtsZXQgYT1bXSxpPVtdO09iamVjdC5lbnRyaWVzKHQpLmZvckVhY2goKGU9PntsZXQgdD1lWzBdLHI9ZVsxXSxuPXRoaXMub3V0cHV0TmFtZXMuaW5kZXhPZih0KTtpZigtMT09PW4pdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIG91dHB1dCAnJHt0fSdgKTthLnB1c2gociksaS5wdXNoKG4pO30pKTtsZXQgcz1uLm1hcCgoKGUsdCk9PmxyKGUsKCgpPT5gaW5wdXQgIiR7dGhpcy5pbnB1dE5hbWVzW29bdF1dfSJgKSkpKSxsPWEubWFwKCgoZSx0KT0+ZT9scihlLCgoKT0+YG91dHB1dCAiJHt0aGlzLm91dHB1dE5hbWVzW2lbdF1dfSJgKSk6bnVsbCkpLHU9YXdhaXQgZnIodGhpcy5zZXNzaW9uSWQsbyxzLGksbCxyKSxmPXt9O2ZvcihsZXQgZT0wO2U8dS5sZW5ndGg7ZSsrKWZbdGhpcy5vdXRwdXROYW1lc1tpW2VdXV09YVtlXT8/V3IodVtlXSk7cmV0dXJuIFkoKSxmfXN0YXJ0UHJvZmlsaW5nKCl7fWVuZFByb2ZpbGluZygpe2NyKHRoaXMuc2Vzc2lvbklkKTt9fTt9KSksbXI9e307R2UobXIse09ubnhydW50aW1lV2ViQXNzZW1ibHlCYWNrZW5kOigpPT5GZSxpbml0aWFsaXplRmxhZ3M6KCk9PnByLHdhc21CYWNrZW5kOigpPT4kcn0pO3ZhciBwcixGZSwkcixocj1UKCgoKT0+e3EoKSxudCgpLGRyKCkscHI9KCk9PntpZigoIm51bWJlciIhPXR5cGVvZiBBLndhc20uaW5pdFRpbWVvdXR8fEEud2FzbS5pbml0VGltZW91dDwwKSYmKEEud2FzbS5pbml0VGltZW91dD0wKSwhMT09PUEud2FzbS5zaW1kJiZjb25zb2xlLndhcm4oJ0RlcHJlY2F0ZWQgcHJvcGVydHkgImVudi53YXNtLnNpbWQiIGlzIHNldCB0byBmYWxzZS4gbm9uLVNJTUQgYnVpbGQgaXMgbm8gbG9uZ2VyIHByb3ZpZGVkLCBhbmQgdGhpcyBzZXR0aW5nIHdpbGwgYmUgaWdub3JlZC4nKSwiYm9vbGVhbiIhPXR5cGVvZiBBLndhc20ucHJveHkmJihBLndhc20ucHJveHk9ITEpLCJib29sZWFuIiE9dHlwZW9mIEEud2FzbS50cmFjZSYmKEEud2FzbS50cmFjZT0hMSksIm51bWJlciIhPXR5cGVvZiBBLndhc20ubnVtVGhyZWFkc3x8IU51bWJlci5pc0ludGVnZXIoQS53YXNtLm51bVRocmVhZHMpfHxBLndhc20ubnVtVGhyZWFkczw9MClpZih0eXBlb2Ygc2VsZjwidSImJiFzZWxmLmNyb3NzT3JpZ2luSXNvbGF0ZWQpQS53YXNtLm51bVRocmVhZHM9MTtlbHNlIHtsZXQgZT10eXBlb2YgbmF2aWdhdG9yPiJ1Ij8kZSgibm9kZTpvcyIpLmNwdXMoKS5sZW5ndGg6bmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3k7QS53YXNtLm51bVRocmVhZHM9TWF0aC5taW4oNCxNYXRoLmNlaWwoKGV8fDEpLzIpKTt9fSwkcj1uZXcoRmU9Y2xhc3N7YXN5bmMgaW5pdChlKXtwcigpLGF3YWl0IG9yKCksYXdhaXQgc3IoZSk7fWFzeW5jIGNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKGUsdCl7bGV0IHI9bmV3IFJlO3JldHVybiBhd2FpdCByLmxvYWRNb2RlbChlLHQpLFByb21pc2UucmVzb2x2ZShyKX19KTt9KSk7cSgpLHEoKSxxKCk7dmFyIEZ0PSIxLjIxLjAiO3tsZXQgZT0oaHIoKSxhdChtcikpLndhc21CYWNrZW5kO2llKCJjcHUiLGUsMTApLGllKCJ3YXNtIixlLDEwKTt9T2JqZWN0LmRlZmluZVByb3BlcnR5KEEudmVyc2lvbnMsIndlYiIse3ZhbHVlOkZ0LGVudW1lcmFibGU6ITB9KTsKCmNsYXNzIFdvcmtlck5hdGl2ZXtjb25zdHJ1Y3Rvcigpe3RoaXMucmVhZHk9ITE7dGhpcy5pbmRleGVkREJNYW5hZ2VyPW5ldyBJbmRleGVkREJNYW5hZ2VyKCJvbmlyaXgtc2RrIiwiZmlsZXMiKSx0aGlzLmluZGV4ZWREQk1hbmFnZXIuZ2V0RmlsZUZyb21JbmRleGVkREIoIlNES18xLjExLjAiKS50aGVuKChhc3luYyBlPT57bGV0IHQ9VVJMLmNyZWF0ZU9iamVjdFVSTChuZXcgQmxvYihbZV0se3R5cGU6InRleHQvamF2YXNjcmlwdCJ9KSk7Y29uc3R7ZGVmYXVsdDphfT1hd2FpdCBpbXBvcnQoLyogd2VicGFja0lnbm9yZTogdHJ1ZSwgd2VicGFja01vZGU6ICJsYXp5IiAqL3QpLHM9YXdhaXQgYSgpO3RoaXMubmF0aXZlU0RLPXMsdGhpcy5zcGF0aWFsQnVmZmVyU2l6ZT10aGlzLm5hdGl2ZVNESy5fT1hfR2V0QnVmZmVyU2l6ZSgpLHRoaXMuZnJvbUJ1ZmZlcj10aGlzLm5hdGl2ZVNESy5fbWFsbG9jKDQqdGhpcy5zcGF0aWFsQnVmZmVyU2l6ZSksdGhpcy50b0J1ZmZlcj10aGlzLm5hdGl2ZVNESy5fbWFsbG9jKDQqdGhpcy5zcGF0aWFsQnVmZmVyU2l6ZSksQS53YXNtLm51bVRocmVhZHM9MTtjb25zdCByPWF3YWl0IHRoaXMuaW5kZXhlZERCTWFuYWdlci5nZXRGaWxlRnJvbUluZGV4ZWREQigib3J0Lndhc20iKSxpPVVSTC5jcmVhdGVPYmplY3RVUkwobmV3IEJsb2IoW3JdLHt0eXBlOiJhcHBsaWNhdGlvbi93YXNtIn0pKTtBLndhc20ud2FzbVBhdGhzPXt3YXNtOmksbWpzOiJodHRwczovL2Nkbi5vbmlyaXguY29tL29uaXJpeC1lbmdpbmUtc2RrL29ydF92MS4yMS4wX21pbi9vcnQtd2FzbS1zaW1kLm1qcyJ9O2xldCBuPWF3YWl0IHRoaXMuaW5kZXhlZERCTWFuYWdlci5nZXRGcm9tQ2FjaGVPckZldGNoKCJzcGFyc2VfbWF0Y2hpbmcub3J0IiwiaHR0cHM6Ly9jZG4ub25pcml4LmNvbS9vbmlyaXgtZW5naW5lLXNkay9zcGFyc2VfbWF0Y2hpbmcub3J0Iik7Y29uc3Qgbz1hd2FpdCBPci5jcmVhdGUobix7ZXhlY3V0aW9uUHJvdmlkZXJzOlsid2FzbSJdfSk7dGhpcy5zZXNzaW9uTWF0Y2hpbmc9byxhd2FpdCB0aGlzLnNlc3Npb25NYXRjaGluZy5ydW4oe2ZlYXRzMDpuZXcgUihuZXcgRmxvYXQzMkFycmF5KEFycmF5KDY0ZTMpLmZpbGwoMCkpLFsxZTMsNjRdKSxmZWF0czE6bmV3IFIobmV3IEZsb2F0MzJBcnJheShBcnJheSg2NGUzKS5maWxsKDApKSxbMWUzLDY0XSl9KSx0aGlzLnJlYWR5PSEwLHBvc3RNZXNzYWdlKCJyZWFkeSIpO30pKTt9c3RhcnQoKXthZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwoYXN5bmMgZT0+e2lmKCF0aGlzLnJlYWR5KXJldHVybjtjb25zdCB0PWUuZGF0YSxhPXQuZnJvbSxzPXQudG87bGV0IHI7aWYoMj09dC5kdHlwZSl7bGV0IGU9dGhpcy5yZWFkRGVzY3JpcHRvcnMoYSksdD10aGlzLnJlYWREZXNjcmlwdG9ycyhzKSxpPWF3YWl0IHRoaXMuc2Vzc2lvbk1hdGNoaW5nLnJ1bih7ZmVhdHMwOmUsZmVhdHMxOnR9KSx7aWR4MDpuLGlkeDE6b309aSxoPVtuLmRpbXNbMF1dO2ZvcihsZXQgZT0wO2U8bi5kaW1zWzBdO2UrKyloLnB1c2goTnVtYmVyKG4uZGF0YVtlXSkpLGgucHVzaChOdW1iZXIoby5kYXRhW2VdKSk7cj1uZXcgRmxvYXQzMkFycmF5KGgpO31lbHNlIHt0aGlzLm5hdGl2ZVNESy5IRUFQRjMyLnNldChhLHRoaXMuZnJvbUJ1ZmZlci80KSx0aGlzLm5hdGl2ZVNESy5IRUFQRjMyLnNldChzLHRoaXMudG9CdWZmZXIvNCk7bGV0IGU9dGhpcy5uYXRpdmVTREsuX09YX01hdGNoKHRoaXMuZnJvbUJ1ZmZlcix0aGlzLnRvQnVmZmVyLHQuZHR5cGUpO3I9bmV3IEZsb2F0MzJBcnJheSh0aGlzLnJlYWRNYXRjaGluZ0RhdGEodGhpcy5uYXRpdmVTREsuSEVBUEYzMixlLzQpKTt9cG9zdE1lc3NhZ2Uocik7fSkpO31yZWFkRGVzY3JpcHRvcnMoZSl7bGV0IHQ9ZVswXSxhPTErMip0O3JldHVybiBuZXcgUihuZXcgRmxvYXQzMkFycmF5KGUuc2xpY2UoYSxhKzY0KnQpKSxbdCw2NF0pfXJlYWRNYXRjaGluZ0RhdGEoZSx0KXtsZXQgYT10LHM9W10scj1lW2FdO3MucHVzaChyKSxhKys7Zm9yKGxldCB0PTA7dDxyO3QrKylzLnB1c2goZVthXSkscy5wdXNoKGVbYSsxXSksYSs9MjtyZXR1cm4gc319Y29uc3Qgd29ya2VyPW5ldyBXb3JrZXJOYXRpdmU7d29ya2VyLnN0YXJ0KCk7Cg=="),b=new Blob([d],{type:"application/javascript"});this.workers[Z]=new Worker(/* webpackIgnore: true, webpackMode: "lazy" */URL.createObjectURL(b),{type:"module"}),this.callbacks[Z]=l,this.workers[Z].addEventListener("message",(l=>{this.callbacks[Z](l.data);}));}}replaceCallback(Z,l){this.workerExists(Z)&&(this.callbacks[Z]=l);}sendDataToWorker(Z,l){this.workers[Z].postMessage(l);}async createWorkers(){return await this.indexedDBManager.getFromCacheOrFetch("ort.wasm","https://cdn.onirix.com/onirix-engine-sdk/ort_v1.21.0_min/ort-wasm-simd.wasm"),Promise.all([new Promise(((Z,l)=>{this.createExtractionWorker("extraction",(l=>{"ready"===l&&Z();}));})),new Promise(((Z,l)=>{this.createMatchingWorker("matching",(l=>{"ready"===l&&Z();}));}))])}}
|
52
52
|
|
53
|
-
class WebXRManager{constructor(t,e,i,a){this.uiManager=t,this.nativeManager=e,this.deviceManager=i,this.workerManager=a,this.hitTestTimeout=void 0,this.hotSwap=!1,this.continuousLocalizationEnabled=!1,this.initialCalibrationPose=null,this.isCalibrated=!0,this.startedOnce=!1;}async isWebXRSupported(){let t=!1;return navigator.xr&&(t=await navigator.xr.isSessionSupported("immersive-ar")),t}async init(t,e,i,a){this.onPose=e,this.onSessionEnd=i,this.isCalibrated=!a;const r=async()=>{const e=["hit-test"],i=["dom-overlay"];t&&i.push("camera-access");try{const t=await new Promise((async(t,a)=>{let r,s=!1;this.requestStallTime&&this.requestStallTime>0&&(r=window.setTimeout((()=>{s=!0,a(new TimeoutError);}),this.requestStallTime));try{const a=await navigator.xr.requestSession("immersive-ar",{requiredFeatures:e,optionalFeatures:i,domOverlay:{root:document.body}});s?await a.end():(window.clearTimeout(r),t(a));}catch(t){window.clearTimeout(r),a(t);}}));await this.onXRSessionStarted(t),this.hitTestStallTime&&this.hitTestStallTime>0&&(this.hitTestTimeout=window.setTimeout((async()=>{this.onHitTestStall&&this.onHitTestStall();}),this.hitTestStallTime));}catch(t){throw console.log(t),new SensorsError(`error while initializing webXR API: ${t}`)}};window.navigator.userAgent.includes("OnirixPlayer")?await r():await this.uiManager.displayPermissionsDialog(r);}startImageDetection(){this.usingImageDetection=!0,this.detectingImage=!0;}stopImageDetection(){this.detectingImage=!1;}start(){this.started=!0,this.usingSpatial&&(this.relocating=!1,this.nativeManager.setWebXRRelocationListener(this.onXRRelocation.bind(this)),this.workerManager.replaceCallback("extraction",(t=>{if(!1!==t)if(this.nativeManager.coarseLocationCheck(t)){let e=this.nativeManager.loadExtractionData(t);this.candidates=Array.from(Array(e).keys()).reverse(),this.extractionData=t.extraction,this.matchKeyframes();}else this.relocating=!1;else this.relocating=!1;})),this.workerManager.replaceCallback("matching",(t=>{this.nativeManager.loadMatch(t),this.matchKeyframes();})));}stop(){this.started=!1,this.xrTransform=null,this.lastRelocationTry=null;}setStartedFlag(){this.startedOnce=!0;}hasStartedOnce(){return this.startedOnce}matchKeyframes(){if(this.candidates.length>0)if(this.nativeManager.spatialLocalize())this.relocating=!1;else {let t=this.candidates.pop();this.workerManager.sendDataToWorker("matching",new WorkerMatchingData(t,this.extractionData,this.nativeManager.getCandidateData(t),this.nativeManager.extractionType()));}else this.nativeManager.spatialLocalize(),this.relocating=!1;}async destroy(){this.xrSession&&(await this.xrSession.end(),this.xrSession=null,this.xrLastPose=null);}async onXRSessionStarted(t){let e=this.uiManager.renderCanvas.getContext("webgl2");e||(e=this.uiManager.renderCanvas.getContext("webgl")),e.getContextAttributes().xrCompatible||await e.makeXRCompatible(),this.xrContext=e,this.framebuffer=this.xrContext.createFramebuffer(),this.xrLayer=new XRWebGLLayer(t,this.xrContext),this.usingSpatial?(navigator.userAgent.includes("OnirixPlayer")||(this.glBinding=new XRWebGLBinding(t,this.xrContext)),this.nativeManager.initExtractionBuffers()):this.detectingImage&&(navigator.userAgent.includes("OnirixPlayer")||(this.glBinding=new XRWebGLBinding(t,this.xrContext))),t.updateRenderState({baseLayer:this.xrLayer}),this.xrLocalRefSpace=await t.requestReferenceSpace("local"),this.xrViewerRefSpace=await t.requestReferenceSpace("viewer"),this.xrHitTestSource=await t.requestHitTestSource({space:this.xrViewerRefSpace}),t.requestAnimationFrame(this.onXRFrame.bind(this)),window.navigator.userAgent.includes("WebXRViewer")?(this.uiManager.renderCanvas.addEventListener("click",(t=>{this.onTouch&&this.onTouch(this.getNormalizedTouchCoords(t));})),this.uiManager.renderCanvas.addEventListener("touchstart",(t=>{this.onTouchStart&&this.onTouchStart(this.getNormalizedTouchCoords(t));})),this.uiManager.renderCanvas.addEventListener("touchend",(t=>{this.onTouchEnd&&this.onTouchEnd(this.getNormalizedTouchCoords(t));}))):(t.addEventListener("select",(t=>{this.onTouch&&this.onTouch(this.getXRInputCoords(t));})),t.addEventListener("selectstart",(t=>{this.onTouchStart&&this.onTouchStart(this.getXRInputCoords(t));})),t.addEventListener("selectend",(t=>{this.onTouchEnd&&this.onTouchEnd(this.getXRInputCoords(t));}))),this.uiManager.renderCanvas.addEventListener("touchmove",(t=>{this.onTouchMove&&this.onTouchMove(this.getNormalizedTouchCoords(t));})),t.addEventListener("end",(()=>{this.hotSwap||this.onSessionEnd&&this.onSessionEnd();})),this.xrSession=t;}enableHotSwap(){this.hotSwap=!0;}disableHotSwap(){this.hotSwap=!1;}hasRelocatedOrDetected(){return (this.usingSpatial||this.usingImageDetection)&&null!=this.xrTransform}needsSmoothing(){return null!=this.xrTransform&&null!=this.prevXrTransform}needsSpatialRelocation(){return this.usingSpatial&&(null==this.lastRelocationTry||this.msSinceRelocation()>2e3)&&(!this.hasRelocatedOrDetected()||this.continuousLocalizationEnabled)}needsImageDetection(){return this.detectingImage&&(null==this.lastRelocationTry||this.msSinceRelocation()>200)}startRelocationTimer(){this.lastRelocationTry=new Date;}msSinceRelocation(){let t=new Date;return this.lastRelocationTry?t-this.lastRelocationTry:0}msSinceOkRelocation(){let t=new Date;return this.lastRelocationTry?t-this.xrTransitionTimer:0}resizeTexture(t,e,i,a,r,s){const n=t.createFramebuffer();t.bindFramebuffer(t.FRAMEBUFFER,n),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,e,0);const o=t.createTexture();t.bindTexture(t.TEXTURE_2D,o),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,r,s,0,t.RGBA,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR);const h=t.createFramebuffer();return t.bindFramebuffer(t.FRAMEBUFFER,h),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,o,0),t.bindFramebuffer(t.READ_FRAMEBUFFER,n),t.bindFramebuffer(t.DRAW_FRAMEBUFFER,h),t.blitFramebuffer(0,0,i,a,0,0,r,s,t.COLOR_BUFFER_BIT,t.LINEAR),o}getCameraIntrinsics(t,e){const i=t,a=e.width,r=e.height;if(this.uiManager.isPortrait()){return [r/2*i[5]*Math.min(480/r,640/a),320,240]}return [r/2*i[5]*Math.min(640/r,480/a),320,240]}offsetByXRTransform(t,e){return e?(new Matrix4).fromArray(e.elements).multiply(t):(new Matrix4).fromArray(this.xrTransform.elements).multiply(t)}onXRRelocation(t){if(this.lastCameraImagePose){let e=(new Matrix4).fromArray(this.lastCameraImagePose),i=(new Matrix4).fromArray(t.elements);this.xrTransitionTimer=new Date,null!=this.xrTransform&&(this.prevXrTransform=this.xrTransform.clone()),this.xrTransform=i.multiply(e.invert());}}onXRFrame(t,e){const i=e.session;if(i.requestAnimationFrame(this.onXRFrame.bind(this)),!this.started)return;const a=e.getViewerPose(this.xrLocalRefSpace);if(!a)return;const r=this.xrContext;this.isCalibrated&&(this.needsSpatialRelocation()&&!this.relocating||this.needsImageDetection())&&(this.relocating=!0,(async()=>{const t=this.getGLState(r),{cameraWidth:i,cameraHeight:s,cameraTexture:n,cameraPose:o}=await this.fetchCameraImage(e,a,r);if(!n)return;this.lastCameraImagePose=o;const{scaledWidth:h,scaledHeight:c}=this.calculateScale(i,s),l=this.resizeTexture(r,n,i,s,h,c);this.cameraData||(this.cameraData=new Uint8ClampedArray(h*c*4)),r.bindTexture(r.TEXTURE_2D,l),r.bindFramebuffer(r.FRAMEBUFFER,this.framebuffer),r.framebufferTexture2D(r.FRAMEBUFFER,r.COLOR_ATTACHMENT0,r.TEXTURE_2D,l,0),r.readPixels(0,0,h,c,r.RGBA,r.UNSIGNED_BYTE,this.cameraData),this.restoreGLState(r,t);const{flip:d,rotate:u}=this.getOrientationFlags();if(this.usingSpatial&&this.workerManager.sendDataToWorker("extraction",new WorkerExtractionData(this.cameraData,h,c,u,d,this.nativeManager.extractionType())),this.detectingImage){let t=this.nativeManager.getXRFrameBuffer(h,c);this.nativeManager.processFrame(this.cameraData,t,c,h,d,u);}this.startRelocationTimer();})()),r.bindFramebuffer(r.FRAMEBUFFER,i.renderState.baseLayer.framebuffer);const s=a.views[0];let n=(new Matrix4).fromArray(s.transform.matrix);if(this.shouldCorrectJump(n)?(n=this.correctJump(n),this.isCalibrated||this.resetCalibration()):this.lastPose=n,this.checkTrackingCalibration(n),this.hasRelocatedOrDetected())if(this.needsSmoothing()){let t=this.lastInterpolatedTransform??this.prevXrTransform,e=this.xrTransform;this.lastInterpolatedTransform=t.interpolatePose(e,.1),n=this.offsetByXRTransform(n,this.lastInterpolatedTransform);}else n=this.offsetByXRTransform(n);if((!this.usingSpatial&&!this.usingImageDetection||this.hasRelocatedOrDetected())&&this.onPose(n.toArray()),this.handleViewportResize(a),this.onHitTestResult){const t=e.getHitTestResults(this.xrHitTestSource);if(t.length>0){this.hitTestTimeout&&(window.clearInterval(this.hitTestTimeout),this.hitTestTimeout=void 0);const e=t[0].getPose(this.xrLocalRefSpace),i=(new Matrix4).fromArray(e.transform.matrix),a=i.extractPosition(),r=((new Quaternion).setFromRotationMatrix(i),n.extractPosition()),s=Math.atan2(r.x-a.x,r.z-a.z),o={position:a,rotation:(new Quaternion).setFromEuler(new Euler(0,s,0))};this.onHitTestResult(o);}}this.onFrame&&this.onFrame(e);}async fetchCameraImage(t,e,i){let a,r,s,n;if(navigator.userAgent.includes("OnirixPlayer")){const o=await t.getCameraImage();a=o.width,r=o.height,n=o.pose??e.views[0].transform.matrix,s=await this.createTextureFromImage(i,o),await this.updateIntrinsicsIfNeeded(o);}else for(const t of e.views)t.camera&&(a=t.camera.width,r=t.camera.height,s=this.glBinding.getCameraImage(t.camera),n=e.views[0].transform.matrix);return {cameraWidth:a,cameraHeight:r,cameraTexture:s,cameraPose:n}}async updateIntrinsicsIfNeeded(t){const[e,i,a]=this.nativeManager.getIntrinsics();Math.abs(e-t.focalLength)>1&&this.nativeManager.setIntrinsics(t.focalLength,320,240);}handleViewportResize(t){const e=this.xrLayer.getViewport(t.views[0]),i=e.width,a=e.height,r=null==this.xrLastPose||this.lastViewportWidth!=i||this.lastViewportHeight!=a;this.xrLastPose=t,this.lastViewportWidth=i,this.lastViewportHeight=a,r&&this.onResize&&this.onResize();}calculateScale(t,e){let i,a;this.uiManager.isPortrait()?(i=640/e,a=480/t):(i=480/e,a=640/t);const r=Math.max(i,a);return {scaledWidth:t*r,scaledHeight:e*r}}async createTextureFromImage(t,e){const i=new Image;await new Promise((t=>{i.src=`data:image/jpeg;base64,${e.data}`,i.onload=t;}));const a=t.createTexture();return t.bindTexture(t.TEXTURE_2D,a),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,i),a}getOrientationFlags(){return this.uiManager.isPortrait()?{flip:1,rotate:3}:{flip:2,rotate:0}}shouldCorrectJump(t){return this.deviceManager.os===DeviceManager.OS.Android&&this.started&&this.lastPose&&!this.jumpPose&&this.hasLargeRotationChange(t)}hasLargeRotationChange(t){return 2*Math.acos(Math.abs((new Quaternion).setFromRotationMatrix(t).dot((new Quaternion).setFromRotationMatrix(this.lastPose))))>1}correctJump(t){this.jumpPose||(this.jumpPose=t.clone());const e=this.jumpPose.clone().invert().multiply(t);return this.lastPose.clone().multiply(e)}getGLState(t){return {readFramebuffer:t.getParameter(t.READ_FRAMEBUFFER_BINDING),drawFramebuffer:t.getParameter(t.DRAW_FRAMEBUFFER_BINDING),texture:t.getParameter(t.TEXTURE_BINDING_2D)}}restoreGLState(t,e){t.bindFramebuffer(t.READ_FRAMEBUFFER,e.readFramebuffer),t.bindFramebuffer(t.DRAW_FRAMEBUFFER,e.drawFramebuffer),t.bindTexture(t.TEXTURE_2D,e.texture);}checkTrackingCalibration(t){if(this.isCalibrated)return;if(!this.initialCalibrationPose)return void(this.initialCalibrationPose=t.clone());const e=t.extractPosition(),i=this.initialCalibrationPose.extractPosition();e.distanceTo(i)>TrackingCalibrationTranslationThreshold&&(this.isCalibrated=!0,this.onTrackingCalibrated&&this.onTrackingCalibrated());}fitCanvasToXRViewport(){if(this.xrLastPose){const t=this.xrLastPose.views[0],e=this.xrLayer.getViewport(t);if((e.width>e.height&&window.innerWidth>window.innerHeight||e.width<=e.height&&window.innerWidth<=window.innerHeight)&&e.width*e.height>window.innerWidth*window.innerHeight)this.uiManager.renderCanvas.width=e.width,this.uiManager.renderCanvas.height=e.height;else {this.uiManager.renderCanvas.width=window.innerWidth;const t=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--sat"),10)||0,e=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--sab"),10)||0,i=window.innerHeight+t+e;this.uiManager.renderCanvas.height=i;}}}getCameraParameters(){let t=60,e=9/16;if(this.xrSession&&this.xrLastPose){const i=this.xrLastPose.views[0].projectionMatrix;e=this.uiManager.renderCanvas.width/this.uiManager.renderCanvas.height,t=radToDeg(2*Math.atan(1/i[5]));}return {fov:t,aspect:e}}getXRLayer(){return this.xrLayer}getXRInputCoords(t){const e=t.inputSource.gamepad.axes;return new Vector2(e[0],-e[1])}getNormalizedTouchCoords(t){const e=new Vector2,i=this.uiManager.renderCanvas.getBoundingClientRect();return null!=t.clientX?(e.x=(t.clientX-i.left)/i.width*2-1,e.y=-(t.clientY-i.top)/i.height*2+1):t.touches[0]?(e.x=t.touches[0].clientX/window.innerWidth*2-1,e.y=-t.touches[0].clientY/window.innerHeight*2+1):(e.x=t.changedTouches[0].clientX/window.innerWidth*2-1,e.y=-t.changedTouches[0].clientY/window.innerHeight*2+1),e}setResizeListener(t){this.onResize=t;}setTouchListener(t){this.onTouch=t;}setTouchStartListener(t){this.onTouchStart=t;}setTouchMoveListener(t){this.onTouchMove=t;}setTouchEndListener(t){this.onTouchEnd=t;}setSessionEndListener(t){this.onSessionEnd=t;}setHitTestListener(t){this.onHitTestResult=t;}setFrameListener(t){this.onFrame=t;}setHitTestStallListener(t){this.onHitTestStall=t;}setRequestStallTimeout(t){this.requestStallTime=t;}setHitTestStallTimeout(t){this.hitTestStallTime=t;}setTrackingCalibratedListener(t){this.onTrackingCalibrated=t;}resetCalibration(){this.initialCalibrationPose=null,this.isCalibrated=!1;}}
|
53
|
+
class WebXRManager{constructor(t,e,i,a){this.uiManager=t,this.nativeManager=e,this.deviceManager=i,this.workerManager=a,this.hitTestTimeout=void 0,this.hotSwap=!1,this.continuousLocalizationEnabled=!1,this.initialCalibrationPose=null,this.isCalibrated=!0,this.startedOnce=!1,this.cameraTexture=null;}async isWebXRSupported(){let t=!1;return navigator.xr&&(t=await navigator.xr.isSessionSupported("immersive-ar")),t}async init(t,e,i,a){this.onPose=e,this.onSessionEnd=i,this.isCalibrated=!a;const r=async()=>{const e=["hit-test"],i=["dom-overlay"];t&&i.push("camera-access");try{const t=await new Promise((async(t,a)=>{let r,s=!1;this.requestStallTime&&this.requestStallTime>0&&(r=window.setTimeout((()=>{s=!0,a(new TimeoutError);}),this.requestStallTime));try{const a=await navigator.xr.requestSession("immersive-ar",{requiredFeatures:e,optionalFeatures:i,domOverlay:{root:document.body}});s?await a.end():(window.clearTimeout(r),t(a));}catch(t){window.clearTimeout(r),a(t);}}));await this.onXRSessionStarted(t),this.hitTestStallTime&&this.hitTestStallTime>0&&(this.hitTestTimeout=window.setTimeout((async()=>{this.onHitTestStall&&this.onHitTestStall();}),this.hitTestStallTime));}catch(t){throw console.log(t),new SensorsError(`error while initializing webXR API: ${t}`)}};window.navigator.userAgent.includes("OnirixPlayer")?await r():await this.uiManager.displayPermissionsDialog(r);}startImageDetection(){this.usingImageDetection=!0,this.detectingImage=!0;}stopImageDetection(){this.detectingImage=!1;}start(){this.started=!0,this.usingSpatial&&(this.relocating=!1,this.nativeManager.setWebXRRelocationListener(this.onXRRelocation.bind(this)),this.workerManager.replaceCallback("extraction",(t=>{if(!1!==t)if(this.nativeManager.coarseLocationCheck(t)){let e=this.nativeManager.loadExtractionData(t);this.candidates=Array.from(Array(e).keys()).reverse(),this.extractionData=t.extraction,this.matchKeyframes();}else this.relocating=!1;else this.relocating=!1;})),this.workerManager.replaceCallback("matching",(t=>{this.nativeManager.loadMatch(t),this.matchKeyframes();})));}stop(){this.started=!1,this.xrTransform=null,this.lastRelocationTry=null;}setStartedFlag(){this.startedOnce=!0;}hasStartedOnce(){return this.startedOnce}matchKeyframes(){if(this.candidates.length>0)if(this.nativeManager.spatialLocalize(this.lastXrPose))this.relocating=!1;else {let t=this.candidates.pop();this.workerManager.sendDataToWorker("matching",new WorkerMatchingData(t,this.extractionData,this.nativeManager.getCandidateData(t),this.nativeManager.extractionType()));}else this.nativeManager.spatialLocalize(this.lastXrPose),this.relocating=!1;}async destroy(){this.xrSession&&(await this.xrSession.end(),this.xrSession=null,this.xrLastPose=null);}async onXRSessionStarted(t){let e=this.uiManager.renderCanvas.getContext("webgl2");e||(e=this.uiManager.renderCanvas.getContext("webgl")),e.getContextAttributes().xrCompatible||await e.makeXRCompatible(),this.xrContext=e,this.framebuffer=this.xrContext.createFramebuffer(),this.xrLayer=new XRWebGLLayer(t,this.xrContext),this.usingSpatial?(navigator.userAgent.includes("OnirixPlayer")||(this.glBinding=new XRWebGLBinding(t,this.xrContext)),this.nativeManager.initExtractionBuffers()):this.detectingImage&&(navigator.userAgent.includes("OnirixPlayer")||(this.glBinding=new XRWebGLBinding(t,this.xrContext))),t.updateRenderState({baseLayer:this.xrLayer}),this.xrLocalRefSpace=await t.requestReferenceSpace("local"),this.xrViewerRefSpace=await t.requestReferenceSpace("viewer"),this.xrHitTestSource=await t.requestHitTestSource({space:this.xrViewerRefSpace}),t.requestAnimationFrame(this.onXRFrame.bind(this)),window.navigator.userAgent.includes("WebXRViewer")?(this.uiManager.renderCanvas.addEventListener("click",(t=>{this.onTouch&&this.onTouch(this.getNormalizedTouchCoords(t));})),this.uiManager.renderCanvas.addEventListener("touchstart",(t=>{this.onTouchStart&&this.onTouchStart(this.getNormalizedTouchCoords(t));})),this.uiManager.renderCanvas.addEventListener("touchend",(t=>{this.onTouchEnd&&this.onTouchEnd(this.getNormalizedTouchCoords(t));}))):(t.addEventListener("select",(t=>{this.onTouch&&this.onTouch(this.getXRInputCoords(t));})),t.addEventListener("selectstart",(t=>{this.onTouchStart&&this.onTouchStart(this.getXRInputCoords(t));})),t.addEventListener("selectend",(t=>{this.onTouchEnd&&this.onTouchEnd(this.getXRInputCoords(t));}))),this.uiManager.renderCanvas.addEventListener("touchmove",(t=>{this.onTouchMove&&this.onTouchMove(this.getNormalizedTouchCoords(t));})),t.addEventListener("end",(()=>{this.hotSwap||this.onSessionEnd&&this.onSessionEnd();})),this.xrSession=t;}enableHotSwap(){this.hotSwap=!0;}disableHotSwap(){this.hotSwap=!1;}hasRelocatedOrDetected(){return (this.usingSpatial||this.usingImageDetection)&&null!=this.xrTransform}needsSmoothing(){return null!=this.xrTransform&&null!=this.prevXrTransform}needsSpatialRelocation(){return this.usingSpatial&&(null==this.lastRelocationTry||this.msSinceRelocation()>2e3)&&(!this.hasRelocatedOrDetected()||this.continuousLocalizationEnabled)}needsImageDetection(){return this.detectingImage&&(null==this.lastRelocationTry||this.msSinceRelocation()>200)}startRelocationTimer(){this.lastRelocationTry=new Date;}msSinceRelocation(){let t=new Date;return this.lastRelocationTry?t-this.lastRelocationTry:0}msSinceOkRelocation(){let t=new Date;return this.lastRelocationTry?t-this.xrTransitionTimer:0}resizeTexture(t,e,i,a,r,s){const n=t.createFramebuffer();t.bindFramebuffer(t.FRAMEBUFFER,n),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,e,0);const o=t.createTexture();t.bindTexture(t.TEXTURE_2D,o),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,r,s,0,t.RGBA,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR);const h=t.createFramebuffer();return t.bindFramebuffer(t.FRAMEBUFFER,h),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,o,0),t.bindFramebuffer(t.READ_FRAMEBUFFER,n),t.bindFramebuffer(t.DRAW_FRAMEBUFFER,h),t.blitFramebuffer(0,0,i,a,0,0,r,s,t.COLOR_BUFFER_BIT,t.LINEAR),o}getCameraIntrinsics(t,e){const i=t,a=e.width,r=e.height;if(this.uiManager.isPortrait()){return [r/2*i[5]*Math.min(480/r,640/a),320,240]}return [r/2*i[5]*Math.min(640/r,480/a),320,240]}offsetByXRTransform(t,e){return e?(new Matrix4).fromArray(e.elements).multiply(t):(new Matrix4).fromArray(this.xrTransform.elements).multiply(t)}onXRRelocation(t){if(this.lastCameraImagePose){let e=(new Matrix4).fromArray(this.lastCameraImagePose),i=(new Matrix4).fromArray(t.elements);this.xrTransitionTimer=new Date,null!=this.xrTransform&&(this.prevXrTransform=this.xrTransform.clone()),this.xrTransform=i.multiply(e.invert());}}onXRFrame(t,e){const i=e.session;if(i.requestAnimationFrame(this.onXRFrame.bind(this)),!this.started)return;const a=e.getViewerPose(this.xrLocalRefSpace);if(!a)return;const r=this.xrContext;this.isCalibrated&&(this.needsSpatialRelocation()&&!this.relocating||this.needsImageDetection())&&(this.relocating=!0,(async()=>{const t=this.getGLState(r),{cameraWidth:i,cameraHeight:s,cameraPose:n}=await this.fetchCameraImage(e,a,r);if(!this.cameraTexture)return;this.lastCameraImagePose=n;const{scaledWidth:o,scaledHeight:h}=this.calculateScale(i,s),c=this.resizeTexture(r,this.cameraTexture,i,s,o,h);this.cameraData||(this.cameraData=new Uint8ClampedArray(o*h*4)),r.bindTexture(r.TEXTURE_2D,c),r.bindFramebuffer(r.FRAMEBUFFER,this.framebuffer),r.framebufferTexture2D(r.FRAMEBUFFER,r.COLOR_ATTACHMENT0,r.TEXTURE_2D,c,0),r.readPixels(0,0,o,h,r.RGBA,r.UNSIGNED_BYTE,this.cameraData),r.deleteTexture(c),this.restoreGLState(r,t);const{flip:l,rotate:u}=this.getOrientationFlags();if(this.usingSpatial&&this.workerManager.sendDataToWorker("extraction",new WorkerExtractionData(this.cameraData,o,h,u,l,this.nativeManager.extractionType())),this.detectingImage){let t=this.nativeManager.getXRFrameBuffer(o,h);this.nativeManager.processFrame(this.cameraData,t,h,o,l,u);}this.startRelocationTimer();})()),r.bindFramebuffer(r.FRAMEBUFFER,i.renderState.baseLayer.framebuffer);const s=a.views[0];let n=(new Matrix4).fromArray(s.transform.matrix);if(this.shouldCorrectJump(n)?(n=this.correctJump(n),this.isCalibrated||this.resetCalibration()):this.lastPose=n,this.lastXrPose=n,this.checkTrackingCalibration(n),this.hasRelocatedOrDetected())if(this.needsSmoothing()){let t=this.lastInterpolatedTransform??this.prevXrTransform,e=this.xrTransform;this.lastInterpolatedTransform=t.interpolatePose(e,.1),n=this.offsetByXRTransform(n,this.lastInterpolatedTransform);}else n=this.offsetByXRTransform(n);if((!this.usingSpatial&&!this.usingImageDetection||this.hasRelocatedOrDetected())&&this.onPose(n.toArray()),this.handleViewportResize(a),this.onHitTestResult){const t=e.getHitTestResults(this.xrHitTestSource);if(t.length>0){this.hitTestTimeout&&(window.clearInterval(this.hitTestTimeout),this.hitTestTimeout=void 0);const e=t[0].getPose(this.xrLocalRefSpace),i=(new Matrix4).fromArray(e.transform.matrix),a=i.extractPosition(),r=((new Quaternion).setFromRotationMatrix(i),n.extractPosition()),s=Math.atan2(r.x-a.x,r.z-a.z),o={position:a,rotation:(new Quaternion).setFromEuler(new Euler(0,s,0))};this.onHitTestResult(o);}}this.onFrame&&this.onFrame(e);}async fetchCameraImage(t,e,i){let a,r,s;if(navigator.userAgent.includes("OnirixPlayer")){const n=await t.getCameraImage();a=n.width,r=n.height,s=n.pose??e.views[0].transform.matrix,await this.setCameraTextureFromImage(i,n),await this.updateIntrinsicsIfNeeded(n);}else for(const t of e.views)t.camera&&(a=t.camera.width,r=t.camera.height,this.cameraTexture=this.glBinding.getCameraImage(t.camera),s=e.views[0].transform.matrix);return {cameraWidth:a,cameraHeight:r,cameraPose:s}}async updateIntrinsicsIfNeeded(t){const[e,i,a]=this.nativeManager.getIntrinsics();Math.abs(e-t.focalLength)>1&&this.nativeManager.setIntrinsics(t.focalLength,320,240);}handleViewportResize(t){const e=this.xrLayer.getViewport(t.views[0]),i=e.width,a=e.height,r=null==this.xrLastPose||this.lastViewportWidth!=i||this.lastViewportHeight!=a;this.xrLastPose=t,this.lastViewportWidth=i,this.lastViewportHeight=a,r&&this.onResize&&this.onResize();}calculateScale(t,e){let i,a;this.uiManager.isPortrait()?(i=640/e,a=480/t):(i=480/e,a=640/t);const r=Math.max(i,a);return {scaledWidth:t*r,scaledHeight:e*r}}async setCameraTextureFromImage(t,e){const i=new Image;await new Promise((t=>{i.src=`data:image/jpeg;base64,${e.data}`,i.onload=t;})),this.cameraTexture||(this.cameraTexture=t.createTexture()),t.bindTexture(t.TEXTURE_2D,this.cameraTexture),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,i);}getOrientationFlags(){return this.uiManager.isPortrait()?{flip:1,rotate:3}:{flip:2,rotate:0}}shouldCorrectJump(t){return this.deviceManager.os===DeviceManager.OS.Android&&this.started&&this.lastPose&&!this.jumpPose&&this.hasLargeRotationChange(t)}hasLargeRotationChange(t){return 2*Math.acos(Math.abs((new Quaternion).setFromRotationMatrix(t).dot((new Quaternion).setFromRotationMatrix(this.lastPose))))>1}correctJump(t){this.jumpPose||(this.jumpPose=t.clone());const e=this.jumpPose.clone().invert().multiply(t);return this.lastPose.clone().multiply(e)}getGLState(t){return {readFramebuffer:t.getParameter(t.READ_FRAMEBUFFER_BINDING),drawFramebuffer:t.getParameter(t.DRAW_FRAMEBUFFER_BINDING),texture:t.getParameter(t.TEXTURE_BINDING_2D)}}restoreGLState(t,e){t.bindFramebuffer(t.READ_FRAMEBUFFER,e.readFramebuffer),t.bindFramebuffer(t.DRAW_FRAMEBUFFER,e.drawFramebuffer),t.bindTexture(t.TEXTURE_2D,e.texture);}checkTrackingCalibration(t){if(this.isCalibrated)return;if(!this.initialCalibrationPose)return void(this.initialCalibrationPose=t.clone());const e=t.extractPosition(),i=this.initialCalibrationPose.extractPosition();e.distanceTo(i)>TrackingCalibrationTranslationThreshold&&(this.isCalibrated=!0,this.onTrackingCalibrated&&this.onTrackingCalibrated());}fitCanvasToXRViewport(){if(this.xrLastPose){const t=this.xrLastPose.views[0],e=this.xrLayer.getViewport(t);if((e.width>e.height&&window.innerWidth>window.innerHeight||e.width<=e.height&&window.innerWidth<=window.innerHeight)&&e.width*e.height>window.innerWidth*window.innerHeight)this.uiManager.renderCanvas.width=e.width,this.uiManager.renderCanvas.height=e.height;else {this.uiManager.renderCanvas.width=window.innerWidth;const t=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--sat"),10)||0,e=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--sab"),10)||0,i=window.innerHeight+t+e;this.uiManager.renderCanvas.height=i;}}}getCameraParameters(){let t=60,e=9/16;if(this.xrSession&&this.xrLastPose){const i=this.xrLastPose.views[0].projectionMatrix;e=this.uiManager.renderCanvas.width/this.uiManager.renderCanvas.height,t=radToDeg(2*Math.atan(1/i[5]));}return {fov:t,aspect:e}}getXRLayer(){return this.xrLayer}getXRInputCoords(t){const e=t.inputSource.gamepad.axes;return new Vector2(e[0],-e[1])}getNormalizedTouchCoords(t){const e=new Vector2,i=this.uiManager.renderCanvas.getBoundingClientRect();return null!=t.clientX?(e.x=(t.clientX-i.left)/i.width*2-1,e.y=-(t.clientY-i.top)/i.height*2+1):t.touches[0]?(e.x=t.touches[0].clientX/window.innerWidth*2-1,e.y=-t.touches[0].clientY/window.innerHeight*2+1):(e.x=t.changedTouches[0].clientX/window.innerWidth*2-1,e.y=-t.changedTouches[0].clientY/window.innerHeight*2+1),e}setResizeListener(t){this.onResize=t;}setTouchListener(t){this.onTouch=t;}setTouchStartListener(t){this.onTouchStart=t;}setTouchMoveListener(t){this.onTouchMove=t;}setTouchEndListener(t){this.onTouchEnd=t;}setSessionEndListener(t){this.onSessionEnd=t;}setHitTestListener(t){this.onHitTestResult=t;}setFrameListener(t){this.onFrame=t;}setHitTestStallListener(t){this.onHitTestStall=t;}setRequestStallTimeout(t){this.requestStallTime=t;}setHitTestStallTimeout(t){this.hitTestStallTime=t;}setTrackingCalibratedListener(t){this.onTrackingCalibrated=t;}resetCalibration(){this.initialCalibrationPose=null,this.isCalibrated=!1;}}
|
54
54
|
|
55
55
|
class EventManager{constructor(){this.eventListeners={},this.eventListenerCount=0;}stop(){this.eventListeners={},this.eventListenerCount=0;}addEventListener(e,t){this.eventListeners[e]||(this.eventListeners[e]=[]);const n=this.eventListenerCount++;return this.eventListeners[e].push({id:n,func:t}),n}triggerEvent(e,t){this.eventListeners[e]&&this.eventListeners[e].map((e=>e.func(t)));}removeEventListener(e){for(let t of Object.keys(this.eventListeners))for(let n=0;n<t.length;n++)if(t[n].id===e){t.splice(n,1);break}}}
|
56
56
|
|