/**
 * Minified by jsDelivr using Terser v5.39.0.
 * Original file: /npm/@zeainc/zea-engine@4.17.0/dist/index.esm.mjs
 *
 * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
 */
var version="4.17.0";class LibsRegistry{registry;version;constructor(A){this.version=A,this.registry={}}registerLib(A){const g=A.name,I=A.version;this.registry[g]&&console.warn("Library already registered:"+g),this.registry[g]=I,console.log(`Registered lib '${g}' v${I}`)}listLibs(){return this.registry}}function isIOSDevice(){return!!/iPad|iPhone|iPod/.test(navigator.platform)||navigator.maxTouchPoints&&navigator.maxTouchPoints>2&&/MacIntel/.test(navigator.platform)}function isMobileDevice(){return navigator.maxTouchPoints&&navigator.maxTouchPoints>0&&/Android|iPhone|iPad|iPod/i.test(navigator.userAgent)}function getBrowserDesc(){const A=navigator.userAgent;let g,I,C,e="",i=""+parseFloat(navigator.appVersion);return navigator.brave?(e="Brave",I=A.indexOf("Chrome"),i=A.substring(I+7,A.indexOf(" ",I+7))):-1!=(I=A.indexOf("Opera"))?(e="Opera",i=A.substring(I+6),-1!=(I=A.indexOf("Version"))&&(i=A.substring(I+8))):-1!=(I=A.indexOf("MSIE"))?(e="Microsoft Internet Explorer",i=A.substring(I+5)):-1!=(I=A.indexOf("Edge"))?(e="Edge",i=A.substring(I+4)):-1!=(I=A.indexOf("Chrome"))?(e="Chrome",i=A.substring(I+7,A.indexOf(" ",I+7))):-1!=(I=A.indexOf("Safari"))?(e="Safari",i=A.substring(I+7),-1!=(I=A.indexOf("Version"))&&(i=A.substring(I+8))):-1!=(I=A.indexOf("Firefox"))?(e="Firefox",i=A.substring(I+8)):(g=A.lastIndexOf(" ")+1)<(I=A.lastIndexOf("/"))&&(e=A.substring(g,I),i=A.substring(I+1)),-1!=(C=i.indexOf(";"))&&(i=i.substring(0,C)),-1!=(C=i.indexOf(" "))&&(i=i.substring(0,C)),{browserName:e,fullVersion:i}}function getGPUDesc(){let A,g;try{A=document.createElement("canvas").getContext("webgl")}catch(A){}if(!A)return{vendor:"Unknown",renderer:"Unknown",gpuVendor:"Unknown",maxTextureSize:0,supportsWebGL:!1,supportsWebGL2:!1};try{g=document.createElement("canvas").getContext("webgl2")}catch(A){}const I=A.getExtension("WEBGL_debug_renderer_info");if(!I)return console.warn("Unable to determine GPU Info:"),{vendor:"Unknown",renderer:"Unknown",gpuVendor:"Unknown",maxTextureSize:0,supportsWebGL:null!=A,supportsWebGL2:null!=g};const C=A.getParameter(I.UNMASKED_VENDOR_WEBGL),e=A.getParameter(I.UNMASKED_RENDERER_WEBGL),i=A.getParameter(A.MAX_TEXTURE_SIZE);let t;return e.match(/NVIDIA/i)?t="NVidia":e.match(/AMD/i)||e.match(/Radeon/i)?t="AMD":e.match(/Intel/i)?t="Intel":e.match(/Mali/i)?t="ARM":e.match(/Apple/i)?t="Apple":e.match(/Adreno/i)?t="Adreno":e.match(/Swiftshader/i)?(t="Google",console.warn("Hardware rendering is disabled or not working on your system. Falling back to the Swiftshader. Expect poor performance:",e)):console.warn("Unable to determine GPU vendor:",e),{vendor:C,renderer:e,gpuVendor:t,maxTextureSize:i,supportsWebGL:!0,supportsWebGL2:null!=g}}const getOS=()=>{const{userAgent:A}=window.navigator;let g=null;return/macintosh/i.test(A)?g="macOS":/ios/i.test(A)?g="iOS":/win/i.test(A)?g="Windows":/android/i.test(A)?g="Android":/linux/i.test(A)&&(g="Linux"),g},SystemDesc=function(){if(!globalThis.navigator||/node/i.test(globalThis.navigator.userAgent))return{OS:"Node",isMobileDevice:!1,isIOSDevice:!1,browserName:"Node",webGLSupported:!1,deviceCategory:"High",hardwareConcurrency:4};const A=isMobileDevice(),g=getBrowserDesc(),I=getGPUDesc();let C="Low";if(I.supportsWebGL)if(A)C="Low";else{const A=I.renderer.replace(/[()]/g,"").split(" ");if("NVidia"==I.gpuVendor){const g=A.indexOf("GTX");if(-1!=g){const I=A[g+1];if(I.endsWith("M")){C=parseInt(I.substring(0,I.length-2))>=900?"Medium":"Low"}else{C=parseInt(I)>=1030?"High":"Medium"}}else C=A.includes("RTX")||A.includes("TITAN")||A.includes("Quadro")?"High":"Low"}else if("AMD"==I.gpuVendor){const g=A.indexOf("Radeon");if(-1!=g){const I=A.indexOf("RX");if(-1!=I)if("Vega"==A[I+1])C="High";else{const g=A[I+1];let e;g.endsWith("X")?(e=parseInt(g.substring(0,g.length-2)),C="High"):e=parseInt(g),C=e>=480?"High":"Medium"}else if("Pro"==A[g+1]){C=parseInt(A[I+1])>=450?"Medium":"Low"}else if("Sky"==A[g+1]){C=parseInt(A[I+1])>=700?"Medium":"Low"}else C="Low"}else C=A.includes("FirePro")||A.includes("Quadro")?"High":"Low"}else("Adreno"==I.gpuVendor||"Intel"==I.gpuVendor||"Google"==I.gpuVendor)&&(C="Low")}let e=globalThis.navigator.hardwareConcurrency;return e||(e=A?4:6),{OS:getOS(),isMobileDevice:A,isIOSDevice:isIOSDevice(),browserName:g.browserName,fullVersion:g.fullVersion,webGLSupported:I.supportsWebGL,gpuDesc:I,deviceCategory:C,hardwareConcurrency:e}}();globalThis.ZeaSystemDesc||(globalThis.ZeaSystemDesc=SystemDesc);let registeredClasses={},classNames={},classDefinitions=[];class Registry{static register(A,g){if(A in registeredClasses)return void console.warn(`There's a class registered with '${A}' name. Second registration failed.`);const I=classDefinitions.length;classDefinitions.push(g),classNames[I]=A,registeredClasses[A]=I}static getClassDefinition(A){if(!(A in registeredClasses))throw new Error(`${A} class is not registered`);return classDefinitions[registeredClasses[A]]}static getClassName(A){const g=classDefinitions.indexOf(A);if(g>=0&&classNames[g])return classNames[g];throw new Error("class is not registered")}static constructClass(A){const g=classDefinitions[registeredClasses[A]];if(!g)throw new Error(`${A} class is not registered`);return new g}static flush(){registeredClasses={},classNames={},classDefinitions=[]}}class StringFunctions{static replaceAll(A,g,I){return A.replace(new RegExp(g,"g"),I)}static stringifyJSONWithFixedPrecision(A,g=0,I=5){return JSON.stringify(A,((A,g)=>g&&g.toFixed?Number(g.toFixed(I)):g),g)}static hashStr(A){let g,I,C,e=0;if(0===A.length)return e;for(g=0,C=A.length;g<C;g++)I=A.charCodeAt(g),e=(e<<5)-e+I,e|=0;return Math.abs(e)}}class Vec2{x;y;constructor(A=0,g=0){this.x=A,this.y=g}set(A,g){this.x=A,this.y=g}setFromOther(A){this.x=A.x,this.y=A.y}isEqual(A){return this.x==A.x&&this.y==A.y}notEqual(A){return this.x!=A.x&&this.y!=A.y}approxEqual(A,g=Number.EPSILON){return Math.abs(this.x-A.x)<g&&Math.abs(this.y-A.y)<g}add(A){return new Vec2(this.x+A.x,this.y+A.y)}addInPlace(A){this.x+=A.x,this.y+=A.y}subtract(A){return new Vec2(this.x-A.x,this.y-A.y)}subtractInPlace(A){return this.x-=A.x,this.y-=A.y,this}scale(A){return new Vec2(this.x*A,this.y*A)}scaleInPlace(A){this.x*=A,this.y*=A}invert(){return new Vec2(1/this.x,1/this.y)}invertInPlace(){return this.x=1/this.x,this.y=1/this.y,this}multiply(A){return new Vec2(this.x*A.x,this.y*A.y)}multiplyInPlace(A){this.x*=A.x,this.y*=A.y}lengthSquared(){const A=this.x,g=this.y;return A*A+g*g}length(){return Math.sqrt(this.lengthSquared())}distanceTo(A){const g=this.x-A.x,I=this.y-A.y;return Math.sqrt(g*g+I*I)}normalize(){const A=this.x,g=this.y;let I=A*A+g*g;return I<Number.EPSILON?new Vec2:(I=1/Math.sqrt(I),new Vec2(A*I,g*I))}normalizeInPlace(){const A=this.x,g=this.y;let I=A*A+g*g;I<Number.EPSILON||(I=1/Math.sqrt(I),this.set(A*I,g*I))}dot(A){return this.x*A.x+this.y*A.y}cross(A){return this.x*A.y-this.y*A.x}angleTo(A){const g=this.normalize().dot(A.normalize());return g>1?0:g<-1?Math.PI:Math.acos(g)}signedAngleTo(A){const g=this.angleTo(A);return this.cross(A)<0?-g:g}rotate(A){const g=Math.cos(A),I=Math.sin(A);return new Vec2(this.x*g-this.y*I,this.x*I+this.y*g)}lerp(A,g){const I=this.x,C=this.y;return new Vec2(I+g*(A.x-I),C+g*(A.y-C))}setRandomDir(A=1){const g=2*Math.random()*Math.PI;return this.x=Math.cos(g)*A,this.y=Math.sin(g)*A,this}setRandom(A=1){return this.x=Math.random()*A,this.y=Math.random()*A,this}clone(){return new Vec2(this.x,this.y)}asArray(){return[this.x,this.y]}fromArray(A){this.x=A[0],this.y=A[1]}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}toJSON(){return{x:this.x,y:this.y}}fromJSON(A){this.x=A.x,this.y=A.y}readBinary(A){this.x=A.loadFloat32(),this.y=A.loadFloat32()}static intersectionOfLines(A,g,I,C){const e=(A.x-g.x)*(I.y-C.y)-(A.y-g.y)*(I.x-C.x);if(0==e)return null;const i=A.x*g.y-A.y*g.x,t=I.x*C.y-I.y*C.x,o=I.x-C.x,a=A.x-g.x,B=I.y-C.y,s=A.y-g.y;return new Vec2((i*o-a*t)/e,(i*B-s*t)/e)}isValid(){for(const A of this.asArray())if(A==1/0||isNaN(A))return!1;return!0}}class Vec3{x;y;z;constructor(A=0,g=0,I=0){this.x=A,this.y=g,this.z=I}get xy(){return new Vec2(this.x,this.y)}get yz(){return new Vec2(this.y,this.z)}set(A,g,I){this.x=A,this.y=void 0!==g?g:A,this.z=void 0!==I?I:A}setFromOther(A){this.x=A.x,this.y=A.y,this.z=A.z}isNull(){return Math.abs(this.x)<Number.EPSILON&&Math.abs(this.y)<Number.EPSILON&&Math.abs(this.z)<Number.EPSILON}is111(){return Math.abs(1-this.x)<Number.EPSILON&&Math.abs(1-this.y)<Number.EPSILON&&Math.abs(1-this.z)<Number.EPSILON}isEqual(A){return this.x==A.x&&this.y==A.y&&this.z==A.z}notEqual(A){return this.x!=A.x&&this.y!=A.y&&this.z!=A.z}approxEqual(A,g=Number.EPSILON){return Math.abs(this.x-A.x)<g&&Math.abs(this.y-A.y)<g&&Math.abs(this.z-A.z)<g}add(A){return new Vec3(this.x+A.x,this.y+A.y,this.z+A.z)}addInPlace(A){this.x+=A.x,this.y+=A.y,this.z+=A.z}subtract(A){return new Vec3(this.x-A.x,this.y-A.y,this.z-A.z)}subtractInPlace(A){this.x-=A.x,this.y-=A.y,this.z-=A.z}multiply(A){return new Vec3(this.x*A.x,this.y*A.y,this.z*A.z)}multiplyInPlace(A){this.x*=A.x,this.y*=A.y,this.z*=A.z}divide(A){return new Vec3(this.x/A.x,this.y/A.y,this.z/A.z)}divideInPlace(A){this.x/=A.x,this.y/=A.y,this.z/=A.z}scale(A){return new Vec3(this.x*A,this.y*A,this.z*A)}scaleInPlace(A){this.x*=A,this.y*=A,this.z*=A}negate(){return new Vec3(-this.x,-this.y,-this.z)}inverse(){return new Vec3(1/this.x,1/this.y,1/this.z)}lengthSquared(){const A=this.x,g=this.y,I=this.z;return A*A+g*g+I*I}length(){return Math.sqrt(this.lengthSquared())}distanceTo(A){const g=this.x-A.x,I=this.y-A.y,C=this.z-A.z;return Math.sqrt(g*g+I*I+C*C)}normalize(){let A=this.x*this.x+this.y*this.y+this.z*this.z;return A<Number.EPSILON?new Vec3:(A=1/Math.sqrt(A),new Vec3(this.x*A,this.y*A,this.z*A))}normalizeInPlace(){let A=this.x*this.x+this.y*this.y+this.z*this.z;if(A<Number.EPSILON)return;A=Math.sqrt(A);const g=1/A;return this.x*=g,this.y*=g,this.z*=g,A}resize(A){const g=this.x*this.x+this.y*this.y+this.z*this.z;if(g<Number.EPSILON)return;const I=A/Math.sqrt(g);return new Vec3(this.x*I,this.y*I,this.z*I)}resizeInPlace(A){const g=this.x*this.x+this.y*this.y+this.z*this.z;if(g<Number.EPSILON)return;const I=A/Math.sqrt(g);this.x*=I,this.y*=I,this.z*=I}dot(A){return this.x*A.x+this.y*A.y+this.z*A.z}cross(A){const g=this.x,I=this.y,C=this.z,e=A.x,i=A.y,t=A.z;return new Vec3(I*t-C*i,C*e-g*t,g*i-I*e)}angleTo(A){const g=this.dot(A);return g>1?0:Math.acos(g)}lerp(A,g){const I=this.x,C=this.y,e=this.z;return new Vec3(I+g*(A.x-I),C+g*(A.y-C),e+g*(A.z-e))}abs(){return new Vec3(Math.abs(this.x),Math.abs(this.y),Math.abs(this.z))}setRandomDir(A=1){const g=2*Math.random()*Math.PI,I=2*Math.random()-1,C=Math.sqrt(1-I*I)*A;return this.x=Math.cos(g)*C,this.y=Math.sin(g)*C,this.z=I*A,this}setRandom(A=1){return this.x=(Math.random()-.5)*A,this.y=(Math.random()-.5)*A,this.z=(Math.random()-.5)*A,this}clone(){return new Vec3(this.x,this.y,this.z)}asArray(){return[this.x,this.y,this.z]}fromArray(A){this.x=A[0],this.y=A[1],this.z=A[1]}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}toJSON(){return{x:this.x,y:this.y,z:this.z}}fromJSON(A){this.x=A.x,this.y=A.y,this.z=A.z}readBinary(A){this.x=A.loadFloat32(),this.y=A.loadFloat32(),this.z=A.loadFloat32()}isValid(){for(const A of this.asArray())if(A==1/0||isNaN(A))return!1;return!0}}class Vec4{x;y;z;w;constructor(A=0,g=0,I=0,C=0){this.x=A,this.y=g,this.z=I,this.w=C}get xyz(){return new Vec3(this.x,this.y,this.z)}set(A,g,I,C){this.x=A,this.y=g,this.z=I,this.w=C}setFromOther(A){this.x=A.x,this.y=A.y,this.z=A.z,this.w=A.w}isEqual(A){return this.x==A.x&&this.y==A.y&&this.z==A.z&&this.w==A.w}notEqual(A){return this.x!=A.x&&this.y!=A.y&&this.z!=A.z&&this.w!=A.w}approxEqual(A,g=Number.EPSILON){return Math.abs(this.x-A.x)<g&&Math.abs(this.y-A.y)<g&&Math.abs(this.z-A.z)<g&&Math.abs(this.w-A.w)<g}add(A){return new Vec4(this.x+A.x,this.y+A.y,this.z+A.z,this.w+A.w)}addInPlace(A){this.x+=A.x,this.y+=A.y,this.z+=A.z,this.w+=A.w}subtract(A){return new Vec4(this.x-A.x,this.y-A.y,this.z-A.z,this.w-A.w)}subtractInPlace(A){this.x-=A.x,this.y-=A.y,this.z-=A.z,this.w-=A.w}multiply(A){return new Vec4(this.x*A.x,this.y*A.y,this.z*A.z,this.w*A.w)}multiplyInPlace(A){this.x*=A.x,this.y*=A.y,this.z*=A.z,this.w*=A.w}divide(A){return new Vec4(this.x/A.x,this.y/A.y,this.z/A.z,this.w/A.w)}divideInPlace(A){this.x/=A.x,this.y/=A.y,this.z/=A.z,this.w/=A.w}scale(A){return new Vec4(this.x*A,this.y*A,this.z*A,this.w*A)}scaleInPlace(A){this.set(this.x*A,this.y*A,this.z*A,this.w*A)}length(){const A=this.x,g=this.y,I=this.z,C=this.w;return Math.sqrt(A*A+g*g+I*I+C*C)}lengthSquared(){const A=this.x,g=this.y,I=this.z,C=this.w;return A*A+g*g+I*I+C*C}normalize(){const A=this.x,g=this.y,I=this.z,C=this.w;let e=A*A+g*g+I*I+C*C;return e<Number.EPSILON?new Vec4:(e=1/Math.sqrt(e),new Vec4(A*e,g*e,I*e))}normalizeInPlace(){const A=this.x,g=this.y,I=this.z,C=this.w;let e=A*A+g*g+I*I+C*C;e<Number.EPSILON||(e=1/Math.sqrt(e),this.set(A*e,g*e,I*e,C*e))}dot(A){return this.x*A.x+this.y*A.y+this.z*A.z+this.w*A.w}cross(A){const g=this.x,I=this.y,C=this.z,e=this.w,i=A.x,t=A.y,o=A.z,a=A.w;return new Vec4(I*o-C*t,C*a-e*o,e*i-g*a,g*t-I*i)}angleTo(A){const g=this.normalize(),I=A.normalize(),C=g.dot(I);return C>1?0:Math.acos(C)}lerp(A,g){const I=this.x,C=this.y,e=this.z,i=this.w;return new Vec4(I+g*(A.x-I),C+g*(A.y-C),e+g*(A.z-e),i+g*(A.w-i))}clone(){return new Vec4(this.x,this.y,this.z,this.w)}toVec3(){return new Vec3(this.x,this.y,this.z)}asArray(){return[this.x,this.y,this.z,this.w]}fromArray(A){this.x=A[0],this.y=A[1],this.z=A[1],this.w=A[1]}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}toJSON(){return{x:this.x,y:this.y,z:this.z,w:this.w}}fromJSON(A){this.x=A.x,this.y=A.y,this.z=A.z,this.w=A.w}readBinary(A){this.x=A.loadFloat32(),this.y=A.loadFloat32(),this.z=A.loadFloat32(),this.w=A.loadFloat32()}isValid(){for(const A of this.asArray())if(A==1/0||isNaN(A))return!1;return!0}}class RGBA{r=0;g=0;b=0;a=255;constructor(A=0,g=0,I=0,C=255){"string"==typeof A?A.startsWith("#")?this.setFromHex(A):this.setFromCSSColorName(A):(this.r=A,this.g=g,this.b=I,this.a=C)}set(A,g,I,C=255){this.r=A,this.g=g,this.b=I,this.a=C}setFromOther(A){this.r=A.r,this.g=A.g,this.b=A.b,this.a=A.a}setFromArray(A){this.r=A[0],this.g=A[1],this.b=A[2],this.a=4==A.length?A[3]:1}setFromHex(A){const g=function(A){const g=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(A);return g?{r:parseInt(g[1],16),g:parseInt(g[2],16),b:parseInt(g[3],16)}:null}(A);g?this.set(g.r,g.g,g.b):console.warn("Invalid hex code:"+A)}setFromCSSColorName(A){if(A.startsWith("#"))this.setFromHex(A);else{const g={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4","indianred ":"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgrey:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"}[A.toLowerCase()];g&&this.setFromHex(g)}}toHex(){function A(A){const g=A.toString(16);return 1==g.length?"0"+g:g}return"#"+A(this.r)+A(this.g)+A(this.b)}equal(A){return this.r==A.r&&this.g==A.g&&this.b==A.b&&this.a==A.a}notEquals(A){return this.r!=A.r&&this.g!=A.g&&this.b!=A.b&&this.a!=A.a}approxEqual(A,g=Number.EPSILON){return Math.abs(this.r-A.r)<g&&Math.abs(this.g-A.g)<g&&Math.abs(this.b-A.b)<g&&Math.abs(this.a-A.a)<g}add(A){return new RGBA(this.r+A.r,this.g+A.g,this.b+A.b,this.a+A.a)}subtract(A){return new RGBA(this.r-A.r,this.g-A.g,this.b-A.b,this.a-A.a)}scale(A){return new RGBA(this.r*A,this.g*A,this.b*A,this.a*A)}scaleInPlace(A){this.r*=A,this.g*=A,this.b*=A,this.a*=A}applyGamma(A){this.set(Math.pow(this.r,A),Math.pow(this.g,A),Math.pow(this.b,A),this.a)}toLinear(A=2.2){return new RGBA(Math.pow(this.r,A),Math.pow(this.g,A),Math.pow(this.b,A),this.a)}toGamma(A=2.2){return new RGBA(Math.pow(this.r,1/A),Math.pow(this.g,1/A),Math.pow(this.b,1/A),this.a)}luminance(){return.2126*this.r+.7152*this.g+.0722*this.b}lerp(A,g){const I=this.r,C=this.g,e=this.b,i=this.a;return new RGBA(I+g*(A.r-I),C+g*(A.g-C),e+g*(A.b-e),i+g*(A.a-i))}static random(A=0,g=!1){return A>0?new RGBA(A+Math.random()*(1-A),A+Math.random()*(1-A),A+Math.random()*(1-A),g?A+Math.random()*(1-A):1):A<0?new RGBA(Math.random()*(1+A),Math.random()*(1+A),Math.random()*(1+A),g?Math.random()*(1+A):1):new RGBA(Math.random(),Math.random(),Math.random(),g?Math.random():1)}clone(){return new RGBA(this.r,this.g,this.b,this.a)}asArray(){return[this.r,this.g,this.b,this.a]}toJSON(){return{r:this.r,g:this.g,b:this.b,a:this.a}}fromJSON(A){this.r=A.r,this.g=A.g,this.b=A.b,this.a=A.a}toCSSString(){return"rgba("+Math.round(255*this.r)+", "+Math.round(255*this.g)+", "+Math.round(255*this.b)+", "+this.a+")"}}let counter=0;class BaseClass{__id;constructor(){this.__id=++counter}getId(){return this.__id}getClassName(){return Registry.getClassName(Object.getPrototypeOf(this).constructor)}}class BaseEvent{constructor(){}}class EventEmitter extends BaseClass{listeners={};constructor(){super()}on(A,g){if(!g)throw new Error("Missing listener.");this.listeners[A]||(this.listeners[A]=[]);const I=this.listeners[A];if(I.includes(g))throw new Error(`Listener "${g.name}" already connected to event "${A}".`);const C=I.length;return I[C]=g,C}once(A,g){const I=C=>{this.off(A,I),g(C)};return this.on(A,I)}off(A,g){if(null==g)throw new Error("Missing callback function (listener).");const I=this.listeners[A]||[];if("number"==typeof g){return void(I[g]=null)}const C=g;I.forEach(((A,g)=>{A===C&&(I[g]=null)}))}removeListenerById(A,g){this.off(A,g)}emit(A,g=new BaseEvent){(this.listeners[A]||[]).forEach((A=>{if(A)try{A(g)}catch(A){console.warn(A)}}))}}class ResizedEvent extends BaseEvent{width;height;constructor(A,g){super(),this.width=A,this.height=g}}class GrowingPacker extends EventEmitter{root;freeNodes=[];constructor(A=0,g=0){super(),this.root={x:0,y:0,w:A,h:g,a:A*g},this.freeNodes.push(this.root)}fit(A){if(0==A.length)return;let g=!1;if(this.root.w<A[0].w&&(this.root.w=A[0].w,g=!0),this.root.h<A[0].h&&(this.root.h=A[0].h,g=!0),g){const A=new ResizedEvent(this.root.w,this.root.h);this.emit("resized",A)}A.forEach((A=>{A.fit=this.__addBlock(A)}))}__addBlock(A){const g=this.findNode(A.w,A.h);return g?this.splitNode(g,A.w,A.h):this.growNode(A.w,A.h)}addBlock(A){let g=!1;if(this.root.w<A.w&&(this.root.w=A.w,g=!0),this.root.h<A.h&&(this.root.h=A.h,g=!0),g){const A=new ResizedEvent(this.root.w,this.root.h);this.emit("resized",A)}const I=this.findNode(A.w,A.h);return I?this.splitNode(I,A.w,A.h):this.growNode(A.w,A.h)}findNode(A,g){const I=this.freeNodes.findIndex((I=>A<=I.w&&g<=I.h));return I>=0?this.freeNodes.splice(I,1)[0]:null}splitNode(A,g,I){return A.used=!0,A.w-g<A.h-I?(A.h-I>0&&(A.down={x:A.x,y:A.y+I,w:A.w,h:A.h-I,a:A.w*(A.h-I)},this.freeNodes.push(A.down)),A.w-g>0&&(A.right={x:A.x+g,y:A.y,w:A.w-g,h:I,a:(A.w-g)*I},this.freeNodes.push(A.right))):(A.w-g>0&&(A.right={x:A.x+g,y:A.y,w:A.w-g,h:A.h,a:(A.w-g)*A.h},this.freeNodes.push(A.right)),A.h-I>0&&(A.down={x:A.x,y:A.y+I,w:g,h:A.h-I,a:g*(A.h-I)},this.freeNodes.push(A.down))),this.freeNodes.sort(((A,g)=>A.a-g.a)),A}growNode(A,g){const I=A<=this.root.w,C=g<=this.root.h,e=C&&this.root.h>=this.root.w+A,i=I&&this.root.w>=this.root.h+g;return e?this.growRight(A,g):i?this.growDown(A,g):C?this.growRight(A,g):I?this.growDown(A,g):null}growRight(A,g){this.root={used:!0,x:0,y:0,w:this.root.w+A,h:this.root.h,a:(this.root.w+A)*this.root.h,down:this.root,right:{x:this.root.w,y:0,w:A,h:this.root.h,a:A*this.root.h}},this.freeNodes.push(this.root.right),this.freeNodes.sort(((A,g)=>A.a-g.a));const I=this.findNode(A,g);let C;I&&(C=this.splitNode(I,A,g));const e=new ResizedEvent(this.root.w,this.root.h);return this.emit("resized",e),C}growDown(A,g){this.root={used:!0,x:0,y:0,w:this.root.w,h:this.root.h+g,a:this.root.w*(this.root.h+g),down:{x:0,y:this.root.h,w:this.root.w,h:g,a:this.root.w*g},right:this.root},this.freeNodes.push(this.root.down),this.freeNodes.sort(((A,g)=>A.a-g.a));const I=this.findNode(A,g);let C;I&&(C=this.splitNode(I,A,g));const e=new ResizedEvent(this.root.w,this.root.h);return this.emit("resized",e),C}}const UInt8=0,SInt8=1,UInt16=2,SInt16=3,UInt32=4,SInt32=5,Float32=6;class MathFunctions{static radToDeg(A){return A/(Math.PI/180)}static degToRad(A){return A*(Math.PI/180)}static isNumeric(A){return!isNaN(parseFloat(A))&&isFinite(A)}static randomInt(A,g){return A=Math.ceil(A),g=Math.floor(g),Math.floor(Math.random()*(g-A))+A}static lerp(A,g,I){return A+I*(g-A)}static clamp(A,g,I){return Math.min(Math.max(A,g),I)}static nearestPow2(A){return Math.pow(2,Math.round(Math.log(A)/Math.log(2)))}static nearestPow10(A){return Math.pow(10,Math.round(Math.log10(A)/Math.log10(10)))}static nextPow2(A){if(0==this.fract(Math.log2(A)))return A;let g=0;for(;A>0;)g++,A>>=1;return 1<<g}static fract(A){return 0==A?0:A<0?A>-1?-A:-A%Math.floor(-A):A<1?A:A%Math.floor(A)}static remap(A,g,I,C,e){return C+(A-g)/(I-g)*(e-C)}static smoothStep(A,g,I){const C=this.clamp((I-A)/(g-A),0,1);return C*C*(3-2*C)}static linStep(A,g,I){return this.clamp((I-A)/(g-A),0,1)}static decode16BitFloatFrom2xUInt8(A){const g=A[0],I=(120&g)>>3;let C=0==I?0:2048;const e=C+((7&g)<<8)+A[1];C=0==I?1:0;return(128&g?1:-1)*e*Math.pow(2,I+C-16)}static encode16BitFloatInto2xUInt8(A){const g=new Uint8Array(2),I=A>=0?128:0;A=Math.abs(A);let C,e=15,i=1024;for(let g=15;g>0;g--)A<i&&(i/=2,e--);C=0==e?A/i/2:(A-i)/i;const t=Math.round(2048*C),o=t/256,a=t-256*o;return g[0]=I+8*e+o,g[1]=a,A>=2048&&(g[0]=255),g}static encode16BitFloat(A){const g=new Float32Array(1);g[0]=A;return(A=>{let g=A>>16&32768,I=A>>12&2047;const C=A>>23&255;return C<103?g:C>142?(g|=31744,g|=(255==C?0:1)&&8388607&A,g):C<113?(I|=2048,g|=(I>>114-C)+(I>>113-C&1),g):(g|=C-112<<10|I>>1,g+=1&I,g)})(new Int32Array(g.buffer)[0])}static decode16BitFloat(A){const g=(32768&A)>>15,I=(31744&A)>>10,C=1023&A;return 0==I?(g?-1:1)*Math.pow(2,-14)*(C/Math.pow(2,10)):31==I?C?NaN:1/0*(g?-1:1):(g?-1:1)*Math.pow(2,I-15)*(1+C/Math.pow(2,10))}static convertFloat32ArrayToUInt16Array(A){const g=new Uint16Array(A.length),I=new Int32Array(A.buffer),C=A=>{let g=A>>16&32768,I=A>>12&2047;const C=A>>23&255;return C<103?g:C>142?(g|=31744,g|=(255==C?0:1)&&8388607&A,g):C<113?(I|=2048,g|=(I>>114-C)+(I>>113-C&1),g):(g|=C-112<<10|I>>1,g+=1&I,g)};for(let e=0;e<A.length;e++)g[e]=C(I[e]);return g}}class Allocation1D{start;size;constructor(A=0,g=0){this.start=A,this.size=g}}class Allocator1D extends EventEmitter{freeList=[];allocations=[];allocationsMap={};allocatedSpace=0;reservedSpace=0;freeSpace=0;constructor(){super()}getAllocation(A){return this.allocations[this.allocationsMap[A]]}allocate(A,g){if(null!=this.allocationsMap[A]){const I=this.allocationsMap[A],C=this.allocations[I];if(g==C.size)return C;if(g<C.size){const A=C.size-g;return this.addBlock(I+1,new Allocation1D(C.start+g,A)),this.freeBlock(I+1),C.size=g,C}{const e=I+1;if(this.freeList.includes(e)&&C.size+this.allocations[e].size>=g){const A=this.allocations[e];if(C.size+A.size==g)return C.size+=A.size,this.freeSpace-=A.size,this.freeList.splice(this.freeList.indexOf(e),1),this.removeBlock(e),C;{const I=g-C.size;return C.size+=I,this.freeSpace-=I,A.start+=I,A.size-=I,C}}delete this.allocationsMap[A],C.start+C.size==this.allocatedSpace?(this.removeBlock(I),this.allocatedSpace-=C.size):this.freeBlock(I)}}let I=-1;for(let A=0;A<this.freeList.length;A++){const C=this.freeList[A],e=this.allocations[C];if(e.size==g){I=C;break}e.size>g&&(I=C)}if(-1!=I){const C=this.allocations[I];if(this.freeSpace-=C.size,this.freeList.splice(this.freeList.indexOf(I),1),C.size>g){const A=C.size-g;this.addBlock(I+1,new Allocation1D(C.start+g,A)),this.freeBlock(I+1),this.allocations[I].size=g}this.allocationsMap[A]=I}else{const I=this.allocatedSpace,C=this.allocations.length;this.allocatedSpace+=g;const e=MathFunctions.nextPow2(this.allocatedSpace);e>this.reservedSpace&&(this.reservedSpace=e,this.emit("resized",{reservedSpace:this.reservedSpace})),this.allocations.push(new Allocation1D(I,g)),this.allocationsMap[A]=C}return this.allocations[this.allocationsMap[A]]}addBlock(A,g){this.allocations.splice(A,0,g);for(const g in this.allocationsMap)this.allocationsMap[g]>=A&&this.allocationsMap[g]++;for(let g=0;g<this.freeList.length;g++)this.freeList[g]>=A&&this.freeList[g]++}removeBlock(A){this.allocations.splice(A,1);for(const g in this.allocationsMap)this.allocationsMap[g]>A&&this.allocationsMap[g]--;for(let g=0;g<this.freeList.length;g++)this.freeList[g]>A&&this.freeList[g]--}freeBlock(A){const g=this.allocations[A];this.freeSpace+=g.size;const I=A-1;if(this.freeList.includes(I)){return this.allocations[I].size+=g.size,void this.removeBlock(A)}const C=A+1;if(this.freeList.includes(C)){const I=this.allocations[C];return I.start-=g.size,I.size+=g.size,void this.removeBlock(A)}this.freeList.push(A),this.freeList.sort(((A,g)=>this.allocations[A].size-this.allocations[g].size))}deallocate(A){const g=this.allocationsMap[A];if(null==g)throw new Error(`allocation ${A} does not exist.`);this.freeBlock(g),delete this.allocationsMap[A]}getFragmentation(){return this.freeSpace/this.allocatedSpace}defragment(){}verifyConsistency(){if(Object.keys(this.allocationsMap).length+this.freeList.length!=this.allocations.length)throw new Error("number of blocks does not match the number of allocations");for(const A in this.allocationsMap){const g=this.allocationsMap[A];if(this.freeList.includes(g))throw new Error("block of used memory is also on the free list")}let A=0;for(let g=0;g<this.allocations.length;g++){const I=this.allocations[g];if(I.start!=A)throw"blocks of memory are not sequential";A+=I.size}if(A!=this.allocatedSpace)throw`allocated size: ${this.allocatedSpace}  does not match allocated blocks: ${A}`;if(this.reservedSpace<this.allocatedSpace)throw`reserved space: ${this.reservedSpace} is less than allocated space: ${this.allocatedSpace}`}}class IntersectionData{screenPos;pointerRay;intersectionPos;geomData;geomItem;componentId;componentIds=[];dist;constructor(A,g,I,C,e){this.screenPos=A,this.pointerRay=g,this.intersectionPos=I,this.geomData=C,this.geomItem=e.geomItem,this.componentId=e.componentId,this.dist=e.dist}}class ChildAddedEvent extends BaseEvent{index;childItem;constructor(A,g){super(),this.index=A,this.childItem=g}}class ControllerAddedEvent extends BaseEvent{controller;constructor(A){super(),this.controller=A}}class CountChangedEvent extends BaseEvent{change;count;constructor(A,g){super(),this.change=A,this.count=g}}class EnvMapAssignedEvent extends BaseEvent{envMap;constructor(A){super(),this.envMap=A}}class IndexEvent extends BaseEvent{index;constructor(A){super(),this.index=A}}class ZeaUIEvent extends BaseEvent{viewport;propagating=!0;constructor(){super()}}class ZeaKeyboardEvent extends ZeaUIEvent{sourceEvent;propagating=!0;altKey;code;ctrlKey;isComposing;key;location;metaKey;repeat;shiftKey;which;constructor(A){super(),A&&(this.sourceEvent=A,this.altKey=A.altKey,this.code=A.code,this.ctrlKey=A.ctrlKey,this.isComposing=A.isComposing,this.key=A.key,this.location=A.location,this.metaKey=A.metaKey,this.repeat=A.repeat,this.shiftKey=A.shiftKey)}stopPropagation(){this.propagating=!1,this.sourceEvent&&this.sourceEvent.stopPropagation()}preventDefault(){this.sourceEvent&&this.sourceEvent.preventDefault()}}class KeyboardEvent extends ZeaKeyboardEvent{}class NameChangedEvent extends BaseEvent{oldName;newName;constructor(A,g){super(),this.oldName=A,this.newName=g}}class OpacityStateChangedEvent extends BaseEvent{isOpaque;isOpaqueStateChanged;constructor(A,g){super(),this.isOpaque=A,this.isOpaqueStateChanged=g}}class ParameterAddedEvent extends BaseEvent{name;constructor(A){super(),this.name=A}}class ParameterRemovedEvent extends BaseEvent{name;constructor(A){super(),this.name=A}}class RangeLoadedEvent extends BaseEvent{range;constructor(A){super(),this.range=A}}class SceneSetEvent extends BaseEvent{scene;constructor(A){super(),this.scene=A}}class SelectabilityChangedEvent extends BaseEvent{value;constructor(A){super(),this.value=A}}class SelectedEvent extends BaseEvent{selected;constructor(A){super(),this.selected=A}}class ShaderNameChangedEvent extends BaseEvent{shaderName;constructor(A){super(),this.shaderName=A}}class StateChangedEvent extends BaseEvent{state;constructor(A){super(),this.state=A}}class StreamFileParsedEvent extends BaseEvent{geomFileID;geomCount;constructor(A,g){super(),this.geomFileID=A,this.geomCount=g}}class TexturedChangedEvent extends BaseEvent{isTextured;param;constructor(A,g){super(),this.isTextured=A,this.param=g}}class ViewChangedEvent extends BaseEvent{interfaceType;viewXfo;viewport;constructor(A,g){super(),this.interfaceType=A,this.viewXfo=g}}class ProgressEvent extends BaseEvent{percent;constructor(A){super(),this.percent=A}}const POINTER_TYPES={mouse:"mouse",touch:"touch",xr:"xr"};let capturedItem$1=null;class ZeaPointerEvent extends ZeaUIEvent{pointerType;pointerRay;pointerPos;detail;intersectionData;leftGeometry;constructor(A){super(),this.pointerType=A}stopPropagation(){this.propagating=!1}setCapture(A){capturedItem$1=A}getCapture(){return capturedItem$1}releaseCapture(){capturedItem$1=null}}const captureItems=[];class XRControllerEvent extends ZeaPointerEvent{controller;button;buttonPressed=0;constructor(A,g,I,C){super(POINTER_TYPES.xr),this.viewport=A,this.controller=g,this.button=I,this.buttonPressed=C}stopPropagation(){this.propagating=!1}setCapture(A){captureItems[this.controller.id]=A}getCapture(){return captureItems[this.controller.id]}releaseCapture(){captureItems[this.controller.id]=null}}let capturedItem=null;class XRPointerEvent extends ZeaPointerEvent{xfo;xrSelectEvent;hitTestResults;constructor(A,g,I,C){super(POINTER_TYPES.xr),this.viewport=A,this.xfo=g,this.xrSelectEvent=I,this.hitTestResults=C}stopPropagation(){this.propagating=!1}setCapture(A){capturedItem=A}getCapture(){return capturedItem}releaseCapture(){capturedItem=null}}class XRPoseEvent extends ZeaPointerEvent{viewXfo;controllers=[];constructor(A,g,I=[]){super(POINTER_TYPES.xr),this.viewport=A,this.viewXfo=g,I.forEach((A=>{this.controllers.push(A)}))}}class XRViewChangedEvent extends ViewChangedEvent{hmd="";controllers=[];xrviewport;constructor(A){super("VR",A)}}class XrViewportEvent extends BaseEvent{xrViewport;constructor(A){super(),this.xrViewport=A}}class ZeaMouseEvent extends ZeaPointerEvent{button;clientX;clientY;rendererX;rendererY;altKey;metaKey;ctrlKey;shiftKey;sourceEvent;constructor(A,g){super(POINTER_TYPES.mouse),this.sourceEvent=A,this.button=A.button,this.clientX=A.clientX,this.clientY=A.clientY,this.rendererX=this.clientX-g.left,this.rendererY=this.clientY-g.top,this.altKey=A.altKey,this.metaKey=A.metaKey,this.ctrlKey=A.ctrlKey,this.shiftKey=A.shiftKey}stopPropagation(){super.stopPropagation(),this.sourceEvent&&this.sourceEvent.stopPropagation()}preventDefault(){this.sourceEvent&&this.sourceEvent.preventDefault()}}class Ray{dir;start;constructor(A,g){this.start=A instanceof Vec3?A:new Vec3,this.dir=g instanceof Vec3?g:new Vec3}closestPoint(A){const g=A.subtract(this.start).dot(this.dir);if(g<Number.EPSILON)return 0;const I=this.dir.dot(this.dir);return I<Number.EPSILON?0:g/I}closestPointOnLineSegment(A,g){const I=this.dir,C=g.subtract(A),e=C.length();C.normalizeInPlace();const i=this.start.subtract(A),t=I.dot(I),o=I.dot(C),a=C.dot(C),B=I.dot(i),s=C.dot(i);if(0==t&&0==a)return[this.start.distanceTo(A),0];if(0==t)return[0,0];if(0==a)return[this.closestPoint(A),0];const l=t*a-o*o;let n,d;return l<.001?(n=0,d=o>a?B/o:s/a):(n=(o*s-a*B)/l,d=(t*s-o*B)/l),[n,MathFunctions.clamp(d/e,0,1)]}pointAtDist(A){return this.start.add(this.dir.scale(A))}intersectRayVector(A){const g=this.dir,I=A.dir,C=this.start.subtract(A.start),e=g.dot(g),i=g.dot(I),t=I.dot(I),o=g.dot(C),a=I.dot(C);if(0==e&&0==t)return;if(0==e){return[0,A.closestPoint(this.start)]}if(0==t){return[this.closestPoint(A.start),0]}const B=e*t-i*i;let s,l;return B<.001?(s=0,l=i>t?o/i:a/t):(s=(i*a-t*o)/B,l=(e*a-i*o)/B),[s,l]}intersectRayPlane(A){const g=this.start.subtract(A.start),I=A.dir.dot(this.dir),C=-A.dir.dot(g);if(Math.abs(I)<Number.PRECISION)return-1;const e=C/I;return e<-Number.PRECISION?-1:e}intersectRayBox3(A,g=0){const I=new Vec3(1/this.dir.x,1/this.dir.y,1/this.dir.z),C=[];C[0]=I.x<0?1:0,C[1]=I.y<0?1:0,C[2]=I.z<0?1:0;const e=[];if(g>0){const I=A.diagonal();I.normalizeInPlace(),I.scaleInPlace(g),e[0]=A.p0.subtract(I),e[1]=A.p1.add(I)}else e[0]=A.p0,e[1]=A.p1;let i=(e[C[0]].x-this.start.x)*I.x,t=(e[1-C[0]].x-this.start.x)*I.x;const o=(e[C[1]].y-this.start.y)*I.y,a=(e[1-C[1]].y-this.start.y)*I.y;if(i>a||o>t)return!1;o>i&&(i=o),a<t&&(t=a);const B=(e[C[2]].z-this.start.z)*I.z,s=(e[1-C[2]].z-this.start.z)*I.z;return!(i>s||B>t)&&(B>i&&(i=B),s<t&&(t=s),!0)}clone(){return new Ray(this.start.clone(),this.dir.clone())}toJSON(){return{start:this.start.toJSON(),dir:this.dir.toJSON()}}fromJSON(A){this.start.fromJSON(A.start),this.dir.fromJSON(A.dir)}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}}class Touch{identifier;clientX=0;clientY=0;screenX=0;screenY=0;pageX=0;pageY=0;radiusX=0;radiusY=0;rotationAngle=0;force=0;altitudeAngle=0;azimuthAngle=0;touchType="direct";rendererX;rendererY;touchPos;touchRay;constructor(A,g){this.identifier=A.identifier,this.clientX=A.clientX,this.clientY=A.clientY,this.screenX=A.screenX,this.screenY=A.screenY,this.pageX=A.pageX,this.pageY=A.pageY,this.radiusX=A.radiusX,this.radiusY=A.radiusY,this.rotationAngle=A.rotationAngle,this.force=A.force,this.rendererX=this.clientX-g.left,this.rendererY=this.clientY-g.top,this.touchPos=new Vec2(this.rendererX,this.rendererY),this.touchRay=new Ray}}class ZeaTouchEvent extends ZeaPointerEvent{touches=[];changedTouches=[];targetTouches=[];altKey=!1;metaKey=!1;ctrlKey=!1;shiftKey=!1;sourceEvent;constructor(A,g){super(POINTER_TYPES.touch),this.sourceEvent=A,this.sourceEvent.stopPropagation(),this.altKey=A.altKey,this.metaKey=A.metaKey,this.ctrlKey=A.ctrlKey,this.shiftKey=A.shiftKey;for(let I=0;I<A.touches.length;I++)this.touches.push(new Touch(A.touches[I],g));if(A.changedTouches)for(let I=0;I<A.changedTouches.length;I++)this.changedTouches.push(new Touch(A.changedTouches[I],g));if(A.targetTouches)for(let I=0;I<A.targetTouches.length;I++)this.targetTouches.push(new Touch(A.targetTouches[I],g))}stopPropagation(){super.stopPropagation(),this.sourceEvent&&this.sourceEvent.stopPropagation()}preventDefault(){}}class ZeaWheelEvent extends ZeaMouseEvent{wheelDelta;deltaMode;deltaX;deltaY;deltaZ;constructor(A,g){super(A,g),this.wheelDelta=A.wheelDelta,this.deltaMode=A.deltaMode,this.deltaX=A.deltaX,this.deltaY=A.deltaY,this.deltaZ=A.deltaZ}}class Color{r=0;g=0;b=0;a=255;constructor(A=0,g=0,I=0,C=1){"string"==typeof A?A.startsWith("#")?this.setFromHex(A):this.setFromCSSColorName(A):(this.r=A,this.g=g,this.b=I,this.a=C)}set(A,g,I,C=1){this.r=A,this.g=g,this.b=I,this.a=C}setFromOther(A){this.r=A.r,this.g=A.g,this.b=A.b,this.a=A.a}getAsRGBArray(){return[255*this.r,255*this.g,255*this.b]}getAsRGBDict(){return{r:255*this.r,g:255*this.g,b:255*this.b}}setFromRGB(A,g,I,C){this.r=A/255,this.g=g/255,this.b=I/255,this.a=C?C/255:1}setFromRGBDict(A){this.r=A.r/255,this.g=A.g/255,this.b=A.b/255,this.a=4==A.a?A.a/255:1}setFromHex(A){const g=function(A){const g=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(A);return g?{r:parseInt(g[1],16),g:parseInt(g[2],16),b:parseInt(g[3],16)}:null}(A);g?this.setFromRGB(g.r,g.g,g.b):console.warn("Invalid hex code:"+A)}setFromCSSColorName(A){if(A.startsWith("#"))this.setFromHex(A);else{const g={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4","indianred ":"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgrey:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"}[A.toLowerCase()];g&&this.setFromHex(g)}}toHex(){function A(A){const g=Math.round(255*A).toString(16);return 1==g.length?"0"+g:g}return"#"+A(this.r)+A(this.g)+A(this.b)}isEqual(A){return this.r==A.r&&this.g==A.g&&this.b==A.b&&this.a==A.a}notEquals(A){return this.r!=A.r&&this.g!=A.g&&this.b!=A.b&&this.a!=A.a}approxEqual(A,g=Number.EPSILON){return Math.abs(this.r-A.r)<g&&Math.abs(this.g-A.g)<g&&Math.abs(this.b-A.b)<g&&Math.abs(this.a-A.a)<g}add(A){return new Color(this.r+A.r,this.g+A.g,this.b+A.b,this.a+A.a)}addInPlace(A){this.r+=A.r,this.g+=A.g,this.b+=A.b,this.a+=A.a}subtract(A){return new Color(this.r-A.r,this.g-A.g,this.b-A.b,this.a-A.a)}scale(A){return new Color(this.r*A,this.g*A,this.b*A,this.a*A)}scaleInPlace(A){this.r*=A,this.g*=A,this.b*=A,this.a*=A}applyGamma(A){this.set(Math.pow(this.r,A),Math.pow(this.g,A),Math.pow(this.b,A),this.a)}toLinear(A=2.2){return new Color(Math.pow(this.r,A),Math.pow(this.g,A),Math.pow(this.b,A),this.a)}toGamma(A=2.2){return new Color(Math.pow(this.r,1/A),Math.pow(this.g,1/A),Math.pow(this.b,1/A),this.a)}luminance(){return.2126*this.r+.7152*this.g+.0722*this.b}lerp(A,g){const I=this.r,C=this.g,e=this.b,i=this.a;return new Color(I+g*(A.r-I),C+g*(A.g-C),e+g*(A.b-e),i+g*(A.a-i))}static random(A=0,g=!1){return A>0?new Color(A+Math.random()*(1-A),A+Math.random()*(1-A),A+Math.random()*(1-A),g?A+Math.random()*(1-A):1):A<0?new Color(Math.random()*(1+A),Math.random()*(1+A),Math.random()*(1+A),g?Math.random()*(1+A):1):new Color(Math.random(),Math.random(),Math.random(),g?Math.random():1)}clone(){return new Color(this.r,this.g,this.b,this.a)}asArray(){return[this.r,this.g,this.b,this.a]}fromArray(A){this.r=A[0]/255,this.g=A[1]/255,this.b=A[2]/255,this.a=4==A.length?A[3]/255:1}toJSON(){return{r:this.r,g:this.g,b:this.b,a:this.a}}fromJSON(A){this.r=A.r,this.g=A.g,this.b=A.b,this.a=A.a}readBinary(A){this.r=A.loadFloat32(),this.g=A.loadFloat32(),this.b=A.loadFloat32(),this.a=A.loadFloat32()}toCSSString(){return"rgba("+Math.round(255*this.r)+", "+Math.round(255*this.g)+", "+Math.round(255*this.b)+", "+this.a+")"}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}}var EulerAnglesAxisOrder;!function(A){A[A.XYZ=0]="XYZ",A[A.YZX=1]="YZX",A[A.ZXY=2]="ZXY",A[A.XZY=3]="XZY",A[A.ZYX=4]="ZYX",A[A.YXZ=5]="YXZ"}(EulerAnglesAxisOrder||(EulerAnglesAxisOrder={}));class EulerAngles{x;y;z;order;constructor(A=0,g=0,I=0,C=0){if(this.x=A,this.y=g,this.z=I,"number"!=typeof C||isNaN(C))switch(C){case"XYZ":this.order=0;break;case"YZX":this.order=1;break;case"ZXY":this.order=2;break;case"XZY":this.order=3;break;case"ZYX":this.order=4;break;case"YXZ":this.order=5;break;default:throw new Error("Invalid Euler Angles Order:"+C)}else this.order=C}set(A,g,I){this.x=A,this.y=g,this.z=I}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}toJSON(){return{x:this.x,y:this.y,z:this.z,order:this.order}}fromJSON(A){this.x=A.x,this.y=A.y,this.z=A.z,this.order=A.order}}class Mat3{m00=1;m01=0;m02=0;m10=0;m11=1;m12=0;m20=0;m21=0;m22=1;constructor(A=1,g=0,I=0,C=0,e=1,i=0,t=0,o=0,a=1){A instanceof Vec3&&g instanceof Vec3&&I instanceof Vec3?this.set(A.x,A.y,A.z,g.x,g.y,g.z,I.x,I.y,I.z):this.set(A,g,I,C,e,i,t,o,a)}get xAxis(){return new Vec3(this.m00,this.m01,this.m02)}set xAxis(A){this.xAxis.set(A.x,A.y,A.z)}get yAxis(){return new Vec3(this.m10,this.m11,this.m12)}set yAxis(A){this.yAxis.set(A.x,A.y,A.z)}get zAxis(){return new Vec3(this.m20,this.m21,this.m22)}set zAxis(A){this.zAxis.set(A.x,A.y,A.z)}set(A=1,g=0,I=0,C=0,e=1,i=0,t=0,o=0,a=1){this.m00=A,this.m01=g,this.m02=I,this.m10=C,this.m11=e,this.m12=i,this.m20=t,this.m21=o,this.m22=a}setIdentity(){this.set()}setFromMat(A){this.m00=A.m00,this.m01=A.m01,this.m02=A.m02,this.m10=A.m10,this.m11=A.m11,this.m12=A.m12,this.m20=A.m20,this.m21=A.m21,this.m22=A.m22}setFromDirectionAndUpvector(A,g){const I=A,C=I.length();if(C<Number.EPSILON)return void this.setIdentity();I.scaleInPlace(1/C);const e=g.cross(I),i=e.length();i>Number.EPSILON&&e.scaleInPlace(1/i);const t=I.cross(e),o=t.length();o>Number.EPSILON&&t.scaleInPlace(1/o),this.set(e.x,e.y,e.z,t.x,t.y,t.z,I.x,I.y,I.z)}inverse(){const A=this.m00,g=this.m01,I=this.m02,C=this.m10,e=this.m11,i=this.m12,t=this.m20,o=this.m21,a=this.m22,B=a*e-i*o,s=-a*C+i*t,l=o*C-e*t;let n=A*B+g*s+I*l;return n?(n=1/n,new Mat3(B*n,(-a*g+I*o)*n,(i*g-I*e)*n,s*n,(a*A-I*t)*n,(-i*A+I*C)*n,l*n,(-o*A+g*t)*n,(e*A-g*C)*n)):(console.warn("Unable to invert Mat3"),new Mat3)}invertInPlace(){const A=this.m00,g=this.m01,I=this.m02,C=this.m10,e=this.m11,i=this.m12,t=this.m20,o=this.m21,a=this.m22,B=a*e-i*o,s=-a*C+i*t,l=o*C-e*t;let n=A*B+g*s+I*l;return n?(n=1/n,this.set(B*n,(-a*g+I*o)*n,(i*g-I*e)*n,s*n,(a*A-I*t)*n,(-i*A+I*C)*n,l*n,(-o*A+g*t)*n,(e*A-g*C)*n),!0):(console.warn("Unable to invert Mat3"),!1)}transpose(){return new Mat3(this.m00,this.m10,this.m20,this.m01,this.m11,this.m21,this.m02,this.m12,this.m22)}transposeInPlace(){const A=this.m01,g=this.m02,I=this.m12;this.m01=this.m10,this.m02=this.m20,this.m10=A,this.m12=this.m21,this.m20=g,this.m21=I}transformVec3(A){return new Vec3(this.m00*A.x+this.m01*A.y+this.m02*A.z,this.m10*A.x+this.m11*A.y+this.m12*A.z,this.m20*A.x+this.m21*A.y+this.m22*A.z)}clone(){return new Mat3(this.m00,this.m01,this.m02,this.m10,this.m11,this.m12,this.m20,this.m21,this.m22)}readBinary(A){const g=A.loadFloat32Array(9);this.fromArray(g)}toJSON(){return this.asArray()}fromJSON(A){this.fromArray(A)}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}asArray(){return[this.m00,this.m01,this.m02,this.m10,this.m11,this.m12,this.m20,this.m21,this.m22]}fromArray(A){this.m00=A[0],this.m01=A[1],this.m02=A[2],this.m10=A[3],this.m11=A[4],this.m12=A[5],this.m20=A[6],this.m21=A[7],this.m22=A[8]}}class Mat4{m00;m01;m02;m03;m10;m11;m12;m13;m20;m21;m22;m23;m30;m31;m32;m33;constructor(A=1,g=0,I=0,C=0,e=0,i=1,t=0,o=0,a=0,B=0,s=1,l=0,n=0,d=0,r=0,c=1){this.m00=A,this.m01=g,this.m02=I,this.m03=C,this.m10=e,this.m11=i,this.m12=t,this.m13=o,this.m20=a,this.m21=B,this.m22=s,this.m23=l,this.m30=n,this.m31=d,this.m32=r,this.m33=c}get xAxis(){return new Vec3(this.m00,this.m01,this.m02)}set xAxis(A){this.xAxis.set(A.x,A.y,A.z)}get yAxis(){return new Vec3(this.m10,this.m11,this.m12)}set yAxis(A){this.yAxis.set(A.x,A.y,A.z)}get zAxis(){return new Vec3(this.m20,this.m21,this.m22)}set zAxis(A){this.zAxis.set(A.x,A.y,A.z)}get translation(){return new Vec3(this.m30,this.m31,this.m32)}set translation(A){this.m30=A.x,this.m31=A.y,this.m32=A.z}set(A=1,g=0,I=0,C=0,e=0,i=1,t=0,o=0,a=0,B=0,s=1,l=0,n=0,d=0,r=0,c=1){this.m00=A,this.m01=g,this.m02=I,this.m03=C,this.m10=e,this.m11=i,this.m12=t,this.m13=o,this.m20=a,this.m21=B,this.m22=s,this.m23=l,this.m30=n,this.m31=d,this.m32=r,this.m33=c}setIdentity(){this.set()}setFromMat4(A){this.m00=A.m00,this.m01=A.m01,this.m02=A.m02,this.m03=A.m03,this.m10=A.m10,this.m11=A.m11,this.m12=A.m12,this.m13=A.m13,this.m20=A.m20,this.m21=A.m21,this.m22=A.m22,this.m23=A.m23,this.m30=A.m30,this.m31=A.m31,this.m32=A.m32,this.m33=A.m33}toMat3(){return new Mat3(this.m00,this.m01,this.m02,this.m10,this.m11,this.m12,this.m20,this.m21,this.m22)}transposeInPlace(){const A=this.m01,g=this.m02,I=this.m03,C=this.m12,e=this.m13,i=this.m23;this.m01=this.m10,this.m02=this.m20,this.m03=this.m30,this.m10=A,this.m12=this.m21,this.m13=this.m31,this.m20=g,this.m21=C,this.m23=this.m32,this.m30=I,this.m31=e,this.m32=i}transpose(){return new Mat4(this.m00,this.m10,this.m20,this.m30,this.m01,this.m11,this.m21,this.m31,this.m02,this.m12,this.m22,this.m32,this.m03,this.m13,this.m23,this.m33)}inverse(){const A=this.m00,g=this.m01,I=this.m02,C=this.m03,e=this.m10,i=this.m11,t=this.m12,o=this.m13,a=this.m20,B=this.m21,s=this.m22,l=this.m23,n=this.m30,d=this.m31,r=this.m32,c=this.m33,h=A*i-g*e,G=A*t-I*e,m=A*o-C*e,b=g*t-I*i,Z=g*o-C*i,u=I*o-C*t,y=a*d-B*n,E=a*r-s*n,Q=a*c-l*n,V=B*r-s*d,R=B*c-l*d,W=s*c-l*r;let p=h*W-G*R+m*V+b*Q-Z*E+u*y;return p?(p=1/p,new Mat4((i*W-t*R+o*V)*p,(I*R-g*W-C*V)*p,(d*u-r*Z+c*b)*p,(s*Z-B*u-l*b)*p,(t*Q-e*W-o*E)*p,(A*W-I*Q+C*E)*p,(r*m-n*u-c*G)*p,(a*u-s*m+l*G)*p,(e*R-i*Q+o*y)*p,(g*Q-A*R-C*y)*p,(n*Z-d*m+c*h)*p,(B*m-a*Z-l*h)*p,(i*E-e*V-t*y)*p,(A*V-g*E+I*y)*p,(d*G-n*b-r*h)*p,(a*b-B*G+s*h)*p)):(console.warn("Unable to invert Mat4"),this)}invertInPlace(){const A=this.m00,g=this.m01,I=this.m02,C=this.m03,e=this.m10,i=this.m11,t=this.m12,o=this.m13,a=this.m20,B=this.m21,s=this.m22,l=this.m23,n=this.m30,d=this.m31,r=this.m32,c=this.m33,h=A*i-g*e,G=A*t-I*e,m=A*o-C*e,b=g*t-I*i,Z=g*o-C*i,u=I*o-C*t,y=a*d-B*n,E=a*r-s*n,Q=a*c-l*n,V=B*r-s*d,R=B*c-l*d,W=s*c-l*r;let p=h*W-G*R+m*V+b*Q-Z*E+u*y;return p?(p=1/p,this.set((i*W-t*R+o*V)*p,(I*R-g*W-C*V)*p,(d*u-r*Z+c*b)*p,(s*Z-B*u-l*b)*p,(t*Q-e*W-o*E)*p,(A*W-I*Q+C*E)*p,(r*m-n*u-c*G)*p,(a*u-s*m+l*G)*p,(e*R-i*Q+o*y)*p,(g*Q-A*R-C*y)*p,(n*Z-d*m+c*h)*p,(B*m-a*Z-l*h)*p,(i*E-e*V-t*y)*p,(A*V-g*E+I*y)*p,(d*G-n*b-r*h)*p,(a*b-B*G+s*h)*p),!0):(console.warn("Unable to invert Mat4"),!1)}setInverse(A){const g=A.m00,I=A.m01,C=A.m02,e=A.m03,i=A.m10,t=A.m11,o=A.m12,a=A.m13,B=A.m20,s=A.m21,l=A.m22,n=A.m23,d=A.m30,r=A.m31,c=A.m32,h=A.m33,G=g*t-I*i,m=g*o-C*i,b=g*a-e*i,Z=I*o-C*t,u=I*a-e*t,y=C*a-e*o,E=B*r-s*d,Q=B*c-l*d,V=B*h-n*d,R=s*c-l*r,W=s*h-n*r,p=l*h-n*c;let S=G*p-m*W+b*R+Z*V-u*Q+y*E;if(!S)throw new Error("Unable to invert Mat4");S=1/S,this.set((t*p-o*W+a*R)*S,(C*W-I*p-e*R)*S,(r*y-c*u+h*Z)*S,(l*u-s*y-n*Z)*S,(o*V-i*p-a*Q)*S,(g*p-C*V+e*Q)*S,(c*b-d*y-h*m)*S,(B*y-l*b+n*m)*S,(i*W-t*V+a*E)*S,(I*V-g*W-e*E)*S,(d*u-r*b+h*G)*S,(s*b-B*u-n*G)*S,(t*Q-i*R-o*E)*S,(g*R-I*Q+C*E)*S,(r*m-d*Z-c*G)*S,(B*Z-s*m+l*G)*S)}multiply(A){const g=this.m00,I=this.m01,C=this.m02,e=this.m03,i=this.m10,t=this.m11,o=this.m12,a=this.m13,B=this.m20,s=this.m21,l=this.m22,n=this.m23,d=this.m30,r=this.m31,c=this.m32,h=this.m33,G=A.asArray();let m=G[0],b=G[1],Z=G[2],u=G[3];const y=new Mat4;return y.m00=m*g+b*i+Z*B+u*d,y.m01=m*I+b*t+Z*s+u*r,y.m02=m*C+b*o+Z*l+u*c,y.m03=m*e+b*a+Z*n+u*h,m=G[4],b=G[5],Z=G[6],u=G[7],y.m10=m*g+b*i+Z*B+u*d,y.m11=m*I+b*t+Z*s+u*r,y.m12=m*C+b*o+Z*l+u*c,y.m13=m*e+b*a+Z*n+u*h,m=G[8],b=G[9],Z=G[10],u=G[11],y.m20=m*g+b*i+Z*B+u*d,y.m21=m*I+b*t+Z*s+u*r,y.m22=m*C+b*o+Z*l+u*c,y.m23=m*e+b*a+Z*n+u*h,m=G[12],b=G[13],Z=G[14],u=G[15],y.m30=m*g+b*i+Z*B+u*d,y.m31=m*I+b*t+Z*s+u*r,y.m32=m*C+b*o+Z*l+u*c,y.m33=m*e+b*a+Z*n+u*h,y}multiplyInPlace(A){const g=this.asArray(),I=g[0],C=g[1],e=g[2],i=g[3],t=g[4],o=g[5],a=g[6],B=g[7],s=g[8],l=g[9],n=g[10],d=g[11],r=g[12],c=g[13],h=g[14],G=g[15],m=A.asArray();let b=m[0],Z=m[1],u=m[2],y=m[3];return this.m00=b*I+Z*t+u*s+y*r,this.m01=b*C+Z*o+u*l+y*c,this.m02=b*e+Z*a+u*n+y*h,this.m03=b*i+Z*B+u*d+y*G,b=m[4],Z=m[5],u=m[6],y=m[7],this.m10=b*I+Z*t+u*s+y*r,this.m11=b*C+Z*o+u*l+y*c,this.m12=b*e+Z*a+u*n+y*h,this.m13=b*i+Z*B+u*d+y*G,b=m[8],Z=m[9],u=m[10],y=m[11],this.m20=b*I+Z*t+u*s+y*r,this.m21=b*C+Z*o+u*l+y*c,this.m22=b*e+Z*a+u*n+y*h,this.m23=b*i+Z*B+u*d+y*G,b=m[12],Z=m[13],u=m[14],y=m[15],this.m30=b*I+Z*t+u*s+y*r,this.m31=b*C+Z*o+u*l+y*c,this.m32=b*e+Z*a+u*n+y*h,this.m33=b*i+Z*B+u*d+y*G,this}postMultiplyInPlace(A){const g=A.asArray(),I=g[0],C=g[1],e=g[2],i=g[3],t=g[4],o=g[5],a=g[6],B=g[7],s=g[8],l=g[9],n=g[10],d=g[11],r=g[12],c=g[13],h=g[14],G=g[15],m=this.asArray();let b=m[0],Z=m[1],u=m[2],y=m[3];return this.m00=b*I+Z*t+u*s+y*r,this.m01=b*C+Z*o+u*l+y*c,this.m02=b*e+Z*a+u*n+y*h,this.m03=b*i+Z*B+u*d+y*G,b=m[4],Z=m[5],u=m[6],y=m[7],this.m10=b*I+Z*t+u*s+y*r,this.m11=b*C+Z*o+u*l+y*c,this.m12=b*e+Z*a+u*n+y*h,this.m13=b*i+Z*B+u*d+y*G,b=m[8],Z=m[9],u=m[10],y=m[11],this.m20=b*I+Z*t+u*s+y*r,this.m21=b*C+Z*o+u*l+y*c,this.m22=b*e+Z*a+u*n+y*h,this.m23=b*i+Z*B+u*d+y*G,b=m[12],Z=m[13],u=m[14],y=m[15],this.m30=b*I+Z*t+u*s+y*r,this.m31=b*C+Z*o+u*l+y*c,this.m32=b*e+Z*a+u*n+y*h,this.m33=b*i+Z*B+u*d+y*G,this}translateInPlace(A){const g=this.asArray(),I=A.x,C=A.y,e=A.z;return g[12]=g[0]*I+g[4]*C+g[8]*e+g[12],g[13]=g[1]*I+g[5]*C+g[9]*e+g[13],g[14]=g[2]*I+g[6]*C+g[10]*e+g[14],g[15]=g[3]*I+g[7]*C+g[11]*e+g[15],this}setLookAt(A,g,I){const C=A.subtract(g),e=C.length();if(e<Number.EPSILON)return void this.setIdentity();C.scaleInPlace(1/e);const i=I.cross(C),t=i.length();t>Number.EPSILON&&i.scaleInPlace(1/t);const o=C.cross(i),a=o.length();a>Number.EPSILON&&o.scaleInPlace(1/a),this.set(i.x,i.y,i.z,0,o.x,o.y,o.z,0,C.x,C.y,C.z,0,A.x,A.y,A.z,1)}setRotation(A,g){const I=A.length();if(Math.abs(I)<Number.EPSILON)return null;const C=A.x/I,e=A.y/I,i=A.z/I,t=Math.sin(g),o=Math.cos(g),a=1-o,B=this.asArray();return B[0]=C*C*a+o,B[1]=e*C*a+i*t,B[2]=i*C*a-e*t,B[3]=0,B[4]=C*e*a-i*t,B[5]=e*e*a+o,B[6]=i*e*a+C*t,B[7]=0,B[8]=C*i*a+e*t,B[9]=e*i*a-C*t,B[10]=i*i*a+o,B[11]=0,B[12]=0,B[13]=0,B[14]=0,B[15]=1,this}setXRotation(A){const g=Math.sin(A),I=Math.cos(A),C=this.asArray();return C[0]=1,C[1]=0,C[2]=0,C[3]=0,C[4]=0,C[5]=I,C[6]=g,C[7]=0,C[8]=0,C[9]=-g,C[10]=I,C[11]=0,C[12]=0,C[13]=0,C[14]=0,C[15]=1,this}setYRotation(A){const g=Math.sin(A),I=Math.cos(A),C=this.asArray();return C[0]=I,C[1]=0,C[2]=-g,C[3]=0,C[4]=0,C[5]=1,C[6]=0,C[7]=0,C[8]=g,C[9]=0,C[10]=I,C[11]=0,C[12]=0,C[13]=0,C[14]=0,C[15]=1,this}setZRotation(A){const g=Math.sin(A),I=Math.cos(A),C=this.asArray();return C[0]=I,C[1]=g,C[2]=0,C[3]=0,C[4]=-g,C[5]=I,C[6]=0,C[7]=0,C[8]=0,C[9]=0,C[10]=1,C[11]=0,C[12]=0,C[13]=0,C[14]=0,C[15]=1,this}transformVec4(A){const g=this.asArray(),I=A.x,C=A.y,e=A.z,i=A.w;return new Vec4(g[0]*I+g[4]*C+g[8]*e+g[12]*i,g[1]*I+g[5]*C+g[9]*e+g[13]*i,g[2]*I+g[6]*C+g[10]*e+g[14]*i,g[3]*I+g[7]*C+g[11]*e+g[15]*i)}transformVec3(A){const g=this.asArray(),I=A.x,C=A.y,e=A.z;return new Vec3(g[0]*I+g[4]*C+g[8]*e+g[12],g[1]*I+g[5]*C+g[9]*e+g[13],g[2]*I+g[6]*C+g[10]*e+g[14])}rotateVec3(A){const g=this.asArray(),I=A.x,C=A.y,e=A.z;return new Vec3(g[0]*I+g[4]*C+g[8]*e,g[1]*I+g[5]*C+g[9]*e,g[2]*I+g[6]*C+g[10]*e)}setPerspectiveMatrix(A,g,I,C){const e=Math.tan(.5*Math.PI-.5*A),i=1/(I-C);this.set(e/g,0,0,0,0,e,0,0,0,0,(I+C)*i,-1,0,0,I*C*i*2,0)}setOrthographicMatrix(A,g,I,C,e,i){const t=1/(A-g),o=1/(I-C),a=1/(e-i);this.set(-2*t,0,0,0,0,-2*o,0,0,0,0,2*a,0,(A+g)*t,(C+I)*o,(i+e)*a,1)}setScale(A,g,I){A instanceof Vec3?this.set(A.x,0,0,0,0,A.y,0,0,0,0,A.z,0,0,0,0,1):this.set(A,0,0,0,0,g,0,0,0,0,I,0,0,0,0,1)}setFromMat3x4Array(A){this.set(A[0],A[1],A[2],0,A[3],A[4],A[5],0,A[6],A[7],A[8],0,A[9],A[10],A[11],1)}clone(){return new Mat4(this.m00,this.m01,this.m02,this.m03,this.m10,this.m11,this.m12,this.m13,this.m20,this.m21,this.m22,this.m23,this.m30,this.m31,this.m32,this.m33)}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}toJSON(){return this.asArray()}fromJSON(A){this.fromArray(A)}readBinary(A){this.fromArray(A.loadFloat32Array(16))}asArray(){return[this.m00,this.m01,this.m02,this.m03,this.m10,this.m11,this.m12,this.m13,this.m20,this.m21,this.m22,this.m23,this.m30,this.m31,this.m32,this.m33]}fromArray(A){this.m00=A[0],this.m01=A[1],this.m02=A[2],this.m03=A[3],this.m10=A[4],this.m11=A[5],this.m12=A[6],this.m13=A[7],this.m20=A[8],this.m21=A[9],this.m22=A[10],this.m23=A[11],this.m30=A[12],this.m31=A[13],this.m32=A[14],this.m33=A[15]}}class Quat{x;y;z;w;constructor(A=0,g=0,I=0,C=1){this.x=A,this.y=g,this.z=I,this.w=C}set(A,g,I,C){this.x=A,this.y=g,this.z=I,this.w=C}setFromOther(A){this.x=A.x,this.y=A.y,this.z=A.z,this.w=A.w}setFromEulerAngles(A){const g=new Vec3;switch(A.order){case EulerAnglesAxisOrder.XYZ:g.set(A.x,-A.y,A.z);break;case EulerAnglesAxisOrder.YZX:g.set(A.y,-A.z,A.x);break;case EulerAnglesAxisOrder.ZXY:g.set(A.z,-A.x,A.y);break;case EulerAnglesAxisOrder.XZY:g.set(A.x,A.z,A.y);break;case EulerAnglesAxisOrder.ZYX:g.set(A.z,A.y,A.x);break;case EulerAnglesAxisOrder.YXZ:g.set(A.y,A.x,A.z);break;default:throw new Error(`Invalid EulerAngles order: ${A.order}`)}const I=.5*g.x,C=.5*g.y,e=.5*g.z,i=Math.cos(I),t=Math.cos(C),o=Math.cos(e),a=Math.sin(I),B=Math.sin(C),s=Math.sin(e),l=i*o,n=i*s,d=a*o,r=a*s,c=t*d-B*n,h=t*r+B*l,G=t*n-B*d;switch(this.w=t*l+B*r,A.order){case 0:this.x=c,this.y=-h,this.z=G;break;case 1:this.x=G,this.y=c,this.z=-h;break;case 2:this.x=-h,this.y=G,this.z=c;break;case 3:this.x=c,this.y=G,this.z=h;break;case 4:this.x=G,this.y=h,this.z=c;break;case 5:this.x=h,this.y=c,this.z=G;break;default:throw new Error(`Invalid EulerAngles order: ${A.order}`)}}toEulerAngles(A){const g=new Vec3;switch(A){case EulerAnglesAxisOrder.XYZ:case"XYZ":g.set(this.z,this.x,this.y);break;case EulerAnglesAxisOrder.YZX:case"YZX":g.set(this.x,this.y,this.z);break;case EulerAnglesAxisOrder.ZXY:case"ZXY":g.set(this.y,this.z,this.x);break;case EulerAnglesAxisOrder.XZY:case"XZY":g.set(this.y,-this.x,this.z);break;case EulerAnglesAxisOrder.ZYX:case"ZYX":g.set(this.x,-this.z,this.y);break;case EulerAnglesAxisOrder.YXZ:case"YXZ":g.set(this.z,-this.y,this.x);break;default:throw new Error("Invalid rotation order:"+A)}const I=new Vec3,C=g.x*g.y+g.z*this.w;if(C>.49999)I.y=2*Math.atan2(g.x,this.w),I.z=.5*Math.PI,I.x=0;else if(C<-.49999)I.y=-2*Math.atan2(g.x,this.w),I.z=-.5*Math.PI,I.x=0;else{const A=g.x*g.x,e=g.y*g.y,i=g.z*g.z;I.y=Math.atan2(2*g.y*this.w-2*g.x*g.z,1-2*e-2*i),I.z=Math.asin(2*C),I.x=Math.atan2(2*g.x*this.w-2*g.y*g.z,1-2*A-2*i)}switch(A){case EulerAnglesAxisOrder.XYZ:case"XYZ":return new EulerAngles(I.y,I.z,I.x,A);case EulerAnglesAxisOrder.YZX:case"YZX":return new EulerAngles(I.x,I.y,I.z,A);case EulerAnglesAxisOrder.ZXY:case"ZXY":return new EulerAngles(I.z,I.x,I.y,A);case EulerAnglesAxisOrder.XZY:case"XZY":return new EulerAngles(-I.y,I.x,I.z,A);case EulerAnglesAxisOrder.ZYX:case"ZYX":return new EulerAngles(I.x,I.z,-I.y,A);case EulerAnglesAxisOrder.YXZ:case"YXZ":return new EulerAngles(I.z,-I.y,I.x,A)}}setFromAxisAndAngle(A,g){const I=g/2,C=A.normalize().scale(Math.sin(I));this.set(C.x,C.y,C.z,Math.cos(I))}setFromDirectionAndUpvector(A,g){const I=new Mat3;I.setFromDirectionAndUpvector(A,g),this.setFromMat3(I)}setFrom2Vectors(A,g){const I=A.cross(g),C=A.dot(g),e=Math.sqrt(2*(1+C));this.set(I.x/e,I.y/e,I.z/e,e/2),this.normalizeInPlace()}setFromMat3(A){const g=A.asArray(),I=g[0]+g[4]+g[8];let C;if(I>0)C=Math.sqrt(I+1),this.w=.5*C,C=.5/C,this.x=(g[5]-g[7])*C,this.y=(g[6]-g[2])*C,this.z=(g[1]-g[3])*C;else{let A=0;g[4]>g[0]&&(A=1),g[8]>g[3*A+A]&&(A=2);const I=(A+1)%3,e=(A+2)%3;C=Math.sqrt(g[3*A+A]-g[3*I+I]-g[3*e+e]+1);const i=[0,0,0,0];i[A]=.5*C,C=.5/C,i[3]=(g[3*I+e]-g[3*e+I])*C,i[I]=(g[3*I+A]+g[3*A+I])*C,i[e]=(g[3*e+A]+g[3*A+e])*C,this.fromArray(i)}this.normalizeInPlace()}setFromMat4(A){const g=A.asArray(),I=g[0]+g[5]+g[10];let C;if(I>0)C=Math.sqrt(I+1),this.w=.5*C,C=.5/C,this.x=(g[6]-g[9])*C,this.y=(g[8]-g[2])*C,this.z=(g[1]-g[4])*C;else{let A=0;g[5]>g[0]&&(A=1),g[10]>g[4*A+A]&&(A=2);const I=(A+1)%3,e=(A+2)%3;C=Math.sqrt(g[4*A+A]-g[4*I+I]-g[4*e+e]+1);const i=[0,0,0,0];i[A]=.5*C,C=.5/C,i[3]=(g[4*I+e]-g[4*e+I])*C,i[I]=(g[4*I+A]+g[4*A+I])*C,i[e]=(g[4*e+A]+g[4*A+e])*C,this.fromArray(i)}this.normalizeInPlace()}isIdentity(){return this.getAngle()<Number.EPSILON}getAngle(){return 2*Math.acos(this.w)}isEqual(A){return this.x==A.x&&this.y==A.y&&this.z==A.z&&this.w==A.w}notEquals(A){return this.x!=A.x&&this.y!=A.y&&this.z!=A.z&&this.w!=A.w}approxEqual(A,g=Number.EPSILON){return Math.abs(this.x-A.x)<g&&Math.abs(this.y-A.y)<g&&Math.abs(this.z-A.z)<g&&Math.abs(this.w-A.w)<g}add(A){return new Quat(this.x+A.x,this.y+A.y,this.z+A.z,this.w+A.w)}addInPlace(A){this.x+=A.x,this.y+=A.y,this.z+=A.z,this.w+=A.w}subtract(A){return new Quat(this.x-A.x,this.y-A.y,this.z-A.z,this.w-A.w)}scale(A){return new Quat(this.x*A,this.y*A,this.z*A,this.w*A)}scaleInPlace(A){this.x*=A,this.y*=A,this.z*=A,this.w*=A}length(){const A=this.x,g=this.y,I=this.z,C=this.w;return Math.sqrt(A*A+g*g+I*I+C*C)}lengthSquared(){const A=this.x,g=this.y,I=this.z,C=this.w;return A*A+g*g+I*I+C*C}normalize(){const A=this.x,g=this.y,I=this.z,C=this.w;let e=A*A+g*g+I*I+C*C;return e<Number.EPSILON?new Quat:(e=1/Math.sqrt(e),new Quat(A*e,g*e,I*e,C*e))}normalizeInPlace(){const A=this.x,g=this.y,I=this.z,C=this.w;let e=A*A+g*g+I*I+C*C;e<Number.EPSILON||(e=1/Math.sqrt(e),this.set(A*e,g*e,I*e,C*e))}dot(A){return this.x*A.x+this.y*A.y+this.z*A.z+this.w*A.w}cross(A){const g=this.x,I=this.y,C=this.z,e=this.w,i=A.x,t=A.y,o=A.z,a=A.w;return new Quat(I*o-C*t,C*a-e*o,e*i-g*a,g*t-I*i)}conjugate(){return new Quat(-this.x,-this.y,-this.z,this.w)}inverse(){return this.conjugate()}alignWith(A){this.dot(A)<0&&this.set(-this.x,-this.y,-this.z,-this.w)}multiply(A){const g=this.x,I=this.y,C=this.z,e=this.w,i=A.x,t=A.y,o=A.z,a=A.w;return new Quat(g*a+e*i+I*o-C*t,I*a+e*t+C*i-g*o,C*a+e*o+g*t-I*i,e*a-g*i-I*t-C*o)}multiplyInPlace(A){const g=this.x,I=this.y,C=this.z,e=this.w,i=A.x,t=A.y,o=A.z,a=A.w;this.set(g*a+e*i+I*o-C*t,I*a+e*t+C*i-g*o,C*a+e*o+g*t-I*i,e*a-g*i-I*t-C*o)}rotateVec3(A){const g=new Quat(A.x,A.y,A.z,0),I=this.multiply(g).multiply(this.conjugate());return new Vec3(I.x,I.y,I.z)}rotateX(A){A*=.5;const g=this.x,I=this.y,C=this.z,e=this.w,i=Math.sin(A),t=Math.cos(A);this.x=g*t+e*i,this.y=I*t+C*i,this.z=C*t-I*i,this.w=e*t-g*i}rotateY(A){A*=.5;const g=this.x,I=this.y,C=this.z,e=this.w,i=Math.sin(A),t=Math.cos(A);this.x=g*t-C*i,this.y=I*t+e*i,this.z=C*t+g*i,this.w=e*t-I*i}rotateZ(A){A*=.5;const g=this.x,I=this.y,C=this.z,e=this.w,i=Math.sin(A),t=Math.cos(A);this.x=g*t+I*i,this.y=I*t-g*i,this.z=C*t+e*i,this.w=e*t-C*i}toMat3(){const A=this.x,g=this.y,I=this.z,C=this.w,e=A+A,i=g+g,t=I+I,o=A*e,a=g*e,B=g*i,s=I*e,l=I*i,n=I*t,d=C*e,r=C*i,c=C*t,h=new Mat3;return h.m00=1-B-n,h.m10=a-c,h.m20=s+r,h.m01=a+c,h.m11=1-o-n,h.m21=l-d,h.m02=s-r,h.m12=l+d,h.m22=1-o-B,h}getXaxis(){const A=this.x*this.y,g=this.x*this.z,I=this.y*this.y,C=this.y*this.w,e=this.z*this.z,i=this.z*this.w;return new Vec3(1-2*(e+I),2*(A+i),2*(g-C))}getYaxis(){const A=this.x*this.x,g=this.x*this.y,I=this.x*this.w,C=this.y*this.z,e=this.z*this.z,i=this.z*this.w;return new Vec3(2*(g-i),1-2*(e+A),2*(C+I))}getZaxis(){const A=this.x*this.x,g=this.x*this.z,I=this.x*this.w,C=this.y*this.y,e=this.y*this.z,i=this.y*this.w;return new Vec3(2*(i+g),2*(e-I),1-2*(C+A))}mirror(A){switch(A){case 0:case 0:default:return new Quat(this.z,this.w,this.x,this.y);case 1:return new Quat(-this.w,this.z,this.y,-this.x);case 2:return new Quat(this.x,this.y,this.z,-this.w)}}toMat4(){const A=this.x,g=this.y,I=this.z,C=this.w,e=A+A,i=g+g,t=I+I,o=A*e,a=g*e,B=g*i,s=I*e,l=I*i,n=I*t,d=C*e,r=C*i,c=C*t,h=new Mat4;return h.m00=1-B-n,h.m10=a-c,h.m20=s+r,h.m01=a+c,h.m11=1-o-n,h.m21=l-d,h.m02=s-r,h.m12=l+d,h.m22=1-o-B,h}lerp(A,g){const I=new Quat(this.x+g*(A.x-this.x),this.y+g*(A.y-this.y),this.z+g*(A.z-this.z),this.w+g*(A.w-this.w));return I.normalizeInPlace(),I}slerp(A,g){const I=this.dot(A);if(I>.999)return this;const C=Math.acos(I),e=Math.sin(C),i=Math.sin(g*C),t=Math.sin((1-g)*C)/e,o=i/e,a=new Quat(t*this.x+o*A.x,t*this.y+o*A.y,t*this.z+o*A.z,t*this.w+o*A.w);return a.normalizeInPlace(),a}clone(){return new Quat(this.x,this.y,this.z,this.w)}asArray(){return[this.x,this.y,this.z,this.w]}fromArray(A){this.x=A[0],this.y=A[1],this.z=A[2],this.w=A[3]}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}toJSON(){return{x:this.x,y:this.y,z:this.z,w:this.w}}fromJSON(A){this.x=A.x,this.y=A.y,this.z=A.z,this.w=A.w,this.normalizeInPlace()}readBinary(A){this.x=A.loadFloat32(),this.y=A.loadFloat32(),this.z=A.loadFloat32(),this.w=A.loadFloat32()}}class Xfo{tr;ori;sc;constructor(A=new Vec3,g=new Quat,I=new Vec3(1,1,1)){this.tr=A,this.ori=g,this.sc=I}set(A,g,I){this.tr=A,this.ori=g,I instanceof Vec3&&(this.sc=I)}setFromOther(A){this.tr=A.tr,this.ori=A.ori,this.sc=A.sc}isIdentity(){return this.tr.isNull()&&this.ori.isIdentity()&&this.sc.is111()}isEqual(A){return this.tr.isEqual(A.tr)&&this.ori.isEqual(A.ori)&&this.sc.isEqual(A.sc)}approxEqual(A,g=Number.EPSILON){return(!A.tr||this.tr.approxEqual(A.tr,g))&&(!A.ori||this.ori.approxEqual(A.ori,g))&&(!A.sc||this.sc.approxEqual(A.sc,g))}setLookAt(A,g,I){const C=A.subtract(g);if(C.length()<Number.EPSILON)throw new Error("Invalid dir");this.ori.setFromDirectionAndUpvector(C,I),this.tr=A}multiply(A){let g=this.sc;if(Math.abs(this.sc.y-this.sc.x)>.001||Math.abs(this.sc.z-this.sc.x)>.001||Math.abs(this.sc.z-this.sc.y)>.001){const I=this.toMat4(),C=A.ori.toMat4(),e=I.multiply(C);g=new Vec3(e.xAxis.length(),e.yAxis.length(),e.zAxis.length())}return new Xfo(this.tr.add(this.ori.rotateVec3(this.sc.multiply(A.tr))),this.ori.multiply(A.ori),g.multiply(A.sc))}inverse(){const A=new Xfo;if(A.ori=this.ori.inverse(),Math.abs(this.sc.y-this.sc.x)>.001||Math.abs(this.sc.z-this.sc.x)>.001||Math.abs(this.sc.z-this.sc.y)>.001){const g=this.toMat4().inverse();A.sc=new Vec3(g.xAxis.length(),g.yAxis.length(),g.zAxis.length())}else A.sc=this.sc.inverse();return A.tr=A.ori.rotateVec3(this.tr.negate().multiply(A.sc)),A}transformVec3(A){return this.tr.add(this.ori.rotateVec3(this.sc.multiply(A)))}lerp(A,g){return new Xfo(this.tr.lerp(A.tr,g),this.ori.slerp(A.ori,g),this.sc.lerp(A.sc,g))}toMat4(){const A=new Mat4(this.sc.x,0,0,0,0,this.sc.y,0,0,0,0,this.sc.z,0,0,0,0,1),g=this.ori.toMat4(),I=new Mat4;return I.translation=this.tr,I.multiply(g).multiply(A)}setFromMat4(A){this.tr=A.translation,this.ori.setFromMat4(A),this.sc.set(A.xAxis.length(),A.yAxis.length(),A.zAxis.length())}clone(){return new Xfo(this.tr.clone(),this.ori.clone(),this.sc.clone())}toJSON(){return{tr:this.tr.toJSON(),ori:this.ori.toJSON(),sc:this.sc.toJSON()}}fromJSON(A){this.tr.fromJSON(A.tr),this.ori.fromJSON(A.ori),A.sc&&this.sc.fromJSON(A.sc)}readBinary(A){this.tr.readBinary(A),this.ori.readBinary(A),this.sc.readBinary(A)}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}}class Box2{p0;p1;constructor(A,g){this.p0=A instanceof Vec2?A:new Vec2(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY),this.p1=g instanceof Vec2?g:new Vec2(Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY)}set(A,g){this.p0=A,this.p1=g}reset(){this.p0.x=Number.POSITIVE_INFINITY,this.p1.x=Number.NEGATIVE_INFINITY,this.p0.y=Number.POSITIVE_INFINITY,this.p1.y=Number.NEGATIVE_INFINITY}isValid(){return this.p0.x!=Number.POSITIVE_INFINITY&&this.p1.x!=Number.NEGATIVE_INFINITY&&this.p0.y!=Number.POSITIVE_INFINITY&&this.p1.y!=Number.NEGATIVE_INFINITY}addPoint(A){(this.p0.x==Number.POSITIVE_INFINITY||A.x<this.p0.x)&&(this.p0.x=A.x),(this.p0.y==Number.POSITIVE_INFINITY||A.y<this.p0.y)&&(this.p0.y=A.y),(this.p1.y==Number.NEGATIVE_INFINITY||A.x>this.p1.x)&&(this.p1.x=A.x),(this.p1.y==Number.NEGATIVE_INFINITY||A.y>this.p1.y)&&(this.p1.y=A.y)}size(){return this.p1.distanceTo(this.p0)}diagonal(){return this.p1.subtract(this.p0)}center(){const A=this.p1.subtract(this.p0);return A.scaleInPlace(.5),A.addInPlace(this.p0),A}clone(){return new Box2(this.p0.clone(),this.p1.clone())}toJSON(){return{p0:this.p0.toJSON(),p1:this.p1.toJSON()}}fromJSON(A){const g={x:MathFunctions.isNumeric(A.p0.x)?A.p0.x:Number.POSITIVE_INFINITY,y:MathFunctions.isNumeric(A.p0.y)?A.p0.y:Number.POSITIVE_INFINITY},I={x:MathFunctions.isNumeric(A.p1.x)?A.p1.x:Number.NEGATIVE_INFINITY,y:MathFunctions.isNumeric(A.p1.y)?A.p1.y:Number.NEGATIVE_INFINITY};this.p0.fromJSON(g),this.p1.fromJSON(I)}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}}class SphereType{pos;radius;constructor(A=new Vec3,g=0){this.pos=A instanceof Vec3?A:new Vec3,this.radius=g}clone(){return new SphereType(this.pos.clone(),this.radius)}intersectsBox(A){return A.intersectsSphere(this)}toJSON(){return{pos:this.pos.toJSON(),radius:this.radius}}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}}class Box3{p0;p1;constructor(A=new Vec3(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY),g=new Vec3(Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY)){this.p0=A,this.p1=g}get min(){return this.p0}get max(){return this.p1}set(A,g){this.p0=A,this.p1=g}reset(){this.p0.x=Number.POSITIVE_INFINITY,this.p0.y=Number.POSITIVE_INFINITY,this.p0.z=Number.POSITIVE_INFINITY,this.p1.x=Number.NEGATIVE_INFINITY,this.p1.y=Number.NEGATIVE_INFINITY,this.p1.z=Number.NEGATIVE_INFINITY}isValid(){return this.p0.x!=Number.POSITIVE_INFINITY&&this.p1.x!=Number.NEGATIVE_INFINITY&&this.p0.y!=Number.POSITIVE_INFINITY&&this.p1.y!=Number.NEGATIVE_INFINITY&&this.p0.z!=Number.POSITIVE_INFINITY&&this.p1.z!=Number.NEGATIVE_INFINITY}addPoint(A){A.x!=Number.POSITIVE_INFINITY&&A.x!=Number.NEGATIVE_INFINITY&&(A.x<this.p0.x&&(this.p0.x=A.x),A.x>this.p1.x&&(this.p1.x=A.x)),A.y!=Number.POSITIVE_INFINITY&&A.y!=Number.NEGATIVE_INFINITY&&(A.y<this.p0.y&&(this.p0.y=A.y),A.y>this.p1.y&&(this.p1.y=A.y)),A.z!=Number.POSITIVE_INFINITY&&A.z!=Number.NEGATIVE_INFINITY&&(A.z<this.p0.z&&(this.p0.z=A.z),A.z>this.p1.z&&(this.p1.z=A.z))}addBox3(A,g){g?(this.addPoint(g.transformVec3(A.p0)),this.addPoint(g.transformVec3(new Vec3(A.p0.x,A.p0.y,A.p1.z))),this.addPoint(g.transformVec3(new Vec3(A.p0.x,A.p1.y,A.p0.z))),this.addPoint(g.transformVec3(new Vec3(A.p1.x,A.p0.y,A.p0.z))),this.addPoint(g.transformVec3(new Vec3(A.p0.x,A.p1.y,A.p1.z))),this.addPoint(g.transformVec3(new Vec3(A.p1.x,A.p0.y,A.p1.z))),this.addPoint(g.transformVec3(new Vec3(A.p1.x,A.p1.y,A.p0.z))),this.addPoint(g.transformVec3(A.p1))):(this.addPoint(A.p0),this.addPoint(A.p1))}size(){return this.p1.distanceTo(this.p0)}diagonal(){return this.p1.subtract(this.p0)}center(){const A=this.p1.subtract(this.p0);return A.scaleInPlace(.5),A.addInPlace(this.p0),A}toMat4(){const A=this.p1.x-this.p0.x,g=this.p1.y-this.p0.y,I=this.p1.z-this.p0.z;return new Mat4(A,0,0,0,0,g,0,0,0,0,I,0,this.p0.x,this.p0.y,this.p0.z,1)}getBoundingSphere(){return new SphereType(this.center(),.5*this.diagonal().length())}intersectsBox(A){return!(A.max.x<this.min.x||A.min.x>this.max.x||A.max.y<this.min.y||A.min.y>this.max.y||A.max.z<this.min.z||A.min.z>this.max.z)}intersectsSphere(A){return(new Vec3).distanceTo(A.pos)<=A.radius*A.radius}intersectsPlane(A){let g,I;return A.normal.x>0?(g=A.normal.x*this.min.x,I=A.normal.x*this.max.x):(g=A.normal.x*this.max.x,I=A.normal.x*this.min.x),A.normal.y>0?(g+=A.normal.y*this.min.y,I+=A.normal.y*this.max.y):(g+=A.normal.y*this.max.y,I+=A.normal.y*this.min.y),A.normal.z>0?(g+=A.normal.z*this.min.z,I+=A.normal.z*this.max.z):(g+=A.normal.z*this.max.z,I+=A.normal.z*this.min.z),g<=-A.w&&I>=-A.w}clone(){return new Box3(this.p0.clone(),this.p1.clone())}toJSON(){return{p0:this.p0.toJSON(),p1:this.p1.toJSON()}}fromJSON(A){const g={x:MathFunctions.isNumeric(A.p0.x)?A.p0.x:Number.POSITIVE_INFINITY,y:MathFunctions.isNumeric(A.p0.y)?A.p0.y:Number.POSITIVE_INFINITY,z:MathFunctions.isNumeric(A.p0.z)?A.p0.z:Number.POSITIVE_INFINITY},I={x:MathFunctions.isNumeric(A.p1.x)?A.p1.x:Number.NEGATIVE_INFINITY,y:MathFunctions.isNumeric(A.p1.y)?A.p1.y:Number.NEGATIVE_INFINITY,z:MathFunctions.isNumeric(A.p1.z)?A.p1.z:Number.NEGATIVE_INFINITY};this.p0.fromJSON(g),this.p1.fromJSON(I)}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}}class PlaneType{normal;w;constructor(A,g=0){this.normal=A instanceof Vec3?A:new Vec3,this.w=g}set(A,g,I,C){this.normal.set(A,g,I),this.w=C}divideScalar(A){this.normal.scaleInPlace(1/A),this.w/=A}distanceToPoint(A){return A.dot(this.normal)+this.w}normalizeInPlace(){const A=1/this.normal.length();this.normal.scaleInPlace(A),this.w*=A}clone(){return new PlaneType(this.normal.clone(),this.w)}toJSON(){return{normal:this.normal.toJSON(),w:this.w}}fromJSON(A){this.normal.fromJSON(A.normal),this.w=A.w}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}}class Frustum{planes;constructor(A,g,I,C,e,i){this.planes=[A||new PlaneType,g||new PlaneType,I||new PlaneType,C||new PlaneType,e||new PlaneType,i||new PlaneType]}setFromMatrix(A){const g=A,I=this.planes;I[0].set(g.m03-g.m00,g.m13-g.m10,g.m23-g.m20,g.m33-g.m30),I[1].set(g.m03+g.m00,g.m13+g.m10,g.m23+g.m20,g.m33+g.m30),I[2].set(g.m03+g.m01,g.m13+g.m11,g.m23+g.m21,g.m33+g.m31),I[3].set(g.m03-g.m01,g.m13-g.m11,g.m23-g.m21,g.m33-g.m31),I[4].set(g.m03-g.m02,g.m13-g.m12,g.m23-g.m22,g.m33-g.m32),I[5].set(g.m03+g.m02,g.m13+g.m12,g.m23+g.m22,g.m33+g.m32),I.forEach((A=>A.normalizeInPlace()))}intersectsBox(A){const g=new Vec3,I=this.planes,{min:C,max:e}=A;for(let A=0;A<6;A++){const i=I[A];if(g.x=i.normal.x>0?e.x:C.x,g.y=i.normal.y>0?e.y:C.y,g.z=i.normal.z>0?e.z:C.z,i.distanceToPoint(g)<0)return!1}return!0}toJSON(){return{p0:this.planes[0].toJSON(),p1:this.planes[1].toJSON(),p2:this.planes[2].toJSON(),p3:this.planes[3].toJSON(),p4:this.planes[4].toJSON(),p5:this.planes[5].toJSON()}}fromJSON(A){this.planes[0].fromJSON(A.p0),this.planes[1].fromJSON(A.p1),this.planes[2].fromJSON(A.p2),this.planes[3].fromJSON(A.p3),this.planes[4].fromJSON(A.p4),this.planes[5].fromJSON(A.p5)}toString(){return StringFunctions.stringifyJSONWithFixedPrecision(this.toJSON())}}class RefCounted extends EventEmitter{#A;constructor(){if(super(),"RefCounted"==this.constructor.name)throw new Error("RefCounted should not be instantiated directly.");this.#A=[]}get refs(){return this.#A}numRefs(){return this.#A.length}addRef(A){if(!A)throw new Error("Error in RefCounted.addRef: Must provide a referer");return this.#A.push(A),!0}removeRef(A){if(!A)throw new Error("Error in RefCounted.removeRef: Must provide a referer");const g=this.#A.indexOf(A);if(-1==g)throw new Error("Error in RefCounted.removeRef: referer not found in refs list.");this.#A.splice(g,1),0==this.#A.length&&this.destroy()}destroy(){this.emit("destructing")}}let numBaseItems=0;class BaseItem extends EventEmitter{#g;#I=void 0;selected=!1;constructor(A=""){super(),this.#g=A,numBaseItems++}static getNumBaseItems(){return numBaseItems}get name(){return this.#g}set name(A){if(this.#g!=A){const g=this.#g;this.#g=A;const I=new NameChangedEvent(g,A);this.emit("nameChanged",I)}}get path(){return this.getPath()}get ownerItem(){return this.#I}getName(){return this.#g}setName(A){this.name=A}getPath(){return null==this.#I?[this.#g]:[...this.#I.getPath(),this.#g]}resolvePath(A,g=0){if(0==g&&("."!=A[0]&&A[0]!=this.#g||g++),".."==A[g]){if(this.#I)return this.#I.resolvePath(A,g+1);throw Error("this.#ownerItem is undefined")}if(g==A.length)return this}getOwner(){return this.#I}setOwner(A){this.#I=A}isSelected(){return this.selected}setSelected(A){this.selected=A;let g=new SelectedEvent(this.selected);this.emit("selectedChanged",g)}toJSON(A){return{type:this.getClassName(),name:this.#g}}fromJSON(A,g){A.name&&(this.#g=A.name)}readBinary(A,g){A.loadStr(),this.setName(A.loadStr())}toString(A){return JSON.stringify(this.toJSON(),null,2)}clone(A){throw new Error(this.constructor.name+" does not implement its clone method")}copyFrom(A,g){this.setName(A.getName())}}class ParameterOwner extends BaseItem{paramEventListenerIDs={};paramMapping={};params=[];deprecatedParamMapping={};constructor(A){super(A)}getNumParameters(){return this.params.length}get numParameters(){return this.params.length}getParameters(){return this.params}getParameterIndex(A){return this.paramMapping[A]}getParameterByIndex(A){return this.params[A]}hasParameter(A){return A in this.paramMapping}addParameterDeprecationMapping(A,g){this.deprecatedParamMapping[A]=g}getParameter(A){let g=this.paramMapping[A];if(null==g){const I=this.deprecatedParamMapping[A];if(!I)return null;console.warn(`Parameter name ${A} is now deprecated. Please use ${I} instead.`),g=this.paramMapping[I]}return this.params[g]}parameterValueChanged(A){this.emit("parameterValueChanged",A)}addParameter(A){return this.insertParameter(A,this.params.length)}insertParameter(A,g){const I=A.getName();null!=this.paramMapping[I]&&(console.warn("Replacing Parameter:"+I),this.removeParameter(I)),A.setOwner(this),this.paramEventListenerIDs[I]=A.on("valueChanged",(g=>{const I={param:A};for(const A in g)I[A]=g[A];this.parameterValueChanged(I)})),this.params.splice(g,0,A);for(let A=g;A<this.params.length;A++)this.paramMapping[this.params[A].getName()]=A;const C=new ParameterAddedEvent(I);return this.emit("parameterAdded",C),A}removeParameter(A){if(null==this.paramMapping[A])throw new Error("Unable to remove Parameter:"+A);const g=this.paramMapping[A];this.params[this.paramMapping[A]].off("valueChanged",this.paramEventListenerIDs[A]),this.params.splice(g,1),delete this.paramMapping[A];for(let A=g;A<this.params.length;A++)this.paramMapping[this.params[A].getName()]=A;const I=new ParameterRemovedEvent(A);this.emit("parameterRemoved",I)}replaceParameter(A){const g=A.getName();if(null==this.paramMapping[g])throw new Error("Unable to replace Parameter:"+g);const I=this.paramMapping[g];return this.removeParameter(g),this.insertParameter(A,I),A}resolvePath(A,g=0){if(0==g&&("."!=A[0]&&A[0]!=this.name||g++),".."==A[g]){if(this.ownerItem)return this.ownerItem.resolvePath(A,g+1);throw Error("this.ownerItem is undefined")}if(g==A.length)return this;const I=this.getParameter(A[g]);if(I)return g<A.length?I.resolvePath(A,g+1):I;throw new Error(`Unable to resolve path : [${A.toString()}] after: ${this.getName()} \nNo child or parameter called : "${A[g]}"`)}toJSON(A){const g=super.toJSON(A),I={};let C=0;for(const g of this.params){if(g.isDrivenByOperator())continue;const e=g.toJSON(A);e&&(I[g.getName()]=e,C++)}return C>0&&(g.params=I),g}fromJSON(A,g){if(super.fromJSON(A,g),A.params)for(const I in A.params){const C=A.params[I];if(C.paramPath)g?.resolvePath(C.paramPath,(A=>{this.replaceParameter(A)}),(()=>{console.warn("Unable to resolve shared parameter:"+C.paramPath)}));else{let A=this.getParameter(I);if(!A&&C.type&&C.name){if(A=Registry.constructClass(C.type),!A){console.error("Unable to construct prop:"+C.name+" of type:"+C.type);continue}A.setName(C.name),this.addParameter(A)}A&&A.fromJSON(C,g)}}}readBinary(A,g){super.readBinary(A,g),this.readBinaryParams(A,g)}readBinaryParams(A,g){if(g?.versions["zea-engine"].compare([0,0,3])>=0){const I=A.loadUInt32();for(let C=0;C<I;C++){const I=A.loadStr(),C=A.loadStr();let e=this.getParameter(C);if(!e){if(e=Registry.constructClass(I),!e){console.error("Unable to construct prop:"+C+" of type:"+I);continue}e.setName(C),this.addParameter(e)}e.readBinary(A,g)}}}clone(A){throw new Error(this.constructor.name+" does not implement its clone method")}copyFrom(A,g){if(!(A instanceof ParameterOwner))throw new Error("cannot copy from src");super.copyFrom(A,g);let I=A.getNumParameters();for(;I--;){const g=A.getParameterByIndex(I),C=this.getParameter(g.getName());C?C.copyFrom(g):this.addParameter(g.clone())}}}const getFileFolder=function(A){return A.substring(0,A.lastIndexOf("/"))+"/"},loadFile=function(A,g,I,C,e=void 0){try{const i=new XMLHttpRequest;i.responseType=g,i.addEventListener("timeout",(g=>{throw new Error("The request for "+A+" timed out.")})),i.addEventListener("error",(g=>{throw new Error("The request for "+A+": xhr.readyState:"+i.readyState)})),i.addEventListener("abort",(g=>{throw new Error("The request for "+A+": xhr.readyState:"+i.readyState)})),i.addEventListener("progress",(A=>{e&&e(A.total,A.loaded)})),i.addEventListener("loadend",(A=>{200==i.status?I(i):C(i.statusText)})),i.open("GET",A,!0),i.send()}catch(A){C(A)}},loadTextfile=function(A,g,I=void 0,C=void 0){loadFile(A,"text",(A=>{g(A.responseText)}),(g=>{if(null==I)throw new Error("Unable to XHR File:"+A);I(g)}),C)},loadJSONfile=function(A,g,I=void 0,C=void 0){loadFile(A,"json",(A=>{g(A.response,A)}),(g=>{if(null==I)throw new Error("Unable to XHR File:"+A);I(g)}),C)},loadXMLfile=function(A,g,I=void 0,C=void 0){loadFile(A,"document",(A=>{g(A.responseXML)}),(g=>{if(null==I)throw new Error("Unable to XHR File:"+A);I(g)}),C)},loadBinfile=function(A,g,I=void 0,C=void 0){loadFile(A,"arraybuffer",(A=>{g(A.response)}),(g=>{if(null==I)throw new Error("Unable to XHR File:"+A);I(g)}),C)};var unpackBase64Str="AGFzbQEAAAABrgIlYAF/AX5gA39/fwF/YAN/fn8AYAR/f39/AX9gAn9/AX9gAAF/YAJ/fwBgA39/fwBgAABgAX8Bf2AEf39/fwBgBn9/f39/fwBgBX9/f39/AGACf38BfGAFf39/f38Bf2AGf39/f39/AX9gCX9/f39/f39/fwF/YAh/f39/f35/fwF/YAJ+fgF/YAF/AGADf398AGAJf39/f39/f39/AGAKf39/f39/f39/fwBgAn9+AGAHf39/f39/fwF/YAp/f39/f39/f39/AX9gB39/f39/f38AYAt/f39/f39/f39/fwBgDX9/f39/f39/f39/f38AYAh/f39/f39/fwBgA39+fwF/YAN+f38Bf2ACfn8Bf2AGf3x/f39/AX9gAnx/AXxgA39/fwF8YAR/f398AAKID1cDZW52Bm1lbW9yeQIAgAIDZW52BXRhYmxlAXABvAK8AgNlbnYJdGFibGVCYXNlA38AA2Vudg5EWU5BTUlDVE9QX1BUUgN/AANlbnYIU1RBQ0tUT1ADfwADZW52BWFib3J0ABMDZW52DWVubGFyZ2VNZW1vcnkABQNlbnYOZ2V0VG90YWxNZW1vcnkABQNlbnYXYWJvcnRPbkNhbm5vdEdyb3dNZW1vcnkABQNlbnYIaW52b2tlX2kACQNlbnYJaW52b2tlX2lpAAQDZW52Cmludm9rZV9paWkAAQNlbnYLaW52b2tlX2lpaWkAAwNlbnYMaW52b2tlX2lpaWlpAA4DZW52Dmludm9rZV9paWlpaWlpABgDZW52EWludm9rZV9paWlpaWlpaWlpABkDZW52CGludm9rZV92ABMDZW52CWludm9rZV92aQAGA2VudgppbnZva2VfdmlpAAcDZW52C2ludm9rZV92aWlpAAoDZW52DGludm9rZV92aWlpaQAMA2Vudg1pbnZva2VfdmlpaWlpAAsDZW52Dmludm9rZV92aWlpaWlpABoDZW52EWludm9rZV92aWlpaWlpaWlpABYDZW52Emludm9rZV92aWlpaWlpaWlpaQAbA2VudhlfX19jeGFfYWxsb2NhdGVfZXhjZXB0aW9uAAkDZW52El9fX2N4YV9iZWdpbl9jYXRjaAAJA2VudhBfX19jeGFfZW5kX2NhdGNoAAgDZW52HF9fX2N4YV9maW5kX21hdGNoaW5nX2NhdGNoXzIABQNlbnYcX19fY3hhX2ZpbmRfbWF0Y2hpbmdfY2F0Y2hfMwAJA2VudhxfX19jeGFfZmluZF9tYXRjaGluZ19jYXRjaF80AAQDZW52FV9fX2N4YV9mcmVlX2V4Y2VwdGlvbgATA2VudgxfX19jeGFfdGhyb3cABwNlbnYHX19fbG9jawATA2VudgtfX19tYXBfZmlsZQAEA2VudhJfX19yZXN1bWVFeGNlcHRpb24AEwNlbnYLX19fc2V0RXJyTm8AEwNlbnYNX19fc3lzY2FsbDE0MAAEA2Vudg1fX19zeXNjYWxsMTQ1AAQDZW52DV9fX3N5c2NhbGwxNDYABANlbnYNX19fc3lzY2FsbDE4MwAEA2Vudg1fX19zeXNjYWxsMTk4AAQDZW52DF9fX3N5c2NhbGwyMAAEA2VudgtfX19zeXNjYWxsNgAEA2VudgxfX19zeXNjYWxsNjAABANlbnYMX19fc3lzY2FsbDgzAAQDZW52DF9fX3N5c2NhbGw5MQAEA2VudglfX191bmxvY2sAEwNlbnYeX19lbWJpbmRfZmluYWxpemVfdmFsdWVfb2JqZWN0ABMDZW52Fl9fZW1iaW5kX3JlZ2lzdGVyX2Jvb2wADANlbnYXX19lbWJpbmRfcmVnaXN0ZXJfY2xhc3MAHANlbnYjX19lbWJpbmRfcmVnaXN0ZXJfY2xhc3NfY29uc3RydWN0b3IACwNlbnYgX19lbWJpbmRfcmVnaXN0ZXJfY2xhc3NfZnVuY3Rpb24AHQNlbnYXX19lbWJpbmRfcmVnaXN0ZXJfZW12YWwABgNlbnYXX19lbWJpbmRfcmVnaXN0ZXJfZmxvYXQABwNlbnYZX19lbWJpbmRfcmVnaXN0ZXJfaW50ZWdlcgAMA2Vudh1fX2VtYmluZF9yZWdpc3Rlcl9tZW1vcnlfdmlldwAHA2VudhxfX2VtYmluZF9yZWdpc3Rlcl9zdGRfc3RyaW5nAAYDZW52HV9fZW1iaW5kX3JlZ2lzdGVyX3N0ZF93c3RyaW5nAAcDZW52Hl9fZW1iaW5kX3JlZ2lzdGVyX3ZhbHVlX29iamVjdAALA2VudiRfX2VtYmluZF9yZWdpc3Rlcl92YWx1ZV9vYmplY3RfZmllbGQAFgNlbnYWX19lbWJpbmRfcmVnaXN0ZXJfdm9pZAAGA2VudgZfYWJvcnQACANlbnYWX2Vtc2NyaXB0ZW5fbWVtY3B5X2JpZwABA2VudgdfZ2V0ZW52AAkDZW52CV9nZXRncm5hbQAJA2VudglfZ2V0cHduYW0ACQNlbnYIX2pzQ2xvc2UAEwNlbnYJX2pzQ3JlYXRlAAkDZW52B19qc09wZW4ACQNlbnYHX2pzUmVhZAABA2VudgdfanNTZWVrAAEDZW52CF9qc1dyaXRlAAEDZW52E19sbHZtX2VoX3R5cGVpZF9mb3IACQNlbnYKX2xvY2FsdGltZQAJA2VudgdfbWt0aW1lAAkDZW52FF9wdGhyZWFkX2dldHNwZWNpZmljAAkDZW52E19wdGhyZWFkX2tleV9jcmVhdGUABANlbnYNX3B0aHJlYWRfb25jZQAEA2VudhRfcHRocmVhZF9zZXRzcGVjaWZpYwAEA2VudgVfdGltZQAJA2VudhBpbnZva2VfaWlpaWlpamlpABkDZW52Cmludm9rZV9pamoADgNlbnYJaW52b2tlX2ppAAQDZW52Cmludm9rZV92aWoACgNlbnYLaW52b2tlX3ZpamkADANlbnYHX2pzVGVsbAAJA4QEggQTAQEGEwQJCRMGEwEBCQcAEwcGBwwJCgEEAQkGCQETCQkEBAQHBAETAQEJBxMHAwkGBhMIBgkTARMEBBMTAQEBIAkJExMGEwEDCQIEEwcEExMKBgEJDAsIBAwEBAEEBAcJBwkDChMGEAERDAAFCwwKBwMBBwEEBgEJAQEOAQkEABMAAQYHBBMTAQkTEwYTBhMJCgYMCgEABwcGBAcTBAQEAhcKDwQHBwoBExMTBQEDBAcJDgQECQEBAwQJASIJAQQJBAkGCQEBBwQHBBMBCQ4JBgMBEwYTAQwBBwcHBhMXBhMHBhMTEwkPBAkTEwQGFR0MBgYGBwkTCQkJAQEJAQAJBAoTCQkJEwYGBBMEAAIBARMMCgQOGRYVCBQSERIGEA4BDRsWGgsMCiQHBhMZGA8OAwEEIwkBCgwLBwETCQkIEwYICgwLCgwLAQgEBh0BAQkEBh0EBgYGCQMEBAEEAQEBAQEEBAQJAwMHBAEhIB8DAwQBBAQBBAkBBQEBCQQJEwgECQEEHhMDFA0FCgUHBBMFAQcEBg4MBRMJEwcIAwYPExMTBgcHBgMEAQYBBgMJCQYTBAYTBhMEBgQTARMTBh4GFw8BBwkDBgQDBwcBBAQGBgYBCQkGEwYGAwcTEwoTBhMTBwoGEwcGBwYTBwcTFQcHExMTBgkGBgQLEwQJBAMBEwgJBhoFfwEjAQt/ASMCC38BQQALfwFBAAt/AUEACweXBSUYX19HTE9CQUxfX3N1Yl9JX2JpbmRfY3BwANEDGl9fR0xPQkFMX19zdWJfSV9icmlkZ2VfY3BwAO0DF19fR0xPQkFMX19zdWJfSV9jcmNfY3BwANIEGl9fR0xPQkFMX19zdWJfSV9nbG9iYWxfY3BwAOoCEF9fX2N4YV9jYW5fY2F0Y2gAhwMWX19fY3hhX2lzX3BvaW50ZXJfdHlwZQCGAxFfX19lcnJub19sb2NhdGlvbgDKAw5fX19nZXRUeXBlTmFtZQDPAwVfZnJlZQBSB19tYWxsb2MAbAtkeW5DYWxsX2RpaQCFAwlkeW5DYWxsX2kAnwIKZHluQ2FsbF9paQCEAwtkeW5DYWxsX2lpaQCDAwxkeW5DYWxsX2lpaWkAggMNZHluQ2FsbF9paWlpaQCBAw5keW5DYWxsX2lpaWlpaQCAAw9keW5DYWxsX2lpaWlpaWkA/wISZHluQ2FsbF9paWlpaWlpaWlpAP4CEWR5bkNhbGxfaWlpaWlpamlpAOcCC2R5bkNhbGxfaWpqAOYCCmR5bkNhbGxfamkA5QIJZHluQ2FsbF92AP0CCmR5bkNhbGxfdmkA/AILZHluQ2FsbF92aWkA+wIMZHluQ2FsbF92aWlkAPoCDGR5bkNhbGxfdmlpaQD5Ag1keW5DYWxsX3ZpaWlpAPgCDmR5bkNhbGxfdmlpaWlpAPcCD2R5bkNhbGxfdmlpaWlpaQD2AhJkeW5DYWxsX3ZpaWlpaWlpaWkA9QITZHluQ2FsbF92aWlpaWlpaWlpaQD0AgtkeW5DYWxsX3ZpagDkAgxkeW5DYWxsX3ZpamkA4wILc2V0VGVtcFJldDAA3AIIc2V0VGhyZXcA7wIKc3RhY2tBbGxvYwDTBAnKBAEAIwALvALzAtoDvgHoA+ED3QPbA/4BvgG+AYEBzQOPA44DX8YEfKkD0wOlBM0EuwKmAcoCywK4ApYC0QKWArIBcVjqA58CxwKBAYEBgQGBAYEBgQGBAaoB8QHdAu8BvgJqc5kE0gLbAs4E8AHMBLoCyQTSA9UD5APXAd8DnAKaAtcBnAKaAtcBuwOiA5wDqgGqAaoB8gLhAuACmALUAcwDywPJA7wDmgP6AYwD+gGeAmmuAW97epkBzwK6AcwCqgKUBKME1ANe4gOJAsQBrwOAAcMBtQGXBO4DmgT+A9gDzwSAAYABgAGAAYABgAGAAfEC5gP1AbkCkwT1AfACuQHtArsB7ALuAr0B3gLTAWHQAtEBvQG9AakBmwOFAZMDFqkBqQGpAWJ+4gJw1wO3AYgBtwG3AYgBtwGIAfwB+wH7AYgBiAGIAYgB8gNW2AK3Ar4EvQLEBLYC8wPUAssEogGvArIEpwTSAZYBtgSLBPED6QPgAyudAp0CPpEDYmJiYmJiYmJiYmJiYmJiYmJihgHaApgEpgLvA5EEyAGiAvQDxQRkyATHBJcBW6AEVeQB5QPVAaMDpgOdA6cDqAOCAYYBhgGGAYYBhgGGAesC2QN/6gFgwQSsAvYD9QPABOwDfb0EvASVBLkEZeMD1gHeA5sCmQLWAZsCmQLWARt/f39/f39/9AGXA5QDiAPcA9MCtAT0AbwBmAOVA4kDqQLnA7wBvAGoAZkDlgOKA8oEqAGoAagB6QK/BOgCN/MBsAKSBPMB8gHfApwB8gEK7IsNggToDQEIfyAARQRADwtB0LcDKAIAIQIgAEF4aiIEIABBfGooAgAiAEF4cSIBaiEGAn8gAEEBcQR/IAQiAAUgBCgCACEDIABBA3FFBEAPCyAEIANrIgAgAkkEQA8LIAMgAWohAUHUtwMoAgAgAEYEQCAAIAZBBGoiAigCACIEQQNxQQNHDQIaQci3AyABNgIAIAIgBEF+cTYCACAAIAFBAXI2AgQgACABaiABNgIADwsgA0EDdiEEIANBgAJJBEAgACgCDCIDIAAoAggiAkYEQEHAtwNBwLcDKAIAQQEgBHRBf3NxNgIABSACIAM2AgwgAyACNgIICyAADAILIAAoAhghBwJAIAAoAgwiBCAARgRAIABBEGoiA0EEaiICKAIAIgRFBEAgAygCACIEBEAgAyECBUEAIQQMAwsLA0AgBEEUaiIFKAIAIgMEQCADIQQgBSECDAELIARBEGoiBSgCACIDBEAgAyEEIAUhAgwBCwsgAkEANgIABSAAKAIIIgIgBDYCDCAEIAI2AggLCyAHBH8gACgCHCIDQQJ0QfC5A2oiAigCACAARgRAIAIgBDYCACAERQRAQcS3A0HEtwMoAgBBASADdEF/c3E2AgAgAAwECwUgB0EQaiAHKAIQIABHQQJ0aiAENgIAIAAgBEUNAxoLIAQgBzYCGCAAQRBqIgIoAgAiAwRAIAQgAzYCECADIAQ2AhgLIAIoAgQiAgRAIAQgAjYCFCACIAQ2AhgLIAAFIAALCwsiBCAGTwRADwsgBkEEaiICKAIAIgNBAXFFBEAPCyADQQJxBEAgAiADQX5xNgIAIAAgAUEBcjYCBCAEIAFqIAE2AgAgASEEBUHYtwMoAgAgBkYEQEHMtwNBzLcDKAIAIAFqIgE2AgBB2LcDIAA2AgAgACABQQFyNgIEIABB1LcDKAIARwRADwtB1LcDQQA2AgBByLcDQQA2AgAPC0HUtwMoAgAgBkYEQEHItwNByLcDKAIAIAFqIgE2AgBB1LcDIAQ2AgAgACABQQFyNgIEIAQgAWogATYCAA8LIANBeHEgAWohByADQQN2IQECQCADQYACSQRAIAYoAgwiAyAGKAIIIgJGBEBBwLcDQcC3AygCAEEBIAF0QX9zcTYCAAUgAiADNgIMIAMgAjYCCAsFIAYoAhghCAJAIAYoAgwiASAGRgRAIAZBEGoiA0EEaiICKAIAIgFFBEAgAygCACIBBEAgAyECBUEAIQEMAwsLA0AgAUEUaiIFKAIAIgMEQCADIQEgBSECDAELIAFBEGoiBSgCACIDBEAgAyEBIAUhAgwBCwsgAkEANgIABSAGKAIIIgIgATYCDCABIAI2AggLCyAIBEAgBigCHCIDQQJ0QfC5A2oiAigCACAGRgRAIAIgATYCACABRQRAQcS3A0HEtwMoAgBBASADdEF/c3E2AgAMBAsFIAhBEGogCCgCECAGR0ECdGogATYCACABRQ0DCyABIAg2AhggBkEQaiICKAIAIgMEQCABIAM2AhAgAyABNgIYCyACKAIEIgIEQCABIAI2AhQgAiABNgIYCwsLCyAAIAdBAXI2AgQgBCAHaiAHNgIAIABB1LcDKAIARgRAQci3AyAHNgIADwUgByEECwsgBEEDdiEBIARBgAJJBEAgAUEDdEHotwNqIQJBwLcDKAIAIgRBASABdCIBcQR/IAJBCGoiASgCAAVBwLcDIAQgAXI2AgAgAkEIaiEBIAILIQQgASAANgIAIAQgADYCDCAAIAQ2AgggACACNgIMDwsgBEEIdiIBBH8gBEH///8HSwR/QR8FIARBDiABIAFBgP4/akEQdkEIcSIDdCICQYDgH2pBEHZBBHEiASADciACIAF0IgJBgIAPakEQdkECcSIBcmsgAiABdEEPdmoiAUEHanZBAXEgAUEBdHILBUEACyIFQQJ0QfC5A2ohAyAAIAU2AhwgAEEANgIUIABBADYCEAJAQcS3AygCACICQQEgBXQiAXEEQCADKAIAIQFBGSAFQQF2ayECIAQgBUEfRgR/QQAFIAILdCEFAkADQCABKAIEQXhxIARGDQEgBUEBdCEDIAFBEGogBUEfdkECdGoiBSgCACICBEAgAyEFIAIhAQwBCwsgBSAANgIAIAAgATYCGCAAIAA2AgwgACAANgIIDAILIAFBCGoiAigCACIEIAA2AgwgAiAANgIAIAAgBDYCCCAAIAE2AgwgAEEANgIYBUHEtwMgAiABcjYCACADIAA2AgAgACADNgIYIAAgADYCDCAAIAA2AggLC0HgtwNB4LcDKAIAQX9qIgA2AgAgAARADwVBiLsDIQALA0AgACgCACIBQQhqIQAgAQ0AC0HgtwNBfzYCAAvDAwEDfyACQYDAAE4EQCAAIAEgAhA6DwsgACEEIAAgAmohAyAAQQNxIAFBA3FGBEADQCAAQQNxBEAgAkUEQCAEDwsgACABLAAAOgAAIABBAWohACABQQFqIQEgAkEBayECDAELCyADQXxxIgJBQGohBQNAIAAgBUwEQCAAIAEoAgA2AgAgACABKAIENgIEIAAgASgCCDYCCCAAIAEoAgw2AgwgACABKAIQNgIQIAAgASgCFDYCFCAAIAEoAhg2AhggACABKAIcNgIcIAAgASgCIDYCICAAIAEoAiQ2AiQgACABKAIoNgIoIAAgASgCLDYCLCAAIAEoAjA2AjAgACABKAI0NgI0IAAgASgCODYCOCAAIAEoAjw2AjwgAEFAayEAIAFBQGshAQwBCwsDQCAAIAJIBEAgACABKAIANgIAIABBBGohACABQQRqIQEMAQsLBSADQQRrIQIDQCAAIAJIBEAgACABLAAAOgAAIAAgASwAAToAASAAIAEsAAI6AAIgACABLAADOgADIABBBGohACABQQRqIQEMAQsLCwNAIAAgA0gEQCAAIAEsAAA6AAAgAEEBaiEAIAFBAWohAQwBCwsgBAuYAgEEfyAAIAJqIQQgAUH/AXEhASACQcMATgRAA0AgAEEDcQRAIAAgAToAACAAQQFqIQAMAQsLIARBfHEiBUFAaiEGIAEgAUEIdHIgAUEQdHIgAUEYdHIhAwNAIAAgBkwEQCAAIAM2AgAgACADNgIEIAAgAzYCCCAAIAM2AgwgACADNgIQIAAgAzYCFCAAIAM2AhggACADNgIcIAAgAzYCICAAIAM2AiQgACADNgIoIAAgAzYCLCAAIAM2AjAgACADNgI0IAAgAzYCOCAAIAM2AjwgAEFAayEADAELCwNAIAAgBUgEQCAAIAM2AgAgAEEEaiEADAELCwsDQCAAIARIBEAgACABOgAAIABBAWohAAwBCwsgBCACawsrAQF/IAAgAEEEaiICKAIAIAFqIgFBA3YgACgCAGo2AgAgAiABQQdxNgIAC2kBAX8jBCEBIwRB0ABqJAQgAUFAa0EANgIAIAFBADYCRCABQQc2AkggAEEINgIAIABBBGoiASABKAIAQQFqNgIAIABBCDYCACABIAEoAgBBAWo2AgBBBBAUIgBBCDYCACAAQYAIQQAQGwuQAQECfyAARQRAIAEQbA8LIAFBv39LBEBBiLwDQQw2AgBBAA8LIAFBC2pBeHEhAiAAQXhqIAFBC0kEf0EQBSACCxDOAyICBEAgAkEIag8LIAEQbCICRQRAQQAPCyACIAAgAEF8aigCACIDQXhxIANBA3EEf0EEBUEIC2siAyABSQR/IAMFIAELEFMaIAAQUiACC0IBAn8gACgCDCIBIAAoAgAiAkEBamotAABBCHQgASACai0AAEEQdHIgASACQQJqai0AAHJBCCAAKAIEa3ZB//8DcQsoAQJ/IAAhAQNAIAFBBGohAiABKAIABEAgAiEBDAELCyABIABrQQJ1CwoAIAAQFRoQkAMLJAEBfyABRQRADwsDQCAAIAJqQQA6AAAgAkEBaiICIAFHDQALCyYBAX8gAEEAOgCABANAIAAgAWpBADoAACABQQFqIgFBgARHDQALC10BAX8gASAASCAAIAEgAmpIcQRAIAEgAmohASAAIgMgAmohAANAIAJBAEoEQCACQQFrIQIgAEEBayIAIAFBAWsiASwAADoAAAwBCwsgAyEABSAAIAEgAhBTGgsgAAuPBQIQfwN+IAJBcHEhBCABIQUgAEG1AWoiCSwAAEUEQCACIQQLIABBLGohDSAAQSBqIQogAEHRAGohDiAAQThqIQ8gAEGQAWohECAAQfAAaiELIABBzABqIREgAEEIaiESIABBBGohDAJAAkADQCAERQRAIAMhAgwCCyANKAIAIQcgACwAAARAIAEgEigCACAMKAIAEFMaIAwoAgAhAiAMQQA2AgAFIAopAwAiEyAErVMhCCATpyECIAgEfyACBSAEIgILBEAgDiwAAARAIAksAAAEQCACIAIgBmpBD3FrIgNBAEoEQCADIQILIAhFBEAgBCECCwsLIAcoAgRFDQQgByAFIAIgBygCACgCDEEfcUHKAGoRAQAhAiAHQbCnAWohCCAPKAIAIgMEfyADBSAIC0GJwQBqLAAABEAgECAFIAIQqwILBSADIQILCyALIAspAwAgAqwiE3w3AwAgAiAGaiEGIAogCikDACATfSITNwMAIBNCAFEgDiwAAEEAR3FFDQEgAgRAIAZBD3FFIAksAABFcg0CCyAFIAJqIQUgBCACayEEIAcgAEEBIBEoAgAQtQEEQCACIQMMAQsLIABBAToAUkF/DwsgDSgCACIDBEAgCykDACADQYi8A2opAwB8IRQgACwAKARAIAApA1ghFSAAKQOIASITQgBRBEAgFSETBSAAKQOAASAUfCEUCyADQazzAGooAgAhAyATIBRTBH9B5AAFIBNCAFEEf0EABSAUQuQAfiATf6cLCyEFIANBzIQDaiwAAEUEQCAFIABByABqIgMoAgBHBEAgAyAFNgIACwsLCyACQX9GBEBBfyEGBSAJLAAABEAgACgCRCABIAYQ6gELCxCFASAGDwtBfwtiAQF/IABFBEBBASEACwJAAkACQANAIAAQbCIBDQJBsLwDQbC8AygCACIBNgIAIAFFDQEgAUEHcUGOAWoRCAAMAAsAC0EEEBQiAEHEJTYCACAAQdgKQQoQGwwBCyABDwtBAAtTAQF/IwQhACMEQeAgaiQEIABBgCBqIgMgAjYCACAAQYAIIAEgAxCAAhogAEGQIGoiAUEANgJEIAFBATYCSCABQUBrQQE2AgAgASAANgIAIAAkBAt6AgV/AX4gAEEYaiIDKAIAIgEgACgCFCIETwRAQgAPCyAAKAIAIQUgASEAAkADQCADIABBAWoiATYCACAFIABqLQAAIgBB/wBxrSACrYYgBnwhBiAAQYABcUUNASACQQdqIQIgASAESQRAIAEhAAwBBUIAIQYLCwsgBgsGAEENEAALGAAgACgCAEEgcUUEQCABIAIgABCNAhoLC+4CAQF/AkACQAJAAkACQCABQQFrDv8BAAIBAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAwsgACgCAEUEQCAAIAE2AgALDAMLIAAoAgBBC0cEQCAAQQM2AgALDAILIAAoAgBBAkkEQCAAQQI2AgALDAELIAAgATYCAAsgAEEEaiICIAIoAgBBAWo2AgALrgIBAn8gACgCLEGs8wBqKAIAIgNBpMsEaigCAARAIANBsMsEaigCACIEBEBBASADQazLBGooAgAgASACIARBD3FB6gBqEQMAQX9GBEBBrPUCQf8BEKQBCwsgA0G4ywRqKAIAIgMEQCABIAIgA0EfcUEqahEEAEUEQEGs9QJB/wEQpAELCwsgACABNgIcIAAgAjYCGCAALAAMBEAgAEEQaiIDKAIAIAJPBEAgAEEUaiIEKAIAIAEgAhBTGiAEIAQoAgAgAmo2AgAgAyADKAIAIAJrNgIACwUgACwAKUUEQAJ/IAAoAjAhA0EBIAJFDQAaIAMoAgQgASACEEMLGgsLIABB+ABqIgMgAykDACACrXw3AwAgACwAKgRAEIUBDwsgAEGoAWogASACEKsCEIUBC4ABAQF/IwQhBSMEQYACaiQEIAIgA0ogBEGAwARxRXEEQCAFIAFBGHRBGHUgAiADayIBQYACSQR/IAEFQYACCxBUGiABQf8BSwRAIAIgA2shAgNAIAAgBUGAAhBjIAFBgH5qIgFB/wFLDQALIAJB/wFxIQELIAAgBSABEGMLIAUkBAsrACAAQf8BcUEYdCAAQQh1Qf8BcUEQdHIgAEEQdUH/AXFBCHRyIABBGHZyC40JARB/IwQhByMEQYABaiQEIAIgAzYCACAHQUBrIgRCADcCACAEQgA3AgggBEIANwIQIARCADcCGCAEQgA3AiAgBEIANwIoIARCADcCMCAEQgA3AjggA0UiEwR/IARBJGohECAEQShqIRFBAAVBACEAA0AgBCABIABqLAAAQQ9xQQJ0aiIFIAUoAgBBAWo2AgAgAEEBaiIAIANHDQALIARBJGoiACEQIARBKGoiCiERIAQoAgghBiAEKAIMIQggBCgCECEJIAQoAhQhCyAEKAIYIQwgBCgCHCENIAQoAiAhDiAAKAIAIRIgCigCACEKIAQoAgQLIQUgBEEANgIAIAJBiBlqQQAgA0EBdBBUGiACQcQAaiIAQQA2AgAgAkEANgIEIAIgBUEPdDYCCCACQQA2AkggAiAGIAVBAXRqIg9BDnQ2AgwgAiAFNgJMIAIgCCAPQQF0aiIPQQ10NgIQIAIgBiAFaiIFNgJQIAIgCSAPQQF0aiIGQQx0NgIUIAIgCCAFaiIFNgJUIAIgCyAGQQF0aiIGQQt0NgIYIAIgCSAFaiIFNgJYIAIgDCAGQQF0aiIGQQp0NgIcIAIgCyAFaiIFNgJcIAIgDSAGQQF0aiIGQQl0NgIgIAIgDCAFaiIFNgJgIAIgDiAGQQF0aiIGQQh0NgIkIAIgDSAFaiIFNgJkIAIgEiAGQQF0aiIGQQd0NgIoIAIgDiAFaiIFNgJoIAIgCiAGQQF0aiIGQQZ0NgIsIAIgECgCACAFaiIFNgJsIAIgBCgCLCIIIAZBAXRqIgZBBXQ2AjAgAiARKAIAIAVqIgU2AnAgAiAEKAIwIgkgBkEBdGoiBkEEdDYCNCACIAggBWoiBTYCdCACIAQoAjQiCCAGQQF0aiIGQQN0NgI4IAIgCSAFaiIFNgJ4IAIgBCgCOCIJIAZBAXRqIgZBAnQ2AjwgAiAIIAVqIgU2AnwgAkFAayAEKAI8IAZBAXRqQQF0NgIAIAIgCSAFajYCgAEgByAAKQIANwIAIAcgACkCCDcCCCAHIAApAhA3AhAgByAAKQIYNwIYIAcgACkCIDcCICAHIAApAig3AiggByAAKQIwNwIwIAcgACkCODcCOAJAAkAgEw0AQQAhAANAIAEgAGosAABBD3EiBARAIAJBiBlqIAcgBEECdGoiBCgCACIFQQF0aiAAOwEAIAQgBUEBajYCAAsgAEEBaiIAIANHDQALAkACQAJAIANBqgJrDgkAAAEBAQEBAQABC0EKIQQMAQsMAQsMAQtBByEECyACQYQBaiIFIAQ2AgBBASAEdCEGQQAhAUEBIQADQCABQRAgBGt0IQQCQCAAQRBJBEADQCAEIAJBBGogAEECdGooAgBJDQIgAEEBaiIAQRBJDQBBECEACwsLIAJBiAFqIAFqIAA6AAAgAkGICWogAUEBdGogBCACIABBAnRqKAIAa0EQIABrdiACQcQAaiAAQQJ0aigCAGoiBCADSQR/IAJBiBlqIARBAXRqLgEABUEACyIEOwEAIAFBAWoiASAGSQRAIAUoAgAhBAwBCwsgByQEC6cDAQZ/IwQhAyMEQRBqJAQgA0EIaiEEIAFBADoAAAJAIABB/v8DEHQEQEGsIygCACgCAAR/QQQFQQELIAJGBEBBASEEBUEBIQQDQAJAAkACQANAAkAgACAHQQJ0aigCACIFQf7/A0gNAiAFQf7/A2sNACAHQQFqIQcgBiACQawjKAIAKAIABH9BBAVBAQtrSQ0BDAgLCwwBCyAFRQ0BCyAHQQFqIQcgBUGAf3FBgMEDRgR/IAEgBmogBToAACAGQQFqBSADQgA3AwAgASAGaiIIIAUgAxCRAUF/RgRAQQAhBAsgA0IANwMAIAhBrCMoAgAoAgAEf0EEBUEBCyADEIgCIgVBAUoEfyAFBUEBCyAGagsiBiACQawjKAIAKAIABH9BBAVBAQtrSQ0BDAQLCyABIAZqQQA6AAALBSADQgA3AwAgBCAANgIAAn8CQAJAAkAgASAEIAIgAxC4A0F/aw4CAAECC0EADAILIAAoAgBFDAELQQELIQQLCyACRQRAIAMkBCAEQf8BcUEARw8LIAEgAkF/ampBADoAACADJAQgBEH/AXFBAEcLNgEDfyAAIQIDQCABQQRqIQMgAkEEaiEEIAIgASgCACIBNgIAIAEEQCAEIQIgAyEBDAELCyAAC1ABAn8CfyACBH8DQCAALAAAIgMgASwAACIERgRAIABBAWohACABQQFqIQFBACACQX9qIgJFDQMaDAELCyADQf8BcSAEQf8BcWsFQQALCyIAC443AQx/AkACQAJAIwQhASMEQRBqJAQgASEKAkAgAEH1AUkEQCAAQQtqQXhxIQJBwLcDKAIAIgYgAEELSQR/QRAiAgUgAgtBA3YiAHYiAUEDcQRAIAFBAXFBAXMgAGoiAEEDdEHotwNqIgFBCGoiBSgCACICQQhqIgQoAgAiAyABRgRAQcC3AyAGQQEgAHRBf3NxNgIABSADIAE2AgwgBSADNgIACyACIABBA3QiAEEDcjYCBCACIABqQQRqIgAgACgCAEEBcjYCACAKJAQgBA8LIAJByLcDKAIAIghLBEAgAQRAIAEgAHRBAiAAdCIAQQAgAGtycSIAQQAgAGtxQX9qIgFBDHZBEHEhACABIAB2IgFBBXZBCHEiAyAAciABIAN2IgBBAnZBBHEiAXIgACABdiIAQQF2QQJxIgFyIAAgAXYiAEEBdkEBcSIBciAAIAF2aiIDQQN0Qei3A2oiAEEIaiIEKAIAIgFBCGoiBygCACIFIABGBEBBwLcDIAZBASADdEF/c3EiADYCAAUgBSAANgIMIAQgBTYCACAGIQALIAEgAkEDcjYCBCABIAJqIgQgA0EDdCIDIAJrIgVBAXI2AgQgASADaiAFNgIAIAgEQEHUtwMoAgAhAyAIQQN2IgJBA3RB6LcDaiEBIABBASACdCICcQR/IAFBCGoiAigCAAVBwLcDIAAgAnI2AgAgAUEIaiECIAELIQAgAiADNgIAIAAgAzYCDCADIAA2AgggAyABNgIMC0HItwMgBTYCAEHUtwMgBDYCACAKJAQgBw8LQcS3AygCACIMBEAgDEEAIAxrcUF/aiIBQQx2QRBxIQAgASAAdiIBQQV2QQhxIgMgAHIgASADdiIAQQJ2QQRxIgFyIAAgAXYiAEEBdkECcSIBciAAIAF2IgBBAXZBAXEiAXIgACABdmpBAnRB8LkDaigCACIDKAIEQXhxIAJrIQEgA0EQaiADKAIQRUECdGooAgAiAARAA0AgACgCBEF4cSACayIFIAFJIgQEQCAFIQELIAQEQCAAIQMLIABBEGogACgCEEVBAnRqKAIAIgANACABIQULBSABIQULIAMgAmoiCyADSwRAIAMoAhghCQJAIAMoAgwiACADRgRAIANBFGoiASgCACIARQRAIANBEGoiASgCACIARQRAQQAhAAwDCwsDQCAAQRRqIgQoAgAiBwRAIAchACAEIQEMAQsgAEEQaiIEKAIAIgcEQCAHIQAgBCEBDAELCyABQQA2AgAFIAMoAggiASAANgIMIAAgATYCCAsLAkAgCQRAIAMgAygCHCIBQQJ0QfC5A2oiBCgCAEYEQCAEIAA2AgAgAEUEQEHEtwMgDEEBIAF0QX9zcTYCAAwDCwUgCUEQaiAJKAIQIANHQQJ0aiAANgIAIABFDQILIAAgCTYCGCADKAIQIgEEQCAAIAE2AhAgASAANgIYCyADKAIUIgEEQCAAIAE2AhQgASAANgIYCwsLIAVBEEkEQCADIAUgAmoiAEEDcjYCBCADIABqQQRqIgAgACgCAEEBcjYCAAUgAyACQQNyNgIEIAsgBUEBcjYCBCALIAVqIAU2AgAgCARAQdS3AygCACEEIAhBA3YiAUEDdEHotwNqIQAgBkEBIAF0IgFxBH8gAEEIaiICKAIABUHAtwMgBiABcjYCACAAQQhqIQIgAAshASACIAQ2AgAgASAENgIMIAQgATYCCCAEIAA2AgwLQci3AyAFNgIAQdS3AyALNgIACyAKJAQgA0EIag8FIAIhAAsFIAIhAAsFIAIhAAsFIABBv39LBEBBfyEABSAAQQtqIgBBeHEhA0HEtwMoAgAiBQRAIABBCHYiAAR/IANB////B0sEf0EfBSADQQ4gACAAQYD+P2pBEHZBCHEiAHQiAUGA4B9qQRB2QQRxIgIgAHIgASACdCIAQYCAD2pBEHZBAnEiAXJrIAAgAXRBD3ZqIgBBB2p2QQFxIABBAXRyCwVBAAshCEEAIANrIQICQAJAIAhBAnRB8LkDaigCACIABEBBGSAIQQF2ayEEQQAhASADIAhBH0YEf0EABSAEC3QhB0EAIQQDQCAAKAIEQXhxIANrIgYgAkkEQCAGBEAgACEBIAYhAgVBACECIAAhAQwECwsgACgCFCIGRSAGIABBEGogB0EfdkECdGooAgAiAEZyRQRAIAYhBAsgByAARSIGQQFzdCEHIAZFDQALBUEAIQELIAQgAXIEfyAEBSAFQQIgCHQiAEEAIABrcnEiAEUEQCADIQAMBwsgAEEAIABrcUF/aiIEQQx2QRBxIQBBACEBIAQgAHYiBEEFdkEIcSIHIAByIAQgB3YiAEECdkEEcSIEciAAIAR2IgBBAXZBAnEiBHIgACAEdiIAQQF2QQFxIgRyIAAgBHZqQQJ0QfC5A2ooAgALIgANACABIQQMAQsDQCAAKAIEQXhxIANrIgQgAkkiBwRAIAQhAgsgBwRAIAAhAQsgAEEQaiAAKAIQRUECdGooAgAiAA0AIAEhBAsLIAQEQCACQci3AygCACADa0kEQCAEIANqIgggBE0NBiAEKAIYIQkCQCAEKAIMIgAgBEYEQCAEQRRqIgEoAgAiAEUEQCAEQRBqIgEoAgAiAEUEQEEAIQAMAwsLA0AgAEEUaiIHKAIAIgYEQCAGIQAgByEBDAELIABBEGoiBygCACIGBEAgBiEAIAchAQwBCwsgAUEANgIABSAEKAIIIgEgADYCDCAAIAE2AggLCwJAIAkEQCAEIAQoAhwiAUECdEHwuQNqIgcoAgBGBEAgByAANgIAIABFBEBBxLcDIAVBASABdEF/c3EiADYCAAwDCwUgCUEQaiAJKAIQIARHQQJ0aiAANgIAIABFBEAgBSEADAMLCyAAIAk2AhggBCgCECIBBEAgACABNgIQIAEgADYCGAsgBCgCFCIBBEAgACABNgIUIAEgADYCGAsLIAUhAAsCQCACQRBJBEAgBCACIANqIgBBA3I2AgQgBCAAakEEaiIAIAAoAgBBAXI2AgAFIAQgA0EDcjYCBCAIIAJBAXI2AgQgCCACaiACNgIAIAJBA3YhASACQYACSQRAIAFBA3RB6LcDaiEAQcC3AygCACICQQEgAXQiAXEEfyAAQQhqIgIoAgAFQcC3AyACIAFyNgIAIABBCGohAiAACyEBIAIgCDYCACABIAg2AgwgCCABNgIIIAggADYCDAwCCyACQQh2IgEEfyACQf///wdLBH9BHwUgAkEOIAEgAUGA/j9qQRB2QQhxIgF0IgNBgOAfakEQdkEEcSIFIAFyIAMgBXQiAUGAgA9qQRB2QQJxIgNyayABIAN0QQ92aiIBQQdqdkEBcSABQQF0cgsFQQALIgFBAnRB8LkDaiEDIAggATYCHCAIQRBqIgVBADYCBCAFQQA2AgAgAEEBIAF0IgVxRQRAQcS3AyAAIAVyNgIAIAMgCDYCACAIIAM2AhggCCAINgIMIAggCDYCCAwCCyADKAIAIQBBGSABQQF2ayEDIAIgAUEfRgR/QQAFIAMLdCEBAkADQCAAKAIEQXhxIAJGDQEgAUEBdCEDIABBEGogAUEfdkECdGoiASgCACIFBEAgAyEBIAUhAAwBCwsgASAINgIAIAggADYCGCAIIAg2AgwgCCAINgIIDAILIABBCGoiASgCACICIAg2AgwgASAINgIAIAggAjYCCCAIIAA2AgwgCEEANgIYCwsgCiQEIARBCGoPBSADIQALBSADIQALBSADIQALCwsLQci3AygCACICIABPBEBB1LcDKAIAIQEgAiAAayIDQQ9LBEBB1LcDIAEgAGoiBTYCAEHItwMgAzYCACAFIANBAXI2AgQgASACaiADNgIAIAEgAEEDcjYCBAVByLcDQQA2AgBB1LcDQQA2AgAgASACQQNyNgIEIAEgAmpBBGoiACAAKAIAQQFyNgIACwwDC0HMtwMoAgAiAiAASwRAQcy3AyACIABrIgI2AgAMAgtBmLsDKAIABH9BoLsDKAIABUGguwNBgCA2AgBBnLsDQYAgNgIAQaS7A0F/NgIAQai7A0F/NgIAQay7A0EANgIAQfy6A0EANgIAQZi7AyAKQXBxQdiq1aoFczYCAEGAIAsiASAAQS9qIgRqIgdBACABayIGcSIFIABNDQBB+LoDKAIAIgEEQEHwugMoAgAiAyAFaiIIIANNIAggAUtyDQELIABBMGohCAJAAkBB/LoDKAIAQQRxBEBBACECBQJAAkACQEHYtwMoAgAiAUUNAEGAuwMhAwNAAkAgAygCACIJIAFNBEAgCSADQQRqIgkoAgBqIAFLDQELIAMoAggiAw0BDAILCyAHIAJrIAZxIgJB/////wdJBEAgAhCHASIBIAMoAgAgCSgCAGpGBEAgAUF/Rw0GBQwDCwVBACECCwwCC0EAEIcBIgFBf0YEQEEAIQIFQZy7AygCACICQX9qIgMgAWpBACACa3EgAWshAiADIAFxBH8gAgVBAAsgBWoiAkHwugMoAgAiB2ohAyACIABLIAJB/////wdJcQRAQfi6AygCACIGBEAgAyAHTSADIAZLcgRAQQAhAgwFCwsgAhCHASIDIAFGDQUgAyEBDAIFQQAhAgsLDAELIAggAksgAkH/////B0kgAUF/R3FxRQRAIAFBf0YEQEEAIQIMAgUMBAsACyAEIAJrQaC7AygCACIDakEAIANrcSIDQf////8HTw0CQQAgAmshBCADEIcBQX9GBEAgBBCHARpBACECBSADIAJqIQIMAwsLQfy6A0H8ugMoAgBBBHI2AgALIAVB/////wdJBEAgBRCHASIBQQAQhwEiA0kgAUF/RyADQX9HcXEhBSADIAFrIgMgAEEoaksiBARAIAMhAgsgAUF/RiAEQQFzciAFQQFzckUNAQsMAQtB8LoDQfC6AygCACACaiIDNgIAIANB9LoDKAIASwRAQfS6AyADNgIACwJAQdi3AygCACIEBEBBgLsDIQMCQAJAA0AgASADKAIAIgUgA0EEaiIHKAIAIgZqRg0BIAMoAggiAw0ACwwBCyADKAIMQQhxRQRAIAEgBEsgBSAETXEEQCAHIAYgAmo2AgBBzLcDKAIAIAJqIQJBACAEQQhqIgNrQQdxIQFB2LcDIAQgA0EHcQR/IAEFQQAiAQtqIgM2AgBBzLcDIAIgAWsiATYCACADIAFBAXI2AgQgBCACakEoNgIEQdy3A0GouwMoAgA2AgAMBAsLCyABQdC3AygCAEkEQEHQtwMgATYCAAsgASACaiEFQYC7AyEDAkACQANAIAMoAgAgBUYNASADKAIIIgMNAEGAuwMhAwsMAQsgAygCDEEIcQRAQYC7AyEDBSADIAE2AgAgA0EEaiIDIAMoAgAgAmo2AgBBACABQQhqIgJrQQdxIQNBACAFQQhqIgdrQQdxIQkgASACQQdxBH8gAwVBAAtqIgggAGohBiAFIAdBB3EEfyAJBUEAC2oiBSAIayAAayEHIAggAEEDcjYCBAJAIAQgBUYEQEHMtwNBzLcDKAIAIAdqIgA2AgBB2LcDIAY2AgAgBiAAQQFyNgIEBUHUtwMoAgAgBUYEQEHItwNByLcDKAIAIAdqIgA2AgBB1LcDIAY2AgAgBiAAQQFyNgIEIAYgAGogADYCAAwCCyAFKAIEIgBBA3FBAUYEfyAAQXhxIQkgAEEDdiECAkAgAEGAAkkEQCAFKAIMIgAgBSgCCCIBRgRAQcC3A0HAtwMoAgBBASACdEF/c3E2AgAFIAEgADYCDCAAIAE2AggLBSAFKAIYIQQCQCAFKAIMIgAgBUYEQCAFQRBqIgFBBGoiAigCACIABEAgAiEBBSABKAIAIgBFBEBBACEADAMLCwNAIABBFGoiAigCACIDBEAgAyEAIAIhAQwBCyAAQRBqIgIoAgAiAwRAIAMhACACIQEMAQsLIAFBADYCAAUgBSgCCCIBIAA2AgwgACABNgIICwsgBEUNAQJAIAUoAhwiAUECdEHwuQNqIgIoAgAgBUYEQCACIAA2AgAgAA0BQcS3A0HEtwMoAgBBASABdEF/c3E2AgAMAwUgBEEQaiAEKAIQIAVHQQJ0aiAANgIAIABFDQMLCyAAIAQ2AhggBUEQaiICKAIAIgEEQCAAIAE2AhAgASAANgIYCyACKAIEIgFFDQEgACABNgIUIAEgADYCGAsLIAUgCWohACAJIAdqBSAFIQAgBwshBSAAQQRqIgAgACgCAEF+cTYCACAGIAVBAXI2AgQgBiAFaiAFNgIAIAVBA3YhASAFQYACSQRAIAFBA3RB6LcDaiEAQcC3AygCACICQQEgAXQiAXEEfyAAQQhqIgIoAgAFQcC3AyACIAFyNgIAIABBCGohAiAACyEBIAIgBjYCACABIAY2AgwgBiABNgIIIAYgADYCDAwCCwJ/IAVBCHYiAAR/QR8gBUH///8HSw0BGiAFQQ4gACAAQYD+P2pBEHZBCHEiAHQiAUGA4B9qQRB2QQRxIgIgAHIgASACdCIAQYCAD2pBEHZBAnEiAXJrIAAgAXRBD3ZqIgBBB2p2QQFxIABBAXRyBUEACwsiAUECdEHwuQNqIQAgBiABNgIcIAZBEGoiAkEANgIEIAJBADYCAEHEtwMoAgAiAkEBIAF0IgNxRQRAQcS3AyACIANyNgIAIAAgBjYCACAGIAA2AhggBiAGNgIMIAYgBjYCCAwCCyAAKAIAIQBBGSABQQF2ayECIAUgAUEfRgR/QQAFIAILdCEBAkADQCAAKAIEQXhxIAVGDQEgAUEBdCECIABBEGogAUEfdkECdGoiASgCACIDBEAgAiEBIAMhAAwBCwsgASAGNgIAIAYgADYCGCAGIAY2AgwgBiAGNgIIDAILIABBCGoiASgCACICIAY2AgwgASAGNgIAIAYgAjYCCCAGIAA2AgwgBkEANgIYCwsgCiQEIAhBCGoPCwsDQAJAIAMoAgAiBSAETQRAIAUgAygCBGoiCCAESw0BCyADKAIIIQMMAQsLQQAgCEFRaiIDQQhqIgVrQQdxIQcgAyAFQQdxBH8gBwVBAAtqIgMgBEEQaiIMSQR/IAQiAwUgAwtBCGohBiADQRhqIQUgAkFYaiEJQQAgAUEIaiILa0EHcSEHQdi3AyABIAtBB3EEfyAHBUEAIgcLaiILNgIAQcy3AyAJIAdrIgc2AgAgCyAHQQFyNgIEIAEgCWpBKDYCBEHctwNBqLsDKAIANgIAIANBBGoiB0EbNgIAIAZBgLsDKQIANwIAIAZBiLsDKQIANwIIQYC7AyABNgIAQYS7AyACNgIAQYy7A0EANgIAQYi7AyAGNgIAIAUhAQNAIAFBBGoiAkEHNgIAIAFBCGogCEkEQCACIQEMAQsLIAMgBEcEQCAHIAcoAgBBfnE2AgAgBCADIARrIgdBAXI2AgQgAyAHNgIAIAdBA3YhAiAHQYACSQRAIAJBA3RB6LcDaiEBQcC3AygCACIDQQEgAnQiAnEEfyABQQhqIgMoAgAFQcC3AyADIAJyNgIAIAFBCGohAyABCyECIAMgBDYCACACIAQ2AgwgBCACNgIIIAQgATYCDAwDCyAHQQh2IgEEfyAHQf///wdLBH9BHwUgB0EOIAEgAUGA/j9qQRB2QQhxIgF0IgJBgOAfakEQdkEEcSIDIAFyIAIgA3QiAUGAgA9qQRB2QQJxIgJyayABIAJ0QQ92aiIBQQdqdkEBcSABQQF0cgsFQQALIgJBAnRB8LkDaiEBIAQgAjYCHCAEQQA2AhQgDEEANgIAQcS3AygCACIDQQEgAnQiBXFFBEBBxLcDIAMgBXI2AgAgASAENgIAIAQgATYCGCAEIAQ2AgwgBCAENgIIDAMLIAEoAgAhAUEZIAJBAXZrIQMgByACQR9GBH9BAAUgAwt0IQICQANAIAEoAgRBeHEgB0YNASACQQF0IQMgAUEQaiACQR92QQJ0aiICKAIAIgUEQCADIQIgBSEBDAELCyACIAQ2AgAgBCABNgIYIAQgBDYCDCAEIAQ2AggMAwsgAUEIaiICKAIAIgMgBDYCDCACIAQ2AgAgBCADNgIIIAQgATYCDCAEQQA2AhgLBUHQtwMoAgAiA0UgASADSXIEQEHQtwMgATYCAAtBgLsDIAE2AgBBhLsDIAI2AgBBjLsDQQA2AgBB5LcDQZi7AygCADYCAEHgtwNBfzYCAEH0twNB6LcDNgIAQfC3A0HotwM2AgBB/LcDQfC3AzYCAEH4twNB8LcDNgIAQYS4A0H4twM2AgBBgLgDQfi3AzYCAEGMuANBgLgDNgIAQYi4A0GAuAM2AgBBlLgDQYi4AzYCAEGQuANBiLgDNgIAQZy4A0GQuAM2AgBBmLgDQZC4AzYCAEGkuANBmLgDNgIAQaC4A0GYuAM2AgBBrLgDQaC4AzYCAEGouANBoLgDNgIAQbS4A0GouAM2AgBBsLgDQai4AzYCAEG8uANBsLgDNgIAQbi4A0GwuAM2AgBBxLgDQbi4AzYCAEHAuANBuLgDNgIAQcy4A0HAuAM2AgBByLgDQcC4AzYCAEHUuANByLgDNgIAQdC4A0HIuAM2AgBB3LgDQdC4AzYCAEHYuANB0LgDNgIAQeS4A0HYuAM2AgBB4LgDQdi4AzYCAEHsuANB4LgDNgIAQei4A0HguAM2AgBB9LgDQei4AzYCAEHwuANB6LgDNgIAQfy4A0HwuAM2AgBB+LgDQfC4AzYCAEGEuQNB+LgDNgIAQYC5A0H4uAM2AgBBjLkDQYC5AzYCAEGIuQNBgLkDNgIAQZS5A0GIuQM2AgBBkLkDQYi5AzYCAEGcuQNBkLkDNgIAQZi5A0GQuQM2AgBBpLkDQZi5AzYCAEGguQNBmLkDNgIAQay5A0GguQM2AgBBqLkDQaC5AzYCAEG0uQNBqLkDNgIAQbC5A0GouQM2AgBBvLkDQbC5AzYCAEG4uQNBsLkDNgIAQcS5A0G4uQM2AgBBwLkDQbi5AzYCAEHMuQNBwLkDNgIAQci5A0HAuQM2AgBB1LkDQci5AzYCAEHQuQNByLkDNgIAQdy5A0HQuQM2AgBB2LkDQdC5AzYCAEHkuQNB2LkDNgIAQeC5A0HYuQM2AgBB7LkDQeC5AzYCAEHouQNB4LkDNgIAIAJBWGohA0EAIAFBCGoiBWtBB3EhAkHYtwMgASAFQQdxBH8gAgVBACICC2oiBTYCAEHMtwMgAyACayICNgIAIAUgAkEBcjYCBCABIANqQSg2AgRB3LcDQai7AygCADYCAAsLQcy3AygCACIBIABLBEBBzLcDIAEgAGsiAjYCAAwDCwtBiLwDQQw2AgAgCiQEQQAPCyAKJARBAA8LQdi3A0HYtwMoAgAiASAAaiIDNgIAIAMgAkEBcjYCBCABIABBA3I2AgQLIAokBCABQQhqC8ESASd/IwQhAiMEQYABaiQEIAJBQGsiAyABLQABQQh0IAEtAAByIAEtAAJBEHRyIAEtAANBGHRyNgIAIAMgAS0ABUEIdCABLQAEciABLQAGQRB0ciABLQAHQRh0cjYCBCADIAEtAAlBCHQgAS0ACHIgAS0ACkEQdHIgAS0AC0EYdHI2AgggAyABLQANQQh0IAEtAAxyIAEtAA5BEHRyIAEtAA9BGHRyNgIMIAMgAS0AEUEIdCABLQAQciABLQASQRB0ciABLQATQRh0cjYCECADIAEtABVBCHQgAS0AFHIgAS0AFkEQdHIgAS0AF0EYdHI2AhQgAyABLQAZQQh0IAEtABhyIAEtABpBEHRyIAEtABtBGHRyNgIYIAMgAS0AHUEIdCABLQAcciABLQAeQRB0ciABLQAfQRh0cjYCHCADIAEtACFBCHQgAS0AIHIgAS0AIkEQdHIgAS0AI0EYdHI2AiAgAyABLQAlQQh0IAEtACRyIAEtACZBEHRyIAEtACdBGHRyNgIkIAMgAS0AKUEIdCABLQAociABLQAqQRB0ciABLQArQRh0cjYCKCADIAEtAC1BCHQgAS0ALHIgAS0ALkEQdHIgAS0AL0EYdHI2AiwgAyABLQAxQQh0IAEtADByIAEtADJBEHRyIAEtADNBGHRyNgIwIAMgAS0ANUEIdCABLQA0ciABLQA2QRB0ciABLQA3QRh0cjYCNCADIAEtADlBCHQgAS0AOHIgAS0AOkEQdHIgAS0AO0EYdHI2AjggAyABLQA9QQh0IAEtADxyIAEtAD5BEHRyIAEtAD9BGHRyNgI8IAIiBSAAQfQBaiIjKAIAIgIoAgAiDDYCACAFQQRqIhUgAigCBCIKNgIAIAVBCGoiFiACKAIIIgY2AgAgBUEMaiIXIAIoAgwiATYCACAFQRBqIhggAigCECILNgIAIAVBFGoiGSACKAIUIg82AgAgBUEYaiIkIAIoAhgiDTYCACAFQRxqIiUgAigCHCIINgIAIAVBIGoiJkHnzKfQBjYCACAFQSRqIhpBhd2e23s2AgAgBUEoaiIbQfLmu+MDNgIAIAVBLGoiHEG66r+qejYCACAFQTBqIh0gACgC+AEiAigCAEH/pLmIBXMiBzYCACAFQTRqIh4gAigCBEGM0ZXYeXMiCTYCACAFQThqIicgACgC/AEiACgCAEGrs4/8AXMiAjYCACAFQTxqIiggACgCBEGZmoPfBXMiADYCAEHnzKfQBiEQQYXdntt7IRJB8ua74wMhE0G66r+qeiEUA0AgCyAHIAsgDGogAyAEQQR0Qfcuai0AAEECdGooAgBqIg5zIgdBEHQgB0EQdnIiCyAQaiIMcyIHQRR0IAdBDHZyIgcgDmogAyAEQQR0Qfguai0AAEECdGooAgBqIREgByALIBFzIgdBGHQgB0EIdnIiDiAMaiIQcyIHQRl0IAdBB3ZyIR8gDyAJIA8gCmogAyAEQQR0Qfkuai0AAEECdGooAgBqIgpzIglBEHQgCUEQdnIiCyASaiIPcyIJQRR0IAlBDHZyIgwgCmogAyAEQQR0Qfouai0AAEECdGooAgBqISAgDSACIA0gBmogAyAEQQR0Qfsuai0AAEECdGooAgBqIgpzIgJBEHQgAkEQdnIiCSATaiIGcyICQRR0IAJBDHZyIgIgCmogAyAEQQR0Qfwuai0AAEECdGooAgBqISEgAiAJICFzIgJBGHQgAkEIdnIiEiAGaiIHcyICQRl0IAJBB3ZyIQ0gCCAAIAggAWogAyAEQQR0Qf0uai0AAEECdGooAgBqIgZzIgBBEHQgAEEQdnIiASAUaiICcyIAQRR0IABBDHZyIgAgBmogAyAEQQR0Qf4uai0AAEECdGooAgBqISIgACABICJzIgBBGHQgAEEIdnIiASACaiIKcyIAQRl0IABBB3ZyIQggASAMIAsgIHMiAEEYdCAAQQh2ciIJIA9qIgtzIgBBGXQgAEEHdnIiASARaiADIARBBHRB/y5qLQAAQQJ0aigCAGoiAnMiAEEQdCAAQRB2ciIAIAdqIQYgACABIAZzIgBBFHQgAEEMdnIiASACaiADIARBBHRBgC9qLQAAQQJ0aigCAGoiDHMiAEEYdCAAQQh2ciIRIAZqIRMgASATcyIAQRl0IABBB3ZyIQ8gDSAOIA0gIGogAyAEQQR0QYEvai0AAEECdGooAgBqIgZzIgBBEHQgAEEQdnIiAiAKaiIBcyIAQRR0IABBDHZyIgAgBmogAyAEQQR0QYIvai0AAEECdGooAgBqIQogACACIApzIgBBGHQgAEEIdnIiByABaiIUcyIAQRl0IABBB3ZyIQ0gCCAJIAggIWogAyAEQQR0QYMvai0AAEECdGooAgBqIgZzIgBBEHQgAEEQdnIiAiAQaiIBcyIAQRR0IABBDHZyIgAgBmogAyAEQQR0QYQvai0AAEECdGooAgBqIQYgACACIAZzIgBBGHQgAEEIdnIiCSABaiIQcyIAQRl0IABBB3ZyIQ4gHyASIB8gImogAyAEQQR0QYUvai0AAEECdGooAgBqIghzIgBBEHQgAEEQdnIiAiALaiIBcyIAQRR0IABBDHZyIgAgCGogAyAEQQR0QYYvai0AAEECdGooAgBqIQggACACIAhzIgBBGHQgAEEIdnIiAiABaiIBcyIAQRl0IABBB3ZyIQsgBEEBaiIAQQpHBEAgACEEIAEhEiAIIQEgDiEIIBEhAAwBCwsgBSAMNgIAIBggCzYCACAdIAc2AgAgJiAQNgIAIBUgCjYCACAZIA82AgAgHiAJNgIAIBogATYCACAWIAY2AgAgJCANNgIAICcgAjYCACAbIBM2AgAgFyAINgIAICUgDjYCACAoIBE2AgAgHCAUNgIAICMoAgAiASAMIAEoAgBzIBBzNgIAIAFBBGoiACAVKAIAIAAoAgBzIBooAgBzNgIAIAFBCGoiACAWKAIAIAAoAgBzIBsoAgBzNgIAIAFBDGoiACAXKAIAIAAoAgBzIBwoAgBzNgIAIAFBEGoiACAYKAIAIAAoAgBzIB0oAgBzNgIAIAFBFGoiACAZKAIAIAAoAgBzIB4oAgBzNgIAIAFBGGoiACANIAAoAgBzIAJzNgIAIAFBHGoiACAOIAAoAgBzIBFzNgIAIAUkBAuBAQEDfwJAIAAiAkEDcQRAIAIhAQNAIAEsAABFDQIgAUEBaiIBIgBBA3ENACABIQALCwNAIABBBGohASAAKAIAIgNBgIGChHhxQYCBgoR4cyADQf/9+3dqcUUEQCABIQAMAQsLIANB/wFxBEADQCAAQQFqIgAsAAANAAsLCyAAIAJrCysBAX8gAkUEQCAADwsgACABIAJBf2oiAxCuARogACADQQJ0akEANgIAIAALdwECfyAAQcQdNgIAIABBBGoiAigCACIBRQRADwsgACwAEARADwsgACwAEgRAQQAkBSMFIQBBACQFIABBAXFFBEAPCwVBACQFQSwgARAMIwUhAUEAJAUgAUEBcUUEQCACQQA2AgAgAEEANgIMDwsLQQAQGCIAEFoLhQsBFn8gAEHglwFqIhQoAgAiAyAAQcgMaiIPKAIAIgRPBEBBfw8LIABB6JcBaiIFKAIAIgIgBEkEQEF/DwsgBC4BAEEBRgRAIAQgABCJBAUgBCgCCCIBIANNIAEgAktyBEBBfw8LIAQgABCKBEUEQEF/DwsLIABB9JQBaiIIKAIAIABBgJUBaiIJKAIAIgIgAEH8lAFqIgYoAgAiAWxqIQMgCCADNgIAIAYgAEGElQFqIgwoAgAgAmsgAWwiAjYCAAJAIABB1AxqIhAoAgAiAQRAIABB4AxqIQMFIABB+JQBaiEVIABBjJUBaiERIABB4AxqIQQgAEHYDGohByADIQECQAJAA0ACQANAAkAgAiABaiABc0GAgIAITwRAIAJBgIACTw0BIAZBACABa0H//wFxNgIACyAVKAIAIRMgESgCACIKQQRqIhIoAgAiAUHi/wFKBEAgCkHoAGoiCygCACABayINQQBOBEAgCkHwAGoiFiAKQfgAaiIOKAIAIAFrIBYoAgBqNgIAAkACQCANBEAgCkEQaiICKAIAIgMgAyABaiANEF0aIBJBADYCACALIA02AgAgDUGAgAJHDQFBgIACIQEFIBJBADYCACALQQA2AgAgCkEQaiECDAELDAELIAooAgAgAigCACANakGAgAIgDWsQXiEDIAsoAgAiASADaiECIANBAEoEQCALIAI2AgAgAiEBCwsgCkHsAGoiAyABQWJqIgs2AgAgDiASKAIAIgE2AgAgAUF/aiAWKAIAIgJqIQ4gAkF/RwRAIAMgCyAOSAR/IAsFIA4LNgIACwsLIAooAhAhAiASIAFBAWo2AgAgFSATQQh0IAIgAWotAAByNgIAIAYgBigCAEEIdCICNgIAIAggCCgCAEEIdCIBNgIADAELCyAUKAIAIQMgBCgCACECIA8oAgAhAQNAIAJBAWohAiADIAEoAgwiAU8NASAFKAIAIAFJDQEgBygCACABLwEARg0ACyAEIAI2AgAgDyABNgIAIAEgABCIBEUEQEF/IQIMAwsgCCAIKAIAIAkoAgAiAyAGKAIAIgJsaiIBNgIAIAYgDCgCACADayACbCICNgIAIBAoAgAiA0UNASADIQEgBCEDDAULCwwBC0F/DwsgBCACNgIAIA8gATYCAEF/DwsLIAEtAAAhAgJAAkAgAygCAA0AIBQoAgAgASgCBCIBTw0AIABB0AxqIAE2AgAgDyABNgIADAELIAAQhwQgAEHwFGoiASwAAEUEQCABQQE6AAAgAEHwDGpBAEGAAhBUGgsLIABB+JQBaiEQIABBjJUBaiETIAgoAgAhACAGKAIAIQEDQAJAIAEgAGogAHNBgICACE8EQCABQYCAAk8NASAGQQAgAGtB//8BcTYCAAsgECgCACEOIBMoAgAiBUEEaiIMKAIAIgBB4v8BSgRAIAVB6ABqIgcoAgAgAGsiCUEATgRAIAVB8ABqIhEgBUH4AGoiBCgCACAAayARKAIAajYCAAJAAkAgCQRAIAVBEGoiASgCACIDIAMgAGogCRBdGiAMQQA2AgAgByAJNgIAIAlBgIACRw0BQYCAAiEABSAMQQA2AgAgB0EANgIAIAVBEGohAQwBCwwBCyAFKAIAIAEoAgAgCWpBgIACIAlrEF4hAyAHKAIAIgAgA2ohASADQQBKBEAgByABNgIAIAEhAAsLIAVB7ABqIgMgAEFiaiIHNgIAIAQgDCgCACIANgIAIABBf2ogESgCACIBaiEEIAFBf0cEQCADIAcgBEgEfyAHBSAECzYCAAsLCyAFKAIQIQEgDCAAQQFqNgIAIBAgDkEIdCABIABqLQAAcjYCACAGIAYoAgBBCHQiATYCACAIIAgoAgBBCHQiADYCAAwBCwsgAgvKAQECfwJAIAAQWCIBQYCAA3EiAkEQdEEQdUEASARAIAJBEHRBEHVBgIB+aw0BIABBAhBVIAAQWCEBIABBEBBVIAEPBSACQRB0QRB1QYCAAUgEQCACDQIgAEEGEFUgAUEKdkEPcQ8LIAJBEHRBEHVBgIABaw0BIAFBgPgAcQRAIABBChBVIAFBBnZB/wFxDwUgAEEOEFUgAUECdkGAfnIPCwALAAsgAEECEFUgABBYQRB0IQEgAEEQEFUgABBYIAFyIQEgAEEQEFUgAQteAQJ/IAEoAgAiAkUgACgCACIDRSADIAJHcnIEQCACIQAgAyEBBQNAIAFBBGoiASgCACICRSAAQQRqIgAoAgAiA0UgAyACR3JyBEAgAiEAIAMhAQUMAQsLCyABIABrC0QBAn8gAQRAA0AgAEEEaiEDIAAoAgAiAkUgAiABRnJFBEAgAyEADAELCyACRQRAQQAhAAsFIAAgABBZQQJ0aiEACyAAC9gEAQF/IAAoAoABIAFLBEAgACgCACABag8LAkAgACgChAEgAUsEQEEBIQIFIAAoAogBIAFLBEBBAiECBSAAKAKMASABSwRAQQMhAgUgACgCkAEgAUsEQEEEIQIFIAAoApQBIAFLBEBBBSECBSAAKAKYASABSwRAQQYhAgUgACgCnAEgAUsEQEEHIQIFIAAoAqABIAFLBEBBCCECBSAAKAKkASABSwRAQQkhAgUgACgCqAEgAUsEQEEKIQIFIAAoAqwBIAFLBEBBCyECBSAAKAKwASABSwRAQQwhAgUgACgCtAEgAUsEQEENIQIFIAAoArgBIAFLBEBBDiECBSAAKAK8ASABSwRAQQ8hAgUgACgCwAEgAUsEQEEQIQIFIAAoAsQBIAFLBEBBESECBSAAKALIASABSwRAQRIhAgUgACgCzAEgAUsEQEETIQIMEwsgACgC0AEgAUsEQEEUIQIMEwsgACgC1AEgAUsEQEEVIQIMEwsgACgC2AEgAUsEQEEWIQIMEwsgACgC3AEgAUsEQEEXIQIMEwsgACgC4AEgAUsEQEEYIQIMEwsgACgC5AEgAUsEQEEZIQIMEwsgACgC6AEgAUsEQEEaIQIMEwsgACgC7AEgAUsEQEEbIQIMEwsgACgC8AEgAUsEQEEcIQIMEwsgACgC9AEgAUsEQEEdIQIMEwsgACgC+AEgAUsEQEEeIQIMEwsgACgC/AEgAUsEQEEfIQIMEwsgACgCAA8LCwsLCwsLCwsLCwsLCwsLCwsLIAAgAkECdGooAgAgASAAIAJBAnRqKAJ8a2oL7QMBB38gAEHgAGoiBigCACIEIAJrIgMgAEHMzQNqKAIAQf9faiIFSSAEIAVJcUUEQCABRQRADwsgAEGklgFqIQcgAyECIABB0M0DaiIIKAIAIQMgBCEAA0AgAkEBaiEEIAcoAgAiBSAAaiAFIAMgAnFqLAAAOgAAIAYgBigCAEEBaiAIKAIAIgNxIgA2AgAgAUF/aiIBBEAgBCECDAELCw8LIABBpJYBaigCACIJIANqIQMgCSAEaiEAIAYgBCABajYCACABQQdLBEAgCSAEIAFBeGoiB0F4cSIIakEIaiIFIAJraiEEIAMhAgNAIAAgAiwAADoAACAAIAIsAAE6AAEgACACLAACOgACIAAgAiwAAzoAAyAAIAIsAAQ6AAQgACACLAAFOgAFIAAgAiwABjoABiAAIAIsAAc6AAcgAkEIaiECIABBCGohACABQXhqIgFBB0sNAAsgCSAFaiEAIAQhAyAHIAhrIQELIAFFBEAPCyAAIAMsAAA6AAAgAUEBRgRADwsgACADLAABOgABIAFBAk0EQA8LIAAgAywAAjoAAiABQQNGBEAPCyAAIAMsAAM6AAMgAUEETQRADwsgACADLAAEOgAEIAFBBUYEQA8LIAAgAywABToABSABQQZNBEAPCyAAIAMsAAY6AAYLhxABBH8jBCEFIwRBgAhqJAQgBUGABGohAiAALACABAR/IAIgAEGABBBTGiMEIQAjBEEQaiQEQRQgABAlIQMgACQEIANBywBqIQRBACEAA0AgAiAAaiIDIAQgAGogAy0AAHM6AAAgAEEBaiIAQYAERw0ACyACQfwDagUgAgshAyAFIQAgA0EANgIAIAEsAIAEBH8gACABQYAEEFMaIwQhASMEQRBqJARBFCABECUhAyABJAQgA0HLAGohBEEAIQEDQCAAIAFqIgMgBCABaiADLQAAczoAACABQQFqIgFBgARHDQALIABB/ANqBSAAC0EANgIAIAIgABBzIQEgAkEAOgAAIAJBADoAASACQQA6AAIgAkEAOgADIAJBADoABCACQQA6AAUgAkEAOgAGIAJBADoAByACQQA6AAggAkEAOgAJIAJBADoACiACQQA6AAsgAkEAOgAMIAJBADoADSACQQA6AA4gAkEAOgAPIAJBADoAECACQQA6ABEgAkEAOgASIAJBADoAEyACQQA6ABQgAkEAOgAVIAJBADoAFiACQQA6ABcgAkEAOgAYIAJBADoAGSACQQA6ABogAkEAOgAbIAJBADoAHCACQQA6AB0gAkEAOgAeIAJBADoAHyACQQA6ACAgAkEAOgAhIAJBADoAIiACQQA6ACMgAkEAOgAkIAJBADoAJSACQQA6ACYgAkEAOgAnIAJBADoAKCACQQA6ACkgAkEAOgAqIAJBADoAKyACQQA6ACwgAkEAOgAtIAJBADoALiACQQA6AC8gAkEAOgAwIAJBADoAMSACQQA6ADIgAkEAOgAzIAJBADoANCACQQA6ADUgAkEAOgA2IAJBADoANyACQQA6ADggAkEAOgA5IAJBADoAOiACQQA6ADsgAkEAOgA8IAJBADoAPSACQQA6AD4gAkEAOgA/IAJBQGtBADoAACACQQA6AEEgAkEAOgBCIAJBADoAQyACQQA6AEQgAkEAOgBFIAJBADoARiACQQA6AEcgAkEAOgBIIAJBADoASSACQQA6AEogAkEAOgBLIAJBADoATCACQQA6AE0gAkEAOgBOIAJBADoATyACQQA6AFAgAkEAOgBRIAJBADoAUiACQQA6AFMgAkEAOgBUIAJBADoAVSACQQA6AFYgAkEAOgBXIAJBADoAWCACQQA6AFkgAkEAOgBaIAJBADoAWyACQQA6AFwgAkEAOgBdIAJBADoAXiACQQA6AF8gAkEAOgBgIAJBADoAYSACQQA6AGIgAkEAOgBjIAJBADoAZCACQQA6AGUgAkEAOgBmIAJBADoAZyACQQA6AGggAkEAOgBpIAJBADoAaiACQQA6AGsgAkEAOgBsIAJBADoAbSACQQA6AG4gAkEAOgBvIAJBADoAcCACQQA6AHEgAkEAOgByIAJBADoAcyACQQA6AHQgAkEAOgB1IAJBADoAdiACQQA6AHcgAkEAOgB4IAJBADoAeSACQQA6AHogAkEAOgB7IAJBADoAfCACQQA6AH0gAkEAOgB+IAJBADoAfyAAQQA6AAAgAEEAOgABIABBADoAAiAAQQA6AAMgAEEAOgAEIABBADoABSAAQQA6AAYgAEEAOgAHIABBADoACCAAQQA6AAkgAEEAOgAKIABBADoACyAAQQA6AAwgAEEAOgANIABBADoADiAAQQA6AA8gAEEAOgAQIABBADoAESAAQQA6ABIgAEEAOgATIABBADoAFCAAQQA6ABUgAEEAOgAWIABBADoAFyAAQQA6ABggAEEAOgAZIABBADoAGiAAQQA6ABsgAEEAOgAcIABBADoAHSAAQQA6AB4gAEEAOgAfIABBADoAICAAQQA6ACEgAEEAOgAiIABBADoAIyAAQQA6ACQgAEEAOgAlIABBADoAJiAAQQA6ACcgAEEAOgAoIABBADoAKSAAQQA6ACogAEEAOgArIABBADoALCAAQQA6AC0gAEEAOgAuIABBADoALyAAQQA6ADAgAEEAOgAxIABBADoAMiAAQQA6ADMgAEEAOgA0IABBADoANSAAQQA6ADYgAEEAOgA3IABBADoAOCAAQQA6ADkgAEEAOgA6IABBADoAOyAAQQA6ADwgAEEAOgA9IABBADoAPiAAQQA6AD8gAEFAa0EAOgAAIABBADoAQSAAQQA6AEIgAEEAOgBDIABBADoARCAAQQA6AEUgAEEAOgBGIABBADoARyAAQQA6AEggAEEAOgBJIABBADoASiAAQQA6AEsgAEEAOgBMIABBADoATSAAQQA6AE4gAEEAOgBPIABBADoAUCAAQQA6AFEgAEEAOgBSIABBADoAUyAAQQA6AFQgAEEAOgBVIABBADoAViAAQQA6AFcgAEEAOgBYIABBADoAWSAAQQA6AFogAEEAOgBbIABBADoAXCAAQQA6AF0gAEEAOgBeIABBADoAXyAAQQA6AGAgAEEAOgBhIABBADoAYiAAQQA6AGMgAEEAOgBkIABBADoAZSAAQQA6AGYgAEEAOgBnIABBADoAaCAAQQA6AGkgAEEAOgBqIABBADoAayAAQQA6AGwgAEEAOgBtIABBADoAbiAAQQA6AG8gAEEAOgBwIABBADoAcSAAQQA6AHIgAEEAOgBzIABBADoAdCAAQQA6AHUgAEEAOgB2IABBADoAdyAAQQA6AHggAEEAOgB5IABBADoAeiAAQQA6AHsgAEEAOgB8IABBADoAfSAAQQA6AH4gAEEAOgB/IAAkBCABRQslAQF/IAIgABBZa0F/aiIDQQBMBEAgAA8LIAAgASADELIDGiAACxYAIABBAEHAywQQVBogAEGowAJqEFwLbQEEfyAAKAIUIABBGGoiBCgCACIFayIDIAJJIgYEfyADBSACIgMLBEAgASAAKAIAIAVqIAMQUxoLIAZFBEAgBCAEKAIAIANqNgIAIAMPCyABIANqQQAgAiADaxBUGiAEIAQoAgAgA2o2AgAgAwueAwEIfyMEIQQjBEEgaiQEIARBCGohBSABQQA2AgAgBEIANwMAIARBEGoiAyAANgIAAkACQAJAAkACQAJAIAEgAyACIAQQuQNBf2sOAgABAgsMAgsgACwAAA0BQQEhAAwCC0EBIQAMAQsgAkEBSwRAQQAhAwJAAkADQCAAIAhqIgYsAABFDQEgBUIANwMAIAEgA0ECdGoiCSAGQawjKAIAKAIABH9BBAVBAQsgBRCKAkF/RgR/IAYsAAAiB0EATg0DIApFBEAgCUH+/wM2AgAgA0EBaiIDIAJPDQQgBiwAACEHCyABIANBAnRqIAdB/wFxQYDAA3I2AgBBASEKIAhBAWoFIAVCADcDACAGQawjKAIAKAIABH9BBAVBAQsgBRCIAiIHQQFKBH8gBwVBAQsgCGoLIQggA0EBaiIDIAJJDQBBACEADAULAAsgASADQQJ0akEANgIAQQEhAAwDC0EAIQAFQQAhAAwBCwwBCyACRQRAIAQkBCAAQf8BcUEARw8LCyABIAJBf2pBAnRqQQA2AgAgBCQEIABB/wFxQQBHC/EBAgN/AX4jBCEBIwRB0ABqJAQgAEGtvANqLAAABEAgASQEQQAPCyAAQYi8A2oiAyAAIAAoAgAoAhRBB3FBhgFqEQAAIgQ3AwACQAJAAkACQAJAAkAgAEGYvANqKAIAQQFrDgMAAQIDCyAAENcCIQIMAwsgABDWAiECDAILIAAQ1QIhAgwBCwwBCyACBEAgAykDACEEBSABJARBAA8LCyAAQZC8A2opAwAgBFUEQCABJAQgAg8LIAFBADYCRCABQRg2AkggAUFAa0EBNgIAIAEgAEEYajYCACAAQay8A2pBAToAAEGs9QJBAxBkIAEkBEEAC9cBAgZ/AX4jBCEDIwRBoAJqJAQgA0EgaiEGIAMhBSAAQSBqIgMpAwAhCSADIAkgAq18NwMAIAJFBEAgBUEgEFsgBkGAAhBbIAUkBA8LIABBKGohByAAQSxqIQggCadBP3EhAwNAIAJBwAAgA2siBEsEfyAEBSACIgQLQcAARgRAIAcgATYCAAUgByAINgIAIABBLGogA2ogASAEEFMaCyAEIANqIgNBwABGBEAgABDhAUEAIQMLIAEgBGohASACIARrIgINAAsgBUEgEFsgBkGAAhBbIAUkBAt4AQF/IABB9A02AgAgAEGo8wBqLAAABEAgAEGs8wBqKAIAIgEEQCABEHkgARBSCwsgAEGQ7gJqKAIAIgEEQCABEFILIABB0OcBaigCACIBBEAgARBSCyAAQdjzAGoQtQIgAEHw8QBqEIQBIABBnMAAahCOASAAEHALBgBBEBAACwgAQQUQAEEACwgAQQIQAEEACzABAX8jBCECIwRBEGokBCACIAE2AgBB8CAoAgAiASAAIAIQzgEaQQogARCrAxoQOQujAgEEfyABRQRAIABBvM0DakEANgIAIABByM0DakEANgIAIABBnM0DaiIEKAIAIgEEQCAAQZjNA2ohBQNAIAUoAgAgAkECdGooAgAiAwRAIAMoAjwiAQRAIAEQUgsgAygCLCIBBEAgARBSCyADKAIUIgEEQCABEFILIAMQUiAEKAIAIQELIAJBAWoiAiABSQ0ACwsgBEEANgIACyAAQazNA2oiAygCACICRQRAIANBADYCAA8LIABBqM0DaiEEQQAhASACIQADQCAEKAIAIAFBAnRqKAIAIgIEQCACKAI8IgAEQCAAEFILIAIoAiwiAARAIAAQUgsgAigCFCIABEAgABBSCyACEFIgAygCACEACyABQQFqIgEgAEkNAAsgA0EANgIAC0gBAX8gAEFAaygCACIBBEAgARCOASABEFILIAAoAkQiAQRAIAEQjgEgARBSCyAAQagBahCNASAAQZwBahCNASAAQZABahCNAQsYAEG39QIsAABFBEAPC0Gs9QJB/wEQ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TBogACABEKwDIgALQQEBfwJAIAAQWSICQX9KBEAgACACQQJ0aiECA0AgAigCACABRg0CIAJBfGoiAiAATw0AQQAhAgsFQQAhAgsLIAILZAEDfwJAIAIEQCABIQMgACEBA0AgAygCACIFRQ0CIANBBGohAyABQQRqIQQgASAFNgIAIAJBf2oiAgRAIAQhAQwBBSAEIQFBACECCwsFIAAhAUEAIQILCyABQQAgAhCwAxogAAvCBAEKfyMEIQYjBEGAQGskBCAAIQcDQAJAA0AgACIEKAIAIQgCQAJAA0ACQAJAAkACQCAIDjAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgECCyAHIQAMBwsMAQsMAgsgBEEEaiIAKAIAIghBLkYNAiAAIQQMAAsACyAEQQRqIQAMAQsgBCgCCEEuRw0ACyAEQRBqIQggBCgCDEEvRgRAIAghBwsMAQsLAkACQANAAkACQAJAAkACQCAAKAIAIgcOXQACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAQILDAMLIAAoAgRB3ABGBEAgAEEIakHcABB0IgIEQCACQQRqQdwAEHQiA0EEaiECIAMEfyACBSAAIgILIQMFIAAiAyECCwUgACIDIQILQQ0hBQwBCyAAIgohCSAHIQsLA0AgBUENRgRAQQAhBSADIQogAiEJIAMoAgAhCwsCQAJAAkAgC0Euaw4CAAECCyAKQQRqIQMgCSECQQ0hBQwCCyAKQQRqIgIhA0ENIQUMAQsLIAkgAEYNAiAJIQAMAQsLDAELIAAoAgBBLkYEQCAAKAIEQS5GBEAgAEEIaiICKAIARQRAIAIhAAsLCwsgAUUEQCAGJAQgAA8LIAYgAEGAEBBvGiABIAYQahogBiQEIAALEwAgAAR/IAAgAUEAEJEBBUEACwvaAwMBfwF+AXwCQCABQRRNBEACQAJAAkACQAJAAkACQAJAAkACQAJAIAFBCWsOCgABAgMEBQYHCAkKCyACKAIAQQNqQXxxIgEoAgAhAyACIAFBBGo2AgAgACADNgIADAsLIAIoAgBBA2pBfHEiASgCACEDIAIgAUEE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ACEEQQAhAwNAIAAgDCADrXxBACAAKAIAKAIQQQNxQbgCahECACAIKAIAQQFGBEAgBiAJNgIACyAHLAAABEAgB0EAOgAACyAGKAIAIAEgAiADayIFQYAESQR/IAUFQYAECxBBIgVBf0YEf0GABAUgBQsgBGohBCADQYAEaiIDIAJJDQALIAQPC0Gs9QIgAxC6BEF/DwsgBAuMAgEDfyABKAIAIQIgAEIANwIAIABBADYCCCACQe////8DSwRAIAAQigELIAFBBGohBAJAIAJBAkkEQCAAIAI6AAsgAgRAIAAhAwUgACACQQJ0akEANgIADwsFIAJBBGpBfHEiAUH/////A00EQCAAIAFBAnQQXyIDNgIAIAAgAUGAgICAeHI2AgggACACNgIEDAILQQgQFCEAQQAkBUEXIABBzO4AEA0jBSEBQQAkBSABQQFxBEAQFyEBIAAQGiABEB4FIABB7CU2AgAgAEH4CkEMEBsLCwtBACQFQR0gAyAEIAIQBxojBSEAQQAkBSAAQQFxBEBBABAYIgAQWgUgAyACQQJ0akEANgIACwsPACABIAAoAgBqIAI2AgALDQAgASAAKAIAaigCAAvQBgECfyAAKAIAIgEEQCABEFIgAEEANgIACyAAQQRqIgEoAgAiAgRAIAIQUiABQQA2AgALIABBCGoiASgCACICBEAgAhBSIAFBADYCAAsgAEEMaiIBKAIAIgIEQCACEFIgAUEANgIACyAAQRBqIgEoAgAiAgRAIAIQUiABQQA2AgALIABBFGoiASgCACICBEAgAhBSIAFBADYCAAsgAEEYaiIBKAIAIgIEQCACEFIgAUEANgIACyAAQRxqIgEoAgAiAgRAIAIQUiABQQA2AgALIABBIGoiASgCACICBEAgAhBSIAFBADYCAAsgAEEkaiIBKAIAIgIEQCACEFIgAUEANgIACyAAQShqIgEoAgAiAgRAIAIQUiABQQA2AgALIABBLGoiASgCACICBEAgAhBSIAFBADYCAAsgAEEwaiIBKAIAIgIEQCACEFIgAUEANgIACyAAQTRqIgEoAgAiAgRAIAIQUiABQQA2AgALIABBOGoiASgCACICBEAgAhBSIAFBADYCAAsgAEE8aiIBKAIAIgIEQCACEFIgAUEANgIACyAAQUBrIgEoAgAiAgRAIAIQUiABQQA2AgALIABBxABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABByABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABBzABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABB0ABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABB1ABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABB2ABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABB3ABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABB4ABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABB5ABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABB6ABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABB7ABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABB8ABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABB9ABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABB+ABqIgEoAgAiAgRAIAIQUiABQQA2AgALIABB/ABqIgAoAgAiAUUEQA8LIAEQUiAAQQA2AgAL6AoBGn8jBCECIwRBEGokBCACQQhqIRIgAiEJIABB4ABqIgooAgAgAEHkAGoiDCgCACICayAAQdDNA2oiDSgCACIDcSETIABBNGohBwJAAkAgAEE4aiILKAIARQ0AIABBHGohDiAAQRhqIRQgAEEgaiEXIABBFGohDyAAQczNA2ohGCAAQaiYAWohFSAAQaSWAWohECAAQaiWAWohESAAQbqYAWohGSAAQcCYAWohFiATIQECQAJAAkACQANAAkAgBygCACIGIAVBBHRqIhosAABBCEcEQCAGIAVBBHRqKAIEIQQgBiAFQQR0akENaiIILAAABEAgBCAMKAIAayADcSATSw0CIAhBADoAAAwCCyAGIAVBBHRqKAIIIQYgAyAEIAJrcSABSQRAIAQgAkcEQCAAIAIgBBCzASAEIQIgCigCACAEayANKAIAIgNxIQELIAYgAUsNBCAGBEAgDigCACEBIBQgBjYCACABIAZJBEAgFygCACICQQBHIAYgAktxBH8gCSACNgIAQaz1AkHYGyAJEGBBrPUCEFYgDigCACEBIBQoAgAFIAYLIQIgDygCACACIAFBIGogAUECdmoiAUsEfyACBSABIgILEFciAUUEQEGs9QIQVgsgDyABNgIAIA4gAjYCAAsgDygCACEBAkAg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ACADIAFBlJUBaiAEai0AACIEQQR0aiEDIAIgBGshAgsgASACakG5lQFqLQAAIQQLIAMgAUHIlgFqIARBAnRqIgEoAgA2AgAgASADNgIACyAKIAA2AgALIA0gADYCACAGJAQLuxIBCX8gAEHwDGpBAEGAAhBUGiAAQZCVAWoiBhCOBCAAQewMaiIIIABB5AxqIgUoAgAiA0F/cyIBQXNKBH8gAQVBcws2AgAgAEHElgFqIgcoAgAiASAAQcCWAWoiAigCAEYEQCAAQciWAWoiBCgCACIBBEAgBCABKAIANgIABSAGQQAQoAEhASAFKAIAIQMLBSAHIAFBcGoiATYCAAsgAEHQDGogATYCACAAQcgMaiIFIAE2AgAgAUEANgIMIABB4AxqIAM2AgAgAUGAAjsBACABQYECOwEEIABByJYBaiAAQbmWAWotAAAiA0ECdGoiBCgCACIBBEAgBCABKAIANgIABSACIAIoAgAiASAAQZSVAWogA2oiCS0AAEEEdGoiBDYCACAEIAcoAgBLBEAgAiAEIAktAABBBHRrNgIAIAYgAxCgASEBCwsgBSgCACABNgIIIABB1AxqIAE2AgAgAEHoDGogCCgCADYCACAAQfEUakEAOgAAIAUoAgBBCGohA0EAIQEDQCADKAIAIAFBA3RqIAE6AAAgAygCACABQQN0akEBOgABIAMoAgAgAUEDdGpBADYCBCABQQFqIgFBgAJHDQBBACEBCwNAIABB9BRqIAFBB3RqQYCAAUHd+QAgAUECaiIDbmtB//8DcSICOwEAIAAgAUEHdGpBhBVqIAI7AQAgACABQQd0akGUFWogAjsBACAAIAFBB3RqQaQVaiACOwEAIAAgAUEHdGpBtBVqIAI7AQAgACABQQd0akHEFWogAjsBACAAIAFBB3RqQdQVaiACOwEAIAAgAUEHdGpB5BVqIAI7AQAgACABQQd0akH2FGpBgIABQb8+IANua0H//wNxIgI7AQAgACABQQd0akGGFWogAjsBACAAIAFBB3RqQZYVaiACOwEAIAAgAUEHdGpBphVqIAI7AQAgACABQQd0akG2FWogAjsBACAAIAFBB3RqQcYVaiACOwEAIAAgAUEHdGpB1hVqIAI7AQAgACABQQd0akHmFWogAjsBACAAIAFBB3RqQfgUakGAgAFBv7MBIANua0H//wNxIgI7AQAgACABQQd0akGIFWogAjsBACAAIAFBB3RqQZgVaiACOwEAIAAgAUEHdGpBqBVqIAI7AQAgACABQQd0akG4FWogAjsBACAAIAFBB3RqQcgVaiACOwEAIAAgAUEHdGpB2BVqIAI7AQAgACABQQd0akHoFWogAjsBACAAIAFBB3RqQfoUakGAgAFB85EBIANua0H//wNxIgI7AQAgACABQQd0akGKFWogAjsBACAAIAFBB3RqQZoVaiACOwEAIAAgAUEHdGpBqhVqIAI7AQAgACABQQd0akG6FWogAjsBACAAIAFBB3RqQcoVaiACOwEAIAAgAUEHdGpB2hVqIAI7AQAgACABQQd0akHqFWogAjsBACAAIAFBB3RqQfwUakGAgAFBockBIANua0H//wNxIgI7AQAgACABQQd0akGMFWogAjsBACAAIAFBB3RqQZwVaiACOwEAIAAgAUEHdGpBrBVqIAI7AQAgACABQQd0akG8FWogAjsBACAAIAFBB3RqQcwVaiACOwEAIAAgAUEHdGpB3BVqIAI7AQAgACABQQd0akHsFWogAjsBACAAIAFBB3RqQf4UakGAgAFBvLUBIANua0H//wNxIgI7AQAgACABQQd0akGOFWogAjsBACAAIAFBB3RqQZ4VaiACOwEAIAAgAUEHdGpBrhVqIAI7AQAgACABQQd0akG+FWogAjsBACAAIAFBB3RqQc4VaiACOwEAIAAgAUEHdGpB3hVqIAI7AQAgACABQQd0akHuFWogAjsBACAAIAFBB3RqQYAVakGAgAFBsswBIANua0H//wNxIgI7AQAgACABQQd0akGQFWogAjsBACAAIAFBB3RqQaAVaiACOwEAIAAgAUEHdGpBsBVqIAI7AQAgACABQQd0akHAFWogAjsBACAAIAFBB3RqQdAVaiACOwEAIAAgAUEHdGpB4BVqIAI7AQAgACABQQd0akHwFWogAjsBACAAIAFBB3RqQYIVakGAgAFB0cABIANua0H//wNxIgM7AQAgACABQQd0akGSFWogAzsBACAAIAFBB3RqQaIVaiADOwEAIAAgAUEHdGpBshVqIAM7AQAgACABQQd0akHCFWogAzsBACAAIAFBB3RqQdIVaiADOwEAIAAgAUEHdGpB4hVqIAM7AQAgACABQQd0akHyFWogAzsBACABQQFqIgFBgAFHDQBB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QEEAEBgQWgUgBhAeCwsgByAZNwMAIAMgGjcDACACIAo2AgAgACgCACgCECECQQAkBSACIAAgF6cgF0IgiKdBABBQIwUhAkEAJAUgAkEBcQRAQQAQGBBaBSABIQ8LCyAPLAAABEAgAEGhvANqLAAARQRAIAUkBEEBDwsLIABB5LwDaiAAQRhqEGoaIAUkBEEBDwsgBSQEQQALBgBBFxAACwYAQRYQAAsGAEEREAALCABBBxAAQQALLQEBfyAAQTsQrQEiAgRAIAJBBGoQyQIhACABBEAgAkEANgIACwVBACEACyAAC9YBAQJ/IwQhAyMEQYAQaiQEAkAgAARAAkACQAJAAkAgACgCAA4wAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIBAgsMBAsgAUEANgIADAELIANBgBAQtgNFBEAgA0EAOgAACyADIAEgAhB7GiABEFkiBARAIARBAWogAkkgASAEQX9qQQJ0aigCAEEvR3EEQCABQfwMEIYCGgsLCyABIAAgAhB4GiADJAQPCwsgAkUEQCADJAQPCyABQQA2AgAgAyQEC78BAQJ/AkAgAkF/aiIEBEBBACECA0ACQAJAAkAgACACQQJ0aigCACIDDl0AAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgECCwwEC0EvIQMLIAEgAkECdGogAzYCACACQQFqIgIgBEkNAAsFQQAhAgsLIAEgAkECdGpBADYCAAtWAQN/IAAoAgQiBUEIdSEEIAVBAXEEQCACKAIAIARqKAIAIQQLIAAoAgAiACgCACgCHCEGIAAgASACIARqIAVBAnEEfyADBUECCyAGQQdxQZgCahEKAAsHACAAIAFGCwsAIAAQ/AEgABBSCxIAIABB2CU2AgAgAEEEahCNAwuDAQEBfyMEIQEjBEEQaiQEQQAkBSAAEAsjBSEAQQAkBSAAQQFxRQRAQQAkBUEZQbvyACABEA1BACQFC0EAEBgiABAVGkEAJAVBGUHj8gAgAUEIahANQQAkBUEAEBghAUEAJAVBBBALIwUhAEEAJAUgAEEBcQRAQQAQGCIAEFoFIAEQWgsLOAEC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IAQQyAEgBSgCACEACwJAIABBqIACahBZIgYEQCACIAYgAhBZIgFJBH8gBgUgAQtBAnRqIQIDQAJAAkACQAJAAkAgAigCAA4wAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIBAgsMAwsMAQsMBAsgAkEEaiECDAELCyADQQA2AgAPCwsCQAJAIABByMsEaigCACIBQdgARiAAQeCEA2ooAgBBBEZxBEBBACEBBSABQcUARgRAQQAhAQwCBUEAIQELCyAFKAIAQeCEA2ooAgBBAUYNACADIAIgBBB4GgwBCyADIAIQmwEgBBB4GgsgAygCABCTASEADwv4AQEDfyMEIQMjBEHwFmokBCADQSRqIQQgAyAAKAIAIgU2AgACQAJAAkACQCAFQQFrDgMAAQIDCyADIAAoAgQ2AgQMAgsgAyAAKAIEQX9zNgIEDAELIAQgACgCCBCmBCAEIANBBGoQqQQLIAIEQCADIAIQvwILIAMoAgAiAkUEQCADJARBAQ8LIAEoAgAiAEUEQCADJARBAQ8LIAJBAUYgAEEBRnFFBEAgAkECRiAAQQJGcUUEQCACQQNGIABBA0ZxRQRAIAMkBEEADwsgA0EEaiABQQRqQSAQa0UhACADJAQgAA8LCyADKAIEIAEoAgRGIQAgAyQEIAALcgEBfyAAKAIAIgNBAUYEQCAAQQRqIgMgAygCAEH//wNxIAEgAhDQBEH//wNxNgIAIAAoAgAhAwsgA0ECRgRAIABBBGoiAyADKAIAIAEgAhCZATYCACAAKAIAIQMLIANBA0cEQA8LIAAoAgggASACEKsEC74FAQJ/IABBCGoiBCgCACICRQRAQQBBzBYQXyICIgNrQT9xIANqIQMgAiADNgLwASACIANBgAFqNgL0ASACIANBoAFqNgL4ASACIANBqAFqNgL8ASACQQAgAkGIAmoiA2tBP3EgA2oiAzYC+AMgAiADQYABajYC/AMgAiADQaABajYCgAQgAiADQagBajYChAQgAkEAIAJBkARqIgNrQT9xIANqIgM2AoAGIAIgA0GAAWo2AoQGIAIgA0GgAWo2AogGIAIgA0GoAWo2AowGIAJBiAhqQQAgAkGYBmoiA2tBP3EgA2oiAzYCACACQYwIaiADQYABajYCACACQZAIaiADQaABajYCACAC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AUGg0ABqIAIEfyADBSAECzYAACABQZjQAGogAEHstwdqIgIoAgA2AABBACQFQQUgAEG4twdqEAUhAyMFIQRBACQFIARBAXFFBEAgAUGc0ABqIAM2AAAgAUGk0ABqIABBovcGai0AAEEwajYAACABQajQAGogAEGk9wZqKAIANgAAIAFBtNAAakEANgAAIAFBuNAAakEANgAAIAFBvNAAaiAAQey4B2ooAgBBCnY2AAACQAJAAkACQCAAQei3B2ooAgBBAWsOAwAAAQILIAFBwNAAakEBNgAADAILIAFBwNAAakECNgAAIAFBxNAAaiIDIAIpAAA3AAAgAyACKQAINwAIIAMgAikAEDcAECADIAIpABg3ABgMAQsgAUHA0ABqQQA2AAALIAFB5NAAaiAAQfi4B2ooAgAiAjYAACACBEAgAUHo0ABqKAAAIgIEQCABQezQAGooAAAiA0F/akGfjQZJBEBBACQFQRAgAiAAQfy4B2ogAxAHGiMFIQJBACQFIAJBAXENCQsLCyABQfDQAGogAEH8+AdqLQAANgAAQQAPCwsLCwsLC0GACBAYIQEjB0GACBBERwRAIAEQHgsgARAVIQECQCAAQajLBGooAgAiAEUEQAJAAkACQAJAAkACQAJAAkACQCABKAIADgwHCAABCAIDCAUECAYIC0ESIQAMCQtBDCEADAgLQRMhAAwHC0EPIQAMBgtBECEADAULQQshAAwEC0EYIQAMAwtBACEADAILQRUhAAsLEBYgAAvEAwEEfyMEIQIjBEFAayQEIAJBIGohAyAAKAIAIgRBAkYEQCADIABBBGoiBSgCACIEOgAAIAMgBEEIdjoAASADIARBEHY6AAIgAyAEQRh2OgADIAFBICADQQQgAhCnASAFQQA2AgAgBSACLQAfQRh0IAItAB5BEHQgAi0AHUEIdCACLQAbQRh0IAItABpBEHQgAi0AGUEIdCACLQAXQRh0IAItABZBEHQgAi0AFUEIdCACLQATQRh0IAItABJBEHQgAi0AEUEIdCACLQAPQRh0IAItAA5BEHQgAi0ADUEIdCACLQALQRh0IAItAApBEHQgAi0ACUEIdCACLQAHQRh0IAItAAZBEHQgAi0ABUEIdCACLQADQRh0IAItAAJBEHQgAi0AAUEIdCACLQAAcnJyIAItAARzc3NzIAItAAhzc3NzIAIt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IBwgAa18NwMAAkACQAJAAkACQAJAAkACQAJAAkAgFCgCACIBQQFrDnkAAQEIAggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAMFBwYECAtBACQFQRsgAEG4pgFqIgEQDCMFIQJBACQFIAJBAXENDSABIAcpAgA3AgAgASAHKQIINwIIIAEgBygCEDYCEEEAJAVBCiAEEAUhASMFIQJBACQFIAJBAXENDSAAQcymAWoiAyABOwEAQQAkBUEMIAQQBSECIwUhAUEAJAUgAUEBcQ0NIABB0KYBaiACNgIAIABBnbwDaiAAQcCmAWooAgAiAUEBcToAACAAQZy8A2ogAUEDdkEBcToAACAAQZ+8A2ogAUECdkEBcToAACAAQaO8A2ogAUEGdkEBcToAACAIIAFBB3ZBAXE6AAAgAEGgvANqIAIEf0EBBSADLgEAQQBHC0EBcToAACAAQdSmAWogAUEBdkEBcToAACAAQaG8A2ogAUEIdkEBcToAACAAQaK8A2ogAUEEdkEBcToAAAwICyAAQbCnAWohAyAAQfCtAmohAkEAJAVBCCABQQJGIg8EfyADBSACIgMLQQAQDSMFIQFBACQFIAFBAXFFBEAgAyAHKQIANwIAIAMgBykCCDcCCCADIAcoAhA2AhAgA0GIwQBqIANBCGoiCSgCACIBQQFxOgAAIANBicEAaiABQQF2QQFxOgAAIANBi8EAaiIGIAFBAnZBAXE6AAAgA0GQwQBqIAFBCnZBAXE6AAAgA0HgwQBqIA8Ef0EAIQUgAUEEdkEBcQUgAUEQcUEARyEFQQALOgAAIANB6sEAaiAFQQFxOgAAIANB4cEAaiIMIAFB4AFxQeABRiICOgAAIANB5MEAaiACBH9BAAVBgIAEIAFBBXZBB3F0CzYCACADQeLBAGoiGSABQQN2QQFxOgAAIANB48EAaiABQQt2QQFxOgAAQQAkBUEMIAQQBSEBIwUhAkEAJAUgAkEBcUUEQCADQRRqIhogATYCAEEAJAVBDCAEEAUhAiMFIQFBACQFAkAgAUEBcUUEQEEAJAVBCyAEEAUhASMFIQVBACQFIAVBAXFF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AGoiBxAMIwUhAkEAJAUCQCACQQFxBEAQFyECBSAAQdDnAWoiAkIANwIAIAJCADcCCCACQgA3AhAgAkIANwIYIAJCADcCICAAQZDuAmoiAkIANwIAIAJCADcCCCACQgA3AhAgAkIANwIYIAJCADcCICAAQazzAGoiCEEANgIAIABBqPMAaiABRSICOgAAAkAgAgRAQQAkBUEEQcDLBBAFIQMjBSEBQQAkBSABQQFxBEAQFyECBUEAJAVBGiADEAwjBSEBQQAkBSABQQFxRQRAIAMhAQwDCxAXIQIgAxBSIABBkO4CaigCACIDBEAgAxBSCwsgAEHQ5wFqKAIAIgMEQCADEFILIAcQtQIMAwsLIAggATYCACAAIAFBnYUDaiwAADoAFSAAQZi8A2pBAjYCACAAQai8A2pBADYCACAGQgA3AwAgAEGtvANqQQA6AAAgAEGsvANqQQA6AAAgAEHI8wBqQQA2AgAgAEGIvANqIgFCADcDACABQgA3AwggAEGcvANqIgFCADcCACABQQA6AAggAEGw8wBqQn83AwAgAEG48wBqQX82AgAgAEGwrQJqIgFCADcDACABQgA3AwggAUIANwMQIAFCADcDGCAAQcC8A2pBADYCACAAQeS8A2pBADYCACAAQb68A2pBADoAACAAQdDzAGpBADoAACAAQbimAWoiAUIANwMAIAFCADcDCCABQgA3AxAgAUIANwMYIAFCADcDICABQgA3AyggAUIANwMwIAFCADcDOCABQUBrQgA3AwAgAUIANwNIIAFCADcDUCABQgA3A1ggAUIANwNgIAFCADcDaCABQQA2AnAgAEHIvANqIgBCADcDACAAQgA3AwggAEIANwMQIABBADoAGA8LCyAFEIQBCyAEEI4BIAAQcCACEB4LjwgBC38jBCECIwRBMGokBCACQRBqIQogAkEIaiEHIAIiCUEYaiIFQgA3AgAgBUIANwIIQQAkBUEUIAAgBUEAEAchAiMFIQNBACQFAkAgA0EBcUUEQCACBH8gBUEEaiIGKAIAIgtBAWohAiAGIAI2AgAgAiAFQQhqIggoAgAiBEsEfyAFKAIMIgNBAEcgAiADS3EEf0EAJAUgCSADNgIAQQJBrPUCQdgbIAkQDiMFIQNBACQFIANBAXENBEEAJAVBFEGs9QIQDCMFIQNBACQFIANBAXENBCAIKAIAIQQgBigCAAUgAgshAyAFKAIAIAMgBEEgaiAEQQJ2aiIESwR/IAMiBAUgBAsQVyIDRQRAQQAkBUEUQaz1AhAMIwUhDEEAJAUgDEEBcQ0ECyAFIAM2AgAgCCAENgIAIAYoAgAFIAUoAgAhAyACCyEEIAMgBEF/ampBADoAACABQQhqIgQoAgAhAyABQQRqIgYgAjYCACADIAJJBEAgASgCDCIIQQBHIAIgCEtxBEBBACQFIAcgCDYCAEECQaz1AkHYGyAHEA4jBSECQQAkBSACQQFxDQRBACQFQRRBrPUCEAwjBSECQQAkBSACQQFxDQQgBCgCACEDIAYoAgAhAgsgASgCACACIANBIGogA0ECdmoiA0sEfyACBSADIgILQQJ0EFciA0UEQEEAJAVBFEGs9QIQDCMFIQdBACQFIAdBAXENBAsgASADNgIAIAQgAjYCAAsCfyAAQZi8A2ooAgBBA0YEQCAFKAIAIQAgASgCACECIAYoAgAhA0EAJAVBFSAAIAIgAxAHGiMFIQBBACQFIABBAXENBAUgBSgCACECIAEoAgAhAyAAQYyuAmooAgBBAXFFBEAgBigCACEAQQAkBUERIAIgAyAAEAcaIwUhAEEAJAUgAEEBcQ0FIAEMAgtBACQFQRYgAiADIAtBAXYiABAHGiMFIQJBACQFIAJBAXENBCABKAIAIABBAnRqQQA2AgALIAELIgAoAgAiAxBZIQAgBCgCACECIAYgADYCACACIABJBEAgASgCDCIHQQBHIAAgB0txBEBBACQFIAogBzYCAEECQaz1AkHYGyAKEA4jBSEAQQAkBSAAQQFxDQRBACQFQRRBrPUCEAwjBSEAQQAkBSAAQQFxDQQgASgCACEDIAQoAgAhAiAGKAIAIQALIAMgACACQSBqIAJBAnZqIgJLBH8gAAUgAiIAC0ECdBBXIgJFBEBBACQFQRRBrPUCEAwjBSEDQQAkBSADQQFxDQQLIAEgAjYCACAEIAA2AgALQQEFQQALIQAgBSgCACIBRQRAIAkkBCAADwsgARBSIAkkBCAADwsLEBchACAFKAIAIgFFBEAgABAeCyABEFIgABAeQQALBgAgACQHC68XAgx/An4jBCEIIwRBgNADaiQEIABBnrwDaiwAAEUEQCAIJARBAA8LIAhBqM8DaiEKIAhBoM8DaiEMIAhBmM8DaiELIAhBkM8DaiENIAhB2M0DaiEHIAhBsM8DaiEEIAhBrM8DaiEJIAAgACgCACgCFEEHcUGGAWoRAAAhDwJAAkACQAJAAkAgAEGYvANqIgYoAgBBAUYEQCAAKAIAKAIQIQIgAEGovANqKAIAQQdqrSEOQQAkBSACIAAgDqcgDkIgiKdBABBQIwUhAkEAJAUgAkEBcUUEQEEAJAVBCCAAEAUhAiMFIQNBACQFIANBAXFFBEBBACQFQQggABAFIQMjBSEFQQAkBSAFQQFxRQRAIANB/wFxQQh0IAJB/wFxciECDAULCwsFIAAoAgAoAhAhAiAAQdSmAWosAABFBEBBACQFQQQgABBOrSMHrUIghoQhDiMFIQNBACQFIANBAXENAkEAJAUgAiAAIA6nIA5CIIinQQAQUCMFIQJBACQFIAJBAXENAkEAJAVBCCAAQYwOEAYhAiMFIQNBACQFIANBAXENAiACRQRAQQAhAQwFC0EAJAVBCSAAIAEQBiEBIwUhAkEAJAUgAkEBcQ0CDAQLIABBqLwDaigCAEEUaq0hDkEAJAUgAiAAIA6nIA5CIIinQQAQUCMFIQJBACQFIAJBAXFFBEBBACQFQQYgABAFGiMFIQJBACQFIAJBAXFFBEAgAEGsvANqLAAARQRAIABB/LMDaigCAEHz/wNqIQIMBQsgCEEANgJEIAhBOTYCSCAIQUBrQQE2AgAgCCAAQRhqNgIAQQAkBSMFIQFBACQFIAFBAXFFBEBBACEBDAYLCwsLCxAXIQEMAgsCQAJAIAYoAgBBAUYEQCAAQdWmAWosAABFDQEFIABBh7QDaiwAAEEwRg0BIABBhrQDaiwAAEFxakEYdEEYdUH/AXFBDkoEQEEAIQEMBAsgAEGHtANqLQAAQTVKBEBBACEBDAQLC0EAJAVBFiAHEAwjBSEDQQAkBSADQQFxBEAQFyEBBSAHQQE6ACkCQAJAIAYoAgBBAUYEf0EAJAVBCCAAEAUhAyMFIQVBACQFIAVBAXENAUEAJAVBCCAAEAUhBSMFIQpBACQFIApBAXENAUEAJAVBFyAHEAwjBSEKQQAkBSAKQQFxDQEgAEGGtANqQQ86AAAgAkH+/wNqIQIgBUH/AXFBCHQgA0H/AXFyBSAAQYS0A2ovAQALIQNBACQFQQMgByAAQQAQDiMFIQVBACQFIAVBAXENACAHQQA6ACggByACQf//A3GtNwMgQQAkBUEEIAdBqAFqIgJBAkEBEA4jBSEFQQAkBSAFQQFxDQBBACQFQQcgCCAHEA0jBSEFQQAkBSAFQQFxBEAQFyEBBUEAJAVBBSAIQYCABEEAEA4jBSEFQQAkBQJAAkAgBUEBcQ0AIAhBsJgBaiADrTcDACAIQciYAWpBADoAACAAQYa0A2otAAAhA0EAJAVBBiAIIANBABAOIwUhA0EAJAUgA0EBcQ0AIAYoAgBBAUcEQEEAJAVBCSACEAUhAiMFIQNBACQFIANBAXENASAAQYi0A2ovAQAgAkH//wNxRwRAIARBADYCRCAEQTk2AkggBEFAa0EBNgIAIAQgAEEYajYCAEEAJAUjBSEBQQAkBSABQQFxDQIgCBCVASAHEIQBQQAhAQwKCwtBACQFQQcgByAEIAkQDiMFIQJBACQFAkAgAkEBcUUEQCABQQhqIgUoAgAhBiABQQRqIgMgCSgCAEEBaiICNgIAIAYgAkkEQCABKAIMIgpBAEcgAiAKS3EEQEEAJAUgDSAKNgIAQQJBrPUCQdgbIA0QDiMFIQJBACQFIAJBAXENA0EAJAVBFEGs9QIQDCMFIQJBACQFIAJBAXENAyAFKAIAIQYgAygCACECCyABKAIAIAIgBkEgaiAGQQJ2aiIGSwR/IAIFIAYiAgtBAnQQVyIGRQRAQQAkBUEUQaz1AhAMIwUhCkEAJAUgCkEBcQ0DCyABIAY2AgAgBSACNgIAIAMoAgAhAgsgASgCAEEAIAJBAnQQVBogBCgCACECIAEoAgAhBiAJKAIAIQRBACQFQREgAiAGIAQQBxojBSECQQAkBSACQQFxDQEgASgCACIEEFkhAiAFKAIAIQYgAyACNgIAIAYgAkkEQCABKAIMIglBAEcgAiAJS3EEQEEAJAUgCyAJNgIAQQJBrPUCQdgbIAsQDiMFIQJBACQFIAJBAXENA0EAJAVBFEGs9QIQDCMFIQJBACQFIAJBAXENAyAFKAIAIQYgAygCACECIAEoAgAhBAsgBCACIAZBIGogBkECdmoiBksEfyACBSAGIgILQQJ0EFciBkUEQEEAJAVBFEGs9QIQDCMFIQRBACQFIARBAXENAwsgASAGNgIAIAUgAjYCAAsgCBCVASAHEIQBIAMhAQwJCwsQFyEBDAELEBchAQsgCBCVAQsMAQsQFyEBCyAHEIQBCwwDCyACQf//A3EiBQRAQQAgBUEgSwR/IAUFQSALIgMQVyICRQRAQQAkBUEUQaz1AhAMIwUhAkEAJAUgAkEBcQRAEBchAQwFBUEAIQILCwVBACECQQAhAwsgACgCACgCDCEEQQAkBSAEIAAgAiAFEAcaIwUhBEEAJAUCQCAEQQFxBEAgAiEBBSAGKAIAQQFHBEAgAEGItANqLwEAIQZBACQFQRNBfyACIAUQByEEIwUhCUEAJAUgCUEBcQRAIAIhAQwDCyAEQf//A3FB//8DcyAGQf//A3FHBEAgB0EANgJEIAdBOTYCSCAHQUBrQQE2AgAgByAAQRhqNgIAQQAkBSMFIQFBACQFIAFBAXEEQCACIQEMBAsgAkUEQEEAIQEMBgsgAhBSQQAhAQwFCwsgAUEIaiILKAIAIQkgAUEEaiIGIAVBAWoiBzYCACAJIAVNBEAgASgCDCIEQQBHIAUgBE9xBH9BACQFIAwgBDYCAEECQaz1AkHYGyAMEA4jBSEEQQAkBSAEQQFxBEAgAiEBDAQLQQAkBUEUQaz1AhAMIwUhBEEAJAUgBEEBcQRAIAIhAQwECyALKAIAIQkgBigCAAUgBwshBCABKAIAIAQgCUEgaiAJQQJ2aiIJSwR/IAQFIAkiBAtBAnQQVyIJRQRAQQAkBUEUQaz1AhAMIwUhDEEAJAUgDEEBcQRAIAIhAQwECwsgASAJNgIAIAsgBDYCAAsgBSADTwRAIAIgByADQSBqIANBAnZqIgNLBH8gBwUgAwsQVyIDBEAgAyECBUEAJAVBFEGs9QIQDCMFIQNBACQFIANBAXEEQCACIQEMBAVBACECCwsLIAIgBWpBADoAACABKAIAIQNBACQFQREgAiADIAUQBxojBSEDQQAkBSADQQFxBEAgAiEBBSABKAIAIgcQWSEEIAsoAgAhBSAGIAQ2AgAgBSAESQRAIAEoAgwiA0EARyAEIANLcQR/QQAkBSAKIAM2AgBBAkGs9QJB2BsgChAOIwUhA0EAJAUgA0EBcQRAIAIhAQwFC0EAJAVBFEGs9QIQDCMFIQNBACQFIANBAXEEQCACIQEMBQsgASEDIAsoAgAhBSAGKAIAIQEgAygCAAUgASEDIAQhASAHCyABIAVBIGogBUECdmoiBEsEfyABBSAEIgELQQJ0EFciBEUEQEEAJAVBFEGs9QIQDCMFIQVBACQFIAVBAXEEQCACIQEMBQsLIAMgBDYCACALIAE2AgALIAJFBEAgBiEBDAQLIAIQUiAGIQEMAwsLCxAXIQIgAUUEQCACIQEMAwsgARBSIAIhAQwCCyABKAIAQQBHIQELIAAoAgAoAhAhAkEAJAUgAiAAIA+nIA9CIIinQQAQUCMFIQBBACQFIABBAXEEQEEAEBgQWgUgCCQEIAEPCwwBCyAAKAIAKAIQIQJBACQFIAIgACAPpyAPQiCIp0EAEFAjBSEAQQAkBSAAQQFxBEBBABAYEFoFIAEQHgsLQQALUAICfwF+IwQhASMEQRBqJAQCf0EAIABB2PMAaiICQegxaiwAAEUNABogASACQbAyaikDADcDAEEBCwR+IAEpAwAFIAAQ0wELIQMgASQEIAMLHQAgAEHY8wBqIAEgAhCQBARADwsgACABIAIQnAELOwEBfyMEIQMjBEEQaiQEIABB2PMAaiABIAIgAxCqBARAIAMoAgAhAAUgACABIAIQ1AEhAAsgAyQEIAALFwAgAEHApQFqQQA6AAAgACABIAIQmAILCgAgABB+IAAQUgscACABIAKtIAOtQiCGhCAEIABBA3FBuAJqEQIACxoAIAEgAq0gA61CIIaEIABBA3FBtAJqERcACx0BAX4gASAAQQdxQYYBahEAACICQiCIpyQHIAKnCyIAIAGtIAKtQiCGhCADrSAErUIghoQgAEEBcUGEAWoREgALJgAgASACIAMgBCAFIAatIAetQiCGhCAIIAkgAEEBcUGCAWoREQALBgBBFRAACwYAQRQQAAsmAEGs9QJBADYCAEGw9QJBADYCAEG09QJBAToAAEG19QJBADYAAAsGAEEPEAALCABBChAAQQALCABBCRAAQQALIwAgASAAUwR/QeQABSABQgBRBH9BAAUgAELkAH4gAX+nCwsLEAAjBUUEQCAAJAUgASQGCwsIAEEIEABBAAsIAEEGEABBAAsIAEEEEABBAAsPAEEAEABEAAAAAAAAAAALIgAgASACIAMgBCAFIAYgByAIIAkgCiAAQQFxQbICahEWAAsgACABIAIgAyAEIAUgBiAHIAggCSAAQQFxQbACahEVAAsaACABIAIgAyAEIAUgBiAAQQdxQagCahELAAsYACABIAIgAyAEIAUgAEEHcUGgAmoRDAALFgAgASACIAMgBCAAQQdxQZgCahEKAAsUACABIAIgAyAAQR9xQfgBahEHAAsUACABIAIgAyAAQQFxQfYBahEUAAsSACABIAIgAEEfcUHWAWoRBgALEAAgASAAQT9xQZYBahETAAsOACAAQQdxQY4BahEIAAsgACABIAIgAyAEIAUgBiAHIAggCSAAQQFxQYABahEQAAsaACABIAIgAyAEIAUgBiAAQQNxQfwAahEPAAsYACABIAIgAyAEIAUgAEEBcUH6AGoRDgALFgAgASACIAMgBCAAQQ9xQeoAahEDAAsUACABIAIgAyAAQR9xQcoAahEBAAsRACABIAIgAEEfcUEqahEEAAsPACABIABBH3FBCmoRCQALDgAgASACIABBAXERDQALGgAgAAR/IABBsApBmAtBABCaAUEARwVBAAsLSQEBfyMEIQMjBEEQaiQEIAMgAigCADYCACAAIAEgAyAAKAIAKAIQQR9xQcoAahEBACIABEAgAiADKAIANgIACyADJAQgAEEBcQt1AQJ/AkAgACABKAIIRgRAQQAgASACIAMQwQEFIABBEGogACgCDCIEQQN0aiEFIABBEGogASACIAMQ+QEgBEEBSgRAIAFBNmohBCAAQRhqIQADQCAAIAEgAiADEPkBIAQsAAANAyAAQQhqIgAgBUkNAAsLCwsLrAUBCX8CQCAAIAEoAghGBEAgASgCBCACRgRAIAFBHGoiACgCAEEBRwRAIAAgAzYCAAsLBSAAIAEoAgBHBEAgACgCDCEFIABBEGogASACIAMgBBCrASAFQQFMDQIgAEEQaiAFQQN0aiEHIABBGGohBSAAKAIIIgZBAnFFBEAgAUEkaiIAKAIAQQFHBEAgBkEBcUUEQCABQTZqIQYDQCAGLAAADQYgACgCAEEBRg0GIAUgASACIAMgBBCrASAFQQhqIgUgB0kNAAwGCwALIAFBGGohBiABQTZqIQgDQCAILAAADQUgACgCAEEBRgRAIAYoAgBBAUYNBgsgBSABIAIgAyAEEKsBIAVBCGoiBSAHSQ0ADAULAAsLIAFBNmohAANAIAAsAAANAyAFIAEgAiADIAQQqwEgBUEIaiIFIAdJDQAMAwsACyABKAIQIAJHBEAgAUEUaiILKAIAIAJHBEAgASADNgIgIAFBLGoiDCgCAEEERg0DIABBEGogACgCDEEDdGohDSABQTRqIQcgAUE1aiEGIAFBNmohCCAAQQhqIQkgAUEYaiEKQQAhAyAAQRBqIQVBACEAAn8CQAJAA0AgBSANTw0BIAdBADoAACAGQQA6AAAgBSABIAIgAkEBIAQQvwEgCCwAAA0BAkAgBiwAAARAIAcsAABFBEAgCSgCAEEBcQRAQQEhAwwDBUEBIQMMBQsACyAKKAIAQQFGDQQgCSgCAEECcUUNBEEBIQNBASEACwsgBUEIaiEFDAALAAsgAEUEQCALIAI2AgAgAUEoaiIAIAAoAgBBAWo2AgAgASgCJEEBRgRAIAooAgBBAkYEQCAIQQE6AAAgAw0DQQQMBAsLCyADDQBBBAwBC0EDCyEAIAwgADYCAAwDCwsgA0EBRgRAIAFBATYCIAsLCwuAAgEIfyAAIAEoAghGBEBBACABIAIgAyAEEMABBSABQTRqIgYsAAAhCSABQTVqIgcsAAAhCiAAQRBqIAAoAgwiCEEDdGohCyAGQQA6AAAgB0EAOgAAIABBEGogASACIAMgBCAFEL8BAkAgCEEBSgRAIAFBGGohDCAAQQhqIQggAUE2aiENIABBGGohAANAIA0sAAANAiAGLAAABEAgDCgCAEEBRg0DIAgoAgBBAnFFDQMFIAcsAAAEQCAIKAIAQQFxRQ0ECwsgBkEAOgAAIAdBADoAACAAIAEgAiADIAQgBRC/ASAAQQhqIgAgC0kNAAsLCyAGIAk6AAAgByAKOgAACwu2AQECfwJAIAJBf2oiBARAQQAhAgNAAkACQAJAIAAgAmosAAAiAw5dAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIBAgsMBAtBLyEDCyABIAJqIAM6AAAgAkEBaiICIARJDQALBUEAIQILCyABIAJqQQA6AAAL4wIBAn8jBCEDIwRBQGskBCACIAIoAgAoAgA2AgAgACABRgR/QQEFIAFBwAtGCwR/QQEFIAEEfyABQbAKQZgLQQAQmgEiAQR/IAEoAgggACgCCEF/c3EEf0EABSAAQQxqIgAoAgAgAUEMaiIBKAIARgR/QQEFIAAoAgBBuAtGBH9BAQUgACgCACIABH8gAEGwCkGgCkEAEJoBIgQEfyABKAIAIgAEfyAAQbAKQaAKQQAQmgEiAQR/IANBBGoiAEIANwIAIABCADcCCCAAQgA3AhAgAEIANwIYIABCADcCICAAQgA3AiggAEEANgIwIAMgATYCACADIAQ2AgggA0F/NgIMIANBATYCMCABIAMgAigCAEEBIAEoAgAoAhxBB3FBmAJqEQoAIAMoAhhBAUYEfyACIAMoAhA2AgBBAQVBAAsFQQALBUEACwVBAAsFQQALCwsLBUEACwVBAAsLIQAgAyQEIAALMQECfyAAKAIAQXRqIgFBCGoiAigCACEAIAIgAEF/ajYCACAAQX9qQQBIBEAgARBSCwsKACAAQQRqKAIACwYAQZXzAAtpAQJ/QQAkBUEFEAQhACMFIQFBACQFIAFBAXEEQEEAEBgQWgsgAARAIAAoAgAiAARAIAApAzBCgH6DQoDWrJn0yJOmwwBRBEAgACgCDBD9AQsLCwJ/QegkQegkKAIAIgA2AgAgAAsQ/QELLwEBfyMEIQEjBEEQaiQEIAAQUkGsvAMoAgBBABBKBEBBhvIAIAEQggEFIAEkBAsLggEBAn8gACgCACICRQRADwsgAQR/QcQNBUHgDQshAyABBEAgAiEBBSACIQEDQCADIAEQdARAIABB3wA2AgALIABBBGoiACgCACIBDQALDwsDQAJAAkAgAyABEHQNACAAKAIAQSBJDQAMAQsgAEHfADYCAAsgAEEEaiIAKAIAIgENAAsLKAEBfyMEIQAjBEEQaiQEQay8A0EtEEgEQEHU8QAgABCCAQUgACQECws6AQF/IAAgASgCCEYEQEEAIAEgAiADEMEBBSAAKAIIIgQgASACIAMgBCgCACgCHEEHcUGYAmoRCgALC8cCAQN/AkAgACABKAIIRgRAIAEoAgQgAkYEQCABQRxqIgAoAgBBAUcEQCAAIAM2AgALCwUgACABKAIARwRAIAAoAggiACABIAIgAyAEIAAoAgAoAhhBB3FBoAJqEQwADAILIAEoAhAgAkcEQCABQRRqIgUoAgAgAkcEQCABIAM2AiAgAUEsaiIDKAIAQQRGDQMgAUE0aiIGQQA6AAAgAUE1aiIHQQA6AAAgACgCCCIAIAEgAiACQQEgBCAAKAIAKAIUQQdxQagCahELAAJAAkAgBywAAARAIAYsAAAEQEEDIQAFQQMhAAwCCwVBBCEADAELDAELIAUgAjYCACABQShqIgIgAigCAEEBajYCACABKAIkQQFGBEAgASgCGEECRgRAIAFBAToANgsLCyADIAA2AgAMAwsLIANBAUYEQCABQQE2AiALCwsLQAEBfyAAIAEoAghGBEBBACABIAIgAyAEEMABBSAAKAIIIgYgASACIAMgBCAFIAYoAgAoAhRBB3FBqAJqEQsACwsYACAAIAEoAghGBEBBACABIAIgAxDBAQsLrgEAAkAgACABKAIIRgRAIAEoAgQgAkYEQCABQRxqIgAoAgBBAUcEQCAAIAM2AgALCwUgACABKAIARgRAIAEoAhAgAkcEQCABQRRqIgAoAgAgAkcEQCABIAM2AiAgACACNgIAIAFBKGoiACAAKAIAQQFqNgIAIAEoAiRBAUYEQCABKAIYQQJGBEAgAUEBOgA2CwsgAUEENgIsDAQLCyADQQFGBEAgAUEBNgIgCwsLCwsaACAAIAEoAghGBEBBACABIAIgAyAEEMABCwvIAQECfyMEIQMjBEFAayQEIAAgAUYEf0EBBSABBH8gAUGwCkGgCkEAEJoBIgEEfyADQQRqIgRCADcCACAEQgA3AgggBEIANwIQIARCADcCGCAEQgA3AiAgBEIANwIoIARBADYCMCADIAE2AgAgAyAANgIIIANBfzYCDCADQQE2AjAgASADIAIoAgBBASABKAIAKAIcQQdxQZgCahEKACADKAIYQQFGBH8gAiADKAIQNgIAQQEFQQALBUEACwVBAAsLIQAgAyQEIAALlAICBX8BfiMEIQEjBEEwaiQEIAFBGGohAiABQRBqIQMgAUEkaiEEEP4BIgAEQCAAKAIAIgAEQCAAKQMwIgVCgH6DQoDWrJn0yJOmwwBSBEAgAkGY8AA2AgBB5u8AIAIQggELIABB0ABqIQIgBUKB1qyZ9MiTpsMAUQRAIAAoAiwhAgsgBCACNgIAIAAoAgAiACgCBCECQZgKIAAgBEGYCigCACgCEEEfcUHKAGoRAQAEQCAEKAIAIgAgACgCACgCCEEfcUEKahEJACEAIAFBmPAANgIAIAEgAjYCBCABIAA2AghBkO8AIAEQggEFIANBmPAANgIAIAMgAjYCBEG97wAgAxCCAQsLC0GM8AAgAUEgahCCAQsNACAAIAEgARBZEKADC7AEAQl/IAFB7////wNLBEAgABCKAQsgAEEIaiIIQQNqIgosAAAiBUEASCIJBH8gCCgCAEH/////B3FBf2ohAiAAKAIEBUEBIQIgBUH/AXELIgcgAUsEfyAHIgEFIAELQQJJIQMgAUEEakF8cUF/aiEBAkAgAwR/QQEiAQUgAQsgAkcEQAJAAn8gAwRAIAAoAgAhBCAJBEAgBCEDQQAhBSAAIQQFIAAgBCAFQf8BcUEBahCPARogBBBSDAMLBSABQQFqIgNB/////wNLIQYCQCABIAJLBEAgBkUEQCADQQJ0EF8hBAwCC0EIEBQhAkEAJAVBFyACQczuABANIwUhBkEAJAUgBkEBcQRAEBchBiACEBogBhAeBSACQewlNgIAIAJB+ApBDBAbCwUCQAJAIAYEQEEIEBQhAUEAJAVBFyABQczuABANIwUhAEEAJAUgAEEBcQRAQQAQGCEAIAEQGgUgAUHsJTYCAEEAJAVBGCABQfgKQQwQDkEAJAUMAgsFQQAkBUEEIANBAnQQBSEEIwUhAkEAJAUgAkEBcQ0BDAQLDAELQQAQGCEACyAAEBUaEBYMBgsLIAkEQCAAKAIAIQNBASEFBSAEIAAgBUH/AXFBAWoQjwEaIABBBGoMAgsLIAQgAyAAQQRqIgIoAgBBAWoQjwEaIAMQUiAFRQ0BIAFBAWohAyACCyEBIAggA0GAgICAeHI2AgAgASAHNgIAIAAgBDYCAAwCCyAKIAc6AAALCwv5AgEFfyMEIQkjBEEQaiQEQe7///8DIAFrIAJJBEAgABCKAQsgAEEIaiIMLAADQQBIBH8gACgCAAUgAAshCiABQef///8BSQRAIAIgAWoiCCABQQF0IgJJBH8gAgUgCCICC0EEakF8cSEIIAJBAkkEf0ECBSAICyICQf////8DSwRAQQgQFCECQQAkBUEXIAJBzO4AEA0jBSEIQQAkBSAIQQFxBEAQFyEIIAIQGiAIEB4FIAJB7CU2AgAgAkH4CkEMEBsLBSACIQsLBUHv////AyELCyALQQJ0EF8hAiAEBEAgAiAKIAQQjwEaCyAGBEAgAiAEQQJ0aiAHIAYQjwEaCyADIAVrIgMgBGsiBwRAIAIgBEECdGogBkECdGogCiAEQQJ0aiAFQQJ0aiAHEI8BGgsgAUEBRwRAIAoQUgsgACACNgIAIAwgC0GAgICAeHI2AgAgACADIAZqIgA2AgQgCUEANgIAIAIgAEECdGogCSgCADYCACAJJAQLPAEBfyACBEBBACQFQR8gACABIAIQBxojBSEBQQAkBSABQQFxBEBBABAYIgAQWgUgACEDCwUgACEDCyADC7gBAQV/IwQhBSMEQRBqJAQgAEEIaiIEQQNqIgYsAAAiA0EASCIHBH8gBCgCAEH/////B3FBf2oFQQELIgQgAkkEQCAAIAQgAiAEayAHBH8gACgCBAUgA0H/AXELIgNBACADIAIgARCeAwUgBwR/IAAoAgAFIAALIgMgASACEJ8DGiAFQQA2AgAgAyACQQJ0aiAFKAIANgIAIAYsAABBAEgEQCAAIAI2AgQFIAYgAjoAAAsLIAUkBCAAC+0BAQR/IAAgABBZQQJ0aiECA0AgAkF8aiICIABLIAIoAgBBUGpBCklBAXNxBEAMAQUgAiEBCwsDQCABQXxqIQQgASAASyIDIAEoAgBBUGpBCklxBEAgBCEBDAELCyADRQRAIAIPCwJAAkADQCABKAIAIgRBLkYNAiAEQVBqQQpJDQEgAUF8aiIBIABLDQAMAgsACyAAEFkhAwJAAkADQCADQQBKBEAgACADQX9qIgRBAnRqKAIAQS9GDQIgBCEDDAELCwwBCyAAIANBAnRqIQALIABBLhB0IgBBAEcgACABSXEEfyABBSACCw8LIAILDQAgACABIAEQbhD/AQvmAgEIfyABQW9LBEAgABCKAQsgAEELaiIJLAAAIgVBAEgiBAR/IAAoAghB/////wdxQX9qIQYgACgCBAVBCiEGIAVB/wFxCyIHIAFLBH8gByIBBSABC0ELSSEDIAFBEGpBcHFBf2ohAQJAIAMEf0EKBSABCyIIIAZHBEACQAJAIAMEQCAAKAIAIQIgBARAQQAhBCAAIQEFIAAgAiAFQf8BcUEBahCJARogAhBSDAMLBSAIQQFqIQIgCCAGSwRAIAIQXyEBBUEAJAVBBCACEAUhASMFIQNBACQFIANBAXEEQEEAEBgQFRoQFgwGCwsgBARAIAAoAgAhAkEBIQQFIAEgACAFQf8BcUEBahCJARogAEEEaiEDDAILCyABIAIgAEEEaiIDKAIAQQFqEIkBGiACEFIgBEUNASAIQQFqIQILIAAgAkGAgICAeHI2AgggAyAHNgIAIAAgATYCAAwCCyAJIAc6AAALCwuCAgEDfyMEIQkjBEEQaiQEQW4gAWsgAkkEQCAAEIoBCyAALAALQQBIBH8gACgCAAUgAAshCiABQef///8HSQR/IAIgAWoiCCABQQF0IgJJBH8gAgUgCCICC0EQakFwcSEIIAJBC0kEf0ELBSAICwVBbwsiAhBfIQggBARAIAggCiAEEIkBGgsgBgRAIAggBGogByAGEIkBGgsgAyAFayIDIARrIgcEQCAIIARqIAZqIAogBGogBWogBxCJARoLIAFBCkcEQCAKEFILIAAgCDYCACAAIAJBgICAgHhyNgIIIAAgAyAGaiIANgIEIAlBADoAACAIIABqIAksAAA6AAAgCSQEC0oBBH8gACABRwRAIAEsAAsiAkEASCEDIAEoAgAhBCABKAIEIQUgAkH/AXEhAiAAIAMEfyAEBSABCyADBH8gBQUgAgsQ/wEaCyAAC7QBAQR/IwQhAyMEQRBqJAQgAEIANwIAIABBADYCCCABLAALQQBIBEAgASgCACEEIAEoAgQiAkFvSwRAIAAQigELIAJBC0kEQCAAIAI6AAsFIAAgAkEQakFwcSIFEF8iATYCACAAIAVBgICAgHhyNgIIIAAgAjYCBCABIQALIAAgBCACEIkBGiADQQA6AAAgACACaiADLAAAOgAABSAAIAEpAgA3AgAgACABKAIINgIICyADJAQLLwAgAEHYJTYCAEEAJAVBGCAAQQRqIAEQDSMFIQBBACQFIABBAXEEQBAXIgAQHgsLPAECfyABEG4iA0ENahBfIgIgAzYCACACIAM2AgQgAkEANgIIIAJBDGoiAiABIANBAWoQUxogACACNgIACwYAIAAQXwspAQF/IwQhBCMEQRBqJAQgBCADNgIAIAAgASACIAQQgAIhACAEJAQgAAtiAQR/An8CQCABKAJMQQBIDQAMAAsgAEH/AXEhAyAAQf8BcSIEIAEsAEtHBEAgAUEUaiIFKAIAIgIgASgCEEkEQCAFIAJBAWo2AgAgAiADOgAAIAQMAgsLIAEgABCBAgsiAAuLAgEGfyMEIQQjBEEQaiQEQawjKAIAIQUgASwASkEBSARAIAFBARCFAhoLQawjIAEoAng2AgACQAJAIABBgAFJBEAgAEH/AXEhBiAAQf8BcSICIAEsAEtHBEAgAUEUaiIHKAIAIgMgASgCEEkEQCAHIANBAWo2AgAgAyAGOgAAIAIhAAwECwsgASAAEIECIQAFIAFBFGoiAigCACIDQQRqIAEoAhBJBEAgAyAAELABIgNBAEgNAiACIAIoAgAgA2o2AgAFIAQgABCwASICQQBIDQIgBCACIAEQjQIgAkkNAgsLIABBf0YNAAwBCyABIAEoAgBBIHI2AgBBfyEAC0GsIyAFNgIAIAQkBCAAC7kBAQR/IwQhBCMEQYABaiQEIARByABqIgNCADcCACADQgA3AgggA0IANwIQIANCADcCGCADQQA2AiAgBEHwAGoiBSACKAIANgIAQQAgASAFIAQgAxCEAkEASAR/QX8FAn8gACgCTBpBAAshAiAAQQEQhQIaIAAgACgCACIGQV9xNgIAIAAgASAFIAQgAxCEAiEBIAAgACgCACIDIAZBIHFyNgIAIANBIHEEf0F/BSABCwshACAEJAQgAAs8AQJ/AkAgACgCACIDBEAgACECA0AgASADEHRFDQIgAkEEaiICKAIAIgMNAAsFIAAhAgsLIAIgAGtBAnULbwEDfyAAIAFrQQJ1IAJJBEADQCAAIAJBf2oiAkECdGogASACQQJ0aigCADYCACACDQALBSACBEAgACEDA0AgAUEEaiEEIANBBGohBSADIAEoAgA2AgAgAkF/aiICBEAgBCEBIAUhAwwBCwsLCyAACzABAn8gAgRAIAAhAwNAIANBBGohBCADIAE2AgAgAkF/aiICBEAgBCEDDAELCwsgAAuTAgEBfwJAAkAgASAAc0EDcQ0AIAJBAEciAyABQQNxQQBHcQRAA0AgACABLAAAIgM6AAAgA0UNAyAAQQFqIQAgAkF/aiICQQBHIgMgAUEBaiIBQQNxQQBHcQ0ACwsgAwRAIAEsAAAEQCACQQNLBEADQCABKAIAIgNBgIGChHhxQYCBgoR4cyADQf/9+3dqcQ0EIAAgAzYCACABQQRqIQEgAEEEaiEAIAJBfGoiAkEDSw0ACwsMAgsFQQAhAgsMAQsgAgRAIAEhAyACIQEDQCAAIAMsAAAiAjoAACACRQRAIAEhAgwDCyADQQFqIQMgAEEBaiEAIAFBf2oiAQ0AQQAhAgsFQQAhAgsLIABBACACEFQaIAALaQEDfyAAIAAQWUECdGohAwJAIAIEQCACIQQgASECIAMhAQNAIAIoAgAiBUUNAiACQQRqIQIgAUEEaiEDIAEgBTYCACAEQX9qIgQEQCADIQEMAQUgAyEBCwsFIAMhAQsLIAFBADYCACAACzIAAkAgAgRAA0AgACgCACABRg0CIABBBGohACACQX9qIgINAEEAIQALBUEAIQALCyAAC3UBAn8CfyABKAIAIgIEfyABKAIERQRAIAAgAhB0IgEEQCABIABrQQJ1DAMFIAAQWQwDCwALAkAgACgCACIDBEAgACECA0AgASADEHQNAiACQQRqIgIoAgAiAw0ACwUgACECCwsgAiAAa0ECdQUgABBZCwsiAAtDAQF/IwQhAiMEQRBqJAQgAiAANgIAIAIgATYCBEHTACACECgiAEGAYEsEQEGIvANBACAAazYCAEF/IQALIAIkBCAAC5QBAQJ/IwQhAiMEQZAgaiQEIAJBCGohAwJAAkAgAARAIAEEQAwCBUGIvANBFjYCAEEAIQALBUGAICEBIAMhAAwBCwwBCyACIAA2AgAgAiABNgIEQbcBIAIQIyIBQYBgSwR/QYi8A0EAIAFrNgIAQX8FIAELQQBIBEBBACEABSAAIANGBEAgAxCHAiEACwsLIAIkBCAACz0BAX8gAEH/AXEiAUGAAUkEfyABBSAAQRh0QRh1Qf+/A3EhASAAQX9HQawjKAIAKAIARXEEfyABBUF/CwsLzgMBA38jBCEGIwRBEGokBAJAIAAEQAJAIAJBA0sEQCACIQQgASgCACEDA0ACQCADKAIAIgVBf2pB/gBLBH8gBUUNASAAIAVBABCRASIFQX9GBEBBfyECDAcLIAQgBWshBCAAIAVqBSAAIAU6AAAgBEF/aiEEIAEoAgAhAyAAQQFqCyEAIAEgA0EEaiIDNgIAIARBA0sNASAEIQMMAwsLIABBADoAACABQQA2AgAgAiAEayECDAMFIAIhAwsLIAMEQCAAIQQgASgCACEAAkACQANAIAAoAgAiBUF/akH+AEsEfyAFRQ0CIAYgBUEAEJEBIgVBf0YEQEF/IQIMBwsgAyAFSQ0DIAQgACgCAEEAEJEBGiAEIAVqIQQgAyAFawUgBCAFOgAAIARBAWohBCABKAIAIQAgA0F/agshAyABIABBBGoiADYCACADDQAMBQsACyAEQQA6AAAgAUEANgIAIAIgA2shAgwDCyACIANrIQILBSABKAIAIgAoAgAiAQRAQQAhAgNAIAFB/wBLBEAgBiABQQAQkQEiAUF/RgRAQX8hAgwFCwVBASEBCyABIAJqIQIgAEEEaiIAKAIAIgENAAsFQQAhAgsLCyAGJAQgAgvlCgETfyABKAIAIQQCfwJAIANFDQAgAygCACIFRQ0AIAAEfyADQQA2AgAgBSEPIAAhCyACIRIgBCEHQSsFIAUhCSAEIQggAiENQRkLDAELIABBAEchA0GsIygCACgCAARAIAMEQCAAIRQgAiETIAQhDkEPDAIFIAQhFSACIRZBDgwCCwALIANFBEAgBBBuIQxBOwwBCwJAIAIEQCAEIQMgACEFIAIhBANAIAMsAAAiCgRAIANBAWohAyAFQQRqIQYgBSAKQf+/A3E2AgAgBEF/aiIERQ0DIAYhBQwBCwsgBUEANgIAIAFBADYCACACIARrIQxBOwwCBSAEIQMLCyABIAM2AgAgAiEMQTsLIQMDQAJAAkACQCADQQ5GBEAgFSEEIBYhAwNAIAQsAAAiBUH/AXFBf2pB/wBJBEAgBEEDcUUEQCAEKAIAIgZB/wFxIQUgBkH//ft3aiAGckGAgYKEeHFFBEADQCADQXxqIQMgBEEEaiIEKAIAIgVB//37d2ogBXJBgIGChHhxRQ0ACyAFQf8BcSEFCwsLIAVB/wFxIgVBf2pB/wBJBEAgBEEBaiEEIANBf2ohAwwBCwsgBUG+fmoiBUEySwRAIAQhBSAAIQYMAwUgBUECdEGkHmooAgAhCSAEQQFqIQggAyENQRkhAwwFCwAFIANBD0YEQAJAIBMEQCAUIQQgEyEDIA4hBQNAAkACQCAFLAAAIgZB/wFxQX9qQf8ASQRAIANBBEsgBUEDcUVxBEACQANAIAUoAgAiBkH//ft3aiAGckGAgYKEeHENASAEIAZB/wFxNgIAIAQgBS0AATYCBCAEIAUtAAI2AgggBUEEaiEKIARBEGohBiAEIAUtAAM2AgwgA0F8aiIDQQRLBEAgBiEEIAohBQwBCwsgBiEEIAoiBSwAACEGDAMLIAZB/wFxIQYLCwsgBkH/AXEiCkF/akH/AE8NACAFQQFqIQUgBEEEaiEGIAQgCjYCACADQX9qIgNFDQMgBiEEDAELCyAKQb5+aiIGQTJLBEAgBCEGDAYLIAZBAnRBpB5qKAIAIQ8gBCELIAMhEiAFQQFqIQdBKyEDDAcFIA4hBQsLIAEgBTYCACACIQxBOyEDDAUFIANBGUYEQCAILQAAQQN2IgNBcGogAyAJQRp1anJBB0sEQCAAIQMgCSEGIAghBSANIQQMBAUgCEEBaiEDIAlBgICAEHEEfyADLAAAQcABcUGAAUcEQCAAIQMgCSEGIAghBSANIQQMBgsgCEECaiEDIAlBgIAgcQR/IAMsAABBwAFxQYABRwRAIAAhAyAJIQYgCCEFIA0hBAwHCyAIQQNqBSADCwUgAwshFSANQX9qIRZBDiEDDAcLAAUgA0ErRgRAIActAAAiBUEDdiIDQXBqIAMgD0EadWpyQQdLBEAgCyEDIA8hBiAHIQUgEiEEDAUFIAdBAWohBCAFQYB/aiAPQQZ0ciIDQQBIBEAgBC0AAEGAf2oiBUE/SwRAIAdBf2ohECALIREMCQsgB0ECaiEEIAUgA0EGdHIiA0EASARAIAQtAABBgH9qIgRBP0sEQCAHQX9qIRAgCyERDAoFIAdBA2ohDiAEIANBBnRyIQMLBSAEIQ4LBSAEIQ4LIAsgAzYCACALQQRqIRQgEkF/aiETQQ8hAwwICwAFIANBO0YEQCAMDwsLCwsLDAILIAVBf2ohBSAGBEAgBSEQIAMhEQUgAyEGIAQhAwwBCwwBCyAFLAAABEAgBSEQIAYhEQUgBgRAIAZBADYCACABQQA2AgALIAIgA2shDEE7IQMMAgsLQYi8A0HUADYCACARBEAgASAQNgIAC0F/IQxBOyEDDAALAAuJAQECfyAARQRADwsgACgCAEUEQA8LIAAQWSEEAkACQANAAkAgBEEATARAIAAhAwwBCyAAIARBf2oiA0ECdGooAgBBL0YNAiADIQQMAQsLDAELIAAgBEECdGohAwsgA0EuEK0BIgMEQCADQQA2AgALIAFFBEAPCyAAQeQMIAIQeBogACABIAIQeBoLpQIBA38jBCEEIwRBEGokBAJAIABBBksEf0EABUGYvAMQHCAAQQZHBEAgACABEIsCIQBBmLwDECoMAgsgAQRAIARBnOoAKQAANwAAIARBpOoAKQAANwAIQQAhAANAIAFBOxCRAiIDIAFrIgJBEEgEQCAEIAEgAhBTGiAEIAJqQQA6AAAgA0EBaiECIAMsAAAEQCACIQELCyAAIAQQiwIaIABBAWoiAEEGRw0ACwtBACEBQayKBCEAA0AgAUECdEHwuwNqKAIAIgJBCGohAyACBH8gAwVBrOoAIgMLEG4hAiAAIAMgAhBTGiAAIAJqIgNBOzoAACAAIAJBAWpqIQAgAUEBaiIBQQZHDQALIANBADoAAEGYvAMQKkGsigQLIQALIAQkBCAACzoBAn8gACgCECAAQRRqIgMoAgAiBGsiACACSwRAIAIhAAsgBCABIAAQUxogAyADKAIAIABqNgIAIAIL/BcDE38CfgJ8IwQhDSMEQbAEaiQEIA1BADYCACABvUIAUwRAIAGaIQFBASERQefpACEOBSAEQYAQcUUhBiAEQQFxBH9B7ekABUHo6QALIQ4gBEGBEHFBAEchESAGRQRAQerpACEOCwsgDUEIaiEJIA1BjARqIg8hEiANQYAEaiIIQQxqIRMCfyABvUKAgICAgICA+P8Ag0KAgICAgICA+P8AUQR/IAVBIHFBAEciAwR/QfrpAAVB/ukACyEFIAEgAWIhBiADBH9BguoABUGG6gALIQkgAEEgIAIgEUEDaiIDIARB//97cRBmIAAgDiAREGMgACAGBH8gCQUgBQtBAxBjIABBICACIAMgBEGAwABzEGYgAwUgASANEI4CRAAAAAAAAABAoiIBRAAAAAAAAAAAYiIGBEAgDSANKAIAQX9qNgIACyAFQSByIgtB4QBGBEAgDkEJaiEGIAVBIHEiBwRAIAYhDgsgA0ELS0EMIANrIgZFckUEQEQAAAAAAAAgQCEbA0AgG0QAAAAAAAAwQKIhGyAGQX9qIgYNAAsgDiwAAEEtRgR8IBsgAZogG6GgmgUgASAboCAboQshAQtBACANKAIAIglrIQYgCUEASAR/IAYFIAkLrCATEJIBIgYgE0YEQCAIQQtqIgZBMDoAAAsgEUECciEIIAZBf2ogCUEfdUECcUErajoAACAGQX5qIgkgBUEPajoAACADQQFIIQogBEEIcUUhDCAPIQUDQCAFIAcgAaoiBkGK6gBqLQAAcjoAACABIAa3oUQAAAAAAAAwQKIhASAFQQFqIgYgEmtBAUYEfyAMIAogAUQAAAAAAAAAAGFxcQR/IAYFIAZBLjoAACAFQQJqCwUgBgshBSABRAAAAAAAAAAAYg0ACwJ/AkAgA0UNAEF+IBJrIAVqIANODQAgA0ECaiEDIAUgEmsMAQsgBSASayIDCyEGIABBICACIBMgCWsiByAIaiADaiIFIAQQZiAAIA4gCBBjIABBMCACIAUgBEGAgARzEGYgACAPIAYQYyAAQTAgAyAGa0EAQQAQZiAAIAkgBxBjIABBICACIAUgBEGAwABzEGYgBQwCCyAGBEAgDSANKAIAQWRqIgc2AgAgAUQAAAAAAACwQaIhAQUgDSgCACEHCyAJQaACaiEGIAdBAEgEfyAJBSAGIgkLIQgDQCAIIAGrIgY2AgAgCEEEaiEIIAEgBrihRAAAAABlzc1BoiIBRAAAAAAAAAAAYg0ACyAHQQBKBEAgCSEGA0AgB0EdSAR/IAcFQR0LIQwgCEF8aiIHIAZPBEAgDK0hGUEAIQoDQCAHIAcoAgCtIBmGIAqtfCIaQoCU69wDgj4CACAaQoCU69wDgKchCiAHQXxqIgcgBk8NAAsgCgRAIAZBfGoiBiAKNgIACwsDQCAIIAZLBEAgCEF8aiIHKAIARQRAIAchCAwCCwsLIA0gDSgCACAMayIHNgIAIAdBAEoNAAsFIAkhBgsgA0EASAR/QQYFIAMLIQogB0EASARAIApBGWpBCW1BAWohECALQeYARiEVIAYhAyAIIQYDQEEAIAdrIgxBCU4EQEEJIQwLIAMgBkkEQEEBIAx0QX9qIRZBgJTr3AMgDHYhFEEAIQcgAyEIA0AgCCAIKAIAIhcgDHYgB2o2AgAgFyAWcSAUbCEHIAhBBGoiCCAGSQ0ACyADQQRqIQggAygCAEUEQCAIIQMLIAcEQCAGIAc2AgAgBkEEaiEGCwUgA0EEaiEIIAMoAgBFBEAgCCEDCwsgFQR/IAkFIAMLIgggEEECdGohByAGIAhrQQJ1IBBKBEAgByEGCyANIA0oAgAgDGoiBzYCACAHQQBIDQAgBiEHCwUgBiEDIAghBwsgCSEMIAMgB0kEQCAMIANrQQJ1QQlsIQYgAygCACIIQQpPBEBBCiEJA0AgBkEBaiEGIAggCUEKbCIJTw0ACwsFQQAhBgsgC0HnAEYhFSAKQQBHIRYgCiALQeYARwR/IAYFQQALayAWIBVxQR90QR91aiIJIAcgDGtBAnVBCWxBd2pIBH8gCUGAyABqIglBCW0hECAJQQlvIglBCEgEQEEKIQgDQCAJQQFqIQsgCEEKbCEIIAlBB0gEQCALIQkMAQsLBUEKIQgLIAwgEEECdGpBhGBqIgkoAgAiECAIcCELIAlBBGogB0YiFCALRXFFBEAgECAIbkEBcQR8RAEAAAAAAEBDBUQAAAAAAABAQwshHCALIAhBAm0iF0khGCAUIAsgF0ZxBHxEAAAAAAAA8D8FRAAAAAAAAPg/CyEBIBgEQEQAAAAAAADgPyEBCyARBEAgHJohGyAOLAAAQS1GIhQEQCAbIRwLIAGaIRsgFEUEQCABIRsLBSABIRsLIAkgECALayILNgIAIBwiASAboCABYgRAIAkgCyAIaiIGNgIAIAZB/5Pr3ANLBEADQCAJQQA2AgAgCUF8aiIJIANJBEAgA0F8aiIDQQA2AgALIAkgCSgCAEEBaiIGNgIAIAZB/5Pr3ANLDQALCyAMIANrQQJ1QQlsIQYgAygCACILQQpPBEBBCiEIA0AgBkEBaiEGIAsgCEEKbCIITw0ACwsLCyAGIQggByAJQQRqIgZNBEAgByEGCyADBSAGIQggByEGIAMLIQkDQAJAIAYgCU0EQEEAIRAMAQsgBkF8aiIDKAIABEBBASEQBSADIQYMAgsLC0EAIAhrIRQgFQRAIAogFkEBc0EBcWoiAyAISiAIQXtKcQR/IAVBf2ohBSADQX9qIAhrBSAFQX5qIQUgA0F/agshAyAEQQhxIgpFBEAgEARAIAZBfGooAgAiCwRAIAtBCnAEQEEAIQcFQQAhB0EKIQoDQCAHQQFqIQcgCyAKQQpsIgpwRQ0ACwsFQQkhBwsFQQkhBwsgBiAMa0ECdUEJbEF3aiEKIAVBIHJB5gBGBEAgAyAKIAdrIgdBAEoEfyAHBUEAIgcLTgRAIAchAwsFIAMgCiAIaiAHayIHQQBKBH8gBwVBACIHC04EQCAHIQMLC0EAIQoLBSAKIQMgBEEIcSEKCyAFQSByQeYARiIVBEBBACEHIAhBAEwEQEEAIQgLBSATIAhBAEgEfyAUBSAIC6wgExCSASIHa0ECSARAA0AgB0F/aiIHQTA6AAAgEyAHa0ECSA0ACwsgB0F/aiAIQR91QQJxQStqOgAAIAdBfmoiByAFOgAAIBMgB2shCAsgAEEgIAIgEUEBaiADaiADIApyIhZBAEdqIAhqIgsgBBBmIAAgDiAREGMgAEEwIAIgCyAEQYCABHMQZiAVBEAgD0EJaiIOIQogD0EIaiEIIAkgDEsEfyAMBSAJCyIHIQkDQCAJKAIArSAOEJIBIQUgCSAHRgRAIAUgDkYEQCAIQTA6AAAgCCEFCwUgBSAPSwRAIA9BMCAFIBJrEFQaA0AgBUF/aiIFIA9LDQALCwsgACAFIAogBWsQYyAJQQRqIgUgDE0EQCAFIQkMAQsLIBYEQCAAQZrqAEEBEGMLIAUgBkkgA0EASnEEQANAIAUoAgCtIA4QkgEiCSAPSwRAIA9BMCAJIBJrEFQaA0AgCUF/aiIJIA9LDQALCyAAIAkgA0EJSAR/IAMFQQkLEGMgA0F3aiEJIAVBBGoiBSAGSSADQQlKcQRAIAkhAwwBBSAJIQMLCwsgAEEwIANBCWpBCUEAEGYFIAlBBGohBSAQBH8gBgUgBQshDCADQX9KBEAgCkUhESAPQQlqIgohEEEAIBJrIRIgD0EIaiEOIAMhBSAJIQYDQCAGKAIArSAKEJIBIgMgCkYEQCAOQTA6AAAgDiEDCwJAIAYgCUYEQCADQQFqIQggACADQQEQYyARIAVBAUhxBEAgCCEDDAILIABBmuoAQQEQYyAIIQMFIAMgD00NASAPQTAgAyASahBUGgNAIANBf2oiAyAPSw0ACwsLIAAgAyAFIBAgA2siA0oEfyADBSAFCxBjIAZBBGoiBiAMSSAFIANrIgVBf0pxDQAgBSEDCwsgAEEwIANBEmpBEkEAEGYgACAHIBMgB2sQYwsgAEEgIAIgCyAEQYDAAHMQZiALCwshACANJAQgACACSAR/IAIFIAALCy4AIABCAFIEQANAIAFBf2oiASAAp0EHcUEwcjoAACAAQgOIIgBCAFINAAsLIAELNgAgAEIAUgRAA0AgAUF/aiIBIACnQQ9xQYrqAGotAAAgAnI6AAAgAEIEiCIAQgBSDQALCyABC/QCAQN/IwQhBCMEQYABaiQEIARB/ABqIQUgBEHkIykCADcCACAEQewjKQIANwIIIARB9CMpAgA3AhAgBEH8IykCADcCGCAEQYQkKQIANwIgIARBjCQpAgA3AiggBEGUJCkCADcCMCAEQZwkKQIANwI4IARBQGtBpCQpAgA3AgAgBEGsJCkCADcCSCAEQbQkKQIANwJQIARBvCQpAgA3AlggBEHEJCkCADcCYCAEQcwkKQIANwJoIARB1CQpAgA3AnAgBEHcJCgCADYCeAJAAkAgAUF/akH+////B00NACABBEBBiLwDQcsANgIAQX8hAAUgBSEAQQEhAQwBCwwBCyAEIAFBfiAAayIFSwR/IAUiAQUgAQs2AjAgBEEUaiIFIAA2AgAgBCAANgIsIARBEGoiBiAAIAFqIgA2AgAgBCAANgIcIAQgAiADEM4BIQAgAQRAIAUoAgAiASABIAYoAgBGQR90QR91akEAOgAACwsgBCQEIAALKQEBfyMEIQQjBEEQaiQEIAQgAzYCACAAIAEgAiAEEMADIQAgBCQEIAAL1gEBAn8CQCABIABzQQNxRQRAIAFBA3EEQANAIAAgASwAACICOgAAIAJFDQMgAEEBaiEAIAFBAWoiAUEDcQ0ACwsgASgCACICQYCBgoR4cUGAgYKEeHMgAkH//ft3anFFBEADQCAAQQRqIQMgACACNgIAIAFBBGoiASgCACICQYCBgoR4cUGAgYKEeHMgAkH//ft3anEEQCADIQAFIAMhAAwBCwsLCyAAIAEsAAAiAjoAACACBEADQCAAQQFqIgAgAUEBaiIBLAAAIgI6AAAgAg0ACwsLIAALjwIBA38gAUH/AXEhBAJAAkAgAkEARyIDIABBA3FBAEdxBEAgAUH/AXEhBQNAIAAtAAAgBUYNAiACQX9qIgJBAEciAyAAQQFqIgBBA3FBAEdxDQALCyADDQBBACEBDAELIAAtAAAgAUH/AXEiA0YEQCACIQEFIARBgYKECGwhBAJAAkAgAkEDSwRAIAIhAQNAIAAoAgAgBHMiAkGAgYKEeHFBgIGChHhzIAJB//37d2pxRQRAIABBBGohACABQXxqIgFBA0sNAQwDCwsFIAIhAQwBCwwBCyABRQRAQQAhAQwDCwsDQCAALQAAIANGDQIgAEEBaiEAIAFBf2oiAQ0AQQAhAQsLCyABBH8gAAVBAAsLQwEBfyMEIQIjBEEQaiQEIAIgADYCACACIAE2AgRB2wAgAhApIgBBgGBLBEBBiLwDQQAgAGs2AgBBfyEACyACJAQgAAuWBgEJfyMEIQIjBEGQAmokBCACQQhqIQUgAiEGAkAgASwAAEUEQEGe5QAQOyIBBEAgASwAAA0CCyAAQQxsQaXlAGoQOyIBBEAgASwAAA0CC0Ht5QAQOyIBBEAgASwAAA0CC0Hy5QAhAQsLQQAhAgNAAkACQAJAIAEgAmosAAAOMAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAELIAIhBAwBCyACQQFqIgJBD0kNASACIQQLCwJAAkACQCABLAAAIgJBLkYEQEHy5QAhAQUgASAEaiwAAARAQfLlACEBBSACQcMARw0CCwsgASwAAUUNAQsgAUHy5QAQiwFFDQAgAUH65QAQiwFFDQBBjLwDKAIAIgIEQANAIAEgAkEIahCLAUUNAyACKAIYIgINAAsLQZC8AxAcAkBBjLwDKAIAIgIEQANAIAEgAkEIahCLAQRAIAIoAhgiAkUNAwwBCwtBkLwDECoMAwsLAkACQEHQuwMoAgANAEGA5gAQOyICRQ0AIAIsAABFDQBB/gEgBGshCSAEQQFqIQoDQAJAIAJBOhCRAiIHLAAAIQMgByACayADQQBHQR90QR91aiIIIAlJBEAgBSACIAgQUxogBSAIaiICQS86AAAgAkEBaiABIAQQUxogBSAKIAhqakEAOgAAIAUgBhAdIgMNASAHLAAAIQMLIAcgA0H/AXFBAEdqIgIsAAANAQwCCwtBHBBsIgIEQCACIAM2AgAgAiAGKAIANgIEIAJBCGoiAyABIAQQUxogAyAEakEAOgAAIAJBjLwDKAIANgIYQYy8AyACNgIAIAIhAQUgAyAGKAIAEMQDGgwBCwwBC0EcEGwiAgRAIAJB3B0oAgA2AgAgAkHgHSgCADYCBCACQQhqIgMgASAEEFMaIAMgBGpBADoAACACQYy8AygCADYCGEGMvAMgAjYCAAsgAiEBC0GQvAMQKiAAIAFyBH8gAQVB3B0LIQIMAQsgAEUEQCABLAABQS5GBEBB3B0hAgwCCwtBACECCyAGJAQgAguKAwEKfyAAKAIIIAAoAgBBotrv1wZqIgYQjAEhBCAAKAIMIAYQjAEhAyAAKAIQIAYQjAEhBwJAIAQgAUECdkkEQCADIAEgBEECdGsiBUkgByAFSXEEQCAHIANyQQNxBEBBACEBBSADQQJ2IQogB0ECdiELQQAhBQNAAkAgACAFIARBAXYiB2oiDEEBdCIIIApqIgNBAnRqKAIAIAYQjAEhCSAAIANBAWpBAnRqKAIAIAYQjAEiAyABSSAJIAEgA2tJcUUEQEEAIQEMBgsgACADIAlqaiwAAARAQQAhAQwGCyACIAAgA2oQiwEiA0UNACAEQQFGIQggBCAHayEEIANBAEgiAwRAIAchBAsgA0UEQCAMIQULIAhFDQFBACEBDAULCyAAIAggC2oiAkECdGooAgAgBhCMASEFIAAgAkEBakECdGooAgAgBhCMASICIAFJIAUgASACa0lxBEAgACACaiEBIAAgAiAFamosAAAEQEEAIQELBUEAIQELCwVBACEBCwVBACEBCwsgAQueAQECfwJAAkACQANAIAJButYAai0AACAARg0BIAJBAWoiAkHXAEcNAEGS1wAhAEHXACECDAILAAsgAgRAQZLXACEADAEFQZLXACEACwwBCwNAIAAhAwNAIANBAWohACADLAAABEAgACEDDAELCyACQX9qIgINAAsLIAEoAhQiAQR/IAEoAgAgASgCBCAAEMYDBUEACyIBBH8gAQUgAAsLPAAgAEGAgAhJBH8gAEEIdkGaP2otAABBBXQgAEEDdkEfcXJBmj9qLQAAIABBB3F2QQFxBSAAQf7/C0kLC7IDAQt/IwQhBiMEQTBqJAQgBkEQaiEHIAZBIGoiAyAAQRxqIgkoAgAiBDYCACADIABBFGoiCigCACAEayIENgIEIAMgATYCCCADIAI2AgwgBiIIIABBPGoiDCgCADYCACAIIAM2AgQgCEECNgIIAkACQCAEIAJqIgZBkgEgCBAiIgVBgGBLBH9BiLwDQQAgBWs2AgBBfyIFBSAFC0YNAEECIQQgAyEBIAUhAwNAIANBAE4EQCAGIANrIQYgAUEIaiEFIAMgASgCBCINSyILBEAgBSEBCyAEIAtBH3RBH3VqIQQgASABKAIAIAMgCwR/IA0FQQALayIDajYCACABQQRqIgUgBSgCACADazYCACAHIAwoAgA2AgAgByABNgIEIAcgBDYCCCAGQZIBIAcQIiIDQYBgSwR/QYi8A0EAIANrNgIAQX8iAwUgAwtGDQIMAQsLIABBADYCECAJQQA2AgAgCkEANgIAIAAgACgCAEEgcjYCACAEQQJGBH9BAAUgAiABKAIEawshAgwBCyAAIAAoAiwiASAAKAIwajYCECAJIAE2AgAgCiABNgIACyAIJAQgAgsGAEGIvAMLeAEBfyMEIQMjBEEgaiQEIAMgACgCPDYCACADQQA2AgQgAyABNgIIIAMgA0EUaiIANgIMIAMgAjYCEEGMASADECAiAUGAYEsEf0GIvANBACABazYCAEF/BSABC0EASAR/IABBfzYCAEF/BSAAKAIACyEAIAMkBCAAC/4BAQZ/IwQhBCMEQSBqJAQgBEEQaiIFIAE2AgAgBUEEaiIHIAIgAEEwaiIIKAIAIgNBAEdrNgIAIAUgAEEsaiIGKAIANgIIIAUgAzYCDCAEIAAoAjw2AgAgBCAFNgIEIARBAjYCCEGRASAEECEiA0GAYEsEf0GIvANBACADazYCAEF/IgMFIAMLQQFIBEAgACAAKAIAIANBMHFBEHNyNgIAIAMhAgUgAyAHKAIAIgVLBEAgAEEEaiIHIAYoAgAiBjYCACAAIAYgAyAFa2o2AgggCCgCAARAIAcgBkEBajYCACABIAJBf2pqIAYsAAA6AAALBSADIQILCyAEJAQgAgs+AQF/IwQhASMEQRBqJAQgASAAKAI8NgIAQQYgARAmIgBBgGBLBEBBiLwDQQAgAGs2AgBBfyEACyABJAQgAAuyBwEKfwJAIABBBGoiBygCACIGQXhxIQIgBkEDcUUEQCABQYACSQ0BIAIgAUEEak8EQCACIAFrQaC7AygCAEEBdE0EQCAADwsLDAELIAAgAmohBCACIAFPBEAgAiABayICQQ9NBEAgAA8LIAcgBkEBcSABckECcjYCACAAIAFqIgEgAkEDcjYCBCAEQQRqIgMgAygCAEEBcjYCACABIAIQlQIgAA8LQdi3AygCACAERgRAQcy3AygCACACaiICIAFNDQEgByAGQQFxIAFyQQJyNgIAIAAgAWoiAyACIAFrIgFBAXI2AgRB2LcDIAM2AgBBzLcDIAE2AgAgAA8LQdS3AygCACAERgRAQci3AygCACACaiIDIAFJDQEgAyABayICQQ9LBEAgByAGQQFxIAFyQQJyNgIAIAAgAWoiASACQQFyNgIEIAAgA2oiAyACNgIAIANBBGoiAyADKAIAQX5xNgIABSAHIAZBAXEgA3JBAnI2AgAgACADakEEaiIBIAEoAgBBAXI2AgBBACEBQQAhAgtByLcDIAI2AgBB1LcDIAE2AgAgAA8LIAQoAgQiA0ECcQ0AIANBeHEgAmoiCCABSQ0AIAggAWshCiADQQN2IQUCQCADQYACSQRAIAQoAgwiAiAEKAIIIgNGBEBBwLcDQcC3AygCAEEBIAV0QX9zcTYCAAUgAyACNgIMIAIgAzYCCAsFIAQoAhghCQJAIAQoAgwiAiAERgRAIARBEGoiA0EEaiIFKAIAIgIEQCAFIQMFIAMoAgAiAkUEQEEAIQIMAwsLA0AgAkEUaiIFKAIAIgsEQCALIQIgBSEDDAELIAJBEGoiBSgCACILBEAgCyECIAUhAwwBCwsgA0EANgIABSAEKAIIIgMgAjYCDCACIAM2AggLCyAJBEAgBCgCHCIDQQJ0QfC5A2oiBSgCACAERgRAIAUgAjYCACACRQRAQcS3A0HEtwMoAgBBASADdEF/c3E2AgAMBAsFIAlBEGogCSgCECAER0ECdGogAjYCACACRQ0DCyACIAk2AhggBEEQaiIFKAIAIgMEQCACIAM2AhAgAyACNgIYCyAFKAIEIgMEQCACIAM2AhQgAyACNgIYCwsLCyAKQRBJBEAgByAIIAZBAXFyQQJyNgIAIAAgCGpBBGoiASABKAIAQQFyNgIABSAHIAZBAXEgAXJBAnI2AgAgACABaiIBIApBA3I2AgQgACAIakEEaiICIAIoAgBBAXI2AgAgASAKEJUCCyAADwtBAAsKACAAKAIEEIcCC5sDAEG4C0G3NRA4QcgLQbw1QQFBAUEAECxB0AtBwTVBAUGAf0H/ABAyQeALQcY1QQFBgH9B/wAQMkHYC0HSNUEBQQBB/wEQMkHoC0HgNUECQYCAfkH//wEQMkHwC0HmNUECQQBB//8DEDJB+AtB9TVBBEGAgICAeEH/////BxAyQYAMQfk1QQRBAEF/EDJBiAxBhjZBBEGAgICAeEH/////BxAyQZAMQYs2QQRBAEF/EDJBmAxBmTZBBBAxQaAMQZ82QQgQMUHICEGmNhA0QZgJQbI2EDRB6AhBBEHTNhA1QbAJQeA2EDBBuAlBAEHwNhAzQcAJQQBBjjcQM0HICUEBQbM3EDNB0AlBAkHaNxAzQdgJQQNB+TcQM0HgCUEEQaE4EDNB6AlBBUG+OBAzQfAJQQRB5DgQM0H4CUEFQYI5EDNBwAlBAEGpORAzQcgJQQFByTkQM0HQCUECQeo5EDNB2AlBA0GLOhAzQeAJQQRBrToQM0HoCUEFQc46EDNBgApBBkHwOhAzQYgKQQdBjzsQM0GQCkEHQa87EDMLBwBBABDQAwsEAEEBCzwBAX8jBCEBIwRBEGokBCABQQA6AAAgACABQQEgACgCACgCDEEfcUHKAGoRAQAaIAEsAAAhACABJAQgAAsWACACRQRAQQEPCyAAKAIEIAEgAhBDCysAIAAgAUEAIAAoAgAoAghBH3FBygBqEQEABEBBAQ8LQaz1AiABELgEQQAL5gICA38DfiAAQQRqIgUoAgAiBEUEQEEBDwsgAachAyABQgBTIAJBAEdxBEAgACAAKAIAKAIUQQdxQYYBahEAACEGAkAgAkEBRgRAIAYhBwUgACgCACgCECECQQAkBSACIABBAEEAQQIQUCMFIQJBACQFIAJBAXFFBEAgACgCACgCFCECQQAkBSACIAAQTq0jB61CIIaEIQgjBSECQQAkBSACQQFxRQRAIAAoAgAoAhAhAkEAJAUgAiAAIAanIAZCIIinQQAQUCMFIQJBACQFIAJBAXFFBEAgCCEHDAQLQQAQGBBaCwsQFyECIAAoAgAoAhAhA0EAJAUgAyAAIAanIAZCIIinQQAQUCMFIQNBACQFIANBAXEEQEEAEBgQWgUgAhAeCwsLQQAhAiAHIAF8pyEDIAUoAgAhBAsgAEEAOgAIIAJBAUYhACACBH9BqTUFQaU1CyECIAQgAyAABH9BrTUFIAILEEILXAEBfyAAQcQdNgIAIAAoAgQiAUUEQCAAEFIPCyAALAAQBEAgABBSDwsgACwAEgRAQQAkBQVBACQFQSwgARAMCyMFIQFBACQFIAFBAXFFBEAgABBSDwtBABAYEFoLGQAgAEECRwRAQQEPCyACQZyBBBDQARpBAQsPACABIAAoAgBqIAI5AwALDQAgASAAKAIAaisDAAtNAQF/QcgAEF8iAEIANwMAIABCADcDCCAAQgA3AxAgAEIANwMYIABCADcDICAAQgA3AyggAEIANwMwIABCADcDOCAAQUBrQgA3AwAgAAs0ACADQQJGBH8gACABIAIQugEFIAAgASACEHsLGiACRQRADwsgASACQX9qQQJ0akEANgIACyYBAX9BIBBfIgBCADcDACAAQgA3AwggAEIANwMQIABCADcDGCAAC5QCAQV/IwQhBSMEQRBqJAQgAigCACEEIAUiA0IANwIAIANBADYCCCAEQW9LBEAgAxCKAQsgAkEEaiEGAkACQCAEQQtJBEAgAyAEOgALIAQEQCADIQIMAgUgAyECCwUgAyAEQRBqQXBxIgcQXyICNgIAIAMgB0GAgICAeHI2AgggAyAENgIEDAELDAELIAIgBiAEEFMaCyACIARqQQA6AAAgASAAKAIAaiIAQQtqIgEsAABBAEgEQCAAKAIAQQA6AAAgAEEANgIEBSAAQQA6AAAgAUEAOgAAC0EAJAVBFCAAQQAQDSMFIQFBACQFIAFBAXEEQEEAEBgiABBaBSAAIAMpAgA3AgAgACADKAIINgIIIAUkBAsLegEEfyABIAAoAgBqIgIsAAsiAUEASCIEBH8gAigCBCIAQQRqEGwhAyABQf8BcSEBIAAFIAFB/wFxIgFBBGoQbCEDIAEhACACKAIECyEFIAMgADYCACACKAIAIQAgA0EEaiAEBH8gAAUgAgsgBAR/IAUFIAELEFMaIAMLJgEBfyAARQRADwsgAEEEaiIBLAALQQBIBEAgASgCABBSCyAAEFILGAEBf0EQEF8iAEIANwMAIABCADcDCCAAC78BAQJ/IwQhAyMEQRBqJAQgACgCACEEIAEgACgCBCIAQQF1aiEBIABBAXEEQCABKAIAIARqKAIAIQQLIAMiACABIAIgBEEfcUH4AWoRBwBBACQFQQRBEBAFIQEjBSECQQAkBSACQQFxRQRAIAEgACgCADYCACABQQRqIgIgAEEEaiIDKQIANwIAIAIgAygCCDYCCCAAJAQgAQ8LEBchASAAQQRqIgAsAAtBAE4EQCABEB4LIAAoAgAQUiABEB5BAAuOAQEBfyAAQQRqIgNCADcCACADQQA2AgggASgCACEBQQAkBUEIIAEgAgR/QQAFQQILQQBBABAIIQEjBSECQQAkBSACQQFxRQRAIAAgATYCAEEAJAVBGyADQd00EAYaIwUhAEEAJAUgAEEBcUUEQA8LCxAXIQAgAywAC0EATgRAIAAQHgsgAygCABBSIAAQHgvRAgECfyMEIQIjBEHQAGokBCAAKAIAIQMgASAAKAIEIgBBAXVqIQEgAEEBcQRAIAEoAgAgA2ooAgAhAwsgAiIAIAEgA0EfcUHWAWoRBgBBACQFQQRByAAQBSEBIwUhAkEAJAUgAkEBcUUEQCABIAAoAgA2AgAgAUEEaiIDIABBBGoiAikCADcCACADIAIoAgg2AgggAkIANwIAIAJBADYCCCABQRBqIgMgAEEQaiICKQIANwIAIAMgAigCCDYCCCACQgA3AwAgAkEANgIIIAFBHGoiAiAAQRxqIgMpAgA3AgAgAiADKQIINwIIIAIgAykCEDcCECACIAMpAhg3AhggAiADKQIgNwIgIAIgAygCKDYCKCAAJAQgAQ8LEBchASAALAAbQQBIBEAgACgCEBBSCyAAQQRqIgAsAAtBAE4EQCABEB4LIAAoAgAQUiABEB5BAAuEAwEDfyMEIQIjBEGA8ABqJAQgAkEAQfzvABBUGiABKAIAIAIQvgIhBCAAQQRqIgNCADcCACADQgA3AgggA0IANwIQIAAgBDYCAEEAJAVBGyADQek0EAYaIwUhAUEAJAUgAUEBcUUEQCAEBEAgAiQEDwtBACQFQRwgAEEQaiACQYAwahAGGiMFIQFBACQFIAFBAXFFBEAgACACQYDQAGooAAA2AhwgACACQYjQAGooAAC4RAAAAAAAAPBBoiACQYTQAGooAAC4oDkDICAAIAJBkNAAaigAALhEAAAAAAAA8EGiIAJBjNAAaigAALigOQMoIAAgAkGU0ABqKAAANgIwIAAgAkGY0ABqKAAANgI0IAAgAkGc0ABqKAAANgI4IAAgAkGg0ABqKAAANgI8IABBQGsgAkGk0ABqKAAANgIAIAAgAkGo0ABqKAAANgJEIAIkBA8LCxAXIQEgACwAG0EASARAIAAoAhAQUgsgAywAC0EATgRAIAEQHgsgAygCABBSIAEQHguuAwEEfyMEIQUjBEFAayQEIAAoAgAhCCABIAAoAgQiAUEBdWohACABQQFxBEAgACgCACAIaigCACEICyAFQRhqIQYgBUEMaiIHIAIQ1QFBACQFQRMgBSADEA0jBSEBQQAkBSABQQFxBEAQFyEABUEAJAUgCCAGIAAgByAFIAQQECMFIQBBACQFAkAgAEEBcQRAEBchAAVBACQFQQRBIBAFIQAjBSEBQQAkBSABQQFxBEAQFyEAIAYsABtBAEgEQCAGKAIQEFILIAZBBGoiAiwAC0EATg0CIAIoAgAQUgwCCyAAIAYoAgA2AgAgAEEEaiICIAZBBGoiASkCADcCACACIAEoAgg2AgggAUIANwIAIAFBADYCCCAAQRBqIgIgBkEQaiIBKQIANwIAIAIgASgCCDYCCCABQgA3AgAgAUEANgIIIAAgBigCHDYCHCAFLAALQQBIBEAgBSgCABBSCyAHLAALQQBOBEAgBSQEIAAPCyAHKAIAEFIgBSQEIAAPCwsgBSwAC0EASARAIAUoAgAQUgsLIAcsAAtBAE4EQCAAEB4LIAcoAgAQUiAAEB5BAAvkAwEDfwJAIwQhBSMEQaCBAWokBCAFQaABaiEHIAVBAEGcARBUGiACKAIAIQYgBSACLAALQQBIBH8gBgUgAgs2AAQgBSAHNgAQIAVBgIABNgAUIAUgBEEBc0EBcTYACCAFQQc2ACQgBUEANgAoIAMoAgAhAiADLAALQQBIBH8gAgUgAwtBnIEEQYABEO0BIAEgBRDOAjYCACAAQQRqIgZCADcCACAGQgA3AgggBkIANwIQQQAkBUEbIAZB8jQQBhojBSEBQQAkBQJAIAFBAXEEQBAXIQEFIAUoAAwiAQRAIAAgATYCAAwDCyAAQQA2AgAgACAFKAAgNgIcIAUoABxBAUcNAiAFKAAYIgQEf0EAIARBIEsEfyAEBUEgC0ECdBBXIgJFBEBBACQFQRRBrPUCEAwjBSEBQQAkBSABQQFxBEAQFyEBDAQLCyACBUEAIQJBAAshA0EAJAVBESAHIAIgBEECdBAHGiMFIQFBACQFIAFBAXFFBEBBACQFQRwgAEEQaiACEAYaIwUhAUEAJAUgAUEBcUUEQCACRQ0EIAMQUgwECwsQFyEBIAIEQCADEFILCwsgACwAG0EASARAIAAoAhAQUgsgBiwAC0EATgRAIAEQHgsgBigCABBSIAEQHg8LIAUkBAtAAQJ/QQQQXyIBQQA2AgBBACQFQRpBBkHy5QAQBhojBSEAQQAkBSAAQQFxBEAQFyEAIAEQUiAAEB4FIAEPC0EACzoBAX8gAEUEQA8LIAAoAgAiAQRAQQAkBUEYIAEQBRojBSEBQQAkBSABQQFxBEBBABAYEFoLCyAAEFILBQBBmAgLzRIBAn9BmAhBoAhBsAhBAEHJMUEWQcwxQQBBzDFBAEHOMUHZMUEnEC1BmAhBAUGQHUHJMUEXQQEQLkEIEF8iAEEFNgIAIABBADYCBEGYCEHcMUEFQZQdQeExQQEgAEEAEC9BCBBfIgBBEjYCACAAQQA2AgRBmAhB6DFBAkGoHUH2MUERIABBABAvQQgQXyIAQQ82AgAgAEEANgIEQZgIQfoxQQNBsB1BgzJBHCAAQQAQL0HACEGIMkGOMkECQdkxQSgQNkEAJAVBBEEEEAUhACMFIQFBACQFIAFBAXFFBEAgAEEANgIAQQAkBUEEQQQQBSEBIwUhAkEAJAUgAkEBcUUEQCABQQA2AgBBACQFQQFBwAhBkDJBgAxB9jFBEiAAQYAMQZgyQRAgARATIwUhAEEAJAUgAEEBcUUEQEEAJAVBBEEEEAUhACMFIQFBACQFIAFBAXFFBEAgAEEENgIAQQAkBUEEQQQQBSEBIwUhAkEAJAUgAkEBcUUEQCABQQQ2AgBBACQFQQFBwAhBnTJByAhB9jFBEyAAQcgIQZgyQREgARATIwUhAEEAJAUgAEEBcUUEQEEAJAVBKUHACBAMIwUhAEEAJAUgAEEBcQRAQQAQGCIAEFoLQeAIQaUyQY4yQQNB2TFBKhA2QQAkBUEEQQQQBSEAIwUhAUEAJAUgAUEBcUUEQCAAQQA2AgBBACQFQQRBBBAFIQEjBSECQQAkBSACQQFxRQRAIAFBADYCAEEAJAVBAUHgCEGvMkHACEH2MUEUIABBwAhBmDJBEiABEBMjBSEAQQAkBSAAQQFxRQRAQQAkBUEEQQQQBSEAIwUhAUEAJAUgAUEBcUUEQCAAQRA2AgBBACQFQQRBBBAFIQEjBSECQQAkBSACQQFxRQRAIAFBEDYCAEEAJAVBAUHgCEG1MkHoCEH2MUEVIABB6AhBmDJBEyABEBMjBSEAQQAkBSAAQQFxRQRAQQAkBUEEQQQQBSEAIwUhAUEAJAUgAUEBcUUEQCAAQRw2AgBBACQFQQRBBBAFIQEjBSECQQAkBSACQQFxRQRAIAFBHDYCAEEAJAVBAUHgCEG9MkGADEH2MUEWIABBgAxBmDJBFCABEBMjBSEAQQAkBSAAQQFxRQRAQQAkBUEpQeAIEAwjBSEAQQAkBSAAQQFxBEBBABAYIgAQWgtBgAlBwzJBjjJBBEHZMUErEDZBACQFQQRBBBAFIQAjBSEBQQAkBQJAIAFBAXFFBEAgAEEANgIAQQAkBUEEQQQQBSEBIwUhAkEAJAUgAkEBcQ0BIAFBADYCAEEAJAVBAUGACUGvMkHACEH2MUEXIABBwAhBmDJBFSABEBMjBSEAQQAkBSAAQQFxDQFBACQFQQRBBBAFIQAjBSEBQQAkBSABQQFxDQEgAEEQNgIAQQAkBUEEQQQQBSEBIwUhAkEAJAUgAkEBcQ0BIAFBEDYCAEEAJAVBAUGACUHRMkHoCEH2MUEYIABB6AhBmDJBFiABEBMjBSEAQQAkBSAAQQFxDQFBACQFQQRBBBAFIQAjBSEBQQAkBSABQQFxDQEgAEEcNgIAQQAkBUEEQQQQBSEBIwUhAkEAJAUgAkEBcQ0BIAFBHDYCAEEAJAVBAUGACUG9MkGADEH2MUEZIABBgAxBmDJBFyABEBMjBSEAQQAkBSAAQQFxDQFBACQFQQRBBBAFIQAjBSEBQQAkBSABQQFxDQEgAEEgNgIAQQAkBUEEQQQQBSEBIwUhAkEAJAUgAkEBcQ0BIAFBIDYCAEEAJAVBAUGACUHWMkGgDEHfMkEBIABBoAxB4zJBASABEBMjBSEAQQAkBSAAQQFxDQFBACQFQQRBBBAFIQAjBSEBQQAkBSABQQFxDQEgAEEoNgIAQQAkBUEEQQQQBSEBIwUhAkEAJAUgAkEBcQ0BIAFBKDYCAEEAJAVBAUGACUHoMkGgDEHfMkEBIABBoAxB4zJBASABEBMjBSEAQQAkBSAAQQFxDQFBACQFQQRBBBAFIQAjBSEBQQAkBSABQQFxDQEgAEEwNgIAQQAkBUEEQQQQBSEBIwUhAkEAJAUgAkEBcQ0BIAFBMDYCAEEAJAVBAUGACUHwMkGADEH2MUEZIABBgAxBmDJBFyABEBMjBSEAQQAkBSAAQQFxDQFBACQFQQRBBBAFIQAjBSEBQQAkBSABQQFxDQEgAEE0NgIAQQAkBUEEQQQQBSEBIwUhAkEAJAUgAkEBcQ0BIAFBNDYCAEEAJAVBAUGACUH3MkGADEH2MUEZIABBgAxBmDJBFyABEBMjBSEAQQAkBSAAQQFxDQFBACQFQQRBBBAFIQAjBSEBQQAkBSABQQFxDQEgAEE4NgIAQQAkBUEEQQQQBSEBIwUhAkEAJAUgAkEBcQ0BIAFBODYCAEEAJAVBAUGACUH7MkGADEH2MUEZIABBgAxBmDJBFyABEBMjBSEAQQAkBSAAQQFxDQFBACQFQQRBBBAFIQAjBSEBQQAkBSABQQFxDQEgAEE8NgIAQQAkBUEEQQQQBSEBIwUhAkEAJAUgAkEBcQ0BIAFBPDYCAEEAJAVBAUGACUGAM0GADEH2MUEZIABBgAxBmDJBFyABEBMjBSEAQQAkBSAAQQFxDQFBACQFQQRBBBAFIQAjBSEBQQAkBSABQQFxDQEgAEHAADYCAEEAJAVBBEEEEAUhASMFIQJBACQFIAJBAXENASABQcAANgIAQQAkBUEBQYAJQYczQYAMQfYxQRkgAEGADEGYMkEXIAEQEyMFIQBBACQFIABBAXENAUEAJAVBBEEEEAUhACMFIQFBACQFIAFBAXENASAAQcQANgIAQQAkBUEEQQQQBSEBIwUhAkEAJAUgAkEBcQ0BIAFBxAA2AgBBACQFQQFBgAlBjjNBgAxB9jFBGSAAQYAMQZgyQRcgARATIwUhAEEAJAUgAEEBcQ0BQQAkBUEpQYAJEAwjBSEAQQAkBSAAQQFxBEBBABAYIgAQWgUPCwsLEBchAEEAJAVBKUGACRAMIwUhAUEAJAUgAUEBcQRAQQAQGCIAEFoFIAAQHgsLCwsLCwsLCwsQFyEAQQAkBUEpQeAIEAwjBSEBQQAkBSABQQFxBEBBABAYIgAQWgUgABAeCwsLCwsLCxAXIQBBACQFQSlBwAgQDCMFIQFBACQFIAFBAXEEQEEAEBgiABBaBSAAEB4LCy0BAX8gASAARgRADwsgAkUEQA8LIAEgACACQX9qIgMQxgEaIAEgA2pBADoAAAsHAEEAEOsDCwQAQQELDgAgAEGczgVqIAEQpgILmAMCBH8CfgJAIARBAEciCSAFQQBHcQRAIARBADYCAAsgAUEgaiIHEFlB/w9LDQAgAEHkzAVqIAFB4cEAaiwAAEEARyIGIAdBAEEFEKACDQAgAEHUzQVqKAIABEAgAEHAzQVqIAYgB0EAQQUQoAJFDQELIAFBsMAAaiEIIABBqIkDaikDACIKQgBSBEAgCCkDACAKWg0BCyAAQbCJA2opAwAiCkIAUgRAIAgpAwAgClgNAQsgACgCACABKAIcIghxDQAgACwACARAIAAoAgQgCHFFDQELIAZFBEAgAEG4iQNqKQMAIgpC//////f/////AFEgCiABQdDAAGopAwAiClVyRQ0BIABBwIkDaikDACILIApZIAtC//////f/////AFJxDQELIABBiMwFaiIGQQA2AhAgBhChAiIBRQ0AQQEhAAJAAkADQCABIAcgAxClAUUEQCAAQQFqIQAgBhChAiIBDQEMAgsLDAELQQAPCyACBEAgAiABIAcQnQFFOgAACyAJRQRAIAAPCyAEIAEgBRBvGiAADwtBAAvFAQECfyAAELsEIABByMsEakEANgIAIABBiIwFakEANgIAIABBvMsEakEAOgAAIABBwMsEakEANgIAIABBxMsEakEAOgAAIABBiMwFahCeASAAQeTMBWoQngEgAEHAzQVqEJ4BIABB+M4FahCeASAAQZzOBWoQngEgAEHwhANqIgEoAgAiAkUEQCAAQfSEA2pBADYCACAAQfiEA2pBADYCAA8LIAIQUiABQQA2AgAgAEH0hANqQQA2AgAgAEH4hANqQQA2AgAL1QIBB38gABC2AkEAJAVBJSAAQYjMBWoiBxAMIwUhAUEAJAUgAUEBcQRAEBchASAAEHkgARAeC0EAJAVBJSAAQeTMBWoiAxAMIwUhAUEAJAUgAUEBcQRAEBchAQVBACQFQSUgAEHAzQVqIgQQDCMFIQFBACQFIAFBAXEEQBAXIQEjByECBUEAJAVBJSAAQZzOBWoiBRAMIwUhAUEAJAUgAUEBcQRAEBchASMHIQIFQQAkBUElIABB+M4FaiIGEAwjBSEBQQAkBSABQQFxBEAQFyEBIwchAgVBACQFQSYgABAMIwUhAUEAJAUgAUEBcUUEQA8LEBchASMHIQIgBigCACIGBEAgBhBSCwsgBSgCACIFBEAgBRBSCwsgBCgCACIEBEAgBBBSCwsgAygCACIDBEAgAxBSCwsgBygCACICRQRAIAAQeSABEB4LIAIQUiAAEHkgARAeC0YBAX8gAEEAOwEUIABBGGoiAUEANgIAIAFBADsBBCABQQA6AAYgAEEgaiIAQgA3AwAgAEIANwMIIABCADcDECAAQgA3AxgL1QIBBX8jBCEDIwRBEGokBCAAQajAAGoiBSgCACECIABBpMAAaiIEIAE2AgAgAiABSQRAIABBrMAAaigCACIGQQBHIAYgAUlxBEAgAyAGNgIAQaz1AkHYGyADEGBBrPUCEFYgBSgCACECIAQoAgAhAQsgAEGgwABqIgQoAgAgASACQSBqIAJBAnZqIgJLBH8gAQUgAiIBCxBXIgJFBEBBrPUCEFYLIAQgAjYCACAFIAE2AgALIABBADoAECAAQeDAAGpBABCoBCAAQQA2AhwgAEGxwQBqQQA6AAAgAEG6wQBqQQA6AAAgAEHwwQBqQQA2AgAgAEH1gQFqQQA6AAAgAEGwwABqIgFCADcDACABQgA3AwggAUIANwMQIABBiMEAaiIBQgA3AwAgAUEAOgAIIABB3MEAaiIAQgA3AgAgAEEANgIIIABBADsBDCAAQQA6AA4gAyQEC4YBAAJAAkACQAJAAkAgAUEPaw4kAAQEBAQBBAQEBAQBBAQCBAQEBAQEBAQEBAQEBAQEBAQEBAQDBAsgAEGomAFqLAAABEAPCyAAIAIQhgQPCyAAQaiYAWosAAAEQA8LIAAgAhCEBA8LIABBqJgBaiwAAARADwsgACACEIEEDwsgACACEPsDCwuLAwEIfyABRQRAQaz1AhBWCyABQYCAEEsEfyABBUGAgBALIgMgAEHMzQNqIgYoAgAiBE0EQA8LAkACQAJAIAIEQCAAQaSWAWooAgBBAEchAiAAQaiYAWoiASwAAEUNAUEEEBQiAUHEJTYCACABQdgKQQoQGwUgAEGomAFqIgEsAAAEQEEAIQIMAwVBACECDAILAAsMAgsgAxBsIgVFDQAgBUEAIAMQVBogBEUgAkEBc3JFBEAgA0F/aiECIABBpJYBaigCACEHIAAoAmAhCCAEQX9qIQlBASEBA0AgBSAIIAFrIgogAnFqIAcgCiAJcWosAAA6AAAgAUEBaiIBIARNDQALCyAAQaSWAWoiASgCACICBEAgAhBSCyABIAU2AgAMAQsgA0GAgIAISSACcgRAQQQQFCICQcQlNgIAIAJB2ApBChAbCyAAQaSWAWoiAigCACIEBEAgBBBSIAJBADYCAAsgAEGolgFqIAMQ9wMgAUEBOgAACyAGIAM2AgAgAEHQzQNqIANBf2o2AgAL1AEBBX8gABDYASABRQRADwsCQAJAAkADQCABIARrIgJBICADa24iBUGAgIACTQRAQYCAgAIhBQsgAiAFSQ0BA0AgAhBsIgZFBEAgAiACQQV2ayICIAVJDQMMAQsLIAZBACACEFQaIAAgA0ECdGogBjYCACAAQYABaiADQQJ0aiACIARqIgQ2AgAgBCABSSICIANBAWoiA0EgSXENAAwCCwALQQQQFCIAQcQlNgIAIABB2ApBChAbDAELIAIEQEEEEBQiAEHEJTYCACAAQdgKQQoQGwsLC6QGAgl/AX4CQCMEIQQjBEEQaiQEIAQhBwJAAkACQAJAIAMsAAAiBA4EAgAAAQMLIABBwJgBaikDACENIAJBBEwNAyANpyEKIAJBfGohCyAEQQJGBH9B6QEFQegBCyEMIAEhAEEAIQIDQCAAQQFqIQMgAkEBaiEEIAAsAAAiBUFoRiAMIAVB/wFxRnIEfyAEIApqQf///wdxIQUgAEECaiIGLQAAQQh0IAMtAAByIABBA2oiCC0AAEEQdHIgAEEEaiIJLQAAQRh0ciIEQQBIBEAgBCAFakF/SgRAIAMgBEGAgIAIaiIDOgAAIAYgA0EIdjoAACAIIANBEHY6AAAgCSADQRh2OgAACwUgBEGAgIB4akEASARAIAMgBCAFayIDOgAAIAYgA0EIdjoAACAIIANBEHY6AAAgCSADQRh2OgAACwsgAkEFaiECIABBBWoFIAQhAiADCyEAIAIgC0gNAAsMAwsgAEHAmAFqKQMAIQ0gAkEDTA0CQQAhACANpyEDIAJBfWohBANAIAEgAGoiAiwAA0FrRgRAIAIgAkEBaiIFLQAAQQh0IAItAAByIAJBAmoiBi0AAEEQdHIgACADakECdmsiAjoAACAFIAJBCHY6AAAgBiACQRB2OgAACyAAQQRqIgAgBEgNAAsMAgsgAywADCEFIABBJGohBCAAQSxqIgYoAgAhAyAAQShqIgggAjYCACADIAJJBEAgACgCMCIAQQBHIAAgAklxBH8gByAANgIAQaz1AkHYGyAHEGBBrPUCEFYgBigCACEDIAgoAgAFIAILIQAgBCgCACAAIANBIGogA0ECdmoiA0sEfyAABSADIgALEFciA0UEQEGs9QIQVgsgBCADNgIAIAYgADYCAAsgBCgCACEGIAUEQEEAIQNBACEABSAHJAQgBg8LIAVB/wFxIQkDQCADIAJJBEAgAyEEQQAhCANAIABBAWohBSAGIARqIAhB/wFxIAEgAGotAABrIgg6AAAgBCAJaiIEIAJJBEAgBSEADAEFIAUhAAsLCyADQQFqIgMgCUcNACAGIQELDAELIAckBEEADwsgByQEIAELtAMBCX8jBCECIwRBIGokBCAAQThqIgUoAgAiA0H/P0sEQCAAENkBIAUoAgAiA0H/P0sEQCAFQQA2AgBBACEDCwsgACgCZCIGIAAoAmAiCEYEfyABQQRqIgQhByAEKAIAIQQgAEHQzQNqKAIAIQlBAAUgAEHQzQNqKAIAIgkgBiAIa3EgAUEEaiIHKAIAIgRNCyEKIABBNGohBiABIAo6AA0gByAIIARqIAlxNgIAIAIgASkCADcCACACIAEpAgg3AgggBSADQQFqIgE2AgAgASAAQTxqIgcoAgAiA00EQCAGKAIAIAFBf2pBBHRqIgAgAikCADcCACAAIAIpAgg3AgggAiQEQQEPCyACQRBqIQQgAEFAaygCACIAQQBHIAEgAEtxBH8gBCAANgIAQaz1AkHYGyAEEGBBrPUCEFYgBygCACEDIAUoAgAFIAELIQAgBigCACAAIANBIGogA0ECdmoiAUsEfyAABSABIgALQQR0EFciAUUEQEGs9QIQVgsgBiABNgIAIAcgADYCACABIAUoAgBBf2pBBHRqIgAgAikCADcCACAAIAIpAgg3AgggAiQEQQEL+QQBB38gASwACEUEQCABKAIAIABB6ABqIgYoAgAiA0FwakoEQCADIABBBGoiBygCACIFayIEQQBIBEBBAA8LIABB8ABqIgggAEH4AGoiCSgCACAFayAIKAIAajYCACAFQYCAAUoEQCAEQQBKBEAgACgCECIDIAMgBWogBBBdGgsgB0EANgIAIAYgBDYCAAUgAyEECyAEQYCAAkYEQEEAIQRBgIACIQMFIAAoAgAgACgCECAEakGAgAIgBGsQXiEEIAYoAgAiBSAEaiEDIARBAEoEQCAGIAM2AgAFIAUhAwsLIABB7ABqIgUgA0FiaiIANgIAIAkgBygCACIDNgIAIANBf2ogCCgCACIGaiEDIAZBf0cEQCAFIAAgA0gEfyAABSADCzYCAAsgBEF/RgRAQQAPCwsLIAEQWEEOdiEGIAEgAUEEaiIFKAIAQQJqIgBBA3YgASgCAGo2AgAgBSAAQQdxNgIAQQAhBEEAIQADQCABEFhBCHYgAEEDdHQgBGohBCABIAUoAgBBCGoiA0EDdiABKAIAajYCACAFIANBB3E2AgAgAEEBaiEDIAAgBkcEQCADIQAMAQsLIAIgBDYCBCABEFhBDnYhBiABIAUoAgBBAmoiAEEDdiABKAIAajYCACAFIABBB3E2AgBBACEEQQAhAANAIAEQWEEIdiAAQQN0dCAEaiEEIAEgBSgCAEEIaiIDQQN2IAEoAgBqNgIAIAUgA0EHcTYCACAAQQFqIQMgACAGRwRAIAMhAAwBCwsgAiAENgIIIAIgARBYQQ12OgAAIAFBAxBVIAIsAAAEQEEBDwsgAiABEFhBC3ZBAWo6AAwgAUEFEFVBAQuYHwEtfwJAIwQhBCMEQRBqJAQgAEHImAFqIh5BAToAACAAQbiYAWoiHywAAARAIABB7ABqIQ4gAEEIaiEHIABBwJgBaiEaIABB8ABqIRMgAEH4AGohEiAAQYQBaiEbIABB6ABqIQggAEEEaiEXIABB8ABqIRggAEEEaiEMBSABRQRAIABBhAFqQQBBnJUBEFQaIABBxABqIgJCADcCACACQgA3AgggAkIANwIQIAJCADcCGCACQQA2AiAgAEGglgFqIABBzM0DaigCACICQYCAgAJJBH8gAgVBgICAAgsgAEHQzQNqKAIAcTYCAAsgAEEANgI4IABBCGoiB0EANgIAIABBBGoiBUEANgIAIABBwJgBaiIaQgA3AwAgAEHoAGoiA0IANwMAIANCADcDCCADQgA3AxAgA0EANgIYIABB8ABqIgZBfzYCACABRQRAIABBwK4CakEANgIAIABBxK4CakEANgIAIABBuK4CakEANgIAIABBvK4CakEBNgIAIABByK4CakEAQfACEFQaIABBhK8BakEAQbT/ABBUGiAAQczMA2pBADoAACAAQbTJA2pBAEGUAxBUGiAAQbDJA2pBAjYCACAAQcjMA2pBADYCAAsgACABEIMBIAMoAgAiAiAFKAIAIghrIgFBAEgNASAGIABB+ABqIhIoAgAgCGsgBigCAGo2AgAgCEGAgAFKBEAgAUEASgRAIAAoAhAiAiACIAhqIAEQXRoLIAVBADYCACADIAE2AgAFIAIhAQsgAUGAgAJGBEBBACEBQYCAAiECBSAAKAIAIAAoAhAgAWpBgIACIAFrEF4hASADKAIAIgggAWohAiABQQBKBEAgAyACNgIABSAIIQILCyAAQewAaiIOIAJBYmoiAjYCACASIAUoAgAiCDYCACAIQX9qIAYoAgAiDGohCCAMQX9HBEAgDiACIAhIBH8gAgUgCAs2AgALIAFBf0YNASAAIABBBGoiDCAAQfAAaiITEKQCRQ0BIAAgDCATIABBhAFqIhsQowJFDQECQCADIQggBSEXIAYhGAsLIAQhDyAAQdDNA2ohECAAQeAAaiEJIABBBGohCiAAQaCWAWohICAAQRBqIRQgAEGIAmohISAAQaiYAWohFSAAQaSWAWohIiAAQaiWAWohDSAAQfQfaiEjIABBzABqIRwgAEHQAGohJCAAQcgAaiEdIABBxABqIRYgAEHYAGohGSAAQeA9aiElIABB3DxqISYgAEHwHmohJyAAQczbAGohKCAAQcjaAGohKSAAQYQBaiEqIABBsJgBaiErIABB8ABqISwgAEH0AGohLSAAQYABaiEuAkACQAJAA0ACQCAJIAkoAgAgECgCACIEcSICNgIAIAooAgAiASAOKAIATgRAA0ACQCABICwoAgAiAyASKAIAIgVqIgJIBEAgASACQX9qRw0BIAcoAgAgLSgCAEgNAQsgLiwAAA0DIAAgDCATEKQCRQ0GIAAgDCATIBsQowJFDQYgCigCACEBDAELCyAIKAIAIgQgAWsiAkEASA0BIBggBSABayADajYCACAB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NwIIIAJCADcCECACQgA3AhggAkEANgIgIABBoJYBaiAAQczNA2ooAgAiAkGAgIACSQR/IAIFQYCAgAILIABB0M0DaigCAHE2AgALIABBADYCOCAAQQhqIghBADYCACAAQQRqIgdBADYCACAAQcCYAWoiGkIANwMAIABB6ABqIgJCADcDACACQgA3AwggAkIANwMQIAJBADYCGCAAQX82AnAgAUUEQCAAQcCuAmpBADYCACAAQcSuAmpBADYCACAAQbiuAmpBADYCACAAQbyuAmpBATYCACAAQciuAmpBAEHwAhBUGiAAQYSvAWpBAEG0/wAQVBogAEHMzANqQQA6AAAgAEG0yQNqQQBBlAMQVBogAEGwyQNqQQI2AgAgAEHIzANqQQA2AgALIAAgARCDASACKAIAIgogBygCACIJayIDQQBIBEAPCyAJQYCAAUoEQCADQQBKBEAgACgCECIKIAogCWogAxBdGgsgB0EANgIAIAIgAzYCAAUgCiEDCyAAKAIAIABBEGoiDigCACADakGAgAIgA2sQXiEDIAIoAgAiCSADaiEKIANBAEoEQCACIAo2AgAgACAKQWJqNgJsBSAAIAlBYmo2AmwgA0F/RgRADwsLIAEEQCAAQczMA2osAAAEQCACIQkgACEKDAMLCyAAENsBBEAgAiEJIAAhCgUPCwsLIABB0M0DaiERIABB4ABqIQsgAEHsAGohFyAAQeQAaiEfIABByMwDaiESIABBwLECaiEMIABBsMkDaiEgIABBpJYBaiETIABBiAJqISEgAEH0H2ohIiAAQcwAaiEUIABB0ABqIRsgAEHIAGohFSAAQcQAaiEPIABB2ABqIRYgAEG8sQJqIRggAEG4sQJqIRkgAEHgPWohIyAAQdw8aiEkIABB8B5qISUgAEHM2wBqISYgAEHI2gBqIScgAEHMzQNqISggAEHMzANqIRwgAEGEAWohKSAAQbCYAWohKkEAIQECQAJAAkACQAJAAkACQAJAA0ACQCALIAsoAgAgESgCAHE2AgAgBygCACIEIBcoAgBKBEAgCSgCACIDIARrIgJBAEgNASAEQYCAAUoEQCACQQBKBEAgDigCACIDIAMgBGogAhBdGgsgB0EANgIAIAkgAjYCAAUgAyECCyAKKAIAIA4oAgAgAmpBgIACIAJrEF4hAiAJKAIAIgQgAmohAyAC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wQBqEJsECwwBCyABQcytAmosAABFDQEgASAAQRBqQQAgDRC1AQRAIAEgAUGIvANqKQMAQQAgASgCACgCEEEDcUG4AmoRAgAgBiQEQQEPBUGs9QJBARBkDAILAAsgASABQZC8A2opAwBBACABKAIAKAIQQQNxQbgCahECACAGJARBAQ8LIAYkBEEAC5oBAQJ/IABCADcDACAAQRBqIgMQtwIgACABNgIIIABBADYC3AEgAEHgwQBqQQA2AgAgAEEANgLMAUEAJAVBBEHYzQMQBSEBIwUhAkEAJAUgAkEBcQRAEBchAiADEIQBIAIQHgtBACQFQQcgASADEA0jBSECQQAkBSACQQFxRQRAIAAgATYCyAEPCxAXIQAgARBSIAMQhAEgABAeC4IDAgd/AX4gAEGQMmohBkGAgAQgAEGUMmoiAygCACICa0GAAkkEQCAAKAIQIgUgBSACaiAGKAIAIAJrIgIQUxogA0EANgIAIAYgAjYCACAAEOIBGiADKAIAIQILIAJBB2ogBigCAEsEQEEADwsgASAAQRBqIgcoAgAgAmpBBxDpASADIAMoAgBBB2o2AgAgARCmASEIIAFBBBC6AiICQX1qIAEQYSIJp2ohBCAJQgBRIAJFIARBAEhycgRAIABB6DFqQQA6AABBAA8LIAYoAgAgAygCACICayEFAkAgBEEASgRAIAEgBygCACACaiAFIARJBH8gBQUgBAsiAhDpASADIAMoAgAgAmo2AgAgBCACayICQQBKBEADQAJAIANBADYCACAGQQA2AgAgABDiAUUEQEEAIQAMAQsgASAHKAIAIAMoAgBqIAUgAkkEfyAFBSACCyIEEOkBIAMgAygCACAEajYCACACIARrIgJBAEoNAQwECwtBAA8LCwsgCCABELgCRgtOAQF/AkACQAJAIAJBmLwDaigCAEECaw4CAAECCyMEIQQjBEGAEGokBCACQcynAWooAgAaIAQkBEEADwsgACADIAJBsKcBahCdBA8LQQALRwAgAEHJiQNqLAAABEAPCyAAQZCFA2osAABFBEAPCyABQZi8A2ooAgBBAkcEQA8LIAFBkK4CakHMERBzBEAPCyABIAIQoQQLOAAgAEHJiQNqLAAABEAPCyABQeitAmouAQBBgQJHBEAPCyAAQZCFA2osAABFBEAPCyABIAIQogQLrQEBAn8jBCED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IABBpA5qIAJBgAFqNgIAIABBqA5qIAJBoAFqNgIAIABBrA5qIAJBqAFqNgIAIABBqBBqQQAgAEG4DmoiAmtBP3EgAmoiAjYCACAAQawQaiACQYABajYCACAAQbAQaiACQaABajYCACAAQbQQaiACQagBajYCAAUgAiABKALwAUGwARBTGiAAIAEoAoACNgKAAiAAIAEsAIQCOgCEAiAAQQAgAEGIAmoiAmtBP3EgAmoiAjYC+AMgACACQYABajYC/AMgACACQaABajYCgAQgACACQagBajYChAQgAiABKAL4A0GwARBTGiAAIAEoAogENgKIBCAAIAEsAIwEOgCMBCAAQQAgAEGQBGoiAmtBP3EgAmoiAjYCgAYgACACQYABajYChAYgACACQaABajYCiAYgACACQagBajYCjAYgAiABKAKABkGwARBTGiAAIAEoApAGNgKQBiAAIAEsAJQGOgCUBiAAQYgIakEAIABBmAZqIgJrQT9xIAJqIgI2AgAgAEGMCGogAkGAAWo2AgAgAEGQCGogAkGgAWo2AgAgAEGUCGogAkGoAWo2AgAgAiABQYgIaigCAEGwARBTGiAAQZgIaiABQZgIaigCADYCACAAQZwIaiABQZwIaiwAADoAACAAQZAKakEAIABBoAhqIgJrQT9xIAJqIgI2AgAgAEGUCmogAkGAAWo2AgAgAEGYCmogAkGgAWo2AgAgAEGcCmogAkGoAWo2AgAgAiABQZAKaigCAEGwARBTGiAAQaAKaiABQaAKaigCADYCACAAQaQKaiABQaQKaiwAADoAACAAQZgMakEAIABBqApqIgJrQT9xIAJqIgI2AgAgAEGcDGogAkGAAWo2AgAgAEGgDGogAkGgAWo2AgAgAEGkDGogAkGoAWo2AgAgAiABQZgMaigCAEGwARBTGiAAQagMaiABQagMaigCADYCACAAQawMaiABQawMaiwAADoAACAAQaAOakEAIABBsAxqIgJrQT9xIAJqIgI2AgAgAEGkDmogAkGAAWo2AgAgAEGoDmogAkGgAWo2AgAgAEGsDmogAkGoAWo2AgAgAiABQaAOaigCAEGwARBTGiAAQbAOaiABQbAOaigCADYCACAAQbQOaiABQbQOaiwAADoAACAAQagQakEAIABBuA5qIgJrQT9xIAJqIgI2AgAgAEGsEGogAkGAAWo2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ABggACACKQAgNwAgIAAgAikAKDcAKCAAIAIpADA3ADAgACACKQA4NwA4IAQgBCgCAEFAaiIANgIAIAMgBmohAyAFIAZrIgUNAAsMAQsgAiADIAUQUxogBCAEKAIAIAVqIgA2AgALQSAhBSAKQYABaiEDAkACQANAIAcoAgAgAGohAiAFQYABIABrIgZNDQEgAiADIAYQUxogBCAEKAIAIAZqNgIAIAkoAgAiACgCACECIAAgAkFAazYCACAAQQRqIgAgACgCACACQb9/S2o2AgAgCCAHKAIAEG0gBygCACIAQUBrIQIgACACKQAANwAAIAAgAikACDcACCAAIAIpABA3ABAgACACKQAYNwAYIAAgAikAIDcAICAAIAIpACg3ACggACACKQAwNwAwIAAgAikAODcAOCAEIAQoAgBBQGoiADYCACADIAZqIQMgBSAGayIFDQALDAELIAIgAyAFEFMaIAQgBCgCACAFaiIANgIAC0EgIQUgCkGgAWohAwJAAkADQCAHKAIAIABqIQIgBUGAASAAayIGTQ0BIAIgAyAGEFMaIAQgBCgCACAGajYCACAJKAIAIgAoAgAhAiAAIAJBQGs2AgAgAEEEaiIAIAAoAgAgAkG/f0tqNgIAIAggBygCABBtIAcoAgAiAEFAayECIAAgAikAADcAACAAIAIpAAg3AAggACACKQAQNwAQIAAgAikAGDcAGCAAIAIpACA3ACAgACACKQAoNwAoIAAgAikAMDcAMCAAIAIpADg3ADggBCAEKAIAQUBqIgA2AgAgAyAGaiEDIAUgBmsiBQ0ACwwBCyACIAMgBRBTGiAEIAQoAgAgBWoiADYCAAtBICEFIApBwAFqIQMCQAJAA0AgBygCACAAaiECIAVBgAEgAGsiBk0NASACIAMgBhBTGiAEIAQoAgAgBmo2AgAgCSgCACIAKAIAIQIgACACQUBrNgIAIABBBGoiACAAKAIAIAJBv39LajYCACAIIAcoAgAQbSAHKAIAIgBBQGshAiAAIAIpAAA3AAAgACACKQAINwAIIAAgAikAEDcAECAAIAIpABg3ABggACACKQAgNwAgIAAgAikAKDcAKCAAIAIpADA3ADAgACACKQA4NwA4IAQgBCgCAEFAaiIANgIAIAMgBmohAyAFIAZrIgUNAAsMAQsgAiADIAUQUxogBCAEKAIAIAVqIgA2AgALQSAhBSAKQeABaiEKAkACQANAAkAgBygCACAAaiEDIAVBgAEgAGsiAk0NACADIAogAhBTGiAEIAQoAgAgAmo2AgAgCSgCACIAKAIAIQMgACADQUBrNgIAIABBBGoiACAAKAIAIANBv39LajYCACAIIAcoAgAQbSAHKAIAIgBBQGshAyAAIAMpAAA3AAAgACADKQAINwAIIAAgAykAEDcAECAAIAMpABg3ABggACADKQAgNwAgIAAgAykAKDcAKCAAIAMpADA3ADAgACADKQA4NwA4IAQgBCgCAEFAaiIANgIAIAUgAmsiBUUNAiAKIAJqIQoMAQsLDAELIAggARDgASALJAQPCyADIAogBRBTGiAEIAQoAgAgBWo2AgAgCCABEOABIAskBAuwAgIEfwN+IABB6DFqIgYsAABFBEBBAA8LIABBqDJqIQUgAEGcMmohByAAQbAyaiEEA0AgBSkDACAHKAIArXwgBCkDAFgEQCAAEKQEDQELCyAGLAAARQRAIABBuDJqLAAARQRAQQAPCyAAKAIAIAQpAwBBABCcAUEADwsgBCkDACIIIAUpAwAiCVoEQCAIIAKtIgp8IAkgBygCAK18WARAIAEgAEGYMmooAgAgCCAJfadqIAIQUxogAyACNgIAIAQgBCkDACAKfDcDACAAQbgyakEBOgAAQQEPCwsgAEG4MmoiBSwAAARAIAAoAgAgCEEAEJwBIAVBADoAAAsgACgCACABIAIQ1AEiAEEASAR/IAZBADoAAEEABSADIAA2AgAgBCAEKQMAIACsfDcDAEEBCwv2BgEPf0GABCAAQcgWaiIOKAIAIgdrIQYgB0UgBiACS3IEfyABIQkgAgUgAEHIEmogB2ogASAGEFMaA0AgACADQYgCbGohDCAAIANBiAJsakHwAWohCCAAIANBiAJsakH4AWohDUHAACEKIABByBJqIANBBnRqIQsgACADQYgCbGpBgAJqIgcoAgAhBAJAAkADQCAIKAIAIARqIQUgCkGAASAEayIJTQ0BIAUgCyAJEFMaIAcgBygCACAJajYCACANKAIAIgQoAgAhBSAEIAVBQGs2AgAgBEEEaiIEIAQoAgAgBUG/f0tqNgIAIAwgCCgCABBtIAgoAgAiBEFAayEFIAQgBSkAADcAACAEIAUpAAg3AAggBCAFKQAQNwAQIAQgBSkAGDcAGCAEIAUpACA3ACAgBCAFKQAoNwAoIAQgBSkAMDcAMCAEIAUpADg3ADggByAHKAIAQUBqIgQ2AgAgCyAJaiELIAogCWsiCg0ACwwBCyAFIAsgChBTGiAHIAcoAgAgCmo2AgALIANBAWoiA0EIRw0ACyABIAZqIQlBACEHIAIgBmsLIgtB/wNLIQ9BACEEA0AgACAEQYgCbGohECAPBEAgACAEQYgCbGpB8AFqIQ0gACAEQYgCbGpB+AFqIREgCSAEQQZ0aiECIAshCiAAIARBiAJsakGAAmoiCCgCACEDA0BBwAAhBSACIQECQAJAA0AgDSgCACADaiEGIAVBgAEgA2siDE0NASAGIAEgDBBTGiAIIAgoAgAgDGo2AgAgESgCACIDKAIAIQYgAyAGQUBrNgIAIANBBGoiAyADKAIAIAZBv39LajYCACAQIA0oAgAQbSANKAIAIgNBQGshBiADIAYpAAA3AAAgAyAGKQAINwAIIAMgBikAEDcAECADIAYpABg3ABggAyAGKQAgNwAgIAMgBikAKDcAKCADIAYpADA3ADAgAyAGKQA4NwA4IAggCCgCAEFAaiIDNgIAIAEgDGohASAFIAxrIgUNACADIQELDAELIAYgASAFEFMaIAggCCgCACAFaiIBNgIACyACQYAEaiECIApBgHxqIgpB/wNLBEAgASEDDAELCwsgBEEBaiIEQQhJDQALIAtB/wNxIgFFBEAgDiABIAdqNgIADwsgAEHIEmogB2ogCSALIAFraiABEFMaIA4gASAHajYCAAu5CgEDfyAAQcAQakEAQfABEFQaIABBwBJqQQA2AgAgAEHEEmoiA0EAOgAAIABByBJqQQBBhAQQVBogAEG0EmoiAigCACIBQawRKQIANwIAIAFBtBEpAgA3AgggAUG8ESkCADcCECABQcQRKQIANwIYIAIoAgAiASABKAIAQaCAoBBzNgIAIAFBDGoiASABKAIAQYCAhIACczYCACAAQQBB8AEQVBogAEEANgKAAiAAQQA6AIQCIABB9AFqIgIoAgAiAUGsESkCADcCACABQbQRKQIANwIIIAFBvBEpAgA3AhAgAUHEESkCADcCGCACKAIAIgEgASgCAEGggKAQczYCACABQQxqIgEgASgCAEGAgICAAnM2AgAgAEGIAmpBAEHwARBUGiAAQQA2AogEIABBADoAjAQgAEH8A2oiAigCACIBQawRKQIANwIAIAFBtBEpAgA3AgggAUG8ESkCADcCECABQcQRKQIANwIYIAIoAgAiASABKAIAQaCAoBBzNgIAIAFBCGoiAiACKAIAQQFzNgIAIAFBDGoiASABKAIAQYCAgIACczYCACAAQZAEakEAQfABEFQaIABBADYCkAYgAEEAOgCUBiAAQYQGaiICKAIAIgFBrBEpAgA3AgAgAUG0ESkCADcCCCABQbwRKQIANwIQIAFBxBEpAgA3AhggAigCACIBIAEoAgBBoICgEHM2AgAgAUEIaiICIAIoAgBBAnM2AgAgAUEMaiIBIAEoAgBBgICAgAJzNgIAIABBmAZqQQBB8AEQVBogAEGYCGpBADYCACAAQZwIakEAOgAAIABBjAhqIgIoAgAiAUGsESkCADcCACABQbQRKQIANwIIIAFBvBEpAgA3AhAgAUHEESkCADcCGCACKAIAIgEgASgCAEGggKAQczYCACABQQhqIgIgAigCAEEDczYCACABQQxqIgEgASgCAEGAgICAAnM2AgAgAEGgCGpBAEHwARBUGiAAQaAKakEANgIAIABBpApqQQA6AAAgAEGUCmoiAigCACIBQawRKQIANwIAIAFBtBEpAgA3AgggAUG8ESkCADcCECABQcQRKQIANwIYIAIoAgAiASABKAIAQaCAoBBzNgIAIAFBCGoiAiACKAIAQQRzNgIAIAFBDGoiASABKAIAQYCAgIACczYCACAAQagKakEAQfABEFQaIABBqAxqQQA2AgAgAEGsDGpBADoAACAAQZwMaiICKAIAIgFBrBEpAgA3AgAgAUG0ESkCADcCCCABQbwRKQIANwIQIAFBxBEpAgA3AhggAigCACIBIAEoAgBBoICgEHM2AgAgAUEIaiICIAIoAgBBBXM2AgAgAUEMaiIBIAEoAgBBgICAgAJzNgIAIABBsAxqQQBB8AEQVBogAEGwDmpBADYCACAAQbQOakEAOgAAIABBpA5qIgIoAgAiAUGsESkCADcCACABQbQRKQIANwIIIAFBvBEpAgA3AhAgAUHEESkCADcCGCACKAIAIgEgASgCAEGggKAQczYCACABQQhqIgIgAigCAEEGczYCACABQQxqIgEgASgCAEGAgICAAnM2AgAgAEG4DmpBAEHwARBUGiAAQbgQakEANgIA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BgYGaWkAdgBSYXJBcmNoaXZlAHZpAG9wZW4AaWlpaWlpAGdldEZpbGVIZWFkZXIAaWlpAHJlYWRGaWxlAGlpaWkAU3RhdGUAaQBlcnJDb2RlAHZpaWkAZXJyVHlwZQBBcmNIZWFkZXIAc3RhdGUAY29tbWVudABmbGFncwBBcmNGaWxlSGVhZGVyAG5hbWUAcGFja1NpemUAZGlpAHZpaWQAdW5wU2l6ZQBob3N0T1MAY3JjAHRpbWUAdW5wVmVyAG1ldGhvZABmaWxlQXR0cgAxM0FyY0ZpbGVIZWFkZXIATlN0M19fMjEyYmFzaWNfc3RyaW5nSXdOU18xMWNoYXJfdHJhaXRzSXdFRU5TXzlhbGxvY2F0b3JJd0VFRUUATlN0M19fMjIxX19iYXNpY19zdHJpbmdfY29tbW9uSUxiMUVFRQA5QXJjSGVhZGVyAE5TdDNfXzIxMmJhc2ljX3N0cmluZ0ljTlNfMTFjaGFyX3RyYWl0c0ljRUVOU185YWxsb2NhdG9ySWNFRUVFADVTdGF0ZQBFUlJfUFJPQ0VTUwBFUlJfUkVBRABFUlJfT1BFTgBQSzEwUmFyQXJjaGl2ZQBQMTBSYXJBcmNoaXZlADEwUmFyQXJjaGl2ZQBTRVQARU5EAENVUgA0RmlsZQB2b2lkAGJvb2wAY2hhcgBzaWduZWQgY2hhcgB1bnNpZ25lZCBjaGFyAHNob3J0AHVuc2lnbmVkIHNob3J0AGludAB1bnNpZ25lZCBpbnQAbG9uZwB1bnNpZ25lZCBsb25nAGZsb2F0AGRvdWJsZQBzdGQ6OnN0cmluZwBzdGQ6OmJhc2ljX3N0cmluZzx1bnNpZ25lZCBjaGFyPgBzdGQ6OndzdHJpbmcAZW1zY3JpcHRlbjo6dmFsAGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGNoYXI+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHNpZ25lZCBjaGFyPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBjaGFyPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxzaG9ydD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dW5zaWduZWQgc2hvcnQ+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGludD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dW5zaWduZWQgaW50PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxsb25nPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBsb25nPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxpbnQ4X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVpbnQ4X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGludDE2X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVpbnQxNl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxpbnQzMl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1aW50MzJfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8ZmxvYXQ+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGRvdWJsZT4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8bG9uZyBkb3VibGU+AE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWVFRQBOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lkRUUATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJZkVFAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SW1FRQBOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lsRUUATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJakVFAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWlFRQBOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0l0RUUATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJc0VFAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWhFRQBOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lhRUUATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJY0VFAE4xMGVtc2NyaXB0ZW4zdmFsRQBOU3QzX18yMTJiYXNpY19zdHJpbmdJaE5TXzExY2hhcl90cmFpdHNJaEVFTlNfOWFsbG9jYXRvckloRUVFRQASERMUFRYXGBkaGxwdHh8gIREiIyQRJSYnKCkqKywRLS4vEBAwEBAQEBAQEDEyMxA0NRAQERERERERERERERERERERERERERERERERETYRERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERE3ERERETgROTo7PD0+ERERERERERERERERERERERERERERERERERERERERERERERERERERERERET8QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBARQEERQkNERUZHSEkQEBBKS0xNThAQEE9QEBAQEFEQEBAQEBAQEBARERFSUxAQEBAQEBAQEBAQEREREVQQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAREVUQEBAQVhAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBXEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBYWVpbEBAQEBAQEBAQEBAQEBAQEBAQEBAQEFwQEBAQEBAQEBAQEBAQEBAQEABBusMACyD//////////////////////////////////////////wBB4sMACzb+//8H/v//BwAAAAAABCAE//9/////f//////////////////////////////////D/wMAH1AAQaLEAAukASAAAAAAAN88QNf///v///////////+///////////////////////8D/P////////////////////////8A/v///38C/v////8AAAAAAP+/tgD///8HBwAAAP8H//////////7/w////////////////+8f/uH/nwAA////////AOD///////////////8DAP//////BzAE/////P8fAAD///8BAEHOxQAL5AH9HwAAAAAAAPAD/3//////////7//f4f/P//7+7p/5///9xeOfWYCwz/8DAO6H+f///W3DhxkCXsD/PwDuv/v///3t478bAQDP/wAA7p/5///97eOfGcCwz/8CAOzHPdYYx//Dxx2BAMD/AADu3/3///3v498dYAPP/wAA7N/9///97+PfHWBAz/8GAOzf/f/////n312AAM//APzs/3/8///7L3+AX/8AAAwA/v////9//wc/IP8DAAAAAJYl8P6u7P87XyD/8wAAAAABAAAA/wMAAP/+////H/7/A////v///x8AQbrHAAuVAv///////3/5/wP//+fB//9/QP8z/////78g///////3////////////PX89//////89/////z1/Pf9//////////z3//////////4cAAAAA//8AAP////////////8fAP7//////////////////////////////////////////////////////////5////7//wf////////////HAQD/3w8A//8PAP//DwD/3w0A////////z///AYAQ/wMAAAAA/wP//////////////wD//////wf//////////z8A////H/8P/wHA/////z8fAP//////D////wP/AwAAAAD///8P/////////3/+/x8A/wP/A4AAQdrJAAsw////////7//vD/8DAAAAAP//////8////////7//AwD///////8/AP/j//////8/AEGXygALG95vAP///////////////////////////////wBBusoACyD//z8//////z8//6r///8/////////31/cH88P/x/cHwBB6MoACwYCgAAA/x8AQfrKAAsShPwvPlC9//PgQwAA//////8BAEGwywALUMD///////8DAAD//////3///////3//////////////////////H3gMAP////+/IP////////+AAAD//38Af39/f39/f3//////AAAAAACAAEGazAALV+AAAAD+Az4f/v///////////3/g/v/////////////34P////8//v////////////9/AAD///8HAAAAAAAA////////////////////////////////PwBB+swACzL/////////////////////////////////HwAAAAAAAP//////////////////////HwBBtM0ACzz//////z//H////w8AAP//////f/CP////gP////////////8AAAAAgP/8////////////////eQ8A/wcAQfnNAAtn/7v3////AAAA////////DwD//////////w8A/wMAAPwI//////8H/////wcA////H/////////f/AID/AwAAAAD///////9/AP8//wP//38E/////////38FAAA4//88AH5+fgB/fwBB8s4AC4gB//////8H/wP//////////////////////////w8A//9/+P//////D/////////////////8//////////////////wMAAAAAfwD44P/9f1/b/////////////////wMAAAD4////////////////PwAA///////////8////////AAAAAAD/DwBBiNAAC1Lf/////////////////////x8AAP8D/v//B/7//wfA/////////////3/8/PwcAAAAAP/v//9///+3/z//PwAAAAD///////////////////8HAEHi0AALB////////x8AQYrRAAtG////H////////wEAAAAAAP///38AAP///wcAAAAAAAD///8//////w//PgAAAAAA/////////////////////////z//AwBB2tEACws//f////+/kf//PwBB+tEACwj//z8A////AwBBitIACwj/////////wABBmtIACxBv8O/+//8PAAAAAAD///8fAEG60gALD////////z8A//8/AP//BwBB2tIACwr///////////8BAEH60gALKP//////////PwAAAMD/AAD8////////AQAA////Af8D////////x/8AQarTAAsM//////////8eAP8DAEHK0wALHv///////z8A/wMAAAAAAAD/////////////////fwBB+tMACw3///////////////8HAEGa1AALBv//////fwBButQACwj/////////AQBB2tQACxT//////////x8A//////9/AAD4/wBB+tQACwEDAEGa1QALmAH/////////////3///////////32Te/+vv/////////7/n39////97X/z9//////////////////////////////////////////////////////8//////f//9/////f//9/////f//9/////f/////3////9///3z////////+////+W/vcKhOqWqpb3917/+/8P7vv/DwBButYAC+sPVCEiGQ0BAgMRSxwMEAQLHRIeJ2hub3BxYiAFBg8TFBUaCBYHKCQXGAkKDhsfJSODgn0mKis8PT4/Q0dKTVhZWltcXV5fYGFjZGVmZ2lqa2xyc3R5ent8AElsbGVnYWwgYnl0ZSBzZXF1ZW5jZQBEb21haW4gZXJyb3IAUmVzdWx0IG5vdCByZXByZXNlbnRhYmxlAE5vdCBhIHR0eQBQZXJtaXNzaW9uIGRlbmllZABPcGVyYXRpb24gbm90IHBlcm1pdHRlZABObyBzdWNoIGZpbGUgb3IgZGlyZWN0b3J5AE5vIHN1Y2ggcHJvY2VzcwBGaWxlIGV4aXN0cwBWYWx1ZSB0b28gbGFyZ2UgZm9yIGRhdGEgdHlwZQBObyBzcGFjZSBsZWZ0IG9uIGRldmljZQBPdXQgb2YgbWVtb3J5AFJlc291cmNlIGJ1c3kASW50ZXJydXB0ZWQgc3lzdGVtIGNhbGwAUmVzb3VyY2UgdGVtcG9yYXJpbHkgdW5hdmFpbGFibGUASW52YWxpZCBzZWVrAENyb3NzLWRldmljZSBsaW5rAFJlYWQtb25seSBmaWxlIHN5c3RlbQBEaXJlY3Rvcnkgbm90IGVtcHR5AENvbm5lY3Rpb24gcmVzZXQgYnkgcGVlcgBPcGVyYXRpb24gdGltZWQgb3V0AENvbm5lY3Rpb24gcmVmdXNlZABIb3N0IGlzIGRvd24ASG9zdCBpcyB1bnJlYWNoYWJsZQBBZGRyZXNzIGluIHVzZQBCcm9rZW4gcGlwZQBJL08gZXJyb3IATm8gc3VjaCBkZXZpY2Ugb3IgYWRkcmVzcwBCbG9jayBkZXZpY2UgcmVxdWlyZWQATm8gc3VjaCBkZXZpY2UATm90IGEgZGlyZWN0b3J5AElzIGEgZGlyZWN0b3J5AFRleHQgZmlsZSBidXN5AEV4ZWMgZm9ybWF0IGVycm9yAEludmFsaWQgYXJndW1lbnQAQXJndW1lbnQgbGlzdCB0b28gbG9uZwBTeW1ib2xpYyBsaW5rIGxvb3AARmlsZW5hbWUgdG9vIGxvbmcAVG9vIG1hbnkgb3BlbiBmaWxlcyBpbiBzeXN0ZW0ATm8gZmlsZSBkZXNjcmlwdG9ycyBhdmFpbGFibGUAQmFkIGZpbGUgZGVzY3JpcHRvcgBObyBjaGlsZCBwcm9jZXNzAEJhZCBhZGRyZXNzAEZpbGUgdG9vIGxhcmdlAFRvbyBtYW55IGxpbmtzAE5vIGxvY2tzIGF2YWlsYWJsZQBSZXNvdXJjZSBkZWFkbG9jayB3b3VsZCBvY2N1cgBTdGF0ZSBub3QgcmVjb3ZlcmFibGUAUHJldmlvdXMgb3duZXIgZGllZABPcGVyYXRpb24gY2FuY2VsZWQARnVuY3Rpb24gbm90IGltcGxlbWVudGVkAE5vIG1lc3NhZ2Ugb2YgZGVzaXJlZCB0eXBlAElkZW50aWZpZXIgcmVtb3ZlZABEZXZpY2Ugbm90IGEgc3RyZWFtAE5vIGRhdGEgYXZhaWxhYmxlAERldmljZSB0aW1lb3V0AE91dCBvZiBzdHJlYW1zIHJlc291cmNlcwBMaW5rIGhhcyBiZWVuIHNldmVyZWQAUHJvdG9jb2wgZXJyb3IAQmFkIG1lc3NhZ2UARmlsZSBkZXNjcmlwdG9yIGluIGJhZCBzdGF0ZQBOb3QgYSBzb2NrZXQARGVzdGluYXRpb24gYWRkcmVzcyByZXF1aXJlZABNZXNzYWdlIHRvbyBsYXJnZQBQcm90b2NvbCB3cm9uZyB0eXBlIGZvciBzb2NrZXQAUHJvdG9jb2wgbm90IGF2YWlsYWJsZQBQcm90b2NvbCBub3Qgc3VwcG9ydGVkAFNvY2tldCB0eXBlIG5vdCBzdXBwb3J0ZWQATm90IHN1cHBvcnRlZABQcm90b2NvbCBmYW1pbHkgbm90IHN1cHBvcnRlZABBZGRyZXNzIGZhbWlseSBub3Qgc3VwcG9ydGVkIGJ5IHByb3RvY29sAEFkZHJlc3Mgbm90IGF2YWlsYWJsZQBOZXR3b3JrIGlzIGRvd24ATmV0d29yayB1bnJlYWNoYWJsZQBDb25uZWN0aW9uIHJlc2V0IGJ5IG5ldHdvcmsAQ29ubmVjdGlvbiBhYm9ydGVkAE5vIGJ1ZmZlciBzcGFjZSBhdmFpbGFibGUAU29ja2V0IGlzIGNvbm5lY3RlZABTb2NrZXQgbm90IGNvbm5lY3RlZABDYW5ub3Qgc2VuZCBhZnRlciBzb2NrZXQgc2h1dGRvd24AT3BlcmF0aW9uIGFscmVhZHkgaW4gcHJvZ3Jlc3MAT3BlcmF0aW9uIGluIHByb2dyZXNzAFN0YWxlIGZpbGUgaGFuZGxlAFJlbW90ZSBJL08gZXJyb3IAUXVvdGEgZXhjZWVkZWQATm8gbWVkaXVtIGZvdW5kAFdyb25nIG1lZGl1bSB0eXBlAE5vIGVycm9yIGluZm9ybWF0aW9uAABMQ19BTEwATENfQ1RZUEUAAAAATENfTlVNRVJJQwAATENfVElNRQAAAAAATENfQ09MTEFURQAATENfTU9ORVRBUlkATENfTUVTU0FHRVMATEFORwBDLlVURi04AFBPU0lYAE1VU0xfTE9DUEFUSAARAAoAERERAAAAAAUAAAAAAAAJAAAAAAsAQa3mAAshEQAPChEREQMKBwABEwkLCwAACQYLAAALAAYRAAAAERERAEHe5gALAQsAQefmAAsYEQAKChEREQAKAAACAAkLAAAACQALAAALAEGY5wALAQwAQaTnAAsVDAAAAAAMAAAAAAkMAAAAAAAMAAAMAEHS5wALAQ4AQd7nAAsVDQAAAAQNAAAAAAkOAAAAAAAOAAAOAEGM6AALARAAQZjoAAseDwAAAAAPAAAAAAkQAAAAAAAQAAAQAAASAAAAEhISAEHP6AALDhIAAAASEhIAAAAAAAAJAEGA6QALAQsAQYzpAAsVCgAAAAAKAAAAAAkLAAAAAAALAAALAEG66QALAQwAQcbpAAtdDAAAAAAMAAAAAAkMAAAAAAAMAAAMAAAtKyAgIDBYMHgALTBYKzBYIDBYLTB4KzB4IDB4AGluZgBJTkYAbmFuAE5BTgAwMTIzNDU2Nzg5QUJDREVGLgBDLlVURi04AEGs6gALGkMAEQAKABEREQAAAAAFAAAAAAAACQAAAAALAEHO6gALGhEADwoREREDCgcAARMJCwsAAAkGCwAACwAGAEH/6gALAQsAQYrrAAsWCgoAAAAACgAAAgAJCwAAAAkACwAACwBBuesACwEMAEHF6wALFQwAAAAADAAAAAAJDAAAAAAADAAADABB8+sACwEOAEH/6wALFQ0AAAAEDQAAAAAJDgAAAAAADgAADgBBrewACwEQAEG57AALHg8AAAAADwAAAAAJEAAAAAAAEAAAEAAAEgAAABISEgBB8OwACw4SAAAAEhISAAAAAAAACQBBoe0ACwELAEGt7QALFQoAAAAACgAAAAAJCwAAAAAACwAACwBB2+0ACwEMAEHn7QALvAcMAAAAAAwAAAAACQwAAAAAAAwAAAwAACUqcwAobnVsbCkAIwArAC0AIAAwAEwAAGpMTEwAagAAAAAAamoAAAAAagAAaiUlJXMlcyVzJXMlcyouKiVjJWMAYmFzaWNfc3RyaW5nAGFsbG9jYXRvcjxUPjo6YWxsb2NhdGUoc2l6ZV90IG4pICduJyBleGNlZWRzIG1heGltdW0gc3VwcG9ydGVkIHNpemUAdGVybWluYXRpbmcgd2l0aCAlcyBleGNlcHRpb24gb2YgdHlwZSAlczogJXMAdGVybWluYXRpbmcgd2l0aCAlcyBleGNlcHRpb24gb2YgdHlwZSAlcwB0ZXJtaW5hdGluZyB3aXRoICVzIGZvcmVpZ24gZXhjZXB0aW9uAHRlcm1pbmF0aW5nAHVuY2F1Z2h0AFN0OWV4Y2VwdGlvbgBOMTBfX2N4eGFiaXYxMTZfX3NoaW1fdHlwZV9pbmZvRQBTdDl0eXBlX2luZm8ATjEwX19jeHhhYml2MTIwX19zaV9jbGFzc190eXBlX2luZm9FAE4xMF9fY3h4YWJpdjExN19fY2xhc3NfdHlwZV9pbmZvRQBwdGhyZWFkX29uY2UgZmFpbHVyZSBpbiBfX2N4YV9nZXRfZ2xvYmFsc19mYXN0KCkAY2Fubm90IGNyZWF0ZSBwdGhyZWFkIGtleSBmb3IgX19jeGFfZ2V0X2dsb2JhbHMoKQBjYW5ub3QgemVybyBvdXQgdGhyZWFkIHZhbHVlIGZvciBfX2N4YV9nZXRfZ2xvYmFscygpAHRlcm1pbmF0ZV9oYW5kbGVyIHVuZXhwZWN0ZWRseSByZXR1cm5lZAB0ZXJtaW5hdGVfaGFuZGxlciB1bmV4cGVjdGVkbHkgdGhyZXcgYW4gZXhjZXB0aW9uAHN0ZDo6YmFkX2FsbG9jAFN0OWJhZF9hbGxvYwBTdDExbG9naWNfZXJyb3IAU3QxMmxlbmd0aF9lcnJvcgBOMTBfX2N4eGFiaXYxMTlfX3BvaW50ZXJfdHlwZV9pbmZvRQBOMTBfX2N4eGFiaXYxMTdfX3BiYXNlX3R5cGVfaW5mb0UATjEwX19jeHhhYml2MTIzX19mdW5kYW1lbnRhbF90eXBlX2luZm9FAHYARG4AYgBjAGgAYQBzAHQAaQBqAGwAbQBmAGQATjEwX19jeHhhYml2MTE2X19lbnVtX3R5cGVfaW5mb0UATjEwX19jeHhhYml2MTIxX192bWlfY2xhc3NfdHlwZV9pbmZvRQ==";class ResourceLoaderPlugin{getType(){return"none"}async loadFile(A){return null}}const Module={},WorkerScope={};!function(A){A.unpackBridge=function(A){return function(A){var g={};function I(C){if(g[C])return g[C].exports;var e=g[C]={i:C,l:!1,exports:{}};return A[C].call(e.exports,e,e.exports,I),e.l=!0,e.exports}return I.m=A,I.c=g,I.d=function(A,g,C){I.o(A,g)||Object.defineProperty(A,g,{enumerable:!0,get:C})},I.r=function(A){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(A,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(A,"__esModule",{value:!0})},I.t=function(A,g){if(1&g&&(A=I(A)),8&g)return A;if(4&g&&"object"==typeof A&&A&&A.__esModule)return A;var C=Object.create(null);if(I.r(C),Object.defineProperty(C,"default",{enumerable:!0,value:A}),2&g&&"string"!=typeof A)for(var e in A)I.d(C,e,function(g){return A[g]}.bind(null,e));return C},I.n=function(A){var g=A&&A.__esModule?function(){return A.default}:function(){return A};return I.d(g,"a",g),g},I.o=function(A,g){return Object.prototype.hasOwnProperty.call(A,g)},I.p="",I(I.s=2)}([function(A,g,I){Object.defineProperty(g,"__esModule",{value:!0});const C=I(1),e={0:"ERAR_SUCCESS",10:"ERAR_END_ARCHIVE",11:"ERAR_NO_MEMORY",12:"ERAR_BAD_DATA",13:"ERAR_BAD_ARCHIVE",14:"ERAR_UNKNOWN_FORMAT",15:"ERAR_EOPEN",16:"ERAR_ECREATE",17:"ERAR_ECLOSE",18:"ERAR_EREAD",19:"ERAR_EWRITE",20:"ERAR_SMALL_BUF",21:"ERAR_UNKNOWN",22:"ERAR_MISSING_PASSWORD",23:"ERAR_EREFERENCE",24:"ERAR_BAD_PASSWORD"},i={0:"Success",11:"Not enough memory",12:"Archive header or data are damaged",13:"File is not RAR archive",14:"Unknown archive format",15:"File open error",16:"File create error",17:"File close error",18:"File read error",19:"File write error",20:"Buffer for archive comment is too small, comment truncated",21:"Unknown error",22:"Password for encrypted file or header is not specified",23:"Cannot open file source for reference record",24:"Wrong password is specified"};class t{constructor(A=""){this._password=A,this._archive=null}getFileList(){let A,[g,I]=this.openArc(!0);if("SUCCESS"!==g.state)A=[g,null];else{let g,C,e=[];for(;[g,C]=this.processNextFile((()=>!0)),"SUCCESS"===g.state;)e.push(C.fileHeader);A="ERAR_END_ARCHIVE"!==g.reason?[g,null]:[{state:"SUCCESS"},{arcHeader:I,fileHeaders:e}]}return this.closeArc(),A}extractAll(){let A,[g,I]=this.openArc(!1);if("SUCCESS"!==g.state)A=[g,null];else{let g,C,e=[];for(;[g,C]=this.processNextFile((()=>!1)),"SUCCESS"===g.state;)e.push(C);A="ERAR_END_ARCHIVE"!==g.reason?[g,null]:[{state:"SUCCESS"},{arcHeader:I,files:e}]}return this.closeArc(),A}extractFiles(A,g){let I,[C,e]=this.openArc(!1,g),i={};for(let g=0;g<A.length;++g)i[A[g]]=g;if("SUCCESS"!==C.state)I=[C,null];else{let g,C,t=Array(A.length).fill(null),o=0;for(;;){let I=!1,e=null;if([g,C]=this.processNextFile((A=>A in i?(e=i[A],!1):(I=!0,!0))),"SUCCESS"!==g.state)break;if(!I&&(t[e]=C,++o===A.length)){g.reason="ERAR_END_ARCHIVE";break}}I="ERAR_END_ARCHIVE"!==g.reason?[g,null]:[{state:"SUCCESS"},{arcHeader:e,files:t}]}return this.closeArc(),I}fileCreated(A){}close(A){this._lastFileContent=this.closeFile(A)}openArc(A,g){C.Ext.current=this,this._archive=new unpack.RarArchive;let I,e=this._archive.open(this._filePath,g||this._password,A);return I=0!==e.state.errCode?[this.getFailInfo(e.state.errCode,e.state.errType),null]:[{state:"SUCCESS"},{comment:e.comment,flags:{volume:!!(1&e.flags),lock:!!(4&e.flags),solid:!!(8&e.flags),authInfo:!!(32&e.flags),recoveryRecord:!!(64&e.flags),headerEncrypted:!!(128&e.flags)}}],C.Ext.current=null,I}processNextFile(A){let g;C.Ext.current=this;let I=this._archive.getFileHeader(),e=[{state:"SUCCESS"},null];if(0===I.state.errCode){let g=A(I.name);this._lastFileContent=null;let C=this._archive.readFile(g);0===C.errCode||g||(e[0]=this.getFailInfo(C.errCode,C.errType),22===C.errCode?C=this._archive.readFile(!0):C.errCode=0),0===C.errCode?e[1]=this._lastFileContent:(I.state.errCode=C.errCode,I.state.errType=C.errType),this._lastFileContent=null}return g=0!==I.state.errCode?[this.getFailInfo(I.state.errCode,I.state.errType),null]:[{state:"SUCCESS"},{fileHeader:{name:I.name,flags:{encrypted:!!(4&I.flags),solid:!!(16&I.flags),directory:!!(32&I.flags)},packSize:I.packSize,unpSize:I.unpSize,crc:I.crc,time:function(A){const g=[5,6,5,5,4,7];let I=[];for(let C of g)I.push(A&(1<<C)-1),A>>=C;let C=A=>A<10?"0"+A:""+A;return`${1980+(I=I.reverse())[0]}-${C(I[1])}-${C(I[2])}T${C(I[3])}:${C(I[4])}:${C(2*I[5])}.000`}(I.time),unpVer:`${Math.floor(I.unpVer/10)}.${I.unpVer%10}`,method:function(A){return{48:"Storing",49:"Fastest",50:"Fast",51:"Normal",52:"Good",53:"Best"}[A]||"Unknown"}(I.method)},extract:e}],C.Ext.current=null,g}closeArc(){C.Ext.current=this,this._archive.delete(),C.Ext.current=null,this._archive=null}getFailInfo(A,g){return{state:"FAIL",reason:e[A],msg:i[A]}}}t._current=null,g.Extractor=t},function(A,g,I){Object.defineProperty(g,"__esModule",{value:!0}),g.Ext={current:null}},function(A,g,I){Object.defineProperty(g,"__esModule",{value:!0}),function(A){for(var I in A)g.hasOwnProperty(I)||(g[I]=A[I])}(I(3));var C=I(1);g.Ext=C.Ext},function(A,g,I){Object.defineProperty(g,"__esModule",{value:!0});const C=I(4),e=I(6);g.createExtractorFromData=function(A,g=""){return new C.DataExtractor(A,g)},g.createExtractorFromFile=function(A,g="",I=""){return new e.FileExtractor(A,g,I)}},function(A,g,I){Object.defineProperty(g,"__esModule",{value:!0});const C=I(5),e=I(0);g.DataExtractor=class extends e.Extractor{constructor(A,g){super(g),this.dataFiles={},this.dataFileMap={},this.currentFd=1;let I={file:new C.DataFile(new Uint8Array(A)),fd:this.currentFd++};this._filePath="_defaultUnrarJS_.rar",this.dataFiles[this._filePath]=I,this.dataFileMap[I.fd]=this._filePath}open(A){let g=this.dataFiles[A];return g?g.fd:0}create(A){let g=this.currentFd++;return this.dataFiles[A]={file:new C.DataFile,fd:this.currentFd++},this.dataFileMap[g]=A,g}closeFile(A){let g=this.dataFiles[this.dataFileMap[A]];if(!g)return null;let I=g.file.readAll();return 1!==A?(delete this.dataFiles[this.dataFileMap[A]],delete this.dataFileMap[A]):g.file.seek(0,"SET"),I}read(A,g,I){let C=this.dataFiles[this.dataFileMap[A]];if(!C)return-1;let e=C.file.read(I);return null===e?-1:(unpack.HEAPU8.set(e,g),e.byteLength)}write(A,g,I){let C=this.dataFiles[this.dataFileMap[A]];return!!C&&(C.file.write(unpack.HEAPU8.slice(g,g+I)),!0)}tell(A){let g=this.dataFiles[this.dataFileMap[A]];return g?g.file.tell():-1}seek(A,g,I){let C=this.dataFiles[this.dataFileMap[A]];return!!C&&C.file.seek(g,I)}}},function(A,g,I){Object.defineProperty(g,"__esModule",{value:!0}),g.DataFile=class{constructor(A){this.buffers=[],this.pos=0,this.size=0,A&&(this.buffers.push(A),this.size=A.byteLength,this.pos=0)}read(A){if(this.flatten(),A+this.pos>this.size)return null;let g=this.pos;return this.pos+=A,this.buffers[0].slice(g,this.pos)}readAll(){return this.flatten(),this.buffers[0]}write(A){return this.buffers.push(A),this.size+=A.byteLength,this.pos+=A.byteLength,!0}tell(){return this.pos}seek(A,g){let I=this.pos;return"SET"===g?I=A:"CUR"===g?I+=A:I=this.size-A,!(I<0||I>this.size||(this.pos=I,0))}flatten(){if(this.buffers.length<=1)return;let A=new Uint8Array(this.size),g=0;for(let I of this.buffers)A.set(I,g),g+=I.byteLength;this.buffers=[A]}}},function(A,g,I){(function(A){Object.defineProperty(g,"__esModule",{value:!0});const C=I(12),e=I(13),i=I(0);g.FileExtractor=class extends i.Extractor{constructor(A,g,I){super(I),this._filePath=A,this.fileMap={},this._target=g}open(A){let g=C.openSync(A,"r");return this.fileMap[g]={size:C.fstatSync(g).size,pos:0,name:A},g}create(A){let g=e.join(this._target,A);e.parse(g).dir.split("/").reduce(((A,g)=>(A+=g+"/",C.existsSync(A)||C.mkdirSync(A),A)),"");let I=C.openSync(g,"w");return this.fileMap[I]={size:0,pos:0,name:A},I}closeFile(A){return delete this.fileMap[A],C.closeSync(A),null}read(g,I,e){let i=this.fileMap[g],t=new A(e),o=C.readSync(g,t,0,e,i.pos);return unpack.HEAPU8.set(t,I),i.pos+=o,o}write(g,I,e){let i=this.fileMap[g],t=C.writeSync(g,new A(unpack.HEAPU8.subarray(I,I+e)),0,e);return i.pos+=t,i.size+=t,t===e}tell(A){return this.fileMap[A].pos}seek(A,g,I){let C=this.fileMap[A],e=C.pos;return"SET"===I?e=0:"END"===I&&(e=C.size),!((e+=g)<0||e>C.size||(C.pos=e,0))}}}).call(this,I(7).Buffer)},function(A,g,I){(function(A){
/*!
         * The buffer module from node.js, for the browser.
         *
         * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
         * @license  MIT
         */
var C=I(9),e=I(10),i=I(11);function t(){return a.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function o(A,g){if(t()<g)throw new RangeError("Invalid typed array length");return a.TYPED_ARRAY_SUPPORT?(A=new Uint8Array(g)).__proto__=a.prototype:(null===A&&(A=new a(g)),A.length=g),A}function a(A,g,I){if(!(a.TYPED_ARRAY_SUPPORT||this instanceof a))return new a(A,g,I);if("number"==typeof A){if("string"==typeof g)throw new Error("If encoding is specified then the first argument must be a string");return l(this,A)}return B(this,A,g,I)}function B(A,g,I,C){if("number"==typeof g)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&g instanceof ArrayBuffer?function(A,g,I,C){if(g.byteLength,I<0||g.byteLength<I)throw new RangeError("'offset' is out of bounds");if(g.byteLength<I+(C||0))throw new RangeError("'length' is out of bounds");return g=void 0===I&&void 0===C?new Uint8Array(g):void 0===C?new Uint8Array(g,I):new Uint8Array(g,I,C),a.TYPED_ARRAY_SUPPORT?(A=g).__proto__=a.prototype:A=n(A,g),A}(A,g,I,C):"string"==typeof g?function(A,g,I){if("string"==typeof I&&""!==I||(I="utf8"),!a.isEncoding(I))throw new TypeError('"encoding" must be a valid string encoding');var C=0|r(g,I),e=(A=o(A,C)).write(g,I);return e!==C&&(A=A.slice(0,e)),A}(A,g,I):function(A,g){if(a.isBuffer(g)){var I=0|d(g.length);return 0===(A=o(A,I)).length||g.copy(A,0,0,I),A}if(g){if("undefined"!=typeof ArrayBuffer&&g.buffer instanceof ArrayBuffer||"length"in g)return"number"!=typeof g.length||function(A){return A!=A}(g.length)?o(A,0):n(A,g);if("Buffer"===g.type&&i(g.data))return n(A,g.data)}throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(A,g)}function s(A){if("number"!=typeof A)throw new TypeError('"size" argument must be a number');if(A<0)throw new RangeError('"size" argument must not be negative')}function l(A,g){if(s(g),A=o(A,g<0?0:0|d(g)),!a.TYPED_ARRAY_SUPPORT)for(var I=0;I<g;++I)A[I]=0;return A}function n(A,g){var I=g.length<0?0:0|d(g.length);A=o(A,I);for(var C=0;C<I;C+=1)A[C]=255&g[C];return A}function d(A){if(A>=t())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+t().toString(16)+" bytes");return 0|A}function r(A,g){if(a.isBuffer(A))return A.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(A)||A instanceof ArrayBuffer))return A.byteLength;"string"!=typeof A&&(A=""+A);var I=A.length;if(0===I)return 0;for(var C=!1;;)switch(g){case"ascii":case"latin1":case"binary":return I;case"utf8":case"utf-8":case void 0:return L(A).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*I;case"hex":return I>>>1;case"base64":return M(A).length;default:if(C)return L(A).length;g=(""+g).toLowerCase(),C=!0}}function c(A,g,I){var C=A[g];A[g]=A[I],A[I]=C}function h(A,g,I,C,e){if(0===A.length)return-1;if("string"==typeof I?(C=I,I=0):I>2147483647?I=2147483647:I<-2147483648&&(I=-2147483648),I=+I,isNaN(I)&&(I=e?0:A.length-1),I<0&&(I=A.length+I),I>=A.length){if(e)return-1;I=A.length-1}else if(I<0){if(!e)return-1;I=0}if("string"==typeof g&&(g=a.from(g,C)),a.isBuffer(g))return 0===g.length?-1:G(A,g,I,C,e);if("number"==typeof g)return g&=255,a.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?e?Uint8Array.prototype.indexOf.call(A,g,I):Uint8Array.prototype.lastIndexOf.call(A,g,I):G(A,[g],I,C,e);throw new TypeError("val must be string, number or Buffer")}function G(A,g,I,C,e){var i,t=1,o=A.length,a=g.length;if(void 0!==C&&("ucs2"===(C=String(C).toLowerCase())||"ucs-2"===C||"utf16le"===C||"utf-16le"===C)){if(A.length<2||g.length<2)return-1;t=2,o/=2,a/=2,I/=2}function B(A,g){return 1===t?A[g]:A.readUInt16BE(g*t)}if(e){var s=-1;for(i=I;i<o;i++)if(B(A,i)===B(g,-1===s?0:i-s)){if(-1===s&&(s=i),i-s+1===a)return s*t}else-1!==s&&(i-=i-s),s=-1}else for(I+a>o&&(I=o-a),i=I;i>=0;i--){for(var l=!0,n=0;n<a;n++)if(B(A,i+n)!==B(g,n)){l=!1;break}if(l)return i}return-1}function m(A,g,I,C){I=Number(I)||0;var e=A.length-I;C?(C=Number(C))>e&&(C=e):C=e;var i=g.length;if(i%2!=0)throw new TypeError("Invalid hex string");C>i/2&&(C=i/2);for(var t=0;t<C;++t){var o=parseInt(g.substr(2*t,2),16);if(isNaN(o))return t;A[I+t]=o}return t}function b(A,g,I,C){return U(L(g,A.length-I),A,I,C)}function Z(A,g,I,C){return U(function(A){for(var g=[],I=0;I<A.length;++I)g.push(255&A.charCodeAt(I));return g}(g),A,I,C)}function u(A,g,I,C){return Z(A,g,I,C)}function y(A,g,I,C){return U(M(g),A,I,C)}function E(A,g,I,C){return U(function(A,g){for(var I,C,e,i=[],t=0;t<A.length&&!((g-=2)<0);++t)C=(I=A.charCodeAt(t))>>8,e=I%256,i.push(e),i.push(C);return i}(g,A.length-I),A,I,C)}function Q(A,g,I){return 0===g&&I===A.length?C.fromByteArray(A):C.fromByteArray(A.slice(g,I))}function V(A,g,I){I=Math.min(A.length,I);for(var C=[],e=g;e<I;){var i,t,o,a,B=A[e],s=null,l=B>239?4:B>223?3:B>191?2:1;if(e+l<=I)switch(l){case 1:B<128&&(s=B);break;case 2:128==(192&(i=A[e+1]))&&(a=(31&B)<<6|63&i)>127&&(s=a);break;case 3:i=A[e+1],t=A[e+2],128==(192&i)&&128==(192&t)&&(a=(15&B)<<12|(63&i)<<6|63&t)>2047&&(a<55296||a>57343)&&(s=a);break;case 4:i=A[e+1],t=A[e+2],o=A[e+3],128==(192&i)&&128==(192&t)&&128==(192&o)&&(a=(15&B)<<18|(63&i)<<12|(63&t)<<6|63&o)>65535&&a<1114112&&(s=a)}null===s?(s=65533,l=1):s>65535&&(s-=65536,C.push(s>>>10&1023|55296),s=56320|1023&s),C.push(s),e+=l}return function(A){var g=A.length;if(g<=R)return String.fromCharCode.apply(String,A);for(var I="",C=0;C<g;)I+=String.fromCharCode.apply(String,A.slice(C,C+=R));return I}(C)}g.Buffer=a,g.SlowBuffer=function(A){return+A!=A&&(A=0),a.alloc(+A)},g.INSPECT_MAX_BYTES=50,a.TYPED_ARRAY_SUPPORT=void 0!==A.TYPED_ARRAY_SUPPORT?A.TYPED_ARRAY_SUPPORT:function(){try{var A=new Uint8Array(1);return A.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===A.foo()&&"function"==typeof A.subarray&&0===A.subarray(1,1).byteLength}catch(A){return!1}}(),g.kMaxLength=t(),a.poolSize=8192,a._augment=function(A){return A.__proto__=a.prototype,A},a.from=function(A,g,I){return B(null,A,g,I)},a.TYPED_ARRAY_SUPPORT&&(a.prototype.__proto__=Uint8Array.prototype,a.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&a[Symbol.species]===a&&Object.defineProperty(a,Symbol.species,{value:null,configurable:!0})),a.alloc=function(A,g,I){return function(A,g,I,C){return s(g),g<=0?o(A,g):void 0!==I?"string"==typeof C?o(A,g).fill(I,C):o(A,g).fill(I):o(A,g)}(null,A,g,I)},a.allocUnsafe=function(A){return l(null,A)},a.allocUnsafeSlow=function(A){return l(null,A)},a.isBuffer=function(A){return!(null==A||!A._isBuffer)},a.compare=function(A,g){if(!a.isBuffer(A)||!a.isBuffer(g))throw new TypeError("Arguments must be Buffers");if(A===g)return 0;for(var I=A.length,C=g.length,e=0,i=Math.min(I,C);e<i;++e)if(A[e]!==g[e]){I=A[e],C=g[e];break}return I<C?-1:C<I?1:0},a.isEncoding=function(A){switch(String(A).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},a.concat=function(A,g){if(!i(A))throw new TypeError('"list" argument must be an Array of Buffers');if(0===A.length)return a.alloc(0);var I;if(void 0===g)for(g=0,I=0;I<A.length;++I)g+=A[I].length;var C=a.allocUnsafe(g),e=0;for(I=0;I<A.length;++I){var t=A[I];if(!a.isBuffer(t))throw new TypeError('"list" argument must be an Array of Buffers');t.copy(C,e),e+=t.length}return C},a.byteLength=r,a.prototype._isBuffer=!0,a.prototype.swap16=function(){var A=this.length;if(A%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var g=0;g<A;g+=2)c(this,g,g+1);return this},a.prototype.swap32=function(){var A=this.length;if(A%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var g=0;g<A;g+=4)c(this,g,g+3),c(this,g+1,g+2);return this},a.prototype.swap64=function(){var A=this.length;if(A%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var g=0;g<A;g+=8)c(this,g,g+7),c(this,g+1,g+6),c(this,g+2,g+5),c(this,g+3,g+4);return this},a.prototype.toString=function(){var A=0|this.length;return 0===A?"":0===arguments.length?V(this,0,A):function(A,g,I){var C=!1;if((void 0===g||g<0)&&(g=0),g>this.length)return"";if((void 0===I||I>this.length)&&(I=this.length),I<=0)return"";if((I>>>=0)<=(g>>>=0))return"";for(A||(A="utf8");;)switch(A){case"hex":return S(this,g,I);case"utf8":case"utf-8":return V(this,g,I);case"ascii":return W(this,g,I);case"latin1":case"binary":return p(this,g,I);case"base64":return Q(this,g,I);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return F(this,g,I);default:if(C)throw new TypeError("Unknown encoding: "+A);A=(A+"").toLowerCase(),C=!0}}.apply(this,arguments)},a.prototype.equals=function(A){if(!a.isBuffer(A))throw new TypeError("Argument must be a Buffer");return this===A||0===a.compare(this,A)},a.prototype.inspect=function(){var A="",I=g.INSPECT_MAX_BYTES;return this.length>0&&(A=this.toString("hex",0,I).match(/.{2}/g).join(" "),this.length>I&&(A+=" ... ")),"<Buffer "+A+">"},a.prototype.compare=function(A,g,I,C,e){if(!a.isBuffer(A))throw new TypeError("Argument must be a Buffer");if(void 0===g&&(g=0),void 0===I&&(I=A?A.length:0),void 0===C&&(C=0),void 0===e&&(e=this.length),g<0||I>A.length||C<0||e>this.length)throw new RangeError("out of range index");if(C>=e&&g>=I)return 0;if(C>=e)return-1;if(g>=I)return 1;if(this===A)return 0;for(var i=(e>>>=0)-(C>>>=0),t=(I>>>=0)-(g>>>=0),o=Math.min(i,t),B=this.slice(C,e),s=A.slice(g,I),l=0;l<o;++l)if(B[l]!==s[l]){i=B[l],t=s[l];break}return i<t?-1:t<i?1:0},a.prototype.includes=function(A,g,I){return-1!==this.indexOf(A,g,I)},a.prototype.indexOf=function(A,g,I){return h(this,A,g,I,!0)},a.prototype.lastIndexOf=function(A,g,I){return h(this,A,g,I,!1)},a.prototype.write=function(A,g,I,C){if(void 0===g)C="utf8",I=this.length,g=0;else if(void 0===I&&"string"==typeof g)C=g,I=this.length,g=0;else{if(!isFinite(g))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");g|=0,isFinite(I)?(I|=0,void 0===C&&(C="utf8")):(C=I,I=void 0)}var e=this.length-g;if((void 0===I||I>e)&&(I=e),A.length>0&&(I<0||g<0)||g>this.length)throw new RangeError("Attempt to write outside buffer bounds");C||(C="utf8");for(var i=!1;;)switch(C){case"hex":return m(this,A,g,I);case"utf8":case"utf-8":return b(this,A,g,I);case"ascii":return Z(this,A,g,I);case"latin1":case"binary":return u(this,A,g,I);case"base64":return y(this,A,g,I);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return E(this,A,g,I);default:if(i)throw new TypeError("Unknown encoding: "+C);C=(""+C).toLowerCase(),i=!0}},a.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var R=4096;function W(A,g,I){var C="";I=Math.min(A.length,I);for(var e=g;e<I;++e)C+=String.fromCharCode(127&A[e]);return C}function p(A,g,I){var C="";I=Math.min(A.length,I);for(var e=g;e<I;++e)C+=String.fromCharCode(A[e]);return C}function S(A,g,I){var C=A.length;(!g||g<0)&&(g=0),(!I||I<0||I>C)&&(I=C);for(var e="",i=g;i<I;++i)e+=f(A[i]);return e}function F(A,g,I){for(var C=A.slice(g,I),e="",i=0;i<C.length;i+=2)e+=String.fromCharCode(C[i]+256*C[i+1]);return e}function w(A,g,I){if(A%1!=0||A<0)throw new RangeError("offset is not uint");if(A+g>I)throw new RangeError("Trying to access beyond buffer length")}function H(A,g,I,C,e,i){if(!a.isBuffer(A))throw new TypeError('"buffer" argument must be a Buffer instance');if(g>e||g<i)throw new RangeError('"value" argument is out of bounds');if(I+C>A.length)throw new RangeError("Index out of range")}function X(A,g,I,C){g<0&&(g=65535+g+1);for(var e=0,i=Math.min(A.length-I,2);e<i;++e)A[I+e]=(g&255<<8*(C?e:1-e))>>>8*(C?e:1-e)}function Y(A,g,I,C){g<0&&(g=4294967295+g+1);for(var e=0,i=Math.min(A.length-I,4);e<i;++e)A[I+e]=g>>>8*(C?e:3-e)&255}function K(A,g,I,C,e,i){if(I+C>A.length)throw new RangeError("Index out of range");if(I<0)throw new RangeError("Index out of range")}function N(A,g,I,C,i){return i||K(A,0,I,4),e.write(A,g,I,C,23,4),I+4}function v(A,g,I,C,i){return i||K(A,0,I,8),e.write(A,g,I,C,52,8),I+8}a.prototype.slice=function(A,g){var I,C=this.length;if((A=~~A)<0?(A+=C)<0&&(A=0):A>C&&(A=C),(g=void 0===g?C:~~g)<0?(g+=C)<0&&(g=0):g>C&&(g=C),g<A&&(g=A),a.TYPED_ARRAY_SUPPORT)(I=this.subarray(A,g)).__proto__=a.prototype;else{var e=g-A;I=new a(e,void 0);for(var i=0;i<e;++i)I[i]=this[i+A]}return I},a.prototype.readUIntLE=function(A,g,I){A|=0,g|=0,I||w(A,g,this.length);for(var C=this[A],e=1,i=0;++i<g&&(e*=256);)C+=this[A+i]*e;return C},a.prototype.readUIntBE=function(A,g,I){A|=0,g|=0,I||w(A,g,this.length);for(var C=this[A+--g],e=1;g>0&&(e*=256);)C+=this[A+--g]*e;return C},a.prototype.readUInt8=function(A,g){return g||w(A,1,this.length),this[A]},a.prototype.readUInt16LE=function(A,g){return g||w(A,2,this.length),this[A]|this[A+1]<<8},a.prototype.readUInt16BE=function(A,g){return g||w(A,2,this.length),this[A]<<8|this[A+1]},a.prototype.readUInt32LE=function(A,g){return g||w(A,4,this.length),(this[A]|this[A+1]<<8|this[A+2]<<16)+16777216*this[A+3]},a.prototype.readUInt32BE=function(A,g){return g||w(A,4,this.length),16777216*this[A]+(this[A+1]<<16|this[A+2]<<8|this[A+3])},a.prototype.readIntLE=function(A,g,I){A|=0,g|=0,I||w(A,g,this.length);for(var C=this[A],e=1,i=0;++i<g&&(e*=256);)C+=this[A+i]*e;return C>=(e*=128)&&(C-=Math.pow(2,8*g)),C},a.prototype.readIntBE=function(A,g,I){A|=0,g|=0,I||w(A,g,this.length);for(var C=g,e=1,i=this[A+--C];C>0&&(e*=256);)i+=this[A+--C]*e;return i>=(e*=128)&&(i-=Math.pow(2,8*g)),i},a.prototype.readInt8=function(A,g){return g||w(A,1,this.length),128&this[A]?-1*(255-this[A]+1):this[A]},a.prototype.readInt16LE=function(A,g){g||w(A,2,this.length);var I=this[A]|this[A+1]<<8;return 32768&I?4294901760|I:I},a.prototype.readInt16BE=function(A,g){g||w(A,2,this.length);var I=this[A+1]|this[A]<<8;return 32768&I?4294901760|I:I},a.prototype.readInt32LE=function(A,g){return g||w(A,4,this.length),this[A]|this[A+1]<<8|this[A+2]<<16|this[A+3]<<24},a.prototype.readInt32BE=function(A,g){return g||w(A,4,this.length),this[A]<<24|this[A+1]<<16|this[A+2]<<8|this[A+3]},a.prototype.readFloatLE=function(A,g){return g||w(A,4,this.length),e.read(this,A,!0,23,4)},a.prototype.readFloatBE=function(A,g){return g||w(A,4,this.length),e.read(this,A,!1,23,4)},a.prototype.readDoubleLE=function(A,g){return g||w(A,8,this.length),e.read(this,A,!0,52,8)},a.prototype.readDoubleBE=function(A,g){return g||w(A,8,this.length),e.read(this,A,!1,52,8)},a.prototype.writeUIntLE=function(A,g,I,C){A=+A,g|=0,I|=0,C||H(this,A,g,I,Math.pow(2,8*I)-1,0);var e=1,i=0;for(this[g]=255&A;++i<I&&(e*=256);)this[g+i]=A/e&255;return g+I},a.prototype.writeUIntBE=function(A,g,I,C){A=+A,g|=0,I|=0,C||H(this,A,g,I,Math.pow(2,8*I)-1,0);var e=I-1,i=1;for(this[g+e]=255&A;--e>=0&&(i*=256);)this[g+e]=A/i&255;return g+I},a.prototype.writeUInt8=function(A,g,I){return A=+A,g|=0,I||H(this,A,g,1,255,0),a.TYPED_ARRAY_SUPPORT||(A=Math.floor(A)),this[g]=255&A,g+1},a.prototype.writeUInt16LE=function(A,g,I){return A=+A,g|=0,I||H(this,A,g,2,65535,0),a.TYPED_ARRAY_SUPPORT?(this[g]=255&A,this[g+1]=A>>>8):X(this,A,g,!0),g+2},a.prototype.writeUInt16BE=function(A,g,I){return A=+A,g|=0,I||H(this,A,g,2,65535,0),a.TYPED_ARRAY_SUPPORT?(this[g]=A>>>8,this[g+1]=255&A):X(this,A,g,!1),g+2},a.prototype.writeUInt32LE=function(A,g,I){return A=+A,g|=0,I||H(this,A,g,4,4294967295,0),a.TYPED_ARRAY_SUPPORT?(this[g+3]=A>>>24,this[g+2]=A>>>16,this[g+1]=A>>>8,this[g]=255&A):Y(this,A,g,!0),g+4},a.prototype.writeUInt32BE=function(A,g,I){return A=+A,g|=0,I||H(this,A,g,4,4294967295,0),a.TYPED_ARRAY_SUPPORT?(this[g]=A>>>24,this[g+1]=A>>>16,this[g+2]=A>>>8,this[g+3]=255&A):Y(this,A,g,!1),g+4},a.prototype.writeIntLE=function(A,g,I,C){if(A=+A,g|=0,!C){var e=Math.pow(2,8*I-1);H(this,A,g,I,e-1,-e)}var i=0,t=1,o=0;for(this[g]=255&A;++i<I&&(t*=256);)A<0&&0===o&&0!==this[g+i-1]&&(o=1),this[g+i]=(A/t|0)-o&255;return g+I},a.prototype.writeIntBE=function(A,g,I,C){if(A=+A,g|=0,!C){var e=Math.pow(2,8*I-1);H(this,A,g,I,e-1,-e)}var i=I-1,t=1,o=0;for(this[g+i]=255&A;--i>=0&&(t*=256);)A<0&&0===o&&0!==this[g+i+1]&&(o=1),this[g+i]=(A/t|0)-o&255;return g+I},a.prototype.writeInt8=function(A,g,I){return A=+A,g|=0,I||H(this,A,g,1,127,-128),a.TYPED_ARRAY_SUPPORT||(A=Math.floor(A)),A<0&&(A=255+A+1),this[g]=255&A,g+1},a.prototype.writeInt16LE=function(A,g,I){return A=+A,g|=0,I||H(this,A,g,2,32767,-32768),a.TYPED_ARRAY_SUPPORT?(this[g]=255&A,this[g+1]=A>>>8):X(this,A,g,!0),g+2},a.prototype.writeInt16BE=function(A,g,I){return A=+A,g|=0,I||H(this,A,g,2,32767,-32768),a.TYPED_ARRAY_SUPPORT?(this[g]=A>>>8,this[g+1]=255&A):X(this,A,g,!1),g+2},a.prototype.writeInt32LE=function(A,g,I){return A=+A,g|=0,I||H(this,A,g,4,2147483647,-2147483648),a.TYPED_ARRAY_SUPPORT?(this[g]=255&A,this[g+1]=A>>>8,this[g+2]=A>>>16,this[g+3]=A>>>24):Y(this,A,g,!0),g+4},a.prototype.writeInt32BE=function(A,g,I){return A=+A,g|=0,I||H(this,A,g,4,2147483647,-2147483648),A<0&&(A=4294967295+A+1),a.TYPED_ARRAY_SUPPORT?(this[g]=A>>>24,this[g+1]=A>>>16,this[g+2]=A>>>8,this[g+3]=255&A):Y(this,A,g,!1),g+4},a.prototype.writeFloatLE=function(A,g,I){return N(this,A,g,!0,I)},a.prototype.writeFloatBE=function(A,g,I){return N(this,A,g,!1,I)},a.prototype.writeDoubleLE=function(A,g,I){return v(this,A,g,!0,I)},a.prototype.writeDoubleBE=function(A,g,I){return v(this,A,g,!1,I)},a.prototype.copy=function(A,g,I,C){if(I||(I=0),C||0===C||(C=this.length),g>=A.length&&(g=A.length),g||(g=0),C>0&&C<I&&(C=I),C===I)return 0;if(0===A.length||0===this.length)return 0;if(g<0)throw new RangeError("targetStart out of bounds");if(I<0||I>=this.length)throw new RangeError("sourceStart out of bounds");if(C<0)throw new RangeError("sourceEnd out of bounds");C>this.length&&(C=this.length),A.length-g<C-I&&(C=A.length-g+I);var e,i=C-I;if(this===A&&I<g&&g<C)for(e=i-1;e>=0;--e)A[e+g]=this[e+I];else if(i<1e3||!a.TYPED_ARRAY_SUPPORT)for(e=0;e<i;++e)A[e+g]=this[e+I];else Uint8Array.prototype.set.call(A,this.subarray(I,I+i),g);return i},a.prototype.fill=function(A,g,I,C){if("string"==typeof A){if("string"==typeof g?(C=g,g=0,I=this.length):"string"==typeof I&&(C=I,I=this.length),1===A.length){var e=A.charCodeAt(0);e<256&&(A=e)}if(void 0!==C&&"string"!=typeof C)throw new TypeError("encoding must be a string");if("string"==typeof C&&!a.isEncoding(C))throw new TypeError("Unknown encoding: "+C)}else"number"==typeof A&&(A&=255);if(g<0||this.length<g||this.length<I)throw new RangeError("Out of range index");if(I<=g)return this;var i;if(g>>>=0,I=void 0===I?this.length:I>>>0,A||(A=0),"number"==typeof A)for(i=g;i<I;++i)this[i]=A;else{var t=a.isBuffer(A)?A:L(new a(A,C).toString()),o=t.length;for(i=0;i<I-g;++i)this[i+g]=t[i%o]}return this};var J=/[^+\/0-9A-Za-z-_]/g;function f(A){return A<16?"0"+A.toString(16):A.toString(16)}function L(A,g){var I;g=g||1/0;for(var C=A.length,e=null,i=[],t=0;t<C;++t){if((I=A.charCodeAt(t))>55295&&I<57344){if(!e){if(I>56319){(g-=3)>-1&&i.push(239,191,189);continue}if(t+1===C){(g-=3)>-1&&i.push(239,191,189);continue}e=I;continue}if(I<56320){(g-=3)>-1&&i.push(239,191,189),e=I;continue}I=65536+(e-55296<<10|I-56320)}else e&&(g-=3)>-1&&i.push(239,191,189);if(e=null,I<128){if((g-=1)<0)break;i.push(I)}else if(I<2048){if((g-=2)<0)break;i.push(I>>6|192,63&I|128)}else if(I<65536){if((g-=3)<0)break;i.push(I>>12|224,I>>6&63|128,63&I|128)}else{if(!(I<1114112))throw new Error("Invalid code point");if((g-=4)<0)break;i.push(I>>18|240,I>>12&63|128,I>>6&63|128,63&I|128)}}return i}function M(A){return C.toByteArray(function(A){if((A=function(A){return A.trim?A.trim():A.replace(/^\s+|\s+$/g,"")}(A).replace(J,"")).length<2)return"";for(;A.length%4!=0;)A+="=";return A}(A))}function U(A,g,I,C){for(var e=0;e<C&&!(e+I>=g.length||e>=A.length);++e)g[e+I]=A[e];return e}}).call(this,I(8))},function(A,g){var I;I=function(){return this}();try{I=I||Function("return this")()||(0,eval)("this")}catch(A){"object"==typeof window&&(I=window)}A.exports=I},function(A,g,I){g.byteLength=function(A){var g=B(A),I=g[0],C=g[1];return 3*(I+C)/4-C},g.toByteArray=function(A){for(var g,I=B(A),C=I[0],t=I[1],o=new i(function(A,g,I){return 3*(g+I)/4-I}(0,C,t)),a=0,s=t>0?C-4:C,l=0;l<s;l+=4)g=e[A.charCodeAt(l)]<<18|e[A.charCodeAt(l+1)]<<12|e[A.charCodeAt(l+2)]<<6|e[A.charCodeAt(l+3)],o[a++]=g>>16&255,o[a++]=g>>8&255,o[a++]=255&g;return 2===t&&(g=e[A.charCodeAt(l)]<<2|e[A.charCodeAt(l+1)]>>4,o[a++]=255&g),1===t&&(g=e[A.charCodeAt(l)]<<10|e[A.charCodeAt(l+1)]<<4|e[A.charCodeAt(l+2)]>>2,o[a++]=g>>8&255,o[a++]=255&g),o},g.fromByteArray=function(A){for(var g,I=A.length,e=I%3,i=[],t=0,o=I-e;t<o;t+=16383)i.push(l(A,t,t+16383>o?o:t+16383));return 1===e?(g=A[I-1],i.push(C[g>>2]+C[g<<4&63]+"==")):2===e&&(g=(A[I-2]<<8)+A[I-1],i.push(C[g>>10]+C[g>>4&63]+C[g<<2&63]+"=")),i.join("")};for(var C=[],e=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",o=0,a=t.length;o<a;++o)C[o]=t[o],e[t.charCodeAt(o)]=o;function B(A){var g=A.length;if(g%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var I=A.indexOf("=");return-1===I&&(I=g),[I,I===g?0:4-I%4]}function s(A){return C[A>>18&63]+C[A>>12&63]+C[A>>6&63]+C[63&A]}function l(A,g,I){for(var C,e=[],i=g;i<I;i+=3)C=(A[i]<<16&16711680)+(A[i+1]<<8&65280)+(255&A[i+2]),e.push(s(C));return e.join("")}e["-".charCodeAt(0)]=62,e["_".charCodeAt(0)]=63},function(A,g){g.read=function(A,g,I,C,e){var i,t,o=8*e-C-1,a=(1<<o)-1,B=a>>1,s=-7,l=I?e-1:0,n=I?-1:1,d=A[g+l];for(l+=n,i=d&(1<<-s)-1,d>>=-s,s+=o;s>0;i=256*i+A[g+l],l+=n,s-=8);for(t=i&(1<<-s)-1,i>>=-s,s+=C;s>0;t=256*t+A[g+l],l+=n,s-=8);if(0===i)i=1-B;else{if(i===a)return t?NaN:1/0*(d?-1:1);t+=Math.pow(2,C),i-=B}return(d?-1:1)*t*Math.pow(2,i-C)},g.write=function(A,g,I,C,e,i){var t,o,a,B=8*i-e-1,s=(1<<B)-1,l=s>>1,n=23===e?Math.pow(2,-24)-Math.pow(2,-77):0,d=C?0:i-1,r=C?1:-1,c=g<0||0===g&&1/g<0?1:0;for(g=Math.abs(g),isNaN(g)||g===1/0?(o=isNaN(g)?1:0,t=s):(t=Math.floor(Math.log(g)/Math.LN2),g*(a=Math.pow(2,-t))<1&&(t--,a*=2),(g+=t+l>=1?n/a:n*Math.pow(2,1-l))*a>=2&&(t++,a/=2),t+l>=s?(o=0,t=s):t+l>=1?(o=(g*a-1)*Math.pow(2,e),t+=l):(o=g*Math.pow(2,l-1)*Math.pow(2,e),t=0));e>=8;A[I+d]=255&o,d+=r,o/=256,e-=8);for(t=t<<e|o,B+=e;B>0;A[I+d]=255&t,d+=r,t/=256,B-=8);A[I+d-r]|=128*c}},function(A,g){var I={}.toString;A.exports=Array.isArray||function(A){return"[object Array]"==I.call(A)}},function(g,I){g.exports=A},function(A,g,I){(function(A){function I(A,g){for(var I=0,C=A.length-1;C>=0;C--){var e=A[C];"."===e?A.splice(C,1):".."===e?(A.splice(C,1),I++):I&&(A.splice(C,1),I--)}if(g)for(;I--;I)A.unshift("..");return A}var C=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,e=function(A){return C.exec(A).slice(1)};function i(A,g){if(A.filter)return A.filter(g);for(var I=[],C=0;C<A.length;C++)g(A[C],C,A)&&I.push(A[C]);return I}g.resolve=function(){for(var g="",C=!1,e=arguments.length-1;e>=-1&&!C;e--){var t=e>=0?arguments[e]:A.cwd();if("string"!=typeof t)throw new TypeError("Arguments to path.resolve must be strings");t&&(g=t+"/"+g,C="/"===t.charAt(0))}return g=I(i(g.split("/"),(function(A){return!!A})),!C).join("/"),(C?"/":"")+g||"."},g.normalize=function(A){var C=g.isAbsolute(A),e="/"===t(A,-1);return(A=I(i(A.split("/"),(function(A){return!!A})),!C).join("/"))||C||(A="."),A&&e&&(A+="/"),(C?"/":"")+A},g.isAbsolute=function(A){return"/"===A.charAt(0)},g.join=function(){var A=Array.prototype.slice.call(arguments,0);return g.normalize(i(A,(function(A,g){if("string"!=typeof A)throw new TypeError("Arguments to path.join must be strings");return A})).join("/"))},g.relative=function(A,I){function C(A){for(var g=0;g<A.length&&""===A[g];g++);for(var I=A.length-1;I>=0&&""===A[I];I--);return g>I?[]:A.slice(g,I-g+1)}A=g.resolve(A).substr(1),I=g.resolve(I).substr(1);for(var e=C(A.split("/")),i=C(I.split("/")),t=Math.min(e.length,i.length),o=t,a=0;a<t;a++)if(e[a]!==i[a]){o=a;break}var B=[];for(a=o;a<e.length;a++)B.push("..");return(B=B.concat(i.slice(o))).join("/")},g.sep="/",g.delimiter=":",g.dirname=function(A){var g=e(A),I=g[0],C=g[1];return I||C?(C&&(C=C.substr(0,C.length-1)),I+C):"."},g.basename=function(A,g){var I=e(A)[2];return g&&I.substr(-1*g.length)===g&&(I=I.substr(0,I.length-g.length)),I},g.extname=function(A){return e(A)[3]};var t="b"==="ab".substr(-1)?function(A,g,I){return A.substr(g,I)}:function(A,g,I){return g<0&&(g=A.length+g),A.substr(g,I)}}).call(this,I(14))},function(A,g){var I,C,e=A.exports={};function i(){throw new Error("setTimeout has not been defined")}function t(){throw new Error("clearTimeout has not been defined")}function o(A){if(I===setTimeout)return setTimeout(A,0);if((I===i||!I)&&setTimeout)return I=setTimeout,setTimeout(A,0);try{return I(A,0)}catch(g){try{return I.call(null,A,0)}catch(g){return I.call(this,A,0)}}}!function(){try{I="function"==typeof setTimeout?setTimeout:i}catch(A){I=i}try{C="function"==typeof clearTimeout?clearTimeout:t}catch(A){C=t}}();var a,B=[],s=!1,l=-1;function n(){s&&a&&(s=!1,a.length?B=a.concat(B):l=-1,B.length&&d())}function d(){if(!s){var A=o(n);s=!0;for(var g=B.length;g;){for(a=B,B=[];++l<g;)a&&a[l].run();l=-1,g=B.length}a=null,s=!1,function(A){if(C===clearTimeout)return clearTimeout(A);if((C===t||!C)&&clearTimeout)return C=clearTimeout,clearTimeout(A);try{C(A)}catch(g){try{return C.call(null,A)}catch(g){return C.call(this,A)}}}(A)}}function r(A,g){this.fun=A,this.array=g}function c(){}e.nextTick=function(A){var g=new Array(arguments.length-1);if(arguments.length>1)for(var I=1;I<arguments.length;I++)g[I-1]=arguments[I];B.push(new r(A,g)),1!==B.length||s||o(d)},r.prototype.run=function(){this.fun.apply(null,this.array)},e.title="browser",e.browser=!0,e.env={},e.argv=[],e.version="",e.versions={},e.on=c,e.addListener=c,e.once=c,e.off=c,e.removeListener=c,e.removeAllListeners=c,e.emit=c,e.prependListener=c,e.prependOnceListener=c,e.listeners=function(A){return[]},e.binding=function(A){throw new Error("process.binding is not supported")},e.cwd=function(){return"/"},e.chdir=function(A){throw new Error("process.chdir is not supported")},e.umask=function(){return 0}}])}(A.fs)}(WorkerScope);const unpackBridge=WorkerScope.unpackBridge;let unpack;var initunpack=function(A){const g=Module,I="omit";var C,e=unpackBridge.Ext,i={open:function(){return e.current.open.apply(e.current,arguments)},close:function(){return e.current.close.apply(e.current,arguments)},read:function(){return e.current.read.apply(e.current,arguments)},write:function(){return e.current.write.apply(e.current,arguments)},tell:function(){return e.current.tell.apply(e.current,arguments)},seek:function(){return e.current.seek.apply(e.current,arguments)},create:function(){return e.current.create.apply(e.current,arguments)}},t={};for(C in Module)Module.hasOwnProperty(C)&&(t[C]=Module[C]);Module.wasmBinary=A,Module.arguments=[],Module.thisProgram="./this.program",Module.quit=function(A,g){throw g},Module.preRun=[],Module.postRun=[];var o=!1,a=!1,B=!1;if(Module.ENVIRONMENT){if("WEB"===Module.ENVIRONMENT)o=!0;else if("WORKER"===Module.ENVIRONMENT)a=!0;else if("NODE"===Module.ENVIRONMENT)B=!0;else if("SHELL"!==Module.ENVIRONMENT)throw new Error("Module['ENVIRONMENT'] value is not valid. must be one of: WEB|WORKER|NODE|SHELL.")}else o="object"==typeof window,a="function"==typeof importScripts,B="object"==typeof process&&"function"==typeof require&&!o&&!a;for(C in(o||a)&&(Module.read=function(A){var g=new XMLHttpRequest;return g.open("GET",A,!1),g.send(null),g.responseText},a&&(Module.readBinary=function(A){var g=new XMLHttpRequest;return g.open("GET",A,!1),g.responseType="arraybuffer",g.send(null),new Uint8Array(g.response)}),Module.readAsync=function(A,g,I){var C=new XMLHttpRequest;C.open("GET",A,!0),C.responseType="arraybuffer",C.onload=function(){200==C.status||0==C.status&&C.response?g(C.response):I()},C.onerror=I,C.send(null)},Module.setWindowTitle=function(A){document.title=A}),Module.print="undefined"!=typeof console?console.log.bind(console):"undefined"!=typeof print?print:null,Module.printErr="undefined"!=typeof printErr?printErr:"undefined"!=typeof console&&console.warn.bind(console)||Module.print,Module.print=Module.print,Module.printErr=Module.printErr,t)t.hasOwnProperty(C)&&(Module[C]=t[C]);t=void 0;function s(A){c(!N);var g=K;return K=K+A+15&-16,g}function l(A){c(L);var g=w[L>>2],I=g+A+15&-16;if((w[L>>2]=I,I>=O)&&!z())return w[L>>2]=g,0;return g}function n(A,g){return g||(g=16),A=Math.ceil(A/g)*g}function d(A){switch(A){case"i1":case"i8":return 1;case"i16":return 2;case"i32":case"float":return 4;case"i64":case"double":return 8;default:if("*"===A[A.length-1])return 4;if("i"===A[0]){var g=parseInt(A.substr(1));return c(g%8==0),g/8}return 0}}new Array(0);var r=0;function c(A,g){A||tI("Assertion failed: "+g)}function h(A,g,I,C){switch("*"===(I=I||"i8").charAt(I.length-1)&&(I="i32"),I){case"i1":case"i8":W[A|0]=g;break;case"i16":S[A>>1]=g;break;case"i32":w[A>>2]=g;break;case"i64":tempI64=[g>>>0,(tempDouble=g,+eA(tempDouble)>=1?tempDouble>0?(0|oA(+tA(tempDouble/4294967296),4294967295))>>>0:~~+iA((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],w[A>>2]=tempI64[0],w[A+4>>2]=tempI64[1];break;case"float":X[A>>2]=g;break;case"double":Y[A>>3]=g;break;default:tI("invalid type for setValue: "+I)}}function G(A,g,I,C){var e,i;"number"==typeof A?(e=!0,i=A):(e=!1,i=A.length);var t,o="string"==typeof g?g:null;if(t=4==I?C:["function"==typeof gI?gI:s,CI,s,l][void 0===I?2:I](Math.max(i,o?1:g.length)),e){var a;for(C=t,c(!(3&t)),a=t+(-4&i);C<a;C+=4)w[C>>2]=0;for(a=t+i;C<a;)W[C++|0]=0;return t}if("i8"===o)return A.subarray||A.slice?p.set(A,t):p.set(new Uint8Array(A),t),t;for(var B,n,r,G=0;G<i;){var m=A[G];0!==(B=o||g[G])?("i64"==B&&(B="i32"),h(t+G,m,B),r!==B&&(n=d(B),r=B),G+=n):G++}return t}function m(A,g){if(0===g||!A)return"";for(var I,C=0,e=0;C|=I=p[A+e|0],(0!=I||g)&&(e++,!g||e!=g););g||(g=e);var i="";if(C<128){for(var t,o=1024;g>0;)t=String.fromCharCode.apply(String,p.subarray(A,A+Math.min(g,o))),i=i?i+t:t,A+=o,g-=o;return i}return u(A)}var b="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0;function Z(A,g){for(var I=g;A[I];)++I;if(I-g>16&&A.subarray&&b)return b.decode(A.subarray(g,I));for(var C,e,i,t,o,a="";;){if(!(C=A[g++]))return a;if(128&C)if(e=63&A[g++],192!=(224&C))if(i=63&A[g++],224==(240&C)?C=(15&C)<<12|e<<6|i:(t=63&A[g++],240==(248&C)?C=(7&C)<<18|e<<12|i<<6|t:(o=63&A[g++],C=248==(252&C)?(3&C)<<24|e<<18|i<<12|t<<6|o:(1&C)<<30|e<<24|i<<18|t<<12|o<<6|63&A[g++])),C<65536)a+=String.fromCharCode(C);else{var B=C-65536;a+=String.fromCharCode(55296|B>>10,56320|1023&B)}else a+=String.fromCharCode((31&C)<<6|e);else a+=String.fromCharCode(C)}}function u(A){return Z(p,A)}function y(A,g,I,C){if(!(C>0))return 0;for(var e=I,i=I+C-1,t=0;t<A.length;++t){var o=A.charCodeAt(t);if(o>=55296&&o<=57343&&(o=65536+((1023&o)<<10)|1023&A.charCodeAt(++t)),o<=127){if(I>=i)break;g[I++]=o}else if(o<=2047){if(I+1>=i)break;g[I++]=192|o>>6,g[I++]=128|63&o}else if(o<=65535){if(I+2>=i)break;g[I++]=224|o>>12,g[I++]=128|o>>6&63,g[I++]=128|63&o}else if(o<=2097151){if(I+3>=i)break;g[I++]=240|o>>18,g[I++]=128|o>>12&63,g[I++]=128|o>>6&63,g[I++]=128|63&o}else if(o<=67108863){if(I+4>=i)break;g[I++]=248|o>>24,g[I++]=128|o>>18&63,g[I++]=128|o>>12&63,g[I++]=128|o>>6&63,g[I++]=128|63&o}else{if(I+5>=i)break;g[I++]=252|o>>30,g[I++]=128|o>>24&63,g[I++]=128|o>>18&63,g[I++]=128|o>>12&63,g[I++]=128|o>>6&63,g[I++]=128|63&o}}return g[I]=0,I-e}function E(A,g,I){return y(A,p,g,I)}function Q(A){for(var g=0,I=0;I<A.length;++I){var C=A.charCodeAt(I);C>=55296&&C<=57343&&(C=65536+((1023&C)<<10)|1023&A.charCodeAt(++I)),C<=127?++g:g+=C<=2047?2:C<=65535?3:C<=2097151?4:C<=67108863?5:6}return g}function V(A){for(var g=0,I="";;){var C=w[A+4*g>>2];if(0==C)return I;if(++g,C>=65536){var e=C-65536;I+=String.fromCharCode(55296|e>>10,56320|1023&e)}else I+=String.fromCharCode(C)}}function R(){var A=function(){var A=new Error;if(!A.stack){try{throw new Error(0)}catch(g){A=g}if(!A.stack)return"(no stack trace available)"}return A.stack.toString()}();return Module.extraStackTrace&&(A+="\n"+Module.extraStackTrace()),function(A){return A.replace(/__Z[\w\d_]+/g,(function(A){return A==A?A:A+" ["+A+"]"}))}(A)}"undefined"!=typeof TextDecoder&&new TextDecoder("utf-16le");var W,p,S,F,w,H,X,Y,K,N,v,J,f,L,M=65536,U=16777216,k=16777216;function D(A,g){return A%g>0&&(A+=g-A%g),A}function x(g){Module.buffer=A=g}function T(){Module.HEAP8=W=new Int8Array(A),Module.HEAP16=S=new Int16Array(A),Module.HEAP32=w=new Int32Array(A),Module.HEAPU8=p=new Uint8Array(A),Module.HEAPU16=F=new Uint16Array(A),Module.HEAPU32=H=new Uint32Array(A),Module.HEAPF32=X=new Float32Array(A),Module.HEAPF64=Y=new Float64Array(A)}function z(){var A=Module.usingWasm?M:U,g=2147483648-A;if(w[L>>2]>g)return!1;var I=O;for(O=Math.max(O,k);O<w[L>>2];)O=O<=536870912?D(2*O,A):Math.min(D((3*O+2147483648)/4,A),g);var C=Module.reallocBuffer(O);return C&&C.byteLength==O?(x(C),T(),!0):(O=I,!1)}K=J=L=0,N=!1,Module.reallocBuffer||(Module.reallocBuffer=function(g){var I;try{if(ArrayBuffer.transfer)I=ArrayBuffer.transfer(A,g);else{var C=W;I=new ArrayBuffer(g),new Int8Array(I).set(C)}}catch(A){return!1}return!!$g(I)&&I});try{Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype,"byteLength").get)(new ArrayBuffer(4))}catch(A){0}var P=Module.TOTAL_STACK||5242880,O=Module.TOTAL_MEMORY||16777216;if(O<P&&Module.printErr("TOTAL_MEMORY should be larger than TOTAL_STACK, was "+O+"! (TOTAL_STACK="+P+")"),Module.buffer?A=Module.buffer:("object"==typeof WebAssembly&&"function"==typeof WebAssembly.Memory?(Module.wasmMemory=new WebAssembly.Memory({initial:O/M}),A=Module.wasmMemory.buffer):A=new ArrayBuffer(O),Module.buffer=A),T(),w[0]=1668509029,S[1]=25459,115!==p[2]||99!==p[3])throw"Runtime error: expected the system to be little-endian!";function j(A){for(;A.length>0;){var g=A.shift();if("function"!=typeof g){var I=g.func;"number"==typeof I?void 0===g.arg?Module.dynCall_v(I):Module.dynCall_vi(I,g.arg):I(void 0===g.arg?null:g.arg)}else g()}}var q=[],_=[],$=[],AA=[],gA=[],IA=!1;function CA(A,g,I){for(var C=0;C<A.length;++C)W[g++|0]=A.charCodeAt(C);I||(W[g|0]=0)}var eA=Math.abs,iA=Math.ceil,tA=Math.floor,oA=Math.min,aA=0,BA=null;function sA(A){aA++,Module.monitorRunDependencies&&Module.monitorRunDependencies(aA)}function lA(A){if(aA--,Module.monitorRunDependencies&&Module.monitorRunDependencies(aA),0==aA&&BA){var g=BA;BA=null,g()}}Module.preloadedImages={},Module.preloadedAudios={};var nA="data:application/octet-stream;base64,";function dA(A){return String.prototype.startsWith?A.startsWith(nA):0===A.indexOf(nA)}!function(){var A="unpack.wast",g="unpack.temp.asm.js";"function"==typeof Module.locateFile&&(dA(A)||(A=Module.locateFile(A)),dA(wasmBinaryFile)||(wasmBinaryFile=Module.locateFile(wasmBinaryFile)),dA(g)||(g=Module.locateFile(g)));const C={asm2wasm:{"f64-rem":function(A,g){return A%g},debugger:function(){}},parent:Module};var e=null;function i(){try{if(Module.wasmBinary)return new Uint8Array(Module.wasmBinary);if(Module.readBinary)return Module.readBinary(wasmBinaryFile);throw"on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)"}catch(A){tI(A)}}function t(A,g,t){if("object"!=typeof WebAssembly)return Module.printErr("no native wasm support detected"),!1;if(!(Module.wasmMemory instanceof WebAssembly.Memory))return Module.printErr("no native wasm Memory in use"),!1;function B(A,g){(e=A.exports).memory&&function(A){var g=Module.buffer;A.byteLength<g.byteLength&&Module.printErr("the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here");var I=new Int8Array(g);new Int8Array(A).set(I),x(A),T()}(e.memory),Module.asm=e,Module.usingWasm=!0,lA()}if(g.memory=Module.wasmMemory,C.global={NaN:NaN,Infinity:1/0},C["global.Math"]=Math,C.env=g,sA(),Module.instantiateWasm)try{return Module.instantiateWasm(C,B)}catch(A){return Module.printErr("Module.instantiateWasm callback failed with error: "+A),!1}function s(A){B(A.instance,A.module)}function l(A){(Module.wasmBinary||!o&&!a||"function"!=typeof fetch?new Promise((function(A,g){A(i())})):fetch(wasmBinaryFile,{credentials:I}).then((function(A){if(!A.ok)throw"failed to load wasm binary file at '"+wasmBinaryFile+"'";return A.arrayBuffer()})).catch((function(){return i()}))).then((function(A){return WebAssembly.instantiate(A,C)})).then(A).catch((function(A){Module.printErr("failed to asynchronously prepare wasm: "+A),tI(A)}))}return Module.wasmBinary||"function"!=typeof WebAssembly.instantiateStreaming||dA(wasmBinaryFile)||"function"!=typeof fetch?l(s):WebAssembly.instantiateStreaming(fetch(wasmBinaryFile,{credentials:I}),C).then(s).catch((function(A){Module.printErr("wasm streaming compile failed: "+A),Module.printErr("falling back to ArrayBuffer instantiation"),l(s)})),{}}Module.asmPreload=Module.asm;var B=Module.reallocBuffer;Module.reallocBuffer=function(A){return"asmjs"===s?B(A):function(A){A=D(A,Module.usingWasm?M:U);var g=Module.buffer.byteLength;if(Module.usingWasm)try{return-1!==Module.wasmMemory.grow((A-g)/65536)?Module.buffer=Module.wasmMemory.buffer:null}catch(A){return null}}(A)};var s="";Module.asm=function(A,g,I){if(!g.table){var C=Module.wasmTableSize;void 0===C&&(C=1024);var e=Module.wasmMaxTableSize;"object"==typeof WebAssembly&&"function"==typeof WebAssembly.Table?g.table=void 0!==e?new WebAssembly.Table({initial:C,maximum:e,element:"anyfunc"}):new WebAssembly.Table({initial:C,element:"anyfunc"}):g.table=new Array(C),Module.wasmTable=g.table}var i;return g.memoryBase||(g.memoryBase=Module.STATIC_BASE),g.tableBase||(g.tableBase=0),(i=t(0,g))||tI("no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods"),i}}(),K=67984,_.push({func:function(){qg()}},{func:function(){jg()}},{func:function(){Og()}},{func:function(){Pg()}});function rA(){return!!rA.uncaught_exception}Module.STATIC_BASE=1024,Module.STATIC_BUMP=66960,K+=16;var cA={last:0,caught:[],infos:{},deAdjust:function(A){if(!A||cA.infos[A])return A;for(var g in cA.infos){var I=+g;if(cA.infos[I].adjusted===A)return I}return A},addRef:function(A){A&&cA.infos[A].refcount++},decRef:function(A){if(A){var g=cA.infos[A];c(g.refcount>0),g.refcount--,0!==g.refcount||g.rethrown||(g.destructor&&Module.dynCall_vi(g.destructor,A),delete cA.infos[A],hA(A))}},clearRef:function(A){A&&(cA.infos[A].refcount=0)}};function hA(A){try{return AI(A)}catch(A){}}function GA(){var A=cA.last;if(!A)return 0|(II(0),0);var g=cA.infos[A],I=g.type;if(!I)return 0|(II(0),A);var C=Array.prototype.slice.call(arguments);Module.___cxa_is_pointer_type(I),GA.buffer||(GA.buffer=gI(4)),w[GA.buffer>>2]=A,A=GA.buffer;for(var e=0;e<C.length;e++)if(C[e]&&Module.___cxa_can_catch(C[e],I,A))return A=w[A>>2],g.adjusted=A,0|(II(C[e]),A);return A=w[A>>2],0|(II(I),A)}var mA={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};function bA(A){return Module.___errno_location&&(w[Module.___errno_location()>>2]=A),A}var ZA={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed",79:"Can   access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported",97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down",113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"},uA={splitPath:function(A){return/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(A).slice(1)},normalizeArray:function(A,g){for(var I=0,C=A.length-1;C>=0;C--){var e=A[C];"."===e?A.splice(C,1):".."===e?(A.splice(C,1),I++):I&&(A.splice(C,1),I--)}if(g)for(;I;I--)A.unshift("..");return A},normalize:function(A){var g="/"===A.charAt(0),I="/"===A.substr(-1);return(A=uA.normalizeArray(A.split("/").filter((function(A){return!!A})),!g).join("/"))||g||(A="."),A&&I&&(A+="/"),(g?"/":"")+A},dirname:function(A){var g=uA.splitPath(A),I=g[0],C=g[1];return I||C?(C&&(C=C.substr(0,C.length-1)),I+C):"."},basename:function(A){if("/"===A)return"/";var g=A.lastIndexOf("/");return-1===g?A:A.substr(g+1)},extname:function(A){return uA.splitPath(A)[3]},join:function(){var A=Array.prototype.slice.call(arguments,0);return uA.normalize(A.join("/"))},join2:function(A,g){return uA.normalize(A+"/"+g)},resolve:function(){for(var A="",g=!1,I=arguments.length-1;I>=-1&&!g;I--){var C=I>=0?arguments[I]:WA.cwd();if("string"!=typeof C)throw new TypeError("Arguments to path.resolve must be strings");if(!C)return"";A=C+"/"+A,g="/"===C.charAt(0)}return(g?"/":"")+(A=uA.normalizeArray(A.split("/").filter((function(A){return!!A})),!g).join("/"))||"."},relative:function(A,g){function I(A){for(var g=0;g<A.length&&""===A[g];g++);for(var I=A.length-1;I>=0&&""===A[I];I--);return g>I?[]:A.slice(g,I-g+1)}A=uA.resolve(A).substr(1),g=uA.resolve(g).substr(1);for(var C=I(A.split("/")),e=I(g.split("/")),i=Math.min(C.length,e.length),t=i,o=0;o<i;o++)if(C[o]!==e[o]){t=o;break}var a=[];for(o=t;o<C.length;o++)a.push("..");return(a=a.concat(e.slice(t))).join("/")}},yA={ttys:[],init:function(){},shutdown:function(){},register:function(A,g){yA.ttys[A]={input:[],output:[],ops:g},WA.registerDevice(A,yA.stream_ops)},stream_ops:{open:function(A){var g=yA.ttys[A.node.rdev];if(!g)throw new WA.ErrnoError(mA.ENODEV);A.tty=g,A.seekable=!1},close:function(A){A.tty.ops.flush(A.tty)},flush:function(A){A.tty.ops.flush(A.tty)},read:function(A,g,I,C,e){if(!A.tty||!A.tty.ops.get_char)throw new WA.ErrnoError(mA.ENXIO);for(var i=0,t=0;t<C;t++){var o;try{o=A.tty.ops.get_char(A.tty)}catch(A){throw new WA.ErrnoError(mA.EIO)}if(void 0===o&&0===i)throw new WA.ErrnoError(mA.EAGAIN);if(null==o)break;i++,g[I+t]=o}return i&&(A.node.timestamp=Date.now()),i},write:function(A,g,I,C,e){if(!A.tty||!A.tty.ops.put_char)throw new WA.ErrnoError(mA.ENXIO);for(var i=0;i<C;i++)try{A.tty.ops.put_char(A.tty,g[I+i])}catch(A){throw new WA.ErrnoError(mA.EIO)}return C&&(A.node.timestamp=Date.now()),i}},default_tty_ops:{get_char:function(A){if(!A.input.length){var g=null;if(B){var I=new Buffer(256),C=0,e="win32"!=process.platform,i=process.stdin.fd;if(e){var t=!1;try{i=fs.openSync("/dev/stdin","r"),t=!0}catch(A){}}try{C=fs.readSync(i,I,0,256,null)}catch(A){if(-1==A.toString().indexOf("EOF"))throw A;C=0}t&&fs.closeSync(i),g=C>0?I.slice(0,C).toString("utf-8"):null}else"undefined"!=typeof window&&"function"==typeof window.prompt?null!==(g=window.prompt("Input: "))&&(g+="\n"):"function"==typeof readline&&null!==(g=readline())&&(g+="\n");if(!g)return null;A.input=Tg(g,!0)}return A.input.shift()},put_char:function(A,g){null===g||10===g?(Module.print(Z(A.output,0)),A.output=[]):0!=g&&A.output.push(g)},flush:function(A){A.output&&A.output.length>0&&(Module.print(Z(A.output,0)),A.output=[])}},default_tty1_ops:{put_char:function(A,g){null===g||10===g?(Module.printErr(Z(A.output,0)),A.output=[]):0!=g&&A.output.push(g)},flush:function(A){A.output&&A.output.length>0&&(Module.printErr(Z(A.output,0)),A.output=[])}}},EA={ops_table:null,mount:function(A){return EA.createNode(null,"/",16895,0)},createNode:function(A,g,I,C){if(WA.isBlkdev(I)||WA.isFIFO(I))throw new WA.ErrnoError(mA.EPERM);EA.ops_table||(EA.ops_table={dir:{node:{getattr:EA.node_ops.getattr,setattr:EA.node_ops.setattr,lookup:EA.node_ops.lookup,mknod:EA.node_ops.mknod,rename:EA.node_ops.rename,unlink:EA.node_ops.unlink,rmdir:EA.node_ops.rmdir,readdir:EA.node_ops.readdir,symlink:EA.node_ops.symlink},stream:{llseek:EA.stream_ops.llseek}},file:{node:{getattr:EA.node_ops.getattr,setattr:EA.node_ops.setattr},stream:{llseek:EA.stream_ops.llseek,read:EA.stream_ops.read,write:EA.stream_ops.write,allocate:EA.stream_ops.allocate,mmap:EA.stream_ops.mmap,msync:EA.stream_ops.msync}},link:{node:{getattr:EA.node_ops.getattr,setattr:EA.node_ops.setattr,readlink:EA.node_ops.readlink},stream:{}},chrdev:{node:{getattr:EA.node_ops.getattr,setattr:EA.node_ops.setattr},stream:WA.chrdev_stream_ops}});var e=WA.createNode(A,g,I,C);return WA.isDir(e.mode)?(e.node_ops=EA.ops_table.dir.node,e.stream_ops=EA.ops_table.dir.stream,e.contents={}):WA.isFile(e.mode)?(e.node_ops=EA.ops_table.file.node,e.stream_ops=EA.ops_table.file.stream,e.usedBytes=0,e.contents=null):WA.isLink(e.mode)?(e.node_ops=EA.ops_table.link.node,e.stream_ops=EA.ops_table.link.stream):WA.isChrdev(e.mode)&&(e.node_ops=EA.ops_table.chrdev.node,e.stream_ops=EA.ops_table.chrdev.stream),e.timestamp=Date.now(),A&&(A.contents[g]=e),e},getFileDataAsRegularArray:function(A){if(A.contents&&A.contents.subarray){for(var g=[],I=0;I<A.usedBytes;++I)g.push(A.contents[I]);return g}return A.contents},getFileDataAsTypedArray:function(A){return A.contents?A.contents.subarray?A.contents.subarray(0,A.usedBytes):new Uint8Array(A.contents):new Uint8Array},expandFileStorage:function(A,g){if(A.contents&&A.contents.subarray&&g>A.contents.length&&(A.contents=EA.getFileDataAsRegularArray(A),A.usedBytes=A.contents.length),!A.contents||A.contents.subarray){var I=A.contents?A.contents.length:0;if(I>=g)return;g=Math.max(g,I*(I<1048576?2:1.125)|0),0!=I&&(g=Math.max(g,256));var C=A.contents;return A.contents=new Uint8Array(g),void(A.usedBytes>0&&A.contents.set(C.subarray(0,A.usedBytes),0))}for(!A.contents&&g>0&&(A.contents=[]);A.contents.length<g;)A.contents.push(0)},resizeFileStorage:function(A,g){if(A.usedBytes!=g){if(0==g)return A.contents=null,void(A.usedBytes=0);if(!A.contents||A.contents.subarray){var I=A.contents;return A.contents=new Uint8Array(new ArrayBuffer(g)),I&&A.contents.set(I.subarray(0,Math.min(g,A.usedBytes))),void(A.usedBytes=g)}if(A.contents||(A.contents=[]),A.contents.length>g)A.contents.length=g;else for(;A.contents.length<g;)A.contents.push(0);A.usedBytes=g}},node_ops:{getattr:function(A){var g={};return g.dev=WA.isChrdev(A.mode)?A.id:1,g.ino=A.id,g.mode=A.mode,g.nlink=1,g.uid=0,g.gid=0,g.rdev=A.rdev,WA.isDir(A.mode)?g.size=4096:WA.isFile(A.mode)?g.size=A.usedBytes:WA.isLink(A.mode)?g.size=A.link.length:g.size=0,g.atime=new Date(A.timestamp),g.mtime=new Date(A.timestamp),g.ctime=new Date(A.timestamp),g.blksize=4096,g.blocks=Math.ceil(g.size/g.blksize),g},setattr:function(A,g){void 0!==g.mode&&(A.mode=g.mode),void 0!==g.timestamp&&(A.timestamp=g.timestamp),void 0!==g.size&&EA.resizeFileStorage(A,g.size)},lookup:function(A,g){throw WA.genericErrors[mA.ENOENT]},mknod:function(A,g,I,C){return EA.createNode(A,g,I,C)},rename:function(A,g,I){if(WA.isDir(A.mode)){var C;try{C=WA.lookupNode(g,I)}catch(A){}if(C)for(var e in C.contents)throw new WA.ErrnoError(mA.ENOTEMPTY)}delete A.parent.contents[A.name],A.name=I,g.contents[I]=A,A.parent=g},unlink:function(A,g){delete A.contents[g]},rmdir:function(A,g){var I=WA.lookupNode(A,g);for(var C in I.contents)throw new WA.ErrnoError(mA.ENOTEMPTY);delete A.contents[g]},readdir:function(A){var g=[".",".."];for(var I in A.contents)A.contents.hasOwnProperty(I)&&g.push(I);return g},symlink:function(A,g,I){var C=EA.createNode(A,g,41471,0);return C.link=I,C},readlink:function(A){if(!WA.isLink(A.mode))throw new WA.ErrnoError(mA.EINVAL);return A.link}},stream_ops:{read:function(A,g,I,C,e){var i=A.node.contents;if(e>=A.node.usedBytes)return 0;var t=Math.min(A.node.usedBytes-e,C);if(c(t>=0),t>8&&i.subarray)g.set(i.subarray(e,e+t),I);else for(var o=0;o<t;o++)g[I+o]=i[e+o];return t},write:function(A,g,I,C,e,i){if(!C)return 0;var t=A.node;if(t.timestamp=Date.now(),g.subarray&&(!t.contents||t.contents.subarray)){if(i)return t.contents=g.subarray(I,I+C),t.usedBytes=C,C;if(0===t.usedBytes&&0===e)return t.contents=new Uint8Array(g.subarray(I,I+C)),t.usedBytes=C,C;if(e+C<=t.usedBytes)return t.contents.set(g.subarray(I,I+C),e),C}if(EA.expandFileStorage(t,e+C),t.contents.subarray&&g.subarray)t.contents.set(g.subarray(I,I+C),e);else for(var o=0;o<C;o++)t.contents[e+o]=g[I+o];return t.usedBytes=Math.max(t.usedBytes,e+C),C},llseek:function(A,g,I){var C=g;if(1===I?C+=A.position:2===I&&WA.isFile(A.node.mode)&&(C+=A.node.usedBytes),C<0)throw new WA.ErrnoError(mA.EINVAL);return C},allocate:function(A,g,I){EA.expandFileStorage(A.node,g+I),A.node.usedBytes=Math.max(A.node.usedBytes,g+I)},mmap:function(A,g,I,C,e,i,t){if(!WA.isFile(A.node.mode))throw new WA.ErrnoError(mA.ENODEV);var o,a,B=A.node.contents;if(2&t||B.buffer!==g&&B.buffer!==g.buffer){if((e>0||e+C<A.node.usedBytes)&&(B=B.subarray?B.subarray(e,e+C):Array.prototype.slice.call(B,e,e+C)),a=!0,!(o=gI(C)))throw new WA.ErrnoError(mA.ENOMEM);g.set(B,o)}else a=!1,o=B.byteOffset;return{ptr:o,allocated:a}},msync:function(A,g,I,C,e){if(!WA.isFile(A.node.mode))throw new WA.ErrnoError(mA.ENODEV);return 2&e||EA.stream_ops.write(A,g,0,C,I,!1),0}}},QA={dbs:{},indexedDB:function(){if("undefined"!=typeof indexedDB)return indexedDB;var A=null;return"object"==typeof window&&(A=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB),c(A,"IDBFS used, but indexedDB not supported"),A},DB_VERSION:21,DB_STORE_NAME:"FILE_DATA",mount:function(A){return EA.mount.apply(null,arguments)},syncfs:function(A,g,I){QA.getLocalSet(A,(function(C,e){if(C)return I(C);QA.getRemoteSet(A,(function(A,C){if(A)return I(A);var i=g?C:e,t=g?e:C;QA.reconcile(i,t,I)}))}))},getDB:function(A,g){var I,C=QA.dbs[A];if(C)return g(null,C);try{I=QA.indexedDB().open(A,QA.DB_VERSION)}catch(A){return g(A)}if(!I)return g("Unable to connect to IndexedDB");I.onupgradeneeded=function(A){var g,I=A.target.result,C=A.target.transaction;(g=I.objectStoreNames.contains(QA.DB_STORE_NAME)?C.objectStore(QA.DB_STORE_NAME):I.createObjectStore(QA.DB_STORE_NAME)).indexNames.contains("timestamp")||g.createIndex("timestamp","timestamp",{unique:!1})},I.onsuccess=function(){C=I.result,QA.dbs[A]=C,g(null,C)},I.onerror=function(A){g(this.error),A.preventDefault()}},getLocalSet:function(A,g){var I={};function C(A){return"."!==A&&".."!==A}function e(A){return function(g){return uA.join2(A,g)}}for(var i=WA.readdir(A.mountpoint).filter(C).map(e(A.mountpoint));i.length;){var t,o=i.pop();try{t=WA.stat(o)}catch(A){return g(A)}WA.isDir(t.mode)&&i.push.apply(i,WA.readdir(o).filter(C).map(e(o))),I[o]={timestamp:t.mtime}}return g(null,{type:"local",entries:I})},getRemoteSet:function(A,g){var I={};QA.getDB(A.mountpoint,(function(A,C){if(A)return g(A);try{var e=C.transaction([QA.DB_STORE_NAME],"readonly");e.onerror=function(A){g(this.error),A.preventDefault()},e.objectStore(QA.DB_STORE_NAME).index("timestamp").openKeyCursor().onsuccess=function(A){var e=A.target.result;if(!e)return g(null,{type:"remote",db:C,entries:I});I[e.primaryKey]={timestamp:e.key},e.continue()}}catch(A){return g(A)}}))},loadLocalEntry:function(A,g){var I,C;try{C=WA.lookupPath(A).node,I=WA.stat(A)}catch(A){return g(A)}return WA.isDir(I.mode)?g(null,{timestamp:I.mtime,mode:I.mode}):WA.isFile(I.mode)?(C.contents=EA.getFileDataAsTypedArray(C),g(null,{timestamp:I.mtime,mode:I.mode,contents:C.contents})):g(new Error("node type not supported"))},storeLocalEntry:function(A,g,I){try{if(WA.isDir(g.mode))WA.mkdir(A,g.mode);else{if(!WA.isFile(g.mode))return I(new Error("node type not supported"));WA.writeFile(A,g.contents,{canOwn:!0})}WA.chmod(A,g.mode),WA.utime(A,g.timestamp,g.timestamp)}catch(A){return I(A)}I(null)},removeLocalEntry:function(A,g){try{WA.lookupPath(A);var I=WA.stat(A);WA.isDir(I.mode)?WA.rmdir(A):WA.isFile(I.mode)&&WA.unlink(A)}catch(A){return g(A)}g(null)},loadRemoteEntry:function(A,g,I){var C=A.get(g);C.onsuccess=function(A){I(null,A.target.result)},C.onerror=function(A){I(this.error),A.preventDefault()}},storeRemoteEntry:function(A,g,I,C){var e=A.put(I,g);e.onsuccess=function(){C(null)},e.onerror=function(A){C(this.error),A.preventDefault()}},removeRemoteEntry:function(A,g,I){var C=A.delete(g);C.onsuccess=function(){I(null)},C.onerror=function(A){I(this.error),A.preventDefault()}},reconcile:function(A,g,I){var C=0,e=[];Object.keys(A.entries).forEach((function(I){var i=A.entries[I],t=g.entries[I];(!t||i.timestamp>t.timestamp)&&(e.push(I),C++)}));var i=[];if(Object.keys(g.entries).forEach((function(I){g.entries[I],A.entries[I]||(i.push(I),C++)})),!C)return I(null);var t=0,o=("remote"===A.type?A.db:g.db).transaction([QA.DB_STORE_NAME],"readwrite"),a=o.objectStore(QA.DB_STORE_NAME);function B(A){return A?B.errored?void 0:(B.errored=!0,I(A)):++t>=C?I(null):void 0}o.onerror=function(A){B(this.error),A.preventDefault()},e.sort().forEach((function(A){"local"===g.type?QA.loadRemoteEntry(a,A,(function(g,I){if(g)return B(g);QA.storeLocalEntry(A,I,B)})):QA.loadLocalEntry(A,(function(g,I){if(g)return B(g);QA.storeRemoteEntry(a,A,I,B)}))})),i.sort().reverse().forEach((function(A){"local"===g.type?QA.removeLocalEntry(A,B):QA.removeRemoteEntry(a,A,B)}))}},VA={isWindows:!1,staticInit:function(){VA.isWindows=!!process.platform.match(/^win/);var A=process.binding("constants");A.fs&&(A=A.fs),VA.flagsForNodeMap={1024:A.O_APPEND,64:A.O_CREAT,128:A.O_EXCL,0:A.O_RDONLY,2:A.O_RDWR,4096:A.O_SYNC,512:A.O_TRUNC,1:A.O_WRONLY}},bufferFrom:function(A){return Buffer.alloc?Buffer.from(A):new Buffer(A)},mount:function(A){return c(B),VA.createNode(null,"/",VA.getMode(A.opts.root),0)},createNode:function(A,g,I,C){if(!WA.isDir(I)&&!WA.isFile(I)&&!WA.isLink(I))throw new WA.ErrnoError(mA.EINVAL);var e=WA.createNode(A,g,I);return e.node_ops=VA.node_ops,e.stream_ops=VA.stream_ops,e},getMode:function(A){var g;try{g=fs.lstatSync(A),VA.isWindows&&(g.mode=g.mode|(292&g.mode)>>2)}catch(A){if(!A.code)throw A;throw new WA.ErrnoError(mA[A.code])}return g.mode},realPath:function(A){for(var g=[];A.parent!==A;)g.push(A.name),A=A.parent;return g.push(A.mount.opts.root),g.reverse(),uA.join.apply(null,g)},flagsForNode:function(A){A&=-2097153,A&=-2049,A&=-32769,A&=-524289;var g=0;for(var I in VA.flagsForNodeMap)A&I&&(g|=VA.flagsForNodeMap[I],A^=I);if(A)throw new WA.ErrnoError(mA.EINVAL);return g},node_ops:{getattr:function(A){var g,I=VA.realPath(A);try{g=fs.lstatSync(I)}catch(A){if(!A.code)throw A;throw new WA.ErrnoError(mA[A.code])}return VA.isWindows&&!g.blksize&&(g.blksize=4096),VA.isWindows&&!g.blocks&&(g.blocks=(g.size+g.blksize-1)/g.blksize|0),{dev:g.dev,ino:g.ino,mode:g.mode,nlink:g.nlink,uid:g.uid,gid:g.gid,rdev:g.rdev,size:g.size,atime:g.atime,mtime:g.mtime,ctime:g.ctime,blksize:g.blksize,blocks:g.blocks}},setattr:function(A,g){var I=VA.realPath(A);try{if(void 0!==g.mode&&(fs.chmodSync(I,g.mode),A.mode=g.mode),void 0!==g.timestamp){var C=new Date(g.timestamp);fs.utimesSync(I,C,C)}void 0!==g.size&&fs.truncateSync(I,g.size)}catch(A){if(!A.code)throw A;throw new WA.ErrnoError(mA[A.code])}},lookup:function(A,g){var I=uA.join2(VA.realPath(A),g),C=VA.getMode(I);return VA.createNode(A,g,C)},mknod:function(A,g,I,C){var e=VA.createNode(A,g,I,C),i=VA.realPath(e);try{WA.isDir(e.mode)?fs.mkdirSync(i,e.mode):fs.writeFileSync(i,"",{mode:e.mode})}catch(A){if(!A.code)throw A;throw new WA.ErrnoError(mA[A.code])}return e},rename:function(A,g,I){var C=VA.realPath(A),e=uA.join2(VA.realPath(g),I);try{fs.renameSync(C,e)}catch(A){if(!A.code)throw A;throw new WA.ErrnoError(mA[A.code])}},unlink:function(A,g){var I=uA.join2(VA.realPath(A),g);try{fs.unlinkSync(I)}catch(A){if(!A.code)throw A;throw new WA.ErrnoError(mA[A.code])}},rmdir:function(A,g){var I=uA.join2(VA.realPath(A),g);try{fs.rmdirSync(I)}catch(A){if(!A.code)throw A;throw new WA.ErrnoError(mA[A.code])}},readdir:function(A){var g=VA.realPath(A);try{return fs.readdirSync(g)}catch(A){if(!A.code)throw A;throw new WA.ErrnoError(mA[A.code])}},symlink:function(A,g,I){var C=uA.join2(VA.realPath(A),g);try{fs.symlinkSync(I,C)}catch(A){if(!A.code)throw A;throw new WA.ErrnoError(mA[A.code])}},readlink:function(A){var g=VA.realPath(A);try{return g=fs.readlinkSync(g),g=NODEJS_PATH.relative(NODEJS_PATH.resolve(A.mount.opts.root),g)}catch(A){if(!A.code)throw A;throw new WA.ErrnoError(mA[A.code])}}},stream_ops:{open:function(A){var g=VA.realPath(A.node);try{WA.isFile(A.node.mode)&&(A.nfd=fs.openSync(g,VA.flagsForNode(A.flags)))}catch(A){if(!A.code)throw A;throw new WA.ErrnoError(mA[A.code])}},close:function(A){try{WA.isFile(A.node.mode)&&A.nfd&&fs.closeSync(A.nfd)}catch(A){if(!A.code)throw A;throw new WA.ErrnoError(mA[A.code])}},read:function(A,g,I,C,e){if(0===C)return 0;try{return fs.readSync(A.nfd,VA.bufferFrom(g.buffer),I,C,e)}catch(A){throw new WA.ErrnoError(mA[A.code])}},write:function(A,g,I,C,e){try{return fs.writeSync(A.nfd,VA.bufferFrom(g.buffer),I,C,e)}catch(A){throw new WA.ErrnoError(mA[A.code])}},llseek:function(A,g,I){var C=g;if(1===I)C+=A.position;else if(2===I&&WA.isFile(A.node.mode))try{C+=fs.fstatSync(A.nfd).size}catch(A){throw new WA.ErrnoError(mA[A.code])}if(C<0)throw new WA.ErrnoError(mA.EINVAL);return C}}},RA={DIR_MODE:16895,FILE_MODE:33279,reader:null,mount:function(A){c(a),RA.reader||(RA.reader=new FileReaderSync);var g=RA.createNode(null,"/",RA.DIR_MODE,0),I={};function C(A){for(var C=A.split("/"),e=g,i=0;i<C.length-1;i++){var t=C.slice(0,i+1).join("/");I[t]||(I[t]=RA.createNode(e,C[i],RA.DIR_MODE,0)),e=I[t]}return e}function e(A){var g=A.split("/");return g[g.length-1]}return Array.prototype.forEach.call(A.opts.files||[],(function(A){RA.createNode(C(A.name),e(A.name),RA.FILE_MODE,0,A,A.lastModifiedDate)})),(A.opts.blobs||[]).forEach((function(A){RA.createNode(C(A.name),e(A.name),RA.FILE_MODE,0,A.data)})),(A.opts.packages||[]).forEach((function(A){A.metadata.files.forEach((function(g){var I=g.filename.substr(1);RA.createNode(C(I),e(I),RA.FILE_MODE,0,A.blob.slice(g.start,g.end))}))})),g},createNode:function(A,g,I,C,e,i){var t=WA.createNode(A,g,I);return t.mode=I,t.node_ops=RA.node_ops,t.stream_ops=RA.stream_ops,t.timestamp=(i||new Date).getTime(),c(RA.FILE_MODE!==RA.DIR_MODE),I===RA.FILE_MODE?(t.size=e.size,t.contents=e):(t.size=4096,t.contents={}),A&&(A.contents[g]=t),t},node_ops:{getattr:function(A){return{dev:1,ino:void 0,mode:A.mode,nlink:1,uid:0,gid:0,rdev:void 0,size:A.size,atime:new Date(A.timestamp),mtime:new Date(A.timestamp),ctime:new Date(A.timestamp),blksize:4096,blocks:Math.ceil(A.size/4096)}},setattr:function(A,g){void 0!==g.mode&&(A.mode=g.mode),void 0!==g.timestamp&&(A.timestamp=g.timestamp)},lookup:function(A,g){throw new WA.ErrnoError(mA.ENOENT)},mknod:function(A,g,I,C){throw new WA.ErrnoError(mA.EPERM)},rename:function(A,g,I){throw new WA.ErrnoError(mA.EPERM)},unlink:function(A,g){throw new WA.ErrnoError(mA.EPERM)},rmdir:function(A,g){throw new WA.ErrnoError(mA.EPERM)},readdir:function(A){var g=[".",".."];for(var I in A.contents)A.contents.hasOwnProperty(I)&&g.push(I);return g},symlink:function(A,g,I){throw new WA.ErrnoError(mA.EPERM)},readlink:function(A){throw new WA.ErrnoError(mA.EPERM)}},stream_ops:{read:function(A,g,I,C,e){if(e>=A.node.size)return 0;var i=A.node.contents.slice(e,e+C),t=RA.reader.readAsArrayBuffer(i);return g.set(new Uint8Array(t),I),i.size},write:function(A,g,I,C,e){throw new WA.ErrnoError(mA.EIO)},llseek:function(A,g,I){var C=g;if(1===I?C+=A.position:2===I&&WA.isFile(A.node.mode)&&(C+=A.node.size),C<0)throw new WA.ErrnoError(mA.EINVAL);return C}}};K+=16,K+=16;var WA={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:!1,ignorePermissions:!0,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,handleFSError:function(A){if(!(A instanceof WA.ErrnoError))throw A+" : "+R();return bA(A.errno)},lookupPath:function(A,g){if(g=g||{},!(A=uA.resolve(WA.cwd(),A)))return{path:"",node:null};var I={follow_mount:!0,recurse_count:0};for(var C in I)void 0===g[C]&&(g[C]=I[C]);if(g.recurse_count>8)throw new WA.ErrnoError(mA.ELOOP);for(var e=uA.normalizeArray(A.split("/").filter((function(A){return!!A})),!1),i=WA.root,t="/",o=0;o<e.length;o++){var a=o===e.length-1;if(a&&g.parent)break;if(i=WA.lookupNode(i,e[o]),t=uA.join2(t,e[o]),WA.isMountpoint(i)&&(!a||a&&g.follow_mount)&&(i=i.mounted.root),!a||g.follow)for(var B=0;WA.isLink(i.mode);){var s=WA.readlink(t);if(t=uA.resolve(uA.dirname(t),s),i=WA.lookupPath(t,{recurse_count:g.recurse_count}).node,B++>40)throw new WA.ErrnoError(mA.ELOOP)}}return{path:t,node:i}},getPath:function(A){for(var g;;){if(WA.isRoot(A)){var I=A.mount.mountpoint;return g?"/"!==I[I.length-1]?I+"/"+g:I+g:I}g=g?A.name+"/"+g:A.name,A=A.parent}},hashName:function(A,g){for(var I=0,C=0;C<g.length;C++)I=(I<<5)-I+g.charCodeAt(C)|0;return(A+I>>>0)%WA.nameTable.length},hashAddNode:function(A){var g=WA.hashName(A.parent.id,A.name);A.name_next=WA.nameTable[g],WA.nameTable[g]=A},hashRemoveNode:function(A){var g=WA.hashName(A.parent.id,A.name);if(WA.nameTable[g]===A)WA.nameTable[g]=A.name_next;else for(var I=WA.nameTable[g];I;){if(I.name_next===A){I.name_next=A.name_next;break}I=I.name_next}},lookupNode:function(A,g){var I=WA.mayLookup(A);if(I)throw new WA.ErrnoError(I,A);for(var C=WA.hashName(A.id,g),e=WA.nameTable[C];e;e=e.name_next){var i=e.name;if(e.parent.id===A.id&&i===g)return e}return WA.lookup(A,g)},createNode:function(A,g,I,C){if(!WA.FSNode){WA.FSNode=function(A,g,I,C){A||(A=this),this.parent=A,this.mount=A.mount,this.mounted=null,this.id=WA.nextInode++,this.name=g,this.mode=I,this.node_ops={},this.stream_ops={},this.rdev=C},WA.FSNode.prototype={};var e=365,i=146;Object.defineProperties(WA.FSNode.prototype,{read:{get:function(){return(this.mode&e)===e},set:function(A){A?this.mode|=e:this.mode&=-366}},write:{get:function(){return(this.mode&i)===i},set:function(A){A?this.mode|=i:this.mode&=-147}},isFolder:{get:function(){return WA.isDir(this.mode)}},isDevice:{get:function(){return WA.isChrdev(this.mode)}}})}var t=new WA.FSNode(A,g,I,C);return WA.hashAddNode(t),t},destroyNode:function(A){WA.hashRemoveNode(A)},isRoot:function(A){return A===A.parent},isMountpoint:function(A){return!!A.mounted},isFile:function(A){return 32768==(61440&A)},isDir:function(A){return 16384==(61440&A)},isLink:function(A){return 40960==(61440&A)},isChrdev:function(A){return 8192==(61440&A)},isBlkdev:function(A){return 24576==(61440&A)},isFIFO:function(A){return 4096==(61440&A)},isSocket:function(A){return!(49152&~A)},flagModes:{r:0,rs:1052672,"r+":2,w:577,wx:705,xw:705,"w+":578,"wx+":706,"xw+":706,a:1089,ax:1217,xa:1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function(A){var g=WA.flagModes[A];if(void 0===g)throw new Error("Unknown file open mode: "+A);return g},flagsToPermissionString:function(A){var g=["r","w","rw"][3&A];return 512&A&&(g+="w"),g},nodePermissions:function(A,g){return WA.ignorePermissions||(-1===g.indexOf("r")||292&A.mode)&&(-1===g.indexOf("w")||146&A.mode)&&(-1===g.indexOf("x")||73&A.mode)?0:mA.EACCES},mayLookup:function(A){var g=WA.nodePermissions(A,"x");return g||(A.node_ops.lookup?0:mA.EACCES)},mayCreate:function(A,g){try{WA.lookupNode(A,g);return mA.EEXIST}catch(A){}return WA.nodePermissions(A,"wx")},mayDelete:function(A,g,I){var C;try{C=WA.lookupNode(A,g)}catch(A){return A.errno}var e=WA.nodePermissions(A,"wx");if(e)return e;if(I){if(!WA.isDir(C.mode))return mA.ENOTDIR;if(WA.isRoot(C)||WA.getPath(C)===WA.cwd())return mA.EBUSY}else if(WA.isDir(C.mode))return mA.EISDIR;return 0},mayOpen:function(A,g){return A?WA.isLink(A.mode)?mA.ELOOP:WA.isDir(A.mode)&&("r"!==WA.flagsToPermissionString(g)||512&g)?mA.EISDIR:WA.nodePermissions(A,WA.flagsToPermissionString(g)):mA.ENOENT},MAX_OPEN_FDS:4096,nextfd:function(A,g){A=A||0,g=g||WA.MAX_OPEN_FDS;for(var I=A;I<=g;I++)if(!WA.streams[I])return I;throw new WA.ErrnoError(mA.EMFILE)},getStream:function(A){return WA.streams[A]},createStream:function(A,g,I){WA.FSStream||(WA.FSStream=function(){},WA.FSStream.prototype={},Object.defineProperties(WA.FSStream.prototype,{object:{get:function(){return this.node},set:function(A){this.node=A}},isRead:{get:function(){return 1!=(2097155&this.flags)}},isWrite:{get:function(){return!!(2097155&this.flags)}},isAppend:{get:function(){return 1024&this.flags}}}));var C=new WA.FSStream;for(var e in A)C[e]=A[e];A=C;var i=WA.nextfd(g,I);return A.fd=i,WA.streams[i]=A,A},closeStream:function(A){WA.streams[A]=null},chrdev_stream_ops:{open:function(A){var g=WA.getDevice(A.node.rdev);A.stream_ops=g.stream_ops,A.stream_ops.open&&A.stream_ops.open(A)},llseek:function(){throw new WA.ErrnoError(mA.ESPIPE)}},major:function(A){return A>>8},minor:function(A){return 255&A},makedev:function(A,g){return A<<8|g},registerDevice:function(A,g){WA.devices[A]={stream_ops:g}},getDevice:function(A){return WA.devices[A]},getMounts:function(A){for(var g=[],I=[A];I.length;){var C=I.pop();g.push(C),I.push.apply(I,C.mounts)}return g},syncfs:function(A,g){"function"==typeof A&&(g=A,A=!1),WA.syncFSRequests++,WA.syncFSRequests>1&&console.log("warning: "+WA.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work");var I=WA.getMounts(WA.root.mount),C=0;function e(A){return c(WA.syncFSRequests>0),WA.syncFSRequests--,g(A)}function i(A){if(A)return i.errored?void 0:(i.errored=!0,e(A));++C>=I.length&&e(null)}I.forEach((function(g){if(!g.type.syncfs)return i(null);g.type.syncfs(g,A,i)}))},mount:function(A,g,I){var C,e="/"===I,i=!I;if(e&&WA.root)throw new WA.ErrnoError(mA.EBUSY);if(!e&&!i){var t=WA.lookupPath(I,{follow_mount:!1});if(I=t.path,C=t.node,WA.isMountpoint(C))throw new WA.ErrnoError(mA.EBUSY);if(!WA.isDir(C.mode))throw new WA.ErrnoError(mA.ENOTDIR)}var o={type:A,opts:g,mountpoint:I,mounts:[]},a=A.mount(o);return a.mount=o,o.root=a,e?WA.root=a:C&&(C.mounted=o,C.mount&&C.mount.mounts.push(o)),a},unmount:function(A){var g=WA.lookupPath(A,{follow_mount:!1});if(!WA.isMountpoint(g.node))throw new WA.ErrnoError(mA.EINVAL);var I=g.node,C=I.mounted,e=WA.getMounts(C);Object.keys(WA.nameTable).forEach((function(A){for(var g=WA.nameTable[A];g;){var I=g.name_next;-1!==e.indexOf(g.mount)&&WA.destroyNode(g),g=I}})),I.mounted=null;var i=I.mount.mounts.indexOf(C);c(-1!==i),I.mount.mounts.splice(i,1)},lookup:function(A,g){return A.node_ops.lookup(A,g)},mknod:function(A,g,I){var C=WA.lookupPath(A,{parent:!0}).node,e=uA.basename(A);if(!e||"."===e||".."===e)throw new WA.ErrnoError(mA.EINVAL);var i=WA.mayCreate(C,e);if(i)throw new WA.ErrnoError(i);if(!C.node_ops.mknod)throw new WA.ErrnoError(mA.EPERM);return C.node_ops.mknod(C,e,g,I)},create:function(A,g){return g=void 0!==g?g:438,g&=4095,g|=32768,WA.mknod(A,g,0)},mkdir:function(A,g){return g=void 0!==g?g:511,g&=1023,g|=16384,WA.mknod(A,g,0)},mkdirTree:function(A,g){for(var I=A.split("/"),C="",e=0;e<I.length;++e)if(I[e]){C+="/"+I[e];try{WA.mkdir(C,g)}catch(A){if(A.errno!=mA.EEXIST)throw A}}},mkdev:function(A,g,I){return void 0===I&&(I=g,g=438),g|=8192,WA.mknod(A,g,I)},symlink:function(A,g){if(!uA.resolve(A))throw new WA.ErrnoError(mA.ENOENT);var I=WA.lookupPath(g,{parent:!0}).node;if(!I)throw new WA.ErrnoError(mA.ENOENT);var C=uA.basename(g),e=WA.mayCreate(I,C);if(e)throw new WA.ErrnoError(e);if(!I.node_ops.symlink)throw new WA.ErrnoError(mA.EPERM);return I.node_ops.symlink(I,C,A)},rename:function(A,g){var I,C,e=uA.dirname(A),i=uA.dirname(g),t=uA.basename(A),o=uA.basename(g);try{I=WA.lookupPath(A,{parent:!0}).node,C=WA.lookupPath(g,{parent:!0}).node}catch(A){throw new WA.ErrnoError(mA.EBUSY)}if(!I||!C)throw new WA.ErrnoError(mA.ENOENT);if(I.mount!==C.mount)throw new WA.ErrnoError(mA.EXDEV);var a,B=WA.lookupNode(I,t),s=uA.relative(A,i);if("."!==s.charAt(0))throw new WA.ErrnoError(mA.EINVAL);if("."!==(s=uA.relative(g,e)).charAt(0))throw new WA.ErrnoError(mA.ENOTEMPTY);try{a=WA.lookupNode(C,o)}catch(A){}if(B!==a){var l=WA.isDir(B.mode),n=WA.mayDelete(I,t,l);if(n)throw new WA.ErrnoError(n);if(n=a?WA.mayDelete(C,o,l):WA.mayCreate(C,o))throw new WA.ErrnoError(n);if(!I.node_ops.rename)throw new WA.ErrnoError(mA.EPERM);if(WA.isMountpoint(B)||a&&WA.isMountpoint(a))throw new WA.ErrnoError(mA.EBUSY);if(C!==I&&(n=WA.nodePermissions(I,"w")))throw new WA.ErrnoError(n);try{WA.trackingDelegate.willMovePath&&WA.trackingDelegate.willMovePath(A,g)}catch(I){console.log("FS.trackingDelegate['willMovePath']('"+A+"', '"+g+"') threw an exception: "+I.message)}WA.hashRemoveNode(B);try{I.node_ops.rename(B,C,o)}catch(A){throw A}finally{WA.hashAddNode(B)}try{WA.trackingDelegate.onMovePath&&WA.trackingDelegate.onMovePath(A,g)}catch(I){console.log("FS.trackingDelegate['onMovePath']('"+A+"', '"+g+"') threw an exception: "+I.message)}}},rmdir:function(A){var g=WA.lookupPath(A,{parent:!0}).node,I=uA.basename(A),C=WA.lookupNode(g,I),e=WA.mayDelete(g,I,!0);if(e)throw new WA.ErrnoError(e);if(!g.node_ops.rmdir)throw new WA.ErrnoError(mA.EPERM);if(WA.isMountpoint(C))throw new WA.ErrnoError(mA.EBUSY);try{WA.trackingDelegate.willDeletePath&&WA.trackingDelegate.willDeletePath(A)}catch(g){console.log("FS.trackingDelegate['willDeletePath']('"+A+"') threw an exception: "+g.message)}g.node_ops.rmdir(g,I),WA.destroyNode(C);try{WA.trackingDelegate.onDeletePath&&WA.trackingDelegate.onDeletePath(A)}catch(g){console.log("FS.trackingDelegate['onDeletePath']('"+A+"') threw an exception: "+g.message)}},readdir:function(A){var g=WA.lookupPath(A,{follow:!0}).node;if(!g.node_ops.readdir)throw new WA.ErrnoError(mA.ENOTDIR);return g.node_ops.readdir(g)},unlink:function(A){var g=WA.lookupPath(A,{parent:!0}).node,I=uA.basename(A),C=WA.lookupNode(g,I),e=WA.mayDelete(g,I,!1);if(e)throw new WA.ErrnoError(e);if(!g.node_ops.unlink)throw new WA.ErrnoError(mA.EPERM);if(WA.isMountpoint(C))throw new WA.ErrnoError(mA.EBUSY);try{WA.trackingDelegate.willDeletePath&&WA.trackingDelegate.willDeletePath(A)}catch(g){console.log("FS.trackingDelegate['willDeletePath']('"+A+"') threw an exception: "+g.message)}g.node_ops.unlink(g,I),WA.destroyNode(C);try{WA.trackingDelegate.onDeletePath&&WA.trackingDelegate.onDeletePath(A)}catch(g){console.log("FS.trackingDelegate['onDeletePath']('"+A+"') threw an exception: "+g.message)}},readlink:function(A){var g=WA.lookupPath(A).node;if(!g)throw new WA.ErrnoError(mA.ENOENT);if(!g.node_ops.readlink)throw new WA.ErrnoError(mA.EINVAL);return uA.resolve(WA.getPath(g.parent),g.node_ops.readlink(g))},stat:function(A,g){var I=WA.lookupPath(A,{follow:!g}).node;if(!I)throw new WA.ErrnoError(mA.ENOENT);if(!I.node_ops.getattr)throw new WA.ErrnoError(mA.EPERM);return I.node_ops.getattr(I)},lstat:function(A){return WA.stat(A,!0)},chmod:function(A,g,I){var C;"string"==typeof A?C=WA.lookupPath(A,{follow:!I}).node:C=A;if(!C.node_ops.setattr)throw new WA.ErrnoError(mA.EPERM);C.node_ops.setattr(C,{mode:4095&g|-4096&C.mode,timestamp:Date.now()})},lchmod:function(A,g){WA.chmod(A,g,!0)},fchmod:function(A,g){var I=WA.getStream(A);if(!I)throw new WA.ErrnoError(mA.EBADF);WA.chmod(I.node,g)},chown:function(A,g,I,C){var e;"string"==typeof A?e=WA.lookupPath(A,{follow:!C}).node:e=A;if(!e.node_ops.setattr)throw new WA.ErrnoError(mA.EPERM);e.node_ops.setattr(e,{timestamp:Date.now()})},lchown:function(A,g,I){WA.chown(A,g,I,!0)},fchown:function(A,g,I){var C=WA.getStream(A);if(!C)throw new WA.ErrnoError(mA.EBADF);WA.chown(C.node,g,I)},truncate:function(A,g){if(g<0)throw new WA.ErrnoError(mA.EINVAL);var I;"string"==typeof A?I=WA.lookupPath(A,{follow:!0}).node:I=A;if(!I.node_ops.setattr)throw new WA.ErrnoError(mA.EPERM);if(WA.isDir(I.mode))throw new WA.ErrnoError(mA.EISDIR);if(!WA.isFile(I.mode))throw new WA.ErrnoError(mA.EINVAL);var C=WA.nodePermissions(I,"w");if(C)throw new WA.ErrnoError(C);I.node_ops.setattr(I,{size:g,timestamp:Date.now()})},ftruncate:function(A,g){var I=WA.getStream(A);if(!I)throw new WA.ErrnoError(mA.EBADF);if(!(2097155&I.flags))throw new WA.ErrnoError(mA.EINVAL);WA.truncate(I.node,g)},utime:function(A,g,I){var C=WA.lookupPath(A,{follow:!0}).node;C.node_ops.setattr(C,{timestamp:Math.max(g,I)})},open:function(A,g,I,C,e){if(""===A)throw new WA.ErrnoError(mA.ENOENT);var i;if(I=void 0===I?438:I,I=64&(g="string"==typeof g?WA.modeStringToFlags(g):g)?4095&I|32768:0,"object"==typeof A)i=A;else{A=uA.normalize(A);try{i=WA.lookupPath(A,{follow:!(131072&g)}).node}catch(A){}}var t=!1;if(64&g)if(i){if(128&g)throw new WA.ErrnoError(mA.EEXIST)}else i=WA.mknod(A,I,0),t=!0;if(!i)throw new WA.ErrnoError(mA.ENOENT);if(WA.isChrdev(i.mode)&&(g&=-513),65536&g&&!WA.isDir(i.mode))throw new WA.ErrnoError(mA.ENOTDIR);if(!t){var o=WA.mayOpen(i,g);if(o)throw new WA.ErrnoError(o)}512&g&&WA.truncate(i,0),g&=-641;var a=WA.createStream({node:i,path:WA.getPath(i),flags:g,seekable:!0,position:0,stream_ops:i.stream_ops,ungotten:[],error:!1},C,e);a.stream_ops.open&&a.stream_ops.open(a),!Module.logReadFiles||1&g||(WA.readFiles||(WA.readFiles={}),A in WA.readFiles||(WA.readFiles[A]=1,Module.printErr("read file: "+A)));try{if(WA.trackingDelegate.onOpenFile){var B=0;1!=(2097155&g)&&(B|=WA.tracking.openFlags.READ),2097155&g&&(B|=WA.tracking.openFlags.WRITE),WA.trackingDelegate.onOpenFile(A,B)}}catch(g){console.log("FS.trackingDelegate['onOpenFile']('"+A+"', flags) threw an exception: "+g.message)}return a},close:function(A){if(WA.isClosed(A))throw new WA.ErrnoError(mA.EBADF);A.getdents&&(A.getdents=null);try{A.stream_ops.close&&A.stream_ops.close(A)}catch(A){throw A}finally{WA.closeStream(A.fd)}A.fd=null},isClosed:function(A){return null===A.fd},llseek:function(A,g,I){if(WA.isClosed(A))throw new WA.ErrnoError(mA.EBADF);if(!A.seekable||!A.stream_ops.llseek)throw new WA.ErrnoError(mA.ESPIPE);return A.position=A.stream_ops.llseek(A,g,I),A.ungotten=[],A.position},read:function(A,g,I,C,e){if(C<0||e<0)throw new WA.ErrnoError(mA.EINVAL);if(WA.isClosed(A))throw new WA.ErrnoError(mA.EBADF);if(1==(2097155&A.flags))throw new WA.ErrnoError(mA.EBADF);if(WA.isDir(A.node.mode))throw new WA.ErrnoError(mA.EISDIR);if(!A.stream_ops.read)throw new WA.ErrnoError(mA.EINVAL);var i=void 0!==e;if(i){if(!A.seekable)throw new WA.ErrnoError(mA.ESPIPE)}else e=A.position;var t=A.stream_ops.read(A,g,I,C,e);return i||(A.position+=t),t},write:function(A,g,I,C,e,i){if(C<0||e<0)throw new WA.ErrnoError(mA.EINVAL);if(WA.isClosed(A))throw new WA.ErrnoError(mA.EBADF);if(!(2097155&A.flags))throw new WA.ErrnoError(mA.EBADF);if(WA.isDir(A.node.mode))throw new WA.ErrnoError(mA.EISDIR);if(!A.stream_ops.write)throw new WA.ErrnoError(mA.EINVAL);1024&A.flags&&WA.llseek(A,0,2);var t=void 0!==e;if(t){if(!A.seekable)throw new WA.ErrnoError(mA.ESPIPE)}else e=A.position;var o=A.stream_ops.write(A,g,I,C,e,i);t||(A.position+=o);try{A.path&&WA.trackingDelegate.onWriteToFile&&WA.trackingDelegate.onWriteToFile(A.path)}catch(A){console.log("FS.trackingDelegate['onWriteToFile']('"+path+"') threw an exception: "+A.message)}return o},allocate:function(A,g,I){if(WA.isClosed(A))throw new WA.ErrnoError(mA.EBADF);if(g<0||I<=0)throw new WA.ErrnoError(mA.EINVAL);if(!(2097155&A.flags))throw new WA.ErrnoError(mA.EBADF);if(!WA.isFile(A.node.mode)&&!WA.isDir(A.node.mode))throw new WA.ErrnoError(mA.ENODEV);if(!A.stream_ops.allocate)throw new WA.ErrnoError(mA.EOPNOTSUPP);A.stream_ops.allocate(A,g,I)},mmap:function(A,g,I,C,e,i,t){if(1==(2097155&A.flags))throw new WA.ErrnoError(mA.EACCES);if(!A.stream_ops.mmap)throw new WA.ErrnoError(mA.ENODEV);return A.stream_ops.mmap(A,g,I,C,e,i,t)},msync:function(A,g,I,C,e){return A&&A.stream_ops.msync?A.stream_ops.msync(A,g,I,C,e):0},munmap:function(A){return 0},ioctl:function(A,g,I){if(!A.stream_ops.ioctl)throw new WA.ErrnoError(mA.ENOTTY);return A.stream_ops.ioctl(A,g,I)},readFile:function(A,g){if((g=g||{}).flags=g.flags||"r",g.encoding=g.encoding||"binary","utf8"!==g.encoding&&"binary"!==g.encoding)throw new Error('Invalid encoding type "'+g.encoding+'"');var I,C=WA.open(A,g.flags),e=WA.stat(A).size,i=new Uint8Array(e);return WA.read(C,i,0,e,0),"utf8"===g.encoding?I=Z(i,0):"binary"===g.encoding&&(I=i),WA.close(C),I},writeFile:function(A,g,I){(I=I||{}).flags=I.flags||"w";var C=WA.open(A,I.flags,I.mode);if("string"==typeof g){var e=new Uint8Array(Q(g)+1),i=y(g,e,0,e.length);WA.write(C,e,0,i,void 0,I.canOwn)}else{if(!ArrayBuffer.isView(g))throw new Error("Unsupported data type");WA.write(C,g,0,g.byteLength,void 0,I.canOwn)}WA.close(C)},cwd:function(){return WA.currentPath},chdir:function(A){var g=WA.lookupPath(A,{follow:!0});if(null===g.node)throw new WA.ErrnoError(mA.ENOENT);if(!WA.isDir(g.node.mode))throw new WA.ErrnoError(mA.ENOTDIR);var I=WA.nodePermissions(g.node,"x");if(I)throw new WA.ErrnoError(I);WA.currentPath=g.path},createDefaultDirectories:function(){WA.mkdir("/tmp"),WA.mkdir("/home"),WA.mkdir("/home/web_user")},createDefaultDevices:function(){var A;if(WA.mkdir("/dev"),WA.registerDevice(WA.makedev(1,3),{read:function(){return 0},write:function(A,g,I,C,e){return C}}),WA.mkdev("/dev/null",WA.makedev(1,3)),yA.register(WA.makedev(5,0),yA.default_tty_ops),yA.register(WA.makedev(6,0),yA.default_tty1_ops),WA.mkdev("/dev/tty",WA.makedev(5,0)),WA.mkdev("/dev/tty1",WA.makedev(6,0)),"undefined"!=typeof crypto){var g=new Uint8Array(1);A=function(){return crypto.getRandomValues(g),g[0]}}else A=B?function(){return require("crypto").randomBytes(1)[0]}:function(){return 256*Math.random()|0};WA.createDevice("/dev","random",A),WA.createDevice("/dev","urandom",A),WA.mkdir("/dev/shm"),WA.mkdir("/dev/shm/tmp")},createSpecialDirectories:function(){WA.mkdir("/proc"),WA.mkdir("/proc/self"),WA.mkdir("/proc/self/fd"),WA.mount({mount:function(){var A=WA.createNode("/proc/self","fd",16895,73);return A.node_ops={lookup:function(A,g){var I=+g,C=WA.getStream(I);if(!C)throw new WA.ErrnoError(mA.EBADF);var e={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:function(){return C.path}}};return e.parent=e,e}},A}},{},"/proc/self/fd")},createStandardStreams:function(){Module.stdin?WA.createDevice("/dev","stdin",Module.stdin):WA.symlink("/dev/tty","/dev/stdin"),Module.stdout?WA.createDevice("/dev","stdout",null,Module.stdout):WA.symlink("/dev/tty","/dev/stdout"),Module.stderr?WA.createDevice("/dev","stderr",null,Module.stderr):WA.symlink("/dev/tty1","/dev/stderr");var A=WA.open("/dev/stdin","r");c(0===A.fd,"invalid handle for stdin ("+A.fd+")");var g=WA.open("/dev/stdout","w");c(1===g.fd,"invalid handle for stdout ("+g.fd+")");var I=WA.open("/dev/stderr","w");c(2===I.fd,"invalid handle for stderr ("+I.fd+")")},ensureErrnoError:function(){WA.ErrnoError||(WA.ErrnoError=function(A,g){this.node=g,this.setErrno=function(A){for(var g in this.errno=A,mA)if(mA[g]===A){this.code=g;break}},this.setErrno(A),this.message=ZA[A],this.stack&&Object.defineProperty(this,"stack",{value:(new Error).stack,writable:!0})},WA.ErrnoError.prototype=new Error,WA.ErrnoError.prototype.constructor=WA.ErrnoError,[mA.ENOENT].forEach((function(A){WA.genericErrors[A]=new WA.ErrnoError(A),WA.genericErrors[A].stack="<generic error, no stack>"})))},staticInit:function(){WA.ensureErrnoError(),WA.nameTable=new Array(4096),WA.mount(EA,{},"/"),WA.createDefaultDirectories(),WA.createDefaultDevices(),WA.createSpecialDirectories(),WA.filesystems={MEMFS:EA,IDBFS:QA,NODEFS:VA,WORKERFS:RA}},init:function(A,g,I){c(!WA.init.initialized,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)"),WA.init.initialized=!0,WA.ensureErrnoError(),Module.stdin=A||Module.stdin,Module.stdout=g||Module.stdout,Module.stderr=I||Module.stderr,WA.createStandardStreams()},quit:function(){WA.init.initialized=!1;var A=Module._fflush;A&&A(0);for(var g=0;g<WA.streams.length;g++){var I=WA.streams[g];I&&WA.close(I)}},getMode:function(A,g){var I=0;return A&&(I|=365),g&&(I|=146),I},joinPath:function(A,g){var I=uA.join.apply(null,A);return g&&"/"==I[0]&&(I=I.substr(1)),I},absolutePath:function(A,g){return uA.resolve(g,A)},standardizePath:function(A){return uA.normalize(A)},findObject:function(A,g){var I=WA.analyzePath(A,g);return I.exists?I.object:(bA(I.error),null)},analyzePath:function(A,g){try{A=(C=WA.lookupPath(A,{follow:!g})).path}catch(A){}var I={isRoot:!1,exists:!1,error:0,name:null,path:null,object:null,parentExists:!1,parentPath:null,parentObject:null};try{var C=WA.lookupPath(A,{parent:!0});I.parentExists=!0,I.parentPath=C.path,I.parentObject=C.node,I.name=uA.basename(A),C=WA.lookupPath(A,{follow:!g}),I.exists=!0,I.path=C.path,I.object=C.node,I.name=C.node.name,I.isRoot="/"===C.path}catch(A){I.error=A.errno}return I},createFolder:function(A,g,I,C){var e=uA.join2("string"==typeof A?A:WA.getPath(A),g),i=WA.getMode(I,C);return WA.mkdir(e,i)},createPath:function(A,g,I,C){A="string"==typeof A?A:WA.getPath(A);for(var e=g.split("/").reverse();e.length;){var i=e.pop();if(i){var t=uA.join2(A,i);try{WA.mkdir(t)}catch(A){}A=t}}return t},createFile:function(A,g,I,C,e){var i=uA.join2("string"==typeof A?A:WA.getPath(A),g),t=WA.getMode(C,e);return WA.create(i,t)},createDataFile:function(A,g,I,C,e,i){var t=g?uA.join2("string"==typeof A?A:WA.getPath(A),g):A,o=WA.getMode(C,e),a=WA.create(t,o);if(I){if("string"==typeof I){for(var B=new Array(I.length),s=0,l=I.length;s<l;++s)B[s]=I.charCodeAt(s);I=B}WA.chmod(a,146|o);var n=WA.open(a,"w");WA.write(n,I,0,I.length,0,i),WA.close(n),WA.chmod(a,o)}return a},createDevice:function(A,g,I,C){var e=uA.join2("string"==typeof A?A:WA.getPath(A),g),i=WA.getMode(!!I,!!C);WA.createDevice.major||(WA.createDevice.major=64);var t=WA.makedev(WA.createDevice.major++,0);return WA.registerDevice(t,{open:function(A){A.seekable=!1},close:function(A){C&&C.buffer&&C.buffer.length&&C(10)},read:function(A,g,C,e,i){for(var t=0,o=0;o<e;o++){var a;try{a=I()}catch(A){throw new WA.ErrnoError(mA.EIO)}if(void 0===a&&0===t)throw new WA.ErrnoError(mA.EAGAIN);if(null==a)break;t++,g[C+o]=a}return t&&(A.node.timestamp=Date.now()),t},write:function(A,g,I,e,i){for(var t=0;t<e;t++)try{C(g[I+t])}catch(A){throw new WA.ErrnoError(mA.EIO)}return e&&(A.node.timestamp=Date.now()),t}}),WA.mkdev(e,i,t)},createLink:function(A,g,I,C,e){var i=uA.join2("string"==typeof A?A:WA.getPath(A),g);return WA.symlink(I,i)},forceLoadFile:function(A){if(A.isDevice||A.isFolder||A.link||A.contents)return!0;var g=!0;if("undefined"!=typeof XMLHttpRequest)throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");if(!Module.read)throw new Error("Cannot load without read() or XMLHttpRequest.");try{A.contents=Tg(Module.read(A.url),!0),A.usedBytes=A.contents.length}catch(A){g=!1}return g||bA(mA.EIO),g},createLazyFile:function(A,g,I,C,e){function i(){this.lengthKnown=!1,this.chunks=[]}if(i.prototype.get=function(A){if(!(A>this.length-1||A<0)){var g=A%this.chunkSize,I=A/this.chunkSize|0;return this.getter(I)[g]}},i.prototype.setDataGetter=function(A){this.getter=A},i.prototype.cacheLength=function(){var A=new XMLHttpRequest;if(A.open("HEAD",I,!1),A.send(null),!(A.status>=200&&A.status<300||304===A.status))throw new Error("Couldn't load "+I+". Status: "+A.status);var g,C=Number(A.getResponseHeader("Content-length")),e=(g=A.getResponseHeader("Accept-Ranges"))&&"bytes"===g,i=(g=A.getResponseHeader("Content-Encoding"))&&"gzip"===g,t=1048576;e||(t=C);var o=this;o.setDataGetter((function(A){var g=A*t,e=(A+1)*t-1;if(e=Math.min(e,C-1),void 0===o.chunks[A]&&(o.chunks[A]=function(A,g){if(A>g)throw new Error("invalid range ("+A+", "+g+") or no bytes requested!");if(g>C-1)throw new Error("only "+C+" bytes available! programmer error!");var e=new XMLHttpRequest;if(e.open("GET",I,!1),C!==t&&e.setRequestHeader("Range","bytes="+A+"-"+g),"undefined"!=typeof Uint8Array&&(e.responseType="arraybuffer"),e.overrideMimeType&&e.overrideMimeType("text/plain; charset=x-user-defined"),e.send(null),!(e.status>=200&&e.status<300||304===e.status))throw new Error("Couldn't load "+I+". Status: "+e.status);return void 0!==e.response?new Uint8Array(e.response||[]):Tg(e.responseText||"",!0)}(g,e)),void 0===o.chunks[A])throw new Error("doXHR failed!");return o.chunks[A]})),!i&&C||(t=C=1,C=this.getter(0).length,t=C,console.log("LazyFiles on gzip forces download of the whole file when length is accessed")),this._length=C,this._chunkSize=t,this.lengthKnown=!0},"undefined"!=typeof XMLHttpRequest){if(!a)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var t=new i;Object.defineProperties(t,{length:{get:function(){return this.lengthKnown||this.cacheLength(),this._length}},chunkSize:{get:function(){return this.lengthKnown||this.cacheLength(),this._chunkSize}}});var o={isDevice:!1,contents:t}}else o={isDevice:!1,url:I};var B=WA.createFile(A,g,o,C,e);o.contents?B.contents=o.contents:o.url&&(B.contents=null,B.url=o.url),Object.defineProperties(B,{usedBytes:{get:function(){return this.contents.length}}});var s={};return Object.keys(B.stream_ops).forEach((function(A){var g=B.stream_ops[A];s[A]=function(){if(!WA.forceLoadFile(B))throw new WA.ErrnoError(mA.EIO);return g.apply(null,arguments)}})),s.read=function(A,g,I,C,e){if(!WA.forceLoadFile(B))throw new WA.ErrnoError(mA.EIO);var i=A.node.contents;if(e>=i.length)return 0;var t=Math.min(i.length-e,C);if(c(t>=0),i.slice)for(var o=0;o<t;o++)g[I+o]=i[e+o];else for(o=0;o<t;o++)g[I+o]=i.get(e+o);return t},B.stream_ops=s,B},createPreloadedFile:function(A,g,I,C,e,i,t,o,a,B){Browser.init();var s=g?uA.resolve(uA.join2(A,g)):A;function l(I){function l(I){B&&B(),o||WA.createDataFile(A,g,I,C,e,a),i&&i(),lA()}var n=!1;Module.preloadPlugins.forEach((function(A){n||A.canHandle(s)&&(A.handle(I,s,l,(function(){t&&t(),lA()})),n=!0)})),n||l(I)}sA(),"string"==typeof I?Browser.asyncLoad(I,(function(A){l(A)}),t):l(I)},indexedDB:function(){return window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB},DB_NAME:function(){return"EM_FS_"+window.location.pathname},DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function(A,g,I){g=g||function(){},I=I||function(){};var C=WA.indexedDB();try{var e=C.open(WA.DB_NAME(),WA.DB_VERSION)}catch(A){return I(A)}e.onupgradeneeded=function(){console.log("creating db"),e.result.createObjectStore(WA.DB_STORE_NAME)},e.onsuccess=function(){var C=e.result.transaction([WA.DB_STORE_NAME],"readwrite"),i=C.objectStore(WA.DB_STORE_NAME),t=0,o=0,a=A.length;function B(){0==o?g():I()}A.forEach((function(A){var g=i.put(WA.analyzePath(A).object.contents,A);g.onsuccess=function(){++t+o==a&&B()},g.onerror=function(){o++,t+o==a&&B()}})),C.onerror=I},e.onerror=I},loadFilesFromDB:function(A,g,I){g=g||function(){},I=I||function(){};var C=WA.indexedDB();try{var e=C.open(WA.DB_NAME(),WA.DB_VERSION)}catch(A){return I(A)}e.onupgradeneeded=I,e.onsuccess=function(){var C=e.result;try{var i=C.transaction([WA.DB_STORE_NAME],"readonly")}catch(A){return void I(A)}var t=i.objectStore(WA.DB_STORE_NAME),o=0,a=0,B=A.length;function s(){0==a?g():I()}A.forEach((function(A){var g=t.get(A);g.onsuccess=function(){WA.analyzePath(A).exists&&WA.unlink(A),WA.createDataFile(uA.dirname(A),uA.basename(A),g.result,!0,!0,!0),++o+a==B&&s()},g.onerror=function(){a++,o+a==B&&s()}})),i.onerror=I},e.onerror=I}},pA={DEFAULT_POLLMASK:5,mappings:{},umask:511,calculateAt:function(A,g){if("/"!==g[0]){var I;if(-100===A)I=WA.cwd();else{var C=WA.getStream(A);if(!C)throw new WA.ErrnoError(mA.EBADF);I=C.path}g=uA.join2(I,g)}return g},doStat:function(A,g,I){try{var C=A(g)}catch(A){if(A&&A.node&&uA.normalize(g)!==uA.normalize(WA.getPath(A.node)))return-mA.ENOTDIR;throw A}return w[I>>2]=C.dev,w[I+4>>2]=0,w[I+8>>2]=C.ino,w[I+12>>2]=C.mode,w[I+16>>2]=C.nlink,w[I+20>>2]=C.uid,w[I+24>>2]=C.gid,w[I+28>>2]=C.rdev,w[I+32>>2]=0,w[I+36>>2]=C.size,w[I+40>>2]=4096,w[I+44>>2]=C.blocks,w[I+48>>2]=C.atime.getTime()/1e3|0,w[I+52>>2]=0,w[I+56>>2]=C.mtime.getTime()/1e3|0,w[I+60>>2]=0,w[I+64>>2]=C.ctime.getTime()/1e3|0,w[I+68>>2]=0,w[I+72>>2]=C.ino,0},doMsync:function(A,g,I,C){var e=new Uint8Array(p.subarray(A,A+I));WA.msync(g,e,0,I,C)},doMkdir:function(A,g){return"/"===(A=uA.normalize(A))[A.length-1]&&(A=A.substr(0,A.length-1)),WA.mkdir(A,g,0),0},doMknod:function(A,g,I){switch(61440&g){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-mA.EINVAL}return WA.mknod(A,g,I),0},doReadlink:function(A,g,I){if(I<=0)return-mA.EINVAL;var C=WA.readlink(A),e=Math.min(I,Q(C)),i=W[g+e];return E(C,g,I+1),W[g+e]=i,e},doAccess:function(A,g){if(-8&g)return-mA.EINVAL;var I;I=WA.lookupPath(A,{follow:!0}).node;var C="";return 4&g&&(C+="r"),2&g&&(C+="w"),1&g&&(C+="x"),C&&WA.nodePermissions(I,C)?-mA.EACCES:0},doDup:function(A,g,I){var C=WA.getStream(I);return C&&WA.close(C),WA.open(A,g,0,I,I).fd},doReadv:function(A,g,I,C){for(var e=0,i=0;i<I;i++){var t=w[g+8*i>>2],o=w[g+(8*i+4)>>2],a=WA.read(A,W,t,o,C);if(a<0)return-1;if(e+=a,a<o)break}return e},doWritev:function(A,g,I,C){for(var e=0,i=0;i<I;i++){var t=w[g+8*i>>2],o=w[g+(8*i+4)>>2],a=WA.write(A,W,t,o,C);if(a<0)return-1;e+=a}return e},varargs:0,get:function(A){return pA.varargs+=4,w[pA.varargs-4>>2]},getStr:function(){return m(pA.get())},getStreamFromFD:function(){var A=WA.getStream(pA.get());if(!A)throw new WA.ErrnoError(mA.EBADF);return A},getSocketFromFD:function(){var A=SOCKFS.getSocket(pA.get());if(!A)throw new WA.ErrnoError(mA.EBADF);return A},getSocketAddress:function(A){var g=pA.get(),I=pA.get();if(A&&0===g)return null;var C=__read_sockaddr(g,I);if(C.errno)throw new WA.ErrnoError(C.errno);return C.addr=DNS.lookup_addr(C.addr)||C.addr,C},get64:function(){var A=pA.get(),g=pA.get();return c(A>=0?0===g:-1===g),A},getZero:function(){c(0===pA.get())}};var SA=42;var FA={};function wA(A){for(;A.length;){var g=A.pop();A.pop()(g)}}function HA(A){return this.fromWireType(H[A>>2])}var XA={},YA={},KA={};function NA(A){if(void 0===A)return"_unknown";var g=(A=A.replace(/[^a-zA-Z0-9_]/g,"$")).charCodeAt(0);return g>=48&&g<=57?"_"+A:A}function vA(A,g){return A=NA(A),new Function("body","return function "+A+'() {\n    "use strict";    return body.apply(this, arguments);\n};\n')(g)}function JA(A,g){var I=vA(g,(function(A){this.name=g,this.message=A;var I=new Error(A).stack;void 0!==I&&(this.stack=this.toString()+"\n"+I.replace(/^Error(:[^\n]*)?\n/,""))}));return I.prototype=Object.create(A.prototype),I.prototype.constructor=I,I.prototype.toString=function(){return void 0===this.message?this.name:this.name+": "+this.message},I}var fA=void 0;function LA(A){throw new fA(A)}function MA(A,g,I){function C(g){var C=I(g);C.length!==A.length&&LA("Mismatched type converter count");for(var e=0;e<A.length;++e)zA(A[e],C[e])}A.forEach((function(A){KA[A]=g}));var e=new Array(g.length),i=[],t=0;g.forEach((function(A,g){YA.hasOwnProperty(A)?e[g]=YA[A]:(i.push(A),XA.hasOwnProperty(A)||(XA[A]=[]),XA[A].push((function(){e[g]=YA[A],++t===i.length&&C(e)})))})),0===i.length&&C(e)}function UA(A){switch(A){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+A)}}var kA=void 0;function DA(A){for(var g="",I=A;p[I];)g+=kA[p[I++]];return g}var xA=void 0;function TA(A){throw new xA(A)}function zA(A,g,I){if(I=I||{},!("argPackAdvance"in g))throw new TypeError("registerType registeredInstance requires argPackAdvance");var C=g.name;if(A||TA('type "'+C+'" must have a positive integer typeid pointer'),YA.hasOwnProperty(A)){if(I.ignoreDuplicateRegistrations)return;TA("Cannot register type '"+C+"' twice")}if(YA[A]=g,delete KA[A],XA.hasOwnProperty(A)){var e=XA[A];delete XA[A],e.forEach((function(A){A()}))}}function PA(A){if(!(this instanceof Cg))return!1;if(!(A instanceof Cg))return!1;for(var g=this.$$.ptrType.registeredClass,I=this.$$.ptr,C=A.$$.ptrType.registeredClass,e=A.$$.ptr;g.baseClass;)I=g.upcast(I),g=g.baseClass;for(;C.baseClass;)e=C.upcast(e),C=C.baseClass;return g===C&&I===e}function OA(A){TA(A.$$.ptrType.registeredClass.name+" instance already deleted")}function jA(){if(this.$$.ptr||OA(this),this.$$.preservePointerOnDelete)return this.$$.count.value+=1,this;var A,g=Object.create(Object.getPrototypeOf(this),{$$:{value:(A=this.$$,{count:A.count,deleteScheduled:A.deleteScheduled,preservePointerOnDelete:A.preservePointerOnDelete,ptr:A.ptr,ptrType:A.ptrType,smartPtr:A.smartPtr,smartPtrType:A.smartPtrType})}});return g.$$.count.value+=1,g.$$.deleteScheduled=!1,g}function qA(){var A;this.$$.ptr||OA(this),this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete&&TA("Object already scheduled for deletion"),this.$$.count.value-=1,0===this.$$.count.value&&((A=this.$$).smartPtr?A.smartPtrType.rawDestructor(A.smartPtr):A.ptrType.registeredClass.rawDestructor(A.ptr)),this.$$.preservePointerOnDelete||(this.$$.smartPtr=void 0,this.$$.ptr=void 0)}function _A(){return!this.$$.ptr}var $A=void 0,Ag=[];function gg(){for(;Ag.length;){var A=Ag.pop();A.$$.deleteScheduled=!1,A.delete()}}function Ig(){return this.$$.ptr||OA(this),this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete&&TA("Object already scheduled for deletion"),Ag.push(this),1===Ag.length&&$A&&$A(gg),this.$$.deleteScheduled=!0,this}function Cg(){}var eg={};function ig(A,g,I){if(void 0===A[g].overloadTable){var C=A[g];A[g]=function(){return A[g].overloadTable.hasOwnProperty(arguments.length)||TA("Function '"+I+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+A[g].overloadTable+")!"),A[g].overloadTable[arguments.length].apply(this,arguments)},A[g].overloadTable=[],A[g].overloadTable[C.argCount]=C}}function tg(A,g,I,C,e,i,t,o){this.name=A,this.constructor=g,this.instancePrototype=I,this.rawDestructor=C,this.baseClass=e,this.getActualType=i,this.upcast=t,this.downcast=o,this.pureVirtualFunctions=[]}function og(A,g,I){for(;g!==I;)g.upcast||TA("Expected null or instance of "+I.name+", got an instance of "+g.name),A=g.upcast(A),g=g.baseClass;return A}function ag(A,g){if(null===g)return this.isReference&&TA("null is not a valid "+this.name),0;g.$$||TA('Cannot pass "'+Yg(g)+'" as a '+this.name),g.$$.ptr||TA("Cannot pass deleted object as a pointer of type "+this.name);var I=g.$$.ptrType.registeredClass;return og(g.$$.ptr,I,this.registeredClass)}function Bg(A,g){var I;if(null===g)return this.isReference&&TA("null is not a valid "+this.name),this.isSmartPointer?(I=this.rawConstructor(),null!==A&&A.push(this.rawDestructor,I),I):0;g.$$||TA('Cannot pass "'+Yg(g)+'" as a '+this.name),g.$$.ptr||TA("Cannot pass deleted object as a pointer of type "+this.name),!this.isConst&&g.$$.ptrType.isConst&&TA("Cannot convert argument of type "+(g.$$.smartPtrType?g.$$.smartPtrType.name:g.$$.ptrType.name)+" to parameter type "+this.name);var C=g.$$.ptrType.registeredClass;if(I=og(g.$$.ptr,C,this.registeredClass),this.isSmartPointer)switch(void 0===g.$$.smartPtr&&TA("Passing raw pointer to smart pointer is illegal"),this.sharingPolicy){case 0:g.$$.smartPtrType===this?I=g.$$.smartPtr:TA("Cannot convert argument of type "+(g.$$.smartPtrType?g.$$.smartPtrType.name:g.$$.ptrType.name)+" to parameter type "+this.name);break;case 1:I=g.$$.smartPtr;break;case 2:if(g.$$.smartPtrType===this)I=g.$$.smartPtr;else{var e=g.clone();I=this.rawShare(I,Xg((function(){e.delete()}))),null!==A&&A.push(this.rawDestructor,I)}break;default:TA("Unsupporting sharing policy")}return I}function sg(A,g){if(null===g)return this.isReference&&TA("null is not a valid "+this.name),0;g.$$||TA('Cannot pass "'+Yg(g)+'" as a '+this.name),g.$$.ptr||TA("Cannot pass deleted object as a pointer of type "+this.name),g.$$.ptrType.isConst&&TA("Cannot convert argument of type "+g.$$.ptrType.name+" to parameter type "+this.name);var I=g.$$.ptrType.registeredClass;return og(g.$$.ptr,I,this.registeredClass)}function lg(A){return this.rawGetPointee&&(A=this.rawGetPointee(A)),A}function ng(A){this.rawDestructor&&this.rawDestructor(A)}function dg(A){null!==A&&A.delete()}function rg(A,g,I){if(g===I)return A;if(void 0===I.baseClass)return null;var C=rg(A,g,I.baseClass);return null===C?null:I.downcast(C)}function cg(){return Object.keys(mg).length}function hg(){var A=[];for(var g in mg)mg.hasOwnProperty(g)&&A.push(mg[g]);return A}function Gg(A){$A=A,Ag.length&&$A&&$A(gg)}var mg={};function bg(A,g){return g=function(A,g){for(void 0===g&&TA("ptr should not be undefined");A.baseClass;)g=A.upcast(g),A=A.baseClass;return g}(A,g),mg[g]}function Zg(A,g){return g.ptrType&&g.ptr||LA("makeClassHandle requires ptr and ptrType"),!!g.smartPtrType!==!!g.smartPtr&&LA("Both smartPtrType and smartPtr must be specified"),g.count={value:1},Object.create(A,{$$:{value:g}})}function ug(A){var g=this.getPointee(A);if(!g)return this.destructor(A),null;var I=bg(this.registeredClass,g);if(void 0!==I){if(0===I.$$.count.value)return I.$$.ptr=g,I.$$.smartPtr=A,I.clone();var C=I.clone();return this.destructor(A),C}function e(){return this.isSmartPointer?Zg(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:g,smartPtrType:this,smartPtr:A}):Zg(this.registeredClass.instancePrototype,{ptrType:this,ptr:A})}var i,t=this.registeredClass.getActualType(g),o=eg[t];if(!o)return e.call(this);i=this.isConst?o.constPointerType:o.pointerType;var a=rg(g,this.registeredClass,i.registeredClass);return null===a?e.call(this):this.isSmartPointer?Zg(i.registeredClass.instancePrototype,{ptrType:i,ptr:a,smartPtrType:this,smartPtr:A}):Zg(i.registeredClass.instancePrototype,{ptrType:i,ptr:a})}function yg(A,g,I,C,e,i,t,o,a,B,s){this.name=A,this.registeredClass=g,this.isReference=I,this.isConst=C,this.isSmartPointer=e,this.pointeeType=i,this.sharingPolicy=t,this.rawGetPointee=o,this.rawConstructor=a,this.rawShare=B,this.rawDestructor=s,e||void 0!==g.baseClass?this.toWireType=Bg:C?(this.toWireType=ag,this.destructorFunction=null):(this.toWireType=sg,this.destructorFunction=null)}function Eg(A,g){var I;if(A=DA(A),void 0!==Module["FUNCTION_TABLE_"+A])I=Module["FUNCTION_TABLE_"+A][g];else if("undefined"!=typeof FUNCTION_TABLE)I=FUNCTION_TABLE[g];else{var C=Module.asm["dynCall_"+A];void 0===C&&void 0===(C=Module.asm["dynCall_"+A.replace(/f/g,"d")])&&TA("No dynCall invoker for signature: "+A),I=function(I){for(var C=[],e=1;e<A.length;++e)C.push("a"+e);var i="return function dynCall_"+A+"_"+g+"("+C.join(", ")+") {\n";return i+="    return dynCall(rawFunction"+(C.length?", ":"")+C.join(", ")+");\n",i+="};\n",new Function("dynCall","rawFunction",i)(I,g)}(C)}return"function"!=typeof I&&TA("unknown function pointer with signature "+A+": "+g),I}var Qg=void 0;function Vg(A){var g=_g(A),I=DA(g);return AI(g),I}function Rg(A,g){var I=[],C={};throw g.forEach((function A(g){C[g]||YA[g]||(KA[g]?KA[g].forEach(A):(I.push(g),C[g]=!0))})),new Qg(A+": "+I.map(Vg).join([", "]))}function Wg(A,g){for(var I=[],C=0;C<A;C++)I.push(w[(g>>2)+C]);return I}function pg(A,g,I,C,e){var i=g.length;i<2&&TA("argTypes array size mismatch! Must at least get return value and 'this' types!");for(var t=null!==g[1]&&null!==I,o=!1,a=1;a<g.length;++a)if(null!==g[a]&&void 0===g[a].destructorFunction){o=!0;break}var B="void"!==g[0].name,s="",l="";for(a=0;a<i-2;++a)s+=(0!==a?", ":"")+"arg"+a,l+=(0!==a?", ":"")+"arg"+a+"Wired";var n="return function "+NA(A)+"("+s+") {\nif (arguments.length !== "+(i-2)+") {\nthrowBindingError('function "+A+" called with ' + arguments.length + ' arguments, expected "+(i-2)+" args!');\n}\n";o&&(n+="var destructors = [];\n");var d=o?"destructors":"null",r=["throwBindingError","invoker","fn","runDestructors","retType","classParam"],c=[TA,C,e,wA,g[0],g[1]];t&&(n+="var thisWired = classParam.toWireType("+d+", this);\n");for(a=0;a<i-2;++a)n+="var arg"+a+"Wired = argType"+a+".toWireType("+d+", arg"+a+"); // "+g[a+2].name+"\n",r.push("argType"+a),c.push(g[a+2]);if(t&&(l="thisWired"+(l.length>0?", ":"")+l),n+=(B?"var rv = ":"")+"invoker(fn"+(l.length>0?", ":"")+l+");\n",o)n+="runDestructors(destructors);\n";else for(a=t?1:2;a<g.length;++a){var h=1===a?"thisWired":"arg"+(a-2)+"Wired";null!==g[a].destructorFunction&&(n+=h+"_dtor("+h+"); // "+g[a].name+"\n",r.push(h+"_dtor"),c.push(g[a].destructorFunction))}return B&&(n+="var ret = retType.fromWireType(rv);\nreturn ret;\n"),n+="}\n",r.push(n),function(A,g){if(!(A instanceof Function))throw new TypeError("new_ called with constructor type "+typeof A+" which is not a function");var I=vA(A.name||"unknownFunctionName",(function(){}));I.prototype=A.prototype;var C=new I,e=A.apply(C,g);return e instanceof Object?e:C}(Function,r).apply(null,c)}var Sg=[],Fg=[{},{value:void 0},{value:null},{value:!0},{value:!1}];function wg(){for(var A=0,g=5;g<Fg.length;++g)void 0!==Fg[g]&&++A;return A}function Hg(){for(var A=5;A<Fg.length;++A)if(void 0!==Fg[A])return Fg[A];return null}function Xg(A){switch(A){case void 0:return 1;case null:return 2;case!0:return 3;case!1:return 4;default:var g=Sg.length?Sg.pop():Fg.length;return Fg[g]={refcount:1,value:A},g}}function Yg(A){if(null===A)return"null";var g=typeof A;return"object"===g||"array"===g||"function"===g?A.toString():""+A}function Kg(A,g){switch(g){case 2:return function(A){return this.fromWireType(X[A>>2])};case 3:return function(A){return this.fromWireType(Y[A>>3])};default:throw new TypeError("Unknown float type: "+A)}}function Ng(A,g,I){switch(g){case 0:return I?function(A){return W[A]}:function(A){return p[A]};case 1:return I?function(A){return S[A>>1]}:function(A){return F[A>>1]};case 2:return I?function(A){return w[A>>2]}:function(A){return H[A>>2]};default:throw new TypeError("Unknown integer type: "+A)}}var vg=K+=16;var Jg={};var fg=K+=16;K+=48,G(Tg("GMT"),"i8",2);var Lg=K,Mg=K+=16,Ug=K+=16;function kg(){if(!kg.called){kg.called=!0,w[Ug>>2]=60*(new Date).getTimezoneOffset();var A=new Date(2e3,0,1),g=new Date(2e3,6,1);w[Mg>>2]=Number(A.getTimezoneOffset()!=g.getTimezoneOffset());var I=t(A),C=t(g),e=G(Tg(I),"i8",0),i=G(Tg(C),"i8",0);g.getTimezoneOffset()<A.getTimezoneOffset()?(w[Lg>>2]=e,w[Lg+4>>2]=i):(w[Lg>>2]=i,w[Lg+4>>2]=e)}function t(A){var g=A.toTimeString().match(/\(([A-Za-z ]+)\)$/);return g?g[1]:"GMT"}}K+=16;var Dg={};var xg=1;function Tg(A,g,I){var C=I>0?I:Q(A)+1,e=new Array(C),i=y(A,e,0,e.length);return g&&(e.length=i),e}WA.staticInit(),_.unshift((function(){Module.noFSInit||WA.init.initialized||WA.init()})),$.push((function(){WA.ignorePermissions=!1})),AA.push((function(){WA.quit()})),_.unshift((function(){})),AA.push((function(){})),fA=Module.InternalError=JA(Error,"InternalError"),function(){for(var A=new Array(256),g=0;g<256;++g)A[g]=String.fromCharCode(g);kA=A}(),xA=Module.BindingError=JA(Error,"BindingError"),Cg.prototype.isAliasOf=PA,Cg.prototype.clone=jA,Cg.prototype.delete=qA,Cg.prototype.isDeleted=_A,Cg.prototype.deleteLater=Ig,yg.prototype.getPointee=lg,yg.prototype.destructor=ng,yg.prototype.argPackAdvance=8,yg.prototype.readValueFromPointer=HA,yg.prototype.deleteObject=dg,yg.prototype.fromWireType=ug,Module.getInheritedInstanceCount=cg,Module.getLiveInheritedInstances=hg,Module.flushPendingDeletes=gg,Module.setDelayFunction=Gg,Qg=Module.UnboundTypeError=JA(Error,"UnboundTypeError"),Module.count_emval_handles=wg,Module.get_first_emval=Hg,function A(g){var I,C;A.called?(C=w[vg>>2],I=w[C>>2]):(A.called=!0,Jg.USER=Jg.LOGNAME="web_user",Jg.PATH="/",Jg.PWD="/",Jg.HOME="/home/web_user",Jg.LANG="C.UTF-8",Jg._=Module.thisProgram,I=s(1024),C=s(256),w[C>>2]=I,w[vg>>2]=C);var e=[],i=0;for(var t in g)if("string"==typeof g[t]){var o=t+"="+g[t];e.push(o),i+=o.length}if(i>1024)throw new Error("Environment size exceeded TOTAL_ENV_SIZE!");for(var a=0;a<e.length;a++){CA(o=e[a],I),w[C+4*a>>2]=I,I+=o.length+1}w[C+4*e.length>>2]=0}(Jg),L=s(4),v=J=n(K),f=n(v+P),w[L>>2]=f,N=!0,Module.wasmTableSize=316,Module.wasmMaxTableSize=316,Module.asmGlobalArg={},Module.asmLibraryArg={abort:tI,enlargeMemory:z,getTotalMemory:function(){return O},abortOnCannotGrowMemory:function(){tI("Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value "+O+", (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 ")},invoke_i:function(A){try{return Module.dynCall_i(A)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_ii:function(A,g){try{return Module.dynCall_ii(A,g)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_iii:function(A,g,I){try{return Module.dynCall_iii(A,g,I)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_iiii:function(A,g,I,C){try{return Module.dynCall_iiii(A,g,I,C)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_iiiii:function(A,g,I,C,e){try{return Module.dynCall_iiiii(A,g,I,C,e)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_iiiiiii:function(A,g,I,C,e,i,t){try{return Module.dynCall_iiiiiii(A,g,I,C,e,i,t)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_iiiiiiiiii:function(A,g,I,C,e,i,t,o,a,B){try{return Module.dynCall_iiiiiiiiii(A,g,I,C,e,i,t,o,a,B)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_iiiiiijii:function(A,g,I,C,e,i,t,o,a,B){try{return Module.dynCall_iiiiiijii(A,g,I,C,e,i,t,o,a,B)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_ijj:function(A,g,I,C,e){try{return Module.dynCall_ijj(A,g,I,C,e)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_ji:function(A,g){try{return Module.dynCall_ji(A,g)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_v:function(A){try{Module.dynCall_v(A)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_vi:function(A,g){try{Module.dynCall_vi(A,g)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_vii:function(A,g,I){try{Module.dynCall_vii(A,g,I)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_viii:function(A,g,I,C){try{Module.dynCall_viii(A,g,I,C)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_viiii:function(A,g,I,C,e){try{Module.dynCall_viiii(A,g,I,C,e)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_viiiii:function(A,g,I,C,e,i){try{Module.dynCall_viiiii(A,g,I,C,e,i)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_viiiiii:function(A,g,I,C,e,i,t){try{Module.dynCall_viiiiii(A,g,I,C,e,i,t)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_viiiiiiiii:function(A,g,I,C,e,i,t,o,a,B){try{Module.dynCall_viiiiiiiii(A,g,I,C,e,i,t,o,a,B)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_viiiiiiiiii:function(A,g,I,C,e,i,t,o,a,B,s){try{Module.dynCall_viiiiiiiiii(A,g,I,C,e,i,t,o,a,B,s)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_vij:function(A,g,I,C){try{Module.dynCall_vij(A,g,I,C)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},invoke_viji:function(A,g,I,C,e){try{Module.dynCall_viji(A,g,I,C,e)}catch(A){if("number"!=typeof A&&"longjmp"!==A)throw A;Module.setThrew(1,0)}},___cxa_allocate_exception:function(A){return gI(A)},___cxa_begin_catch:function(A){var g=cA.infos[A];return g&&!g.caught&&(g.caught=!0,rA.uncaught_exception--),g&&(g.rethrown=!1),cA.caught.push(A),cA.addRef(cA.deAdjust(A)),A},___cxa_end_catch:function(){Module.setThrew(0);var A=cA.caught.pop();A&&(cA.decRef(cA.deAdjust(A)),cA.last=0)},___cxa_find_matching_catch_2:function(){return GA.apply(null,arguments)},___cxa_find_matching_catch_3:function(){return GA.apply(null,arguments)},___cxa_find_matching_catch_4:function(){return GA.apply(null,arguments)},___cxa_free_exception:hA,___cxa_throw:function(A,g,I){throw cA.infos[A]={ptr:A,adjusted:A,type:g,destructor:I,refcount:0,caught:!1,rethrown:!1},cA.last=A,"uncaught_exception"in rA?rA.uncaught_exception++:rA.uncaught_exception=1,A},___lock:function(){},___map_file:function(A,g){return bA(mA.EPERM),-1},___resumeException:function(A){throw cA.last||(cA.last=A),A},___setErrNo:bA,___syscall140:function(A,g){pA.varargs=g;try{var I=pA.getStreamFromFD(),C=(pA.get(),pA.get()),e=pA.get(),i=pA.get(),t=C;return WA.llseek(I,t,i),w[e>>2]=I.position,I.getdents&&0===t&&0===i&&(I.getdents=null),0}catch(A){return void 0!==WA&&A instanceof WA.ErrnoError||tI(A),-A.errno}},___syscall145:function(A,g){pA.varargs=g;try{var I=pA.getStreamFromFD(),C=pA.get(),e=pA.get();return pA.doReadv(I,C,e)}catch(A){return void 0!==WA&&A instanceof WA.ErrnoError||tI(A),-A.errno}},___syscall146:function(A,g){pA.varargs=g;try{var I=pA.getStreamFromFD(),C=pA.get(),e=pA.get();return pA.doWritev(I,C,e)}catch(A){return void 0!==WA&&A instanceof WA.ErrnoError||tI(A),-A.errno}},___syscall183:function(A,g){pA.varargs=g;try{var I=pA.get(),C=pA.get();if(0===C)return-mA.EINVAL;var e=WA.cwd();return C<Q(e)+1?-mA.ERANGE:(E(e,I,C),I)}catch(A){return void 0!==WA&&A instanceof WA.ErrnoError||tI(A),-A.errno}},___syscall198:function(A,g){pA.varargs=g;try{var I=pA.getStr(),C=pA.get(),e=pA.get();return WA.chown(I,C,e),0}catch(A){return void 0!==WA&&A instanceof WA.ErrnoError||tI(A),-A.errno}},___syscall20:function(A,g){pA.varargs=g;try{return SA}catch(A){return void 0!==WA&&A instanceof WA.ErrnoError||tI(A),-A.errno}},___syscall6:function(A,g){pA.varargs=g;try{var I=pA.getStreamFromFD();return WA.close(I),0}catch(A){return void 0!==WA&&A instanceof WA.ErrnoError||tI(A),-A.errno}},___syscall60:function(A,g){pA.varargs=g;try{var I=pA.get(),C=pA.umask;return pA.umask=I,C}catch(A){return void 0!==WA&&A instanceof WA.ErrnoError||tI(A),-A.errno}},___syscall83:function(A,g){pA.varargs=g;try{var I=pA.getStr(),C=pA.getStr();return WA.symlink(I,C),0}catch(A){return void 0!==WA&&A instanceof WA.ErrnoError||tI(A),-A.errno}},___syscall91:function(A,g){pA.varargs=g;try{var I=pA.get(),C=pA.get(),e=pA.mappings[I];if(!e)return 0;if(C===e.len){var i=WA.getStream(e.fd);pA.doMsync(I,i,C,e.flags),WA.munmap(i),pA.mappings[I]=null,e.allocated&&AI(e.malloc)}return 0}catch(A){return void 0!==WA&&A instanceof WA.ErrnoError||tI(A),-A.errno}},___unlock:function(){},__embind_finalize_value_object:function(A){var g=FA[A];delete FA[A];var I=g.rawConstructor,C=g.rawDestructor,e=g.fields;MA([A],e.map((function(A){return A.getterReturnType})).concat(e.map((function(A){return A.setterArgumentType}))),(function(A){var i={};return e.forEach((function(g,I){var C=g.fieldName,t=A[I],o=g.getter,a=g.getterContext,B=A[I+e.length],s=g.setter,l=g.setterContext;i[C]={read:function(A){return t.fromWireType(o(a,A))},write:function(A,g){var I=[];s(l,A,B.toWireType(I,g)),wA(I)}}})),[{name:g.name,fromWireType:function(A){var g={};for(var I in i)g[I]=i[I].read(A);return C(A),g},toWireType:function(A,g){for(var e in i)if(!(e in g))throw new TypeError("Missing field");var t=I();for(e in i)i[e].write(t,g[e]);return null!==A&&A.push(C,t),t},argPackAdvance:8,readValueFromPointer:HA,destructorFunction:C}]}))},__embind_register_bool:function(A,g,I,C,e){var i=UA(I);zA(A,{name:g=DA(g),fromWireType:function(A){return!!A},toWireType:function(A,g){return g?C:e},argPackAdvance:8,readValueFromPointer:function(A){var C;if(1===I)C=W;else if(2===I)C=S;else{if(4!==I)throw new TypeError("Unknown boolean type size: "+g);C=w}return this.fromWireType(C[A>>i])},destructorFunction:null})},__embind_register_class:function(A,g,I,C,e,i,t,o,a,B,s,l,n){s=DA(s),i=Eg(e,i),o&&(o=Eg(t,o)),B&&(B=Eg(a,B)),n=Eg(l,n);var d=NA(s);!function(A,g,I){Module.hasOwnProperty(A)?((void 0===I||void 0!==Module[A].overloadTable&&void 0!==Module[A].overloadTable[I])&&TA("Cannot register public name '"+A+"' twice"),ig(Module,A,A),Module.hasOwnProperty(I)&&TA("Cannot register multiple overloads of a function with the same number of arguments ("+I+")!"),Module[A].overloadTable[I]=g):(Module[A]=g,void 0!==I&&(Module[A].numArguments=I))}(d,(function(){Rg("Cannot construct "+s+" due to unbound types",[C])})),MA([A,g,I],C?[C]:[],(function(g){var I,e;g=g[0],e=C?(I=g.registeredClass).instancePrototype:Cg.prototype;var t=vA(d,(function(){if(Object.getPrototypeOf(this)!==a)throw new xA("Use 'new' to construct "+s);if(void 0===l.constructor_body)throw new xA(s+" has no accessible constructor");var A=l.constructor_body[arguments.length];if(void 0===A)throw new xA("Tried to invoke ctor of "+s+" with invalid number of parameters ("+arguments.length+") - expected ("+Object.keys(l.constructor_body).toString()+") parameters instead!");return A.apply(this,arguments)})),a=Object.create(e,{constructor:{value:t}});t.prototype=a;var l=new tg(s,t,a,n,I,i,o,B),r=new yg(s,l,!0,!1,!1),c=new yg(s+"*",l,!1,!1,!1),h=new yg(s+" const*",l,!1,!0,!1);return eg[A]={pointerType:c,constPointerType:h},function(A,g,I){Module.hasOwnProperty(A)||LA("Replacing nonexistant public symbol"),void 0!==Module[A].overloadTable&&void 0!==I?Module[A].overloadTable[I]=g:(Module[A]=g,Module[A].argCount=I)}(d,t),[r,c,h]}))},__embind_register_class_constructor:function(A,g,I,C,e,i){var t=Wg(g,I);e=Eg(C,e),MA([],[A],(function(A){var I="constructor "+(A=A[0]).name;if(void 0===A.registeredClass.constructor_body&&(A.registeredClass.constructor_body=[]),void 0!==A.registeredClass.constructor_body[g-1])throw new xA("Cannot register multiple constructors with identical number of parameters ("+(g-1)+") for class '"+A.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!");return A.registeredClass.constructor_body[g-1]=function(){Rg("Cannot construct "+A.name+" due to unbound types",t)},MA([],t,(function(C){return A.registeredClass.constructor_body[g-1]=function(){arguments.length!==g-1&&TA(I+" called with "+arguments.length+" arguments, expected "+(g-1));var A=[],t=new Array(g);t[0]=i;for(var o=1;o<g;++o)t[o]=C[o].toWireType(A,arguments[o-1]);var a=e.apply(null,t);return wA(A),C[0].fromWireType(a)},[]})),[]}))},__embind_register_class_function:function(A,g,I,C,e,i,t,o){var a=Wg(I,C);g=DA(g),i=Eg(e,i),MA([],[A],(function(A){var C=(A=A[0]).name+"."+g;function e(){Rg("Cannot call "+C+" due to unbound types",a)}o&&A.registeredClass.pureVirtualFunctions.push(g);var B=A.registeredClass.instancePrototype,s=B[g];return void 0===s||void 0===s.overloadTable&&s.className!==A.name&&s.argCount===I-2?(e.argCount=I-2,e.className=A.name,B[g]=e):(ig(B,g,C),B[g].overloadTable[I-2]=e),MA([],a,(function(e){var o=pg(C,e,A,i,t);return void 0===B[g].overloadTable?(o.argCount=I-2,B[g]=o):B[g].overloadTable[I-2]=o,[]})),[]}))},__embind_register_emval:function(A,g){zA(A,{name:g=DA(g),fromWireType:function(A){var g=Fg[A].value;return function(A){A>4&&0==--Fg[A].refcount&&(Fg[A]=void 0,Sg.push(A))}(A),g},toWireType:function(A,g){return Xg(g)},argPackAdvance:8,readValueFromPointer:HA,destructorFunction:null})},__embind_register_float:function(A,g,I){var C=UA(I);zA(A,{name:g=DA(g),fromWireType:function(A){return A},toWireType:function(A,g){if("number"!=typeof g&&"boolean"!=typeof g)throw new TypeError('Cannot convert "'+Yg(g)+'" to '+this.name);return g},argPackAdvance:8,readValueFromPointer:Kg(g,C),destructorFunction:null})},__embind_register_integer:function(A,g,I,C,e){g=DA(g),-1===e&&(e=4294967295);var i=UA(I),t=function(A){return A};if(0===C){var o=32-8*I;t=function(A){return A<<o>>>o}}var a=-1!=g.indexOf("unsigned");zA(A,{name:g,fromWireType:t,toWireType:function(A,I){if("number"!=typeof I&&"boolean"!=typeof I)throw new TypeError('Cannot convert "'+Yg(I)+'" to '+this.name);if(I<C||I>e)throw new TypeError('Passing a number "'+Yg(I)+'" from JS side to C/C++ side to an argument of type "'+g+'", which is outside the valid range ['+C+", "+e+"]!");return a?I>>>0:0|I},argPackAdvance:8,readValueFromPointer:Ng(g,i,0!==C),destructorFunction:null})},__embind_register_memory_view:function(A,g,I){var C=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][g];function e(A){var g=H,I=g[A>>=2],e=g[A+1];return new C(g.buffer,e,I)}zA(A,{name:I=DA(I),fromWireType:e,argPackAdvance:8,readValueFromPointer:e},{ignoreDuplicateRegistrations:!0})},__embind_register_std_string:function(A,g){zA(A,{name:g=DA(g),fromWireType:function(A){for(var g=H[A>>2],I=new Array(g),C=0;C<g;++C)I[C]=String.fromCharCode(p[A+4+C]);return AI(A),I.join("")},toWireType:function(A,g){function I(A,g){return A[g]}var C;g instanceof ArrayBuffer&&(g=new Uint8Array(g)),g instanceof Uint8Array||g instanceof Uint8ClampedArray||g instanceof Int8Array?C=I:"string"==typeof g?C=function(A,g){return A.charCodeAt(g)}:TA("Cannot pass non-string to std::string");var e=g.length,i=gI(4+e);H[i>>2]=e;for(var t=0;t<e;++t){var o=C(g,t);o>255&&(AI(i),TA("String has UTF-16 code units that do not fit in 8 bits")),p[i+4+t]=o}return null!==A&&A.push(AI,i),i},argPackAdvance:8,readValueFromPointer:HA,destructorFunction:function(A){AI(A)}})},__embind_register_std_wstring:function(A,g,I){var C,e;I=DA(I),2===g?(C=function(){return F},e=1):4===g&&(C=function(){return H},e=2),zA(A,{name:I,fromWireType:function(A){for(var g=C(),I=H[A>>2],i=new Array(I),t=A+4>>e,o=0;o<I;++o)i[o]=String.fromCharCode(g[t+o]);return AI(A),i.join("")},toWireType:function(A,I){var i=C(),t=I.length,o=gI(4+t*g);H[o>>2]=t;for(var a=o+4>>e,B=0;B<t;++B)i[a+B]=I.charCodeAt(B);return null!==A&&A.push(AI,o),o},argPackAdvance:8,readValueFromPointer:HA,destructorFunction:function(A){AI(A)}})},__embind_register_value_object:function(A,g,I,C,e,i){FA[A]={name:DA(g),rawConstructor:Eg(I,C),rawDestructor:Eg(e,i),fields:[]}},__embind_register_value_object_field:function(A,g,I,C,e,i,t,o,a,B){FA[A].fields.push({fieldName:DA(g),getterReturnType:I,getter:Eg(C,e),getterContext:i,setterArgumentType:t,setter:Eg(o,a),setterContext:B})},__embind_register_void:function(A,g){zA(A,{isVoid:!0,name:g=DA(g),argPackAdvance:0,fromWireType:function(){},toWireType:function(A,g){}})},_abort:function(){Module.abort()},_emscripten_memcpy_big:function(A,g,I){return p.set(p.subarray(g,g+I),A),A},_getenv:function A(g){return 0===g?0:(g=m(g),Jg.hasOwnProperty(g)?(A.ret&&AI(A.ret),A.ret=(I=Jg[g],C=Q(I)+1,(e=gI(C))&&y(I,W,e,C),e)):0);var I,C,e},_getgrnam:function(){Module.printErr("missing function: getgrnam"),tI(-1)},_getpwnam:function(){throw"getpwnam: TODO"},_jsClose:function(){return i.close.apply(null,arguments)},_jsCreate:function(A){return i.create.call(null,V(A))},_jsOpen:function(A){return i.open.call(null,V(A))},_jsRead:function(){return i.read.apply(null,arguments)},_jsSeek:function(A,g,I){return i.seek.call(null,A,g,u(I))},_jsTell:function(){return i.tell.apply(null,arguments)},_jsWrite:function(){return i.write.apply(null,arguments)},_llvm_eh_typeid_for:function(A){return A},_localtime:function(A){return function(A,g){kg();var I=new Date(1e3*w[A>>2]);w[g>>2]=I.getSeconds(),w[g+4>>2]=I.getMinutes(),w[g+8>>2]=I.getHours(),w[g+12>>2]=I.getDate(),w[g+16>>2]=I.getMonth(),w[g+20>>2]=I.getFullYear()-1900,w[g+24>>2]=I.getDay();var C=new Date(I.getFullYear(),0,1),e=(I.getTime()-C.getTime())/864e5|0;w[g+28>>2]=e,w[g+36>>2]=-60*I.getTimezoneOffset();var i=new Date(2e3,6,1).getTimezoneOffset(),t=C.getTimezoneOffset(),o=0|(i!=t&&I.getTimezoneOffset()==Math.min(t,i));w[g+32>>2]=o;var a=w[Lg+(o?4:0)>>2];return w[g+40>>2]=a,g}(A,fg)},_mktime:function(A){kg();var g=new Date(w[A+20>>2]+1900,w[A+16>>2],w[A+12>>2],w[A+8>>2],w[A+4>>2],w[A>>2],0),I=w[A+32>>2],C=g.getTimezoneOffset(),e=new Date(g.getFullYear(),0,1),i=new Date(2e3,6,1).getTimezoneOffset(),t=e.getTimezoneOffset(),o=Math.min(t,i);if(I<0)w[A+32>>2]=Number(i!=t&&o==C);else if(I>0!=(o==C)){var a=Math.max(t,i),B=I>0?o:a;g.setTime(g.getTime()+6e4*(B-C))}w[A+24>>2]=g.getDay();var s=(g.getTime()-e.getTime())/864e5|0;return w[A+28>>2]=s,g.getTime()/1e3|0},_pthread_getspecific:function(A){return Dg[A]||0},_pthread_key_create:function(A,g){return 0==A?mA.EINVAL:(w[A>>2]=xg,Dg[xg]=0,xg++,0)},_pthread_once:function A(g,I){A.seen||(A.seen={}),g in A.seen||(Module.dynCall_v(I),A.seen[g]=1)},_pthread_setspecific:function(A,g){return A in Dg?(Dg[A]=g,0):mA.EINVAL},_time:function(A){var g=Date.now()/1e3|0;return A&&(w[A>>2]=g),g},DYNAMICTOP_PTR:L,STACKTOP:J};var zg=Module.asm(Module.asmGlobalArg,Module.asmLibraryArg,A);Module.asm=zg;var Pg=Module.__GLOBAL__sub_I_bind_cpp=function(){return Module.asm.__GLOBAL__sub_I_bind_cpp.apply(null,arguments)},Og=Module.__GLOBAL__sub_I_bridge_cpp=function(){return Module.asm.__GLOBAL__sub_I_bridge_cpp.apply(null,arguments)},jg=Module.__GLOBAL__sub_I_crc_cpp=function(){return Module.asm.__GLOBAL__sub_I_crc_cpp.apply(null,arguments)},qg=Module.__GLOBAL__sub_I_global_cpp=function(){return Module.asm.__GLOBAL__sub_I_global_cpp.apply(null,arguments)};Module.___cxa_can_catch=function(){return Module.asm.___cxa_can_catch.apply(null,arguments)},Module.___cxa_is_pointer_type=function(){return Module.asm.___cxa_is_pointer_type.apply(null,arguments)},Module.___errno_location=function(){return Module.asm.___errno_location.apply(null,arguments)};var _g=Module.___getTypeName=function(){return Module.asm.___getTypeName.apply(null,arguments)},$g=Module._emscripten_replace_memory=function(){return Module.asm._emscripten_replace_memory.apply(null,arguments)},AI=Module._free=function(){return Module.asm._free.apply(null,arguments)},gI=Module._malloc=function(){return Module.asm._malloc.apply(null,arguments)},II=Module.setTempRet0=function(){return Module.asm.setTempRet0.apply(null,arguments)};Module.setThrew=function(){return Module.asm.setThrew.apply(null,arguments)};var CI=Module.stackAlloc=function(){return Module.asm.stackAlloc.apply(null,arguments)};function eI(A){this.name="ExitStatus",this.message="Program terminated with exit("+A+")",this.status=A}function iI(A){function g(){Module.calledRun||(Module.calledRun=!0,r||(IA||(IA=!0,j(_)),j($),Module.onRuntimeInitialized&&Module.onRuntimeInitialized(),function(){if(Module.postRun)for("function"==typeof Module.postRun&&(Module.postRun=[Module.postRun]);Module.postRun.length;)A=Module.postRun.shift(),gA.unshift(A);var A;j(gA)}()))}A=A||Module.arguments,aA>0||(!function(){if(Module.preRun)for("function"==typeof Module.preRun&&(Module.preRun=[Module.preRun]);Module.preRun.length;)A=Module.preRun.shift(),q.unshift(A);var A;j(q)}(),aA>0||Module.calledRun||(Module.setStatus?(Module.setStatus("Running..."),setTimeout((function(){setTimeout((function(){Module.setStatus("")}),1),g()}),1)):g()))}function tI(A){throw Module.onAbort&&Module.onAbort(A),void 0!==A?(Module.print(A),Module.printErr(A),A=JSON.stringify(A)):A="",r=!0,"abort("+A+"). Build with -s ASSERTIONS=1 for more info."}if(Module.dynCall_dii=function(){return Module.asm.dynCall_dii.apply(null,arguments)},Module.dynCall_i=function(){return Module.asm.dynCall_i.apply(null,arguments)},Module.dynCall_ii=function(){return Module.asm.dynCall_ii.apply(null,arguments)},Module.dynCall_iii=function(){return Module.asm.dynCall_iii.apply(null,arguments)},Module.dynCall_iiii=function(){return Module.asm.dynCall_iiii.apply(null,arguments)},Module.dynCall_iiiii=function(){return Module.asm.dynCall_iiiii.apply(null,arguments)},Module.dynCall_iiiiii=function(){return Module.asm.dynCall_iiiiii.apply(null,arguments)},Module.dynCall_iiiiiii=function(){return Module.asm.dynCall_iiiiiii.apply(null,arguments)},Module.dynCall_iiiiiiiiii=function(){return Module.asm.dynCall_iiiiiiiiii.apply(null,arguments)},Module.dynCall_iiiiiijii=function(){return Module.asm.dynCall_iiiiiijii.apply(null,arguments)},Module.dynCall_ijj=function(){return Module.asm.dynCall_ijj.apply(null,arguments)},Module.dynCall_ji=function(){return Module.asm.dynCall_ji.apply(null,arguments)},Module.dynCall_v=function(){return Module.asm.dynCall_v.apply(null,arguments)},Module.dynCall_vi=function(){return Module.asm.dynCall_vi.apply(null,arguments)},Module.dynCall_vii=function(){return Module.asm.dynCall_vii.apply(null,arguments)},Module.dynCall_viid=function(){return Module.asm.dynCall_viid.apply(null,arguments)},Module.dynCall_viii=function(){return Module.asm.dynCall_viii.apply(null,arguments)},Module.dynCall_viiii=function(){return Module.asm.dynCall_viiii.apply(null,arguments)},Module.dynCall_viiiii=function(){return Module.asm.dynCall_viiiii.apply(null,arguments)},Module.dynCall_viiiiii=function(){return Module.asm.dynCall_viiiiii.apply(null,arguments)},Module.dynCall_viiiiiiiii=function(){return Module.asm.dynCall_viiiiiiiii.apply(null,arguments)},Module.dynCall_viiiiiiiiii=function(){return Module.asm.dynCall_viiiiiiiiii.apply(null,arguments)},Module.dynCall_vij=function(){return Module.asm.dynCall_vij.apply(null,arguments)},Module.dynCall_viji=function(){return Module.asm.dynCall_viji.apply(null,arguments)},Module.asm=zg,eI.prototype=new Error,eI.prototype.constructor=eI,BA=function A(){Module.calledRun||iI(),Module.calledRun||(BA=A)},Module.run=iI,Module.exit=function(A,g){g&&Module.noExitRuntime&&0===A||(Module.noExitRuntime||(r=!0,J=undefined,j(AA),Module.onExit&&Module.onExit(A)),B&&process.exit(A),Module.quit(A,new eI(A)))},Module.abort=tI,Module.preInit)for("function"==typeof Module.preInit&&(Module.preInit=[Module.preInit]);Module.preInit.length>0;)Module.preInit.pop()();return Module.noExitRuntime=!0,iI(),g};function getExtractor(A){return fetch(new Request(A)).then((A=>{if(A.ok)return A.arrayBuffer();throw new Error("404 Error: File not found.")})).then((A=>unpackBridge.createExtractorFromData(A)))}function extract({resourceId:A,url:g}){return new Promise((function(A,I){if(!unpackBridge)throw new Error("unpackBridge not detected");if(!unpack)throw new Error("unpack not detected");getExtractor(g).then((g=>{A(g.extractAll())}),(A=>{I(A)}))}))}function handleMessage$1(A,g){if("init"==A.type)unpack=initunpack(A.buffer),unpack.onRuntimeInitialized=()=>{g({type:"WASM_LOADED"})};else if("fetch"==A.type)extract(A).then((I=>{returnData(A,I,g)}),(I=>{const C={taskId:A.taskId,type:"ERROR",resourceId:A.resourceId,url:A.url};g(C)}));else if("unpack"==A.type){const{buffer:I}=A;if(!unpackBridge)throw new Error("unpackBridge not detected");if(!unpack)throw new Error("unpack not detected");const C=unpackBridge.createExtractorFromData(I).extractAll();returnData(A,C,g)}}function returnData(A,g,I){const[C,e]=g;if("FAIL"==C.state){return void I({taskId:A.taskId,type:"ERROR",reason:C.reason,msg:C.msg,resourceId:A.resourceId,url:A.url})}const i={taskId:A.taskId,type:"FINISHED",resourceId:A.resourceId,entries:{}},t=[];if(e&&e.files)for(const A of e.files)i.entries[A.fileHeader.name]=A.extract[1],t.push(A.extract[1].buffer);I(i,t)}globalThis.onmessage=function(A){handleMessage$1(A.data,self.postMessage)};let taskCounter=0;class WorkerPool extends EventEmitter{poolSize=Math.max(1,SystemDesc.hardwareConcurrency-1);workers=[];workerTaskCount=[];taskPromiseResolves={};taskQueue=[];availableWorkers=[];terminationTimeouts=[];terminateWorkersWhenFree=!0;terminationLatency=2e3;constructor(A){super(),this.terminateWorkersWhenFree=A}addTask(A,g){return this.addTaskCallback((()=>({taskData:A,transferables:g})))}addTaskCallback(A){taskCounter++;const g=taskCounter;return new Promise((async I=>{this.taskPromiseResolves[g]=I,this.taskQueue.push({taskId:g,dataFactory:A}),this.availableWorkers.length>0?this.consumeTask():this.workers.length<this.poolSize&&(await this.addWorker(),this.consumeTask())}))}async consumeTask(){const A=this.availableWorkers.pop();if(this.workerTaskCount[A]>0)return;if(0==this.taskQueue.length)return void(this.terminateWorkersWhenFree&&this.scheduleWorkerTermination(A));if(-1!=this.terminationTimeouts[A]?(clearTimeout(this.terminationTimeouts[A]),this.terminationTimeouts[A]=-1):this.workers[A]||await this.allocWorker(A),0==this.taskQueue.length)return void(this.terminateWorkersWhenFree&&this.scheduleWorkerTermination(A));const g=this.taskQueue.pop(),{taskData:I,transferables:C}=g.dataFactory(A);I.taskId=g.taskId,this.workerTaskCount[A]++,this.workers[A].postMessage(I,C)}addWorker(){const A=this.workers.length;return this.workers.push(null),this.allocWorker(A)}allocWorker(A){return new Promise((g=>{this.constructWorker().then((I=>{I.onmessage=g=>{if(g.data.taskId in this.taskPromiseResolves){const I=g.data.taskId;if(delete g.data.taskId,this.taskPromiseResolves[I](g.data),delete this.taskPromiseResolves[I],this.workerTaskCount[A]--,this.workerTaskCount[A]>0)return;-1==this.availableWorkers.indexOf(A)&&this.availableWorkers.push(A),this.taskQueue.length>0?this.consumeTask():this.terminateWorkersWhenFree&&this.scheduleWorkerTermination(A)}else g.data.eventName&&(g.data.workerId=A,this.emit(g.data.eventName,g.data))},this.workers[A]=I,this.terminationTimeouts[A]=-1,this.workerTaskCount[A]=0,this.availableWorkers.push(A),g()}))}))}scheduleWorkerTermination(A){this.terminationTimeouts[A]=setTimeout((()=>{this.terminateWorker(A),this.terminationTimeouts[A]=-1}),this.terminationLatency)}terminateWorker(A){this.workers[A].terminate(),this.workers[A]=null}messageWorker(A,g){taskCounter++;const I=taskCounter;return new Promise((C=>{this.taskPromiseResolves[I]=C,g.taskId=I,this.workers[A].postMessage(g)}))}}function decodeBase64(A,g){var I=atob(A);if(g){for(var C=new Uint8Array(I.length),e=0,i=I.length;e<i;++e)C[e]=I.charCodeAt(e);return String.fromCharCode.apply(null,new Uint16Array(C.buffer))}return I}function createURL(A,g,I){var C=void 0===g?null:g,e=decodeBase64(A,void 0!==I&&I),i=e.indexOf("\n",10)+1,t=e.substring(i)+(C?"//# sourceMappingURL="+C:""),o=new Blob([t],{type:"application/javascript"});return URL.createObjectURL(o)}function createBase64WorkerFactory(A,g,I){var C;return function(e){return C=C||createURL(A,g,I),new Worker(C,e)}}var WorkerFactory$2=createBase64WorkerFactory("Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwp2YXIgd29ya2VyX2NvZGUgPSAoZnVuY3Rpb24gKGV4cG9ydHMpIHsKICAndXNlIHN0cmljdCc7CgogIC8vIDwhLS0gcHJldHRpZXItaWdub3JlLXN0YXJ0IC0tPgogIC8qIGVzbGludC1kaXNhYmxlIHJlcXVpcmUtanNkb2MgKi8KCiAgY29uc3QgTW9kdWxlID0ge307CgogIGNvbnN0IFdvcmtlclNjb3BlID0ge307CgogIC8vLS0tLS0tLS0tLS0tLS0tLS0tLS11bnBhY2tCcmlkZ2UuanMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgIShmdW5jdGlvbiAodCwgZSkgewogICAgLy8gVGhlIGZvbGxvd2luZyBjb2RlIGhhcyBiZWVuIF9jYXJlZnVsbHlfIG1vZGlmaWVkIGJ5IGhhbmQuCiAgICAvLyBUaGVyZSB3ZXJlIHZhcmlvdXMgY2FzZXMgZm9yIGluIHdoYXQgY29udGV4dCB0aGUgY29kZSBtaWdodAogICAgLy8gYmUgcnVuLCBhbmQgSSByZW1vdmVkIGFsbCBidXQgdGhlIHdlYndvcmtlciBjYXNlLgogICAgLy8gVGhlcmUgd2FzIGNvZGUgdG8gaGFuZGxlIGxvYWRpbmcgaW4gYSBub2RlSlMgY29udGV4dCwgdGhhdCB0cmllZCB0byBpbXBvcnQoImZzIikKICAgIC8vIFdlYlBhY2sga2VwdHMgdHJpcHBpbmcgdXAgb24gdGhhdCBjb2RlIGluIGl0cyBzdGF0aWMgYW5hbHlzaXMgb2YgdGhlIGNvZGUsIHNvCiAgICAvLyBJIGNhcmVmdWxseSByZW1vdmVkIGl0LgogICAgdC51bnBhY2tCcmlkZ2UgPSBlKHQuZnMpOwogIH0pKFdvcmtlclNjb3BlLCBmdW5jdGlvbiAodCkgewogICAgcmV0dXJuIChmdW5jdGlvbiAodCkgewogICAgICB2YXIgZSA9IHt9OwogICAgICBmdW5jdGlvbiByKG4pIHsKICAgICAgICBpZiAoZVtuXSkgcmV0dXJuIGVbbl0uZXhwb3J0cwogICAgICAgIHZhciBpID0gKGVbbl0gPSB7IGk6IG4sIGw6ICExLCBleHBvcnRzOiB7fSB9KTsKICAgICAgICByZXR1cm4gdFtuXS5jYWxsKGkuZXhwb3J0cywgaSwgaS5leHBvcnRzLCByKSwgKGkubCA9ICEwKSwgaS5leHBvcnRzCiAgICAgIH0KICAgICAgcmV0dXJuICgKICAgICAgICAoci5tID0gdCksCiAgICAgICAgKHIuYyA9IGUpLAogICAgICAgIChyLmQgPSBmdW5jdGlvbiAodCwgZSwgbikgewogICAgICAgICAgci5vKHQsIGUpIHx8IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LCBlLCB7IGVudW1lcmFibGU6ICEwLCBnZXQ6IG4gfSk7CiAgICAgICAgfSksCiAgICAgICAgKHIuciA9IGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAndW5kZWZpbmVkJyAhPSB0eXBlb2YgU3ltYm9sICYmCiAgICAgICAgICAgIFN5bWJvbC50b1N0cmluZ1RhZyAmJgogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodCwgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KSwKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHQsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogITAgfSk7CiAgICAgICAgfSksCiAgICAgICAgKHIudCA9IGZ1bmN0aW9uICh0LCBlKSB7CiAgICAgICAgICBpZiAoKDEgJiBlICYmICh0ID0gcih0KSksIDggJiBlKSkgcmV0dXJuIHQKICAgICAgICAgIGlmICg0ICYgZSAmJiAnb2JqZWN0JyA9PSB0eXBlb2YgdCAmJiB0ICYmIHQuX19lc01vZHVsZSkgcmV0dXJuIHQKICAgICAgICAgIHZhciBuID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgIGlmICgoci5yKG4pLCBPYmplY3QuZGVmaW5lUHJvcGVydHkobiwgJ2RlZmF1bHQnLCB7IGVudW1lcmFibGU6ICEwLCB2YWx1ZTogdCB9KSwgMiAmIGUgJiYgJ3N0cmluZycgIT0gdHlwZW9mIHQpKQogICAgICAgICAgICBmb3IgKHZhciBpIGluIHQpCiAgICAgICAgICAgICAgci5kKAogICAgICAgICAgICAgICAgbiwKICAgICAgICAgICAgICAgIGksCiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoZSkgewogICAgICAgICAgICAgICAgICByZXR1cm4gdFtlXQogICAgICAgICAgICAgICAgfS5iaW5kKG51bGwsIGkpCiAgICAgICAgICAgICAgKTsKICAgICAgICAgIHJldHVybiBuCiAgICAgICAgfSksCiAgICAgICAgKHIubiA9IGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICB2YXIgZSA9CiAgICAgICAgICAgIHQgJiYgdC5fX2VzTW9kdWxlCiAgICAgICAgICAgICAgPyBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgIHJldHVybiB0LmRlZmF1bHQKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICA6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuIHQKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICByZXR1cm4gci5kKGUsICdhJywgZSksIGUKICAgICAgICB9KSwKICAgICAgICAoci5vID0gZnVuY3Rpb24gKHQsIGUpIHsKICAgICAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodCwgZSkKICAgICAgICB9KSwKICAgICAgICAoci5wID0gJycpLAogICAgICAgIHIoKHIucyA9IDIpKQogICAgICApCiAgICB9KShbCiAgICAgIGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogITAgfSk7CiAgICAgICAgY29uc3QgbiA9IHIoMSksCiAgICAgICAgICBpID0gewogICAgICAgICAgICAwOiAnRVJBUl9TVUNDRVNTJywKICAgICAgICAgICAgMTA6ICdFUkFSX0VORF9BUkNISVZFJywKICAgICAgICAgICAgMTE6ICdFUkFSX05PX01FTU9SWScsCiAgICAgICAgICAgIDEyOiAnRVJBUl9CQURfREFUQScsCiAgICAgICAgICAgIDEzOiAnRVJBUl9CQURfQVJDSElWRScsCiAgICAgICAgICAgIDE0OiAnRVJBUl9VTktOT1dOX0ZPUk1BVCcsCiAgICAgICAgICAgIDE1OiAnRVJBUl9FT1BFTicsCiAgICAgICAgICAgIDE2OiAnRVJBUl9FQ1JFQVRFJywKICAgICAgICAgICAgMTc6ICdFUkFSX0VDTE9TRScsCiAgICAgICAgICAgIDE4OiAnRVJBUl9FUkVBRCcsCiAgICAgICAgICAgIDE5OiAnRVJBUl9FV1JJVEUnLAogICAgICAgICAgICAyMDogJ0VSQVJfU01BTExfQlVGJywKICAgICAgICAgICAgMjE6ICdFUkFSX1VOS05PV04nLAogICAgICAgICAgICAyMjogJ0VSQVJfTUlTU0lOR19QQVNTV09SRCcsCiAgICAgICAgICAgIDIzOiAnRVJBUl9FUkVGRVJFTkNFJywKICAgICAgICAgICAgMjQ6ICdFUkFSX0JBRF9QQVNTV09SRCcsCiAgICAgICAgICB9LAogICAgICAgICAgbyA9IHsKICAgICAgICAgICAgMDogJ1N1Y2Nlc3MnLAogICAgICAgICAgICAxMTogJ05vdCBlbm91Z2ggbWVtb3J5JywKICAgICAgICAgICAgMTI6ICdBcmNoaXZlIGhlYWRlciBvciBkYXRhIGFyZSBkYW1hZ2VkJywKICAgICAgICAgICAgMTM6ICdGaWxlIGlzIG5vdCBSQVIgYXJjaGl2ZScsCiAgICAgICAgICAgIDE0OiAnVW5rbm93biBhcmNoaXZlIGZvcm1hdCcsCiAgICAgICAgICAgIDE1OiAnRmlsZSBvcGVuIGVycm9yJywKICAgICAgICAgICAgMTY6ICdGaWxlIGNyZWF0ZSBlcnJvcicsCiAgICAgICAgICAgIDE3OiAnRmlsZSBjbG9zZSBlcnJvcicsCiAgICAgICAgICAgIDE4OiAnRmlsZSByZWFkIGVycm9yJywKICAgICAgICAgICAgMTk6ICdGaWxlIHdyaXRlIGVycm9yJywKICAgICAgICAgICAgMjA6ICdCdWZmZXIgZm9yIGFyY2hpdmUgY29tbWVudCBpcyB0b28gc21hbGwsIGNvbW1lbnQgdHJ1bmNhdGVkJywKICAgICAgICAgICAgMjE6ICdVbmtub3duIGVycm9yJywKICAgICAgICAgICAgMjI6ICdQYXNzd29yZCBmb3IgZW5jcnlwdGVkIGZpbGUgb3IgaGVhZGVyIGlzIG5vdCBzcGVjaWZpZWQnLAogICAgICAgICAgICAyMzogJ0Nhbm5vdCBvcGVuIGZpbGUgc291cmNlIGZvciByZWZlcmVuY2UgcmVjb3JkJywKICAgICAgICAgICAgMjQ6ICdXcm9uZyBwYXNzd29yZCBpcyBzcGVjaWZpZWQnLAogICAgICAgICAgfTsKICAgICAgICBjbGFzcyBzIHsKICAgICAgICAgIGNvbnN0cnVjdG9yKHQgPSAnJykgewogICh0aGlzLl9wYXNzd29yZCA9IHQpLCAodGhpcy5fYXJjaGl2ZSA9IG51bGwpOwogICAgICAgICAgfQogICAgICAgICAgZ2V0RmlsZUxpc3QoKSB7CiAgICAgICAgICAgIGxldCB0LAogICAgICAgICAgICAgIFtlLCByXSA9IHRoaXMub3BlbkFyYyghMCk7CiAgICAgICAgICAgIGlmICgnU1VDQ0VTUycgIT09IGUuc3RhdGUpIHQgPSBbZSwgbnVsbF07CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgIGxldCBlLAogICAgICAgICAgICAgICAgbiwKICAgICAgICAgICAgICAgIGkgPSBbXTsKICAgICAgICAgICAgICBmb3IgKDsgKFtlLCBuXSA9IHRoaXMucHJvY2Vzc05leHRGaWxlKCgpID0+ICEwKSksICdTVUNDRVNTJyA9PT0gZS5zdGF0ZTsgKSBpLnB1c2gobi5maWxlSGVhZGVyKTsKICAgICAgICAgICAgICB0ID0gJ0VSQVJfRU5EX0FSQ0hJVkUnICE9PSBlLnJlYXNvbiA/IFtlLCBudWxsXSA6IFt7IHN0YXRlOiAnU1VDQ0VTUycgfSwgeyBhcmNIZWFkZXI6IHIsIGZpbGVIZWFkZXJzOiBpIH1dOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0aGlzLmNsb3NlQXJjKCksIHQKICAgICAgICAgIH0KICAgICAgICAgIGV4dHJhY3RBbGwoKSB7CiAgICAgICAgICAgIGxldCB0LAogICAgICAgICAgICAgIFtlLCByXSA9IHRoaXMub3BlbkFyYyghMSk7CiAgICAgICAgICAgIGlmICgnU1VDQ0VTUycgIT09IGUuc3RhdGUpIHQgPSBbZSwgbnVsbF07CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgIGxldCBlLAogICAgICAgICAgICAgICAgbiwKICAgICAgICAgICAgICAgIGkgPSBbXTsKICAgICAgICAgICAgICBmb3IgKDsgKFtlLCBuXSA9IHRoaXMucHJvY2Vzc05leHRGaWxlKCgpID0+ICExKSksICdTVUNDRVNTJyA9PT0gZS5zdGF0ZTsgKSBpLnB1c2gobik7CiAgICAgICAgICAgICAgdCA9ICdFUkFSX0VORF9BUkNISVZFJyAhPT0gZS5yZWFzb24gPyBbZSwgbnVsbF0gOiBbeyBzdGF0ZTogJ1NVQ0NFU1MnIH0sIHsgYXJjSGVhZGVyOiByLCBmaWxlczogaSB9XTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhpcy5jbG9zZUFyYygpLCB0CiAgICAgICAgICB9CiAgICAgICAgICBleHRyYWN0RmlsZXModCwgZSkgewogICAgICAgICAgICBsZXQgciwKICAgICAgICAgICAgICBbbiwgaV0gPSB0aGlzLm9wZW5BcmMoITEsIGUpLAogICAgICAgICAgICAgIG8gPSB7fTsKICAgICAgICAgICAgZm9yIChsZXQgZSA9IDA7IGUgPCB0Lmxlbmd0aDsgKytlKSBvW3RbZV1dID0gZTsKICAgICAgICAgICAgaWYgKCdTVUNDRVNTJyAhPT0gbi5zdGF0ZSkgciA9IFtuLCBudWxsXTsKICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgbGV0IGUsCiAgICAgICAgICAgICAgICBuLAogICAgICAgICAgICAgICAgcyA9IEFycmF5KHQubGVuZ3RoKS5maWxsKG51bGwpLAogICAgICAgICAgICAgICAgdSA9IDA7CiAgICAgICAgICAgICAgZm9yICg7OykgewogICAgICAgICAgICAgICAgbGV0IHIgPSAhMSwKICAgICAgICAgICAgICAgICAgaSA9IG51bGw7CiAgICAgICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICAgICgoW2UsIG5dID0gdGhpcy5wcm9jZXNzTmV4dEZpbGUoKHQpID0+ICh0IGluIG8gPyAoKGkgPSBvW3RdKSwgITEpIDogKChyID0gITApLCAhMCkpKSksCiAgICAgICAgICAgICAgICAgICdTVUNDRVNTJyAhPT0gZS5zdGF0ZSkKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgICAgIGlmICghciAmJiAoKHNbaV0gPSBuKSwgKyt1ID09PSB0Lmxlbmd0aCkpIHsKICAgICAgICAgICAgICAgICAgZS5yZWFzb24gPSAnRVJBUl9FTkRfQVJDSElWRSc7CiAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHIgPSAnRVJBUl9FTkRfQVJDSElWRScgIT09IGUucmVhc29uID8gW2UsIG51bGxdIDogW3sgc3RhdGU6ICdTVUNDRVNTJyB9LCB7IGFyY0hlYWRlcjogaSwgZmlsZXM6IHMgfV07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2xvc2VBcmMoKSwgcgogICAgICAgICAgfQogICAgICAgICAgZmlsZUNyZWF0ZWQodCkge30KICAgICAgICAgIGNsb3NlKHQpIHsKICAgICAgICAgICAgdGhpcy5fbGFzdEZpbGVDb250ZW50ID0gdGhpcy5jbG9zZUZpbGUodCk7CiAgICAgICAgICB9CiAgICAgICAgICBvcGVuQXJjKHQsIGUpIHsKICAobi5FeHQuY3VycmVudCA9IHRoaXMpLCAodGhpcy5fYXJjaGl2ZSA9IG5ldyB1bnBhY2suUmFyQXJjaGl2ZSgpKTsKICAgICAgICAgICAgbGV0IHIsCiAgICAgICAgICAgICAgaSA9IHRoaXMuX2FyY2hpdmUub3Blbih0aGlzLl9maWxlUGF0aCwgZSB8fCB0aGlzLl9wYXNzd29yZCwgdCk7CiAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgKHIgPQogICAgICAgICAgICAgICAgMCAhPT0gaS5zdGF0ZS5lcnJDb2RlCiAgICAgICAgICAgICAgICAgID8gW3RoaXMuZ2V0RmFpbEluZm8oaS5zdGF0ZS5lcnJDb2RlLCBpLnN0YXRlLmVyclR5cGUpLCBudWxsXQogICAgICAgICAgICAgICAgICA6IFsKICAgICAgICAgICAgICAgICAgICAgIHsgc3RhdGU6ICdTVUNDRVNTJyB9LAogICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBjb21tZW50OiBpLmNvbW1lbnQsCiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgdm9sdW1lOiAwICE9ICgxICYgaS5mbGFncyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jazogMCAhPSAoNCAmIGkuZmxhZ3MpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHNvbGlkOiAwICE9ICg4ICYgaS5mbGFncyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0aEluZm86IDAgIT0gKDMyICYgaS5mbGFncyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb3ZlcnlSZWNvcmQ6IDAgIT0gKDY0ICYgaS5mbGFncyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyRW5jcnlwdGVkOiAwICE9ICgxMjggJiBpLmZsYWdzKSwKICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgXSksCiAgICAgICAgICAgICAgKG4uRXh0LmN1cnJlbnQgPSBudWxsKSwKICAgICAgICAgICAgICByCiAgICAgICAgICAgICkKICAgICAgICAgIH0KICAgICAgICAgIHByb2Nlc3NOZXh0RmlsZSh0KSB7CiAgICAgICAgICAgIGxldCBlOwogICAgICAgICAgICBuLkV4dC5jdXJyZW50ID0gdGhpczsKICAgICAgICAgICAgbGV0IHIgPSB0aGlzLl9hcmNoaXZlLmdldEZpbGVIZWFkZXIoKSwKICAgICAgICAgICAgICBpID0gW3sgc3RhdGU6ICdTVUNDRVNTJyB9LCBudWxsXTsKICAgICAgICAgICAgaWYgKDAgPT09IHIuc3RhdGUuZXJyQ29kZSkgewogICAgICAgICAgICAgIGxldCBlID0gdChyLm5hbWUpOwogICAgICAgICAgICAgIHRoaXMuX2xhc3RGaWxlQ29udGVudCA9IG51bGw7CiAgICAgICAgICAgICAgbGV0IG4gPSB0aGlzLl9hcmNoaXZlLnJlYWRGaWxlKGUpOwogICAgICAgICAgICAgIDAgPT09IG4uZXJyQ29kZSB8fAogICAgICAgICAgICAgICAgZSB8fAogICAgICAgICAgICAgICAgKChpWzBdID0gdGhpcy5nZXRGYWlsSW5mbyhuLmVyckNvZGUsIG4uZXJyVHlwZSkpLAogICAgICAgICAgICAgICAgMjIgPT09IG4uZXJyQ29kZSA/IChuID0gdGhpcy5fYXJjaGl2ZS5yZWFkRmlsZSghMCkpIDogKG4uZXJyQ29kZSA9IDApKSwKICAgICAgICAgICAgICAgIDAgPT09IG4uZXJyQ29kZQogICAgICAgICAgICAgICAgICA/IChpWzFdID0gdGhpcy5fbGFzdEZpbGVDb250ZW50KQogICAgICAgICAgICAgICAgICA6ICgoci5zdGF0ZS5lcnJDb2RlID0gbi5lcnJDb2RlKSwgKHIuc3RhdGUuZXJyVHlwZSA9IG4uZXJyVHlwZSkpLAogICAgICAgICAgICAgICAgKHRoaXMuX2xhc3RGaWxlQ29udGVudCA9IG51bGwpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgKGUgPQogICAgICAgICAgICAgICAgMCAhPT0gci5zdGF0ZS5lcnJDb2RlCiAgICAgICAgICAgICAgICAgID8gW3RoaXMuZ2V0RmFpbEluZm8oci5zdGF0ZS5lcnJDb2RlLCByLnN0YXRlLmVyclR5cGUpLCBudWxsXQogICAgICAgICAgICAgICAgICA6IFsKICAgICAgICAgICAgICAgICAgICAgIHsgc3RhdGU6ICdTVUNDRVNTJyB9LAogICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBmaWxlSGVhZGVyOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogci5uYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmNyeXB0ZWQ6IDAgIT0gKDQgJiByLmZsYWdzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvbGlkOiAwICE9ICgxNiAmIHIuZmxhZ3MpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0b3J5OiAwICE9ICgzMiAmIHIuZmxhZ3MpLAogICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja1NpemU6IHIucGFja1NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgdW5wU2l6ZTogci51bnBTaXplLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNyYzogci5jcmMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZTogKGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlID0gWzUsIDYsIDUsIDUsIDQsIDddOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHIgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IG4gb2YgZSkgci5wdXNoKHQgJiAoKDEgPDwgbikgLSAxKSksICh0ID4+PSBuKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBuID0gKHQpID0+ICh0IDwgMTAgPyAnMCcgKyB0IDogJycgKyB0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGAkezE5ODAgKyAociA9IHIucmV2ZXJzZSgpKVswXX0tJHtuKHJbMV0pfS0ke24oclsyXSl9YCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBUJHtuKHJbM10pfToke24ocls0XSl9OiR7bigyICogcls1XSl9LjAwMGAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICB9KShyLnRpbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHVucFZlcjogYCR7TWF0aC5mbG9vcihyLnVucFZlciAvIDEwKX0uJHtyLnVucFZlciAlIDEwfWAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kOiAoZnVuY3Rpb24gKHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsgNDg6ICdTdG9yaW5nJywgNDk6ICdGYXN0ZXN0JywgNTA6ICdGYXN0JywgNTE6ICdOb3JtYWwnLCA1MjogJ0dvb2QnLCA1MzogJ0Jlc3QnIH1bdF0gfHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1Vua25vd24nCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgfSkoci5tZXRob2QpLAogICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICBleHRyYWN0OiBpLAogICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICBdKSwKICAgICAgICAgICAgICAobi5FeHQuY3VycmVudCA9IG51bGwpLAogICAgICAgICAgICAgIGUKICAgICAgICAgICAgKQogICAgICAgICAgfQogICAgICAgICAgY2xvc2VBcmMoKSB7CiAgKG4uRXh0LmN1cnJlbnQgPSB0aGlzKSwgdGhpcy5fYXJjaGl2ZS5kZWxldGUoKSwgKG4uRXh0LmN1cnJlbnQgPSBudWxsKSwgKHRoaXMuX2FyY2hpdmUgPSBudWxsKTsKICAgICAgICAgIH0KICAgICAgICAgIGdldEZhaWxJbmZvKHQsIGUpIHsKICAgICAgICAgICAgcmV0dXJuIHsgc3RhdGU6ICdGQUlMJywgcmVhc29uOiBpW3RdLCBtc2c6IG9bdF0gfQogICAgICAgICAgfQogICAgICAgIH0KICAocy5fY3VycmVudCA9IG51bGwpLCAoZS5FeHRyYWN0b3IgPSBzKTsKICAgICAgfSwKICAgICAgZnVuY3Rpb24gKHQsIGUsIHIpIHsKICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZSwgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiAhMCB9KSwgKGUuRXh0ID0geyBjdXJyZW50OiBudWxsIH0pOwogICAgICB9LAogICAgICBmdW5jdGlvbiAodCwgZSwgcikgewogICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlLCAnX19lc01vZHVsZScsIHsgdmFsdWU6ICEwIH0pLAogICAgICAgICAgKGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAgIGZvciAodmFyIHIgaW4gdCkgZS5oYXNPd25Qcm9wZXJ0eShyKSB8fCAoZVtyXSA9IHRbcl0pOwogICAgICAgICAgfSkocigzKSk7CiAgICAgICAgdmFyIG4gPSByKDEpOwogICAgICAgIGUuRXh0ID0gbi5FeHQ7CiAgICAgIH0sCiAgICAgIGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogITAgfSk7CiAgICAgICAgY29uc3QgbiA9IHIoNCksCiAgICAgICAgICBpID0gcig2KQogICAgICAgIDsoZS5jcmVhdGVFeHRyYWN0b3JGcm9tRGF0YSA9IGZ1bmN0aW9uICh0LCBlID0gJycpIHsKICAgICAgICAgIHJldHVybiBuZXcgbi5EYXRhRXh0cmFjdG9yKHQsIGUpCiAgICAgICAgfSksCiAgICAgICAgICAoZS5jcmVhdGVFeHRyYWN0b3JGcm9tRmlsZSA9IGZ1bmN0aW9uICh0LCBlID0gJycsIHIgPSAnJykgewogICAgICAgICAgICByZXR1cm4gbmV3IGkuRmlsZUV4dHJhY3Rvcih0LCBlLCByKQogICAgICAgICAgfSk7CiAgICAgIH0sCiAgICAgIGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogITAgfSk7CiAgICAgICAgY29uc3QgbiA9IHIoNSksCiAgICAgICAgICBpID0gcigwKTsKICAgICAgICBlLkRhdGFFeHRyYWN0b3IgPSBjbGFzcyBleHRlbmRzIGkuRXh0cmFjdG9yIHsKICAgICAgICAgIGNvbnN0cnVjdG9yKHQsIGUpIHsKICAgICAgICAgICAgc3VwZXIoZSksICh0aGlzLmRhdGFGaWxlcyA9IHt9KSwgKHRoaXMuZGF0YUZpbGVNYXAgPSB7fSksICh0aGlzLmN1cnJlbnRGZCA9IDEpOwogICAgICAgICAgICBsZXQgciA9IHsgZmlsZTogbmV3IG4uRGF0YUZpbGUobmV3IFVpbnQ4QXJyYXkodCkpLCBmZDogdGhpcy5jdXJyZW50RmQrKyB9CiAgICAgICAgICAgIDsodGhpcy5fZmlsZVBhdGggPSAnX2RlZmF1bHRVbnJhckpTXy5yYXInKSwKICAgICAgICAgICAgICAodGhpcy5kYXRhRmlsZXNbdGhpcy5fZmlsZVBhdGhdID0gciksCiAgICAgICAgICAgICAgKHRoaXMuZGF0YUZpbGVNYXBbci5mZF0gPSB0aGlzLl9maWxlUGF0aCk7CiAgICAgICAgICB9CiAgICAgICAgICBvcGVuKHQpIHsKICAgICAgICAgICAgbGV0IGUgPSB0aGlzLmRhdGFGaWxlc1t0XTsKICAgICAgICAgICAgcmV0dXJuIGUgPyBlLmZkIDogMAogICAgICAgICAgfQogICAgICAgICAgY3JlYXRlKHQpIHsKICAgICAgICAgICAgbGV0IGUgPSB0aGlzLmN1cnJlbnRGZCsrOwogICAgICAgICAgICByZXR1cm4gKHRoaXMuZGF0YUZpbGVzW3RdID0geyBmaWxlOiBuZXcgbi5EYXRhRmlsZSgpLCBmZDogdGhpcy5jdXJyZW50RmQrKyB9KSwgKHRoaXMuZGF0YUZpbGVNYXBbZV0gPSB0KSwgZQogICAgICAgICAgfQogICAgICAgICAgY2xvc2VGaWxlKHQpIHsKICAgICAgICAgICAgbGV0IGUgPSB0aGlzLmRhdGFGaWxlc1t0aGlzLmRhdGFGaWxlTWFwW3RdXTsKICAgICAgICAgICAgaWYgKCFlKSByZXR1cm4gbnVsbAogICAgICAgICAgICBsZXQgciA9IGUuZmlsZS5yZWFkQWxsKCk7CiAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgMSAhPT0gdCA/IChkZWxldGUgdGhpcy5kYXRhRmlsZXNbdGhpcy5kYXRhRmlsZU1hcFt0XV0sIGRlbGV0ZSB0aGlzLmRhdGFGaWxlTWFwW3RdKSA6IGUuZmlsZS5zZWVrKDAsICdTRVQnKSwKICAgICAgICAgICAgICByCiAgICAgICAgICAgICkKICAgICAgICAgIH0KICAgICAgICAgIHJlYWQodCwgZSwgcikgewogICAgICAgICAgICBsZXQgbiA9IHRoaXMuZGF0YUZpbGVzW3RoaXMuZGF0YUZpbGVNYXBbdF1dOwogICAgICAgICAgICBpZiAoIW4pIHJldHVybiAtMQogICAgICAgICAgICBsZXQgaSA9IG4uZmlsZS5yZWFkKHIpOwogICAgICAgICAgICByZXR1cm4gbnVsbCA9PT0gaSA/IC0xIDogKHVucGFjay5IRUFQVTguc2V0KGksIGUpLCBpLmJ5dGVMZW5ndGgpCiAgICAgICAgICB9CiAgICAgICAgICB3cml0ZSh0LCBlLCByKSB7CiAgICAgICAgICAgIGxldCBuID0gdGhpcy5kYXRhRmlsZXNbdGhpcy5kYXRhRmlsZU1hcFt0XV07CiAgICAgICAgICAgIHJldHVybiAhIW4gJiYgKG4uZmlsZS53cml0ZSh1bnBhY2suSEVBUFU4LnNsaWNlKGUsIGUgKyByKSksICEwKQogICAgICAgICAgfQogICAgICAgICAgdGVsbCh0KSB7CiAgICAgICAgICAgIGxldCBlID0gdGhpcy5kYXRhRmlsZXNbdGhpcy5kYXRhRmlsZU1hcFt0XV07CiAgICAgICAgICAgIHJldHVybiBlID8gZS5maWxlLnRlbGwoKSA6IC0xCiAgICAgICAgICB9CiAgICAgICAgICBzZWVrKHQsIGUsIHIpIHsKICAgICAgICAgICAgbGV0IG4gPSB0aGlzLmRhdGFGaWxlc1t0aGlzLmRhdGFGaWxlTWFwW3RdXTsKICAgICAgICAgICAgcmV0dXJuICEhbiAmJiBuLmZpbGUuc2VlayhlLCByKQogICAgICAgICAgfQogICAgICAgIH07CiAgICAgIH0sCiAgICAgIGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogITAgfSk7CiAgICAgICAgZS5EYXRhRmlsZSA9IGNsYXNzIHsKICAgICAgICAgIGNvbnN0cnVjdG9yKHQpIHsKICAodGhpcy5idWZmZXJzID0gW10pLAogICAgICAgICAgICAgICh0aGlzLnBvcyA9IDApLAogICAgICAgICAgICAgICh0aGlzLnNpemUgPSAwKSwKICAgICAgICAgICAgICB0ICYmICh0aGlzLmJ1ZmZlcnMucHVzaCh0KSwgKHRoaXMuc2l6ZSA9IHQuYnl0ZUxlbmd0aCksICh0aGlzLnBvcyA9IDApKTsKICAgICAgICAgIH0KICAgICAgICAgIHJlYWQodCkgewogICAgICAgICAgICBpZiAoKHRoaXMuZmxhdHRlbigpLCB0ICsgdGhpcy5wb3MgPiB0aGlzLnNpemUpKSByZXR1cm4gbnVsbAogICAgICAgICAgICBsZXQgZSA9IHRoaXMucG9zOwogICAgICAgICAgICByZXR1cm4gKHRoaXMucG9zICs9IHQpLCB0aGlzLmJ1ZmZlcnNbMF0uc2xpY2UoZSwgdGhpcy5wb3MpCiAgICAgICAgICB9CiAgICAgICAgICByZWFkQWxsKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5mbGF0dGVuKCksIHRoaXMuYnVmZmVyc1swXQogICAgICAgICAgfQogICAgICAgICAgd3JpdGUodCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5idWZmZXJzLnB1c2godCksICh0aGlzLnNpemUgKz0gdC5ieXRlTGVuZ3RoKSwgKHRoaXMucG9zICs9IHQuYnl0ZUxlbmd0aCksICEwCiAgICAgICAgICB9CiAgICAgICAgICB0ZWxsKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5wb3MKICAgICAgICAgIH0KICAgICAgICAgIHNlZWsodCwgZSkgewogICAgICAgICAgICBsZXQgciA9IHRoaXMucG9zOwogICAgICAgICAgICByZXR1cm4gKAogICAgICAgICAgICAgICdTRVQnID09PSBlID8gKHIgPSB0KSA6ICdDVVInID09PSBlID8gKHIgKz0gdCkgOiAociA9IHRoaXMuc2l6ZSAtIHQpLAogICAgICAgICAgICAgICEociA8IDAgfHwgciA+IHRoaXMuc2l6ZSB8fCAoKHRoaXMucG9zID0gciksIDApKQogICAgICAgICAgICApCiAgICAgICAgICB9CiAgICAgICAgICBmbGF0dGVuKCkgewogICAgICAgICAgICBpZiAodGhpcy5idWZmZXJzLmxlbmd0aCA8PSAxKSByZXR1cm4KICAgICAgICAgICAgbGV0IHQgPSBuZXcgVWludDhBcnJheSh0aGlzLnNpemUpLAogICAgICAgICAgICAgIGUgPSAwOwogICAgICAgICAgICBmb3IgKGxldCByIG9mIHRoaXMuYnVmZmVycykgdC5zZXQociwgZSksIChlICs9IHIuYnl0ZUxlbmd0aCk7CiAgICAgICAgICAgIHRoaXMuYnVmZmVycyA9IFt0XTsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICB9LAogICAgICBmdW5jdGlvbiAodCwgZSwgcikgewogIChmdW5jdGlvbiAodCkgewogICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogITAgfSk7CiAgICAgICAgICBjb25zdCBuID0gcigxMiksCiAgICAgICAgICAgIGkgPSByKDEzKSwKICAgICAgICAgICAgbyA9IHIoMCk7CiAgICAgICAgICBlLkZpbGVFeHRyYWN0b3IgPSBjbGFzcyBleHRlbmRzIG8uRXh0cmFjdG9yIHsKICAgICAgICAgICAgY29uc3RydWN0b3IodCwgZSwgcikgewogICAgICAgICAgICAgIHN1cGVyKHIpLCAodGhpcy5fZmlsZVBhdGggPSB0KSwgKHRoaXMuZmlsZU1hcCA9IHt9KSwgKHRoaXMuX3RhcmdldCA9IGUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG9wZW4odCkgewogICAgICAgICAgICAgIGxldCBlID0gbi5vcGVuU3luYyh0LCAncicpOwogICAgICAgICAgICAgIHJldHVybiAodGhpcy5maWxlTWFwW2VdID0geyBzaXplOiBuLmZzdGF0U3luYyhlKS5zaXplLCBwb3M6IDAsIG5hbWU6IHQgfSksIGUKICAgICAgICAgICAgfQogICAgICAgICAgICBjcmVhdGUodCkgewogICAgICAgICAgICAgIGxldCBlID0gaS5qb2luKHRoaXMuX3RhcmdldCwgdCk7CiAgICAgICAgICAgICAgaS5wYXJzZShlKQogICAgICAgICAgICAgICAgLmRpci5zcGxpdCgnLycpCiAgICAgICAgICAgICAgICAucmVkdWNlKCh0LCBlKSA9PiAoKHQgKz0gZSArICcvJyksIG4uZXhpc3RzU3luYyh0KSB8fCBuLm1rZGlyU3luYyh0KSwgdCksICcnKTsKICAgICAgICAgICAgICBsZXQgciA9IG4ub3BlblN5bmMoZSwgJ3cnKTsKICAgICAgICAgICAgICByZXR1cm4gKHRoaXMuZmlsZU1hcFtyXSA9IHsgc2l6ZTogMCwgcG9zOiAwLCBuYW1lOiB0IH0pLCByCiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2xvc2VGaWxlKHQpIHsKICAgICAgICAgICAgICByZXR1cm4gZGVsZXRlIHRoaXMuZmlsZU1hcFt0XSwgbi5jbG9zZVN5bmModCksIG51bGwKICAgICAgICAgICAgfQogICAgICAgICAgICByZWFkKGUsIHIsIGkpIHsKICAgICAgICAgICAgICBsZXQgbyA9IHRoaXMuZmlsZU1hcFtlXSwKICAgICAgICAgICAgICAgIHMgPSBuZXcgdChpKSwKICAgICAgICAgICAgICAgIHUgPSBuLnJlYWRTeW5jKGUsIHMsIDAsIGksIG8ucG9zKTsKICAgICAgICAgICAgICByZXR1cm4gdW5wYWNrLkhFQVBVOC5zZXQocywgciksIChvLnBvcyArPSB1KSwgdQogICAgICAgICAgICB9CiAgICAgICAgICAgIHdyaXRlKGUsIHIsIGkpIHsKICAgICAgICAgICAgICBsZXQgbyA9IHRoaXMuZmlsZU1hcFtlXSwKICAgICAgICAgICAgICAgIHMgPSBuLndyaXRlU3luYyhlLCBuZXcgdCh1bnBhY2suSEVBUFU4LnN1YmFycmF5KHIsIHIgKyBpKSksIDAsIGkpOwogICAgICAgICAgICAgIHJldHVybiAoby5wb3MgKz0gcyksIChvLnNpemUgKz0gcyksIHMgPT09IGkKICAgICAgICAgICAgfQogICAgICAgICAgICB0ZWxsKHQpIHsKICAgICAgICAgICAgICByZXR1cm4gdGhpcy5maWxlTWFwW3RdLnBvcwogICAgICAgICAgICB9CiAgICAgICAgICAgIHNlZWsodCwgZSwgcikgewogICAgICAgICAgICAgIGxldCBuID0gdGhpcy5maWxlTWFwW3RdLAogICAgICAgICAgICAgICAgaSA9IG4ucG9zOwogICAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICAnU0VUJyA9PT0gciA/IChpID0gMCkgOiAnRU5EJyA9PT0gciAmJiAoaSA9IG4uc2l6ZSksICEoKGkgKz0gZSkgPCAwIHx8IGkgPiBuLnNpemUgfHwgKChuLnBvcyA9IGkpLCAwKSkKICAgICAgICAgICAgICApCiAgICAgICAgICAgIH0KICAgICAgICAgIH07CiAgICAgICAgfS5jYWxsKHRoaXMsIHIoNykuQnVmZmVyKSk7CiAgICAgIH0sCiAgICAgIGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgKGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAvKiEKICAgICAgICAgICAqIFRoZSBidWZmZXIgbW9kdWxlIGZyb20gbm9kZS5qcywgZm9yIHRoZSBicm93c2VyLgogICAgICAgICAgICoKICAgICAgICAgICAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxmZXJvc3NAZmVyb3NzLm9yZz4gPGh0dHA6Ly9mZXJvc3Mub3JnPgogICAgICAgICAgICogQGxpY2Vuc2UgIE1JVAogICAgICAgICAgICovCiAgICAgICAgICB2YXIgbiA9IHIoOSksCiAgICAgICAgICAgIGkgPSByKDEwKSwKICAgICAgICAgICAgbyA9IHIoMTEpOwogICAgICAgICAgZnVuY3Rpb24gcygpIHsKICAgICAgICAgICAgcmV0dXJuIGEuVFlQRURfQVJSQVlfU1VQUE9SVCA/IDIxNDc0ODM2NDcgOiAxMDczNzQxODIzCiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiB1KHQsIGUpIHsKICAgICAgICAgICAgaWYgKHMoKSA8IGUpIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbnZhbGlkIHR5cGVkIGFycmF5IGxlbmd0aCcpCiAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgYS5UWVBFRF9BUlJBWV9TVVBQT1JUCiAgICAgICAgICAgICAgICA/ICgodCA9IG5ldyBVaW50OEFycmF5KGUpKS5fX3Byb3RvX18gPSBhLnByb3RvdHlwZSkKICAgICAgICAgICAgICAgIDogKG51bGwgPT09IHQgJiYgKHQgPSBuZXcgYShlKSksICh0Lmxlbmd0aCA9IGUpKSwKICAgICAgICAgICAgICB0CiAgICAgICAgICAgICkKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGEodCwgZSwgcikgewogICAgICAgICAgICBpZiAoIShhLlRZUEVEX0FSUkFZX1NVUFBPUlQgfHwgdGhpcyBpbnN0YW5jZW9mIGEpKSByZXR1cm4gbmV3IGEodCwgZSwgcikKICAgICAgICAgICAgaWYgKCdudW1iZXInID09IHR5cGVvZiB0KSB7CiAgICAgICAgICAgICAgaWYgKCdzdHJpbmcnID09IHR5cGVvZiBlKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJZiBlbmNvZGluZyBpcyBzcGVjaWZpZWQgdGhlbiB0aGUgZmlyc3QgYXJndW1lbnQgbXVzdCBiZSBhIHN0cmluZycpCiAgICAgICAgICAgICAgcmV0dXJuIGwodGhpcywgdCkKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZih0aGlzLCB0LCBlLCByKQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gZih0LCBlLCByLCBuKSB7CiAgICAgICAgICAgIGlmICgnbnVtYmVyJyA9PSB0eXBlb2YgZSkgdGhyb3cgbmV3IFR5cGVFcnJvcignInZhbHVlIiBhcmd1bWVudCBtdXN0IG5vdCBiZSBhIG51bWJlcicpCiAgICAgICAgICAgIHJldHVybiAndW5kZWZpbmVkJyAhPSB0eXBlb2YgQXJyYXlCdWZmZXIgJiYgZSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyCiAgICAgICAgICAgICAgPyAoZnVuY3Rpb24gKHQsIGUsIHIsIG4pIHsKICAgICAgICAgICAgICAgICAgaWYgKChlLmJ5dGVMZW5ndGgsIHIgPCAwIHx8IGUuYnl0ZUxlbmd0aCA8IHIpKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcigiJ29mZnNldCcgaXMgb3V0IG9mIGJvdW5kcyIpCiAgICAgICAgICAgICAgICAgIGlmIChlLmJ5dGVMZW5ndGggPCByICsgKG4gfHwgMCkpIHRocm93IG5ldyBSYW5nZUVycm9yKCInbGVuZ3RoJyBpcyBvdXQgb2YgYm91bmRzIikKICAgICAgICAgICAgICAgICAgZSA9CiAgICAgICAgICAgICAgICAgICAgdm9pZCAwID09PSByICYmIHZvaWQgMCA9PT0gbgogICAgICAgICAgICAgICAgICAgICAgPyBuZXcgVWludDhBcnJheShlKQogICAgICAgICAgICAgICAgICAgICAgOiB2b2lkIDAgPT09IG4KICAgICAgICAgICAgICAgICAgICAgID8gbmV3IFVpbnQ4QXJyYXkoZSwgcikKICAgICAgICAgICAgICAgICAgICAgIDogbmV3IFVpbnQ4QXJyYXkoZSwgciwgbik7CiAgICAgICAgICAgICAgICAgIGEuVFlQRURfQVJSQVlfU1VQUE9SVCA/ICgodCA9IGUpLl9fcHJvdG9fXyA9IGEucHJvdG90eXBlKSA6ICh0ID0gYyh0LCBlKSk7CiAgICAgICAgICAgICAgICAgIHJldHVybiB0CiAgICAgICAgICAgICAgICB9KSh0LCBlLCByLCBuKQogICAgICAgICAgICAgIDogJ3N0cmluZycgPT0gdHlwZW9mIGUKICAgICAgICAgICAgICA/IChmdW5jdGlvbiAodCwgZSwgcikgewogICgnc3RyaW5nJyA9PSB0eXBlb2YgciAmJiAnJyAhPT0gcikgfHwgKHIgPSAndXRmOCcpOwogICAgICAgICAgICAgICAgICBpZiAoIWEuaXNFbmNvZGluZyhyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignImVuY29kaW5nIiBtdXN0IGJlIGEgdmFsaWQgc3RyaW5nIGVuY29kaW5nJykKICAgICAgICAgICAgICAgICAgdmFyIG4gPSAwIHwgZyhlLCByKSwKICAgICAgICAgICAgICAgICAgICBpID0gKHQgPSB1KHQsIG4pKS53cml0ZShlLCByKTsKICAgICAgICAgICAgICAgICAgaSAhPT0gbiAmJiAodCA9IHQuc2xpY2UoMCwgaSkpOwogICAgICAgICAgICAgICAgICByZXR1cm4gdAogICAgICAgICAgICAgICAgfSkodCwgZSwgcikKICAgICAgICAgICAgICA6IChmdW5jdGlvbiAodCwgZSkgewogICAgICAgICAgICAgICAgICBpZiAoYS5pc0J1ZmZlcihlKSkgewogICAgICAgICAgICAgICAgICAgIHZhciByID0gMCB8IHAoZS5sZW5ndGgpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiAwID09PSAodCA9IHUodCwgcikpLmxlbmd0aCA/IHQgOiAoZS5jb3B5KHQsIDAsIDAsIHIpLCB0KQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChlKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCgndW5kZWZpbmVkJyAhPSB0eXBlb2YgQXJyYXlCdWZmZXIgJiYgZS5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgfHwgJ2xlbmd0aCcgaW4gZSkKICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnbnVtYmVyJyAhPSB0eXBlb2YgZS5sZW5ndGggfHwKICAgICAgICAgICAgICAgICAgICAgICAgKGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHQgIT0gdAogICAgICAgICAgICAgICAgICAgICAgICB9KShlLmxlbmd0aCkKICAgICAgICAgICAgICAgICAgICAgICAgPyB1KHQsIDApCiAgICAgICAgICAgICAgICAgICAgICAgIDogYyh0LCBlKQogICAgICAgICAgICAgICAgICAgIGlmICgnQnVmZmVyJyA9PT0gZS50eXBlICYmIG8oZS5kYXRhKSkgcmV0dXJuIGModCwgZS5kYXRhKQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoCiAgICAgICAgICAgICAgICAgICAgJ0ZpcnN0IGFyZ3VtZW50IG11c3QgYmUgYSBzdHJpbmcsIEJ1ZmZlciwgQXJyYXlCdWZmZXIsIEFycmF5LCBvciBhcnJheS1saWtlIG9iamVjdC4nCiAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIH0pKHQsIGUpCiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBoKHQpIHsKICAgICAgICAgICAgaWYgKCdudW1iZXInICE9IHR5cGVvZiB0KSB0aHJvdyBuZXcgVHlwZUVycm9yKCcic2l6ZSIgYXJndW1lbnQgbXVzdCBiZSBhIG51bWJlcicpCiAgICAgICAgICAgIGlmICh0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJyJzaXplIiBhcmd1bWVudCBtdXN0IG5vdCBiZSBuZWdhdGl2ZScpCiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBsKHQsIGUpIHsKICAgICAgICAgICAgaWYgKChoKGUpLCAodCA9IHUodCwgZSA8IDAgPyAwIDogMCB8IHAoZSkpKSwgIWEuVFlQRURfQVJSQVlfU1VQUE9SVCkpIGZvciAodmFyIHIgPSAwOyByIDwgZTsgKytyKSB0W3JdID0gMDsKICAgICAgICAgICAgcmV0dXJuIHQKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGModCwgZSkgewogICAgICAgICAgICB2YXIgciA9IGUubGVuZ3RoIDwgMCA/IDAgOiAwIHwgcChlLmxlbmd0aCk7CiAgICAgICAgICAgIHQgPSB1KHQsIHIpOwogICAgICAgICAgICBmb3IgKHZhciBuID0gMDsgbiA8IHI7IG4gKz0gMSkgdFtuXSA9IDI1NSAmIGVbbl07CiAgICAgICAgICAgIHJldHVybiB0CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBwKHQpIHsKICAgICAgICAgICAgaWYgKHQgPj0gcygpKQogICAgICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKAogICAgICAgICAgICAgICAgJ0F0dGVtcHQgdG8gYWxsb2NhdGUgQnVmZmVyIGxhcmdlciB0aGFuIG1heGltdW0gc2l6ZTogMHgnICsgcygpLnRvU3RyaW5nKDE2KSArICcgYnl0ZXMnCiAgICAgICAgICAgICAgKQogICAgICAgICAgICByZXR1cm4gMCB8IHQKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGcodCwgZSkgewogICAgICAgICAgICBpZiAoYS5pc0J1ZmZlcih0KSkgcmV0dXJuIHQubGVuZ3RoCiAgICAgICAgICAgIGlmICgKICAgICAgICAgICAgICAndW5kZWZpbmVkJyAhPSB0eXBlb2YgQXJyYXlCdWZmZXIgJiYKICAgICAgICAgICAgICAnZnVuY3Rpb24nID09IHR5cGVvZiBBcnJheUJ1ZmZlci5pc1ZpZXcgJiYKICAgICAgICAgICAgICAoQXJyYXlCdWZmZXIuaXNWaWV3KHQpIHx8IHQgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikKICAgICAgICAgICAgKQogICAgICAgICAgICAgIHJldHVybiB0LmJ5dGVMZW5ndGgKICAgICAgICAgICAgJ3N0cmluZycgIT0gdHlwZW9mIHQgJiYgKHQgPSAnJyArIHQpOwogICAgICAgICAgICB2YXIgciA9IHQubGVuZ3RoOwogICAgICAgICAgICBpZiAoMCA9PT0gcikgcmV0dXJuIDAKICAgICAgICAgICAgZm9yICh2YXIgbiA9ICExOyA7ICkKICAgICAgICAgICAgICBzd2l0Y2ggKGUpIHsKICAgICAgICAgICAgICAgIGNhc2UgJ2FzY2lpJzoKICAgICAgICAgICAgICAgIGNhc2UgJ2xhdGluMSc6CiAgICAgICAgICAgICAgICBjYXNlICdiaW5hcnknOgogICAgICAgICAgICAgICAgICByZXR1cm4gcgogICAgICAgICAgICAgICAgY2FzZSAndXRmOCc6CiAgICAgICAgICAgICAgICBjYXNlICd1dGYtOCc6CiAgICAgICAgICAgICAgICBjYXNlIHZvaWQgMDoKICAgICAgICAgICAgICAgICAgcmV0dXJuIGsodCkubGVuZ3RoCiAgICAgICAgICAgICAgICBjYXNlICd1Y3MyJzoKICAgICAgICAgICAgICAgIGNhc2UgJ3Vjcy0yJzoKICAgICAgICAgICAgICAgIGNhc2UgJ3V0ZjE2bGUnOgogICAgICAgICAgICAgICAgY2FzZSAndXRmLTE2bGUnOgogICAgICAgICAgICAgICAgICByZXR1cm4gMiAqIHIKICAgICAgICAgICAgICAgIGNhc2UgJ2hleCc6CiAgICAgICAgICAgICAgICAgIHJldHVybiByID4+PiAxCiAgICAgICAgICAgICAgICBjYXNlICdiYXNlNjQnOgogICAgICAgICAgICAgICAgICByZXR1cm4gaih0KS5sZW5ndGgKICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgIGlmIChuKSByZXR1cm4gayh0KS5sZW5ndGgKICAgICAgICAgICAgICAgICAgOyhlID0gKCcnICsgZSkudG9Mb3dlckNhc2UoKSksIChuID0gITApOwogICAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGQodCwgZSwgcikgewogICAgICAgICAgICB2YXIgbiA9IHRbZV0KICAgICAgICAgICAgOyh0W2VdID0gdFtyXSksICh0W3JdID0gbik7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiB5KHQsIGUsIHIsIG4sIGkpIHsKICAgICAgICAgICAgaWYgKDAgPT09IHQubGVuZ3RoKSByZXR1cm4gLTEKICAgICAgICAgICAgaWYgKAogICAgICAgICAgICAgICgnc3RyaW5nJyA9PSB0eXBlb2YgcgogICAgICAgICAgICAgICAgPyAoKG4gPSByKSwgKHIgPSAwKSkKICAgICAgICAgICAgICAgIDogciA+IDIxNDc0ODM2NDcKICAgICAgICAgICAgICAgID8gKHIgPSAyMTQ3NDgzNjQ3KQogICAgICAgICAgICAgICAgOiByIDwgLTIxNDc0ODM2NDggJiYgKHIgPSAtMjE0NzQ4MzY0OCksCiAgICAgICAgICAgICAgKHIgPSArciksCiAgICAgICAgICAgICAgaXNOYU4ocikgJiYgKHIgPSBpID8gMCA6IHQubGVuZ3RoIC0gMSksCiAgICAgICAgICAgICAgciA8IDAgJiYgKHIgPSB0Lmxlbmd0aCArIHIpLAogICAgICAgICAgICAgIHIgPj0gdC5sZW5ndGgpCiAgICAgICAgICAgICkgewogICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gLTEKICAgICAgICAgICAgICByID0gdC5sZW5ndGggLSAxOwogICAgICAgICAgICB9IGVsc2UgaWYgKHIgPCAwKSB7CiAgICAgICAgICAgICAgaWYgKCFpKSByZXR1cm4gLTEKICAgICAgICAgICAgICByID0gMDsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoKCdzdHJpbmcnID09IHR5cGVvZiBlICYmIChlID0gYS5mcm9tKGUsIG4pKSwgYS5pc0J1ZmZlcihlKSkpIHJldHVybiAwID09PSBlLmxlbmd0aCA/IC0xIDogdyh0LCBlLCByLCBuLCBpKQogICAgICAgICAgICBpZiAoJ251bWJlcicgPT0gdHlwZW9mIGUpCiAgICAgICAgICAgICAgcmV0dXJuICgKICAgICAgICAgICAgICAgIChlICY9IDI1NSksCiAgICAgICAgICAgICAgICBhLlRZUEVEX0FSUkFZX1NVUFBPUlQgJiYgJ2Z1bmN0aW9uJyA9PSB0eXBlb2YgVWludDhBcnJheS5wcm90b3R5cGUuaW5kZXhPZgogICAgICAgICAgICAgICAgICA/IGkKICAgICAgICAgICAgICAgICAgICA/IFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbCh0LCBlLCByKQogICAgICAgICAgICAgICAgICAgIDogVWludDhBcnJheS5wcm90b3R5cGUubGFzdEluZGV4T2YuY2FsbCh0LCBlLCByKQogICAgICAgICAgICAgICAgICA6IHcodCwgW2VdLCByLCBuLCBpKQogICAgICAgICAgICAgICkKICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmFsIG11c3QgYmUgc3RyaW5nLCBudW1iZXIgb3IgQnVmZmVyJykKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHcodCwgZSwgciwgbiwgaSkgewogICAgICAgICAgICB2YXIgbywKICAgICAgICAgICAgICBzID0gMSwKICAgICAgICAgICAgICB1ID0gdC5sZW5ndGgsCiAgICAgICAgICAgICAgYSA9IGUubGVuZ3RoOwogICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgdm9pZCAwICE9PSBuICYmCiAgICAgICAgICAgICAgKCd1Y3MyJyA9PT0gKG4gPSBTdHJpbmcobikudG9Mb3dlckNhc2UoKSkgfHwgJ3Vjcy0yJyA9PT0gbiB8fCAndXRmMTZsZScgPT09IG4gfHwgJ3V0Zi0xNmxlJyA9PT0gbikKICAgICAgICAgICAgKSB7CiAgICAgICAgICAgICAgaWYgKHQubGVuZ3RoIDwgMiB8fCBlLmxlbmd0aCA8IDIpIHJldHVybiAtMQogICAgICAgICAgICAgIDsocyA9IDIpLCAodSAvPSAyKSwgKGEgLz0gMiksIChyIC89IDIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZ1bmN0aW9uIGYodCwgZSkgewogICAgICAgICAgICAgIHJldHVybiAxID09PSBzID8gdFtlXSA6IHQucmVhZFVJbnQxNkJFKGUgKiBzKQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChpKSB7CiAgICAgICAgICAgICAgdmFyIGggPSAtMTsKICAgICAgICAgICAgICBmb3IgKG8gPSByOyBvIDwgdTsgbysrKQogICAgICAgICAgICAgICAgaWYgKGYodCwgbykgPT09IGYoZSwgLTEgPT09IGggPyAwIDogbyAtIGgpKSB7CiAgICAgICAgICAgICAgICAgIGlmICgoLTEgPT09IGggJiYgKGggPSBvKSwgbyAtIGggKyAxID09PSBhKSkgcmV0dXJuIGggKiBzCiAgICAgICAgICAgICAgICB9IGVsc2UgLTEgIT09IGggJiYgKG8gLT0gbyAtIGgpLCAoaCA9IC0xKTsKICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgZm9yIChyICsgYSA+IHUgJiYgKHIgPSB1IC0gYSksIG8gPSByOyBvID49IDA7IG8tLSkgewogICAgICAgICAgICAgICAgZm9yICh2YXIgbCA9ICEwLCBjID0gMDsgYyA8IGE7IGMrKykKICAgICAgICAgICAgICAgICAgaWYgKGYodCwgbyArIGMpICE9PSBmKGUsIGMpKSB7CiAgICAgICAgICAgICAgICAgICAgbCA9ICExOwogICAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChsKSByZXR1cm4gbwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIC0xCiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBFKHQsIGUsIHIsIG4pIHsKICAgICAgICAgICAgciA9IE51bWJlcihyKSB8fCAwOwogICAgICAgICAgICB2YXIgaSA9IHQubGVuZ3RoIC0gcjsKICAgICAgICAgICAgbiA/IChuID0gTnVtYmVyKG4pKSA+IGkgJiYgKG4gPSBpKSA6IChuID0gaSk7CiAgICAgICAgICAgIHZhciBvID0gZS5sZW5ndGg7CiAgICAgICAgICAgIGlmIChvICUgMiAhPSAwKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIGhleCBzdHJpbmcnKQogICAgICAgICAgICBuID4gbyAvIDIgJiYgKG4gPSBvIC8gMik7CiAgICAgICAgICAgIGZvciAodmFyIHMgPSAwOyBzIDwgbjsgKytzKSB7CiAgICAgICAgICAgICAgdmFyIHUgPSBwYXJzZUludChlLnN1YnN0cigyICogcywgMiksIDE2KTsKICAgICAgICAgICAgICBpZiAoaXNOYU4odSkpIHJldHVybiBzCiAgICAgICAgICAgICAgdFtyICsgc10gPSB1OwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBzCiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiB2KHQsIGUsIHIsIG4pIHsKICAgICAgICAgICAgcmV0dXJuIHooayhlLCB0Lmxlbmd0aCAtIHIpLCB0LCByLCBuKQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gQSh0LCBlLCByLCBuKSB7CiAgICAgICAgICAgIHJldHVybiB6KAogICAgICAgICAgICAgIChmdW5jdGlvbiAodCkgewogICAgICAgICAgICAgICAgZm9yICh2YXIgZSA9IFtdLCByID0gMDsgciA8IHQubGVuZ3RoOyArK3IpIGUucHVzaCgyNTUgJiB0LmNoYXJDb2RlQXQocikpOwogICAgICAgICAgICAgICAgcmV0dXJuIGUKICAgICAgICAgICAgICB9KShlKSwKICAgICAgICAgICAgICB0LAogICAgICAgICAgICAgIHIsCiAgICAgICAgICAgICAgbgogICAgICAgICAgICApCiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfKHQsIGUsIHIsIG4pIHsKICAgICAgICAgICAgcmV0dXJuIEEodCwgZSwgciwgbikKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGIodCwgZSwgciwgbikgewogICAgICAgICAgICByZXR1cm4geihqKGUpLCB0LCByLCBuKQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gbSh0LCBlLCByLCBuKSB7CiAgICAgICAgICAgIHJldHVybiB6KAogICAgICAgICAgICAgIChmdW5jdGlvbiAodCwgZSkgewogICAgICAgICAgICAgICAgZm9yICh2YXIgciwgbiwgaSwgbyA9IFtdLCBzID0gMDsgcyA8IHQubGVuZ3RoICYmICEoKGUgLT0gMikgPCAwKTsgKytzKQogICAgICAgICAgICAgICAgICAociA9IHQuY2hhckNvZGVBdChzKSksIChuID0gciA+PiA4KSwgKGkgPSByICUgMjU2KSwgby5wdXNoKGkpLCBvLnB1c2gobik7CiAgICAgICAgICAgICAgICByZXR1cm4gbwogICAgICAgICAgICAgIH0pKGUsIHQubGVuZ3RoIC0gciksCiAgICAgICAgICAgICAgdCwKICAgICAgICAgICAgICByLAogICAgICAgICAgICAgIG4KICAgICAgICAgICAgKQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gUih0LCBlLCByKSB7CiAgICAgICAgICAgIHJldHVybiAwID09PSBlICYmIHIgPT09IHQubGVuZ3RoID8gbi5mcm9tQnl0ZUFycmF5KHQpIDogbi5mcm9tQnl0ZUFycmF5KHQuc2xpY2UoZSwgcikpCiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBTKHQsIGUsIHIpIHsKICAgICAgICAgICAgciA9IE1hdGgubWluKHQubGVuZ3RoLCByKTsKICAgICAgICAgICAgZm9yICh2YXIgbiA9IFtdLCBpID0gZTsgaSA8IHI7ICkgewogICAgICAgICAgICAgIHZhciBvLAogICAgICAgICAgICAgICAgcywKICAgICAgICAgICAgICAgIHUsCiAgICAgICAgICAgICAgICBhLAogICAgICAgICAgICAgICAgZiA9IHRbaV0sCiAgICAgICAgICAgICAgICBoID0gbnVsbCwKICAgICAgICAgICAgICAgIGwgPSBmID4gMjM5ID8gNCA6IGYgPiAyMjMgPyAzIDogZiA+IDE5MSA/IDIgOiAxOwogICAgICAgICAgICAgIGlmIChpICsgbCA8PSByKQogICAgICAgICAgICAgICAgc3dpdGNoIChsKSB7CiAgICAgICAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICAgICAgICBmIDwgMTI4ICYmIChoID0gZik7CiAgICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgICAgIDEyOCA9PSAoMTkyICYgKG8gPSB0W2kgKyAxXSkpICYmIChhID0gKCgzMSAmIGYpIDw8IDYpIHwgKDYzICYgbykpID4gMTI3ICYmIChoID0gYSk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgICAgICAgY2FzZSAzOgogIChvID0gdFtpICsgMV0pLAogICAgICAgICAgICAgICAgICAgICAgKHMgPSB0W2kgKyAyXSksCiAgICAgICAgICAgICAgICAgICAgICAxMjggPT0gKDE5MiAmIG8pICYmCiAgICAgICAgICAgICAgICAgICAgICAgIDEyOCA9PSAoMTkyICYgcykgJiYKICAgICAgICAgICAgICAgICAgICAgICAgKGEgPSAoKDE1ICYgZikgPDwgMTIpIHwgKCg2MyAmIG8pIDw8IDYpIHwgKDYzICYgcykpID4gMjA0NyAmJgogICAgICAgICAgICAgICAgICAgICAgICAoYSA8IDU1Mjk2IHx8IGEgPiA1NzM0MykgJiYKICAgICAgICAgICAgICAgICAgICAgICAgKGggPSBhKTsKICAgICAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICAgICAgICBjYXNlIDQ6CiAgKG8gPSB0W2kgKyAxXSksCiAgICAgICAgICAgICAgICAgICAgICAocyA9IHRbaSArIDJdKSwKICAgICAgICAgICAgICAgICAgICAgICh1ID0gdFtpICsgM10pLAogICAgICAgICAgICAgICAgICAgICAgMTI4ID09ICgxOTIgJiBvKSAmJgogICAgICAgICAgICAgICAgICAgICAgICAxMjggPT0gKDE5MiAmIHMpICYmCiAgICAgICAgICAgICAgICAgICAgICAgIDEyOCA9PSAoMTkyICYgdSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgKGEgPSAoKDE1ICYgZikgPDwgMTgpIHwgKCg2MyAmIG8pIDw8IDEyKSB8ICgoNjMgJiBzKSA8PCA2KSB8ICg2MyAmIHUpKSA+IDY1NTM1ICYmCiAgICAgICAgICAgICAgICAgICAgICAgIGEgPCAxMTE0MTEyICYmCiAgICAgICAgICAgICAgICAgICAgICAgIChoID0gYSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgbnVsbCA9PT0gaAogICAgICAgICAgICAgICAgPyAoKGggPSA2NTUzMyksIChsID0gMSkpCiAgICAgICAgICAgICAgICA6IGggPiA2NTUzNSAmJiAoKGggLT0gNjU1MzYpLCBuLnB1c2goKChoID4+PiAxMCkgJiAxMDIzKSB8IDU1Mjk2KSwgKGggPSA1NjMyMCB8ICgxMDIzICYgaCkpKSwKICAgICAgICAgICAgICAgIG4ucHVzaChoKSwKICAgICAgICAgICAgICAgIChpICs9IGwpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiAoZnVuY3Rpb24gKHQpIHsKICAgICAgICAgICAgICB2YXIgZSA9IHQubGVuZ3RoOwogICAgICAgICAgICAgIGlmIChlIDw9IFQpIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZywgdCkKICAgICAgICAgICAgICB2YXIgciA9ICcnLAogICAgICAgICAgICAgICAgbiA9IDA7CiAgICAgICAgICAgICAgZm9yICg7IG4gPCBlOyApIHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShTdHJpbmcsIHQuc2xpY2UobiwgKG4gKz0gVCkpKTsKICAgICAgICAgICAgICByZXR1cm4gcgogICAgICAgICAgICB9KShuKQogICAgICAgICAgfQogIChlLkJ1ZmZlciA9IGEpLAogICAgICAgICAgICAoZS5TbG93QnVmZmVyID0gZnVuY3Rpb24gKHQpIHsKICArdCAhPSB0ICYmICh0ID0gMCk7CiAgICAgICAgICAgICAgcmV0dXJuIGEuYWxsb2MoK3QpCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoZS5JTlNQRUNUX01BWF9CWVRFUyA9IDUwKSwKICAgICAgICAgICAgKGEuVFlQRURfQVJSQVlfU1VQUE9SVCA9CiAgICAgICAgICAgICAgdm9pZCAwICE9PSB0LlRZUEVEX0FSUkFZX1NVUFBPUlQKICAgICAgICAgICAgICAgID8gdC5UWVBFRF9BUlJBWV9TVVBQT1JUCiAgICAgICAgICAgICAgICA6IChmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgIHZhciB0ID0gbmV3IFVpbnQ4QXJyYXkoMSk7CiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKAogICAgICAgICAgICAgICAgICAgICAgICAodC5fX3Byb3RvX18gPSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgX19wcm90b19fOiBVaW50OEFycmF5LnByb3RvdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgICBmb286IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiA0MgogICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgIH0pLAogICAgICAgICAgICAgICAgICAgICAgICA0MiA9PT0gdC5mb28oKSAmJiAnZnVuY3Rpb24nID09IHR5cGVvZiB0LnN1YmFycmF5ICYmIDAgPT09IHQuc3ViYXJyYXkoMSwgMSkuYnl0ZUxlbmd0aAogICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKHQpIHsKICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhMQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgfSkoKSksCiAgICAgICAgICAgIChlLmtNYXhMZW5ndGggPSBzKCkpLAogICAgICAgICAgICAoYS5wb29sU2l6ZSA9IDgxOTIpLAogICAgICAgICAgICAoYS5fYXVnbWVudCA9IGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAgICAgcmV0dXJuICh0Ll9fcHJvdG9fXyA9IGEucHJvdG90eXBlKSwgdAogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEuZnJvbSA9IGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGYobnVsbCwgdCwgZSwgcikKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIGEuVFlQRURfQVJSQVlfU1VQUE9SVCAmJgogICAgICAgICAgICAgICgoYS5wcm90b3R5cGUuX19wcm90b19fID0gVWludDhBcnJheS5wcm90b3R5cGUpLAogICAgICAgICAgICAgIChhLl9fcHJvdG9fXyA9IFVpbnQ4QXJyYXkpLAogICAgICAgICAgICAgICd1bmRlZmluZWQnICE9IHR5cGVvZiBTeW1ib2wgJiYKICAgICAgICAgICAgICAgIFN5bWJvbC5zcGVjaWVzICYmCiAgICAgICAgICAgICAgICBhW1N5bWJvbC5zcGVjaWVzXSA9PT0gYSAmJgogICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGEsIFN5bWJvbC5zcGVjaWVzLCB7IHZhbHVlOiBudWxsLCBjb25maWd1cmFibGU6ICEwIH0pKSwKICAgICAgICAgICAgKGEuYWxsb2MgPSBmdW5jdGlvbiAodCwgZSwgcikgewogICAgICAgICAgICAgIHJldHVybiAoZnVuY3Rpb24gKHQsIGUsIHIsIG4pIHsKICAgICAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICAgIGgoZSksCiAgICAgICAgICAgICAgICAgIGUgPD0gMAogICAgICAgICAgICAgICAgICAgID8gdSh0LCBlKQogICAgICAgICAgICAgICAgICAgIDogdm9pZCAwICE9PSByCiAgICAgICAgICAgICAgICAgICAgPyAnc3RyaW5nJyA9PSB0eXBlb2YgbgogICAgICAgICAgICAgICAgICAgICAgPyB1KHQsIGUpLmZpbGwociwgbikKICAgICAgICAgICAgICAgICAgICAgIDogdSh0LCBlKS5maWxsKHIpCiAgICAgICAgICAgICAgICAgICAgOiB1KHQsIGUpCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgfSkobnVsbCwgdCwgZSwgcikKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLmFsbG9jVW5zYWZlID0gZnVuY3Rpb24gKHQpIHsKICAgICAgICAgICAgICByZXR1cm4gbChudWxsLCB0KQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEuYWxsb2NVbnNhZmVTbG93ID0gZnVuY3Rpb24gKHQpIHsKICAgICAgICAgICAgICByZXR1cm4gbChudWxsLCB0KQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEuaXNCdWZmZXIgPSBmdW5jdGlvbiAodCkgewogICAgICAgICAgICAgIHJldHVybiAhKG51bGwgPT0gdCB8fCAhdC5faXNCdWZmZXIpCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5jb21wYXJlID0gZnVuY3Rpb24gKHQsIGUpIHsKICAgICAgICAgICAgICBpZiAoIWEuaXNCdWZmZXIodCkgfHwgIWEuaXNCdWZmZXIoZSkpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50cyBtdXN0IGJlIEJ1ZmZlcnMnKQogICAgICAgICAgICAgIGlmICh0ID09PSBlKSByZXR1cm4gMAogICAgICAgICAgICAgIGZvciAodmFyIHIgPSB0Lmxlbmd0aCwgbiA9IGUubGVuZ3RoLCBpID0gMCwgbyA9IE1hdGgubWluKHIsIG4pOyBpIDwgbzsgKytpKQogICAgICAgICAgICAgICAgaWYgKHRbaV0gIT09IGVbaV0pIHsKICAociA9IHRbaV0pLCAobiA9IGVbaV0pOwogICAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiByIDwgbiA/IC0xIDogbiA8IHIgPyAxIDogMAogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEuaXNFbmNvZGluZyA9IGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAgICAgc3dpdGNoIChTdHJpbmcodCkudG9Mb3dlckNhc2UoKSkgewogICAgICAgICAgICAgICAgY2FzZSAnaGV4JzoKICAgICAgICAgICAgICAgIGNhc2UgJ3V0ZjgnOgogICAgICAgICAgICAgICAgY2FzZSAndXRmLTgnOgogICAgICAgICAgICAgICAgY2FzZSAnYXNjaWknOgogICAgICAgICAgICAgICAgY2FzZSAnbGF0aW4xJzoKICAgICAgICAgICAgICAgIGNhc2UgJ2JpbmFyeSc6CiAgICAgICAgICAgICAgICBjYXNlICdiYXNlNjQnOgogICAgICAgICAgICAgICAgY2FzZSAndWNzMic6CiAgICAgICAgICAgICAgICBjYXNlICd1Y3MtMic6CiAgICAgICAgICAgICAgICBjYXNlICd1dGYxNmxlJzoKICAgICAgICAgICAgICAgIGNhc2UgJ3V0Zi0xNmxlJzoKICAgICAgICAgICAgICAgICAgcmV0dXJuICEwCiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICByZXR1cm4gITEKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5jb25jYXQgPSBmdW5jdGlvbiAodCwgZSkgewogICAgICAgICAgICAgIGlmICghbyh0KSkgdGhyb3cgbmV3IFR5cGVFcnJvcignImxpc3QiIGFyZ3VtZW50IG11c3QgYmUgYW4gQXJyYXkgb2YgQnVmZmVycycpCiAgICAgICAgICAgICAgaWYgKDAgPT09IHQubGVuZ3RoKSByZXR1cm4gYS5hbGxvYygwKQogICAgICAgICAgICAgIHZhciByOwogICAgICAgICAgICAgIGlmICh2b2lkIDAgPT09IGUpIGZvciAoZSA9IDAsIHIgPSAwOyByIDwgdC5sZW5ndGg7ICsrcikgZSArPSB0W3JdLmxlbmd0aDsKICAgICAgICAgICAgICB2YXIgbiA9IGEuYWxsb2NVbnNhZmUoZSksCiAgICAgICAgICAgICAgICBpID0gMDsKICAgICAgICAgICAgICBmb3IgKHIgPSAwOyByIDwgdC5sZW5ndGg7ICsrcikgewogICAgICAgICAgICAgICAgdmFyIHMgPSB0W3JdOwogICAgICAgICAgICAgICAgaWYgKCFhLmlzQnVmZmVyKHMpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCcibGlzdCIgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzJykKICAgICAgICAgICAgICAgIHMuY29weShuLCBpKSwgKGkgKz0gcy5sZW5ndGgpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gbgogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEuYnl0ZUxlbmd0aCA9IGcpLAogICAgICAgICAgICAoYS5wcm90b3R5cGUuX2lzQnVmZmVyID0gITApLAogICAgICAgICAgICAoYS5wcm90b3R5cGUuc3dhcDE2ID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgIHZhciB0ID0gdGhpcy5sZW5ndGg7CiAgICAgICAgICAgICAgaWYgKHQgJSAyICE9IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMTYtYml0cycpCiAgICAgICAgICAgICAgZm9yICh2YXIgZSA9IDA7IGUgPCB0OyBlICs9IDIpIGQodGhpcywgZSwgZSArIDEpOwogICAgICAgICAgICAgIHJldHVybiB0aGlzCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUuc3dhcDMyID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgIHZhciB0ID0gdGhpcy5sZW5ndGg7CiAgICAgICAgICAgICAgaWYgKHQgJSA0ICE9IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMzItYml0cycpCiAgICAgICAgICAgICAgZm9yICh2YXIgZSA9IDA7IGUgPCB0OyBlICs9IDQpIGQodGhpcywgZSwgZSArIDMpLCBkKHRoaXMsIGUgKyAxLCBlICsgMik7CiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS5zd2FwNjQgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgdmFyIHQgPSB0aGlzLmxlbmd0aDsKICAgICAgICAgICAgICBpZiAodCAlIDggIT0gMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0J1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA2NC1iaXRzJykKICAgICAgICAgICAgICBmb3IgKHZhciBlID0gMDsgZSA8IHQ7IGUgKz0gOCkKICAgICAgICAgICAgICAgIGQodGhpcywgZSwgZSArIDcpLCBkKHRoaXMsIGUgKyAxLCBlICsgNiksIGQodGhpcywgZSArIDIsIGUgKyA1KSwgZCh0aGlzLCBlICsgMywgZSArIDQpOwogICAgICAgICAgICAgIHJldHVybiB0aGlzCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgdmFyIHQgPSAwIHwgdGhpcy5sZW5ndGg7CiAgICAgICAgICAgICAgcmV0dXJuIDAgPT09IHQKICAgICAgICAgICAgICAgID8gJycKICAgICAgICAgICAgICAgIDogMCA9PT0gYXJndW1lbnRzLmxlbmd0aAogICAgICAgICAgICAgICAgPyBTKHRoaXMsIDAsIHQpCiAgICAgICAgICAgICAgICA6IGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSAhMTsKICAgICAgICAgICAgICAgICAgICBpZiAoKCh2b2lkIDAgPT09IGUgfHwgZSA8IDApICYmIChlID0gMCksIGUgPiB0aGlzLmxlbmd0aCkpIHJldHVybiAnJwogICAgICAgICAgICAgICAgICAgIGlmICgoKHZvaWQgMCA9PT0gciB8fCByID4gdGhpcy5sZW5ndGgpICYmIChyID0gdGhpcy5sZW5ndGgpLCByIDw9IDApKSByZXR1cm4gJycKICAgICAgICAgICAgICAgICAgICBpZiAoKHIgPj4+PSAwKSA8PSAoZSA+Pj49IDApKSByZXR1cm4gJycKICAgICAgICAgICAgICAgICAgICBmb3IgKHQgfHwgKHQgPSAndXRmOCcpOyA7ICkKICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodCkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdoZXgnOgogICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBVKHRoaXMsIGUsIHIpCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3V0ZjgnOgogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd1dGYtOCc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFModGhpcywgZSwgcikKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnYXNjaWknOgogICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBQKHRoaXMsIGUsIHIpCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2xhdGluMSc6CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2JpbmFyeSc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEModGhpcywgZSwgcikKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnYmFzZTY0JzoKICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gUih0aGlzLCBlLCByKQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd1Y3MyJzoKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndWNzLTInOgogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd1dGYxNmxlJzoKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndXRmLTE2bGUnOgogICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBCKHRoaXMsIGUsIHIpCiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG4pIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyB0KQogICAgICAgICAgICAgICAgICAgICAgICAgIDsodCA9ICh0ICsgJycpLnRvTG93ZXJDYXNlKCkpLCAobiA9ICEwKTsKICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgfS5hcHBseSh0aGlzLCBhcmd1bWVudHMpCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24gKHQpIHsKICAgICAgICAgICAgICBpZiAoIWEuaXNCdWZmZXIodCkpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXInKQogICAgICAgICAgICAgIHJldHVybiB0aGlzID09PSB0IHx8IDAgPT09IGEuY29tcGFyZSh0aGlzLCB0KQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLmluc3BlY3QgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgdmFyIHQgPSAnJywKICAgICAgICAgICAgICAgIHIgPSBlLklOU1BFQ1RfTUFYX0JZVEVTOwogICAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICB0aGlzLmxlbmd0aCA+IDAgJiYKICAgICAgICAgICAgICAgICAgKCh0ID0gdGhpcy50b1N0cmluZygnaGV4JywgMCwgcikubWF0Y2goLy57Mn0vZykuam9pbignICcpKSwgdGhpcy5sZW5ndGggPiByICYmICh0ICs9ICcgLi4uICcpKSwKICAgICAgICAgICAgICAgICc8QnVmZmVyICcgKyB0ICsgJz4nCiAgICAgICAgICAgICAgKQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLmNvbXBhcmUgPSBmdW5jdGlvbiAodCwgZSwgciwgbiwgaSkgewogICAgICAgICAgICAgIGlmICghYS5pc0J1ZmZlcih0KSkgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlcicpCiAgICAgICAgICAgICAgaWYgKAogICAgICAgICAgICAgICAgKHZvaWQgMCA9PT0gZSAmJiAoZSA9IDApLAogICAgICAgICAgICAgICAgdm9pZCAwID09PSByICYmIChyID0gdCA/IHQubGVuZ3RoIDogMCksCiAgICAgICAgICAgICAgICB2b2lkIDAgPT09IG4gJiYgKG4gPSAwKSwKICAgICAgICAgICAgICAgIHZvaWQgMCA9PT0gaSAmJiAoaSA9IHRoaXMubGVuZ3RoKSwKICAgICAgICAgICAgICAgIGUgPCAwIHx8IHIgPiB0Lmxlbmd0aCB8fCBuIDwgMCB8fCBpID4gdGhpcy5sZW5ndGgpCiAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ291dCBvZiByYW5nZSBpbmRleCcpCiAgICAgICAgICAgICAgaWYgKG4gPj0gaSAmJiBlID49IHIpIHJldHVybiAwCiAgICAgICAgICAgICAgaWYgKG4gPj0gaSkgcmV0dXJuIC0xCiAgICAgICAgICAgICAgaWYgKGUgPj0gcikgcmV0dXJuIDEKICAgICAgICAgICAgICBpZiAoKChlID4+Pj0gMCksIChyID4+Pj0gMCksIChuID4+Pj0gMCksIChpID4+Pj0gMCksIHRoaXMgPT09IHQpKSByZXR1cm4gMAogICAgICAgICAgICAgIGZvciAoCiAgICAgICAgICAgICAgICB2YXIgbyA9IGkgLSBuLCBzID0gciAtIGUsIHUgPSBNYXRoLm1pbihvLCBzKSwgZiA9IHRoaXMuc2xpY2UobiwgaSksIGggPSB0LnNsaWNlKGUsIHIpLCBsID0gMDsKICAgICAgICAgICAgICAgIGwgPCB1OwogICAgICAgICAgICAgICAgKytsCiAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgaWYgKGZbbF0gIT09IGhbbF0pIHsKICAobyA9IGZbbF0pLCAocyA9IGhbbF0pOwogICAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiBvIDwgcyA/IC0xIDogcyA8IG8gPyAxIDogMAogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLmluY2x1ZGVzID0gZnVuY3Rpb24gKHQsIGUsIHIpIHsKICAgICAgICAgICAgICByZXR1cm4gLTEgIT09IHRoaXMuaW5kZXhPZih0LCBlLCByKQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLmluZGV4T2YgPSBmdW5jdGlvbiAodCwgZSwgcikgewogICAgICAgICAgICAgIHJldHVybiB5KHRoaXMsIHQsIGUsIHIsICEwKQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLmxhc3RJbmRleE9mID0gZnVuY3Rpb24gKHQsIGUsIHIpIHsKICAgICAgICAgICAgICByZXR1cm4geSh0aGlzLCB0LCBlLCByLCAhMSkKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS53cml0ZSA9IGZ1bmN0aW9uICh0LCBlLCByLCBuKSB7CiAgICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gZSkgKG4gPSAndXRmOCcpLCAociA9IHRoaXMubGVuZ3RoKSwgKGUgPSAwKTsKICAgICAgICAgICAgICBlbHNlIGlmICh2b2lkIDAgPT09IHIgJiYgJ3N0cmluZycgPT0gdHlwZW9mIGUpIChuID0gZSksIChyID0gdGhpcy5sZW5ndGgpLCAoZSA9IDApOwogICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgaWYgKCFpc0Zpbml0ZShlKSkKICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdCdWZmZXIud3JpdGUoc3RyaW5nLCBlbmNvZGluZywgb2Zmc2V0WywgbGVuZ3RoXSkgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZCcpCiAgICAgICAgICAgICAgICA7KGUgfD0gMCksIGlzRmluaXRlKHIpID8gKChyIHw9IDApLCB2b2lkIDAgPT09IG4gJiYgKG4gPSAndXRmOCcpKSA6ICgobiA9IHIpLCAociA9IHZvaWQgMCkpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB2YXIgaSA9IHRoaXMubGVuZ3RoIC0gZTsKICAgICAgICAgICAgICBpZiAoKCh2b2lkIDAgPT09IHIgfHwgciA+IGkpICYmIChyID0gaSksICh0Lmxlbmd0aCA+IDAgJiYgKHIgPCAwIHx8IGUgPCAwKSkgfHwgZSA+IHRoaXMubGVuZ3RoKSkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdBdHRlbXB0IHRvIHdyaXRlIG91dHNpZGUgYnVmZmVyIGJvdW5kcycpCiAgICAgICAgICAgICAgbiB8fCAobiA9ICd1dGY4Jyk7CiAgICAgICAgICAgICAgZm9yICh2YXIgbyA9ICExOyA7ICkKICAgICAgICAgICAgICAgIHN3aXRjaCAobikgewogICAgICAgICAgICAgICAgICBjYXNlICdoZXgnOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBFKHRoaXMsIHQsIGUsIHIpCiAgICAgICAgICAgICAgICAgIGNhc2UgJ3V0ZjgnOgogICAgICAgICAgICAgICAgICBjYXNlICd1dGYtOCc6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHYodGhpcywgdCwgZSwgcikKICAgICAgICAgICAgICAgICAgY2FzZSAnYXNjaWknOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBBKHRoaXMsIHQsIGUsIHIpCiAgICAgICAgICAgICAgICAgIGNhc2UgJ2xhdGluMSc6CiAgICAgICAgICAgICAgICAgIGNhc2UgJ2JpbmFyeSc6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF8odGhpcywgdCwgZSwgcikKICAgICAgICAgICAgICAgICAgY2FzZSAnYmFzZTY0JzoKICAgICAgICAgICAgICAgICAgICByZXR1cm4gYih0aGlzLCB0LCBlLCByKQogICAgICAgICAgICAgICAgICBjYXNlICd1Y3MyJzoKICAgICAgICAgICAgICAgICAgY2FzZSAndWNzLTInOgogICAgICAgICAgICAgICAgICBjYXNlICd1dGYxNmxlJzoKICAgICAgICAgICAgICAgICAgY2FzZSAndXRmLTE2bGUnOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBtKHRoaXMsIHQsIGUsIHIpCiAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgaWYgKG8pIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBuKQogICAgICAgICAgICAgICAgICAgIDsobiA9ICgnJyArIG4pLnRvTG93ZXJDYXNlKCkpLCAobyA9ICEwKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogJ0J1ZmZlcicsIGRhdGE6IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHRoaXMuX2FyciB8fCB0aGlzLCAwKSB9CiAgICAgICAgICAgIH0pOwogICAgICAgICAgdmFyIFQgPSA0MDk2OwogICAgICAgICAgZnVuY3Rpb24gUCh0LCBlLCByKSB7CiAgICAgICAgICAgIHZhciBuID0gJyc7CiAgICAgICAgICAgIHIgPSBNYXRoLm1pbih0Lmxlbmd0aCwgcik7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSBlOyBpIDwgcjsgKytpKSBuICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMTI3ICYgdFtpXSk7CiAgICAgICAgICAgIHJldHVybiBuCiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBDKHQsIGUsIHIpIHsKICAgICAgICAgICAgdmFyIG4gPSAnJzsKICAgICAgICAgICAgciA9IE1hdGgubWluKHQubGVuZ3RoLCByKTsKICAgICAgICAgICAgZm9yICh2YXIgaSA9IGU7IGkgPCByOyArK2kpIG4gKz0gU3RyaW5nLmZyb21DaGFyQ29kZSh0W2ldKTsKICAgICAgICAgICAgcmV0dXJuIG4KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIFUodCwgZSwgcikgewogICAgICAgICAgICB2YXIgbiA9IHQubGVuZ3RoCiAgICAgICAgICAgIDsoIWUgfHwgZSA8IDApICYmIChlID0gMCksICghciB8fCByIDwgMCB8fCByID4gbikgJiYgKHIgPSBuKTsKICAgICAgICAgICAgZm9yICh2YXIgaSA9ICcnLCBvID0gZTsgbyA8IHI7ICsrbykgaSArPSBOKHRbb10pOwogICAgICAgICAgICByZXR1cm4gaQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gQih0LCBlLCByKSB7CiAgICAgICAgICAgIGZvciAodmFyIG4gPSB0LnNsaWNlKGUsIHIpLCBpID0gJycsIG8gPSAwOyBvIDwgbi5sZW5ndGg7IG8gKz0gMikKICAgICAgICAgICAgICBpICs9IFN0cmluZy5mcm9tQ2hhckNvZGUobltvXSArIDI1NiAqIG5bbyArIDFdKTsKICAgICAgICAgICAgcmV0dXJuIGkKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIEYodCwgZSwgcikgewogICAgICAgICAgICBpZiAodCAlIDEgIT0gMCB8fCB0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ29mZnNldCBpcyBub3QgdWludCcpCiAgICAgICAgICAgIGlmICh0ICsgZSA+IHIpIHRocm93IG5ldyBSYW5nZUVycm9yKCdUcnlpbmcgdG8gYWNjZXNzIGJleW9uZCBidWZmZXIgbGVuZ3RoJykKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIE0odCwgZSwgciwgbiwgaSwgbykgewogICAgICAgICAgICBpZiAoIWEuaXNCdWZmZXIodCkpIHRocm93IG5ldyBUeXBlRXJyb3IoJyJidWZmZXIiIGFyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXIgaW5zdGFuY2UnKQogICAgICAgICAgICBpZiAoZSA+IGkgfHwgZSA8IG8pIHRocm93IG5ldyBSYW5nZUVycm9yKCcidmFsdWUiIGFyZ3VtZW50IGlzIG91dCBvZiBib3VuZHMnKQogICAgICAgICAgICBpZiAociArIG4gPiB0Lmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0luZGV4IG91dCBvZiByYW5nZScpCiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiB4KHQsIGUsIHIsIG4pIHsKICAgICAgICAgICAgZSA8IDAgJiYgKGUgPSA2NTUzNSArIGUgKyAxKTsKICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIG8gPSBNYXRoLm1pbih0Lmxlbmd0aCAtIHIsIDIpOyBpIDwgbzsgKytpKQogICAgICAgICAgICAgIHRbciArIGldID0gKGUgJiAoMjU1IDw8ICg4ICogKG4gPyBpIDogMSAtIGkpKSkpID4+PiAoOCAqIChuID8gaSA6IDEgLSBpKSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBJKHQsIGUsIHIsIG4pIHsKICAgICAgICAgICAgZSA8IDAgJiYgKGUgPSA0Mjk0OTY3Mjk1ICsgZSArIDEpOwogICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbyA9IE1hdGgubWluKHQubGVuZ3RoIC0gciwgNCk7IGkgPCBvOyArK2kpIHRbciArIGldID0gKGUgPj4+ICg4ICogKG4gPyBpIDogMyAtIGkpKSkgJiAyNTU7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBPKHQsIGUsIHIsIG4sIGksIG8pIHsKICAgICAgICAgICAgaWYgKHIgKyBuID4gdC5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKQogICAgICAgICAgICBpZiAociA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gWSh0LCBlLCByLCBuLCBvKSB7CiAgICAgICAgICAgIHJldHVybiBvIHx8IE8odCwgMCwgciwgNCksIGkud3JpdGUodCwgZSwgciwgbiwgMjMsIDQpLCByICsgNAogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gTCh0LCBlLCByLCBuLCBvKSB7CiAgICAgICAgICAgIHJldHVybiBvIHx8IE8odCwgMCwgciwgOCksIGkud3JpdGUodCwgZSwgciwgbiwgNTIsIDgpLCByICsgOAogICAgICAgICAgfQogIChhLnByb3RvdHlwZS5zbGljZSA9IGZ1bmN0aW9uICh0LCBlKSB7CiAgICAgICAgICAgIHZhciByLAogICAgICAgICAgICAgIG4gPSB0aGlzLmxlbmd0aDsKICAgICAgICAgICAgaWYgKAogICAgICAgICAgICAgICgodCA9IH5+dCksCiAgICAgICAgICAgICAgKGUgPSB2b2lkIDAgPT09IGUgPyBuIDogfn5lKSwKICAgICAgICAgICAgICB0IDwgMCA/ICh0ICs9IG4pIDwgMCAmJiAodCA9IDApIDogdCA+IG4gJiYgKHQgPSBuKSwKICAgICAgICAgICAgICBlIDwgMCA/IChlICs9IG4pIDwgMCAmJiAoZSA9IDApIDogZSA+IG4gJiYgKGUgPSBuKSwKICAgICAgICAgICAgICBlIDwgdCAmJiAoZSA9IHQpLAogICAgICAgICAgICAgIGEuVFlQRURfQVJSQVlfU1VQUE9SVCkKICAgICAgICAgICAgKQogICAgICAgICAgICAgIChyID0gdGhpcy5zdWJhcnJheSh0LCBlKSkuX19wcm90b19fID0gYS5wcm90b3R5cGU7CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgIHZhciBpID0gZSAtIHQ7CiAgICAgICAgICAgICAgciA9IG5ldyBhKGksIHZvaWQgMCk7CiAgICAgICAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCBpOyArK28pIHJbb10gPSB0aGlzW28gKyB0XTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gcgogICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS5yZWFkVUludExFID0gZnVuY3Rpb24gKHQsIGUsIHIpIHsKICAodCB8PSAwKSwgKGUgfD0gMCksIHIgfHwgRih0LCBlLCB0aGlzLmxlbmd0aCk7CiAgICAgICAgICAgICAgZm9yICh2YXIgbiA9IHRoaXNbdF0sIGkgPSAxLCBvID0gMDsgKytvIDwgZSAmJiAoaSAqPSAyNTYpOyApIG4gKz0gdGhpc1t0ICsgb10gKiBpOwogICAgICAgICAgICAgIHJldHVybiBuCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUucmVhZFVJbnRCRSA9IGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgKHQgfD0gMCksIChlIHw9IDApLCByIHx8IEYodCwgZSwgdGhpcy5sZW5ndGgpOwogICAgICAgICAgICAgIGZvciAodmFyIG4gPSB0aGlzW3QgKyAtLWVdLCBpID0gMTsgZSA+IDAgJiYgKGkgKj0gMjU2KTsgKSBuICs9IHRoaXNbdCArIC0tZV0gKiBpOwogICAgICAgICAgICAgIHJldHVybiBuCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUucmVhZFVJbnQ4ID0gZnVuY3Rpb24gKHQsIGUpIHsKICAgICAgICAgICAgICByZXR1cm4gZSB8fCBGKHQsIDEsIHRoaXMubGVuZ3RoKSwgdGhpc1t0XQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLnJlYWRVSW50MTZMRSA9IGZ1bmN0aW9uICh0LCBlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGUgfHwgRih0LCAyLCB0aGlzLmxlbmd0aCksIHRoaXNbdF0gfCAodGhpc1t0ICsgMV0gPDwgOCkKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS5yZWFkVUludDE2QkUgPSBmdW5jdGlvbiAodCwgZSkgewogICAgICAgICAgICAgIHJldHVybiBlIHx8IEYodCwgMiwgdGhpcy5sZW5ndGgpLCAodGhpc1t0XSA8PCA4KSB8IHRoaXNbdCArIDFdCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUucmVhZFVJbnQzMkxFID0gZnVuY3Rpb24gKHQsIGUpIHsKICAgICAgICAgICAgICByZXR1cm4gKAogICAgICAgICAgICAgICAgZSB8fCBGKHQsIDQsIHRoaXMubGVuZ3RoKSwgKHRoaXNbdF0gfCAodGhpc1t0ICsgMV0gPDwgOCkgfCAodGhpc1t0ICsgMl0gPDwgMTYpKSArIDE2Nzc3MjE2ICogdGhpc1t0ICsgM10KICAgICAgICAgICAgICApCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUucmVhZFVJbnQzMkJFID0gZnVuY3Rpb24gKHQsIGUpIHsKICAgICAgICAgICAgICByZXR1cm4gKAogICAgICAgICAgICAgICAgZSB8fCBGKHQsIDQsIHRoaXMubGVuZ3RoKSwgMTY3NzcyMTYgKiB0aGlzW3RdICsgKCh0aGlzW3QgKyAxXSA8PCAxNikgfCAodGhpc1t0ICsgMl0gPDwgOCkgfCB0aGlzW3QgKyAzXSkKICAgICAgICAgICAgICApCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUucmVhZEludExFID0gZnVuY3Rpb24gKHQsIGUsIHIpIHsKICAodCB8PSAwKSwgKGUgfD0gMCksIHIgfHwgRih0LCBlLCB0aGlzLmxlbmd0aCk7CiAgICAgICAgICAgICAgZm9yICh2YXIgbiA9IHRoaXNbdF0sIGkgPSAxLCBvID0gMDsgKytvIDwgZSAmJiAoaSAqPSAyNTYpOyApIG4gKz0gdGhpc1t0ICsgb10gKiBpOwogICAgICAgICAgICAgIHJldHVybiBuID49IChpICo9IDEyOCkgJiYgKG4gLT0gTWF0aC5wb3coMiwgOCAqIGUpKSwgbgogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLnJlYWRJbnRCRSA9IGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgKHQgfD0gMCksIChlIHw9IDApLCByIHx8IEYodCwgZSwgdGhpcy5sZW5ndGgpOwogICAgICAgICAgICAgIGZvciAodmFyIG4gPSBlLCBpID0gMSwgbyA9IHRoaXNbdCArIC0tbl07IG4gPiAwICYmIChpICo9IDI1Nik7ICkgbyArPSB0aGlzW3QgKyAtLW5dICogaTsKICAgICAgICAgICAgICByZXR1cm4gbyA+PSAoaSAqPSAxMjgpICYmIChvIC09IE1hdGgucG93KDIsIDggKiBlKSksIG8KICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS5yZWFkSW50OCA9IGZ1bmN0aW9uICh0LCBlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGUgfHwgRih0LCAxLCB0aGlzLmxlbmd0aCksIDEyOCAmIHRoaXNbdF0gPyAtMSAqICgyNTUgLSB0aGlzW3RdICsgMSkgOiB0aGlzW3RdCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUucmVhZEludDE2TEUgPSBmdW5jdGlvbiAodCwgZSkgewogICAgICAgICAgICAgIGUgfHwgRih0LCAyLCB0aGlzLmxlbmd0aCk7CiAgICAgICAgICAgICAgdmFyIHIgPSB0aGlzW3RdIHwgKHRoaXNbdCArIDFdIDw8IDgpOwogICAgICAgICAgICAgIHJldHVybiAzMjc2OCAmIHIgPyA0Mjk0OTAxNzYwIHwgciA6IHIKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS5yZWFkSW50MTZCRSA9IGZ1bmN0aW9uICh0LCBlKSB7CiAgICAgICAgICAgICAgZSB8fCBGKHQsIDIsIHRoaXMubGVuZ3RoKTsKICAgICAgICAgICAgICB2YXIgciA9IHRoaXNbdCArIDFdIHwgKHRoaXNbdF0gPDwgOCk7CiAgICAgICAgICAgICAgcmV0dXJuIDMyNzY4ICYgciA/IDQyOTQ5MDE3NjAgfCByIDogcgogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLnJlYWRJbnQzMkxFID0gZnVuY3Rpb24gKHQsIGUpIHsKICAgICAgICAgICAgICByZXR1cm4gZSB8fCBGKHQsIDQsIHRoaXMubGVuZ3RoKSwgdGhpc1t0XSB8ICh0aGlzW3QgKyAxXSA8PCA4KSB8ICh0aGlzW3QgKyAyXSA8PCAxNikgfCAodGhpc1t0ICsgM10gPDwgMjQpCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUucmVhZEludDMyQkUgPSBmdW5jdGlvbiAodCwgZSkgewogICAgICAgICAgICAgIHJldHVybiBlIHx8IEYodCwgNCwgdGhpcy5sZW5ndGgpLCAodGhpc1t0XSA8PCAyNCkgfCAodGhpc1t0ICsgMV0gPDwgMTYpIHwgKHRoaXNbdCArIDJdIDw8IDgpIHwgdGhpc1t0ICsgM10KICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS5yZWFkRmxvYXRMRSA9IGZ1bmN0aW9uICh0LCBlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGUgfHwgRih0LCA0LCB0aGlzLmxlbmd0aCksIGkucmVhZCh0aGlzLCB0LCAhMCwgMjMsIDQpCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUucmVhZEZsb2F0QkUgPSBmdW5jdGlvbiAodCwgZSkgewogICAgICAgICAgICAgIHJldHVybiBlIHx8IEYodCwgNCwgdGhpcy5sZW5ndGgpLCBpLnJlYWQodGhpcywgdCwgITEsIDIzLCA0KQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLnJlYWREb3VibGVMRSA9IGZ1bmN0aW9uICh0LCBlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGUgfHwgRih0LCA4LCB0aGlzLmxlbmd0aCksIGkucmVhZCh0aGlzLCB0LCAhMCwgNTIsIDgpCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUucmVhZERvdWJsZUJFID0gZnVuY3Rpb24gKHQsIGUpIHsKICAgICAgICAgICAgICByZXR1cm4gZSB8fCBGKHQsIDgsIHRoaXMubGVuZ3RoKSwgaS5yZWFkKHRoaXMsIHQsICExLCA1MiwgOCkKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS53cml0ZVVJbnRMRSA9IGZ1bmN0aW9uICh0LCBlLCByLCBuKSB7CiAgKCh0ID0gK3QpLCAoZSB8PSAwKSwgKHIgfD0gMCksIG4pIHx8IE0odGhpcywgdCwgZSwgciwgTWF0aC5wb3coMiwgOCAqIHIpIC0gMSwgMCk7CiAgICAgICAgICAgICAgdmFyIGkgPSAxLAogICAgICAgICAgICAgICAgbyA9IDA7CiAgICAgICAgICAgICAgZm9yICh0aGlzW2VdID0gMjU1ICYgdDsgKytvIDwgciAmJiAoaSAqPSAyNTYpOyApIHRoaXNbZSArIG9dID0gKHQgLyBpKSAmIDI1NTsKICAgICAgICAgICAgICByZXR1cm4gZSArIHIKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS53cml0ZVVJbnRCRSA9IGZ1bmN0aW9uICh0LCBlLCByLCBuKSB7CiAgKCh0ID0gK3QpLCAoZSB8PSAwKSwgKHIgfD0gMCksIG4pIHx8IE0odGhpcywgdCwgZSwgciwgTWF0aC5wb3coMiwgOCAqIHIpIC0gMSwgMCk7CiAgICAgICAgICAgICAgdmFyIGkgPSByIC0gMSwKICAgICAgICAgICAgICAgIG8gPSAxOwogICAgICAgICAgICAgIGZvciAodGhpc1tlICsgaV0gPSAyNTUgJiB0OyAtLWkgPj0gMCAmJiAobyAqPSAyNTYpOyApIHRoaXNbZSArIGldID0gKHQgLyBvKSAmIDI1NTsKICAgICAgICAgICAgICByZXR1cm4gZSArIHIKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS53cml0ZVVJbnQ4ID0gZnVuY3Rpb24gKHQsIGUsIHIpIHsKICAgICAgICAgICAgICByZXR1cm4gKAogICAgICAgICAgICAgICAgKHQgPSArdCksCiAgICAgICAgICAgICAgICAoZSB8PSAwKSwKICAgICAgICAgICAgICAgIHIgfHwgTSh0aGlzLCB0LCBlLCAxLCAyNTUsIDApLAogICAgICAgICAgICAgICAgYS5UWVBFRF9BUlJBWV9TVVBQT1JUIHx8ICh0ID0gTWF0aC5mbG9vcih0KSksCiAgICAgICAgICAgICAgICAodGhpc1tlXSA9IDI1NSAmIHQpLAogICAgICAgICAgICAgICAgZSArIDEKICAgICAgICAgICAgICApCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUud3JpdGVVSW50MTZMRSA9IGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgICAgICAgICAgICAgcmV0dXJuICgKICAgICAgICAgICAgICAgICh0ID0gK3QpLAogICAgICAgICAgICAgICAgKGUgfD0gMCksCiAgICAgICAgICAgICAgICByIHx8IE0odGhpcywgdCwgZSwgMiwgNjU1MzUsIDApLAogICAgICAgICAgICAgICAgYS5UWVBFRF9BUlJBWV9TVVBQT1JUID8gKCh0aGlzW2VdID0gMjU1ICYgdCksICh0aGlzW2UgKyAxXSA9IHQgPj4+IDgpKSA6IHgodGhpcywgdCwgZSwgITApLAogICAgICAgICAgICAgICAgZSArIDIKICAgICAgICAgICAgICApCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUud3JpdGVVSW50MTZCRSA9IGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgICAgICAgICAgICAgcmV0dXJuICgKICAgICAgICAgICAgICAgICh0ID0gK3QpLAogICAgICAgICAgICAgICAgKGUgfD0gMCksCiAgICAgICAgICAgICAgICByIHx8IE0odGhpcywgdCwgZSwgMiwgNjU1MzUsIDApLAogICAgICAgICAgICAgICAgYS5UWVBFRF9BUlJBWV9TVVBQT1JUID8gKCh0aGlzW2VdID0gdCA+Pj4gOCksICh0aGlzW2UgKyAxXSA9IDI1NSAmIHQpKSA6IHgodGhpcywgdCwgZSwgITEpLAogICAgICAgICAgICAgICAgZSArIDIKICAgICAgICAgICAgICApCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUud3JpdGVVSW50MzJMRSA9IGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgICAgICAgICAgICAgcmV0dXJuICgKICAgICAgICAgICAgICAgICh0ID0gK3QpLAogICAgICAgICAgICAgICAgKGUgfD0gMCksCiAgICAgICAgICAgICAgICByIHx8IE0odGhpcywgdCwgZSwgNCwgNDI5NDk2NzI5NSwgMCksCiAgICAgICAgICAgICAgICBhLlRZUEVEX0FSUkFZX1NVUFBPUlQKICAgICAgICAgICAgICAgICAgPyAoKHRoaXNbZSArIDNdID0gdCA+Pj4gMjQpLCAodGhpc1tlICsgMl0gPSB0ID4+PiAxNiksICh0aGlzW2UgKyAxXSA9IHQgPj4+IDgpLCAodGhpc1tlXSA9IDI1NSAmIHQpKQogICAgICAgICAgICAgICAgICA6IEkodGhpcywgdCwgZSwgITApLAogICAgICAgICAgICAgICAgZSArIDQKICAgICAgICAgICAgICApCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUud3JpdGVVSW50MzJCRSA9IGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgICAgICAgICAgICAgcmV0dXJuICgKICAgICAgICAgICAgICAgICh0ID0gK3QpLAogICAgICAgICAgICAgICAgKGUgfD0gMCksCiAgICAgICAgICAgICAgICByIHx8IE0odGhpcywgdCwgZSwgNCwgNDI5NDk2NzI5NSwgMCksCiAgICAgICAgICAgICAgICBhLlRZUEVEX0FSUkFZX1NVUFBPUlQKICAgICAgICAgICAgICAgICAgPyAoKHRoaXNbZV0gPSB0ID4+PiAyNCksICh0aGlzW2UgKyAxXSA9IHQgPj4+IDE2KSwgKHRoaXNbZSArIDJdID0gdCA+Pj4gOCksICh0aGlzW2UgKyAzXSA9IDI1NSAmIHQpKQogICAgICAgICAgICAgICAgICA6IEkodGhpcywgdCwgZSwgITEpLAogICAgICAgICAgICAgICAgZSArIDQKICAgICAgICAgICAgICApCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUud3JpdGVJbnRMRSA9IGZ1bmN0aW9uICh0LCBlLCByLCBuKSB7CiAgICAgICAgICAgICAgaWYgKCgodCA9ICt0KSwgKGUgfD0gMCksICFuKSkgewogICAgICAgICAgICAgICAgdmFyIGkgPSBNYXRoLnBvdygyLCA4ICogciAtIDEpOwogICAgICAgICAgICAgICAgTSh0aGlzLCB0LCBlLCByLCBpIC0gMSwgLWkpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB2YXIgbyA9IDAsCiAgICAgICAgICAgICAgICBzID0gMSwKICAgICAgICAgICAgICAgIHUgPSAwOwogICAgICAgICAgICAgIGZvciAodGhpc1tlXSA9IDI1NSAmIHQ7ICsrbyA8IHIgJiYgKHMgKj0gMjU2KTsgKQogICAgICAgICAgICAgICAgdCA8IDAgJiYgMCA9PT0gdSAmJiAwICE9PSB0aGlzW2UgKyBvIC0gMV0gJiYgKHUgPSAxKSwgKHRoaXNbZSArIG9dID0gKCgodCAvIHMpID4+IDApIC0gdSkgJiAyNTUpOwogICAgICAgICAgICAgIHJldHVybiBlICsgcgogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLndyaXRlSW50QkUgPSBmdW5jdGlvbiAodCwgZSwgciwgbikgewogICAgICAgICAgICAgIGlmICgoKHQgPSArdCksIChlIHw9IDApLCAhbikpIHsKICAgICAgICAgICAgICAgIHZhciBpID0gTWF0aC5wb3coMiwgOCAqIHIgLSAxKTsKICAgICAgICAgICAgICAgIE0odGhpcywgdCwgZSwgciwgaSAtIDEsIC1pKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmFyIG8gPSByIC0gMSwKICAgICAgICAgICAgICAgIHMgPSAxLAogICAgICAgICAgICAgICAgdSA9IDA7CiAgICAgICAgICAgICAgZm9yICh0aGlzW2UgKyBvXSA9IDI1NSAmIHQ7IC0tbyA+PSAwICYmIChzICo9IDI1Nik7ICkKICAgICAgICAgICAgICAgIHQgPCAwICYmIDAgPT09IHUgJiYgMCAhPT0gdGhpc1tlICsgbyArIDFdICYmICh1ID0gMSksICh0aGlzW2UgKyBvXSA9ICgoKHQgLyBzKSA+PiAwKSAtIHUpICYgMjU1KTsKICAgICAgICAgICAgICByZXR1cm4gZSArIHIKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbiAodCwgZSwgcikgewogICAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICAodCA9ICt0KSwKICAgICAgICAgICAgICAgIChlIHw9IDApLAogICAgICAgICAgICAgICAgciB8fCBNKHRoaXMsIHQsIGUsIDEsIDEyNywgLTEyOCksCiAgICAgICAgICAgICAgICBhLlRZUEVEX0FSUkFZX1NVUFBPUlQgfHwgKHQgPSBNYXRoLmZsb29yKHQpKSwKICAgICAgICAgICAgICAgIHQgPCAwICYmICh0ID0gMjU1ICsgdCArIDEpLAogICAgICAgICAgICAgICAgKHRoaXNbZV0gPSAyNTUgJiB0KSwKICAgICAgICAgICAgICAgIGUgKyAxCiAgICAgICAgICAgICAgKQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLndyaXRlSW50MTZMRSA9IGZ1bmN0aW9uICh0LCBlLCByKSB7CiAgICAgICAgICAgICAgcmV0dXJuICgKICAgICAgICAgICAgICAgICh0ID0gK3QpLAogICAgICAgICAgICAgICAgKGUgfD0gMCksCiAgICAgICAgICAgICAgICByIHx8IE0odGhpcywgdCwgZSwgMiwgMzI3NjcsIC0zMjc2OCksCiAgICAgICAgICAgICAgICBhLlRZUEVEX0FSUkFZX1NVUFBPUlQgPyAoKHRoaXNbZV0gPSAyNTUgJiB0KSwgKHRoaXNbZSArIDFdID0gdCA+Pj4gOCkpIDogeCh0aGlzLCB0LCBlLCAhMCksCiAgICAgICAgICAgICAgICBlICsgMgogICAgICAgICAgICAgICkKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS53cml0ZUludDE2QkUgPSBmdW5jdGlvbiAodCwgZSwgcikgewogICAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICAodCA9ICt0KSwKICAgICAgICAgICAgICAgIChlIHw9IDApLAogICAgICAgICAgICAgICAgciB8fCBNKHRoaXMsIHQsIGUsIDIsIDMyNzY3LCAtMzI3NjgpLAogICAgICAgICAgICAgICAgYS5UWVBFRF9BUlJBWV9TVVBQT1JUID8gKCh0aGlzW2VdID0gdCA+Pj4gOCksICh0aGlzW2UgKyAxXSA9IDI1NSAmIHQpKSA6IHgodGhpcywgdCwgZSwgITEpLAogICAgICAgICAgICAgICAgZSArIDIKICAgICAgICAgICAgICApCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUud3JpdGVJbnQzMkxFID0gZnVuY3Rpb24gKHQsIGUsIHIpIHsKICAgICAgICAgICAgICByZXR1cm4gKAogICAgICAgICAgICAgICAgKHQgPSArdCksCiAgICAgICAgICAgICAgICAoZSB8PSAwKSwKICAgICAgICAgICAgICAgIHIgfHwgTSh0aGlzLCB0LCBlLCA0LCAyMTQ3NDgzNjQ3LCAtMjE0NzQ4MzY0OCksCiAgICAgICAgICAgICAgICBhLlRZUEVEX0FSUkFZX1NVUFBPUlQKICAgICAgICAgICAgICAgICAgPyAoKHRoaXNbZV0gPSAyNTUgJiB0KSwgKHRoaXNbZSArIDFdID0gdCA+Pj4gOCksICh0aGlzW2UgKyAyXSA9IHQgPj4+IDE2KSwgKHRoaXNbZSArIDNdID0gdCA+Pj4gMjQpKQogICAgICAgICAgICAgICAgICA6IEkodGhpcywgdCwgZSwgITApLAogICAgICAgICAgICAgICAgZSArIDQKICAgICAgICAgICAgICApCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUud3JpdGVJbnQzMkJFID0gZnVuY3Rpb24gKHQsIGUsIHIpIHsKICAgICAgICAgICAgICByZXR1cm4gKAogICAgICAgICAgICAgICAgKHQgPSArdCksCiAgICAgICAgICAgICAgICAoZSB8PSAwKSwKICAgICAgICAgICAgICAgIHIgfHwgTSh0aGlzLCB0LCBlLCA0LCAyMTQ3NDgzNjQ3LCAtMjE0NzQ4MzY0OCksCiAgICAgICAgICAgICAgICB0IDwgMCAmJiAodCA9IDQyOTQ5NjcyOTUgKyB0ICsgMSksCiAgICAgICAgICAgICAgICBhLlRZUEVEX0FSUkFZX1NVUFBPUlQKICAgICAgICAgICAgICAgICAgPyAoKHRoaXNbZV0gPSB0ID4+PiAyNCksICh0aGlzW2UgKyAxXSA9IHQgPj4+IDE2KSwgKHRoaXNbZSArIDJdID0gdCA+Pj4gOCksICh0aGlzW2UgKyAzXSA9IDI1NSAmIHQpKQogICAgICAgICAgICAgICAgICA6IEkodGhpcywgdCwgZSwgITEpLAogICAgICAgICAgICAgICAgZSArIDQKICAgICAgICAgICAgICApCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUud3JpdGVGbG9hdExFID0gZnVuY3Rpb24gKHQsIGUsIHIpIHsKICAgICAgICAgICAgICByZXR1cm4gWSh0aGlzLCB0LCBlLCAhMCwgcikKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChhLnByb3RvdHlwZS53cml0ZUZsb2F0QkUgPSBmdW5jdGlvbiAodCwgZSwgcikgewogICAgICAgICAgICAgIHJldHVybiBZKHRoaXMsIHQsIGUsICExLCByKQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLndyaXRlRG91YmxlTEUgPSBmdW5jdGlvbiAodCwgZSwgcikgewogICAgICAgICAgICAgIHJldHVybiBMKHRoaXMsIHQsIGUsICEwLCByKQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbiAodCwgZSwgcikgewogICAgICAgICAgICAgIHJldHVybiBMKHRoaXMsIHQsIGUsICExLCByKQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGEucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiAodCwgZSwgciwgbikgewogICAgICAgICAgICAgIGlmICgKICAgICAgICAgICAgICAgIChyIHx8IChyID0gMCksCiAgICAgICAgICAgICAgICBuIHx8IDAgPT09IG4gfHwgKG4gPSB0aGlzLmxlbmd0aCksCiAgICAgICAgICAgICAgICBlID49IHQubGVuZ3RoICYmIChlID0gdC5sZW5ndGgpLAogICAgICAgICAgICAgICAgZSB8fCAoZSA9IDApLAogICAgICAgICAgICAgICAgbiA+IDAgJiYgbiA8IHIgJiYgKG4gPSByKSwKICAgICAgICAgICAgICAgIG4gPT09IHIpCiAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgcmV0dXJuIDAKICAgICAgICAgICAgICBpZiAoMCA9PT0gdC5sZW5ndGggfHwgMCA9PT0gdGhpcy5sZW5ndGgpIHJldHVybiAwCiAgICAgICAgICAgICAgaWYgKGUgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcigndGFyZ2V0U3RhcnQgb3V0IG9mIGJvdW5kcycpCiAgICAgICAgICAgICAgaWYgKHIgPCAwIHx8IHIgPj0gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VTdGFydCBvdXQgb2YgYm91bmRzJykKICAgICAgICAgICAgICBpZiAobiA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VFbmQgb3V0IG9mIGJvdW5kcycpCiAgICAgICAgICAgICAgbiA+IHRoaXMubGVuZ3RoICYmIChuID0gdGhpcy5sZW5ndGgpLCB0Lmxlbmd0aCAtIGUgPCBuIC0gciAmJiAobiA9IHQubGVuZ3RoIC0gZSArIHIpOwogICAgICAgICAgICAgIHZhciBpLAogICAgICAgICAgICAgICAgbyA9IG4gLSByOwogICAgICAgICAgICAgIGlmICh0aGlzID09PSB0ICYmIHIgPCBlICYmIGUgPCBuKSBmb3IgKGkgPSBvIC0gMTsgaSA+PSAwOyAtLWkpIHRbaSArIGVdID0gdGhpc1tpICsgcl07CiAgICAgICAgICAgICAgZWxzZSBpZiAobyA8IDFlMyB8fCAhYS5UWVBFRF9BUlJBWV9TVVBQT1JUKSBmb3IgKGkgPSAwOyBpIDwgbzsgKytpKSB0W2kgKyBlXSA9IHRoaXNbaSArIHJdOwogICAgICAgICAgICAgIGVsc2UgVWludDhBcnJheS5wcm90b3R5cGUuc2V0LmNhbGwodCwgdGhpcy5zdWJhcnJheShyLCByICsgbyksIGUpOwogICAgICAgICAgICAgIHJldHVybiBvCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoYS5wcm90b3R5cGUuZmlsbCA9IGZ1bmN0aW9uICh0LCBlLCByLCBuKSB7CiAgICAgICAgICAgICAgaWYgKCdzdHJpbmcnID09IHR5cGVvZiB0KSB7CiAgICAgICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICAgICgnc3RyaW5nJyA9PSB0eXBlb2YgZQogICAgICAgICAgICAgICAgICAgID8gKChuID0gZSksIChlID0gMCksIChyID0gdGhpcy5sZW5ndGgpKQogICAgICAgICAgICAgICAgICAgIDogJ3N0cmluZycgPT0gdHlwZW9mIHIgJiYgKChuID0gciksIChyID0gdGhpcy5sZW5ndGgpKSwKICAgICAgICAgICAgICAgICAgMSA9PT0gdC5sZW5ndGgpCiAgICAgICAgICAgICAgICApIHsKICAgICAgICAgICAgICAgICAgdmFyIGkgPSB0LmNoYXJDb2RlQXQoMCk7CiAgICAgICAgICAgICAgICAgIGkgPCAyNTYgJiYgKHQgPSBpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmICh2b2lkIDAgIT09IG4gJiYgJ3N0cmluZycgIT0gdHlwZW9mIG4pIHRocm93IG5ldyBUeXBlRXJyb3IoJ2VuY29kaW5nIG11c3QgYmUgYSBzdHJpbmcnKQogICAgICAgICAgICAgICAgaWYgKCdzdHJpbmcnID09IHR5cGVvZiBuICYmICFhLmlzRW5jb2RpbmcobikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBuKQogICAgICAgICAgICAgIH0gZWxzZSAnbnVtYmVyJyA9PSB0eXBlb2YgdCAmJiAodCAmPSAyNTUpOwogICAgICAgICAgICAgIGlmIChlIDwgMCB8fCB0aGlzLmxlbmd0aCA8IGUgfHwgdGhpcy5sZW5ndGggPCByKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignT3V0IG9mIHJhbmdlIGluZGV4JykKICAgICAgICAgICAgICBpZiAociA8PSBlKSByZXR1cm4gdGhpcwogICAgICAgICAgICAgIHZhciBvOwogICAgICAgICAgICAgIGlmICgoKGUgPj4+PSAwKSwgKHIgPSB2b2lkIDAgPT09IHIgPyB0aGlzLmxlbmd0aCA6IHIgPj4+IDApLCB0IHx8ICh0ID0gMCksICdudW1iZXInID09IHR5cGVvZiB0KSkKICAgICAgICAgICAgICAgIGZvciAobyA9IGU7IG8gPCByOyArK28pIHRoaXNbb10gPSB0OwogICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdmFyIHMgPSBhLmlzQnVmZmVyKHQpID8gdCA6IGsobmV3IGEodCwgbikudG9TdHJpbmcoKSksCiAgICAgICAgICAgICAgICAgIHUgPSBzLmxlbmd0aDsKICAgICAgICAgICAgICAgIGZvciAobyA9IDA7IG8gPCByIC0gZTsgKytvKSB0aGlzW28gKyBlXSA9IHNbbyAlIHVdOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gdGhpcwogICAgICAgICAgICB9KTsKICAgICAgICAgIHZhciBEID0gL1teK1wvMC05QS1aYS16LV9dL2c7CiAgICAgICAgICBmdW5jdGlvbiBOKHQpIHsKICAgICAgICAgICAgcmV0dXJuIHQgPCAxNiA/ICcwJyArIHQudG9TdHJpbmcoMTYpIDogdC50b1N0cmluZygxNikKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGsodCwgZSkgewogICAgICAgICAgICB2YXIgcjsKICAgICAgICAgICAgZSA9IGUgfHwgMSAvIDA7CiAgICAgICAgICAgIGZvciAodmFyIG4gPSB0Lmxlbmd0aCwgaSA9IG51bGwsIG8gPSBbXSwgcyA9IDA7IHMgPCBuOyArK3MpIHsKICAgICAgICAgICAgICBpZiAoKHIgPSB0LmNoYXJDb2RlQXQocykpID4gNTUyOTUgJiYgciA8IDU3MzQ0KSB7CiAgICAgICAgICAgICAgICBpZiAoIWkpIHsKICAgICAgICAgICAgICAgICAgaWYgKHIgPiA1NjMxOSkgewogIChlIC09IDMpID4gLTEgJiYgby5wdXNoKDIzOSwgMTkxLCAxODkpOwogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKHMgKyAxID09PSBuKSB7CiAgKGUgLT0gMykgPiAtMSAmJiBvLnB1c2goMjM5LCAxOTEsIDE4OSk7CiAgICAgICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpID0gcjsKICAgICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChyIDwgNTYzMjApIHsKICAoZSAtPSAzKSA+IC0xICYmIG8ucHVzaCgyMzksIDE5MSwgMTg5KSwgKGkgPSByKTsKICAgICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHIgPSA2NTUzNiArICgoKGkgLSA1NTI5NikgPDwgMTApIHwgKHIgLSA1NjMyMCkpOwogICAgICAgICAgICAgIH0gZWxzZSBpICYmIChlIC09IDMpID4gLTEgJiYgby5wdXNoKDIzOSwgMTkxLCAxODkpOwogICAgICAgICAgICAgIGlmICgoKGkgPSBudWxsKSwgciA8IDEyOCkpIHsKICAgICAgICAgICAgICAgIGlmICgoZSAtPSAxKSA8IDApIGJyZWFrCiAgICAgICAgICAgICAgICBvLnB1c2gocik7CiAgICAgICAgICAgICAgfSBlbHNlIGlmIChyIDwgMjA0OCkgewogICAgICAgICAgICAgICAgaWYgKChlIC09IDIpIDwgMCkgYnJlYWsKICAgICAgICAgICAgICAgIG8ucHVzaCgociA+PiA2KSB8IDE5MiwgKDYzICYgcikgfCAxMjgpOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAociA8IDY1NTM2KSB7CiAgICAgICAgICAgICAgICBpZiAoKGUgLT0gMykgPCAwKSBicmVhawogICAgICAgICAgICAgICAgby5wdXNoKChyID4+IDEyKSB8IDIyNCwgKChyID4+IDYpICYgNjMpIHwgMTI4LCAoNjMgJiByKSB8IDEyOCk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGlmICghKHIgPCAxMTE0MTEyKSkgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvZGUgcG9pbnQnKQogICAgICAgICAgICAgICAgaWYgKChlIC09IDQpIDwgMCkgYnJlYWsKICAgICAgICAgICAgICAgIG8ucHVzaCgociA+PiAxOCkgfCAyNDAsICgociA+PiAxMikgJiA2MykgfCAxMjgsICgociA+PiA2KSAmIDYzKSB8IDEyOCwgKDYzICYgcikgfCAxMjgpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gaih0KSB7CiAgICAgICAgICAgIHJldHVybiBuLnRvQnl0ZUFycmF5KAogICAgICAgICAgICAgIChmdW5jdGlvbiAodCkgewogICAgICAgICAgICAgICAgaWYgKAogICAgICAgICAgICAgICAgICAodCA9IChmdW5jdGlvbiAodCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiB0LnRyaW0gPyB0LnRyaW0oKSA6IHQucmVwbGFjZSgvXlxzK3xccyskL2csICcnKQogICAgICAgICAgICAgICAgICB9KSh0KS5yZXBsYWNlKEQsICcnKSkubGVuZ3RoIDwgMgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICByZXR1cm4gJycKICAgICAgICAgICAgICAgIGZvciAoOyB0Lmxlbmd0aCAlIDQgIT0gMDsgKSB0ICs9ICc9JzsKICAgICAgICAgICAgICAgIHJldHVybiB0CiAgICAgICAgICAgICAgfSkodCkKICAgICAgICAgICAgKQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24geih0LCBlLCByLCBuKSB7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbiAmJiAhKGkgKyByID49IGUubGVuZ3RoIHx8IGkgPj0gdC5sZW5ndGgpOyArK2kpIGVbaSArIHJdID0gdFtpXTsKICAgICAgICAgICAgcmV0dXJuIGkKICAgICAgICAgIH0KICAgICAgICB9LmNhbGwodGhpcywgcig4KSkpOwogICAgICB9LAogICAgICBmdW5jdGlvbiAodCwgZSkgewogICAgICAgIHZhciByOwogICAgICAgIHIgPSAoZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuIHRoaXMKICAgICAgICB9KSgpOwogICAgICAgIHRyeSB7CiAgICAgICAgICByID0gciB8fCBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpIHx8ICgwLCBldmFsKSgndGhpcycpOwogICAgICAgIH0gY2F0Y2ggKHQpIHsKICAgICAgICAgICdvYmplY3QnID09IHR5cGVvZiB3aW5kb3cgJiYgKHIgPSB3aW5kb3cpOwogICAgICAgIH0KICAgICAgICB0LmV4cG9ydHMgPSByOwogICAgICB9LAogICAgICBmdW5jdGlvbiAodCwgZSwgcikgewogIChlLmJ5dGVMZW5ndGggPSBmdW5jdGlvbiAodCkgewogICAgICAgICAgdmFyIGUgPSBmKHQpLAogICAgICAgICAgICByID0gZVswXSwKICAgICAgICAgICAgbiA9IGVbMV07CiAgICAgICAgICByZXR1cm4gKDMgKiAociArIG4pKSAvIDQgLSBuCiAgICAgICAgfSksCiAgICAgICAgICAoZS50b0J5dGVBcnJheSA9IGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAgIGZvciAoCiAgICAgICAgICAgICAgdmFyIGUsCiAgICAgICAgICAgICAgICByID0gZih0KSwKICAgICAgICAgICAgICAgIG4gPSByWzBdLAogICAgICAgICAgICAgICAgcyA9IHJbMV0sCiAgICAgICAgICAgICAgICB1ID0gbmV3IG8oCiAgICAgICAgICAgICAgICAgIChmdW5jdGlvbiAodCwgZSwgcikgewogICAgICAgICAgICAgICAgICAgIHJldHVybiAoMyAqIChlICsgcikpIC8gNCAtIHIKICAgICAgICAgICAgICAgICAgfSkoMCwgbiwgcykKICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICBhID0gMCwKICAgICAgICAgICAgICAgIGggPSBzID4gMCA/IG4gLSA0IDogbiwKICAgICAgICAgICAgICAgIGwgPSAwOwogICAgICAgICAgICAgIGwgPCBoOwogICAgICAgICAgICAgIGwgKz0gNAogICAgICAgICAgICApCiAgICAgICAgICAgICAgKGUgPQogICAgICAgICAgICAgICAgKGlbdC5jaGFyQ29kZUF0KGwpXSA8PCAxOCkgfAogICAgICAgICAgICAgICAgKGlbdC5jaGFyQ29kZUF0KGwgKyAxKV0gPDwgMTIpIHwKICAgICAgICAgICAgICAgIChpW3QuY2hhckNvZGVBdChsICsgMildIDw8IDYpIHwKICAgICAgICAgICAgICAgIGlbdC5jaGFyQ29kZUF0KGwgKyAzKV0pLAogICAgICAgICAgICAgICAgKHVbYSsrXSA9IChlID4+IDE2KSAmIDI1NSksCiAgICAgICAgICAgICAgICAodVthKytdID0gKGUgPj4gOCkgJiAyNTUpLAogICAgICAgICAgICAgICAgKHVbYSsrXSA9IDI1NSAmIGUpOwogICAgICAgICAgICAyID09PSBzICYmICgoZSA9IChpW3QuY2hhckNvZGVBdChsKV0gPDwgMikgfCAoaVt0LmNoYXJDb2RlQXQobCArIDEpXSA+PiA0KSksICh1W2ErK10gPSAyNTUgJiBlKSk7CiAgICAgICAgICAgIDEgPT09IHMgJiYKICAgICAgICAgICAgICAoKGUgPSAoaVt0LmNoYXJDb2RlQXQobCldIDw8IDEwKSB8IChpW3QuY2hhckNvZGVBdChsICsgMSldIDw8IDQpIHwgKGlbdC5jaGFyQ29kZUF0KGwgKyAyKV0gPj4gMikpLAogICAgICAgICAgICAgICh1W2ErK10gPSAoZSA+PiA4KSAmIDI1NSksCiAgICAgICAgICAgICAgKHVbYSsrXSA9IDI1NSAmIGUpKTsKICAgICAgICAgICAgcmV0dXJuIHUKICAgICAgICAgIH0pLAogICAgICAgICAgKGUuZnJvbUJ5dGVBcnJheSA9IGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAgIGZvciAodmFyIGUsIHIgPSB0Lmxlbmd0aCwgaSA9IHIgJSAzLCBvID0gW10sIHMgPSAwLCB1ID0gciAtIGk7IHMgPCB1OyBzICs9IDE2MzgzKQogICAgICAgICAgICAgIG8ucHVzaChsKHQsIHMsIHMgKyAxNjM4MyA+IHUgPyB1IDogcyArIDE2MzgzKSk7CiAgICAgICAgICAgIDEgPT09IGkKICAgICAgICAgICAgICA/ICgoZSA9IHRbciAtIDFdKSwgby5wdXNoKG5bZSA+PiAyXSArIG5bKGUgPDwgNCkgJiA2M10gKyAnPT0nKSkKICAgICAgICAgICAgICA6IDIgPT09IGkgJiYKICAgICAgICAgICAgICAgICgoZSA9ICh0W3IgLSAyXSA8PCA4KSArIHRbciAtIDFdKSwgby5wdXNoKG5bZSA+PiAxMF0gKyBuWyhlID4+IDQpICYgNjNdICsgblsoZSA8PCAyKSAmIDYzXSArICc9JykpOwogICAgICAgICAgICByZXR1cm4gby5qb2luKCcnKQogICAgICAgICAgfSk7CiAgICAgICAgZm9yICgKICAgICAgICAgIHZhciBuID0gW10sCiAgICAgICAgICAgIGkgPSBbXSwKICAgICAgICAgICAgbyA9ICd1bmRlZmluZWQnICE9IHR5cGVvZiBVaW50OEFycmF5ID8gVWludDhBcnJheSA6IEFycmF5LAogICAgICAgICAgICBzID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8nLAogICAgICAgICAgICB1ID0gMCwKICAgICAgICAgICAgYSA9IHMubGVuZ3RoOwogICAgICAgICAgdSA8IGE7CiAgICAgICAgICArK3UKICAgICAgICApCiAgICAgICAgICAoblt1XSA9IHNbdV0pLCAoaVtzLmNoYXJDb2RlQXQodSldID0gdSk7CiAgICAgICAgZnVuY3Rpb24gZih0KSB7CiAgICAgICAgICB2YXIgZSA9IHQubGVuZ3RoOwogICAgICAgICAgaWYgKGUgJSA0ID4gMCkgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHN0cmluZy4gTGVuZ3RoIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA0JykKICAgICAgICAgIHZhciByID0gdC5pbmRleE9mKCc9Jyk7CiAgICAgICAgICByZXR1cm4gLTEgPT09IHIgJiYgKHIgPSBlKSwgW3IsIHIgPT09IGUgPyAwIDogNCAtIChyICUgNCldCiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGgodCkgewogICAgICAgICAgcmV0dXJuIG5bKHQgPj4gMTgpICYgNjNdICsgblsodCA+PiAxMikgJiA2M10gKyBuWyh0ID4+IDYpICYgNjNdICsgbls2MyAmIHRdCiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGwodCwgZSwgcikgewogICAgICAgICAgZm9yICh2YXIgbiwgaSA9IFtdLCBvID0gZTsgbyA8IHI7IG8gKz0gMykKICAgICAgICAgICAgKG4gPSAoKHRbb10gPDwgMTYpICYgMTY3MTE2ODApICsgKCh0W28gKyAxXSA8PCA4KSAmIDY1MjgwKSArICgyNTUgJiB0W28gKyAyXSkpLCBpLnB1c2goaChuKSk7CiAgICAgICAgICByZXR1cm4gaS5qb2luKCcnKQogICAgICAgIH0KICAoaVsnLScuY2hhckNvZGVBdCgwKV0gPSA2MiksIChpWydfJy5jaGFyQ29kZUF0KDApXSA9IDYzKTsKICAgICAgfSwKICAgICAgZnVuY3Rpb24gKHQsIGUpIHsKICAoZS5yZWFkID0gZnVuY3Rpb24gKHQsIGUsIHIsIG4sIGkpIHsKICAgICAgICAgIHZhciBvLAogICAgICAgICAgICBzLAogICAgICAgICAgICB1ID0gOCAqIGkgLSBuIC0gMSwKICAgICAgICAgICAgYSA9ICgxIDw8IHUpIC0gMSwKICAgICAgICAgICAgZiA9IGEgPj4gMSwKICAgICAgICAgICAgaCA9IC03LAogICAgICAgICAgICBsID0gciA/IGkgLSAxIDogMCwKICAgICAgICAgICAgYyA9IHIgPyAtMSA6IDEsCiAgICAgICAgICAgIHAgPSB0W2UgKyBsXTsKICAgICAgICAgIGZvciAobCArPSBjLCBvID0gcCAmICgoMSA8PCAtaCkgLSAxKSwgcCA+Pj0gLWgsIGggKz0gdTsgaCA+IDA7IG8gPSAyNTYgKiBvICsgdFtlICsgbF0sIGwgKz0gYywgaCAtPSA4KTsKICAgICAgICAgIGZvciAocyA9IG8gJiAoKDEgPDwgLWgpIC0gMSksIG8gPj49IC1oLCBoICs9IG47IGggPiAwOyBzID0gMjU2ICogcyArIHRbZSArIGxdLCBsICs9IGMsIGggLT0gOCk7CiAgICAgICAgICBpZiAoMCA9PT0gbykgbyA9IDEgLSBmOwogICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGlmIChvID09PSBhKSByZXR1cm4gcyA/IE5hTiA6ICgxIC8gMCkgKiAocCA/IC0xIDogMSkKICAgICAgICAgICAgOyhzICs9IE1hdGgucG93KDIsIG4pKSwgKG8gLT0gZik7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gKHAgPyAtMSA6IDEpICogcyAqIE1hdGgucG93KDIsIG8gLSBuKQogICAgICAgIH0pLAogICAgICAgICAgKGUud3JpdGUgPSBmdW5jdGlvbiAodCwgZSwgciwgbiwgaSwgbykgewogICAgICAgICAgICB2YXIgcywKICAgICAgICAgICAgICB1LAogICAgICAgICAgICAgIGEsCiAgICAgICAgICAgICAgZiA9IDggKiBvIC0gaSAtIDEsCiAgICAgICAgICAgICAgaCA9ICgxIDw8IGYpIC0gMSwKICAgICAgICAgICAgICBsID0gaCA+PiAxLAogICAgICAgICAgICAgIGMgPSAyMyA9PT0gaSA/IE1hdGgucG93KDIsIC0yNCkgLSBNYXRoLnBvdygyLCAtNzcpIDogMCwKICAgICAgICAgICAgICBwID0gbiA/IDAgOiBvIC0gMSwKICAgICAgICAgICAgICBnID0gbiA/IDEgOiAtMSwKICAgICAgICAgICAgICBkID0gZSA8IDAgfHwgKDAgPT09IGUgJiYgMSAvIGUgPCAwKSA/IDEgOiAwOwogICAgICAgICAgICBmb3IgKAogICAgICAgICAgICAgIGUgPSBNYXRoLmFicyhlKSwKICAgICAgICAgICAgICAgIGlzTmFOKGUpIHx8IGUgPT09IDEgLyAwCiAgICAgICAgICAgICAgICAgID8gKCh1ID0gaXNOYU4oZSkgPyAxIDogMCksIChzID0gaCkpCiAgICAgICAgICAgICAgICAgIDogKChzID0gTWF0aC5mbG9vcihNYXRoLmxvZyhlKSAvIE1hdGguTE4yKSksCiAgICAgICAgICAgICAgICAgICAgZSAqIChhID0gTWF0aC5wb3coMiwgLXMpKSA8IDEgJiYgKHMtLSwgKGEgKj0gMikpLAogICAgICAgICAgICAgICAgICAgIChlICs9IHMgKyBsID49IDEgPyBjIC8gYSA6IGMgKiBNYXRoLnBvdygyLCAxIC0gbCkpICogYSA+PSAyICYmIChzKyssIChhIC89IDIpKSwKICAgICAgICAgICAgICAgICAgICBzICsgbCA+PSBoCiAgICAgICAgICAgICAgICAgICAgICA/ICgodSA9IDApLCAocyA9IGgpKQogICAgICAgICAgICAgICAgICAgICAgOiBzICsgbCA+PSAxCiAgICAgICAgICAgICAgICAgICAgICA/ICgodSA9IChlICogYSAtIDEpICogTWF0aC5wb3coMiwgaSkpLCAocyArPSBsKSkKICAgICAgICAgICAgICAgICAgICAgIDogKCh1ID0gZSAqIE1hdGgucG93KDIsIGwgLSAxKSAqIE1hdGgucG93KDIsIGkpKSwgKHMgPSAwKSkpOwogICAgICAgICAgICAgIGkgPj0gODsKICAgICAgICAgICAgICB0W3IgKyBwXSA9IDI1NSAmIHUsIHAgKz0gZywgdSAvPSAyNTYsIGkgLT0gOAogICAgICAgICAgICApOwogICAgICAgICAgICBmb3IgKHMgPSAocyA8PCBpKSB8IHUsIGYgKz0gaTsgZiA+IDA7IHRbciArIHBdID0gMjU1ICYgcywgcCArPSBnLCBzIC89IDI1NiwgZiAtPSA4KTsKICAgICAgICAgICAgdFtyICsgcCAtIGddIHw9IDEyOCAqIGQ7CiAgICAgICAgICB9KTsKICAgICAgfSwKICAgICAgZnVuY3Rpb24gKHQsIGUpIHsKICAgICAgICB2YXIgciA9IHt9LnRvU3RyaW5nOwogICAgICAgIHQuZXhwb3J0cyA9CiAgICAgICAgICBBcnJheS5pc0FycmF5IHx8CiAgICAgICAgICBmdW5jdGlvbiAodCkgewogICAgICAgICAgICByZXR1cm4gJ1tvYmplY3QgQXJyYXldJyA9PSByLmNhbGwodCkKICAgICAgICAgIH07CiAgICAgIH0sCiAgICAgIGZ1bmN0aW9uIChlLCByKSB7CiAgICAgICAgZS5leHBvcnRzID0gdDsKICAgICAgfSwKICAgICAgZnVuY3Rpb24gKHQsIGUsIHIpIHsKICAoZnVuY3Rpb24gKHQpIHsKICAgICAgICAgIGZ1bmN0aW9uIHIodCwgZSkgewogICAgICAgICAgICBmb3IgKHZhciByID0gMCwgbiA9IHQubGVuZ3RoIC0gMTsgbiA+PSAwOyBuLS0pIHsKICAgICAgICAgICAgICB2YXIgaSA9IHRbbl07CiAgICAgICAgICAgICAgJy4nID09PSBpID8gdC5zcGxpY2UobiwgMSkgOiAnLi4nID09PSBpID8gKHQuc3BsaWNlKG4sIDEpLCByKyspIDogciAmJiAodC5zcGxpY2UobiwgMSksIHItLSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGUpIGZvciAoOyByLS07IHIpIHQudW5zaGlmdCgnLi4nKTsKICAgICAgICAgICAgcmV0dXJuIHQKICAgICAgICAgIH0KICAgICAgICAgIHZhciBuID0gL14oXC8/fCkoW1xzXFNdKj8pKCg/OlwuezEsMn18W15cL10rP3wpKFwuW14uXC9dKnwpKSg/OltcL10qKSQvLAogICAgICAgICAgICBpID0gZnVuY3Rpb24gKHQpIHsKICAgICAgICAgICAgICByZXR1cm4gbi5leGVjKHQpLnNsaWNlKDEpCiAgICAgICAgICAgIH07CiAgICAgICAgICBmdW5jdGlvbiBvKHQsIGUpIHsKICAgICAgICAgICAgaWYgKHQuZmlsdGVyKSByZXR1cm4gdC5maWx0ZXIoZSkKICAgICAgICAgICAgZm9yICh2YXIgciA9IFtdLCBuID0gMDsgbiA8IHQubGVuZ3RoOyBuKyspIGUodFtuXSwgbiwgdCkgJiYgci5wdXNoKHRbbl0pOwogICAgICAgICAgICByZXR1cm4gcgogICAgICAgICAgfQogIChlLnJlc29sdmUgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIGZvciAodmFyIGUgPSAnJywgbiA9ICExLCBpID0gYXJndW1lbnRzLmxlbmd0aCAtIDE7IGkgPj0gLTEgJiYgIW47IGktLSkgewogICAgICAgICAgICAgIHZhciBzID0gaSA+PSAwID8gYXJndW1lbnRzW2ldIDogdC5jd2QoKTsKICAgICAgICAgICAgICBpZiAoJ3N0cmluZycgIT0gdHlwZW9mIHMpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50cyB0byBwYXRoLnJlc29sdmUgbXVzdCBiZSBzdHJpbmdzJykKICAgICAgICAgICAgICBzICYmICgoZSA9IHMgKyAnLycgKyBlKSwgKG4gPSAnLycgPT09IHMuY2hhckF0KDApKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuICgKICAgICAgICAgICAgICAoZSA9IHIoCiAgICAgICAgICAgICAgICBvKGUuc3BsaXQoJy8nKSwgZnVuY3Rpb24gKHQpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuICEhdAogICAgICAgICAgICAgICAgfSksCiAgICAgICAgICAgICAgICAhbgogICAgICAgICAgICAgICkuam9pbignLycpKSwKICAgICAgICAgICAgICAobiA/ICcvJyA6ICcnKSArIGUgfHwgJy4nCiAgICAgICAgICAgICkKICAgICAgICAgIH0pLAogICAgICAgICAgICAoZS5ub3JtYWxpemUgPSBmdW5jdGlvbiAodCkgewogICAgICAgICAgICAgIHZhciBuID0gZS5pc0Fic29sdXRlKHQpLAogICAgICAgICAgICAgICAgaSA9ICcvJyA9PT0gcyh0LCAtMSk7CiAgICAgICAgICAgICAgcmV0dXJuICgKICAgICAgICAgICAgICAgICh0ID0gcigKICAgICAgICAgICAgICAgICAgbyh0LnNwbGl0KCcvJyksIGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEhdAogICAgICAgICAgICAgICAgICB9KSwKICAgICAgICAgICAgICAgICAgIW4KICAgICAgICAgICAgICAgICkuam9pbignLycpKSB8fAogICAgICAgICAgICAgICAgICBuIHx8CiAgICAgICAgICAgICAgICAgICh0ID0gJy4nKSwKICAgICAgICAgICAgICAgIHQgJiYgaSAmJiAodCArPSAnLycpLAogICAgICAgICAgICAgICAgKG4gPyAnLycgOiAnJykgKyB0CiAgICAgICAgICAgICAgKQogICAgICAgICAgICB9KSwKICAgICAgICAgICAgKGUuaXNBYnNvbHV0ZSA9IGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAgICAgcmV0dXJuICcvJyA9PT0gdC5jaGFyQXQoMCkKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChlLmpvaW4gPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgdmFyIHQgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDApOwogICAgICAgICAgICAgIHJldHVybiBlLm5vcm1hbGl6ZSgKICAgICAgICAgICAgICAgIG8odCwgZnVuY3Rpb24gKHQsIGUpIHsKICAgICAgICAgICAgICAgICAgaWYgKCdzdHJpbmcnICE9IHR5cGVvZiB0KSB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudHMgdG8gcGF0aC5qb2luIG11c3QgYmUgc3RyaW5ncycpCiAgICAgICAgICAgICAgICAgIHJldHVybiB0CiAgICAgICAgICAgICAgICB9KS5qb2luKCcvJykKICAgICAgICAgICAgICApCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoZS5yZWxhdGl2ZSA9IGZ1bmN0aW9uICh0LCByKSB7CiAgICAgICAgICAgICAgZnVuY3Rpb24gbih0KSB7CiAgICAgICAgICAgICAgICBmb3IgKHZhciBlID0gMDsgZSA8IHQubGVuZ3RoICYmICcnID09PSB0W2VdOyBlKyspOwogICAgICAgICAgICAgICAgZm9yICh2YXIgciA9IHQubGVuZ3RoIC0gMTsgciA+PSAwICYmICcnID09PSB0W3JdOyByLS0pOwogICAgICAgICAgICAgICAgcmV0dXJuIGUgPiByID8gW10gOiB0LnNsaWNlKGUsIHIgLSBlICsgMSkKICAgICAgICAgICAgICB9CiAgKHQgPSBlLnJlc29sdmUodCkuc3Vic3RyKDEpKSwgKHIgPSBlLnJlc29sdmUocikuc3Vic3RyKDEpKTsKICAgICAgICAgICAgICBmb3IgKAogICAgICAgICAgICAgICAgdmFyIGkgPSBuKHQuc3BsaXQoJy8nKSksIG8gPSBuKHIuc3BsaXQoJy8nKSksIHMgPSBNYXRoLm1pbihpLmxlbmd0aCwgby5sZW5ndGgpLCB1ID0gcywgYSA9IDA7CiAgICAgICAgICAgICAgICBhIDwgczsKICAgICAgICAgICAgICAgIGErKwogICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIGlmIChpW2FdICE9PSBvW2FdKSB7CiAgICAgICAgICAgICAgICAgIHUgPSBhOwogICAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHZhciBmID0gW107CiAgICAgICAgICAgICAgZm9yIChhID0gdTsgYSA8IGkubGVuZ3RoOyBhKyspIGYucHVzaCgnLi4nKTsKICAgICAgICAgICAgICByZXR1cm4gKGYgPSBmLmNvbmNhdChvLnNsaWNlKHUpKSkuam9pbignLycpCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICAoZS5zZXAgPSAnLycpLAogICAgICAgICAgICAoZS5kZWxpbWl0ZXIgPSAnOicpLAogICAgICAgICAgICAoZS5kaXJuYW1lID0gZnVuY3Rpb24gKHQpIHsKICAgICAgICAgICAgICB2YXIgZSA9IGkodCksCiAgICAgICAgICAgICAgICByID0gZVswXSwKICAgICAgICAgICAgICAgIG4gPSBlWzFdOwogICAgICAgICAgICAgIHJldHVybiByIHx8IG4gPyAobiAmJiAobiA9IG4uc3Vic3RyKDAsIG4ubGVuZ3RoIC0gMSkpLCByICsgbikgOiAnLicKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChlLmJhc2VuYW1lID0gZnVuY3Rpb24gKHQsIGUpIHsKICAgICAgICAgICAgICB2YXIgciA9IGkodClbMl07CiAgICAgICAgICAgICAgcmV0dXJuIGUgJiYgci5zdWJzdHIoLTEgKiBlLmxlbmd0aCkgPT09IGUgJiYgKHIgPSByLnN1YnN0cigwLCByLmxlbmd0aCAtIGUubGVuZ3RoKSksIHIKICAgICAgICAgICAgfSksCiAgICAgICAgICAgIChlLmV4dG5hbWUgPSBmdW5jdGlvbiAodCkgewogICAgICAgICAgICAgIHJldHVybiBpKHQpWzNdCiAgICAgICAgICAgIH0pOwogICAgICAgICAgdmFyIHMgPQogICAgICAgICAgICAnYicgPT09ICdhYicuc3Vic3RyKC0xKQogICAgICAgICAgICAgID8gZnVuY3Rpb24gKHQsIGUsIHIpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuIHQuc3Vic3RyKGUsIHIpCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgOiBmdW5jdGlvbiAodCwgZSwgcikgewogICAgICAgICAgICAgICAgICByZXR1cm4gZSA8IDAgJiYgKGUgPSB0Lmxlbmd0aCArIGUpLCB0LnN1YnN0cihlLCByKQogICAgICAgICAgICAgICAgfTsKICAgICAgICB9LmNhbGwodGhpcywgcigxNCkpKTsKICAgICAgfSwKICAgICAgZnVuY3Rpb24gKHQsIGUpIHsKICAgICAgICB2YXIgciwKICAgICAgICAgIG4sCiAgICAgICAgICBpID0gKHQuZXhwb3J0cyA9IHt9KTsKICAgICAgICBmdW5jdGlvbiBvKCkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdzZXRUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJykKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gcygpIHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcignY2xlYXJUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJykKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gdSh0KSB7CiAgICAgICAgICBpZiAociA9PT0gc2V0VGltZW91dCkgcmV0dXJuIHNldFRpbWVvdXQodCwgMCkKICAgICAgICAgIGlmICgociA9PT0gbyB8fCAhcikgJiYgc2V0VGltZW91dCkgcmV0dXJuIChyID0gc2V0VGltZW91dCksIHNldFRpbWVvdXQodCwgMCkKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHJldHVybiByKHQsIDApCiAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgcmV0dXJuIHIuY2FsbChudWxsLCB0LCAwKQogICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHIuY2FsbCh0aGlzLCB0LCAwKQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgICEoZnVuY3Rpb24gKCkgewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgciA9ICdmdW5jdGlvbicgPT0gdHlwZW9mIHNldFRpbWVvdXQgPyBzZXRUaW1lb3V0IDogbzsKICAgICAgICAgIH0gY2F0Y2ggKHQpIHsKICAgICAgICAgICAgciA9IG87CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBuID0gJ2Z1bmN0aW9uJyA9PSB0eXBlb2YgY2xlYXJUaW1lb3V0ID8gY2xlYXJUaW1lb3V0IDogczsKICAgICAgICAgIH0gY2F0Y2ggKHQpIHsKICAgICAgICAgICAgbiA9IHM7CiAgICAgICAgICB9CiAgICAgICAgfSkoKTsKICAgICAgICB2YXIgYSwKICAgICAgICAgIGYgPSBbXSwKICAgICAgICAgIGggPSAhMSwKICAgICAgICAgIGwgPSAtMTsKICAgICAgICBmdW5jdGlvbiBjKCkgewogICAgICAgICAgaCAmJiBhICYmICgoaCA9ICExKSwgYS5sZW5ndGggPyAoZiA9IGEuY29uY2F0KGYpKSA6IChsID0gLTEpLCBmLmxlbmd0aCAmJiBwKCkpOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBwKCkgewogICAgICAgICAgaWYgKCFoKSB7CiAgICAgICAgICAgIHZhciB0ID0gdShjKTsKICAgICAgICAgICAgaCA9ICEwOwogICAgICAgICAgICBmb3IgKHZhciBlID0gZi5sZW5ndGg7IGU7ICkgewogICAgICAgICAgICAgIGZvciAoYSA9IGYsIGYgPSBbXTsgKytsIDwgZTsgKSBhICYmIGFbbF0ucnVuKCkKICAgICAgICAgICAgICA7KGwgPSAtMSksIChlID0gZi5sZW5ndGgpOwogICAgICAgICAgICB9CiAgKGEgPSBudWxsKSwKICAgICAgICAgICAgICAoaCA9ICExKSwKICAgICAgICAgICAgICAoZnVuY3Rpb24gKHQpIHsKICAgICAgICAgICAgICAgIGlmIChuID09PSBjbGVhclRpbWVvdXQpIHJldHVybiBjbGVhclRpbWVvdXQodCkKICAgICAgICAgICAgICAgIGlmICgobiA9PT0gcyB8fCAhbikgJiYgY2xlYXJUaW1lb3V0KSByZXR1cm4gKG4gPSBjbGVhclRpbWVvdXQpLCBjbGVhclRpbWVvdXQodCkKICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgIG4odCk7CiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG4uY2FsbChudWxsLCB0KQogICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG4uY2FsbCh0aGlzLCB0KQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSkodCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGcodCwgZSkgewogICh0aGlzLmZ1biA9IHQpLCAodGhpcy5hcnJheSA9IGUpOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBkKCkge30KICAoaS5uZXh0VGljayA9IGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICB2YXIgZSA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoIC0gMSk7CiAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIGZvciAodmFyIHIgPSAxOyByIDwgYXJndW1lbnRzLmxlbmd0aDsgcisrKSBlW3IgLSAxXSA9IGFyZ3VtZW50c1tyXTsKICAgICAgICAgIGYucHVzaChuZXcgZyh0LCBlKSksIDEgIT09IGYubGVuZ3RoIHx8IGggfHwgdShwKTsKICAgICAgICB9KSwKICAgICAgICAgIChnLnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIHRoaXMuZnVuLmFwcGx5KG51bGwsIHRoaXMuYXJyYXkpOwogICAgICAgICAgfSksCiAgICAgICAgICAoaS50aXRsZSA9ICdicm93c2VyJyksCiAgICAgICAgICAoaS5icm93c2VyID0gITApLAogICAgICAgICAgKGkuZW52ID0ge30pLAogICAgICAgICAgKGkuYXJndiA9IFtdKSwKICAgICAgICAgIChpLnZlcnNpb24gPSAnJyksCiAgICAgICAgICAoaS52ZXJzaW9ucyA9IHt9KSwKICAgICAgICAgIChpLm9uID0gZCksCiAgICAgICAgICAoaS5hZGRMaXN0ZW5lciA9IGQpLAogICAgICAgICAgKGkub25jZSA9IGQpLAogICAgICAgICAgKGkub2ZmID0gZCksCiAgICAgICAgICAoaS5yZW1vdmVMaXN0ZW5lciA9IGQpLAogICAgICAgICAgKGkucmVtb3ZlQWxsTGlzdGVuZXJzID0gZCksCiAgICAgICAgICAoaS5lbWl0ID0gZCksCiAgICAgICAgICAoaS5wcmVwZW5kTGlzdGVuZXIgPSBkKSwKICAgICAgICAgIChpLnByZXBlbmRPbmNlTGlzdGVuZXIgPSBkKSwKICAgICAgICAgIChpLmxpc3RlbmVycyA9IGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAgIHJldHVybiBbXQogICAgICAgICAgfSksCiAgICAgICAgICAoaS5iaW5kaW5nID0gZnVuY3Rpb24gKHQpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpCiAgICAgICAgICB9KSwKICAgICAgICAgIChpLmN3ZCA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgcmV0dXJuICcvJwogICAgICAgICAgfSksCiAgICAgICAgICAoaS5jaGRpciA9IGZ1bmN0aW9uICh0KSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJykKICAgICAgICAgIH0pLAogICAgICAgICAgKGkudW1hc2sgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIHJldHVybiAwCiAgICAgICAgICB9KTsKICAgICAgfSwKICAgIF0pCiAgfSk7CiAgLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgogIGNvbnN0IHVucGFja0JyaWRnZSA9IFdvcmtlclNjb3BlLnVucGFja0JyaWRnZTsKCiAgbGV0IHVucGFjazsKCiAgLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tdW5wYWNrLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICB2YXIgaW5pdHVucGFjayA9IGZ1bmN0aW9uIChidWZmZXIpIHsKICAgIC8vIFRoZSBmb2xsb3dpbmcgY29kZSBoYXMgYmVlbiBfY2FyZWZ1bGx5XyBtb2RpZmllZCBieSBoYW5kLgogICAgLy8gRHVlIHRvIFdlYlBhY2sgZW1iZWRkaW5nIHRoaXMgc2NyaXB0IGludG8gdGhlIFplYSBlbmdpbmUKICAgIC8vIGJ1aWxkLCBjZXJ0YWluIGZlYXR1cmVzIGJyb2tlLgogICAgLy8gVGhlcmUgd2FzIGNvZGUgdG8gaGFuZGxlIGxvYWRpbmcgaW4gYSBub2RlSlMgY29udGV4dCwgdGhhdCB0cmllZCB0byBpbXBvcnQoImZzIikKICAgIC8vIFdlYlBhY2sga2VwdHMgdHJpcHBpbmcgdXAgb24gdGhhdCBjb2RlIGluIGl0cyBzdGF0aWMgYW5hbHlzaXMgb2YgdGhlIGNvZGUsIHNvCiAgICAvLyBJIGNhcmVmdWxseSByZW1vdmVkIGl0LgogICAgLy8gVGhlIGdsb2JhbCBzY29wZSBvZiB0aGUgc2NyaXB0IHNlZW1zIHRvIGJlIGRpZmZlcmVudCwgc28gdW5wYWNrQnJpZGdlIHdhcyBub3QgYXZhaWxhYmxlLgogICAgLy8gVGhlIHVucGFja0JyaWRnZSBjb2RlIGFzc2lnbnMgdW5wYWNrQnJpZGdlIHRvIHRoZSBwYXNzZWQgaW4gc2NvcGUsIHdoaWNoIGlzICd0aGlzJywgYnV0IHRoYXQKICAgIC8vIHNjb3BlIGlzbid0IGF2YWlsYWJsZSBpbnNpZGUgdGhpcyAndW5wYWNrJyBmdW5jdGlvbi4KICAgIGNvbnN0IHVucGFjayA9IE1vZHVsZTsKCiAgICAvLyBOb3RlOiB0aGUgZm9sbG93aW5nIGlzIHRoZSBVUkwgb2YgdGhlIHVucGFjay53YXNtIGZpbGUgaW4gb3VyIFplYUVuZ2luZSBwcm9qZWN0IG9uIG91cgogICAgLy8gc2VydmVyLiBJZGVhbGx5IHdlIGNvdWxkIHVzZSBhIHJlbGF0aXZlIHBhdGggZnJvbSB0aGUgWmVhRW5naW5lIGZpbGUsIGJ1dAogICAgLy8gdGhhdCBpc24ndCBwb3NzaWJsZSB5ZXQuIChUT0RPOiBBc2sgTWF1cm8gYWJvdXQgdGhpcykKICAgIGNvbnN0IGNyZWRlbnRpYWxzID0gJ29taXQnOwoKICAgIHZhciBFeHQgPSB1bnBhY2tCcmlkZ2UuRXh0OwogICAgdmFyIGpzQVBJID0gewogICAgICBvcGVuOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIEV4dC5jdXJyZW50Lm9wZW4uYXBwbHkoRXh0LmN1cnJlbnQsIGFyZ3VtZW50cykKICAgICAgfSwKICAgICAgY2xvc2U6IGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gRXh0LmN1cnJlbnQuY2xvc2UuYXBwbHkoRXh0LmN1cnJlbnQsIGFyZ3VtZW50cykKICAgICAgfSwKICAgICAgcmVhZDogZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBFeHQuY3VycmVudC5yZWFkLmFwcGx5KEV4dC5jdXJyZW50LCBhcmd1bWVudHMpCiAgICAgIH0sCiAgICAgIHdyaXRlOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIEV4dC5jdXJyZW50LndyaXRlLmFwcGx5KEV4dC5jdXJyZW50LCBhcmd1bWVudHMpCiAgICAgIH0sCiAgICAgIHRlbGw6IGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gRXh0LmN1cnJlbnQudGVsbC5hcHBseShFeHQuY3VycmVudCwgYXJndW1lbnRzKQogICAgICB9LAogICAgICBzZWVrOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIEV4dC5jdXJyZW50LnNlZWsuYXBwbHkoRXh0LmN1cnJlbnQsIGFyZ3VtZW50cykKICAgICAgfSwKICAgICAgY3JlYXRlOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIEV4dC5jdXJyZW50LmNyZWF0ZS5hcHBseShFeHQuY3VycmVudCwgYXJndW1lbnRzKQogICAgICB9LAogICAgfTsKICAgIHZhciBtb2R1bGVPdmVycmlkZXMgPSB7fTsKICAgIHZhciBrZXk7CiAgICBmb3IgKGtleSBpbiBNb2R1bGUpIHsKICAgICAgaWYgKE1vZHVsZS5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7CiAgICAgICAgbW9kdWxlT3ZlcnJpZGVzW2tleV0gPSBNb2R1bGVba2V5XTsKICAgICAgfQogICAgfQogICAgTW9kdWxlWyd3YXNtQmluYXJ5J10gPSBidWZmZXI7CiAgICBNb2R1bGVbJ2FyZ3VtZW50cyddID0gW107CiAgICBNb2R1bGVbJ3RoaXNQcm9ncmFtJ10gPSAnLi90aGlzLnByb2dyYW0nOwogICAgTW9kdWxlWydxdWl0J10gPSBmdW5jdGlvbiAoc3RhdHVzLCB0b1Rocm93KSB7CiAgICAgIHRocm93IHRvVGhyb3cKICAgIH07CiAgICBNb2R1bGVbJ3ByZVJ1biddID0gW107CiAgICBNb2R1bGVbJ3Bvc3RSdW4nXSA9IFtdOwogICAgdmFyIEVOVklST05NRU5UX0lTX1dFQiA9IGZhbHNlOwogICAgdmFyIEVOVklST05NRU5UX0lTX1dPUktFUiA9IGZhbHNlOwogICAgdmFyIEVOVklST05NRU5UX0lTX05PREUgPSBmYWxzZTsKICAgIGlmIChNb2R1bGVbJ0VOVklST05NRU5UJ10pIHsKICAgICAgaWYgKE1vZHVsZVsnRU5WSVJPTk1FTlQnXSA9PT0gJ1dFQicpIHsKICAgICAgICBFTlZJUk9OTUVOVF9JU19XRUIgPSB0cnVlOwogICAgICB9IGVsc2UgaWYgKE1vZHVsZVsnRU5WSVJPTk1FTlQnXSA9PT0gJ1dPUktFUicpIHsKICAgICAgICBFTlZJUk9OTUVOVF9JU19XT1JLRVIgPSB0cnVlOwogICAgICB9IGVsc2UgaWYgKE1vZHVsZVsnRU5WSVJPTk1FTlQnXSA9PT0gJ05PREUnKSB7CiAgICAgICAgRU5WSVJPTk1FTlRfSVNfTk9ERSA9IHRydWU7CiAgICAgIH0gZWxzZSBpZiAoTW9kdWxlWydFTlZJUk9OTUVOVCddID09PSAnU0hFTEwnKSA7IGVsc2UgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiTW9kdWxlWydFTlZJUk9OTUVOVCddIHZhbHVlIGlzIG5vdCB2YWxpZC4gbXVzdCBiZSBvbmUgb2Y6IFdFQnxXT1JLRVJ8Tk9ERXxTSEVMTC4iKQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBFTlZJUk9OTUVOVF9JU19XRUIgPSB0eXBlb2Ygd2luZG93ID09PSAnb2JqZWN0JzsKICAgICAgRU5WSVJPTk1FTlRfSVNfV09SS0VSID0gdHlwZW9mIGltcG9ydFNjcmlwdHMgPT09ICdmdW5jdGlvbic7CiAgICAgIEVOVklST05NRU5UX0lTX05PREUgPQogICAgICAgIHR5cGVvZiBwcm9jZXNzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyAmJiAhRU5WSVJPTk1FTlRfSVNfV0VCICYmICFFTlZJUk9OTUVOVF9JU19XT1JLRVI7CiAgICB9CiAgICBpZiAoRU5WSVJPTk1FTlRfSVNfV0VCIHx8IEVOVklST05NRU5UX0lTX1dPUktFUikgewogICAgICBNb2R1bGVbJ3JlYWQnXSA9IGZ1bmN0aW9uIHNoZWxsX3JlYWQodXJsKSB7CiAgICAgICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpOwogICAgICAgIHhoci5vcGVuKCdHRVQnLCB1cmwsIGZhbHNlKTsKICAgICAgICB4aHIuc2VuZChudWxsKTsKICAgICAgICByZXR1cm4geGhyLnJlc3BvbnNlVGV4dAogICAgICB9OwogICAgICBpZiAoRU5WSVJPTk1FTlRfSVNfV09SS0VSKSB7CiAgICAgICAgTW9kdWxlWydyZWFkQmluYXJ5J10gPSBmdW5jdGlvbiByZWFkQmluYXJ5KHVybCkgewogICAgICAgICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpOwogICAgICAgICAgeGhyLm9wZW4oJ0dFVCcsIHVybCwgZmFsc2UpOwogICAgICAgICAgeGhyLnJlc3BvbnNlVHlwZSA9ICdhcnJheWJ1ZmZlcic7CiAgICAgICAgICB4aHIuc2VuZChudWxsKTsKICAgICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheSh4aHIucmVzcG9uc2UpCiAgICAgICAgfTsKICAgICAgfQogICAgICBNb2R1bGVbJ3JlYWRBc3luYyddID0gZnVuY3Rpb24gcmVhZEFzeW5jKHVybCwgb25sb2FkLCBvbmVycm9yKSB7CiAgICAgICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpOwogICAgICAgIHhoci5vcGVuKCdHRVQnLCB1cmwsIHRydWUpOwogICAgICAgIHhoci5yZXNwb25zZVR5cGUgPSAnYXJyYXlidWZmZXInOwogICAgICAgIHhoci5vbmxvYWQgPSBmdW5jdGlvbiB4aHJfb25sb2FkKCkgewogICAgICAgICAgaWYgKHhoci5zdGF0dXMgPT0gMjAwIHx8ICh4aHIuc3RhdHVzID09IDAgJiYgeGhyLnJlc3BvbnNlKSkgewogICAgICAgICAgICBvbmxvYWQoeGhyLnJlc3BvbnNlKTsKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgICB9CiAgICAgICAgICBvbmVycm9yKCk7CiAgICAgICAgfTsKICAgICAgICB4aHIub25lcnJvciA9IG9uZXJyb3I7CiAgICAgICAgeGhyLnNlbmQobnVsbCk7CiAgICAgIH07CiAgICAgIE1vZHVsZVsnc2V0V2luZG93VGl0bGUnXSA9IGZ1bmN0aW9uICh0aXRsZSkgewogICAgICAgIGRvY3VtZW50LnRpdGxlID0gdGl0bGU7CiAgICAgIH07CiAgICB9CiAgICBNb2R1bGVbJ3ByaW50J10gPQogICAgICB0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgPyBjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpIDogdHlwZW9mIHByaW50ICE9PSAndW5kZWZpbmVkJyA/IHByaW50IDogbnVsbDsKICAgIE1vZHVsZVsncHJpbnRFcnInXSA9CiAgICAgIHR5cGVvZiBwcmludEVyciAhPT0gJ3VuZGVmaW5lZCcKICAgICAgICA/IHByaW50RXJyCiAgICAgICAgOiAodHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnICYmIGNvbnNvbGUud2Fybi5iaW5kKGNvbnNvbGUpKSB8fCBNb2R1bGVbJ3ByaW50J107CiAgICBNb2R1bGUucHJpbnQgPSBNb2R1bGVbJ3ByaW50J107CiAgICBNb2R1bGUucHJpbnRFcnIgPSBNb2R1bGVbJ3ByaW50RXJyJ107CiAgICBmb3IgKGtleSBpbiBtb2R1bGVPdmVycmlkZXMpIHsKICAgICAgaWYgKG1vZHVsZU92ZXJyaWRlcy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7CiAgICAgICAgTW9kdWxlW2tleV0gPSBtb2R1bGVPdmVycmlkZXNba2V5XTsKICAgICAgfQogICAgfQogICAgbW9kdWxlT3ZlcnJpZGVzID0gdW5kZWZpbmVkOwogICAgdmFyIFNUQUNLX0FMSUdOID0gMTY7CiAgICBmdW5jdGlvbiBzdGF0aWNBbGxvYyhzaXplKSB7CiAgICAgIGFzc2VydCghc3RhdGljU2VhbGVkKTsKICAgICAgdmFyIHJldCA9IFNUQVRJQ1RPUDsKICAgICAgU1RBVElDVE9QID0gKFNUQVRJQ1RPUCArIHNpemUgKyAxNSkgJiAtMTY7CiAgICAgIHJldHVybiByZXQKICAgIH0KICAgIGZ1bmN0aW9uIGR5bmFtaWNBbGxvYyhzaXplKSB7CiAgICAgIGFzc2VydChEWU5BTUlDVE9QX1BUUik7CiAgICAgIHZhciByZXQgPSBIRUFQMzJbRFlOQU1JQ1RPUF9QVFIgPj4gMl07CiAgICAgIHZhciBlbmQgPSAocmV0ICsgc2l6ZSArIDE1KSAmIC0xNjsKICAgICAgSEVBUDMyW0RZTkFNSUNUT1BfUFRSID4+IDJdID0gZW5kOwogICAgICBpZiAoZW5kID49IFRPVEFMX01FTU9SWSkgewogICAgICAgIHZhciBzdWNjZXNzID0gZW5sYXJnZU1lbW9yeSgpOwogICAgICAgIGlmICghc3VjY2VzcykgewogICAgICAgICAgSEVBUDMyW0RZTkFNSUNUT1BfUFRSID4+IDJdID0gcmV0OwogICAgICAgICAgcmV0dXJuIDAKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIHJldAogICAgfQogICAgZnVuY3Rpb24gYWxpZ25NZW1vcnkoc2l6ZSwgZmFjdG9yKSB7CiAgICAgIGlmICghZmFjdG9yKSBmYWN0b3IgPSBTVEFDS19BTElHTjsKICAgICAgdmFyIHJldCA9IChzaXplID0gTWF0aC5jZWlsKHNpemUgLyBmYWN0b3IpICogZmFjdG9yKTsKICAgICAgcmV0dXJuIHJldAogICAgfQogICAgZnVuY3Rpb24gZ2V0TmF0aXZlVHlwZVNpemUodHlwZSkgewogICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICBjYXNlICdpMSc6CiAgICAgICAgY2FzZSAnaTgnOgogICAgICAgICAgcmV0dXJuIDEKICAgICAgICBjYXNlICdpMTYnOgogICAgICAgICAgcmV0dXJuIDIKICAgICAgICBjYXNlICdpMzInOgogICAgICAgICAgcmV0dXJuIDQKICAgICAgICBjYXNlICdpNjQnOgogICAgICAgICAgcmV0dXJuIDgKICAgICAgICBjYXNlICdmbG9hdCc6CiAgICAgICAgICByZXR1cm4gNAogICAgICAgIGNhc2UgJ2RvdWJsZSc6CiAgICAgICAgICByZXR1cm4gOAogICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgIGlmICh0eXBlW3R5cGUubGVuZ3RoIC0gMV0gPT09ICcqJykgewogICAgICAgICAgICByZXR1cm4gNAogICAgICAgICAgfSBlbHNlIGlmICh0eXBlWzBdID09PSAnaScpIHsKICAgICAgICAgICAgdmFyIGJpdHMgPSBwYXJzZUludCh0eXBlLnN1YnN0cigxKSk7CiAgICAgICAgICAgIGFzc2VydChiaXRzICUgOCA9PT0gMCk7CiAgICAgICAgICAgIHJldHVybiBiaXRzIC8gOAogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIDAKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIG5ldyBBcnJheSgwKTsKICAgIHZhciBHTE9CQUxfQkFTRSA9IDEwMjQ7CiAgICB2YXIgQUJPUlQgPSAwOwogICAgZnVuY3Rpb24gYXNzZXJ0KGNvbmRpdGlvbiwgdGV4dCkgewogICAgICBpZiAoIWNvbmRpdGlvbikgewogICAgICAgIGFib3J0KCdBc3NlcnRpb24gZmFpbGVkOiAnICsgdGV4dCk7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIHNldFZhbHVlKHB0ciwgdmFsdWUsIHR5cGUsIG5vU2FmZSkgewogICAgICB0eXBlID0gdHlwZSB8fCAnaTgnOwogICAgICBpZiAodHlwZS5jaGFyQXQodHlwZS5sZW5ndGggLSAxKSA9PT0gJyonKSB0eXBlID0gJ2kzMic7CiAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgIGNhc2UgJ2kxJzoKICAgICAgICAgIEhFQVA4W3B0ciA+PiAwXSA9IHZhbHVlOwogICAgICAgICAgYnJlYWsKICAgICAgICBjYXNlICdpOCc6CiAgICAgICAgICBIRUFQOFtwdHIgPj4gMF0gPSB2YWx1ZTsKICAgICAgICAgIGJyZWFrCiAgICAgICAgY2FzZSAnaTE2JzoKICAgICAgICAgIEhFQVAxNltwdHIgPj4gMV0gPSB2YWx1ZTsKICAgICAgICAgIGJyZWFrCiAgICAgICAgY2FzZSAnaTMyJzoKICAgICAgICAgIEhFQVAzMltwdHIgPj4gMl0gPSB2YWx1ZTsKICAgICAgICAgIGJyZWFrCiAgICAgICAgY2FzZSAnaTY0JzoKICAodGVtcEk2NCA9IFsKICAgICAgICAgICAgdmFsdWUgPj4+IDAsCiAgICAgICAgICAgICgodGVtcERvdWJsZSA9IHZhbHVlKSwKICAgICAgICAgICAgK01hdGhfYWJzKHRlbXBEb3VibGUpID49IDEKICAgICAgICAgICAgICA/IHRlbXBEb3VibGUgPiAwCiAgICAgICAgICAgICAgICA/IChNYXRoX21pbigrTWF0aF9mbG9vcih0ZW1wRG91YmxlIC8gNDI5NDk2NzI5NiksIDQyOTQ5NjcyOTUpIHwgMCkgPj4+IDAKICAgICAgICAgICAgICAgIDogfn4rTWF0aF9jZWlsKCh0ZW1wRG91YmxlIC0gKyh+fnRlbXBEb3VibGUgPj4+IDApKSAvIDQyOTQ5NjcyOTYpID4+PiAwCiAgICAgICAgICAgICAgOiAwKSwKICAgICAgICAgIF0pLAogICAgICAgICAgICAoSEVBUDMyW3B0ciA+PiAyXSA9IHRlbXBJNjRbMF0pLAogICAgICAgICAgICAoSEVBUDMyWyhwdHIgKyA0KSA+PiAyXSA9IHRlbXBJNjRbMV0pOwogICAgICAgICAgYnJlYWsKICAgICAgICBjYXNlICdmbG9hdCc6CiAgICAgICAgICBIRUFQRjMyW3B0ciA+PiAyXSA9IHZhbHVlOwogICAgICAgICAgYnJlYWsKICAgICAgICBjYXNlICdkb3VibGUnOgogICAgICAgICAgSEVBUEY2NFtwdHIgPj4gM10gPSB2YWx1ZTsKICAgICAgICAgIGJyZWFrCiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIGFib3J0KCdpbnZhbGlkIHR5cGUgZm9yIHNldFZhbHVlOiAnICsgdHlwZSk7CiAgICAgIH0KICAgIH0KICAgIHZhciBBTExPQ19OT1JNQUwgPSAwOwogICAgdmFyIEFMTE9DX1NUQVRJQyA9IDI7CiAgICB2YXIgQUxMT0NfTk9ORSA9IDQ7CiAgICBmdW5jdGlvbiBhbGxvY2F0ZShzbGFiLCB0eXBlcywgYWxsb2NhdG9yLCBwdHIpIHsKICAgICAgdmFyIHplcm9pbml0LCBzaXplOwogICAgICBpZiAodHlwZW9mIHNsYWIgPT09ICdudW1iZXInKSB7CiAgICAgICAgemVyb2luaXQgPSB0cnVlOwogICAgICAgIHNpemUgPSBzbGFiOwogICAgICB9IGVsc2UgewogICAgICAgIHplcm9pbml0ID0gZmFsc2U7CiAgICAgICAgc2l6ZSA9IHNsYWIubGVuZ3RoOwogICAgICB9CiAgICAgIHZhciBzaW5nbGVUeXBlID0gdHlwZW9mIHR5cGVzID09PSAnc3RyaW5nJyA/IHR5cGVzIDogbnVsbDsKICAgICAgdmFyIHJldDsKICAgICAgaWYgKGFsbG9jYXRvciA9PSBBTExPQ19OT05FKSB7CiAgICAgICAgcmV0ID0gcHRyOwogICAgICB9IGVsc2UgewogICAgICAgIHJldCA9IFt0eXBlb2YgX21hbGxvYyA9PT0gJ2Z1bmN0aW9uJyA/IF9tYWxsb2MgOiBzdGF0aWNBbGxvYywgc3RhY2tBbGxvYywgc3RhdGljQWxsb2MsIGR5bmFtaWNBbGxvY11bCiAgICAgICAgICBhbGxvY2F0b3IgPT09IHVuZGVmaW5lZCA/IEFMTE9DX1NUQVRJQyA6IGFsbG9jYXRvcgogICAgICAgIF0oTWF0aC5tYXgoc2l6ZSwgc2luZ2xlVHlwZSA/IDEgOiB0eXBlcy5sZW5ndGgpKTsKICAgICAgfQogICAgICBpZiAoemVyb2luaXQpIHsKICAgICAgICB2YXIgc3RvcDsKICAgICAgICBwdHIgPSByZXQ7CiAgICAgICAgYXNzZXJ0KChyZXQgJiAzKSA9PSAwKTsKICAgICAgICBzdG9wID0gcmV0ICsgKHNpemUgJiB+Myk7CiAgICAgICAgZm9yICg7IHB0ciA8IHN0b3A7IHB0ciArPSA0KSB7CiAgICAgICAgICBIRUFQMzJbcHRyID4+IDJdID0gMDsKICAgICAgICB9CiAgICAgICAgc3RvcCA9IHJldCArIHNpemU7CiAgICAgICAgd2hpbGUgKHB0ciA8IHN0b3ApIHsKICAgICAgICAgIEhFQVA4W3B0cisrID4+IDBdID0gMDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldAogICAgICB9CiAgICAgIGlmIChzaW5nbGVUeXBlID09PSAnaTgnKSB7CiAgICAgICAgaWYgKHNsYWIuc3ViYXJyYXkgfHwgc2xhYi5zbGljZSkgewogICAgICAgICAgSEVBUFU4LnNldChzbGFiLCByZXQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBIRUFQVTguc2V0KG5ldyBVaW50OEFycmF5KHNsYWIpLCByZXQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0CiAgICAgIH0KICAgICAgdmFyIGkgPSAwLAogICAgICAgIHR5cGUsCiAgICAgICAgdHlwZVNpemUsCiAgICAgICAgcHJldmlvdXNUeXBlOwogICAgICB3aGlsZSAoaSA8IHNpemUpIHsKICAgICAgICB2YXIgY3VyciA9IHNsYWJbaV07CiAgICAgICAgdHlwZSA9IHNpbmdsZVR5cGUgfHwgdHlwZXNbaV07CiAgICAgICAgaWYgKHR5cGUgPT09IDApIHsKICAgICAgICAgIGkrKzsKICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgfQogICAgICAgIGlmICh0eXBlID09ICdpNjQnKSB0eXBlID0gJ2kzMic7CiAgICAgICAgc2V0VmFsdWUocmV0ICsgaSwgY3VyciwgdHlwZSk7CiAgICAgICAgaWYgKHByZXZpb3VzVHlwZSAhPT0gdHlwZSkgewogICAgICAgICAgdHlwZVNpemUgPSBnZXROYXRpdmVUeXBlU2l6ZSh0eXBlKTsKICAgICAgICAgIHByZXZpb3VzVHlwZSA9IHR5cGU7CiAgICAgICAgfQogICAgICAgIGkgKz0gdHlwZVNpemU7CiAgICAgIH0KICAgICAgcmV0dXJuIHJldAogICAgfQogICAgZnVuY3Rpb24gUG9pbnRlcl9zdHJpbmdpZnkocHRyLCBsZW5ndGgpIHsKICAgICAgaWYgKGxlbmd0aCA9PT0gMCB8fCAhcHRyKSByZXR1cm4gJycKICAgICAgdmFyIGhhc1V0ZiA9IDA7CiAgICAgIHZhciB0OwogICAgICB2YXIgaSA9IDA7CiAgICAgIHdoaWxlICgxKSB7CiAgICAgICAgdCA9IEhFQVBVOFsocHRyICsgaSkgPj4gMF07CiAgICAgICAgaGFzVXRmIHw9IHQ7CiAgICAgICAgaWYgKHQgPT0gMCAmJiAhbGVuZ3RoKSBicmVhawogICAgICAgIGkrKzsKICAgICAgICBpZiAobGVuZ3RoICYmIGkgPT0gbGVuZ3RoKSBicmVhawogICAgICB9CiAgICAgIGlmICghbGVuZ3RoKSBsZW5ndGggPSBpOwogICAgICB2YXIgcmV0ID0gJyc7CiAgICAgIGlmIChoYXNVdGYgPCAxMjgpIHsKICAgICAgICB2YXIgTUFYX0NIVU5LID0gMTAyNDsKICAgICAgICB2YXIgY3VycjsKICAgICAgICB3aGlsZSAobGVuZ3RoID4gMCkgewogICAgICAgICAgY3VyciA9IFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBIRUFQVTguc3ViYXJyYXkocHRyLCBwdHIgKyBNYXRoLm1pbihsZW5ndGgsIE1BWF9DSFVOSykpKTsKICAgICAgICAgIHJldCA9IHJldCA/IHJldCArIGN1cnIgOiBjdXJyOwogICAgICAgICAgcHRyICs9IE1BWF9DSFVOSzsKICAgICAgICAgIGxlbmd0aCAtPSBNQVhfQ0hVTks7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQKICAgICAgfQogICAgICByZXR1cm4gVVRGOFRvU3RyaW5nKHB0cikKICAgIH0KICAgIHZhciBVVEY4RGVjb2RlciA9IHR5cGVvZiBUZXh0RGVjb2RlciAhPT0gJ3VuZGVmaW5lZCcgPyBuZXcgVGV4dERlY29kZXIoJ3V0ZjgnKSA6IHVuZGVmaW5lZDsKICAgIGZ1bmN0aW9uIFVURjhBcnJheVRvU3RyaW5nKHU4QXJyYXksIGlkeCkgewogICAgICB2YXIgZW5kUHRyID0gaWR4OwogICAgICB3aGlsZSAodThBcnJheVtlbmRQdHJdKSArK2VuZFB0cjsKICAgICAgaWYgKGVuZFB0ciAtIGlkeCA+IDE2ICYmIHU4QXJyYXkuc3ViYXJyYXkgJiYgVVRGOERlY29kZXIpIHsKICAgICAgICByZXR1cm4gVVRGOERlY29kZXIuZGVjb2RlKHU4QXJyYXkuc3ViYXJyYXkoaWR4LCBlbmRQdHIpKQogICAgICB9IGVsc2UgewogICAgICAgIHZhciB1MCwgdTEsIHUyLCB1MywgdTQsIHU1OwogICAgICAgIHZhciBzdHIgPSAnJzsKICAgICAgICB3aGlsZSAoMSkgewogICAgICAgICAgdTAgPSB1OEFycmF5W2lkeCsrXTsKICAgICAgICAgIGlmICghdTApIHJldHVybiBzdHIKICAgICAgICAgIGlmICghKHUwICYgMTI4KSkgewogICAgICAgICAgICBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSh1MCk7CiAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICB9CiAgICAgICAgICB1MSA9IHU4QXJyYXlbaWR4KytdICYgNjM7CiAgICAgICAgICBpZiAoKHUwICYgMjI0KSA9PSAxOTIpIHsKICAgICAgICAgICAgc3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKCh1MCAmIDMxKSA8PCA2KSB8IHUxKTsKICAgICAgICAgICAgY29udGludWUKICAgICAgICAgIH0KICAgICAgICAgIHUyID0gdThBcnJheVtpZHgrK10gJiA2MzsKICAgICAgICAgIGlmICgodTAgJiAyNDApID09IDIyNCkgewogICAgICAgICAgICB1MCA9ICgodTAgJiAxNSkgPDwgMTIpIHwgKHUxIDw8IDYpIHwgdTI7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB1MyA9IHU4QXJyYXlbaWR4KytdICYgNjM7CiAgICAgICAgICAgIGlmICgodTAgJiAyNDgpID09IDI0MCkgewogICAgICAgICAgICAgIHUwID0gKCh1MCAmIDcpIDw8IDE4KSB8ICh1MSA8PCAxMikgfCAodTIgPDwgNikgfCB1MzsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB1NCA9IHU4QXJyYXlbaWR4KytdICYgNjM7CiAgICAgICAgICAgICAgaWYgKCh1MCAmIDI1MikgPT0gMjQ4KSB7CiAgICAgICAgICAgICAgICB1MCA9ICgodTAgJiAzKSA8PCAyNCkgfCAodTEgPDwgMTgpIHwgKHUyIDw8IDEyKSB8ICh1MyA8PCA2KSB8IHU0OwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB1NSA9IHU4QXJyYXlbaWR4KytdICYgNjM7CiAgICAgICAgICAgICAgICB1MCA9ICgodTAgJiAxKSA8PCAzMCkgfCAodTEgPDwgMjQpIHwgKHUyIDw8IDE4KSB8ICh1MyA8PCAxMikgfCAodTQgPDwgNikgfCB1NTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmICh1MCA8IDY1NTM2KSB7CiAgICAgICAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHUwKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHZhciBjaCA9IHUwIC0gNjU1MzY7CiAgICAgICAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2IHwgKGNoID4+IDEwKSwgNTYzMjAgfCAoY2ggJiAxMDIzKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBVVEY4VG9TdHJpbmcocHRyKSB7CiAgICAgIHJldHVybiBVVEY4QXJyYXlUb1N0cmluZyhIRUFQVTgsIHB0cikKICAgIH0KICAgIGZ1bmN0aW9uIHN0cmluZ1RvVVRGOEFycmF5KHN0ciwgb3V0VThBcnJheSwgb3V0SWR4LCBtYXhCeXRlc1RvV3JpdGUpIHsKICAgICAgaWYgKCEobWF4Qnl0ZXNUb1dyaXRlID4gMCkpIHJldHVybiAwCiAgICAgIHZhciBzdGFydElkeCA9IG91dElkeDsKICAgICAgdmFyIGVuZElkeCA9IG91dElkeCArIG1heEJ5dGVzVG9Xcml0ZSAtIDE7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKSB7CiAgICAgICAgdmFyIHUgPSBzdHIuY2hhckNvZGVBdChpKTsKICAgICAgICBpZiAodSA+PSA1NTI5NiAmJiB1IDw9IDU3MzQzKSB1ID0gKDY1NTM2ICsgKCh1ICYgMTAyMykgPDwgMTApKSB8IChzdHIuY2hhckNvZGVBdCgrK2kpICYgMTAyMyk7CiAgICAgICAgaWYgKHUgPD0gMTI3KSB7CiAgICAgICAgICBpZiAob3V0SWR4ID49IGVuZElkeCkgYnJlYWsKICAgICAgICAgIG91dFU4QXJyYXlbb3V0SWR4KytdID0gdTsKICAgICAgICB9IGVsc2UgaWYgKHUgPD0gMjA0NykgewogICAgICAgICAgaWYgKG91dElkeCArIDEgPj0gZW5kSWR4KSBicmVhawogICAgICAgICAgb3V0VThBcnJheVtvdXRJZHgrK10gPSAxOTIgfCAodSA+PiA2KTsKICAgICAgICAgIG91dFU4QXJyYXlbb3V0SWR4KytdID0gMTI4IHwgKHUgJiA2Myk7CiAgICAgICAgfSBlbHNlIGlmICh1IDw9IDY1NTM1KSB7CiAgICAgICAgICBpZiAob3V0SWR4ICsgMiA+PSBlbmRJZHgpIGJyZWFrCiAgICAgICAgICBvdXRVOEFycmF5W291dElkeCsrXSA9IDIyNCB8ICh1ID4+IDEyKTsKICAgICAgICAgIG91dFU4QXJyYXlbb3V0SWR4KytdID0gMTI4IHwgKCh1ID4+IDYpICYgNjMpOwogICAgICAgICAgb3V0VThBcnJheVtvdXRJZHgrK10gPSAxMjggfCAodSAmIDYzKTsKICAgICAgICB9IGVsc2UgaWYgKHUgPD0gMjA5NzE1MSkgewogICAgICAgICAgaWYgKG91dElkeCArIDMgPj0gZW5kSWR4KSBicmVhawogICAgICAgICAgb3V0VThBcnJheVtvdXRJZHgrK10gPSAyNDAgfCAodSA+PiAxOCk7CiAgICAgICAgICBvdXRVOEFycmF5W291dElkeCsrXSA9IDEyOCB8ICgodSA+PiAxMikgJiA2Myk7CiAgICAgICAgICBvdXRVOEFycmF5W291dElkeCsrXSA9IDEyOCB8ICgodSA+PiA2KSAmIDYzKTsKICAgICAgICAgIG91dFU4QXJyYXlbb3V0SWR4KytdID0gMTI4IHwgKHUgJiA2Myk7CiAgICAgICAgfSBlbHNlIGlmICh1IDw9IDY3MTA4ODYzKSB7CiAgICAgICAgICBpZiAob3V0SWR4ICsgNCA+PSBlbmRJZHgpIGJyZWFrCiAgICAgICAgICBvdXRVOEFycmF5W291dElkeCsrXSA9IDI0OCB8ICh1ID4+IDI0KTsKICAgICAgICAgIG91dFU4QXJyYXlbb3V0SWR4KytdID0gMTI4IHwgKCh1ID4+IDE4KSAmIDYzKTsKICAgICAgICAgIG91dFU4QXJyYXlbb3V0SWR4KytdID0gMTI4IHwgKCh1ID4+IDEyKSAmIDYzKTsKICAgICAgICAgIG91dFU4QXJyYXlbb3V0SWR4KytdID0gMTI4IHwgKCh1ID4+IDYpICYgNjMpOwogICAgICAgICAgb3V0VThBcnJheVtvdXRJZHgrK10gPSAxMjggfCAodSAmIDYzKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKG91dElkeCArIDUgPj0gZW5kSWR4KSBicmVhawogICAgICAgICAgb3V0VThBcnJheVtvdXRJZHgrK10gPSAyNTIgfCAodSA+PiAzMCk7CiAgICAgICAgICBvdXRVOEFycmF5W291dElkeCsrXSA9IDEyOCB8ICgodSA+PiAyNCkgJiA2Myk7CiAgICAgICAgICBvdXRVOEFycmF5W291dElkeCsrXSA9IDEyOCB8ICgodSA+PiAxOCkgJiA2Myk7CiAgICAgICAgICBvdXRVOEFycmF5W291dElkeCsrXSA9IDEyOCB8ICgodSA+PiAxMikgJiA2Myk7CiAgICAgICAgICBvdXRVOEFycmF5W291dElkeCsrXSA9IDEyOCB8ICgodSA+PiA2KSAmIDYzKTsKICAgICAgICAgIG91dFU4QXJyYXlbb3V0SWR4KytdID0gMTI4IHwgKHUgJiA2Myk7CiAgICAgICAgfQogICAgICB9CiAgICAgIG91dFU4QXJyYXlbb3V0SWR4XSA9IDA7CiAgICAgIHJldHVybiBvdXRJZHggLSBzdGFydElkeAogICAgfQogICAgZnVuY3Rpb24gc3RyaW5nVG9VVEY4KHN0ciwgb3V0UHRyLCBtYXhCeXRlc1RvV3JpdGUpIHsKICAgICAgcmV0dXJuIHN0cmluZ1RvVVRGOEFycmF5KHN0ciwgSEVBUFU4LCBvdXRQdHIsIG1heEJ5dGVzVG9Xcml0ZSkKICAgIH0KICAgIGZ1bmN0aW9uIGxlbmd0aEJ5dGVzVVRGOChzdHIpIHsKICAgICAgdmFyIGxlbiA9IDA7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKSB7CiAgICAgICAgdmFyIHUgPSBzdHIuY2hhckNvZGVBdChpKTsKICAgICAgICBpZiAodSA+PSA1NTI5NiAmJiB1IDw9IDU3MzQzKSB1ID0gKDY1NTM2ICsgKCh1ICYgMTAyMykgPDwgMTApKSB8IChzdHIuY2hhckNvZGVBdCgrK2kpICYgMTAyMyk7CiAgICAgICAgaWYgKHUgPD0gMTI3KSB7CiAgICAgICAgICArK2xlbjsKICAgICAgICB9IGVsc2UgaWYgKHUgPD0gMjA0NykgewogICAgICAgICAgbGVuICs9IDI7CiAgICAgICAgfSBlbHNlIGlmICh1IDw9IDY1NTM1KSB7CiAgICAgICAgICBsZW4gKz0gMzsKICAgICAgICB9IGVsc2UgaWYgKHUgPD0gMjA5NzE1MSkgewogICAgICAgICAgbGVuICs9IDQ7CiAgICAgICAgfSBlbHNlIGlmICh1IDw9IDY3MTA4ODYzKSB7CiAgICAgICAgICBsZW4gKz0gNTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbGVuICs9IDY7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBsZW4KICAgIH0KICAgIHR5cGVvZiBUZXh0RGVjb2RlciAhPT0gJ3VuZGVmaW5lZCcgPyBuZXcgVGV4dERlY29kZXIoJ3V0Zi0xNmxlJykgOiB1bmRlZmluZWQ7CiAgICBmdW5jdGlvbiBVVEYzMlRvU3RyaW5nKHB0cikgewogICAgICB2YXIgaSA9IDA7CiAgICAgIHZhciBzdHIgPSAnJzsKICAgICAgd2hpbGUgKDEpIHsKICAgICAgICB2YXIgdXRmMzIgPSBIRUFQMzJbKHB0ciArIGkgKiA0KSA+PiAyXTsKICAgICAgICBpZiAodXRmMzIgPT0gMCkgcmV0dXJuIHN0cgogICAgICAgICsraTsKICAgICAgICBpZiAodXRmMzIgPj0gNjU1MzYpIHsKICAgICAgICAgIHZhciBjaCA9IHV0ZjMyIC0gNjU1MzY7CiAgICAgICAgICBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSg1NTI5NiB8IChjaCA+PiAxMCksIDU2MzIwIHwgKGNoICYgMTAyMykpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSh1dGYzMik7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBhbGxvY2F0ZVVURjgoc3RyKSB7CiAgICAgIHZhciBzaXplID0gbGVuZ3RoQnl0ZXNVVEY4KHN0cikgKyAxOwogICAgICB2YXIgcmV0ID0gX21hbGxvYyhzaXplKTsKICAgICAgaWYgKHJldCkgc3RyaW5nVG9VVEY4QXJyYXkoc3RyLCBIRUFQOCwgcmV0LCBzaXplKTsKICAgICAgcmV0dXJuIHJldAogICAgfQogICAgZnVuY3Rpb24gZGVtYW5nbGUoZnVuYykgewogICAgICByZXR1cm4gZnVuYwogICAgfQogICAgZnVuY3Rpb24gZGVtYW5nbGVBbGwodGV4dCkgewogICAgICB2YXIgcmVnZXggPSAvX19aW1x3XGRfXSsvZzsKICAgICAgcmV0dXJuIHRleHQucmVwbGFjZShyZWdleCwgZnVuY3Rpb24gKHgpIHsKICAgICAgICB2YXIgeSA9IGRlbWFuZ2xlKHgpOwogICAgICAgIHJldHVybiB4ID09PSB5ID8geCA6IHggKyAnIFsnICsgeSArICddJwogICAgICB9KQogICAgfQogICAgZnVuY3Rpb24ganNTdGFja1RyYWNlKCkgewogICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCk7CiAgICAgIGlmICghZXJyLnN0YWNrKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcigwKQogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIGVyciA9IGU7CiAgICAgICAgfQogICAgICAgIGlmICghZXJyLnN0YWNrKSB7CiAgICAgICAgICByZXR1cm4gJyhubyBzdGFjayB0cmFjZSBhdmFpbGFibGUpJwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gZXJyLnN0YWNrLnRvU3RyaW5nKCkKICAgIH0KICAgIGZ1bmN0aW9uIHN0YWNrVHJhY2UoKSB7CiAgICAgIHZhciBqcyA9IGpzU3RhY2tUcmFjZSgpOwogICAgICBpZiAoTW9kdWxlWydleHRyYVN0YWNrVHJhY2UnXSkganMgKz0gJ1xuJyArIE1vZHVsZVsnZXh0cmFTdGFja1RyYWNlJ10oKTsKICAgICAgcmV0dXJuIGRlbWFuZ2xlQWxsKGpzKQogICAgfQogICAgdmFyIFdBU01fUEFHRV9TSVpFID0gNjU1MzY7CiAgICB2YXIgQVNNSlNfUEFHRV9TSVpFID0gMTY3NzcyMTY7CiAgICB2YXIgTUlOX1RPVEFMX01FTU9SWSA9IDE2Nzc3MjE2OwogICAgZnVuY3Rpb24gYWxpZ25VcCh4LCBtdWx0aXBsZSkgewogICAgICBpZiAoeCAlIG11bHRpcGxlID4gMCkgewogICAgICAgIHggKz0gbXVsdGlwbGUgLSAoeCAlIG11bHRpcGxlKTsKICAgICAgfQogICAgICByZXR1cm4geAogICAgfQogICAgdmFyIGJ1ZmZlciwgSEVBUDgsIEhFQVBVOCwgSEVBUDE2LCBIRUFQVTE2LCBIRUFQMzIsIEhFQVBVMzIsIEhFQVBGMzIsIEhFQVBGNjQ7CiAgICBmdW5jdGlvbiB1cGRhdGVHbG9iYWxCdWZmZXIoYnVmKSB7CiAgICAgIE1vZHVsZVsnYnVmZmVyJ10gPSBidWZmZXIgPSBidWY7CiAgICB9CiAgICBmdW5jdGlvbiB1cGRhdGVHbG9iYWxCdWZmZXJWaWV3cygpIHsKICAgICAgTW9kdWxlWydIRUFQOCddID0gSEVBUDggPSBuZXcgSW50OEFycmF5KGJ1ZmZlcik7CiAgICAgIE1vZHVsZVsnSEVBUDE2J10gPSBIRUFQMTYgPSBuZXcgSW50MTZBcnJheShidWZmZXIpOwogICAgICBNb2R1bGVbJ0hFQVAzMiddID0gSEVBUDMyID0gbmV3IEludDMyQXJyYXkoYnVmZmVyKTsKICAgICAgTW9kdWxlWydIRUFQVTgnXSA9IEhFQVBVOCA9IG5ldyBVaW50OEFycmF5KGJ1ZmZlcik7CiAgICAgIE1vZHVsZVsnSEVBUFUxNiddID0gSEVBUFUxNiA9IG5ldyBVaW50MTZBcnJheShidWZmZXIpOwogICAgICBNb2R1bGVbJ0hFQVBVMzInXSA9IEhFQVBVMzIgPSBuZXcgVWludDMyQXJyYXkoYnVmZmVyKTsKICAgICAgTW9kdWxlWydIRUFQRjMyJ10gPSBIRUFQRjMyID0gbmV3IEZsb2F0MzJBcnJheShidWZmZXIpOwogICAgICBNb2R1bGVbJ0hFQVBGNjQnXSA9IEhFQVBGNjQgPSBuZXcgRmxvYXQ2NEFycmF5KGJ1ZmZlcik7CiAgICB9CiAgICB2YXIgU1RBVElDX0JBU0UsIFNUQVRJQ1RPUCwgc3RhdGljU2VhbGVkOwogICAgdmFyIFNUQUNLX0JBU0UsIFNUQUNLVE9QLCBTVEFDS19NQVg7CiAgICB2YXIgRFlOQU1JQ19CQVNFLCBEWU5BTUlDVE9QX1BUUjsKICAgIFNUQVRJQ19CQVNFID0gU1RBVElDVE9QID0gU1RBQ0tfQkFTRSA9IFNUQUNLVE9QID0gU1RBQ0tfTUFYID0gRFlOQU1JQ19CQVNFID0gRFlOQU1JQ1RPUF9QVFIgPSAwOwogICAgc3RhdGljU2VhbGVkID0gZmFsc2U7CiAgICBmdW5jdGlvbiBhYm9ydE9uQ2Fubm90R3Jvd01lbW9yeSgpIHsKICAgICAgYWJvcnQoCiAgICAgICAgJ0Nhbm5vdCBlbmxhcmdlIG1lbW9yeSBhcnJheXMuIEVpdGhlciAoMSkgY29tcGlsZSB3aXRoICAtcyBUT1RBTF9NRU1PUlk9WCAgd2l0aCBYIGhpZ2hlciB0aGFuIHRoZSBjdXJyZW50IHZhbHVlICcgKwogICAgICAgICAgVE9UQUxfTUVNT1JZICsKICAgICAgICAgICcsICgyKSBjb21waWxlIHdpdGggIC1zIEFMTE9XX01FTU9SWV9HUk9XVEg9MSAgd2hpY2ggYWxsb3dzIGluY3JlYXNpbmcgdGhlIHNpemUgYXQgcnVudGltZSwgb3IgKDMpIGlmIHlvdSB3YW50IG1hbGxvYyB0byByZXR1cm4gTlVMTCAoMCkgaW5zdGVhZCBvZiB0aGlzIGFib3J0LCBjb21waWxlIHdpdGggIC1zIEFCT1JUSU5HX01BTExPQz0wICcKICAgICAgKTsKICAgIH0KICAgIGlmICghTW9kdWxlWydyZWFsbG9jQnVmZmVyJ10pCiAgICAgIE1vZHVsZVsncmVhbGxvY0J1ZmZlciddID0gZnVuY3Rpb24gKHNpemUpIHsKICAgICAgICB2YXIgcmV0OwogICAgICAgIHRyeSB7CiAgICAgICAgICBpZiAoQXJyYXlCdWZmZXIudHJhbnNmZXIpIHsKICAgICAgICAgICAgcmV0ID0gQXJyYXlCdWZmZXIudHJhbnNmZXIoYnVmZmVyLCBzaXplKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHZhciBvbGRIRUFQOCA9IEhFQVA4OwogICAgICAgICAgICByZXQgPSBuZXcgQXJyYXlCdWZmZXIoc2l6ZSk7CiAgICAgICAgICAgIHZhciB0ZW1wID0gbmV3IEludDhBcnJheShyZXQpOwogICAgICAgICAgICB0ZW1wLnNldChvbGRIRUFQOCk7CiAgICAgICAgICB9CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlCiAgICAgICAgfQogICAgICAgIHZhciBzdWNjZXNzID0gX2Vtc2NyaXB0ZW5fcmVwbGFjZV9tZW1vcnkocmV0KTsKICAgICAgICBpZiAoIXN1Y2Nlc3MpIHJldHVybiBmYWxzZQogICAgICAgIHJldHVybiByZXQKICAgICAgfTsKICAgIGZ1bmN0aW9uIGVubGFyZ2VNZW1vcnkoKSB7CiAgICAgIHZhciBQQUdFX01VTFRJUExFID0gTW9kdWxlWyd1c2luZ1dhc20nXSA/IFdBU01fUEFHRV9TSVpFIDogQVNNSlNfUEFHRV9TSVpFOwogICAgICB2YXIgTElNSVQgPSAyMTQ3NDgzNjQ4IC0gUEFHRV9NVUxUSVBMRTsKICAgICAgaWYgKEhFQVAzMltEWU5BTUlDVE9QX1BUUiA+PiAyXSA+IExJTUlUKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlCiAgICAgIH0KICAgICAgdmFyIE9MRF9UT1RBTF9NRU1PUlkgPSBUT1RBTF9NRU1PUlk7CiAgICAgIFRPVEFMX01FTU9SWSA9IE1hdGgubWF4KFRPVEFMX01FTU9SWSwgTUlOX1RPVEFMX01FTU9SWSk7CiAgICAgIHdoaWxlIChUT1RBTF9NRU1PUlkgPCBIRUFQMzJbRFlOQU1JQ1RPUF9QVFIgPj4gMl0pIHsKICAgICAgICBpZiAoVE9UQUxfTUVNT1JZIDw9IDUzNjg3MDkxMikgewogICAgICAgICAgVE9UQUxfTUVNT1JZID0gYWxpZ25VcCgyICogVE9UQUxfTUVNT1JZLCBQQUdFX01VTFRJUExFKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgVE9UQUxfTUVNT1JZID0gTWF0aC5taW4oYWxpZ25VcCgoMyAqIFRPVEFMX01FTU9SWSArIDIxNDc0ODM2NDgpIC8gNCwgUEFHRV9NVUxUSVBMRSksIExJTUlUKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgdmFyIHJlcGxhY2VtZW50ID0gTW9kdWxlWydyZWFsbG9jQnVmZmVyJ10oVE9UQUxfTUVNT1JZKTsKICAgICAgaWYgKCFyZXBsYWNlbWVudCB8fCByZXBsYWNlbWVudC5ieXRlTGVuZ3RoICE9IFRPVEFMX01FTU9SWSkgewogICAgICAgIFRPVEFMX01FTU9SWSA9IE9MRF9UT1RBTF9NRU1PUlk7CiAgICAgICAgcmV0dXJuIGZhbHNlCiAgICAgIH0KICAgICAgdXBkYXRlR2xvYmFsQnVmZmVyKHJlcGxhY2VtZW50KTsKICAgICAgdXBkYXRlR2xvYmFsQnVmZmVyVmlld3MoKTsKICAgICAgcmV0dXJuIHRydWUKICAgIH0KICAgIHZhciBieXRlTGVuZ3RoOwogICAgdHJ5IHsKICAgICAgYnl0ZUxlbmd0aCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5jYWxsLmJpbmQoT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihBcnJheUJ1ZmZlci5wcm90b3R5cGUsICdieXRlTGVuZ3RoJykuZ2V0KTsKICAgICAgYnl0ZUxlbmd0aChuZXcgQXJyYXlCdWZmZXIoNCkpOwogICAgfSBjYXRjaCAoZSkgewogICAgICBieXRlTGVuZ3RoID0gZnVuY3Rpb24gKGJ1ZmZlcikgewogICAgICAgIHJldHVybiBidWZmZXIuYnl0ZUxlbmd0aAogICAgICB9OwogICAgfQogICAgdmFyIFRPVEFMX1NUQUNLID0gTW9kdWxlWydUT1RBTF9TVEFDSyddIHx8IDUyNDI4ODA7CiAgICB2YXIgVE9UQUxfTUVNT1JZID0gTW9kdWxlWydUT1RBTF9NRU1PUlknXSB8fCAxNjc3NzIxNjsKICAgIGlmIChUT1RBTF9NRU1PUlkgPCBUT1RBTF9TVEFDSykKICAgICAgTW9kdWxlLnByaW50RXJyKAogICAgICAgICdUT1RBTF9NRU1PUlkgc2hvdWxkIGJlIGxhcmdlciB0aGFuIFRPVEFMX1NUQUNLLCB3YXMgJyArIFRPVEFMX01FTU9SWSArICchIChUT1RBTF9TVEFDSz0nICsgVE9UQUxfU1RBQ0sgKyAnKScKICAgICAgKTsKICAgIGlmIChNb2R1bGVbJ2J1ZmZlciddKSB7CiAgICAgIGJ1ZmZlciA9IE1vZHVsZVsnYnVmZmVyJ107CiAgICB9IGVsc2UgewogICAgICBpZiAodHlwZW9mIFdlYkFzc2VtYmx5ID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgV2ViQXNzZW1ibHkuTWVtb3J5ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgTW9kdWxlWyd3YXNtTWVtb3J5J10gPSBuZXcgV2ViQXNzZW1ibHkuTWVtb3J5KHsgaW5pdGlhbDogVE9UQUxfTUVNT1JZIC8gV0FTTV9QQUdFX1NJWkUgfSk7CiAgICAgICAgYnVmZmVyID0gTW9kdWxlWyd3YXNtTWVtb3J5J10uYnVmZmVyOwogICAgICB9IGVsc2UgewogICAgICAgIGJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcihUT1RBTF9NRU1PUlkpOwogICAgICB9CiAgICAgIE1vZHVsZVsnYnVmZmVyJ10gPSBidWZmZXI7CiAgICB9CiAgICB1cGRhdGVHbG9iYWxCdWZmZXJWaWV3cygpOwogICAgZnVuY3Rpb24gZ2V0VG90YWxNZW1vcnkoKSB7CiAgICAgIHJldHVybiBUT1RBTF9NRU1PUlkKICAgIH0KICAgIEhFQVAzMlswXSA9IDE2Njg1MDkwMjk7CiAgICBIRUFQMTZbMV0gPSAyNTQ1OTsKICAgIGlmIChIRUFQVThbMl0gIT09IDExNSB8fCBIRUFQVThbM10gIT09IDk5KSB0aHJvdyAnUnVudGltZSBlcnJvcjogZXhwZWN0ZWQgdGhlIHN5c3RlbSB0byBiZSBsaXR0bGUtZW5kaWFuIScKICAgIGZ1bmN0aW9uIGNhbGxSdW50aW1lQ2FsbGJhY2tzKGNhbGxiYWNrcykgewogICAgICB3aGlsZSAoY2FsbGJhY2tzLmxlbmd0aCA+IDApIHsKICAgICAgICB2YXIgY2FsbGJhY2sgPSBjYWxsYmFja3Muc2hpZnQoKTsKICAgICAgICBpZiAodHlwZW9mIGNhbGxiYWNrID09ICdmdW5jdGlvbicpIHsKICAgICAgICAgIGNhbGxiYWNrKCk7CiAgICAgICAgICBjb250aW51ZQogICAgICAgIH0KICAgICAgICB2YXIgZnVuYyA9IGNhbGxiYWNrLmZ1bmM7CiAgICAgICAgaWYgKHR5cGVvZiBmdW5jID09PSAnbnVtYmVyJykgewogICAgICAgICAgaWYgKGNhbGxiYWNrLmFyZyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIE1vZHVsZVsnZHluQ2FsbF92J10oZnVuYyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBNb2R1bGVbJ2R5bkNhbGxfdmknXShmdW5jLCBjYWxsYmFjay5hcmcpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBmdW5jKGNhbGxiYWNrLmFyZyA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGNhbGxiYWNrLmFyZyk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICB2YXIgX19BVFBSRVJVTl9fID0gW107CiAgICB2YXIgX19BVElOSVRfXyA9IFtdOwogICAgdmFyIF9fQVRNQUlOX18gPSBbXTsKICAgIHZhciBfX0FURVhJVF9fID0gW107CiAgICB2YXIgX19BVFBPU1RSVU5fXyA9IFtdOwogICAgdmFyIHJ1bnRpbWVJbml0aWFsaXplZCA9IGZhbHNlOwogICAgZnVuY3Rpb24gcHJlUnVuKCkgewogICAgICBpZiAoTW9kdWxlWydwcmVSdW4nXSkgewogICAgICAgIGlmICh0eXBlb2YgTW9kdWxlWydwcmVSdW4nXSA9PSAnZnVuY3Rpb24nKSBNb2R1bGVbJ3ByZVJ1biddID0gW01vZHVsZVsncHJlUnVuJ11dOwogICAgICAgIHdoaWxlIChNb2R1bGVbJ3ByZVJ1biddLmxlbmd0aCkgewogICAgICAgICAgYWRkT25QcmVSdW4oTW9kdWxlWydwcmVSdW4nXS5zaGlmdCgpKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY2FsbFJ1bnRpbWVDYWxsYmFja3MoX19BVFBSRVJVTl9fKTsKICAgIH0KICAgIGZ1bmN0aW9uIGVuc3VyZUluaXRSdW50aW1lKCkgewogICAgICBpZiAocnVudGltZUluaXRpYWxpemVkKSByZXR1cm4KICAgICAgcnVudGltZUluaXRpYWxpemVkID0gdHJ1ZTsKICAgICAgY2FsbFJ1bnRpbWVDYWxsYmFja3MoX19BVElOSVRfXyk7CiAgICB9CiAgICBmdW5jdGlvbiBwcmVNYWluKCkgewogICAgICBjYWxsUnVudGltZUNhbGxiYWNrcyhfX0FUTUFJTl9fKTsKICAgIH0KICAgIGZ1bmN0aW9uIGV4aXRSdW50aW1lKCkgewogICAgICBjYWxsUnVudGltZUNhbGxiYWNrcyhfX0FURVhJVF9fKTsKICAgIH0KICAgIGZ1bmN0aW9uIHBvc3RSdW4oKSB7CiAgICAgIGlmIChNb2R1bGVbJ3Bvc3RSdW4nXSkgewogICAgICAgIGlmICh0eXBlb2YgTW9kdWxlWydwb3N0UnVuJ10gPT0gJ2Z1bmN0aW9uJykgTW9kdWxlWydwb3N0UnVuJ10gPSBbTW9kdWxlWydwb3N0UnVuJ11dOwogICAgICAgIHdoaWxlIChNb2R1bGVbJ3Bvc3RSdW4nXS5sZW5ndGgpIHsKICAgICAgICAgIGFkZE9uUG9zdFJ1bihNb2R1bGVbJ3Bvc3RSdW4nXS5zaGlmdCgpKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY2FsbFJ1bnRpbWVDYWxsYmFja3MoX19BVFBPU1RSVU5fXyk7CiAgICB9CiAgICBmdW5jdGlvbiBhZGRPblByZVJ1bihjYikgewogICAgICBfX0FUUFJFUlVOX18udW5zaGlmdChjYik7CiAgICB9CiAgICBmdW5jdGlvbiBhZGRPblBvc3RSdW4oY2IpIHsKICAgICAgX19BVFBPU1RSVU5fXy51bnNoaWZ0KGNiKTsKICAgIH0KICAgIGZ1bmN0aW9uIHdyaXRlQXNjaWlUb01lbW9yeShzdHIsIGJ1ZmZlciwgZG9udEFkZE51bGwpIHsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyArK2kpIHsKICAgICAgICBIRUFQOFtidWZmZXIrKyA+PiAwXSA9IHN0ci5jaGFyQ29kZUF0KGkpOwogICAgICB9CiAgICAgIGlmICghZG9udEFkZE51bGwpIEhFQVA4W2J1ZmZlciA+PiAwXSA9IDA7CiAgICB9CiAgICB2YXIgTWF0aF9hYnMgPSBNYXRoLmFiczsKICAgIHZhciBNYXRoX2NlaWwgPSBNYXRoLmNlaWw7CiAgICB2YXIgTWF0aF9mbG9vciA9IE1hdGguZmxvb3I7CiAgICB2YXIgTWF0aF9taW4gPSBNYXRoLm1pbjsKICAgIHZhciBydW5EZXBlbmRlbmNpZXMgPSAwOwogICAgdmFyIGRlcGVuZGVuY2llc0Z1bGZpbGxlZCA9IG51bGw7CiAgICBmdW5jdGlvbiBhZGRSdW5EZXBlbmRlbmN5KGlkKSB7CiAgICAgIHJ1bkRlcGVuZGVuY2llcysrOwogICAgICBpZiAoTW9kdWxlWydtb25pdG9yUnVuRGVwZW5kZW5jaWVzJ10pIHsKICAgICAgICBNb2R1bGVbJ21vbml0b3JSdW5EZXBlbmRlbmNpZXMnXShydW5EZXBlbmRlbmNpZXMpOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiByZW1vdmVSdW5EZXBlbmRlbmN5KGlkKSB7CiAgICAgIHJ1bkRlcGVuZGVuY2llcy0tOwogICAgICBpZiAoTW9kdWxlWydtb25pdG9yUnVuRGVwZW5kZW5jaWVzJ10pIHsKICAgICAgICBNb2R1bGVbJ21vbml0b3JSdW5EZXBlbmRlbmNpZXMnXShydW5EZXBlbmRlbmNpZXMpOwogICAgICB9CiAgICAgIGlmIChydW5EZXBlbmRlbmNpZXMgPT0gMCkgewogICAgICAgIGlmIChkZXBlbmRlbmNpZXNGdWxmaWxsZWQpIHsKICAgICAgICAgIHZhciBjYWxsYmFjayA9IGRlcGVuZGVuY2llc0Z1bGZpbGxlZDsKICAgICAgICAgIGRlcGVuZGVuY2llc0Z1bGZpbGxlZCA9IG51bGw7CiAgICAgICAgICBjYWxsYmFjaygpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgTW9kdWxlWydwcmVsb2FkZWRJbWFnZXMnXSA9IHt9OwogICAgTW9kdWxlWydwcmVsb2FkZWRBdWRpb3MnXSA9IHt9OwogICAgdmFyIGRhdGFVUklQcmVmaXggPSAnZGF0YTphcHBsaWNhdGlvbi9vY3RldC1zdHJlYW07YmFzZTY0LCc7CiAgICBmdW5jdGlvbiBpc0RhdGFVUkkoZmlsZW5hbWUpIHsKICAgICAgcmV0dXJuIFN0cmluZy5wcm90b3R5cGUuc3RhcnRzV2l0aCA/IGZpbGVuYW1lLnN0YXJ0c1dpdGgoZGF0YVVSSVByZWZpeCkgOiBmaWxlbmFtZS5pbmRleE9mKGRhdGFVUklQcmVmaXgpID09PSAwCiAgICB9CiAgICBmdW5jdGlvbiBpbnRlZ3JhdGVXYXNtSlMoKSB7CiAgICAgIHZhciB3YXNtVGV4dEZpbGUgPSAndW5wYWNrLndhc3QnOwogICAgICB2YXIgYXNtanNDb2RlRmlsZSA9ICd1bnBhY2sudGVtcC5hc20uanMnOwogICAgICBpZiAodHlwZW9mIE1vZHVsZVsnbG9jYXRlRmlsZSddID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgaWYgKCFpc0RhdGFVUkkod2FzbVRleHRGaWxlKSkgewogICAgICAgICAgd2FzbVRleHRGaWxlID0gTW9kdWxlWydsb2NhdGVGaWxlJ10od2FzbVRleHRGaWxlKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFpc0RhdGFVUkkod2FzbUJpbmFyeUZpbGUpKSB7CiAgICAgICAgICB3YXNtQmluYXJ5RmlsZSA9IE1vZHVsZVsnbG9jYXRlRmlsZSddKHdhc21CaW5hcnlGaWxlKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFpc0RhdGFVUkkoYXNtanNDb2RlRmlsZSkpIHsKICAgICAgICAgIGFzbWpzQ29kZUZpbGUgPSBNb2R1bGVbJ2xvY2F0ZUZpbGUnXShhc21qc0NvZGVGaWxlKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3Qgd2FzbVBhZ2VTaXplID0gNjQgKiAxMDI0OwogICAgICBjb25zdCBpbmZvID0gewogICAgICAgIGFzbTJ3YXNtOiB7CiAgICAgICAgICAnZjY0LXJlbSc6IGZ1bmN0aW9uICh4LCB5KSB7CiAgICAgICAgICAgIHJldHVybiB4ICUgeQogICAgICAgICAgfSwKICAgICAgICAgIGRlYnVnZ2VyOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIGRlYnVnZ2VyCiAgICAgICAgICB9LAogICAgICAgIH0sCiAgICAgICAgcGFyZW50OiBNb2R1bGUsCiAgICAgIH07CiAgICAgIHZhciBleHBvcnRzID0gbnVsbDsKICAgICAgZnVuY3Rpb24gbWVyZ2VNZW1vcnkobmV3QnVmZmVyKSB7CiAgICAgICAgdmFyIG9sZEJ1ZmZlciA9IE1vZHVsZVsnYnVmZmVyJ107CiAgICAgICAgaWYgKG5ld0J1ZmZlci5ieXRlTGVuZ3RoIDwgb2xkQnVmZmVyLmJ5dGVMZW5ndGgpIHsKICAgICAgICAgIE1vZHVsZVsncHJpbnRFcnInXSgKICAgICAgICAgICAgJ3RoZSBuZXcgYnVmZmVyIGluIG1lcmdlTWVtb3J5IGlzIHNtYWxsZXIgdGhhbiB0aGUgcHJldmlvdXMgb25lLiBpbiBuYXRpdmUgd2FzbSwgd2Ugc2hvdWxkIGdyb3cgbWVtb3J5IGhlcmUnCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICB2YXIgb2xkVmlldyA9IG5ldyBJbnQ4QXJyYXkob2xkQnVmZmVyKTsKICAgICAgICB2YXIgbmV3VmlldyA9IG5ldyBJbnQ4QXJyYXkobmV3QnVmZmVyKTsKICAgICAgICBuZXdWaWV3LnNldChvbGRWaWV3KTsKICAgICAgICB1cGRhdGVHbG9iYWxCdWZmZXIobmV3QnVmZmVyKTsKICAgICAgICB1cGRhdGVHbG9iYWxCdWZmZXJWaWV3cygpOwogICAgICB9CiAgICAgIGZ1bmN0aW9uIGZpeEltcG9ydHMoaW1wb3J0cykgewogICAgICAgIHJldHVybiBpbXBvcnRzCiAgICAgIH0KICAgICAgZnVuY3Rpb24gZ2V0QmluYXJ5KCkgewogICAgICAgIHRyeSB7CiAgICAgICAgICBpZiAoTW9kdWxlWyd3YXNtQmluYXJ5J10pIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KE1vZHVsZVsnd2FzbUJpbmFyeSddKQogICAgICAgICAgfQogICAgICAgICAgaWYgKE1vZHVsZVsncmVhZEJpbmFyeSddKSB7CiAgICAgICAgICAgIHJldHVybiBNb2R1bGVbJ3JlYWRCaW5hcnknXSh3YXNtQmluYXJ5RmlsZSkKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRocm93ICJvbiB0aGUgd2ViLCB3ZSBuZWVkIHRoZSB3YXNtIGJpbmFyeSB0byBiZSBwcmVsb2FkZWQgYW5kIHNldCBvbiBNb2R1bGVbJ3dhc21CaW5hcnknXS4gZW1jYy5weSB3aWxsIGRvIHRoYXQgZm9yIHlvdSB3aGVuIGdlbmVyYXRpbmcgSFRNTCAoYnV0IG5vdCBKUykiCiAgICAgICAgICB9CiAgICAgICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgICAgICBhYm9ydChlcnIpOwogICAgICAgIH0KICAgICAgfQogICAgICBmdW5jdGlvbiBnZXRCaW5hcnlQcm9taXNlKCkgewogICAgICAgIGlmICghTW9kdWxlWyd3YXNtQmluYXJ5J10gJiYgKEVOVklST05NRU5UX0lTX1dFQiB8fCBFTlZJUk9OTUVOVF9JU19XT1JLRVIpICYmIHR5cGVvZiBmZXRjaCA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgICAgcmV0dXJuIGZldGNoKHdhc21CaW5hcnlGaWxlLCB7IGNyZWRlbnRpYWxzIH0pCiAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkgewogICAgICAgICAgICAgIGlmICghcmVzcG9uc2VbJ29rJ10pIHsKICAgICAgICAgICAgICAgIHRocm93ICJmYWlsZWQgdG8gbG9hZCB3YXNtIGJpbmFyeSBmaWxlIGF0ICciICsgd2FzbUJpbmFyeUZpbGUgKyAiJyIKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlWydhcnJheUJ1ZmZlciddKCkKICAgICAgICAgICAgfSkKICAgICAgICAgICAgLmNhdGNoKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICByZXR1cm4gZ2V0QmluYXJ5KCkKICAgICAgICAgICAgfSkKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICAgIHJlc29sdmUoZ2V0QmluYXJ5KCkpOwogICAgICAgIH0pCiAgICAgIH0KICAgICAgZnVuY3Rpb24gZG9OYXRpdmVXYXNtKGdsb2JhbCwgZW52LCBwcm92aWRlZEJ1ZmZlcikgewogICAgICAgIGlmICh0eXBlb2YgV2ViQXNzZW1ibHkgIT09ICdvYmplY3QnKSB7CiAgICAgICAgICBNb2R1bGVbJ3ByaW50RXJyJ10oJ25vIG5hdGl2ZSB3YXNtIHN1cHBvcnQgZGV0ZWN0ZWQnKTsKICAgICAgICAgIHJldHVybiBmYWxzZQogICAgICAgIH0KICAgICAgICBpZiAoIShNb2R1bGVbJ3dhc21NZW1vcnknXSBpbnN0YW5jZW9mIFdlYkFzc2VtYmx5Lk1lbW9yeSkpIHsKICAgICAgICAgIE1vZHVsZVsncHJpbnRFcnInXSgnbm8gbmF0aXZlIHdhc20gTWVtb3J5IGluIHVzZScpOwogICAgICAgICAgcmV0dXJuIGZhbHNlCiAgICAgICAgfQogICAgICAgIGVudlsnbWVtb3J5J10gPSBNb2R1bGVbJ3dhc21NZW1vcnknXTsKICAgICAgICBpbmZvWydnbG9iYWwnXSA9IHsgTmFOOiBOYU4sIEluZmluaXR5OiBJbmZpbml0eSB9OwogICAgICAgIGluZm9bJ2dsb2JhbC5NYXRoJ10gPSBNYXRoOwogICAgICAgIGluZm9bJ2VudiddID0gZW52OwogICAgICAgIGZ1bmN0aW9uIHJlY2VpdmVJbnN0YW5jZShpbnN0YW5jZSwgbW9kdWxlKSB7CiAgICAgICAgICBleHBvcnRzID0gaW5zdGFuY2UuZXhwb3J0czsKICAgICAgICAgIGlmIChleHBvcnRzLm1lbW9yeSkgbWVyZ2VNZW1vcnkoZXhwb3J0cy5tZW1vcnkpOwogICAgICAgICAgTW9kdWxlWydhc20nXSA9IGV4cG9ydHM7CiAgICAgICAgICBNb2R1bGVbJ3VzaW5nV2FzbSddID0gdHJ1ZTsKICAgICAgICAgIHJlbW92ZVJ1bkRlcGVuZGVuY3koKTsKICAgICAgICB9CiAgICAgICAgYWRkUnVuRGVwZW5kZW5jeSgpOwogICAgICAgIGlmIChNb2R1bGVbJ2luc3RhbnRpYXRlV2FzbSddKSB7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICByZXR1cm4gTW9kdWxlWydpbnN0YW50aWF0ZVdhc20nXShpbmZvLCByZWNlaXZlSW5zdGFuY2UpCiAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIE1vZHVsZVsncHJpbnRFcnInXSgnTW9kdWxlLmluc3RhbnRpYXRlV2FzbSBjYWxsYmFjayBmYWlsZWQgd2l0aCBlcnJvcjogJyArIGUpOwogICAgICAgICAgICByZXR1cm4gZmFsc2UKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gcmVjZWl2ZUluc3RhbnRpYXRlZFNvdXJjZShvdXRwdXQpIHsKICAgICAgICAgIHJlY2VpdmVJbnN0YW5jZShvdXRwdXRbJ2luc3RhbmNlJ10sIG91dHB1dFsnbW9kdWxlJ10pOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBpbnN0YW50aWF0ZUFycmF5QnVmZmVyKHJlY2VpdmVyKSB7CiAgICAgICAgICBnZXRCaW5hcnlQcm9taXNlKCkKICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKGJpbmFyeSkgewogICAgICAgICAgICAgIHJldHVybiBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZShiaW5hcnksIGluZm8pCiAgICAgICAgICAgIH0pCiAgICAgICAgICAgIC50aGVuKHJlY2VpdmVyKQogICAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgICAgIE1vZHVsZVsncHJpbnRFcnInXSgnZmFpbGVkIHRvIGFzeW5jaHJvbm91c2x5IHByZXBhcmUgd2FzbTogJyArIHJlYXNvbik7CiAgICAgICAgICAgICAgYWJvcnQocmVhc29uKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIGlmICgKICAgICAgICAgICFNb2R1bGVbJ3dhc21CaW5hcnknXSAmJgogICAgICAgICAgdHlwZW9mIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nID09PSAnZnVuY3Rpb24nICYmCiAgICAgICAgICAhaXNEYXRhVVJJKHdhc21CaW5hcnlGaWxlKSAmJgogICAgICAgICAgdHlwZW9mIGZldGNoID09PSAnZnVuY3Rpb24nCiAgICAgICAgKSB7CiAgICAgICAgICBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZyhmZXRjaCh3YXNtQmluYXJ5RmlsZSwgeyBjcmVkZW50aWFscyB9KSwgaW5mbykKICAgICAgICAgICAgLnRoZW4ocmVjZWl2ZUluc3RhbnRpYXRlZFNvdXJjZSkKICAgICAgICAgICAgLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgICAgICBNb2R1bGVbJ3ByaW50RXJyJ10oJ3dhc20gc3RyZWFtaW5nIGNvbXBpbGUgZmFpbGVkOiAnICsgcmVhc29uKTsKICAgICAgICAgICAgICBNb2R1bGVbJ3ByaW50RXJyJ10oJ2ZhbGxpbmcgYmFjayB0byBBcnJheUJ1ZmZlciBpbnN0YW50aWF0aW9uJyk7CiAgICAgICAgICAgICAgaW5zdGFudGlhdGVBcnJheUJ1ZmZlcihyZWNlaXZlSW5zdGFudGlhdGVkU291cmNlKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGluc3RhbnRpYXRlQXJyYXlCdWZmZXIocmVjZWl2ZUluc3RhbnRpYXRlZFNvdXJjZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB7fQogICAgICB9CiAgICAgIE1vZHVsZVsnYXNtUHJlbG9hZCddID0gTW9kdWxlWydhc20nXTsKICAgICAgdmFyIGFzbWpzUmVhbGxvY0J1ZmZlciA9IE1vZHVsZVsncmVhbGxvY0J1ZmZlciddOwogICAgICB2YXIgd2FzbVJlYWxsb2NCdWZmZXIgPSBmdW5jdGlvbiAoc2l6ZSkgewogICAgICAgIHZhciBQQUdFX01VTFRJUExFID0gTW9kdWxlWyd1c2luZ1dhc20nXSA/IFdBU01fUEFHRV9TSVpFIDogQVNNSlNfUEFHRV9TSVpFOwogICAgICAgIHNpemUgPSBhbGlnblVwKHNpemUsIFBBR0VfTVVMVElQTEUpOwogICAgICAgIHZhciBvbGQgPSBNb2R1bGVbJ2J1ZmZlciddOwogICAgICAgIHZhciBvbGRTaXplID0gb2xkLmJ5dGVMZW5ndGg7CiAgICAgICAgaWYgKE1vZHVsZVsndXNpbmdXYXNtJ10pIHsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHZhciByZXN1bHQgPSBNb2R1bGVbJ3dhc21NZW1vcnknXS5ncm93KChzaXplIC0gb2xkU2l6ZSkgLyB3YXNtUGFnZVNpemUpOwogICAgICAgICAgICBpZiAocmVzdWx0ICE9PSAoLTEgfCAwKSkgewogICAgICAgICAgICAgIHJldHVybiAoTW9kdWxlWydidWZmZXInXSA9IE1vZHVsZVsnd2FzbU1lbW9yeSddLmJ1ZmZlcikKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXR1cm4gbnVsbAogICAgICAgICAgICB9CiAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9OwogICAgICBNb2R1bGVbJ3JlYWxsb2NCdWZmZXInXSA9IGZ1bmN0aW9uIChzaXplKSB7CiAgICAgICAgaWYgKGZpbmFsTWV0aG9kID09PSAnYXNtanMnKSB7CiAgICAgICAgICByZXR1cm4gYXNtanNSZWFsbG9jQnVmZmVyKHNpemUpCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiB3YXNtUmVhbGxvY0J1ZmZlcihzaXplKQogICAgICAgIH0KICAgICAgfTsKICAgICAgdmFyIGZpbmFsTWV0aG9kID0gJyc7CiAgICAgIE1vZHVsZVsnYXNtJ10gPSBmdW5jdGlvbiAoZ2xvYmFsLCBlbnYsIHByb3ZpZGVkQnVmZmVyKSB7CiAgICAgICAgZW52ID0gZml4SW1wb3J0cyhlbnYpOwogICAgICAgIGlmICghZW52Wyd0YWJsZSddKSB7CiAgICAgICAgICB2YXIgVEFCTEVfU0laRSA9IE1vZHVsZVsnd2FzbVRhYmxlU2l6ZSddOwogICAgICAgICAgaWYgKFRBQkxFX1NJWkUgPT09IHVuZGVmaW5lZCkgVEFCTEVfU0laRSA9IDEwMjQ7CiAgICAgICAgICB2YXIgTUFYX1RBQkxFX1NJWkUgPSBNb2R1bGVbJ3dhc21NYXhUYWJsZVNpemUnXTsKICAgICAgICAgIGlmICh0eXBlb2YgV2ViQXNzZW1ibHkgPT09ICdvYmplY3QnICYmIHR5cGVvZiBXZWJBc3NlbWJseS5UYWJsZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgICAgICBpZiAoTUFYX1RBQkxFX1NJWkUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgIGVudlsndGFibGUnXSA9IG5ldyBXZWJBc3NlbWJseS5UYWJsZSh7IGluaXRpYWw6IFRBQkxFX1NJWkUsIG1heGltdW06IE1BWF9UQUJMRV9TSVpFLCBlbGVtZW50OiAnYW55ZnVuYycgfSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZW52Wyd0YWJsZSddID0gbmV3IFdlYkFzc2VtYmx5LlRhYmxlKHsgaW5pdGlhbDogVEFCTEVfU0laRSwgZWxlbWVudDogJ2FueWZ1bmMnIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbnZbJ3RhYmxlJ10gPSBuZXcgQXJyYXkoVEFCTEVfU0laRSk7CiAgICAgICAgICB9CiAgICAgICAgICBNb2R1bGVbJ3dhc21UYWJsZSddID0gZW52Wyd0YWJsZSddOwogICAgICAgIH0KICAgICAgICBpZiAoIWVudlsnbWVtb3J5QmFzZSddKSB7CiAgICAgICAgICBlbnZbJ21lbW9yeUJhc2UnXSA9IE1vZHVsZVsnU1RBVElDX0JBU0UnXTsKICAgICAgICB9CiAgICAgICAgaWYgKCFlbnZbJ3RhYmxlQmFzZSddKSB7CiAgICAgICAgICBlbnZbJ3RhYmxlQmFzZSddID0gMDsKICAgICAgICB9CiAgICAgICAgdmFyIGV4cG9ydHM7CiAgICAgICAgZXhwb3J0cyA9IGRvTmF0aXZlV2FzbShnbG9iYWwsIGVudik7CiAgICAgICAgaWYgKCFleHBvcnRzKQogICAgICAgICAgYWJvcnQoCiAgICAgICAgICAgICdubyBiaW5hcnllbiBtZXRob2Qgc3VjY2VlZGVkLiBjb25zaWRlciBlbmFibGluZyBtb3JlIG9wdGlvbnMsIGxpa2UgaW50ZXJwcmV0aW5nLCBpZiB5b3Ugd2FudCB0aGF0OiBodHRwczovL2dpdGh1Yi5jb20va3JpcGtlbi9lbXNjcmlwdGVuL3dpa2kvV2ViQXNzZW1ibHkjYmluYXJ5ZW4tbWV0aG9kcycKICAgICAgICAgICk7CiAgICAgICAgcmV0dXJuIGV4cG9ydHMKICAgICAgfTsKICAgIH0KICAgIGludGVncmF0ZVdhc21KUygpOwogICAgU1RBVElDX0JBU0UgPSBHTE9CQUxfQkFTRTsKICAgIFNUQVRJQ1RPUCA9IFNUQVRJQ19CQVNFICsgNjY5NjA7CiAgICBfX0FUSU5JVF9fLnB1c2goCiAgICAgIHsKICAgICAgICBmdW5jOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICBfX0dMT0JBTF9fc3ViX0lfZ2xvYmFsX2NwcCgpOwogICAgICAgIH0sCiAgICAgIH0sCiAgICAgIHsKICAgICAgICBmdW5jOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICBfX0dMT0JBTF9fc3ViX0lfY3JjX2NwcCgpOwogICAgICAgIH0sCiAgICAgIH0sCiAgICAgIHsKICAgICAgICBmdW5jOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICBfX0dMT0JBTF9fc3ViX0lfYnJpZGdlX2NwcCgpOwogICAgICAgIH0sCiAgICAgIH0sCiAgICAgIHsKICAgICAgICBmdW5jOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICBfX0dMT0JBTF9fc3ViX0lfYmluZF9jcHAoKTsKICAgICAgICB9LAogICAgICB9CiAgICApOwogICAgdmFyIFNUQVRJQ19CVU1QID0gNjY5NjA7CiAgICBNb2R1bGVbJ1NUQVRJQ19CQVNFJ10gPSBTVEFUSUNfQkFTRTsKICAgIE1vZHVsZVsnU1RBVElDX0JVTVAnXSA9IFNUQVRJQ19CVU1QOwogICAgU1RBVElDVE9QICs9IDE2OwogICAgZnVuY3Rpb24gX19fY3hhX2FsbG9jYXRlX2V4Y2VwdGlvbihzaXplKSB7CiAgICAgIHJldHVybiBfbWFsbG9jKHNpemUpCiAgICB9CiAgICBmdW5jdGlvbiBfX1pTdDE4dW5jYXVnaHRfZXhjZXB0aW9udigpIHsKICAgICAgcmV0dXJuICEhX19aU3QxOHVuY2F1Z2h0X2V4Y2VwdGlvbnYudW5jYXVnaHRfZXhjZXB0aW9uCiAgICB9CiAgICB2YXIgRVhDRVBUSU9OUyA9IHsKICAgICAgbGFzdDogMCwKICAgICAgY2F1Z2h0OiBbXSwKICAgICAgaW5mb3M6IHt9LAogICAgICBkZUFkanVzdDogZnVuY3Rpb24gKGFkanVzdGVkKSB7CiAgICAgICAgaWYgKCFhZGp1c3RlZCB8fCBFWENFUFRJT05TLmluZm9zW2FkanVzdGVkXSkgcmV0dXJuIGFkanVzdGVkCiAgICAgICAgZm9yICh2YXIga2V5IGluIEVYQ0VQVElPTlMuaW5mb3MpIHsKICAgICAgICAgIHZhciBwdHIgPSAra2V5OwogICAgICAgICAgdmFyIGluZm8gPSBFWENFUFRJT05TLmluZm9zW3B0cl07CiAgICAgICAgICBpZiAoaW5mby5hZGp1c3RlZCA9PT0gYWRqdXN0ZWQpIHsKICAgICAgICAgICAgcmV0dXJuIHB0cgogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gYWRqdXN0ZWQKICAgICAgfSwKICAgICAgYWRkUmVmOiBmdW5jdGlvbiAocHRyKSB7CiAgICAgICAgaWYgKCFwdHIpIHJldHVybgogICAgICAgIHZhciBpbmZvID0gRVhDRVBUSU9OUy5pbmZvc1twdHJdOwogICAgICAgIGluZm8ucmVmY291bnQrKzsKICAgICAgfSwKICAgICAgZGVjUmVmOiBmdW5jdGlvbiAocHRyKSB7CiAgICAgICAgaWYgKCFwdHIpIHJldHVybgogICAgICAgIHZhciBpbmZvID0gRVhDRVBUSU9OUy5pbmZvc1twdHJdOwogICAgICAgIGFzc2VydChpbmZvLnJlZmNvdW50ID4gMCk7CiAgICAgICAgaW5mby5yZWZjb3VudC0tOwogICAgICAgIGlmIChpbmZvLnJlZmNvdW50ID09PSAwICYmICFpbmZvLnJldGhyb3duKSB7CiAgICAgICAgICBpZiAoaW5mby5kZXN0cnVjdG9yKSB7CiAgICAgICAgICAgIE1vZHVsZVsnZHluQ2FsbF92aSddKGluZm8uZGVzdHJ1Y3RvciwgcHRyKTsKICAgICAgICAgIH0KICAgICAgICAgIGRlbGV0ZSBFWENFUFRJT05TLmluZm9zW3B0cl07CiAgICAgICAgICBfX19jeGFfZnJlZV9leGNlcHRpb24ocHRyKTsKICAgICAgICB9CiAgICAgIH0sCiAgICAgIGNsZWFyUmVmOiBmdW5jdGlvbiAocHRyKSB7CiAgICAgICAgaWYgKCFwdHIpIHJldHVybgogICAgICAgIHZhciBpbmZvID0gRVhDRVBUSU9OUy5pbmZvc1twdHJdOwogICAgICAgIGluZm8ucmVmY291bnQgPSAwOwogICAgICB9LAogICAgfTsKICAgIGZ1bmN0aW9uIF9fX2N4YV9iZWdpbl9jYXRjaChwdHIpIHsKICAgICAgdmFyIGluZm8gPSBFWENFUFRJT05TLmluZm9zW3B0cl07CiAgICAgIGlmIChpbmZvICYmICFpbmZvLmNhdWdodCkgewogICAgICAgIGluZm8uY2F1Z2h0ID0gdHJ1ZTsKICAgICAgICBfX1pTdDE4dW5jYXVnaHRfZXhjZXB0aW9udi51bmNhdWdodF9leGNlcHRpb24tLTsKICAgICAgfQogICAgICBpZiAoaW5mbykgaW5mby5yZXRocm93biA9IGZhbHNlOwogICAgICBFWENFUFRJT05TLmNhdWdodC5wdXNoKHB0cik7CiAgICAgIEVYQ0VQVElPTlMuYWRkUmVmKEVYQ0VQVElPTlMuZGVBZGp1c3QocHRyKSk7CiAgICAgIHJldHVybiBwdHIKICAgIH0KICAgIGZ1bmN0aW9uIF9fX2N4YV9mcmVlX2V4Y2VwdGlvbihwdHIpIHsKICAgICAgdHJ5IHsKICAgICAgICByZXR1cm4gX2ZyZWUocHRyKQogICAgICB9IGNhdGNoIChlKSB7fQogICAgfQogICAgZnVuY3Rpb24gX19fY3hhX2VuZF9jYXRjaCgpIHsKICAgICAgTW9kdWxlWydzZXRUaHJldyddKDApOwogICAgICB2YXIgcHRyID0gRVhDRVBUSU9OUy5jYXVnaHQucG9wKCk7CiAgICAgIGlmIChwdHIpIHsKICAgICAgICBFWENFUFRJT05TLmRlY1JlZihFWENFUFRJT05TLmRlQWRqdXN0KHB0cikpOwogICAgICAgIEVYQ0VQVElPTlMubGFzdCA9IDA7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIF9fX2N4YV9maW5kX21hdGNoaW5nX2NhdGNoXzIoKSB7CiAgICAgIHJldHVybiBfX19jeGFfZmluZF9tYXRjaGluZ19jYXRjaC5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICB9CiAgICBmdW5jdGlvbiBfX19jeGFfZmluZF9tYXRjaGluZ19jYXRjaF8zKCkgewogICAgICByZXR1cm4gX19fY3hhX2ZpbmRfbWF0Y2hpbmdfY2F0Y2guYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfQogICAgZnVuY3Rpb24gX19fY3hhX2ZpbmRfbWF0Y2hpbmdfY2F0Y2hfNCgpIHsKICAgICAgcmV0dXJuIF9fX2N4YV9maW5kX21hdGNoaW5nX2NhdGNoLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0KICAgIGZ1bmN0aW9uIF9fX3Jlc3VtZUV4Y2VwdGlvbihwdHIpIHsKICAgICAgaWYgKCFFWENFUFRJT05TLmxhc3QpIHsKICAgICAgICBFWENFUFRJT05TLmxhc3QgPSBwdHI7CiAgICAgIH0KICAgICAgdGhyb3cgcHRyCiAgICB9CiAgICBmdW5jdGlvbiBfX19jeGFfZmluZF9tYXRjaGluZ19jYXRjaCgpIHsKICAgICAgdmFyIHRocm93biA9IEVYQ0VQVElPTlMubGFzdDsKICAgICAgaWYgKCF0aHJvd24pIHsKICAgICAgICByZXR1cm4gKHNldFRlbXBSZXQwKDApLCAwKSB8IDAKICAgICAgfQogICAgICB2YXIgaW5mbyA9IEVYQ0VQVElPTlMuaW5mb3NbdGhyb3duXTsKICAgICAgdmFyIHRocm93bnR5cGUgPSBpbmZvLnR5cGU7CiAgICAgIGlmICghdGhyb3dudHlwZSkgewogICAgICAgIHJldHVybiAoc2V0VGVtcFJldDAoMCksIHRocm93bikgfCAwCiAgICAgIH0KICAgICAgdmFyIHR5cGVBcnJheSA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7CiAgICAgIE1vZHVsZVsnX19fY3hhX2lzX3BvaW50ZXJfdHlwZSddKHRocm93bnR5cGUpOwogICAgICBpZiAoIV9fX2N4YV9maW5kX21hdGNoaW5nX2NhdGNoLmJ1ZmZlcikgX19fY3hhX2ZpbmRfbWF0Y2hpbmdfY2F0Y2guYnVmZmVyID0gX21hbGxvYyg0KTsKICAgICAgSEVBUDMyW19fX2N4YV9maW5kX21hdGNoaW5nX2NhdGNoLmJ1ZmZlciA+PiAyXSA9IHRocm93bjsKICAgICAgdGhyb3duID0gX19fY3hhX2ZpbmRfbWF0Y2hpbmdfY2F0Y2guYnVmZmVyOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHR5cGVBcnJheS5sZW5ndGg7IGkrKykgewogICAgICAgIGlmICh0eXBlQXJyYXlbaV0gJiYgTW9kdWxlWydfX19jeGFfY2FuX2NhdGNoJ10odHlwZUFycmF5W2ldLCB0aHJvd250eXBlLCB0aHJvd24pKSB7CiAgICAgICAgICB0aHJvd24gPSBIRUFQMzJbdGhyb3duID4+IDJdOwogICAgICAgICAgaW5mby5hZGp1c3RlZCA9IHRocm93bjsKICAgICAgICAgIHJldHVybiAoc2V0VGVtcFJldDAodHlwZUFycmF5W2ldKSwgdGhyb3duKSB8IDAKICAgICAgICB9CiAgICAgIH0KICAgICAgdGhyb3duID0gSEVBUDMyW3Rocm93biA+PiAyXTsKICAgICAgcmV0dXJuIChzZXRUZW1wUmV0MCh0aHJvd250eXBlKSwgdGhyb3duKSB8IDAKICAgIH0KICAgIGZ1bmN0aW9uIF9fX2N4YV90aHJvdyhwdHIsIHR5cGUsIGRlc3RydWN0b3IpIHsKICAgICAgRVhDRVBUSU9OUy5pbmZvc1twdHJdID0gewogICAgICAgIHB0cjogcHRyLAogICAgICAgIGFkanVzdGVkOiBwdHIsCiAgICAgICAgdHlwZTogdHlwZSwKICAgICAgICBkZXN0cnVjdG9yOiBkZXN0cnVjdG9yLAogICAgICAgIHJlZmNvdW50OiAwLAogICAgICAgIGNhdWdodDogZmFsc2UsCiAgICAgICAgcmV0aHJvd246IGZhbHNlLAogICAgICB9OwogICAgICBFWENFUFRJT05TLmxhc3QgPSBwdHI7CiAgICAgIGlmICghKCd1bmNhdWdodF9leGNlcHRpb24nIGluIF9fWlN0MTh1bmNhdWdodF9leGNlcHRpb252KSkgewogICAgICAgIF9fWlN0MTh1bmNhdWdodF9leGNlcHRpb252LnVuY2F1Z2h0X2V4Y2VwdGlvbiA9IDE7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgX19aU3QxOHVuY2F1Z2h0X2V4Y2VwdGlvbnYudW5jYXVnaHRfZXhjZXB0aW9uKys7CiAgICAgIH0KICAgICAgdGhyb3cgcHRyCiAgICB9CiAgICBmdW5jdGlvbiBfX19sb2NrKCkge30KICAgIHZhciBFUlJOT19DT0RFUyA9IHsKICAgICAgRVBFUk06IDEsCiAgICAgIEVOT0VOVDogMiwKICAgICAgRVNSQ0g6IDMsCiAgICAgIEVJTlRSOiA0LAogICAgICBFSU86IDUsCiAgICAgIEVOWElPOiA2LAogICAgICBFMkJJRzogNywKICAgICAgRU5PRVhFQzogOCwKICAgICAgRUJBREY6IDksCiAgICAgIEVDSElMRDogMTAsCiAgICAgIEVBR0FJTjogMTEsCiAgICAgIEVXT1VMREJMT0NLOiAxMSwKICAgICAgRU5PTUVNOiAxMiwKICAgICAgRUFDQ0VTOiAxMywKICAgICAgRUZBVUxUOiAxNCwKICAgICAgRU5PVEJMSzogMTUsCiAgICAgIEVCVVNZOiAxNiwKICAgICAgRUVYSVNUOiAxNywKICAgICAgRVhERVY6IDE4LAogICAgICBFTk9ERVY6IDE5LAogICAgICBFTk9URElSOiAyMCwKICAgICAgRUlTRElSOiAyMSwKICAgICAgRUlOVkFMOiAyMiwKICAgICAgRU5GSUxFOiAyMywKICAgICAgRU1GSUxFOiAyNCwKICAgICAgRU5PVFRZOiAyNSwKICAgICAgRVRYVEJTWTogMjYsCiAgICAgIEVGQklHOiAyNywKICAgICAgRU5PU1BDOiAyOCwKICAgICAgRVNQSVBFOiAyOSwKICAgICAgRVJPRlM6IDMwLAogICAgICBFTUxJTks6IDMxLAogICAgICBFUElQRTogMzIsCiAgICAgIEVET006IDMzLAogICAgICBFUkFOR0U6IDM0LAogICAgICBFTk9NU0c6IDQyLAogICAgICBFSURSTTogNDMsCiAgICAgIEVDSFJORzogNDQsCiAgICAgIEVMMk5TWU5DOiA0NSwKICAgICAgRUwzSExUOiA0NiwKICAgICAgRUwzUlNUOiA0NywKICAgICAgRUxOUk5HOiA0OCwKICAgICAgRVVOQVRDSDogNDksCiAgICAgIEVOT0NTSTogNTAsCiAgICAgIEVMMkhMVDogNTEsCiAgICAgIEVERUFETEs6IDM1LAogICAgICBFTk9MQ0s6IDM3LAogICAgICBFQkFERTogNTIsCiAgICAgIEVCQURSOiA1MywKICAgICAgRVhGVUxMOiA1NCwKICAgICAgRU5PQU5POiA1NSwKICAgICAgRUJBRFJRQzogNTYsCiAgICAgIEVCQURTTFQ6IDU3LAogICAgICBFREVBRExPQ0s6IDM1LAogICAgICBFQkZPTlQ6IDU5LAogICAgICBFTk9TVFI6IDYwLAogICAgICBFTk9EQVRBOiA2MSwKICAgICAgRVRJTUU6IDYyLAogICAgICBFTk9TUjogNjMsCiAgICAgIEVOT05FVDogNjQsCiAgICAgIEVOT1BLRzogNjUsCiAgICAgIEVSRU1PVEU6IDY2LAogICAgICBFTk9MSU5LOiA2NywKICAgICAgRUFEVjogNjgsCiAgICAgIEVTUk1OVDogNjksCiAgICAgIEVDT01NOiA3MCwKICAgICAgRVBST1RPOiA3MSwKICAgICAgRU1VTFRJSE9QOiA3MiwKICAgICAgRURPVERPVDogNzMsCiAgICAgIEVCQURNU0c6IDc0LAogICAgICBFTk9UVU5JUTogNzYsCiAgICAgIEVCQURGRDogNzcsCiAgICAgIEVSRU1DSEc6IDc4LAogICAgICBFTElCQUNDOiA3OSwKICAgICAgRUxJQkJBRDogODAsCiAgICAgIEVMSUJTQ046IDgxLAogICAgICBFTElCTUFYOiA4MiwKICAgICAgRUxJQkVYRUM6IDgzLAogICAgICBFTk9TWVM6IDM4LAogICAgICBFTk9URU1QVFk6IDM5LAogICAgICBFTkFNRVRPT0xPTkc6IDM2LAogICAgICBFTE9PUDogNDAsCiAgICAgIEVPUE5PVFNVUFA6IDk1LAogICAgICBFUEZOT1NVUFBPUlQ6IDk2LAogICAgICBFQ09OTlJFU0VUOiAxMDQsCiAgICAgIEVOT0JVRlM6IDEwNSwKICAgICAgRUFGTk9TVVBQT1JUOiA5NywKICAgICAgRVBST1RPVFlQRTogOTEsCiAgICAgIEVOT1RTT0NLOiA4OCwKICAgICAgRU5PUFJPVE9PUFQ6IDkyLAogICAgICBFU0hVVERPV046IDEwOCwKICAgICAgRUNPTk5SRUZVU0VEOiAxMTEsCiAgICAgIEVBRERSSU5VU0U6IDk4LAogICAgICBFQ09OTkFCT1JURUQ6IDEwMywKICAgICAgRU5FVFVOUkVBQ0g6IDEwMSwKICAgICAgRU5FVERPV046IDEwMCwKICAgICAgRVRJTUVET1VUOiAxMTAsCiAgICAgIEVIT1NURE9XTjogMTEyLAogICAgICBFSE9TVFVOUkVBQ0g6IDExMywKICAgICAgRUlOUFJPR1JFU1M6IDExNSwKICAgICAgRUFMUkVBRFk6IDExNCwKICAgICAgRURFU1RBRERSUkVROiA4OSwKICAgICAgRU1TR1NJWkU6IDkwLAogICAgICBFUFJPVE9OT1NVUFBPUlQ6IDkzLAogICAgICBFU09DS1ROT1NVUFBPUlQ6IDk0LAogICAgICBFQUREUk5PVEFWQUlMOiA5OSwKICAgICAgRU5FVFJFU0VUOiAxMDIsCiAgICAgIEVJU0NPTk46IDEwNiwKICAgICAgRU5PVENPTk46IDEwNywKICAgICAgRVRPT01BTllSRUZTOiAxMDksCiAgICAgIEVVU0VSUzogODcsCiAgICAgIEVEUVVPVDogMTIyLAogICAgICBFU1RBTEU6IDExNiwKICAgICAgRU5PVFNVUDogOTUsCiAgICAgIEVOT01FRElVTTogMTIzLAogICAgICBFSUxTRVE6IDg0LAogICAgICBFT1ZFUkZMT1c6IDc1LAogICAgICBFQ0FOQ0VMRUQ6IDEyNSwKICAgICAgRU5PVFJFQ09WRVJBQkxFOiAxMzEsCiAgICAgIEVPV05FUkRFQUQ6IDEzMCwKICAgICAgRVNUUlBJUEU6IDg2LAogICAgfTsKICAgIGZ1bmN0aW9uIF9fX3NldEVyck5vKHZhbHVlKSB7CiAgICAgIGlmIChNb2R1bGVbJ19fX2Vycm5vX2xvY2F0aW9uJ10pIEhFQVAzMltNb2R1bGVbJ19fX2Vycm5vX2xvY2F0aW9uJ10oKSA+PiAyXSA9IHZhbHVlOwogICAgICByZXR1cm4gdmFsdWUKICAgIH0KICAgIGZ1bmN0aW9uIF9fX21hcF9maWxlKHBhdGhuYW1lLCBzaXplKSB7CiAgICAgIF9fX3NldEVyck5vKEVSUk5PX0NPREVTLkVQRVJNKTsKICAgICAgcmV0dXJuIC0xCiAgICB9CiAgICB2YXIgRVJSTk9fTUVTU0FHRVMgPSB7CiAgICAgIDA6ICdTdWNjZXNzJywKICAgICAgMTogJ05vdCBzdXBlci11c2VyJywKICAgICAgMjogJ05vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnknLAogICAgICAzOiAnTm8gc3VjaCBwcm9jZXNzJywKICAgICAgNDogJ0ludGVycnVwdGVkIHN5c3RlbSBjYWxsJywKICAgICAgNTogJ0kvTyBlcnJvcicsCiAgICAgIDY6ICdObyBzdWNoIGRldmljZSBvciBhZGRyZXNzJywKICAgICAgNzogJ0FyZyBsaXN0IHRvbyBsb25nJywKICAgICAgODogJ0V4ZWMgZm9ybWF0IGVycm9yJywKICAgICAgOTogJ0JhZCBmaWxlIG51bWJlcicsCiAgICAgIDEwOiAnTm8gY2hpbGRyZW4nLAogICAgICAxMTogJ05vIG1vcmUgcHJvY2Vzc2VzJywKICAgICAgMTI6ICdOb3QgZW5vdWdoIGNvcmUnLAogICAgICAxMzogJ1Blcm1pc3Npb24gZGVuaWVkJywKICAgICAgMTQ6ICdCYWQgYWRkcmVzcycsCiAgICAgIDE1OiAnQmxvY2sgZGV2aWNlIHJlcXVpcmVkJywKICAgICAgMTY6ICdNb3VudCBkZXZpY2UgYnVzeScsCiAgICAgIDE3OiAnRmlsZSBleGlzdHMnLAogICAgICAxODogJ0Nyb3NzLWRldmljZSBsaW5rJywKICAgICAgMTk6ICdObyBzdWNoIGRldmljZScsCiAgICAgIDIwOiAnTm90IGEgZGlyZWN0b3J5JywKICAgICAgMjE6ICdJcyBhIGRpcmVjdG9yeScsCiAgICAgIDIyOiAnSW52YWxpZCBhcmd1bWVudCcsCiAgICAgIDIzOiAnVG9vIG1hbnkgb3BlbiBmaWxlcyBpbiBzeXN0ZW0nLAogICAgICAyNDogJ1RvbyBtYW55IG9wZW4gZmlsZXMnLAogICAgICAyNTogJ05vdCBhIHR5cGV3cml0ZXInLAogICAgICAyNjogJ1RleHQgZmlsZSBidXN5JywKICAgICAgMjc6ICdGaWxlIHRvbyBsYXJnZScsCiAgICAgIDI4OiAnTm8gc3BhY2UgbGVmdCBvbiBkZXZpY2UnLAogICAgICAyOTogJ0lsbGVnYWwgc2VlaycsCiAgICAgIDMwOiAnUmVhZCBvbmx5IGZpbGUgc3lzdGVtJywKICAgICAgMzE6ICdUb28gbWFueSBsaW5rcycsCiAgICAgIDMyOiAnQnJva2VuIHBpcGUnLAogICAgICAzMzogJ01hdGggYXJnIG91dCBvZiBkb21haW4gb2YgZnVuYycsCiAgICAgIDM0OiAnTWF0aCByZXN1bHQgbm90IHJlcHJlc2VudGFibGUnLAogICAgICAzNTogJ0ZpbGUgbG9ja2luZyBkZWFkbG9jayBlcnJvcicsCiAgICAgIDM2OiAnRmlsZSBvciBwYXRoIG5hbWUgdG9vIGxvbmcnLAogICAgICAzNzogJ05vIHJlY29yZCBsb2NrcyBhdmFpbGFibGUnLAogICAgICAzODogJ0Z1bmN0aW9uIG5vdCBpbXBsZW1lbnRlZCcsCiAgICAgIDM5OiAnRGlyZWN0b3J5IG5vdCBlbXB0eScsCiAgICAgIDQwOiAnVG9vIG1hbnkgc3ltYm9saWMgbGlua3MnLAogICAgICA0MjogJ05vIG1lc3NhZ2Ugb2YgZGVzaXJlZCB0eXBlJywKICAgICAgNDM6ICdJZGVudGlmaWVyIHJlbW92ZWQnLAogICAgICA0NDogJ0NoYW5uZWwgbnVtYmVyIG91dCBvZiByYW5nZScsCiAgICAgIDQ1OiAnTGV2ZWwgMiBub3Qgc3luY2hyb25pemVkJywKICAgICAgNDY6ICdMZXZlbCAzIGhhbHRlZCcsCiAgICAgIDQ3OiAnTGV2ZWwgMyByZXNldCcsCiAgICAgIDQ4OiAnTGluayBudW1iZXIgb3V0IG9mIHJhbmdlJywKICAgICAgNDk6ICdQcm90b2NvbCBkcml2ZXIgbm90IGF0dGFjaGVkJywKICAgICAgNTA6ICdObyBDU0kgc3RydWN0dXJlIGF2YWlsYWJsZScsCiAgICAgIDUxOiAnTGV2ZWwgMiBoYWx0ZWQnLAogICAgICA1MjogJ0ludmFsaWQgZXhjaGFuZ2UnLAogICAgICA1MzogJ0ludmFsaWQgcmVxdWVzdCBkZXNjcmlwdG9yJywKICAgICAgNTQ6ICdFeGNoYW5nZSBmdWxsJywKICAgICAgNTU6ICdObyBhbm9kZScsCiAgICAgIDU2OiAnSW52YWxpZCByZXF1ZXN0IGNvZGUnLAogICAgICA1NzogJ0ludmFsaWQgc2xvdCcsCiAgICAgIDU5OiAnQmFkIGZvbnQgZmlsZSBmbXQnLAogICAgICA2MDogJ0RldmljZSBub3QgYSBzdHJlYW0nLAogICAgICA2MTogJ05vIGRhdGEgKGZvciBubyBkZWxheSBpbyknLAogICAgICA2MjogJ1RpbWVyIGV4cGlyZWQnLAogICAgICA2MzogJ091dCBvZiBzdHJlYW1zIHJlc291cmNlcycsCiAgICAgIDY0OiAnTWFjaGluZSBpcyBub3Qgb24gdGhlIG5ldHdvcmsnLAogICAgICA2NTogJ1BhY2thZ2Ugbm90IGluc3RhbGxlZCcsCiAgICAgIDY2OiAnVGhlIG9iamVjdCBpcyByZW1vdGUnLAogICAgICA2NzogJ1RoZSBsaW5rIGhhcyBiZWVuIHNldmVyZWQnLAogICAgICA2ODogJ0FkdmVydGlzZSBlcnJvcicsCiAgICAgIDY5OiAnU3Jtb3VudCBlcnJvcicsCiAgICAgIDcwOiAnQ29tbXVuaWNhdGlvbiBlcnJvciBvbiBzZW5kJywKICAgICAgNzE6ICdQcm90b2NvbCBlcnJvcicsCiAgICAgIDcyOiAnTXVsdGlob3AgYXR0ZW1wdGVkJywKICAgICAgNzM6ICdDcm9zcyBtb3VudCBwb2ludCAobm90IHJlYWxseSBlcnJvciknLAogICAgICA3NDogJ1RyeWluZyB0byByZWFkIHVucmVhZGFibGUgbWVzc2FnZScsCiAgICAgIDc1OiAnVmFsdWUgdG9vIGxhcmdlIGZvciBkZWZpbmVkIGRhdGEgdHlwZScsCiAgICAgIDc2OiAnR2l2ZW4gbG9nLiBuYW1lIG5vdCB1bmlxdWUnLAogICAgICA3NzogJ2YuZC4gaW52YWxpZCBmb3IgdGhpcyBvcGVyYXRpb24nLAogICAgICA3ODogJ1JlbW90ZSBhZGRyZXNzIGNoYW5nZWQnLAogICAgICA3OTogJ0NhbiAgIGFjY2VzcyBhIG5lZWRlZCBzaGFyZWQgbGliJywKICAgICAgODA6ICdBY2Nlc3NpbmcgYSBjb3JydXB0ZWQgc2hhcmVkIGxpYicsCiAgICAgIDgxOiAnLmxpYiBzZWN0aW9uIGluIGEub3V0IGNvcnJ1cHRlZCcsCiAgICAgIDgyOiAnQXR0ZW1wdGluZyB0byBsaW5rIGluIHRvbyBtYW55IGxpYnMnLAogICAgICA4MzogJ0F0dGVtcHRpbmcgdG8gZXhlYyBhIHNoYXJlZCBsaWJyYXJ5JywKICAgICAgODQ6ICdJbGxlZ2FsIGJ5dGUgc2VxdWVuY2UnLAogICAgICA4NjogJ1N0cmVhbXMgcGlwZSBlcnJvcicsCiAgICAgIDg3OiAnVG9vIG1hbnkgdXNlcnMnLAogICAgICA4ODogJ1NvY2tldCBvcGVyYXRpb24gb24gbm9uLXNvY2tldCcsCiAgICAgIDg5OiAnRGVzdGluYXRpb24gYWRkcmVzcyByZXF1aXJlZCcsCiAgICAgIDkwOiAnTWVzc2FnZSB0b28gbG9uZycsCiAgICAgIDkxOiAnUHJvdG9jb2wgd3JvbmcgdHlwZSBmb3Igc29ja2V0JywKICAgICAgOTI6ICdQcm90b2NvbCBub3QgYXZhaWxhYmxlJywKICAgICAgOTM6ICdVbmtub3duIHByb3RvY29sJywKICAgICAgOTQ6ICdTb2NrZXQgdHlwZSBub3Qgc3VwcG9ydGVkJywKICAgICAgOTU6ICdOb3Qgc3VwcG9ydGVkJywKICAgICAgOTY6ICdQcm90b2NvbCBmYW1pbHkgbm90IHN1cHBvcnRlZCcsCiAgICAgIDk3OiAnQWRkcmVzcyBmYW1pbHkgbm90IHN1cHBvcnRlZCBieSBwcm90b2NvbCBmYW1pbHknLAogICAgICA5ODogJ0FkZHJlc3MgYWxyZWFkeSBpbiB1c2UnLAogICAgICA5OTogJ0FkZHJlc3Mgbm90IGF2YWlsYWJsZScsCiAgICAgIDEwMDogJ05ldHdvcmsgaW50ZXJmYWNlIGlzIG5vdCBjb25maWd1cmVkJywKICAgICAgMTAxOiAnTmV0d29yayBpcyB1bnJlYWNoYWJsZScsCiAgICAgIDEwMjogJ0Nvbm5lY3Rpb24gcmVzZXQgYnkgbmV0d29yaycsCiAgICAgIDEwMzogJ0Nvbm5lY3Rpb24gYWJvcnRlZCcsCiAgICAgIDEwNDogJ0Nvbm5lY3Rpb24gcmVzZXQgYnkgcGVlcicsCiAgICAgIDEwNTogJ05vIGJ1ZmZlciBzcGFjZSBhdmFpbGFibGUnLAogICAgICAxMDY6ICdTb2NrZXQgaXMgYWxyZWFkeSBjb25uZWN0ZWQnLAogICAgICAxMDc6ICdTb2NrZXQgaXMgbm90IGNvbm5lY3RlZCcsCiAgICAgIDEwODogIkNhbid0IHNlbmQgYWZ0ZXIgc29ja2V0IHNodXRkb3duIiwKICAgICAgMTA5OiAnVG9vIG1hbnkgcmVmZXJlbmNlcycsCiAgICAgIDExMDogJ0Nvbm5lY3Rpb24gdGltZWQgb3V0JywKICAgICAgMTExOiAnQ29ubmVjdGlvbiByZWZ1c2VkJywKICAgICAgMTEyOiAnSG9zdCBpcyBkb3duJywKICAgICAgMTEzOiAnSG9zdCBpcyB1bnJlYWNoYWJsZScsCiAgICAgIDExNDogJ1NvY2tldCBhbHJlYWR5IGNvbm5lY3RlZCcsCiAgICAgIDExNTogJ0Nvbm5lY3Rpb24gYWxyZWFkeSBpbiBwcm9ncmVzcycsCiAgICAgIDExNjogJ1N0YWxlIGZpbGUgaGFuZGxlJywKICAgICAgMTIyOiAnUXVvdGEgZXhjZWVkZWQnLAogICAgICAxMjM6ICdObyBtZWRpdW0gKGluIHRhcGUgZHJpdmUpJywKICAgICAgMTI1OiAnT3BlcmF0aW9uIGNhbmNlbGVkJywKICAgICAgMTMwOiAnUHJldmlvdXMgb3duZXIgZGllZCcsCiAgICAgIDEzMTogJ1N0YXRlIG5vdCByZWNvdmVyYWJsZScsCiAgICB9OwogICAgdmFyIFBBVEggPSB7CiAgICAgIHNwbGl0UGF0aDogZnVuY3Rpb24gKGZpbGVuYW1lKSB7CiAgICAgICAgdmFyIHNwbGl0UGF0aFJlID0gL14oXC8/fCkoW1xzXFNdKj8pKCg/OlwuezEsMn18W15cL10rP3wpKFwuW14uXC9dKnwpKSg/OltcL10qKSQvOwogICAgICAgIHJldHVybiBzcGxpdFBhdGhSZS5leGVjKGZpbGVuYW1lKS5zbGljZSgxKQogICAgICB9LAogICAgICBub3JtYWxpemVBcnJheTogZnVuY3Rpb24gKHBhcnRzLCBhbGxvd0Fib3ZlUm9vdCkgewogICAgICAgIHZhciB1cCA9IDA7CiAgICAgICAgZm9yICh2YXIgaSA9IHBhcnRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgICAgICB2YXIgbGFzdCA9IHBhcnRzW2ldOwogICAgICAgICAgaWYgKGxhc3QgPT09ICcuJykgewogICAgICAgICAgICBwYXJ0cy5zcGxpY2UoaSwgMSk7CiAgICAgICAgICB9IGVsc2UgaWYgKGxhc3QgPT09ICcuLicpIHsKICAgICAgICAgICAgcGFydHMuc3BsaWNlKGksIDEpOwogICAgICAgICAgICB1cCsrOwogICAgICAgICAgfSBlbHNlIGlmICh1cCkgewogICAgICAgICAgICBwYXJ0cy5zcGxpY2UoaSwgMSk7CiAgICAgICAgICAgIHVwLS07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChhbGxvd0Fib3ZlUm9vdCkgewogICAgICAgICAgZm9yICg7IHVwOyB1cC0tKSB7CiAgICAgICAgICAgIHBhcnRzLnVuc2hpZnQoJy4uJyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBwYXJ0cwogICAgICB9LAogICAgICBub3JtYWxpemU6IGZ1bmN0aW9uIChwYXRoKSB7CiAgICAgICAgdmFyIGlzQWJzb2x1dGUgPSBwYXRoLmNoYXJBdCgwKSA9PT0gJy8nLAogICAgICAgICAgdHJhaWxpbmdTbGFzaCA9IHBhdGguc3Vic3RyKC0xKSA9PT0gJy8nOwogICAgICAgIHBhdGggPSBQQVRILm5vcm1hbGl6ZUFycmF5KAogICAgICAgICAgcGF0aC5zcGxpdCgnLycpLmZpbHRlcihmdW5jdGlvbiAocCkgewogICAgICAgICAgICByZXR1cm4gISFwCiAgICAgICAgICB9KSwKICAgICAgICAgICFpc0Fic29sdXRlCiAgICAgICAgKS5qb2luKCcvJyk7CiAgICAgICAgaWYgKCFwYXRoICYmICFpc0Fic29sdXRlKSB7CiAgICAgICAgICBwYXRoID0gJy4nOwogICAgICAgIH0KICAgICAgICBpZiAocGF0aCAmJiB0cmFpbGluZ1NsYXNoKSB7CiAgICAgICAgICBwYXRoICs9ICcvJzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIChpc0Fic29sdXRlID8gJy8nIDogJycpICsgcGF0aAogICAgICB9LAogICAgICBkaXJuYW1lOiBmdW5jdGlvbiAocGF0aCkgewogICAgICAgIHZhciByZXN1bHQgPSBQQVRILnNwbGl0UGF0aChwYXRoKSwKICAgICAgICAgIHJvb3QgPSByZXN1bHRbMF0sCiAgICAgICAgICBkaXIgPSByZXN1bHRbMV07CiAgICAgICAgaWYgKCFyb290ICYmICFkaXIpIHsKICAgICAgICAgIHJldHVybiAnLicKICAgICAgICB9CiAgICAgICAgaWYgKGRpcikgewogICAgICAgICAgZGlyID0gZGlyLnN1YnN0cigwLCBkaXIubGVuZ3RoIC0gMSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByb290ICsgZGlyCiAgICAgIH0sCiAgICAgIGJhc2VuYW1lOiBmdW5jdGlvbiAocGF0aCkgewogICAgICAgIGlmIChwYXRoID09PSAnLycpIHJldHVybiAnLycKICAgICAgICB2YXIgbGFzdFNsYXNoID0gcGF0aC5sYXN0SW5kZXhPZignLycpOwogICAgICAgIGlmIChsYXN0U2xhc2ggPT09IC0xKSByZXR1cm4gcGF0aAogICAgICAgIHJldHVybiBwYXRoLnN1YnN0cihsYXN0U2xhc2ggKyAxKQogICAgICB9LAogICAgICBleHRuYW1lOiBmdW5jdGlvbiAocGF0aCkgewogICAgICAgIHJldHVybiBQQVRILnNwbGl0UGF0aChwYXRoKVszXQogICAgICB9LAogICAgICBqb2luOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIHBhdGhzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKTsKICAgICAgICByZXR1cm4gUEFUSC5ub3JtYWxpemUocGF0aHMuam9pbignLycpKQogICAgICB9LAogICAgICBqb2luMjogZnVuY3Rpb24gKGwsIHIpIHsKICAgICAgICByZXR1cm4gUEFUSC5ub3JtYWxpemUobCArICcvJyArIHIpCiAgICAgIH0sCiAgICAgIHJlc29sdmU6IGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgcmVzb2x2ZWRQYXRoID0gJycsCiAgICAgICAgICByZXNvbHZlZEFic29sdXRlID0gZmFsc2U7CiAgICAgICAgZm9yICh2YXIgaSA9IGFyZ3VtZW50cy5sZW5ndGggLSAxOyBpID49IC0xICYmICFyZXNvbHZlZEFic29sdXRlOyBpLS0pIHsKICAgICAgICAgIHZhciBwYXRoID0gaSA+PSAwID8gYXJndW1lbnRzW2ldIDogRlMuY3dkKCk7CiAgICAgICAgICBpZiAodHlwZW9mIHBhdGggIT09ICdzdHJpbmcnKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50cyB0byBwYXRoLnJlc29sdmUgbXVzdCBiZSBzdHJpbmdzJykKICAgICAgICAgIH0gZWxzZSBpZiAoIXBhdGgpIHsKICAgICAgICAgICAgcmV0dXJuICcnCiAgICAgICAgICB9CiAgICAgICAgICByZXNvbHZlZFBhdGggPSBwYXRoICsgJy8nICsgcmVzb2x2ZWRQYXRoOwogICAgICAgICAgcmVzb2x2ZWRBYnNvbHV0ZSA9IHBhdGguY2hhckF0KDApID09PSAnLyc7CiAgICAgICAgfQogICAgICAgIHJlc29sdmVkUGF0aCA9IFBBVEgubm9ybWFsaXplQXJyYXkoCiAgICAgICAgICByZXNvbHZlZFBhdGguc3BsaXQoJy8nKS5maWx0ZXIoZnVuY3Rpb24gKHApIHsKICAgICAgICAgICAgcmV0dXJuICEhcAogICAgICAgICAgfSksCiAgICAgICAgICAhcmVzb2x2ZWRBYnNvbHV0ZQogICAgICAgICkuam9pbignLycpOwogICAgICAgIHJldHVybiAocmVzb2x2ZWRBYnNvbHV0ZSA/ICcvJyA6ICcnKSArIHJlc29sdmVkUGF0aCB8fCAnLicKICAgICAgfSwKICAgICAgcmVsYXRpdmU6IGZ1bmN0aW9uIChmcm9tLCB0bykgewogICAgICAgIGZyb20gPSBQQVRILnJlc29sdmUoZnJvbSkuc3Vic3RyKDEpOwogICAgICAgIHRvID0gUEFUSC5yZXNvbHZlKHRvKS5zdWJzdHIoMSk7CiAgICAgICAgZnVuY3Rpb24gdHJpbShhcnIpIHsKICAgICAgICAgIHZhciBzdGFydCA9IDA7CiAgICAgICAgICBmb3IgKDsgc3RhcnQgPCBhcnIubGVuZ3RoOyBzdGFydCsrKSB7CiAgICAgICAgICAgIGlmIChhcnJbc3RhcnRdICE9PSAnJykgYnJlYWsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBlbmQgPSBhcnIubGVuZ3RoIC0gMTsKICAgICAgICAgIGZvciAoOyBlbmQgPj0gMDsgZW5kLS0pIHsKICAgICAgICAgICAgaWYgKGFycltlbmRdICE9PSAnJykgYnJlYWsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChzdGFydCA+IGVuZCkgcmV0dXJuIFtdCiAgICAgICAgICByZXR1cm4gYXJyLnNsaWNlKHN0YXJ0LCBlbmQgLSBzdGFydCArIDEpCiAgICAgICAgfQogICAgICAgIHZhciBmcm9tUGFydHMgPSB0cmltKGZyb20uc3BsaXQoJy8nKSk7CiAgICAgICAgdmFyIHRvUGFydHMgPSB0cmltKHRvLnNwbGl0KCcvJykpOwogICAgICAgIHZhciBsZW5ndGggPSBNYXRoLm1pbihmcm9tUGFydHMubGVuZ3RoLCB0b1BhcnRzLmxlbmd0aCk7CiAgICAgICAgdmFyIHNhbWVQYXJ0c0xlbmd0aCA9IGxlbmd0aDsKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBpZiAoZnJvbVBhcnRzW2ldICE9PSB0b1BhcnRzW2ldKSB7CiAgICAgICAgICAgIHNhbWVQYXJ0c0xlbmd0aCA9IGk7CiAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHZhciBvdXRwdXRQYXJ0cyA9IFtdOwogICAgICAgIGZvciAodmFyIGkgPSBzYW1lUGFydHNMZW5ndGg7IGkgPCBmcm9tUGFydHMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIG91dHB1dFBhcnRzLnB1c2goJy4uJyk7CiAgICAgICAgfQogICAgICAgIG91dHB1dFBhcnRzID0gb3V0cHV0UGFydHMuY29uY2F0KHRvUGFydHMuc2xpY2Uoc2FtZVBhcnRzTGVuZ3RoKSk7CiAgICAgICAgcmV0dXJuIG91dHB1dFBhcnRzLmpvaW4oJy8nKQogICAgICB9LAogICAgfTsKICAgIHZhciBUVFkgPSB7CiAgICAgIHR0eXM6IFtdLAogICAgICBpbml0OiBmdW5jdGlvbiAoKSB7fSwKICAgICAgc2h1dGRvd246IGZ1bmN0aW9uICgpIHt9LAogICAgICByZWdpc3RlcjogZnVuY3Rpb24gKGRldiwgb3BzKSB7CiAgICAgICAgVFRZLnR0eXNbZGV2XSA9IHsgaW5wdXQ6IFtdLCBvdXRwdXQ6IFtdLCBvcHM6IG9wcyB9OwogICAgICAgIEZTLnJlZ2lzdGVyRGV2aWNlKGRldiwgVFRZLnN0cmVhbV9vcHMpOwogICAgICB9LAogICAgICBzdHJlYW1fb3BzOiB7CiAgICAgICAgb3BlbjogZnVuY3Rpb24gKHN0cmVhbSkgewogICAgICAgICAgdmFyIHR0eSA9IFRUWS50dHlzW3N0cmVhbS5ub2RlLnJkZXZdOwogICAgICAgICAgaWYgKCF0dHkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRU5PREVWKQogICAgICAgICAgfQogICAgICAgICAgc3RyZWFtLnR0eSA9IHR0eTsKICAgICAgICAgIHN0cmVhbS5zZWVrYWJsZSA9IGZhbHNlOwogICAgICAgIH0sCiAgICAgICAgY2xvc2U6IGZ1bmN0aW9uIChzdHJlYW0pIHsKICAgICAgICAgIHN0cmVhbS50dHkub3BzLmZsdXNoKHN0cmVhbS50dHkpOwogICAgICAgIH0sCiAgICAgICAgZmx1c2g6IGZ1bmN0aW9uIChzdHJlYW0pIHsKICAgICAgICAgIHN0cmVhbS50dHkub3BzLmZsdXNoKHN0cmVhbS50dHkpOwogICAgICAgIH0sCiAgICAgICAgcmVhZDogZnVuY3Rpb24gKHN0cmVhbSwgYnVmZmVyLCBvZmZzZXQsIGxlbmd0aCwgcG9zKSB7CiAgICAgICAgICBpZiAoIXN0cmVhbS50dHkgfHwgIXN0cmVhbS50dHkub3BzLmdldF9jaGFyKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVOWElPKQogICAgICAgICAgfQogICAgICAgICAgdmFyIGJ5dGVzUmVhZCA9IDA7CiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHZhciByZXN1bHQ7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgcmVzdWx0ID0gc3RyZWFtLnR0eS5vcHMuZ2V0X2NoYXIoc3RyZWFtLnR0eSk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FSU8pCiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJlc3VsdCA9PT0gdW5kZWZpbmVkICYmIGJ5dGVzUmVhZCA9PT0gMCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVBR0FJTikKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsIHx8IHJlc3VsdCA9PT0gdW5kZWZpbmVkKSBicmVhawogICAgICAgICAgICBieXRlc1JlYWQrKzsKICAgICAgICAgICAgYnVmZmVyW29mZnNldCArIGldID0gcmVzdWx0OwogICAgICAgICAgfQogICAgICAgICAgaWYgKGJ5dGVzUmVhZCkgewogICAgICAgICAgICBzdHJlYW0ubm9kZS50aW1lc3RhbXAgPSBEYXRlLm5vdygpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGJ5dGVzUmVhZAogICAgICAgIH0sCiAgICAgICAgd3JpdGU6IGZ1bmN0aW9uIChzdHJlYW0sIGJ1ZmZlciwgb2Zmc2V0LCBsZW5ndGgsIHBvcykgewogICAgICAgICAgaWYgKCFzdHJlYW0udHR5IHx8ICFzdHJlYW0udHR5Lm9wcy5wdXRfY2hhcikgewogICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTlhJTykKICAgICAgICAgIH0KICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICBzdHJlYW0udHR5Lm9wcy5wdXRfY2hhcihzdHJlYW0udHR5LCBidWZmZXJbb2Zmc2V0ICsgaV0pOwogICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUlPKQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobGVuZ3RoKSB7CiAgICAgICAgICAgIHN0cmVhbS5ub2RlLnRpbWVzdGFtcCA9IERhdGUubm93KCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gaQogICAgICAgIH0sCiAgICAgIH0sCiAgICAgIGRlZmF1bHRfdHR5X29wczogewogICAgICAgIGdldF9jaGFyOiBmdW5jdGlvbiAodHR5KSB7CiAgICAgICAgICBpZiAoIXR0eS5pbnB1dC5sZW5ndGgpIHsKICAgICAgICAgICAgdmFyIHJlc3VsdCA9IG51bGw7CiAgICAgICAgICAgIGlmIChFTlZJUk9OTUVOVF9JU19OT0RFKSB7CiAgICAgICAgICAgICAgdmFyIEJVRlNJWkUgPSAyNTY7CiAgICAgICAgICAgICAgdmFyIGJ1ZiA9IG5ldyBCdWZmZXIoQlVGU0laRSk7CiAgICAgICAgICAgICAgdmFyIGJ5dGVzUmVhZCA9IDA7CiAgICAgICAgICAgICAgdmFyIGlzUG9zaXhQbGF0Zm9ybSA9IHByb2Nlc3MucGxhdGZvcm0gIT0gJ3dpbjMyJzsKICAgICAgICAgICAgICB2YXIgZmQgPSBwcm9jZXNzLnN0ZGluLmZkOwogICAgICAgICAgICAgIGlmIChpc1Bvc2l4UGxhdGZvcm0pIHsKICAgICAgICAgICAgICAgIHZhciB1c2luZ0RldmljZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgZmQgPSBmcy5vcGVuU3luYygnL2Rldi9zdGRpbicsICdyJyk7CiAgICAgICAgICAgICAgICAgIHVzaW5nRGV2aWNlID0gdHJ1ZTsKICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICBieXRlc1JlYWQgPSBmcy5yZWFkU3luYyhmZCwgYnVmLCAwLCBCVUZTSVpFLCBudWxsKTsKICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICBpZiAoZS50b1N0cmluZygpLmluZGV4T2YoJ0VPRicpICE9IC0xKSBieXRlc1JlYWQgPSAwOwogICAgICAgICAgICAgICAgZWxzZSB0aHJvdyBlCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmICh1c2luZ0RldmljZSkgewogICAgICAgICAgICAgICAgZnMuY2xvc2VTeW5jKGZkKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKGJ5dGVzUmVhZCA+IDApIHsKICAgICAgICAgICAgICAgIHJlc3VsdCA9IGJ1Zi5zbGljZSgwLCBieXRlc1JlYWQpLnRvU3RyaW5nKCd1dGYtOCcpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICByZXN1bHQgPSBudWxsOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ICE9ICd1bmRlZmluZWQnICYmIHR5cGVvZiB3aW5kb3cucHJvbXB0ID09ICdmdW5jdGlvbicpIHsKICAgICAgICAgICAgICByZXN1bHQgPSB3aW5kb3cucHJvbXB0KCdJbnB1dDogJyk7CiAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPT0gbnVsbCkgewogICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdcbic7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiByZWFkbGluZSA9PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgICAgICAgcmVzdWx0ID0gcmVhZGxpbmUoKTsKICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ1xuJzsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCFyZXN1bHQpIHsKICAgICAgICAgICAgICByZXR1cm4gbnVsbAogICAgICAgICAgICB9CiAgICAgICAgICAgIHR0eS5pbnB1dCA9IGludEFycmF5RnJvbVN0cmluZyhyZXN1bHQsIHRydWUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHR0eS5pbnB1dC5zaGlmdCgpCiAgICAgICAgfSwKICAgICAgICBwdXRfY2hhcjogZnVuY3Rpb24gKHR0eSwgdmFsKSB7CiAgICAgICAgICBpZiAodmFsID09PSBudWxsIHx8IHZhbCA9PT0gMTApIHsKICAgICAgICAgICAgTW9kdWxlWydwcmludCddKFVURjhBcnJheVRvU3RyaW5nKHR0eS5vdXRwdXQsIDApKTsKICAgICAgICAgICAgdHR5Lm91dHB1dCA9IFtdOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKHZhbCAhPSAwKSB0dHkub3V0cHV0LnB1c2godmFsKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIGZsdXNoOiBmdW5jdGlvbiAodHR5KSB7CiAgICAgICAgICBpZiAodHR5Lm91dHB1dCAmJiB0dHkub3V0cHV0Lmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgTW9kdWxlWydwcmludCddKFVURjhBcnJheVRvU3RyaW5nKHR0eS5vdXRwdXQsIDApKTsKICAgICAgICAgICAgdHR5Lm91dHB1dCA9IFtdOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgIH0sCiAgICAgIGRlZmF1bHRfdHR5MV9vcHM6IHsKICAgICAgICBwdXRfY2hhcjogZnVuY3Rpb24gKHR0eSwgdmFsKSB7CiAgICAgICAgICBpZiAodmFsID09PSBudWxsIHx8IHZhbCA9PT0gMTApIHsKICAgICAgICAgICAgTW9kdWxlWydwcmludEVyciddKFVURjhBcnJheVRvU3RyaW5nKHR0eS5vdXRwdXQsIDApKTsKICAgICAgICAgICAgdHR5Lm91dHB1dCA9IFtdOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKHZhbCAhPSAwKSB0dHkub3V0cHV0LnB1c2godmFsKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIGZsdXNoOiBmdW5jdGlvbiAodHR5KSB7CiAgICAgICAgICBpZiAodHR5Lm91dHB1dCAmJiB0dHkub3V0cHV0Lmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgTW9kdWxlWydwcmludEVyciddKFVURjhBcnJheVRvU3RyaW5nKHR0eS5vdXRwdXQsIDApKTsKICAgICAgICAgICAgdHR5Lm91dHB1dCA9IFtdOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgIH0sCiAgICB9OwogICAgdmFyIE1FTUZTID0gewogICAgICBvcHNfdGFibGU6IG51bGwsCiAgICAgIG1vdW50OiBmdW5jdGlvbiAobW91bnQpIHsKICAgICAgICByZXR1cm4gTUVNRlMuY3JlYXRlTm9kZShudWxsLCAnLycsIDE2Mzg0IHwgNTExLCAwKQogICAgICB9LAogICAgICBjcmVhdGVOb2RlOiBmdW5jdGlvbiAocGFyZW50LCBuYW1lLCBtb2RlLCBkZXYpIHsKICAgICAgICBpZiAoRlMuaXNCbGtkZXYobW9kZSkgfHwgRlMuaXNGSUZPKG1vZGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FUEVSTSkKICAgICAgICB9CiAgICAgICAgaWYgKCFNRU1GUy5vcHNfdGFibGUpIHsKICAgICAgICAgIE1FTUZTLm9wc190YWJsZSA9IHsKICAgICAgICAgICAgZGlyOiB7CiAgICAgICAgICAgICAgbm9kZTogewogICAgICAgICAgICAgICAgZ2V0YXR0cjogTUVNRlMubm9kZV9vcHMuZ2V0YXR0ciwKICAgICAgICAgICAgICAgIHNldGF0dHI6IE1FTUZTLm5vZGVfb3BzLnNldGF0dHIsCiAgICAgICAgICAgICAgICBsb29rdXA6IE1FTUZTLm5vZGVfb3BzLmxvb2t1cCwKICAgICAgICAgICAgICAgIG1rbm9kOiBNRU1GUy5ub2RlX29wcy5ta25vZCwKICAgICAgICAgICAgICAgIHJlbmFtZTogTUVNRlMubm9kZV9vcHMucmVuYW1lLAogICAgICAgICAgICAgICAgdW5saW5rOiBNRU1GUy5ub2RlX29wcy51bmxpbmssCiAgICAgICAgICAgICAgICBybWRpcjogTUVNRlMubm9kZV9vcHMucm1kaXIsCiAgICAgICAgICAgICAgICByZWFkZGlyOiBNRU1GUy5ub2RlX29wcy5yZWFkZGlyLAogICAgICAgICAgICAgICAgc3ltbGluazogTUVNRlMubm9kZV9vcHMuc3ltbGluaywKICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgIHN0cmVhbTogeyBsbHNlZWs6IE1FTUZTLnN0cmVhbV9vcHMubGxzZWVrIH0sCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGZpbGU6IHsKICAgICAgICAgICAgICBub2RlOiB7IGdldGF0dHI6IE1FTUZTLm5vZGVfb3BzLmdldGF0dHIsIHNldGF0dHI6IE1FTUZTLm5vZGVfb3BzLnNldGF0dHIgfSwKICAgICAgICAgICAgICBzdHJlYW06IHsKICAgICAgICAgICAgICAgIGxsc2VlazogTUVNRlMuc3RyZWFtX29wcy5sbHNlZWssCiAgICAgICAgICAgICAgICByZWFkOiBNRU1GUy5zdHJlYW1fb3BzLnJlYWQsCiAgICAgICAgICAgICAgICB3cml0ZTogTUVNRlMuc3RyZWFtX29wcy53cml0ZSwKICAgICAgICAgICAgICAgIGFsbG9jYXRlOiBNRU1GUy5zdHJlYW1fb3BzLmFsbG9jYXRlLAogICAgICAgICAgICAgICAgbW1hcDogTUVNRlMuc3RyZWFtX29wcy5tbWFwLAogICAgICAgICAgICAgICAgbXN5bmM6IE1FTUZTLnN0cmVhbV9vcHMubXN5bmMsCiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgfSwKICAgICAgICAgICAgbGluazogewogICAgICAgICAgICAgIG5vZGU6IHsKICAgICAgICAgICAgICAgIGdldGF0dHI6IE1FTUZTLm5vZGVfb3BzLmdldGF0dHIsCiAgICAgICAgICAgICAgICBzZXRhdHRyOiBNRU1GUy5ub2RlX29wcy5zZXRhdHRyLAogICAgICAgICAgICAgICAgcmVhZGxpbms6IE1FTUZTLm5vZGVfb3BzLnJlYWRsaW5rLAogICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgc3RyZWFtOiB7fSwKICAgICAgICAgICAgfSwKICAgICAgICAgICAgY2hyZGV2OiB7CiAgICAgICAgICAgICAgbm9kZTogeyBnZXRhdHRyOiBNRU1GUy5ub2RlX29wcy5nZXRhdHRyLCBzZXRhdHRyOiBNRU1GUy5ub2RlX29wcy5zZXRhdHRyIH0sCiAgICAgICAgICAgICAgc3RyZWFtOiBGUy5jaHJkZXZfc3RyZWFtX29wcywKICAgICAgICAgICAgfSwKICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIHZhciBub2RlID0gRlMuY3JlYXRlTm9kZShwYXJlbnQsIG5hbWUsIG1vZGUsIGRldik7CiAgICAgICAgaWYgKEZTLmlzRGlyKG5vZGUubW9kZSkpIHsKICAgICAgICAgIG5vZGUubm9kZV9vcHMgPSBNRU1GUy5vcHNfdGFibGUuZGlyLm5vZGU7CiAgICAgICAgICBub2RlLnN0cmVhbV9vcHMgPSBNRU1GUy5vcHNfdGFibGUuZGlyLnN0cmVhbTsKICAgICAgICAgIG5vZGUuY29udGVudHMgPSB7fTsKICAgICAgICB9IGVsc2UgaWYgKEZTLmlzRmlsZShub2RlLm1vZGUpKSB7CiAgICAgICAgICBub2RlLm5vZGVfb3BzID0gTUVNRlMub3BzX3RhYmxlLmZpbGUubm9kZTsKICAgICAgICAgIG5vZGUuc3RyZWFtX29wcyA9IE1FTUZTLm9wc190YWJsZS5maWxlLnN0cmVhbTsKICAgICAgICAgIG5vZGUudXNlZEJ5dGVzID0gMDsKICAgICAgICAgIG5vZGUuY29udGVudHMgPSBudWxsOwogICAgICAgIH0gZWxzZSBpZiAoRlMuaXNMaW5rKG5vZGUubW9kZSkpIHsKICAgICAgICAgIG5vZGUubm9kZV9vcHMgPSBNRU1GUy5vcHNfdGFibGUubGluay5ub2RlOwogICAgICAgICAgbm9kZS5zdHJlYW1fb3BzID0gTUVNRlMub3BzX3RhYmxlLmxpbmsuc3RyZWFtOwogICAgICAgIH0gZWxzZSBpZiAoRlMuaXNDaHJkZXYobm9kZS5tb2RlKSkgewogICAgICAgICAgbm9kZS5ub2RlX29wcyA9IE1FTUZTLm9wc190YWJsZS5jaHJkZXYubm9kZTsKICAgICAgICAgIG5vZGUuc3RyZWFtX29wcyA9IE1FTUZTLm9wc190YWJsZS5jaHJkZXYuc3RyZWFtOwogICAgICAgIH0KICAgICAgICBub2RlLnRpbWVzdGFtcCA9IERhdGUubm93KCk7CiAgICAgICAgaWYgKHBhcmVudCkgewogICAgICAgICAgcGFyZW50LmNvbnRlbnRzW25hbWVdID0gbm9kZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5vZGUKICAgICAgfSwKICAgICAgZ2V0RmlsZURhdGFBc1JlZ3VsYXJBcnJheTogZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICBpZiAobm9kZS5jb250ZW50cyAmJiBub2RlLmNvbnRlbnRzLnN1YmFycmF5KSB7CiAgICAgICAgICB2YXIgYXJyID0gW107CiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGUudXNlZEJ5dGVzOyArK2kpIGFyci5wdXNoKG5vZGUuY29udGVudHNbaV0pOwogICAgICAgICAgcmV0dXJuIGFycgogICAgICAgIH0KICAgICAgICByZXR1cm4gbm9kZS5jb250ZW50cwogICAgICB9LAogICAgICBnZXRGaWxlRGF0YUFzVHlwZWRBcnJheTogZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICBpZiAoIW5vZGUuY29udGVudHMpIHJldHVybiBuZXcgVWludDhBcnJheSgpCiAgICAgICAgaWYgKG5vZGUuY29udGVudHMuc3ViYXJyYXkpIHJldHVybiBub2RlLmNvbnRlbnRzLnN1YmFycmF5KDAsIG5vZGUudXNlZEJ5dGVzKQogICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShub2RlLmNvbnRlbnRzKQogICAgICB9LAogICAgICBleHBhbmRGaWxlU3RvcmFnZTogZnVuY3Rpb24gKG5vZGUsIG5ld0NhcGFjaXR5KSB7CiAgICAgICAgaWYgKG5vZGUuY29udGVudHMgJiYgbm9kZS5jb250ZW50cy5zdWJhcnJheSAmJiBuZXdDYXBhY2l0eSA+IG5vZGUuY29udGVudHMubGVuZ3RoKSB7CiAgICAgICAgICBub2RlLmNvbnRlbnRzID0gTUVNRlMuZ2V0RmlsZURhdGFBc1JlZ3VsYXJBcnJheShub2RlKTsKICAgICAgICAgIG5vZGUudXNlZEJ5dGVzID0gbm9kZS5jb250ZW50cy5sZW5ndGg7CiAgICAgICAgfQogICAgICAgIGlmICghbm9kZS5jb250ZW50cyB8fCBub2RlLmNvbnRlbnRzLnN1YmFycmF5KSB7CiAgICAgICAgICB2YXIgcHJldkNhcGFjaXR5ID0gbm9kZS5jb250ZW50cyA/IG5vZGUuY29udGVudHMubGVuZ3RoIDogMDsKICAgICAgICAgIGlmIChwcmV2Q2FwYWNpdHkgPj0gbmV3Q2FwYWNpdHkpIHJldHVybgogICAgICAgICAgdmFyIENBUEFDSVRZX0RPVUJMSU5HX01BWCA9IDEwMjQgKiAxMDI0OwogICAgICAgICAgbmV3Q2FwYWNpdHkgPSBNYXRoLm1heChuZXdDYXBhY2l0eSwgKHByZXZDYXBhY2l0eSAqIChwcmV2Q2FwYWNpdHkgPCBDQVBBQ0lUWV9ET1VCTElOR19NQVggPyAyIDogMS4xMjUpKSB8IDApOwogICAgICAgICAgaWYgKHByZXZDYXBhY2l0eSAhPSAwKSBuZXdDYXBhY2l0eSA9IE1hdGgubWF4KG5ld0NhcGFjaXR5LCAyNTYpOwogICAgICAgICAgdmFyIG9sZENvbnRlbnRzID0gbm9kZS5jb250ZW50czsKICAgICAgICAgIG5vZGUuY29udGVudHMgPSBuZXcgVWludDhBcnJheShuZXdDYXBhY2l0eSk7CiAgICAgICAgICBpZiAobm9kZS51c2VkQnl0ZXMgPiAwKSBub2RlLmNvbnRlbnRzLnNldChvbGRDb250ZW50cy5zdWJhcnJheSgwLCBub2RlLnVzZWRCeXRlcyksIDApOwogICAgICAgICAgcmV0dXJuCiAgICAgICAgfQogICAgICAgIGlmICghbm9kZS5jb250ZW50cyAmJiBuZXdDYXBhY2l0eSA+IDApIG5vZGUuY29udGVudHMgPSBbXTsKICAgICAgICB3aGlsZSAobm9kZS5jb250ZW50cy5sZW5ndGggPCBuZXdDYXBhY2l0eSkgbm9kZS5jb250ZW50cy5wdXNoKDApOwogICAgICB9LAogICAgICByZXNpemVGaWxlU3RvcmFnZTogZnVuY3Rpb24gKG5vZGUsIG5ld1NpemUpIHsKICAgICAgICBpZiAobm9kZS51c2VkQnl0ZXMgPT0gbmV3U2l6ZSkgcmV0dXJuCiAgICAgICAgaWYgKG5ld1NpemUgPT0gMCkgewogICAgICAgICAgbm9kZS5jb250ZW50cyA9IG51bGw7CiAgICAgICAgICBub2RlLnVzZWRCeXRlcyA9IDA7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgaWYgKCFub2RlLmNvbnRlbnRzIHx8IG5vZGUuY29udGVudHMuc3ViYXJyYXkpIHsKICAgICAgICAgIHZhciBvbGRDb250ZW50cyA9IG5vZGUuY29udGVudHM7CiAgICAgICAgICBub2RlLmNvbnRlbnRzID0gbmV3IFVpbnQ4QXJyYXkobmV3IEFycmF5QnVmZmVyKG5ld1NpemUpKTsKICAgICAgICAgIGlmIChvbGRDb250ZW50cykgewogICAgICAgICAgICBub2RlLmNvbnRlbnRzLnNldChvbGRDb250ZW50cy5zdWJhcnJheSgwLCBNYXRoLm1pbihuZXdTaXplLCBub2RlLnVzZWRCeXRlcykpKTsKICAgICAgICAgIH0KICAgICAgICAgIG5vZGUudXNlZEJ5dGVzID0gbmV3U2l6ZTsKICAgICAgICAgIHJldHVybgogICAgICAgIH0KICAgICAgICBpZiAoIW5vZGUuY29udGVudHMpIG5vZGUuY29udGVudHMgPSBbXTsKICAgICAgICBpZiAobm9kZS5jb250ZW50cy5sZW5ndGggPiBuZXdTaXplKSBub2RlLmNvbnRlbnRzLmxlbmd0aCA9IG5ld1NpemU7CiAgICAgICAgZWxzZSB3aGlsZSAobm9kZS5jb250ZW50cy5sZW5ndGggPCBuZXdTaXplKSBub2RlLmNvbnRlbnRzLnB1c2goMCk7CiAgICAgICAgbm9kZS51c2VkQnl0ZXMgPSBuZXdTaXplOwogICAgICB9LAogICAgICBub2RlX29wczogewogICAgICAgIGdldGF0dHI6IGZ1bmN0aW9uIChub2RlKSB7CiAgICAgICAgICB2YXIgYXR0ciA9IHt9OwogICAgICAgICAgYXR0ci5kZXYgPSBGUy5pc0NocmRldihub2RlLm1vZGUpID8gbm9kZS5pZCA6IDE7CiAgICAgICAgICBhdHRyLmlubyA9IG5vZGUuaWQ7CiAgICAgICAgICBhdHRyLm1vZGUgPSBub2RlLm1vZGU7CiAgICAgICAgICBhdHRyLm5saW5rID0gMTsKICAgICAgICAgIGF0dHIudWlkID0gMDsKICAgICAgICAgIGF0dHIuZ2lkID0gMDsKICAgICAgICAgIGF0dHIucmRldiA9IG5vZGUucmRldjsKICAgICAgICAgIGlmIChGUy5pc0Rpcihub2RlLm1vZGUpKSB7CiAgICAgICAgICAgIGF0dHIuc2l6ZSA9IDQwOTY7CiAgICAgICAgICB9IGVsc2UgaWYgKEZTLmlzRmlsZShub2RlLm1vZGUpKSB7CiAgICAgICAgICAgIGF0dHIuc2l6ZSA9IG5vZGUudXNlZEJ5dGVzOwogICAgICAgICAgfSBlbHNlIGlmIChGUy5pc0xpbmsobm9kZS5tb2RlKSkgewogICAgICAgICAgICBhdHRyLnNpemUgPSBub2RlLmxpbmsubGVuZ3RoOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYXR0ci5zaXplID0gMDsKICAgICAgICAgIH0KICAgICAgICAgIGF0dHIuYXRpbWUgPSBuZXcgRGF0ZShub2RlLnRpbWVzdGFtcCk7CiAgICAgICAgICBhdHRyLm10aW1lID0gbmV3IERhdGUobm9kZS50aW1lc3RhbXApOwogICAgICAgICAgYXR0ci5jdGltZSA9IG5ldyBEYXRlKG5vZGUudGltZXN0YW1wKTsKICAgICAgICAgIGF0dHIuYmxrc2l6ZSA9IDQwOTY7CiAgICAgICAgICBhdHRyLmJsb2NrcyA9IE1hdGguY2VpbChhdHRyLnNpemUgLyBhdHRyLmJsa3NpemUpOwogICAgICAgICAgcmV0dXJuIGF0dHIKICAgICAgICB9LAogICAgICAgIHNldGF0dHI6IGZ1bmN0aW9uIChub2RlLCBhdHRyKSB7CiAgICAgICAgICBpZiAoYXR0ci5tb2RlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgbm9kZS5tb2RlID0gYXR0ci5tb2RlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGF0dHIudGltZXN0YW1wICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgbm9kZS50aW1lc3RhbXAgPSBhdHRyLnRpbWVzdGFtcDsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChhdHRyLnNpemUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBNRU1GUy5yZXNpemVGaWxlU3RvcmFnZShub2RlLCBhdHRyLnNpemUpOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgbG9va3VwOiBmdW5jdGlvbiAocGFyZW50LCBuYW1lKSB7CiAgICAgICAgICB0aHJvdyBGUy5nZW5lcmljRXJyb3JzW0VSUk5PX0NPREVTLkVOT0VOVF0KICAgICAgICB9LAogICAgICAgIG1rbm9kOiBmdW5jdGlvbiAocGFyZW50LCBuYW1lLCBtb2RlLCBkZXYpIHsKICAgICAgICAgIHJldHVybiBNRU1GUy5jcmVhdGVOb2RlKHBhcmVudCwgbmFtZSwgbW9kZSwgZGV2KQogICAgICAgIH0sCiAgICAgICAgcmVuYW1lOiBmdW5jdGlvbiAob2xkX25vZGUsIG5ld19kaXIsIG5ld19uYW1lKSB7CiAgICAgICAgICBpZiAoRlMuaXNEaXIob2xkX25vZGUubW9kZSkpIHsKICAgICAgICAgICAgdmFyIG5ld19ub2RlOwogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIG5ld19ub2RlID0gRlMubG9va3VwTm9kZShuZXdfZGlyLCBuZXdfbmFtZSk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9CiAgICAgICAgICAgIGlmIChuZXdfbm9kZSkgewogICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gbmV3X25vZGUuY29udGVudHMpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVOT1RFTVBUWSkKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGRlbGV0ZSBvbGRfbm9kZS5wYXJlbnQuY29udGVudHNbb2xkX25vZGUubmFtZV07CiAgICAgICAgICBvbGRfbm9kZS5uYW1lID0gbmV3X25hbWU7CiAgICAgICAgICBuZXdfZGlyLmNvbnRlbnRzW25ld19uYW1lXSA9IG9sZF9ub2RlOwogICAgICAgICAgb2xkX25vZGUucGFyZW50ID0gbmV3X2RpcjsKICAgICAgICB9LAogICAgICAgIHVubGluazogZnVuY3Rpb24gKHBhcmVudCwgbmFtZSkgewogICAgICAgICAgZGVsZXRlIHBhcmVudC5jb250ZW50c1tuYW1lXTsKICAgICAgICB9LAogICAgICAgIHJtZGlyOiBmdW5jdGlvbiAocGFyZW50LCBuYW1lKSB7CiAgICAgICAgICB2YXIgbm9kZSA9IEZTLmxvb2t1cE5vZGUocGFyZW50LCBuYW1lKTsKICAgICAgICAgIGZvciAodmFyIGkgaW4gbm9kZS5jb250ZW50cykgewogICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTk9URU1QVFkpCiAgICAgICAgICB9CiAgICAgICAgICBkZWxldGUgcGFyZW50LmNvbnRlbnRzW25hbWVdOwogICAgICAgIH0sCiAgICAgICAgcmVhZGRpcjogZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICAgIHZhciBlbnRyaWVzID0gWycuJywgJy4uJ107CiAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gbm9kZS5jb250ZW50cykgewogICAgICAgICAgICBpZiAoIW5vZGUuY29udGVudHMuaGFzT3duUHJvcGVydHkoa2V5KSkgewogICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW50cmllcy5wdXNoKGtleSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gZW50cmllcwogICAgICAgIH0sCiAgICAgICAgc3ltbGluazogZnVuY3Rpb24gKHBhcmVudCwgbmV3bmFtZSwgb2xkcGF0aCkgewogICAgICAgICAgdmFyIG5vZGUgPSBNRU1GUy5jcmVhdGVOb2RlKHBhcmVudCwgbmV3bmFtZSwgNTExIHwgNDA5NjAsIDApOwogICAgICAgICAgbm9kZS5saW5rID0gb2xkcGF0aDsKICAgICAgICAgIHJldHVybiBub2RlCiAgICAgICAgfSwKICAgICAgICByZWFkbGluazogZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICAgIGlmICghRlMuaXNMaW5rKG5vZGUubW9kZSkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUlOVkFMKQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG5vZGUubGluawogICAgICAgIH0sCiAgICAgIH0sCiAgICAgIHN0cmVhbV9vcHM6IHsKICAgICAgICByZWFkOiBmdW5jdGlvbiAoc3RyZWFtLCBidWZmZXIsIG9mZnNldCwgbGVuZ3RoLCBwb3NpdGlvbikgewogICAgICAgICAgdmFyIGNvbnRlbnRzID0gc3RyZWFtLm5vZGUuY29udGVudHM7CiAgICAgICAgICBpZiAocG9zaXRpb24gPj0gc3RyZWFtLm5vZGUudXNlZEJ5dGVzKSByZXR1cm4gMAogICAgICAgICAgdmFyIHNpemUgPSBNYXRoLm1pbihzdHJlYW0ubm9kZS51c2VkQnl0ZXMgLSBwb3NpdGlvbiwgbGVuZ3RoKTsKICAgICAgICAgIGFzc2VydChzaXplID49IDApOwogICAgICAgICAgaWYgKHNpemUgPiA4ICYmIGNvbnRlbnRzLnN1YmFycmF5KSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXQoY29udGVudHMuc3ViYXJyYXkocG9zaXRpb24sIHBvc2l0aW9uICsgc2l6ZSksIG9mZnNldCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNpemU7IGkrKykgYnVmZmVyW29mZnNldCArIGldID0gY29udGVudHNbcG9zaXRpb24gKyBpXTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBzaXplCiAgICAgICAgfSwKICAgICAgICB3cml0ZTogZnVuY3Rpb24gKHN0cmVhbSwgYnVmZmVyLCBvZmZzZXQsIGxlbmd0aCwgcG9zaXRpb24sIGNhbk93bikgewogICAgICAgICAgaWYgKCFsZW5ndGgpIHJldHVybiAwCiAgICAgICAgICB2YXIgbm9kZSA9IHN0cmVhbS5ub2RlOwogICAgICAgICAgbm9kZS50aW1lc3RhbXAgPSBEYXRlLm5vdygpOwogICAgICAgICAgaWYgKGJ1ZmZlci5zdWJhcnJheSAmJiAoIW5vZGUuY29udGVudHMgfHwgbm9kZS5jb250ZW50cy5zdWJhcnJheSkpIHsKICAgICAgICAgICAgaWYgKGNhbk93bikgewogICAgICAgICAgICAgIG5vZGUuY29udGVudHMgPSBidWZmZXIuc3ViYXJyYXkob2Zmc2V0LCBvZmZzZXQgKyBsZW5ndGgpOwogICAgICAgICAgICAgIG5vZGUudXNlZEJ5dGVzID0gbGVuZ3RoOwogICAgICAgICAgICAgIHJldHVybiBsZW5ndGgKICAgICAgICAgICAgfSBlbHNlIGlmIChub2RlLnVzZWRCeXRlcyA9PT0gMCAmJiBwb3NpdGlvbiA9PT0gMCkgewogICAgICAgICAgICAgIG5vZGUuY29udGVudHMgPSBuZXcgVWludDhBcnJheShidWZmZXIuc3ViYXJyYXkob2Zmc2V0LCBvZmZzZXQgKyBsZW5ndGgpKTsKICAgICAgICAgICAgICBub2RlLnVzZWRCeXRlcyA9IGxlbmd0aDsKICAgICAgICAgICAgICByZXR1cm4gbGVuZ3RoCiAgICAgICAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24gKyBsZW5ndGggPD0gbm9kZS51c2VkQnl0ZXMpIHsKICAgICAgICAgICAgICBub2RlLmNvbnRlbnRzLnNldChidWZmZXIuc3ViYXJyYXkob2Zmc2V0LCBvZmZzZXQgKyBsZW5ndGgpLCBwb3NpdGlvbik7CiAgICAgICAgICAgICAgcmV0dXJuIGxlbmd0aAogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBNRU1GUy5leHBhbmRGaWxlU3RvcmFnZShub2RlLCBwb3NpdGlvbiArIGxlbmd0aCk7CiAgICAgICAgICBpZiAobm9kZS5jb250ZW50cy5zdWJhcnJheSAmJiBidWZmZXIuc3ViYXJyYXkpCiAgICAgICAgICAgIG5vZGUuY29udGVudHMuc2V0KGJ1ZmZlci5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIGxlbmd0aCksIHBvc2l0aW9uKTsKICAgICAgICAgIGVsc2UgewogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgbm9kZS5jb250ZW50c1twb3NpdGlvbiArIGldID0gYnVmZmVyW29mZnNldCArIGldOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBub2RlLnVzZWRCeXRlcyA9IE1hdGgubWF4KG5vZGUudXNlZEJ5dGVzLCBwb3NpdGlvbiArIGxlbmd0aCk7CiAgICAgICAgICByZXR1cm4gbGVuZ3RoCiAgICAgICAgfSwKICAgICAgICBsbHNlZWs6IGZ1bmN0aW9uIChzdHJlYW0sIG9mZnNldCwgd2hlbmNlKSB7CiAgICAgICAgICB2YXIgcG9zaXRpb24gPSBvZmZzZXQ7CiAgICAgICAgICBpZiAod2hlbmNlID09PSAxKSB7CiAgICAgICAgICAgIHBvc2l0aW9uICs9IHN0cmVhbS5wb3NpdGlvbjsKICAgICAgICAgIH0gZWxzZSBpZiAod2hlbmNlID09PSAyKSB7CiAgICAgICAgICAgIGlmIChGUy5pc0ZpbGUoc3RyZWFtLm5vZGUubW9kZSkpIHsKICAgICAgICAgICAgICBwb3NpdGlvbiArPSBzdHJlYW0ubm9kZS51c2VkQnl0ZXM7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChwb3NpdGlvbiA8IDApIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUlOVkFMKQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHBvc2l0aW9uCiAgICAgICAgfSwKICAgICAgICBhbGxvY2F0ZTogZnVuY3Rpb24gKHN0cmVhbSwgb2Zmc2V0LCBsZW5ndGgpIHsKICAgICAgICAgIE1FTUZTLmV4cGFuZEZpbGVTdG9yYWdlKHN0cmVhbS5ub2RlLCBvZmZzZXQgKyBsZW5ndGgpOwogICAgICAgICAgc3RyZWFtLm5vZGUudXNlZEJ5dGVzID0gTWF0aC5tYXgoc3RyZWFtLm5vZGUudXNlZEJ5dGVzLCBvZmZzZXQgKyBsZW5ndGgpOwogICAgICAgIH0sCiAgICAgICAgbW1hcDogZnVuY3Rpb24gKHN0cmVhbSwgYnVmZmVyLCBvZmZzZXQsIGxlbmd0aCwgcG9zaXRpb24sIHByb3QsIGZsYWdzKSB7CiAgICAgICAgICBpZiAoIUZTLmlzRmlsZShzdHJlYW0ubm9kZS5tb2RlKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTk9ERVYpCiAgICAgICAgICB9CiAgICAgICAgICB2YXIgcHRyOwogICAgICAgICAgdmFyIGFsbG9jYXRlZDsKICAgICAgICAgIHZhciBjb250ZW50cyA9IHN0cmVhbS5ub2RlLmNvbnRlbnRzOwogICAgICAgICAgaWYgKCEoZmxhZ3MgJiAyKSAmJiAoY29udGVudHMuYnVmZmVyID09PSBidWZmZXIgfHwgY29udGVudHMuYnVmZmVyID09PSBidWZmZXIuYnVmZmVyKSkgewogICAgICAgICAgICBhbGxvY2F0ZWQgPSBmYWxzZTsKICAgICAgICAgICAgcHRyID0gY29udGVudHMuYnl0ZU9mZnNldDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmIChwb3NpdGlvbiA+IDAgfHwgcG9zaXRpb24gKyBsZW5ndGggPCBzdHJlYW0ubm9kZS51c2VkQnl0ZXMpIHsKICAgICAgICAgICAgICBpZiAoY29udGVudHMuc3ViYXJyYXkpIHsKICAgICAgICAgICAgICAgIGNvbnRlbnRzID0gY29udGVudHMuc3ViYXJyYXkocG9zaXRpb24sIHBvc2l0aW9uICsgbGVuZ3RoKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgY29udGVudHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChjb250ZW50cywgcG9zaXRpb24sIHBvc2l0aW9uICsgbGVuZ3RoKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYWxsb2NhdGVkID0gdHJ1ZTsKICAgICAgICAgICAgcHRyID0gX21hbGxvYyhsZW5ndGgpOwogICAgICAgICAgICBpZiAoIXB0cikgewogICAgICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVOT01FTSkKICAgICAgICAgICAgfQogICAgICAgICAgICBidWZmZXIuc2V0KGNvbnRlbnRzLCBwdHIpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHsgcHRyOiBwdHIsIGFsbG9jYXRlZDogYWxsb2NhdGVkIH0KICAgICAgICB9LAogICAgICAgIG1zeW5jOiBmdW5jdGlvbiAoc3RyZWFtLCBidWZmZXIsIG9mZnNldCwgbGVuZ3RoLCBtbWFwRmxhZ3MpIHsKICAgICAgICAgIGlmICghRlMuaXNGaWxlKHN0cmVhbS5ub2RlLm1vZGUpKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVOT0RFVikKICAgICAgICAgIH0KICAgICAgICAgIGlmIChtbWFwRmxhZ3MgJiAyKSB7CiAgICAgICAgICAgIHJldHVybiAwCiAgICAgICAgICB9CiAgICAgICAgICBNRU1GUy5zdHJlYW1fb3BzLndyaXRlKHN0cmVhbSwgYnVmZmVyLCAwLCBsZW5ndGgsIG9mZnNldCwgZmFsc2UpOwogICAgICAgICAgcmV0dXJuIDAKICAgICAgICB9LAogICAgICB9LAogICAgfTsKICAgIHZhciBJREJGUyA9IHsKICAgICAgZGJzOiB7fSwKICAgICAgaW5kZXhlZERCOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgaWYgKHR5cGVvZiBpbmRleGVkREIgIT09ICd1bmRlZmluZWQnKSByZXR1cm4gaW5kZXhlZERCCiAgICAgICAgdmFyIHJldCA9IG51bGw7CiAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnKQogICAgICAgICAgcmV0ID0gd2luZG93LmluZGV4ZWREQiB8fCB3aW5kb3cubW96SW5kZXhlZERCIHx8IHdpbmRvdy53ZWJraXRJbmRleGVkREIgfHwgd2luZG93Lm1zSW5kZXhlZERCOwogICAgICAgIGFzc2VydChyZXQsICdJREJGUyB1c2VkLCBidXQgaW5kZXhlZERCIG5vdCBzdXBwb3J0ZWQnKTsKICAgICAgICByZXR1cm4gcmV0CiAgICAgIH0sCiAgICAgIERCX1ZFUlNJT046IDIxLAogICAgICBEQl9TVE9SRV9OQU1FOiAnRklMRV9EQVRBJywKICAgICAgbW91bnQ6IGZ1bmN0aW9uIChtb3VudCkgewogICAgICAgIHJldHVybiBNRU1GUy5tb3VudC5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICAgIH0sCiAgICAgIHN5bmNmczogZnVuY3Rpb24gKG1vdW50LCBwb3B1bGF0ZSwgY2FsbGJhY2spIHsKICAgICAgICBJREJGUy5nZXRMb2NhbFNldChtb3VudCwgZnVuY3Rpb24gKGVyciwgbG9jYWwpIHsKICAgICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpCiAgICAgICAgICBJREJGUy5nZXRSZW1vdGVTZXQobW91bnQsIGZ1bmN0aW9uIChlcnIsIHJlbW90ZSkgewogICAgICAgICAgICBpZiAoZXJyKSByZXR1cm4gY2FsbGJhY2soZXJyKQogICAgICAgICAgICB2YXIgc3JjID0gcG9wdWxhdGUgPyByZW1vdGUgOiBsb2NhbDsKICAgICAgICAgICAgdmFyIGRzdCA9IHBvcHVsYXRlID8gbG9jYWwgOiByZW1vdGU7CiAgICAgICAgICAgIElEQkZTLnJlY29uY2lsZShzcmMsIGRzdCwgY2FsbGJhY2spOwogICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgIH0sCiAgICAgIGdldERCOiBmdW5jdGlvbiAobmFtZSwgY2FsbGJhY2spIHsKICAgICAgICB2YXIgZGIgPSBJREJGUy5kYnNbbmFtZV07CiAgICAgICAgaWYgKGRiKSB7CiAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgZGIpCiAgICAgICAgfQogICAgICAgIHZhciByZXE7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHJlcSA9IElEQkZTLmluZGV4ZWREQigpLm9wZW4obmFtZSwgSURCRlMuREJfVkVSU0lPTik7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGUpCiAgICAgICAgfQogICAgICAgIGlmICghcmVxKSB7CiAgICAgICAgICByZXR1cm4gY2FsbGJhY2soJ1VuYWJsZSB0byBjb25uZWN0IHRvIEluZGV4ZWREQicpCiAgICAgICAgfQogICAgICAgIHJlcS5vbnVwZ3JhZGVuZWVkZWQgPSBmdW5jdGlvbiAoZSkgewogICAgICAgICAgdmFyIGRiID0gZS50YXJnZXQucmVzdWx0OwogICAgICAgICAgdmFyIHRyYW5zYWN0aW9uID0gZS50YXJnZXQudHJhbnNhY3Rpb247CiAgICAgICAgICB2YXIgZmlsZVN0b3JlOwogICAgICAgICAgaWYgKGRiLm9iamVjdFN0b3JlTmFtZXMuY29udGFpbnMoSURCRlMuREJfU1RPUkVfTkFNRSkpIHsKICAgICAgICAgICAgZmlsZVN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUoSURCRlMuREJfU1RPUkVfTkFNRSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmaWxlU3RvcmUgPSBkYi5jcmVhdGVPYmplY3RTdG9yZShJREJGUy5EQl9TVE9SRV9OQU1FKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghZmlsZVN0b3JlLmluZGV4TmFtZXMuY29udGFpbnMoJ3RpbWVzdGFtcCcpKSB7CiAgICAgICAgICAgIGZpbGVTdG9yZS5jcmVhdGVJbmRleCgndGltZXN0YW1wJywgJ3RpbWVzdGFtcCcsIHsgdW5pcXVlOiBmYWxzZSB9KTsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHJlcS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICBkYiA9IHJlcS5yZXN1bHQ7CiAgICAgICAgICBJREJGUy5kYnNbbmFtZV0gPSBkYjsKICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGRiKTsKICAgICAgICB9OwogICAgICAgIHJlcS5vbmVycm9yID0gZnVuY3Rpb24gKGUpIHsKICAgICAgICAgIGNhbGxiYWNrKHRoaXMuZXJyb3IpOwogICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgIH07CiAgICAgIH0sCiAgICAgIGdldExvY2FsU2V0OiBmdW5jdGlvbiAobW91bnQsIGNhbGxiYWNrKSB7CiAgICAgICAgdmFyIGVudHJpZXMgPSB7fTsKICAgICAgICBmdW5jdGlvbiBpc1JlYWxEaXIocCkgewogICAgICAgICAgcmV0dXJuIHAgIT09ICcuJyAmJiBwICE9PSAnLi4nCiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIHRvQWJzb2x1dGUocm9vdCkgewogICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChwKSB7CiAgICAgICAgICAgIHJldHVybiBQQVRILmpvaW4yKHJvb3QsIHApCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHZhciBjaGVjayA9IEZTLnJlYWRkaXIobW91bnQubW91bnRwb2ludCkuZmlsdGVyKGlzUmVhbERpcikubWFwKHRvQWJzb2x1dGUobW91bnQubW91bnRwb2ludCkpOwogICAgICAgIHdoaWxlIChjaGVjay5sZW5ndGgpIHsKICAgICAgICAgIHZhciBwYXRoID0gY2hlY2sucG9wKCk7CiAgICAgICAgICB2YXIgc3RhdDsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHN0YXQgPSBGUy5zdGF0KHBhdGgpOwogICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZSkKICAgICAgICAgIH0KICAgICAgICAgIGlmIChGUy5pc0RpcihzdGF0Lm1vZGUpKSB7CiAgICAgICAgICAgIGNoZWNrLnB1c2guYXBwbHkoY2hlY2ssIEZTLnJlYWRkaXIocGF0aCkuZmlsdGVyKGlzUmVhbERpcikubWFwKHRvQWJzb2x1dGUocGF0aCkpKTsKICAgICAgICAgIH0KICAgICAgICAgIGVudHJpZXNbcGF0aF0gPSB7IHRpbWVzdGFtcDogc3RhdC5tdGltZSB9OwogICAgICAgIH0KICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgeyB0eXBlOiAnbG9jYWwnLCBlbnRyaWVzOiBlbnRyaWVzIH0pCiAgICAgIH0sCiAgICAgIGdldFJlbW90ZVNldDogZnVuY3Rpb24gKG1vdW50LCBjYWxsYmFjaykgewogICAgICAgIHZhciBlbnRyaWVzID0ge307CiAgICAgICAgSURCRlMuZ2V0REIobW91bnQubW91bnRwb2ludCwgZnVuY3Rpb24gKGVyciwgZGIpIHsKICAgICAgICAgIGlmIChlcnIpIHJldHVybiBjYWxsYmFjayhlcnIpCiAgICAgICAgICB0cnkgewogICAgICAgICAgICB2YXIgdHJhbnNhY3Rpb24gPSBkYi50cmFuc2FjdGlvbihbSURCRlMuREJfU1RPUkVfTkFNRV0sICdyZWFkb25seScpOwogICAgICAgICAgICB0cmFuc2FjdGlvbi5vbmVycm9yID0gZnVuY3Rpb24gKGUpIHsKICAgICAgICAgICAgICBjYWxsYmFjayh0aGlzLmVycm9yKTsKICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIHZhciBzdG9yZSA9IHRyYW5zYWN0aW9uLm9iamVjdFN0b3JlKElEQkZTLkRCX1NUT1JFX05BTUUpOwogICAgICAgICAgICB2YXIgaW5kZXggPSBzdG9yZS5pbmRleCgndGltZXN0YW1wJyk7CiAgICAgICAgICAgIGluZGV4Lm9wZW5LZXlDdXJzb3IoKS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoZXZlbnQpIHsKICAgICAgICAgICAgICB2YXIgY3Vyc29yID0gZXZlbnQudGFyZ2V0LnJlc3VsdDsKICAgICAgICAgICAgICBpZiAoIWN1cnNvcikgewogICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIHsgdHlwZTogJ3JlbW90ZScsIGRiOiBkYiwgZW50cmllczogZW50cmllcyB9KQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBlbnRyaWVzW2N1cnNvci5wcmltYXJ5S2V5XSA9IHsgdGltZXN0YW1wOiBjdXJzb3Iua2V5IH07CiAgICAgICAgICAgICAgY3Vyc29yLmNvbnRpbnVlKCk7CiAgICAgICAgICAgIH07CiAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhlKQogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9LAogICAgICBsb2FkTG9jYWxFbnRyeTogZnVuY3Rpb24gKHBhdGgsIGNhbGxiYWNrKSB7CiAgICAgICAgdmFyIHN0YXQsIG5vZGU7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHZhciBsb29rdXAgPSBGUy5sb29rdXBQYXRoKHBhdGgpOwogICAgICAgICAgbm9kZSA9IGxvb2t1cC5ub2RlOwogICAgICAgICAgc3RhdCA9IEZTLnN0YXQocGF0aCk7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGUpCiAgICAgICAgfQogICAgICAgIGlmIChGUy5pc0RpcihzdGF0Lm1vZGUpKSB7CiAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgeyB0aW1lc3RhbXA6IHN0YXQubXRpbWUsIG1vZGU6IHN0YXQubW9kZSB9KQogICAgICAgIH0gZWxzZSBpZiAoRlMuaXNGaWxlKHN0YXQubW9kZSkpIHsKICAgICAgICAgIG5vZGUuY29udGVudHMgPSBNRU1GUy5nZXRGaWxlRGF0YUFzVHlwZWRBcnJheShub2RlKTsKICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCB7IHRpbWVzdGFtcDogc3RhdC5tdGltZSwgbW9kZTogc3RhdC5tb2RlLCBjb250ZW50czogbm9kZS5jb250ZW50cyB9KQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobmV3IEVycm9yKCdub2RlIHR5cGUgbm90IHN1cHBvcnRlZCcpKQogICAgICAgIH0KICAgICAgfSwKICAgICAgc3RvcmVMb2NhbEVudHJ5OiBmdW5jdGlvbiAocGF0aCwgZW50cnksIGNhbGxiYWNrKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGlmIChGUy5pc0RpcihlbnRyeS5tb2RlKSkgewogICAgICAgICAgICBGUy5ta2RpcihwYXRoLCBlbnRyeS5tb2RlKTsKICAgICAgICAgIH0gZWxzZSBpZiAoRlMuaXNGaWxlKGVudHJ5Lm1vZGUpKSB7CiAgICAgICAgICAgIEZTLndyaXRlRmlsZShwYXRoLCBlbnRyeS5jb250ZW50cywgeyBjYW5Pd246IHRydWUgfSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobmV3IEVycm9yKCdub2RlIHR5cGUgbm90IHN1cHBvcnRlZCcpKQogICAgICAgICAgfQogICAgICAgICAgRlMuY2htb2QocGF0aCwgZW50cnkubW9kZSk7CiAgICAgICAgICBGUy51dGltZShwYXRoLCBlbnRyeS50aW1lc3RhbXAsIGVudHJ5LnRpbWVzdGFtcCk7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGUpCiAgICAgICAgfQogICAgICAgIGNhbGxiYWNrKG51bGwpOwogICAgICB9LAogICAgICByZW1vdmVMb2NhbEVudHJ5OiBmdW5jdGlvbiAocGF0aCwgY2FsbGJhY2spIHsKICAgICAgICB0cnkgewogICAgICAgICAgdmFyIGxvb2t1cCA9IEZTLmxvb2t1cFBhdGgocGF0aCk7CiAgICAgICAgICB2YXIgc3RhdCA9IEZTLnN0YXQocGF0aCk7CiAgICAgICAgICBpZiAoRlMuaXNEaXIoc3RhdC5tb2RlKSkgewogICAgICAgICAgICBGUy5ybWRpcihwYXRoKTsKICAgICAgICAgIH0gZWxzZSBpZiAoRlMuaXNGaWxlKHN0YXQubW9kZSkpIHsKICAgICAgICAgICAgRlMudW5saW5rKHBhdGgpOwogICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIHJldHVybiBjYWxsYmFjayhlKQogICAgICAgIH0KICAgICAgICBjYWxsYmFjayhudWxsKTsKICAgICAgfSwKICAgICAgbG9hZFJlbW90ZUVudHJ5OiBmdW5jdGlvbiAoc3RvcmUsIHBhdGgsIGNhbGxiYWNrKSB7CiAgICAgICAgdmFyIHJlcSA9IHN0b3JlLmdldChwYXRoKTsKICAgICAgICByZXEub25zdWNjZXNzID0gZnVuY3Rpb24gKGV2ZW50KSB7CiAgICAgICAgICBjYWxsYmFjayhudWxsLCBldmVudC50YXJnZXQucmVzdWx0KTsKICAgICAgICB9OwogICAgICAgIHJlcS5vbmVycm9yID0gZnVuY3Rpb24gKGUpIHsKICAgICAgICAgIGNhbGxiYWNrKHRoaXMuZXJyb3IpOwogICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgIH07CiAgICAgIH0sCiAgICAgIHN0b3JlUmVtb3RlRW50cnk6IGZ1bmN0aW9uIChzdG9yZSwgcGF0aCwgZW50cnksIGNhbGxiYWNrKSB7CiAgICAgICAgdmFyIHJlcSA9IHN0b3JlLnB1dChlbnRyeSwgcGF0aCk7CiAgICAgICAgcmVxLm9uc3VjY2VzcyA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgIGNhbGxiYWNrKG51bGwpOwogICAgICAgIH07CiAgICAgICAgcmVxLm9uZXJyb3IgPSBmdW5jdGlvbiAoZSkgewogICAgICAgICAgY2FsbGJhY2sodGhpcy5lcnJvcik7CiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7CiAgICAgICAgfTsKICAgICAgfSwKICAgICAgcmVtb3ZlUmVtb3RlRW50cnk6IGZ1bmN0aW9uIChzdG9yZSwgcGF0aCwgY2FsbGJhY2spIHsKICAgICAgICB2YXIgcmVxID0gc3RvcmUuZGVsZXRlKHBhdGgpOwogICAgICAgIHJlcS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICBjYWxsYmFjayhudWxsKTsKICAgICAgICB9OwogICAgICAgIHJlcS5vbmVycm9yID0gZnVuY3Rpb24gKGUpIHsKICAgICAgICAgIGNhbGxiYWNrKHRoaXMuZXJyb3IpOwogICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgIH07CiAgICAgIH0sCiAgICAgIHJlY29uY2lsZTogZnVuY3Rpb24gKHNyYywgZHN0LCBjYWxsYmFjaykgewogICAgICAgIHZhciB0b3RhbCA9IDA7CiAgICAgICAgdmFyIGNyZWF0ZSA9IFtdOwogICAgICAgIE9iamVjdC5rZXlzKHNyYy5lbnRyaWVzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgIHZhciBlID0gc3JjLmVudHJpZXNba2V5XTsKICAgICAgICAgIHZhciBlMiA9IGRzdC5lbnRyaWVzW2tleV07CiAgICAgICAgICBpZiAoIWUyIHx8IGUudGltZXN0YW1wID4gZTIudGltZXN0YW1wKSB7CiAgICAgICAgICAgIGNyZWF0ZS5wdXNoKGtleSk7CiAgICAgICAgICAgIHRvdGFsKys7CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgICAgdmFyIHJlbW92ZSA9IFtdOwogICAgICAgIE9iamVjdC5rZXlzKGRzdC5lbnRyaWVzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgIGRzdC5lbnRyaWVzW2tleV07CiAgICAgICAgICB2YXIgZTIgPSBzcmMuZW50cmllc1trZXldOwogICAgICAgICAgaWYgKCFlMikgewogICAgICAgICAgICByZW1vdmUucHVzaChrZXkpOwogICAgICAgICAgICB0b3RhbCsrOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICAgIGlmICghdG90YWwpIHsKICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsKQogICAgICAgIH0KICAgICAgICB2YXIgY29tcGxldGVkID0gMDsKICAgICAgICB2YXIgZGIgPSBzcmMudHlwZSA9PT0gJ3JlbW90ZScgPyBzcmMuZGIgOiBkc3QuZGI7CiAgICAgICAgdmFyIHRyYW5zYWN0aW9uID0gZGIudHJhbnNhY3Rpb24oW0lEQkZTLkRCX1NUT1JFX05BTUVdLCAncmVhZHdyaXRlJyk7CiAgICAgICAgdmFyIHN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUoSURCRlMuREJfU1RPUkVfTkFNRSk7CiAgICAgICAgZnVuY3Rpb24gZG9uZShlcnIpIHsKICAgICAgICAgIGlmIChlcnIpIHsKICAgICAgICAgICAgaWYgKCFkb25lLmVycm9yZWQpIHsKICAgICAgICAgICAgICBkb25lLmVycm9yZWQgPSB0cnVlOwogICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhlcnIpCiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgICB9CiAgICAgICAgICBpZiAoKytjb21wbGV0ZWQgPj0gdG90YWwpIHsKICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwpCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHRyYW5zYWN0aW9uLm9uZXJyb3IgPSBmdW5jdGlvbiAoZSkgewogICAgICAgICAgZG9uZSh0aGlzLmVycm9yKTsKICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgICB9OwogICAgICAgIGNyZWF0ZS5zb3J0KCkuZm9yRWFjaChmdW5jdGlvbiAocGF0aCkgewogICAgICAgICAgaWYgKGRzdC50eXBlID09PSAnbG9jYWwnKSB7CiAgICAgICAgICAgIElEQkZTLmxvYWRSZW1vdGVFbnRyeShzdG9yZSwgcGF0aCwgZnVuY3Rpb24gKGVyciwgZW50cnkpIHsKICAgICAgICAgICAgICBpZiAoZXJyKSByZXR1cm4gZG9uZShlcnIpCiAgICAgICAgICAgICAgSURCRlMuc3RvcmVMb2NhbEVudHJ5KHBhdGgsIGVudHJ5LCBkb25lKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBJREJGUy5sb2FkTG9jYWxFbnRyeShwYXRoLCBmdW5jdGlvbiAoZXJyLCBlbnRyeSkgewogICAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiBkb25lKGVycikKICAgICAgICAgICAgICBJREJGUy5zdG9yZVJlbW90ZUVudHJ5KHN0b3JlLCBwYXRoLCBlbnRyeSwgZG9uZSk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICAgIHJlbW92ZQogICAgICAgICAgLnNvcnQoKQogICAgICAgICAgLnJldmVyc2UoKQogICAgICAgICAgLmZvckVhY2goZnVuY3Rpb24gKHBhdGgpIHsKICAgICAgICAgICAgaWYgKGRzdC50eXBlID09PSAnbG9jYWwnKSB7CiAgICAgICAgICAgICAgSURCRlMucmVtb3ZlTG9jYWxFbnRyeShwYXRoLCBkb25lKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBJREJGUy5yZW1vdmVSZW1vdGVFbnRyeShzdG9yZSwgcGF0aCwgZG9uZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICB9LAogICAgfTsKICAgIHZhciBOT0RFRlMgPSB7CiAgICAgIGlzV2luZG93czogZmFsc2UsCiAgICAgIHN0YXRpY0luaXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICBOT0RFRlMuaXNXaW5kb3dzID0gISFwcm9jZXNzLnBsYXRmb3JtLm1hdGNoKC9ed2luLyk7CiAgICAgICAgdmFyIGZsYWdzID0gcHJvY2Vzc1snYmluZGluZyddKCdjb25zdGFudHMnKTsKICAgICAgICBpZiAoZmxhZ3NbJ2ZzJ10pIHsKICAgICAgICAgIGZsYWdzID0gZmxhZ3NbJ2ZzJ107CiAgICAgICAgfQogICAgICAgIE5PREVGUy5mbGFnc0Zvck5vZGVNYXAgPSB7CiAgICAgICAgICAxMDI0OiBmbGFnc1snT19BUFBFTkQnXSwKICAgICAgICAgIDY0OiBmbGFnc1snT19DUkVBVCddLAogICAgICAgICAgMTI4OiBmbGFnc1snT19FWENMJ10sCiAgICAgICAgICAwOiBmbGFnc1snT19SRE9OTFknXSwKICAgICAgICAgIDI6IGZsYWdzWydPX1JEV1InXSwKICAgICAgICAgIDQwOTY6IGZsYWdzWydPX1NZTkMnXSwKICAgICAgICAgIDUxMjogZmxhZ3NbJ09fVFJVTkMnXSwKICAgICAgICAgIDE6IGZsYWdzWydPX1dST05MWSddLAogICAgICAgIH07CiAgICAgIH0sCiAgICAgIGJ1ZmZlckZyb206IGZ1bmN0aW9uIChhcnJheUJ1ZmZlcikgewogICAgICAgIHJldHVybiBCdWZmZXIuYWxsb2MgPyBCdWZmZXIuZnJvbShhcnJheUJ1ZmZlcikgOiBuZXcgQnVmZmVyKGFycmF5QnVmZmVyKQogICAgICB9LAogICAgICBtb3VudDogZnVuY3Rpb24gKG1vdW50KSB7CiAgICAgICAgYXNzZXJ0KEVOVklST05NRU5UX0lTX05PREUpOwogICAgICAgIHJldHVybiBOT0RFRlMuY3JlYXRlTm9kZShudWxsLCAnLycsIE5PREVGUy5nZXRNb2RlKG1vdW50Lm9wdHMucm9vdCksIDApCiAgICAgIH0sCiAgICAgIGNyZWF0ZU5vZGU6IGZ1bmN0aW9uIChwYXJlbnQsIG5hbWUsIG1vZGUsIGRldikgewogICAgICAgIGlmICghRlMuaXNEaXIobW9kZSkgJiYgIUZTLmlzRmlsZShtb2RlKSAmJiAhRlMuaXNMaW5rKG1vZGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FSU5WQUwpCiAgICAgICAgfQogICAgICAgIHZhciBub2RlID0gRlMuY3JlYXRlTm9kZShwYXJlbnQsIG5hbWUsIG1vZGUpOwogICAgICAgIG5vZGUubm9kZV9vcHMgPSBOT0RFRlMubm9kZV9vcHM7CiAgICAgICAgbm9kZS5zdHJlYW1fb3BzID0gTk9ERUZTLnN0cmVhbV9vcHM7CiAgICAgICAgcmV0dXJuIG5vZGUKICAgICAgfSwKICAgICAgZ2V0TW9kZTogZnVuY3Rpb24gKHBhdGgpIHsKICAgICAgICB2YXIgc3RhdDsKICAgICAgICB0cnkgewogICAgICAgICAgc3RhdCA9IGZzLmxzdGF0U3luYyhwYXRoKTsKICAgICAgICAgIGlmIChOT0RFRlMuaXNXaW5kb3dzKSB7CiAgICAgICAgICAgIHN0YXQubW9kZSA9IHN0YXQubW9kZSB8ICgoc3RhdC5tb2RlICYgMjkyKSA+PiAyKTsKICAgICAgICAgIH0KICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICBpZiAoIWUuY29kZSkgdGhyb3cgZQogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVNbZS5jb2RlXSkKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHN0YXQubW9kZQogICAgICB9LAogICAgICByZWFsUGF0aDogZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICB2YXIgcGFydHMgPSBbXTsKICAgICAgICB3aGlsZSAobm9kZS5wYXJlbnQgIT09IG5vZGUpIHsKICAgICAgICAgIHBhcnRzLnB1c2gobm9kZS5uYW1lKTsKICAgICAgICAgIG5vZGUgPSBub2RlLnBhcmVudDsKICAgICAgICB9CiAgICAgICAgcGFydHMucHVzaChub2RlLm1vdW50Lm9wdHMucm9vdCk7CiAgICAgICAgcGFydHMucmV2ZXJzZSgpOwogICAgICAgIHJldHVybiBQQVRILmpvaW4uYXBwbHkobnVsbCwgcGFydHMpCiAgICAgIH0sCiAgICAgIGZsYWdzRm9yTm9kZTogZnVuY3Rpb24gKGZsYWdzKSB7CiAgICAgICAgZmxhZ3MgJj0gfjIwOTcxNTI7CiAgICAgICAgZmxhZ3MgJj0gfjIwNDg7CiAgICAgICAgZmxhZ3MgJj0gfjMyNzY4OwogICAgICAgIGZsYWdzICY9IH41MjQyODg7CiAgICAgICAgdmFyIG5ld0ZsYWdzID0gMDsKICAgICAgICBmb3IgKHZhciBrIGluIE5PREVGUy5mbGFnc0Zvck5vZGVNYXApIHsKICAgICAgICAgIGlmIChmbGFncyAmIGspIHsKICAgICAgICAgICAgbmV3RmxhZ3MgfD0gTk9ERUZTLmZsYWdzRm9yTm9kZU1hcFtrXTsKICAgICAgICAgICAgZmxhZ3MgXj0gazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKCFmbGFncykgewogICAgICAgICAgcmV0dXJuIG5ld0ZsYWdzCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVJTlZBTCkKICAgICAgICB9CiAgICAgIH0sCiAgICAgIG5vZGVfb3BzOiB7CiAgICAgICAgZ2V0YXR0cjogZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICAgIHZhciBwYXRoID0gTk9ERUZTLnJlYWxQYXRoKG5vZGUpOwogICAgICAgICAgdmFyIHN0YXQ7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBzdGF0ID0gZnMubHN0YXRTeW5jKHBhdGgpOwogICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICBpZiAoIWUuY29kZSkgdGhyb3cgZQogICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFU1tlLmNvZGVdKQogICAgICAgICAgfQogICAgICAgICAgaWYgKE5PREVGUy5pc1dpbmRvd3MgJiYgIXN0YXQuYmxrc2l6ZSkgewogICAgICAgICAgICBzdGF0LmJsa3NpemUgPSA0MDk2OwogICAgICAgICAgfQogICAgICAgICAgaWYgKE5PREVGUy5pc1dpbmRvd3MgJiYgIXN0YXQuYmxvY2tzKSB7CiAgICAgICAgICAgIHN0YXQuYmxvY2tzID0gKChzdGF0LnNpemUgKyBzdGF0LmJsa3NpemUgLSAxKSAvIHN0YXQuYmxrc2l6ZSkgfCAwOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgZGV2OiBzdGF0LmRldiwKICAgICAgICAgICAgaW5vOiBzdGF0LmlubywKICAgICAgICAgICAgbW9kZTogc3RhdC5tb2RlLAogICAgICAgICAgICBubGluazogc3RhdC5ubGluaywKICAgICAgICAgICAgdWlkOiBzdGF0LnVpZCwKICAgICAgICAgICAgZ2lkOiBzdGF0LmdpZCwKICAgICAgICAgICAgcmRldjogc3RhdC5yZGV2LAogICAgICAgICAgICBzaXplOiBzdGF0LnNpemUsCiAgICAgICAgICAgIGF0aW1lOiBzdGF0LmF0aW1lLAogICAgICAgICAgICBtdGltZTogc3RhdC5tdGltZSwKICAgICAgICAgICAgY3RpbWU6IHN0YXQuY3RpbWUsCiAgICAgICAgICAgIGJsa3NpemU6IHN0YXQuYmxrc2l6ZSwKICAgICAgICAgICAgYmxvY2tzOiBzdGF0LmJsb2NrcywKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHNldGF0dHI6IGZ1bmN0aW9uIChub2RlLCBhdHRyKSB7CiAgICAgICAgICB2YXIgcGF0aCA9IE5PREVGUy5yZWFsUGF0aChub2RlKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGlmIChhdHRyLm1vZGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgIGZzLmNobW9kU3luYyhwYXRoLCBhdHRyLm1vZGUpOwogICAgICAgICAgICAgIG5vZGUubW9kZSA9IGF0dHIubW9kZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoYXR0ci50aW1lc3RhbXAgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgIHZhciBkYXRlID0gbmV3IERhdGUoYXR0ci50aW1lc3RhbXApOwogICAgICAgICAgICAgIGZzLnV0aW1lc1N5bmMocGF0aCwgZGF0ZSwgZGF0ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGF0dHIuc2l6ZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgZnMudHJ1bmNhdGVTeW5jKHBhdGgsIGF0dHIuc2l6ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgaWYgKCFlLmNvZGUpIHRocm93IGUKICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVNbZS5jb2RlXSkKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIGxvb2t1cDogZnVuY3Rpb24gKHBhcmVudCwgbmFtZSkgewogICAgICAgICAgdmFyIHBhdGggPSBQQVRILmpvaW4yKE5PREVGUy5yZWFsUGF0aChwYXJlbnQpLCBuYW1lKTsKICAgICAgICAgIHZhciBtb2RlID0gTk9ERUZTLmdldE1vZGUocGF0aCk7CiAgICAgICAgICByZXR1cm4gTk9ERUZTLmNyZWF0ZU5vZGUocGFyZW50LCBuYW1lLCBtb2RlKQogICAgICAgIH0sCiAgICAgICAgbWtub2Q6IGZ1bmN0aW9uIChwYXJlbnQsIG5hbWUsIG1vZGUsIGRldikgewogICAgICAgICAgdmFyIG5vZGUgPSBOT0RFRlMuY3JlYXRlTm9kZShwYXJlbnQsIG5hbWUsIG1vZGUsIGRldik7CiAgICAgICAgICB2YXIgcGF0aCA9IE5PREVGUy5yZWFsUGF0aChub2RlKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGlmIChGUy5pc0Rpcihub2RlLm1vZGUpKSB7CiAgICAgICAgICAgICAgZnMubWtkaXJTeW5jKHBhdGgsIG5vZGUubW9kZSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZnMud3JpdGVGaWxlU3luYyhwYXRoLCAnJywgeyBtb2RlOiBub2RlLm1vZGUgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgaWYgKCFlLmNvZGUpIHRocm93IGUKICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVNbZS5jb2RlXSkKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBub2RlCiAgICAgICAgfSwKICAgICAgICByZW5hbWU6IGZ1bmN0aW9uIChvbGROb2RlLCBuZXdEaXIsIG5ld05hbWUpIHsKICAgICAgICAgIHZhciBvbGRQYXRoID0gTk9ERUZTLnJlYWxQYXRoKG9sZE5vZGUpOwogICAgICAgICAgdmFyIG5ld1BhdGggPSBQQVRILmpvaW4yKE5PREVGUy5yZWFsUGF0aChuZXdEaXIpLCBuZXdOYW1lKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGZzLnJlbmFtZVN5bmMob2xkUGF0aCwgbmV3UGF0aCk7CiAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIGlmICghZS5jb2RlKSB0aHJvdyBlCiAgICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTW2UuY29kZV0pCiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICB1bmxpbms6IGZ1bmN0aW9uIChwYXJlbnQsIG5hbWUpIHsKICAgICAgICAgIHZhciBwYXRoID0gUEFUSC5qb2luMihOT0RFRlMucmVhbFBhdGgocGFyZW50KSwgbmFtZSk7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBmcy51bmxpbmtTeW5jKHBhdGgpOwogICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICBpZiAoIWUuY29kZSkgdGhyb3cgZQogICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFU1tlLmNvZGVdKQogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgcm1kaXI6IGZ1bmN0aW9uIChwYXJlbnQsIG5hbWUpIHsKICAgICAgICAgIHZhciBwYXRoID0gUEFUSC5qb2luMihOT0RFRlMucmVhbFBhdGgocGFyZW50KSwgbmFtZSk7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBmcy5ybWRpclN5bmMocGF0aCk7CiAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIGlmICghZS5jb2RlKSB0aHJvdyBlCiAgICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTW2UuY29kZV0pCiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICByZWFkZGlyOiBmdW5jdGlvbiAobm9kZSkgewogICAgICAgICAgdmFyIHBhdGggPSBOT0RFRlMucmVhbFBhdGgobm9kZSk7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICByZXR1cm4gZnMucmVhZGRpclN5bmMocGF0aCkKICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgaWYgKCFlLmNvZGUpIHRocm93IGUKICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVNbZS5jb2RlXSkKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHN5bWxpbms6IGZ1bmN0aW9uIChwYXJlbnQsIG5ld05hbWUsIG9sZFBhdGgpIHsKICAgICAgICAgIHZhciBuZXdQYXRoID0gUEFUSC5qb2luMihOT0RFRlMucmVhbFBhdGgocGFyZW50KSwgbmV3TmFtZSk7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBmcy5zeW1saW5rU3luYyhvbGRQYXRoLCBuZXdQYXRoKTsKICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgaWYgKCFlLmNvZGUpIHRocm93IGUKICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVNbZS5jb2RlXSkKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHJlYWRsaW5rOiBmdW5jdGlvbiAobm9kZSkgewogICAgICAgICAgdmFyIHBhdGggPSBOT0RFRlMucmVhbFBhdGgobm9kZSk7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBwYXRoID0gZnMucmVhZGxpbmtTeW5jKHBhdGgpOwogICAgICAgICAgICBwYXRoID0gTk9ERUpTX1BBVEgucmVsYXRpdmUoTk9ERUpTX1BBVEgucmVzb2x2ZShub2RlLm1vdW50Lm9wdHMucm9vdCksIHBhdGgpOwogICAgICAgICAgICByZXR1cm4gcGF0aAogICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICBpZiAoIWUuY29kZSkgdGhyb3cgZQogICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFU1tlLmNvZGVdKQogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgIH0sCiAgICAgIHN0cmVhbV9vcHM6IHsKICAgICAgICBvcGVuOiBmdW5jdGlvbiAoc3RyZWFtKSB7CiAgICAgICAgICB2YXIgcGF0aCA9IE5PREVGUy5yZWFsUGF0aChzdHJlYW0ubm9kZSk7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBpZiAoRlMuaXNGaWxlKHN0cmVhbS5ub2RlLm1vZGUpKSB7CiAgICAgICAgICAgICAgc3RyZWFtLm5mZCA9IGZzLm9wZW5TeW5jKHBhdGgsIE5PREVGUy5mbGFnc0Zvck5vZGUoc3RyZWFtLmZsYWdzKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgaWYgKCFlLmNvZGUpIHRocm93IGUKICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVNbZS5jb2RlXSkKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIGNsb3NlOiBmdW5jdGlvbiAoc3RyZWFtKSB7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBpZiAoRlMuaXNGaWxlKHN0cmVhbS5ub2RlLm1vZGUpICYmIHN0cmVhbS5uZmQpIHsKICAgICAgICAgICAgICBmcy5jbG9zZVN5bmMoc3RyZWFtLm5mZCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgaWYgKCFlLmNvZGUpIHRocm93IGUKICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVNbZS5jb2RlXSkKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHJlYWQ6IGZ1bmN0aW9uIChzdHJlYW0sIGJ1ZmZlciwgb2Zmc2V0LCBsZW5ndGgsIHBvc2l0aW9uKSB7CiAgICAgICAgICBpZiAobGVuZ3RoID09PSAwKSByZXR1cm4gMAogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcmV0dXJuIGZzLnJlYWRTeW5jKHN0cmVhbS5uZmQsIE5PREVGUy5idWZmZXJGcm9tKGJ1ZmZlci5idWZmZXIpLCBvZmZzZXQsIGxlbmd0aCwgcG9zaXRpb24pCiAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTW2UuY29kZV0pCiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICB3cml0ZTogZnVuY3Rpb24gKHN0cmVhbSwgYnVmZmVyLCBvZmZzZXQsIGxlbmd0aCwgcG9zaXRpb24pIHsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHJldHVybiBmcy53cml0ZVN5bmMoc3RyZWFtLm5mZCwgTk9ERUZTLmJ1ZmZlckZyb20oYnVmZmVyLmJ1ZmZlciksIG9mZnNldCwgbGVuZ3RoLCBwb3NpdGlvbikKICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVNbZS5jb2RlXSkKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIGxsc2VlazogZnVuY3Rpb24gKHN0cmVhbSwgb2Zmc2V0LCB3aGVuY2UpIHsKICAgICAgICAgIHZhciBwb3NpdGlvbiA9IG9mZnNldDsKICAgICAgICAgIGlmICh3aGVuY2UgPT09IDEpIHsKICAgICAgICAgICAgcG9zaXRpb24gKz0gc3RyZWFtLnBvc2l0aW9uOwogICAgICAgICAgfSBlbHNlIGlmICh3aGVuY2UgPT09IDIpIHsKICAgICAgICAgICAgaWYgKEZTLmlzRmlsZShzdHJlYW0ubm9kZS5tb2RlKSkgewogICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICB2YXIgc3RhdCA9IGZzLmZzdGF0U3luYyhzdHJlYW0ubmZkKTsKICAgICAgICAgICAgICAgIHBvc2l0aW9uICs9IHN0YXQuc2l6ZTsKICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFU1tlLmNvZGVdKQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKHBvc2l0aW9uIDwgMCkgewogICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FSU5WQUwpCiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gcG9zaXRpb24KICAgICAgICB9LAogICAgICB9LAogICAgfTsKICAgIHZhciBXT1JLRVJGUyA9IHsKICAgICAgRElSX01PREU6IDE2ODk1LAogICAgICBGSUxFX01PREU6IDMzMjc5LAogICAgICByZWFkZXI6IG51bGwsCiAgICAgIG1vdW50OiBmdW5jdGlvbiAobW91bnQpIHsKICAgICAgICBhc3NlcnQoRU5WSVJPTk1FTlRfSVNfV09SS0VSKTsKICAgICAgICBpZiAoIVdPUktFUkZTLnJlYWRlcikgV09SS0VSRlMucmVhZGVyID0gbmV3IEZpbGVSZWFkZXJTeW5jKCk7CiAgICAgICAgdmFyIHJvb3QgPSBXT1JLRVJGUy5jcmVhdGVOb2RlKG51bGwsICcvJywgV09SS0VSRlMuRElSX01PREUsIDApOwogICAgICAgIHZhciBjcmVhdGVkUGFyZW50cyA9IHt9OwogICAgICAgIGZ1bmN0aW9uIGVuc3VyZVBhcmVudChwYXRoKSB7CiAgICAgICAgICB2YXIgcGFydHMgPSBwYXRoLnNwbGl0KCcvJyk7CiAgICAgICAgICB2YXIgcGFyZW50ID0gcm9vdDsKICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoIC0gMTsgaSsrKSB7CiAgICAgICAgICAgIHZhciBjdXJyID0gcGFydHMuc2xpY2UoMCwgaSArIDEpLmpvaW4oJy8nKTsKICAgICAgICAgICAgaWYgKCFjcmVhdGVkUGFyZW50c1tjdXJyXSkgewogICAgICAgICAgICAgIGNyZWF0ZWRQYXJlbnRzW2N1cnJdID0gV09SS0VSRlMuY3JlYXRlTm9kZShwYXJlbnQsIHBhcnRzW2ldLCBXT1JLRVJGUy5ESVJfTU9ERSwgMCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcGFyZW50ID0gY3JlYXRlZFBhcmVudHNbY3Vycl07CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gcGFyZW50CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGJhc2UocGF0aCkgewogICAgICAgICAgdmFyIHBhcnRzID0gcGF0aC5zcGxpdCgnLycpOwogICAgICAgICAgcmV0dXJuIHBhcnRzW3BhcnRzLmxlbmd0aCAtIDFdCiAgICAgICAgfQogICAgICAgIEFycmF5LnByb3RvdHlwZS5mb3JFYWNoLmNhbGwobW91bnQub3B0c1snZmlsZXMnXSB8fCBbXSwgZnVuY3Rpb24gKGZpbGUpIHsKICAgICAgICAgIFdPUktFUkZTLmNyZWF0ZU5vZGUoCiAgICAgICAgICAgIGVuc3VyZVBhcmVudChmaWxlLm5hbWUpLAogICAgICAgICAgICBiYXNlKGZpbGUubmFtZSksCiAgICAgICAgICAgIFdPUktFUkZTLkZJTEVfTU9ERSwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgZmlsZSwKICAgICAgICAgICAgZmlsZS5sYXN0TW9kaWZpZWREYXRlCiAgICAgICAgICApOwogICAgICAgIH0pCiAgICAgICAgOyhtb3VudC5vcHRzWydibG9icyddIHx8IFtdKS5mb3JFYWNoKGZ1bmN0aW9uIChvYmopIHsKICAgICAgICAgIFdPUktFUkZTLmNyZWF0ZU5vZGUoZW5zdXJlUGFyZW50KG9ialsnbmFtZSddKSwgYmFzZShvYmpbJ25hbWUnXSksIFdPUktFUkZTLkZJTEVfTU9ERSwgMCwgb2JqWydkYXRhJ10pOwogICAgICAgIH0pCiAgICAgICAgOyhtb3VudC5vcHRzWydwYWNrYWdlcyddIHx8IFtdKS5mb3JFYWNoKGZ1bmN0aW9uIChwYWNrKSB7CiAgICAgICAgICBwYWNrWydtZXRhZGF0YSddLmZpbGVzLmZvckVhY2goZnVuY3Rpb24gKGZpbGUpIHsKICAgICAgICAgICAgdmFyIG5hbWUgPSBmaWxlLmZpbGVuYW1lLnN1YnN0cigxKTsKICAgICAgICAgICAgV09SS0VSRlMuY3JlYXRlTm9kZSgKICAgICAgICAgICAgICBlbnN1cmVQYXJlbnQobmFtZSksCiAgICAgICAgICAgICAgYmFzZShuYW1lKSwKICAgICAgICAgICAgICBXT1JLRVJGUy5GSUxFX01PREUsCiAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICBwYWNrWydibG9iJ10uc2xpY2UoZmlsZS5zdGFydCwgZmlsZS5lbmQpCiAgICAgICAgICAgICk7CiAgICAgICAgICB9KTsKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gcm9vdAogICAgICB9LAogICAgICBjcmVhdGVOb2RlOiBmdW5jdGlvbiAocGFyZW50LCBuYW1lLCBtb2RlLCBkZXYsIGNvbnRlbnRzLCBtdGltZSkgewogICAgICAgIHZhciBub2RlID0gRlMuY3JlYXRlTm9kZShwYXJlbnQsIG5hbWUsIG1vZGUpOwogICAgICAgIG5vZGUubW9kZSA9IG1vZGU7CiAgICAgICAgbm9kZS5ub2RlX29wcyA9IFdPUktFUkZTLm5vZGVfb3BzOwogICAgICAgIG5vZGUuc3RyZWFtX29wcyA9IFdPUktFUkZTLnN0cmVhbV9vcHM7CiAgICAgICAgbm9kZS50aW1lc3RhbXAgPSAobXRpbWUgfHwgbmV3IERhdGUoKSkuZ2V0VGltZSgpOwogICAgICAgIGFzc2VydChXT1JLRVJGUy5GSUxFX01PREUgIT09IFdPUktFUkZTLkRJUl9NT0RFKTsKICAgICAgICBpZiAobW9kZSA9PT0gV09SS0VSRlMuRklMRV9NT0RFKSB7CiAgICAgICAgICBub2RlLnNpemUgPSBjb250ZW50cy5zaXplOwogICAgICAgICAgbm9kZS5jb250ZW50cyA9IGNvbnRlbnRzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBub2RlLnNpemUgPSA0MDk2OwogICAgICAgICAgbm9kZS5jb250ZW50cyA9IHt9OwogICAgICAgIH0KICAgICAgICBpZiAocGFyZW50KSB7CiAgICAgICAgICBwYXJlbnQuY29udGVudHNbbmFtZV0gPSBub2RlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbm9kZQogICAgICB9LAogICAgICBub2RlX29wczogewogICAgICAgIGdldGF0dHI6IGZ1bmN0aW9uIChub2RlKSB7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBkZXY6IDEsCiAgICAgICAgICAgIGlubzogdW5kZWZpbmVkLAogICAgICAgICAgICBtb2RlOiBub2RlLm1vZGUsCiAgICAgICAgICAgIG5saW5rOiAxLAogICAgICAgICAgICB1aWQ6IDAsCiAgICAgICAgICAgIGdpZDogMCwKICAgICAgICAgICAgcmRldjogdW5kZWZpbmVkLAogICAgICAgICAgICBzaXplOiBub2RlLnNpemUsCiAgICAgICAgICAgIGF0aW1lOiBuZXcgRGF0ZShub2RlLnRpbWVzdGFtcCksCiAgICAgICAgICAgIG10aW1lOiBuZXcgRGF0ZShub2RlLnRpbWVzdGFtcCksCiAgICAgICAgICAgIGN0aW1lOiBuZXcgRGF0ZShub2RlLnRpbWVzdGFtcCksCiAgICAgICAgICAgIGJsa3NpemU6IDQwOTYsCiAgICAgICAgICAgIGJsb2NrczogTWF0aC5jZWlsKG5vZGUuc2l6ZSAvIDQwOTYpLAogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgc2V0YXR0cjogZnVuY3Rpb24gKG5vZGUsIGF0dHIpIHsKICAgICAgICAgIGlmIChhdHRyLm1vZGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBub2RlLm1vZGUgPSBhdHRyLm1vZGU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoYXR0ci50aW1lc3RhbXAgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBub2RlLnRpbWVzdGFtcCA9IGF0dHIudGltZXN0YW1wOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgbG9va3VwOiBmdW5jdGlvbiAocGFyZW50LCBuYW1lKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTk9FTlQpCiAgICAgICAgfSwKICAgICAgICBta25vZDogZnVuY3Rpb24gKHBhcmVudCwgbmFtZSwgbW9kZSwgZGV2KSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FUEVSTSkKICAgICAgICB9LAogICAgICAgIHJlbmFtZTogZnVuY3Rpb24gKG9sZE5vZGUsIG5ld0RpciwgbmV3TmFtZSkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRVBFUk0pCiAgICAgICAgfSwKICAgICAgICB1bmxpbms6IGZ1bmN0aW9uIChwYXJlbnQsIG5hbWUpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVQRVJNKQogICAgICAgIH0sCiAgICAgICAgcm1kaXI6IGZ1bmN0aW9uIChwYXJlbnQsIG5hbWUpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVQRVJNKQogICAgICAgIH0sCiAgICAgICAgcmVhZGRpcjogZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICAgIHZhciBlbnRyaWVzID0gWycuJywgJy4uJ107CiAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gbm9kZS5jb250ZW50cykgewogICAgICAgICAgICBpZiAoIW5vZGUuY29udGVudHMuaGFzT3duUHJvcGVydHkoa2V5KSkgewogICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW50cmllcy5wdXNoKGtleSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gZW50cmllcwogICAgICAgIH0sCiAgICAgICAgc3ltbGluazogZnVuY3Rpb24gKHBhcmVudCwgbmV3TmFtZSwgb2xkUGF0aCkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRVBFUk0pCiAgICAgICAgfSwKICAgICAgICByZWFkbGluazogZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVQRVJNKQogICAgICAgIH0sCiAgICAgIH0sCiAgICAgIHN0cmVhbV9vcHM6IHsKICAgICAgICByZWFkOiBmdW5jdGlvbiAoc3RyZWFtLCBidWZmZXIsIG9mZnNldCwgbGVuZ3RoLCBwb3NpdGlvbikgewogICAgICAgICAgaWYgKHBvc2l0aW9uID49IHN0cmVhbS5ub2RlLnNpemUpIHJldHVybiAwCiAgICAgICAgICB2YXIgY2h1bmsgPSBzdHJlYW0ubm9kZS5jb250ZW50cy5zbGljZShwb3NpdGlvbiwgcG9zaXRpb24gKyBsZW5ndGgpOwogICAgICAgICAgdmFyIGFiID0gV09SS0VSRlMucmVhZGVyLnJlYWRBc0FycmF5QnVmZmVyKGNodW5rKTsKICAgICAgICAgIGJ1ZmZlci5zZXQobmV3IFVpbnQ4QXJyYXkoYWIpLCBvZmZzZXQpOwogICAgICAgICAgcmV0dXJuIGNodW5rLnNpemUKICAgICAgICB9LAogICAgICAgIHdyaXRlOiBmdW5jdGlvbiAoc3RyZWFtLCBidWZmZXIsIG9mZnNldCwgbGVuZ3RoLCBwb3NpdGlvbikgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUlPKQogICAgICAgIH0sCiAgICAgICAgbGxzZWVrOiBmdW5jdGlvbiAoc3RyZWFtLCBvZmZzZXQsIHdoZW5jZSkgewogICAgICAgICAgdmFyIHBvc2l0aW9uID0gb2Zmc2V0OwogICAgICAgICAgaWYgKHdoZW5jZSA9PT0gMSkgewogICAgICAgICAgICBwb3NpdGlvbiArPSBzdHJlYW0ucG9zaXRpb247CiAgICAgICAgICB9IGVsc2UgaWYgKHdoZW5jZSA9PT0gMikgewogICAgICAgICAgICBpZiAoRlMuaXNGaWxlKHN0cmVhbS5ub2RlLm1vZGUpKSB7CiAgICAgICAgICAgICAgcG9zaXRpb24gKz0gc3RyZWFtLm5vZGUuc2l6ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKHBvc2l0aW9uIDwgMCkgewogICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FSU5WQUwpCiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gcG9zaXRpb24KICAgICAgICB9LAogICAgICB9LAogICAgfTsKICAgIFNUQVRJQ1RPUCArPSAxNjsKICAgIFNUQVRJQ1RPUCArPSAxNjsKICAgIFNUQVRJQ1RPUCArPSAxNjsKICAgIHZhciBGUyA9IHsKICAgICAgcm9vdDogbnVsbCwKICAgICAgbW91bnRzOiBbXSwKICAgICAgZGV2aWNlczoge30sCiAgICAgIHN0cmVhbXM6IFtdLAogICAgICBuZXh0SW5vZGU6IDEsCiAgICAgIG5hbWVUYWJsZTogbnVsbCwKICAgICAgY3VycmVudFBhdGg6ICcvJywKICAgICAgaW5pdGlhbGl6ZWQ6IGZhbHNlLAogICAgICBpZ25vcmVQZXJtaXNzaW9uczogdHJ1ZSwKICAgICAgdHJhY2tpbmdEZWxlZ2F0ZToge30sCiAgICAgIHRyYWNraW5nOiB7IG9wZW5GbGFnczogeyBSRUFEOiAxLCBXUklURTogMiB9IH0sCiAgICAgIEVycm5vRXJyb3I6IG51bGwsCiAgICAgIGdlbmVyaWNFcnJvcnM6IHt9LAogICAgICBmaWxlc3lzdGVtczogbnVsbCwKICAgICAgc3luY0ZTUmVxdWVzdHM6IDAsCiAgICAgIGhhbmRsZUZTRXJyb3I6IGZ1bmN0aW9uIChlKSB7CiAgICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIEZTLkVycm5vRXJyb3IpKSB0aHJvdyBlICsgJyA6ICcgKyBzdGFja1RyYWNlKCkKICAgICAgICByZXR1cm4gX19fc2V0RXJyTm8oZS5lcnJubykKICAgICAgfSwKICAgICAgbG9va3VwUGF0aDogZnVuY3Rpb24gKHBhdGgsIG9wdHMpIHsKICAgICAgICBwYXRoID0gUEFUSC5yZXNvbHZlKEZTLmN3ZCgpLCBwYXRoKTsKICAgICAgICBvcHRzID0gb3B0cyB8fCB7fTsKICAgICAgICBpZiAoIXBhdGgpIHJldHVybiB7IHBhdGg6ICcnLCBub2RlOiBudWxsIH0KICAgICAgICB2YXIgZGVmYXVsdHMgPSB7IGZvbGxvd19tb3VudDogdHJ1ZSwgcmVjdXJzZV9jb3VudDogMCB9OwogICAgICAgIGZvciAodmFyIGtleSBpbiBkZWZhdWx0cykgewogICAgICAgICAgaWYgKG9wdHNba2V5XSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIG9wdHNba2V5XSA9IGRlZmF1bHRzW2tleV07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChvcHRzLnJlY3Vyc2VfY291bnQgPiA4KSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTE9PUCkKICAgICAgICB9CiAgICAgICAgdmFyIHBhcnRzID0gUEFUSC5ub3JtYWxpemVBcnJheSgKICAgICAgICAgIHBhdGguc3BsaXQoJy8nKS5maWx0ZXIoZnVuY3Rpb24gKHApIHsKICAgICAgICAgICAgcmV0dXJuICEhcAogICAgICAgICAgfSksCiAgICAgICAgICBmYWxzZQogICAgICAgICk7CiAgICAgICAgdmFyIGN1cnJlbnQgPSBGUy5yb290OwogICAgICAgIHZhciBjdXJyZW50X3BhdGggPSAnLyc7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgdmFyIGlzbGFzdCA9IGkgPT09IHBhcnRzLmxlbmd0aCAtIDE7CiAgICAgICAgICBpZiAoaXNsYXN0ICYmIG9wdHMucGFyZW50KSB7CiAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICB9CiAgICAgICAgICBjdXJyZW50ID0gRlMubG9va3VwTm9kZShjdXJyZW50LCBwYXJ0c1tpXSk7CiAgICAgICAgICBjdXJyZW50X3BhdGggPSBQQVRILmpvaW4yKGN1cnJlbnRfcGF0aCwgcGFydHNbaV0pOwogICAgICAgICAgaWYgKEZTLmlzTW91bnRwb2ludChjdXJyZW50KSkgewogICAgICAgICAgICBpZiAoIWlzbGFzdCB8fCAoaXNsYXN0ICYmIG9wdHMuZm9sbG93X21vdW50KSkgewogICAgICAgICAgICAgIGN1cnJlbnQgPSBjdXJyZW50Lm1vdW50ZWQucm9vdDsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKCFpc2xhc3QgfHwgb3B0cy5mb2xsb3cpIHsKICAgICAgICAgICAgdmFyIGNvdW50ID0gMDsKICAgICAgICAgICAgd2hpbGUgKEZTLmlzTGluayhjdXJyZW50Lm1vZGUpKSB7CiAgICAgICAgICAgICAgdmFyIGxpbmsgPSBGUy5yZWFkbGluayhjdXJyZW50X3BhdGgpOwogICAgICAgICAgICAgIGN1cnJlbnRfcGF0aCA9IFBBVEgucmVzb2x2ZShQQVRILmRpcm5hbWUoY3VycmVudF9wYXRoKSwgbGluayk7CiAgICAgICAgICAgICAgdmFyIGxvb2t1cCA9IEZTLmxvb2t1cFBhdGgoY3VycmVudF9wYXRoLCB7IHJlY3Vyc2VfY291bnQ6IG9wdHMucmVjdXJzZV9jb3VudCB9KTsKICAgICAgICAgICAgICBjdXJyZW50ID0gbG9va3VwLm5vZGU7CiAgICAgICAgICAgICAgaWYgKGNvdW50KysgPiA0MCkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUxPT1ApCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB7IHBhdGg6IGN1cnJlbnRfcGF0aCwgbm9kZTogY3VycmVudCB9CiAgICAgIH0sCiAgICAgIGdldFBhdGg6IGZ1bmN0aW9uIChub2RlKSB7CiAgICAgICAgdmFyIHBhdGg7CiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgIGlmIChGUy5pc1Jvb3Qobm9kZSkpIHsKICAgICAgICAgICAgdmFyIG1vdW50ID0gbm9kZS5tb3VudC5tb3VudHBvaW50OwogICAgICAgICAgICBpZiAoIXBhdGgpIHJldHVybiBtb3VudAogICAgICAgICAgICByZXR1cm4gbW91bnRbbW91bnQubGVuZ3RoIC0gMV0gIT09ICcvJyA/IG1vdW50ICsgJy8nICsgcGF0aCA6IG1vdW50ICsgcGF0aAogICAgICAgICAgfQogICAgICAgICAgcGF0aCA9IHBhdGggPyBub2RlLm5hbWUgKyAnLycgKyBwYXRoIDogbm9kZS5uYW1lOwogICAgICAgICAgbm9kZSA9IG5vZGUucGFyZW50OwogICAgICAgIH0KICAgICAgfSwKICAgICAgaGFzaE5hbWU6IGZ1bmN0aW9uIChwYXJlbnRpZCwgbmFtZSkgewogICAgICAgIHZhciBoYXNoID0gMDsKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5hbWUubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGhhc2ggPSAoKGhhc2ggPDwgNSkgLSBoYXNoICsgbmFtZS5jaGFyQ29kZUF0KGkpKSB8IDA7CiAgICAgICAgfQogICAgICAgIHJldHVybiAoKHBhcmVudGlkICsgaGFzaCkgPj4+IDApICUgRlMubmFtZVRhYmxlLmxlbmd0aAogICAgICB9LAogICAgICBoYXNoQWRkTm9kZTogZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICB2YXIgaGFzaCA9IEZTLmhhc2hOYW1lKG5vZGUucGFyZW50LmlkLCBub2RlLm5hbWUpOwogICAgICAgIG5vZGUubmFtZV9uZXh0ID0gRlMubmFtZVRhYmxlW2hhc2hdOwogICAgICAgIEZTLm5hbWVUYWJsZVtoYXNoXSA9IG5vZGU7CiAgICAgIH0sCiAgICAgIGhhc2hSZW1vdmVOb2RlOiBmdW5jdGlvbiAobm9kZSkgewogICAgICAgIHZhciBoYXNoID0gRlMuaGFzaE5hbWUobm9kZS5wYXJlbnQuaWQsIG5vZGUubmFtZSk7CiAgICAgICAgaWYgKEZTLm5hbWVUYWJsZVtoYXNoXSA9PT0gbm9kZSkgewogICAgICAgICAgRlMubmFtZVRhYmxlW2hhc2hdID0gbm9kZS5uYW1lX25leHQ7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciBjdXJyZW50ID0gRlMubmFtZVRhYmxlW2hhc2hdOwogICAgICAgICAgd2hpbGUgKGN1cnJlbnQpIHsKICAgICAgICAgICAgaWYgKGN1cnJlbnQubmFtZV9uZXh0ID09PSBub2RlKSB7CiAgICAgICAgICAgICAgY3VycmVudC5uYW1lX25leHQgPSBub2RlLm5hbWVfbmV4dDsKICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICB9CiAgICAgICAgICAgIGN1cnJlbnQgPSBjdXJyZW50Lm5hbWVfbmV4dDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0sCiAgICAgIGxvb2t1cE5vZGU6IGZ1bmN0aW9uIChwYXJlbnQsIG5hbWUpIHsKICAgICAgICB2YXIgZXJyID0gRlMubWF5TG9va3VwKHBhcmVudCk7CiAgICAgICAgaWYgKGVycikgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoZXJyLCBwYXJlbnQpCiAgICAgICAgfQogICAgICAgIHZhciBoYXNoID0gRlMuaGFzaE5hbWUocGFyZW50LmlkLCBuYW1lKTsKICAgICAgICBmb3IgKHZhciBub2RlID0gRlMubmFtZVRhYmxlW2hhc2hdOyBub2RlOyBub2RlID0gbm9kZS5uYW1lX25leHQpIHsKICAgICAgICAgIHZhciBub2RlTmFtZSA9IG5vZGUubmFtZTsKICAgICAgICAgIGlmIChub2RlLnBhcmVudC5pZCA9PT0gcGFyZW50LmlkICYmIG5vZGVOYW1lID09PSBuYW1lKSB7CiAgICAgICAgICAgIHJldHVybiBub2RlCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBGUy5sb29rdXAocGFyZW50LCBuYW1lKQogICAgICB9LAogICAgICBjcmVhdGVOb2RlOiBmdW5jdGlvbiAocGFyZW50LCBuYW1lLCBtb2RlLCByZGV2KSB7CiAgICAgICAgaWYgKCFGUy5GU05vZGUpIHsKICAgICAgICAgIEZTLkZTTm9kZSA9IGZ1bmN0aW9uIChwYXJlbnQsIG5hbWUsIG1vZGUsIHJkZXYpIHsKICAgICAgICAgICAgaWYgKCFwYXJlbnQpIHsKICAgICAgICAgICAgICBwYXJlbnQgPSB0aGlzOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50OwogICAgICAgICAgICB0aGlzLm1vdW50ID0gcGFyZW50Lm1vdW50OwogICAgICAgICAgICB0aGlzLm1vdW50ZWQgPSBudWxsOwogICAgICAgICAgICB0aGlzLmlkID0gRlMubmV4dElub2RlKys7CiAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICAgICAgICAgIHRoaXMubW9kZSA9IG1vZGU7CiAgICAgICAgICAgIHRoaXMubm9kZV9vcHMgPSB7fTsKICAgICAgICAgICAgdGhpcy5zdHJlYW1fb3BzID0ge307CiAgICAgICAgICAgIHRoaXMucmRldiA9IHJkZXY7CiAgICAgICAgICB9OwogICAgICAgICAgRlMuRlNOb2RlLnByb3RvdHlwZSA9IHt9OwogICAgICAgICAgdmFyIHJlYWRNb2RlID0gMjkyIHwgNzM7CiAgICAgICAgICB2YXIgd3JpdGVNb2RlID0gMTQ2OwogICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoRlMuRlNOb2RlLnByb3RvdHlwZSwgewogICAgICAgICAgICByZWFkOiB7CiAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gKHRoaXMubW9kZSAmIHJlYWRNb2RlKSA9PT0gcmVhZE1vZGUKICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgIHNldDogZnVuY3Rpb24gKHZhbCkgewogICAgICAgICAgICAgICAgdmFsID8gKHRoaXMubW9kZSB8PSByZWFkTW9kZSkgOiAodGhpcy5tb2RlICY9IH5yZWFkTW9kZSk7CiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgfSwKICAgICAgICAgICAgd3JpdGU6IHsKICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgIHJldHVybiAodGhpcy5tb2RlICYgd3JpdGVNb2RlKSA9PT0gd3JpdGVNb2RlCiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uICh2YWwpIHsKICAgICAgICAgICAgICAgIHZhbCA/ICh0aGlzLm1vZGUgfD0gd3JpdGVNb2RlKSA6ICh0aGlzLm1vZGUgJj0gfndyaXRlTW9kZSk7CiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgfSwKICAgICAgICAgICAgaXNGb2xkZXI6IHsKICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgIHJldHVybiBGUy5pc0Rpcih0aGlzLm1vZGUpCiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgfSwKICAgICAgICAgICAgaXNEZXZpY2U6IHsKICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgIHJldHVybiBGUy5pc0NocmRldih0aGlzLm1vZGUpCiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgfSwKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICB2YXIgbm9kZSA9IG5ldyBGUy5GU05vZGUocGFyZW50LCBuYW1lLCBtb2RlLCByZGV2KTsKICAgICAgICBGUy5oYXNoQWRkTm9kZShub2RlKTsKICAgICAgICByZXR1cm4gbm9kZQogICAgICB9LAogICAgICBkZXN0cm95Tm9kZTogZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICBGUy5oYXNoUmVtb3ZlTm9kZShub2RlKTsKICAgICAgfSwKICAgICAgaXNSb290OiBmdW5jdGlvbiAobm9kZSkgewogICAgICAgIHJldHVybiBub2RlID09PSBub2RlLnBhcmVudAogICAgICB9LAogICAgICBpc01vdW50cG9pbnQ6IGZ1bmN0aW9uIChub2RlKSB7CiAgICAgICAgcmV0dXJuICEhbm9kZS5tb3VudGVkCiAgICAgIH0sCiAgICAgIGlzRmlsZTogZnVuY3Rpb24gKG1vZGUpIHsKICAgICAgICByZXR1cm4gKG1vZGUgJiA2MTQ0MCkgPT09IDMyNzY4CiAgICAgIH0sCiAgICAgIGlzRGlyOiBmdW5jdGlvbiAobW9kZSkgewogICAgICAgIHJldHVybiAobW9kZSAmIDYxNDQwKSA9PT0gMTYzODQKICAgICAgfSwKICAgICAgaXNMaW5rOiBmdW5jdGlvbiAobW9kZSkgewogICAgICAgIHJldHVybiAobW9kZSAmIDYxNDQwKSA9PT0gNDA5NjAKICAgICAgfSwKICAgICAgaXNDaHJkZXY6IGZ1bmN0aW9uIChtb2RlKSB7CiAgICAgICAgcmV0dXJuIChtb2RlICYgNjE0NDApID09PSA4MTkyCiAgICAgIH0sCiAgICAgIGlzQmxrZGV2OiBmdW5jdGlvbiAobW9kZSkgewogICAgICAgIHJldHVybiAobW9kZSAmIDYxNDQwKSA9PT0gMjQ1NzYKICAgICAgfSwKICAgICAgaXNGSUZPOiBmdW5jdGlvbiAobW9kZSkgewogICAgICAgIHJldHVybiAobW9kZSAmIDYxNDQwKSA9PT0gNDA5NgogICAgICB9LAogICAgICBpc1NvY2tldDogZnVuY3Rpb24gKG1vZGUpIHsKICAgICAgICByZXR1cm4gKG1vZGUgJiA0OTE1MikgPT09IDQ5MTUyCiAgICAgIH0sCiAgICAgIGZsYWdNb2RlczogewogICAgICAgIHI6IDAsCiAgICAgICAgcnM6IDEwNTI2NzIsCiAgICAgICAgJ3IrJzogMiwKICAgICAgICB3OiA1NzcsCiAgICAgICAgd3g6IDcwNSwKICAgICAgICB4dzogNzA1LAogICAgICAgICd3Kyc6IDU3OCwKICAgICAgICAnd3grJzogNzA2LAogICAgICAgICd4dysnOiA3MDYsCiAgICAgICAgYTogMTA4OSwKICAgICAgICBheDogMTIxNywKICAgICAgICB4YTogMTIxNywKICAgICAgICAnYSsnOiAxMDkwLAogICAgICAgICdheCsnOiAxMjE4LAogICAgICAgICd4YSsnOiAxMjE4LAogICAgICB9LAogICAgICBtb2RlU3RyaW5nVG9GbGFnczogZnVuY3Rpb24gKHN0cikgewogICAgICAgIHZhciBmbGFncyA9IEZTLmZsYWdNb2Rlc1tzdHJdOwogICAgICAgIGlmICh0eXBlb2YgZmxhZ3MgPT09ICd1bmRlZmluZWQnKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gZmlsZSBvcGVuIG1vZGU6ICcgKyBzdHIpCiAgICAgICAgfQogICAgICAgIHJldHVybiBmbGFncwogICAgICB9LAogICAgICBmbGFnc1RvUGVybWlzc2lvblN0cmluZzogZnVuY3Rpb24gKGZsYWcpIHsKICAgICAgICB2YXIgcGVybXMgPSBbJ3InLCAndycsICdydyddW2ZsYWcgJiAzXTsKICAgICAgICBpZiAoZmxhZyAmIDUxMikgewogICAgICAgICAgcGVybXMgKz0gJ3cnOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcGVybXMKICAgICAgfSwKICAgICAgbm9kZVBlcm1pc3Npb25zOiBmdW5jdGlvbiAobm9kZSwgcGVybXMpIHsKICAgICAgICBpZiAoRlMuaWdub3JlUGVybWlzc2lvbnMpIHsKICAgICAgICAgIHJldHVybiAwCiAgICAgICAgfQogICAgICAgIGlmIChwZXJtcy5pbmRleE9mKCdyJykgIT09IC0xICYmICEobm9kZS5tb2RlICYgMjkyKSkgewogICAgICAgICAgcmV0dXJuIEVSUk5PX0NPREVTLkVBQ0NFUwogICAgICAgIH0gZWxzZSBpZiAocGVybXMuaW5kZXhPZigndycpICE9PSAtMSAmJiAhKG5vZGUubW9kZSAmIDE0NikpIHsKICAgICAgICAgIHJldHVybiBFUlJOT19DT0RFUy5FQUNDRVMKICAgICAgICB9IGVsc2UgaWYgKHBlcm1zLmluZGV4T2YoJ3gnKSAhPT0gLTEgJiYgIShub2RlLm1vZGUgJiA3MykpIHsKICAgICAgICAgIHJldHVybiBFUlJOT19DT0RFUy5FQUNDRVMKICAgICAgICB9CiAgICAgICAgcmV0dXJuIDAKICAgICAgfSwKICAgICAgbWF5TG9va3VwOiBmdW5jdGlvbiAoZGlyKSB7CiAgICAgICAgdmFyIGVyciA9IEZTLm5vZGVQZXJtaXNzaW9ucyhkaXIsICd4Jyk7CiAgICAgICAgaWYgKGVycikgcmV0dXJuIGVycgogICAgICAgIGlmICghZGlyLm5vZGVfb3BzLmxvb2t1cCkgcmV0dXJuIEVSUk5PX0NPREVTLkVBQ0NFUwogICAgICAgIHJldHVybiAwCiAgICAgIH0sCiAgICAgIG1heUNyZWF0ZTogZnVuY3Rpb24gKGRpciwgbmFtZSkgewogICAgICAgIHRyeSB7CiAgICAgICAgICB2YXIgbm9kZSA9IEZTLmxvb2t1cE5vZGUoZGlyLCBuYW1lKTsKICAgICAgICAgIHJldHVybiBFUlJOT19DT0RFUy5FRVhJU1QKICAgICAgICB9IGNhdGNoIChlKSB7fQogICAgICAgIHJldHVybiBGUy5ub2RlUGVybWlzc2lvbnMoZGlyLCAnd3gnKQogICAgICB9LAogICAgICBtYXlEZWxldGU6IGZ1bmN0aW9uIChkaXIsIG5hbWUsIGlzZGlyKSB7CiAgICAgICAgdmFyIG5vZGU7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIG5vZGUgPSBGUy5sb29rdXBOb2RlKGRpciwgbmFtZSk7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgcmV0dXJuIGUuZXJybm8KICAgICAgICB9CiAgICAgICAgdmFyIGVyciA9IEZTLm5vZGVQZXJtaXNzaW9ucyhkaXIsICd3eCcpOwogICAgICAgIGlmIChlcnIpIHsKICAgICAgICAgIHJldHVybiBlcnIKICAgICAgICB9CiAgICAgICAgaWYgKGlzZGlyKSB7CiAgICAgICAgICBpZiAoIUZTLmlzRGlyKG5vZGUubW9kZSkpIHsKICAgICAgICAgICAgcmV0dXJuIEVSUk5PX0NPREVTLkVOT1RESVIKICAgICAgICAgIH0KICAgICAgICAgIGlmIChGUy5pc1Jvb3Qobm9kZSkgfHwgRlMuZ2V0UGF0aChub2RlKSA9PT0gRlMuY3dkKCkpIHsKICAgICAgICAgICAgcmV0dXJuIEVSUk5PX0NPREVTLkVCVVNZCiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChGUy5pc0Rpcihub2RlLm1vZGUpKSB7CiAgICAgICAgICAgIHJldHVybiBFUlJOT19DT0RFUy5FSVNESVIKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIDAKICAgICAgfSwKICAgICAgbWF5T3BlbjogZnVuY3Rpb24gKG5vZGUsIGZsYWdzKSB7CiAgICAgICAgaWYgKCFub2RlKSB7CiAgICAgICAgICByZXR1cm4gRVJSTk9fQ09ERVMuRU5PRU5UCiAgICAgICAgfQogICAgICAgIGlmIChGUy5pc0xpbmsobm9kZS5tb2RlKSkgewogICAgICAgICAgcmV0dXJuIEVSUk5PX0NPREVTLkVMT09QCiAgICAgICAgfSBlbHNlIGlmIChGUy5pc0Rpcihub2RlLm1vZGUpKSB7CiAgICAgICAgICBpZiAoRlMuZmxhZ3NUb1Blcm1pc3Npb25TdHJpbmcoZmxhZ3MpICE9PSAncicgfHwgZmxhZ3MgJiA1MTIpIHsKICAgICAgICAgICAgcmV0dXJuIEVSUk5PX0NPREVTLkVJU0RJUgogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gRlMubm9kZVBlcm1pc3Npb25zKG5vZGUsIEZTLmZsYWdzVG9QZXJtaXNzaW9uU3RyaW5nKGZsYWdzKSkKICAgICAgfSwKICAgICAgTUFYX09QRU5fRkRTOiA0MDk2LAogICAgICBuZXh0ZmQ6IGZ1bmN0aW9uIChmZF9zdGFydCwgZmRfZW5kKSB7CiAgICAgICAgZmRfc3RhcnQgPSBmZF9zdGFydCB8fCAwOwogICAgICAgIGZkX2VuZCA9IGZkX2VuZCB8fCBGUy5NQVhfT1BFTl9GRFM7CiAgICAgICAgZm9yICh2YXIgZmQgPSBmZF9zdGFydDsgZmQgPD0gZmRfZW5kOyBmZCsrKSB7CiAgICAgICAgICBpZiAoIUZTLnN0cmVhbXNbZmRdKSB7CiAgICAgICAgICAgIHJldHVybiBmZAogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTUZJTEUpCiAgICAgIH0sCiAgICAgIGdldFN0cmVhbTogZnVuY3Rpb24gKGZkKSB7CiAgICAgICAgcmV0dXJuIEZTLnN0cmVhbXNbZmRdCiAgICAgIH0sCiAgICAgIGNyZWF0ZVN0cmVhbTogZnVuY3Rpb24gKHN0cmVhbSwgZmRfc3RhcnQsIGZkX2VuZCkgewogICAgICAgIGlmICghRlMuRlNTdHJlYW0pIHsKICAgICAgICAgIEZTLkZTU3RyZWFtID0gZnVuY3Rpb24gKCkge307CiAgICAgICAgICBGUy5GU1N0cmVhbS5wcm90b3R5cGUgPSB7fTsKICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKEZTLkZTU3RyZWFtLnByb3RvdHlwZSwgewogICAgICAgICAgICBvYmplY3Q6IHsKICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm5vZGUKICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgIHNldDogZnVuY3Rpb24gKHZhbCkgewogICAgICAgICAgICAgICAgdGhpcy5ub2RlID0gdmFsOwogICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGlzUmVhZDogewogICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgcmV0dXJuICh0aGlzLmZsYWdzICYgMjA5NzE1NSkgIT09IDEKICAgICAgICAgICAgICB9LAogICAgICAgICAgICB9LAogICAgICAgICAgICBpc1dyaXRlOiB7CiAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gKHRoaXMuZmxhZ3MgJiAyMDk3MTU1KSAhPT0gMAogICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGlzQXBwZW5kOiB7CiAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5mbGFncyAmIDEwMjQKICAgICAgICAgICAgICB9LAogICAgICAgICAgICB9LAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIHZhciBuZXdTdHJlYW0gPSBuZXcgRlMuRlNTdHJlYW0oKTsKICAgICAgICBmb3IgKHZhciBwIGluIHN0cmVhbSkgewogICAgICAgICAgbmV3U3RyZWFtW3BdID0gc3RyZWFtW3BdOwogICAgICAgIH0KICAgICAgICBzdHJlYW0gPSBuZXdTdHJlYW07CiAgICAgICAgdmFyIGZkID0gRlMubmV4dGZkKGZkX3N0YXJ0LCBmZF9lbmQpOwogICAgICAgIHN0cmVhbS5mZCA9IGZkOwogICAgICAgIEZTLnN0cmVhbXNbZmRdID0gc3RyZWFtOwogICAgICAgIHJldHVybiBzdHJlYW0KICAgICAgfSwKICAgICAgY2xvc2VTdHJlYW06IGZ1bmN0aW9uIChmZCkgewogICAgICAgIEZTLnN0cmVhbXNbZmRdID0gbnVsbDsKICAgICAgfSwKICAgICAgY2hyZGV2X3N0cmVhbV9vcHM6IHsKICAgICAgICBvcGVuOiBmdW5jdGlvbiAoc3RyZWFtKSB7CiAgICAgICAgICB2YXIgZGV2aWNlID0gRlMuZ2V0RGV2aWNlKHN0cmVhbS5ub2RlLnJkZXYpOwogICAgICAgICAgc3RyZWFtLnN0cmVhbV9vcHMgPSBkZXZpY2Uuc3RyZWFtX29wczsKICAgICAgICAgIGlmIChzdHJlYW0uc3RyZWFtX29wcy5vcGVuKSB7CiAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1fb3BzLm9wZW4oc3RyZWFtKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIGxsc2VlazogZnVuY3Rpb24gKCkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRVNQSVBFKQogICAgICAgIH0sCiAgICAgIH0sCiAgICAgIG1ham9yOiBmdW5jdGlvbiAoZGV2KSB7CiAgICAgICAgcmV0dXJuIGRldiA+PiA4CiAgICAgIH0sCiAgICAgIG1pbm9yOiBmdW5jdGlvbiAoZGV2KSB7CiAgICAgICAgcmV0dXJuIGRldiAmIDI1NQogICAgICB9LAogICAgICBtYWtlZGV2OiBmdW5jdGlvbiAobWEsIG1pKSB7CiAgICAgICAgcmV0dXJuIChtYSA8PCA4KSB8IG1pCiAgICAgIH0sCiAgICAgIHJlZ2lzdGVyRGV2aWNlOiBmdW5jdGlvbiAoZGV2LCBvcHMpIHsKICAgICAgICBGUy5kZXZpY2VzW2Rldl0gPSB7IHN0cmVhbV9vcHM6IG9wcyB9OwogICAgICB9LAogICAgICBnZXREZXZpY2U6IGZ1bmN0aW9uIChkZXYpIHsKICAgICAgICByZXR1cm4gRlMuZGV2aWNlc1tkZXZdCiAgICAgIH0sCiAgICAgIGdldE1vdW50czogZnVuY3Rpb24gKG1vdW50KSB7CiAgICAgICAgdmFyIG1vdW50cyA9IFtdOwogICAgICAgIHZhciBjaGVjayA9IFttb3VudF07CiAgICAgICAgd2hpbGUgKGNoZWNrLmxlbmd0aCkgewogICAgICAgICAgdmFyIG0gPSBjaGVjay5wb3AoKTsKICAgICAgICAgIG1vdW50cy5wdXNoKG0pOwogICAgICAgICAgY2hlY2sucHVzaC5hcHBseShjaGVjaywgbS5tb3VudHMpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbW91bnRzCiAgICAgIH0sCiAgICAgIHN5bmNmczogZnVuY3Rpb24gKHBvcHVsYXRlLCBjYWxsYmFjaykgewogICAgICAgIGlmICh0eXBlb2YgcG9wdWxhdGUgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgIGNhbGxiYWNrID0gcG9wdWxhdGU7CiAgICAgICAgICBwb3B1bGF0ZSA9IGZhbHNlOwogICAgICAgIH0KICAgICAgICBGUy5zeW5jRlNSZXF1ZXN0cysrOwogICAgICAgIGlmIChGUy5zeW5jRlNSZXF1ZXN0cyA+IDEpIHsKICAgICAgICAgIGNvbnNvbGUubG9nKAogICAgICAgICAgICAnd2FybmluZzogJyArIEZTLnN5bmNGU1JlcXVlc3RzICsgJyBGUy5zeW5jZnMgb3BlcmF0aW9ucyBpbiBmbGlnaHQgYXQgb25jZSwgcHJvYmFibHkganVzdCBkb2luZyBleHRyYSB3b3JrJwogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgdmFyIG1vdW50cyA9IEZTLmdldE1vdW50cyhGUy5yb290Lm1vdW50KTsKICAgICAgICB2YXIgY29tcGxldGVkID0gMDsKICAgICAgICBmdW5jdGlvbiBkb0NhbGxiYWNrKGVycikgewogICAgICAgICAgYXNzZXJ0KEZTLnN5bmNGU1JlcXVlc3RzID4gMCk7CiAgICAgICAgICBGUy5zeW5jRlNSZXF1ZXN0cy0tOwogICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycikKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gZG9uZShlcnIpIHsKICAgICAgICAgIGlmIChlcnIpIHsKICAgICAgICAgICAgaWYgKCFkb25lLmVycm9yZWQpIHsKICAgICAgICAgICAgICBkb25lLmVycm9yZWQgPSB0cnVlOwogICAgICAgICAgICAgIHJldHVybiBkb0NhbGxiYWNrKGVycikKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4KICAgICAgICAgIH0KICAgICAgICAgIGlmICgrK2NvbXBsZXRlZCA+PSBtb3VudHMubGVuZ3RoKSB7CiAgICAgICAgICAgIGRvQ2FsbGJhY2sobnVsbCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG1vdW50cy5mb3JFYWNoKGZ1bmN0aW9uIChtb3VudCkgewogICAgICAgICAgaWYgKCFtb3VudC50eXBlLnN5bmNmcykgewogICAgICAgICAgICByZXR1cm4gZG9uZShudWxsKQogICAgICAgICAgfQogICAgICAgICAgbW91bnQudHlwZS5zeW5jZnMobW91bnQsIHBvcHVsYXRlLCBkb25lKTsKICAgICAgICB9KTsKICAgICAgfSwKICAgICAgbW91bnQ6IGZ1bmN0aW9uICh0eXBlLCBvcHRzLCBtb3VudHBvaW50KSB7CiAgICAgICAgdmFyIHJvb3QgPSBtb3VudHBvaW50ID09PSAnLyc7CiAgICAgICAgdmFyIHBzZXVkbyA9ICFtb3VudHBvaW50OwogICAgICAgIHZhciBub2RlOwogICAgICAgIGlmIChyb290ICYmIEZTLnJvb3QpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVCVVNZKQogICAgICAgIH0gZWxzZSBpZiAoIXJvb3QgJiYgIXBzZXVkbykgewogICAgICAgICAgdmFyIGxvb2t1cCA9IEZTLmxvb2t1cFBhdGgobW91bnRwb2ludCwgeyBmb2xsb3dfbW91bnQ6IGZhbHNlIH0pOwogICAgICAgICAgbW91bnRwb2ludCA9IGxvb2t1cC5wYXRoOwogICAgICAgICAgbm9kZSA9IGxvb2t1cC5ub2RlOwogICAgICAgICAgaWYgKEZTLmlzTW91bnRwb2ludChub2RlKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FQlVTWSkKICAgICAgICAgIH0KICAgICAgICAgIGlmICghRlMuaXNEaXIobm9kZS5tb2RlKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTk9URElSKQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB2YXIgbW91bnQgPSB7IHR5cGU6IHR5cGUsIG9wdHM6IG9wdHMsIG1vdW50cG9pbnQ6IG1vdW50cG9pbnQsIG1vdW50czogW10gfTsKICAgICAgICB2YXIgbW91bnRSb290ID0gdHlwZS5tb3VudChtb3VudCk7CiAgICAgICAgbW91bnRSb290Lm1vdW50ID0gbW91bnQ7CiAgICAgICAgbW91bnQucm9vdCA9IG1vdW50Um9vdDsKICAgICAgICBpZiAocm9vdCkgewogICAgICAgICAgRlMucm9vdCA9IG1vdW50Um9vdDsKICAgICAgICB9IGVsc2UgaWYgKG5vZGUpIHsKICAgICAgICAgIG5vZGUubW91bnRlZCA9IG1vdW50OwogICAgICAgICAgaWYgKG5vZGUubW91bnQpIHsKICAgICAgICAgICAgbm9kZS5tb3VudC5tb3VudHMucHVzaChtb3VudCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBtb3VudFJvb3QKICAgICAgfSwKICAgICAgdW5tb3VudDogZnVuY3Rpb24gKG1vdW50cG9pbnQpIHsKICAgICAgICB2YXIgbG9va3VwID0gRlMubG9va3VwUGF0aChtb3VudHBvaW50LCB7IGZvbGxvd19tb3VudDogZmFsc2UgfSk7CiAgICAgICAgaWYgKCFGUy5pc01vdW50cG9pbnQobG9va3VwLm5vZGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FSU5WQUwpCiAgICAgICAgfQogICAgICAgIHZhciBub2RlID0gbG9va3VwLm5vZGU7CiAgICAgICAgdmFyIG1vdW50ID0gbm9kZS5tb3VudGVkOwogICAgICAgIHZhciBtb3VudHMgPSBGUy5nZXRNb3VudHMobW91bnQpOwogICAgICAgIE9iamVjdC5rZXlzKEZTLm5hbWVUYWJsZSkuZm9yRWFjaChmdW5jdGlvbiAoaGFzaCkgewogICAgICAgICAgdmFyIGN1cnJlbnQgPSBGUy5uYW1lVGFibGVbaGFzaF07CiAgICAgICAgICB3aGlsZSAoY3VycmVudCkgewogICAgICAgICAgICB2YXIgbmV4dCA9IGN1cnJlbnQubmFtZV9uZXh0OwogICAgICAgICAgICBpZiAobW91bnRzLmluZGV4T2YoY3VycmVudC5tb3VudCkgIT09IC0xKSB7CiAgICAgICAgICAgICAgRlMuZGVzdHJveU5vZGUoY3VycmVudCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY3VycmVudCA9IG5leHQ7CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgICAgbm9kZS5tb3VudGVkID0gbnVsbDsKICAgICAgICB2YXIgaWR4ID0gbm9kZS5tb3VudC5tb3VudHMuaW5kZXhPZihtb3VudCk7CiAgICAgICAgYXNzZXJ0KGlkeCAhPT0gLTEpOwogICAgICAgIG5vZGUubW91bnQubW91bnRzLnNwbGljZShpZHgsIDEpOwogICAgICB9LAogICAgICBsb29rdXA6IGZ1bmN0aW9uIChwYXJlbnQsIG5hbWUpIHsKICAgICAgICByZXR1cm4gcGFyZW50Lm5vZGVfb3BzLmxvb2t1cChwYXJlbnQsIG5hbWUpCiAgICAgIH0sCiAgICAgIG1rbm9kOiBmdW5jdGlvbiAocGF0aCwgbW9kZSwgZGV2KSB7CiAgICAgICAgdmFyIGxvb2t1cCA9IEZTLmxvb2t1cFBhdGgocGF0aCwgeyBwYXJlbnQ6IHRydWUgfSk7CiAgICAgICAgdmFyIHBhcmVudCA9IGxvb2t1cC5ub2RlOwogICAgICAgIHZhciBuYW1lID0gUEFUSC5iYXNlbmFtZShwYXRoKTsKICAgICAgICBpZiAoIW5hbWUgfHwgbmFtZSA9PT0gJy4nIHx8IG5hbWUgPT09ICcuLicpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVJTlZBTCkKICAgICAgICB9CiAgICAgICAgdmFyIGVyciA9IEZTLm1heUNyZWF0ZShwYXJlbnQsIG5hbWUpOwogICAgICAgIGlmIChlcnIpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKGVycikKICAgICAgICB9CiAgICAgICAgaWYgKCFwYXJlbnQubm9kZV9vcHMubWtub2QpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVQRVJNKQogICAgICAgIH0KICAgICAgICByZXR1cm4gcGFyZW50Lm5vZGVfb3BzLm1rbm9kKHBhcmVudCwgbmFtZSwgbW9kZSwgZGV2KQogICAgICB9LAogICAgICBjcmVhdGU6IGZ1bmN0aW9uIChwYXRoLCBtb2RlKSB7CiAgICAgICAgbW9kZSA9IG1vZGUgIT09IHVuZGVmaW5lZCA/IG1vZGUgOiA0Mzg7CiAgICAgICAgbW9kZSAmPSA0MDk1OwogICAgICAgIG1vZGUgfD0gMzI3Njg7CiAgICAgICAgcmV0dXJuIEZTLm1rbm9kKHBhdGgsIG1vZGUsIDApCiAgICAgIH0sCiAgICAgIG1rZGlyOiBmdW5jdGlvbiAocGF0aCwgbW9kZSkgewogICAgICAgIG1vZGUgPSBtb2RlICE9PSB1bmRlZmluZWQgPyBtb2RlIDogNTExOwogICAgICAgIG1vZGUgJj0gNTExIHwgNTEyOwogICAgICAgIG1vZGUgfD0gMTYzODQ7CiAgICAgICAgcmV0dXJuIEZTLm1rbm9kKHBhdGgsIG1vZGUsIDApCiAgICAgIH0sCiAgICAgIG1rZGlyVHJlZTogZnVuY3Rpb24gKHBhdGgsIG1vZGUpIHsKICAgICAgICB2YXIgZGlycyA9IHBhdGguc3BsaXQoJy8nKTsKICAgICAgICB2YXIgZCA9ICcnOwogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGlycy5sZW5ndGg7ICsraSkgewogICAgICAgICAgaWYgKCFkaXJzW2ldKSBjb250aW51ZQogICAgICAgICAgZCArPSAnLycgKyBkaXJzW2ldOwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgRlMubWtkaXIoZCwgbW9kZSk7CiAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIGlmIChlLmVycm5vICE9IEVSUk5PX0NPREVTLkVFWElTVCkgdGhyb3cgZQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgbWtkZXY6IGZ1bmN0aW9uIChwYXRoLCBtb2RlLCBkZXYpIHsKICAgICAgICBpZiAodHlwZW9mIGRldiA9PT0gJ3VuZGVmaW5lZCcpIHsKICAgICAgICAgIGRldiA9IG1vZGU7CiAgICAgICAgICBtb2RlID0gNDM4OwogICAgICAgIH0KICAgICAgICBtb2RlIHw9IDgxOTI7CiAgICAgICAgcmV0dXJuIEZTLm1rbm9kKHBhdGgsIG1vZGUsIGRldikKICAgICAgfSwKICAgICAgc3ltbGluazogZnVuY3Rpb24gKG9sZHBhdGgsIG5ld3BhdGgpIHsKICAgICAgICBpZiAoIVBBVEgucmVzb2x2ZShvbGRwYXRoKSkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRU5PRU5UKQogICAgICAgIH0KICAgICAgICB2YXIgbG9va3VwID0gRlMubG9va3VwUGF0aChuZXdwYXRoLCB7IHBhcmVudDogdHJ1ZSB9KTsKICAgICAgICB2YXIgcGFyZW50ID0gbG9va3VwLm5vZGU7CiAgICAgICAgaWYgKCFwYXJlbnQpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVOT0VOVCkKICAgICAgICB9CiAgICAgICAgdmFyIG5ld25hbWUgPSBQQVRILmJhc2VuYW1lKG5ld3BhdGgpOwogICAgICAgIHZhciBlcnIgPSBGUy5tYXlDcmVhdGUocGFyZW50LCBuZXduYW1lKTsKICAgICAgICBpZiAoZXJyKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihlcnIpCiAgICAgICAgfQogICAgICAgIGlmICghcGFyZW50Lm5vZGVfb3BzLnN5bWxpbmspIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVQRVJNKQogICAgICAgIH0KICAgICAgICByZXR1cm4gcGFyZW50Lm5vZGVfb3BzLnN5bWxpbmsocGFyZW50LCBuZXduYW1lLCBvbGRwYXRoKQogICAgICB9LAogICAgICByZW5hbWU6IGZ1bmN0aW9uIChvbGRfcGF0aCwgbmV3X3BhdGgpIHsKICAgICAgICB2YXIgb2xkX2Rpcm5hbWUgPSBQQVRILmRpcm5hbWUob2xkX3BhdGgpOwogICAgICAgIHZhciBuZXdfZGlybmFtZSA9IFBBVEguZGlybmFtZShuZXdfcGF0aCk7CiAgICAgICAgdmFyIG9sZF9uYW1lID0gUEFUSC5iYXNlbmFtZShvbGRfcGF0aCk7CiAgICAgICAgdmFyIG5ld19uYW1lID0gUEFUSC5iYXNlbmFtZShuZXdfcGF0aCk7CiAgICAgICAgdmFyIGxvb2t1cCwgb2xkX2RpciwgbmV3X2RpcjsKICAgICAgICB0cnkgewogICAgICAgICAgbG9va3VwID0gRlMubG9va3VwUGF0aChvbGRfcGF0aCwgeyBwYXJlbnQ6IHRydWUgfSk7CiAgICAgICAgICBvbGRfZGlyID0gbG9va3VwLm5vZGU7CiAgICAgICAgICBsb29rdXAgPSBGUy5sb29rdXBQYXRoKG5ld19wYXRoLCB7IHBhcmVudDogdHJ1ZSB9KTsKICAgICAgICAgIG5ld19kaXIgPSBsb29rdXAubm9kZTsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FQlVTWSkKICAgICAgICB9CiAgICAgICAgaWYgKCFvbGRfZGlyIHx8ICFuZXdfZGlyKSB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTk9FTlQpCiAgICAgICAgaWYgKG9sZF9kaXIubW91bnQgIT09IG5ld19kaXIubW91bnQpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVYREVWKQogICAgICAgIH0KICAgICAgICB2YXIgb2xkX25vZGUgPSBGUy5sb29rdXBOb2RlKG9sZF9kaXIsIG9sZF9uYW1lKTsKICAgICAgICB2YXIgcmVsYXRpdmUgPSBQQVRILnJlbGF0aXZlKG9sZF9wYXRoLCBuZXdfZGlybmFtZSk7CiAgICAgICAgaWYgKHJlbGF0aXZlLmNoYXJBdCgwKSAhPT0gJy4nKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FSU5WQUwpCiAgICAgICAgfQogICAgICAgIHJlbGF0aXZlID0gUEFUSC5yZWxhdGl2ZShuZXdfcGF0aCwgb2xkX2Rpcm5hbWUpOwogICAgICAgIGlmIChyZWxhdGl2ZS5jaGFyQXQoMCkgIT09ICcuJykgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRU5PVEVNUFRZKQogICAgICAgIH0KICAgICAgICB2YXIgbmV3X25vZGU7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIG5ld19ub2RlID0gRlMubG9va3VwTm9kZShuZXdfZGlyLCBuZXdfbmFtZSk7CiAgICAgICAgfSBjYXRjaCAoZSkge30KICAgICAgICBpZiAob2xkX25vZGUgPT09IG5ld19ub2RlKSB7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgdmFyIGlzZGlyID0gRlMuaXNEaXIob2xkX25vZGUubW9kZSk7CiAgICAgICAgdmFyIGVyciA9IEZTLm1heURlbGV0ZShvbGRfZGlyLCBvbGRfbmFtZSwgaXNkaXIpOwogICAgICAgIGlmIChlcnIpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKGVycikKICAgICAgICB9CiAgICAgICAgZXJyID0gbmV3X25vZGUgPyBGUy5tYXlEZWxldGUobmV3X2RpciwgbmV3X25hbWUsIGlzZGlyKSA6IEZTLm1heUNyZWF0ZShuZXdfZGlyLCBuZXdfbmFtZSk7CiAgICAgICAgaWYgKGVycikgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoZXJyKQogICAgICAgIH0KICAgICAgICBpZiAoIW9sZF9kaXIubm9kZV9vcHMucmVuYW1lKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FUEVSTSkKICAgICAgICB9CiAgICAgICAgaWYgKEZTLmlzTW91bnRwb2ludChvbGRfbm9kZSkgfHwgKG5ld19ub2RlICYmIEZTLmlzTW91bnRwb2ludChuZXdfbm9kZSkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FQlVTWSkKICAgICAgICB9CiAgICAgICAgaWYgKG5ld19kaXIgIT09IG9sZF9kaXIpIHsKICAgICAgICAgIGVyciA9IEZTLm5vZGVQZXJtaXNzaW9ucyhvbGRfZGlyLCAndycpOwogICAgICAgICAgaWYgKGVycikgewogICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihlcnIpCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBpZiAoRlMudHJhY2tpbmdEZWxlZ2F0ZVsnd2lsbE1vdmVQYXRoJ10pIHsKICAgICAgICAgICAgRlMudHJhY2tpbmdEZWxlZ2F0ZVsnd2lsbE1vdmVQYXRoJ10ob2xkX3BhdGgsIG5ld19wYXRoKTsKICAgICAgICAgIH0KICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICBjb25zb2xlLmxvZygKICAgICAgICAgICAgIkZTLnRyYWNraW5nRGVsZWdhdGVbJ3dpbGxNb3ZlUGF0aCddKCciICsgb2xkX3BhdGggKyAiJywgJyIgKyBuZXdfcGF0aCArICInKSB0aHJldyBhbiBleGNlcHRpb246ICIgKyBlLm1lc3NhZ2UKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIEZTLmhhc2hSZW1vdmVOb2RlKG9sZF9ub2RlKTsKICAgICAgICB0cnkgewogICAgICAgICAgb2xkX2Rpci5ub2RlX29wcy5yZW5hbWUob2xkX25vZGUsIG5ld19kaXIsIG5ld19uYW1lKTsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICB0aHJvdyBlCiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIEZTLmhhc2hBZGROb2RlKG9sZF9ub2RlKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGlmIChGUy50cmFja2luZ0RlbGVnYXRlWydvbk1vdmVQYXRoJ10pIEZTLnRyYWNraW5nRGVsZWdhdGVbJ29uTW92ZVBhdGgnXShvbGRfcGF0aCwgbmV3X3BhdGgpOwogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIGNvbnNvbGUubG9nKAogICAgICAgICAgICAiRlMudHJhY2tpbmdEZWxlZ2F0ZVsnb25Nb3ZlUGF0aCddKCciICsgb2xkX3BhdGggKyAiJywgJyIgKyBuZXdfcGF0aCArICInKSB0aHJldyBhbiBleGNlcHRpb246ICIgKyBlLm1lc3NhZ2UKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICB9LAogICAgICBybWRpcjogZnVuY3Rpb24gKHBhdGgpIHsKICAgICAgICB2YXIgbG9va3VwID0gRlMubG9va3VwUGF0aChwYXRoLCB7IHBhcmVudDogdHJ1ZSB9KTsKICAgICAgICB2YXIgcGFyZW50ID0gbG9va3VwLm5vZGU7CiAgICAgICAgdmFyIG5hbWUgPSBQQVRILmJhc2VuYW1lKHBhdGgpOwogICAgICAgIHZhciBub2RlID0gRlMubG9va3VwTm9kZShwYXJlbnQsIG5hbWUpOwogICAgICAgIHZhciBlcnIgPSBGUy5tYXlEZWxldGUocGFyZW50LCBuYW1lLCB0cnVlKTsKICAgICAgICBpZiAoZXJyKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihlcnIpCiAgICAgICAgfQogICAgICAgIGlmICghcGFyZW50Lm5vZGVfb3BzLnJtZGlyKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FUEVSTSkKICAgICAgICB9CiAgICAgICAgaWYgKEZTLmlzTW91bnRwb2ludChub2RlKSkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUJVU1kpCiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBpZiAoRlMudHJhY2tpbmdEZWxlZ2F0ZVsnd2lsbERlbGV0ZVBhdGgnXSkgewogICAgICAgICAgICBGUy50cmFja2luZ0RlbGVnYXRlWyd3aWxsRGVsZXRlUGF0aCddKHBhdGgpOwogICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIGNvbnNvbGUubG9nKCJGUy50cmFja2luZ0RlbGVnYXRlWyd3aWxsRGVsZXRlUGF0aCddKCciICsgcGF0aCArICInKSB0aHJldyBhbiBleGNlcHRpb246ICIgKyBlLm1lc3NhZ2UpOwogICAgICAgIH0KICAgICAgICBwYXJlbnQubm9kZV9vcHMucm1kaXIocGFyZW50LCBuYW1lKTsKICAgICAgICBGUy5kZXN0cm95Tm9kZShub2RlKTsKICAgICAgICB0cnkgewogICAgICAgICAgaWYgKEZTLnRyYWNraW5nRGVsZWdhdGVbJ29uRGVsZXRlUGF0aCddKSBGUy50cmFja2luZ0RlbGVnYXRlWydvbkRlbGV0ZVBhdGgnXShwYXRoKTsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICBjb25zb2xlLmxvZygiRlMudHJhY2tpbmdEZWxlZ2F0ZVsnb25EZWxldGVQYXRoJ10oJyIgKyBwYXRoICsgIicpIHRocmV3IGFuIGV4Y2VwdGlvbjogIiArIGUubWVzc2FnZSk7CiAgICAgICAgfQogICAgICB9LAogICAgICByZWFkZGlyOiBmdW5jdGlvbiAocGF0aCkgewogICAgICAgIHZhciBsb29rdXAgPSBGUy5sb29rdXBQYXRoKHBhdGgsIHsgZm9sbG93OiB0cnVlIH0pOwogICAgICAgIHZhciBub2RlID0gbG9va3VwLm5vZGU7CiAgICAgICAgaWYgKCFub2RlLm5vZGVfb3BzLnJlYWRkaXIpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVOT1RESVIpCiAgICAgICAgfQogICAgICAgIHJldHVybiBub2RlLm5vZGVfb3BzLnJlYWRkaXIobm9kZSkKICAgICAgfSwKICAgICAgdW5saW5rOiBmdW5jdGlvbiAocGF0aCkgewogICAgICAgIHZhciBsb29rdXAgPSBGUy5sb29rdXBQYXRoKHBhdGgsIHsgcGFyZW50OiB0cnVlIH0pOwogICAgICAgIHZhciBwYXJlbnQgPSBsb29rdXAubm9kZTsKICAgICAgICB2YXIgbmFtZSA9IFBBVEguYmFzZW5hbWUocGF0aCk7CiAgICAgICAgdmFyIG5vZGUgPSBGUy5sb29rdXBOb2RlKHBhcmVudCwgbmFtZSk7CiAgICAgICAgdmFyIGVyciA9IEZTLm1heURlbGV0ZShwYXJlbnQsIG5hbWUsIGZhbHNlKTsKICAgICAgICBpZiAoZXJyKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihlcnIpCiAgICAgICAgfQogICAgICAgIGlmICghcGFyZW50Lm5vZGVfb3BzLnVubGluaykgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRVBFUk0pCiAgICAgICAgfQogICAgICAgIGlmIChGUy5pc01vdW50cG9pbnQobm9kZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVCVVNZKQogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgaWYgKEZTLnRyYWNraW5nRGVsZWdhdGVbJ3dpbGxEZWxldGVQYXRoJ10pIHsKICAgICAgICAgICAgRlMudHJhY2tpbmdEZWxlZ2F0ZVsnd2lsbERlbGV0ZVBhdGgnXShwYXRoKTsKICAgICAgICAgIH0KICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICBjb25zb2xlLmxvZygiRlMudHJhY2tpbmdEZWxlZ2F0ZVsnd2lsbERlbGV0ZVBhdGgnXSgnIiArIHBhdGggKyAiJykgdGhyZXcgYW4gZXhjZXB0aW9uOiAiICsgZS5tZXNzYWdlKTsKICAgICAgICB9CiAgICAgICAgcGFyZW50Lm5vZGVfb3BzLnVubGluayhwYXJlbnQsIG5hbWUpOwogICAgICAgIEZTLmRlc3Ryb3lOb2RlKG5vZGUpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBpZiAoRlMudHJhY2tpbmdEZWxlZ2F0ZVsnb25EZWxldGVQYXRoJ10pIEZTLnRyYWNraW5nRGVsZWdhdGVbJ29uRGVsZXRlUGF0aCddKHBhdGgpOwogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIGNvbnNvbGUubG9nKCJGUy50cmFja2luZ0RlbGVnYXRlWydvbkRlbGV0ZVBhdGgnXSgnIiArIHBhdGggKyAiJykgdGhyZXcgYW4gZXhjZXB0aW9uOiAiICsgZS5tZXNzYWdlKTsKICAgICAgICB9CiAgICAgIH0sCiAgICAgIHJlYWRsaW5rOiBmdW5jdGlvbiAocGF0aCkgewogICAgICAgIHZhciBsb29rdXAgPSBGUy5sb29rdXBQYXRoKHBhdGgpOwogICAgICAgIHZhciBsaW5rID0gbG9va3VwLm5vZGU7CiAgICAgICAgaWYgKCFsaW5rKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTk9FTlQpCiAgICAgICAgfQogICAgICAgIGlmICghbGluay5ub2RlX29wcy5yZWFkbGluaykgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUlOVkFMKQogICAgICAgIH0KICAgICAgICByZXR1cm4gUEFUSC5yZXNvbHZlKEZTLmdldFBhdGgobGluay5wYXJlbnQpLCBsaW5rLm5vZGVfb3BzLnJlYWRsaW5rKGxpbmspKQogICAgICB9LAogICAgICBzdGF0OiBmdW5jdGlvbiAocGF0aCwgZG9udEZvbGxvdykgewogICAgICAgIHZhciBsb29rdXAgPSBGUy5sb29rdXBQYXRoKHBhdGgsIHsgZm9sbG93OiAhZG9udEZvbGxvdyB9KTsKICAgICAgICB2YXIgbm9kZSA9IGxvb2t1cC5ub2RlOwogICAgICAgIGlmICghbm9kZSkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRU5PRU5UKQogICAgICAgIH0KICAgICAgICBpZiAoIW5vZGUubm9kZV9vcHMuZ2V0YXR0cikgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRVBFUk0pCiAgICAgICAgfQogICAgICAgIHJldHVybiBub2RlLm5vZGVfb3BzLmdldGF0dHIobm9kZSkKICAgICAgfSwKICAgICAgbHN0YXQ6IGZ1bmN0aW9uIChwYXRoKSB7CiAgICAgICAgcmV0dXJuIEZTLnN0YXQocGF0aCwgdHJ1ZSkKICAgICAgfSwKICAgICAgY2htb2Q6IGZ1bmN0aW9uIChwYXRoLCBtb2RlLCBkb250Rm9sbG93KSB7CiAgICAgICAgdmFyIG5vZGU7CiAgICAgICAgaWYgKHR5cGVvZiBwYXRoID09PSAnc3RyaW5nJykgewogICAgICAgICAgdmFyIGxvb2t1cCA9IEZTLmxvb2t1cFBhdGgocGF0aCwgeyBmb2xsb3c6ICFkb250Rm9sbG93IH0pOwogICAgICAgICAgbm9kZSA9IGxvb2t1cC5ub2RlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBub2RlID0gcGF0aDsKICAgICAgICB9CiAgICAgICAgaWYgKCFub2RlLm5vZGVfb3BzLnNldGF0dHIpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVQRVJNKQogICAgICAgIH0KICAgICAgICBub2RlLm5vZGVfb3BzLnNldGF0dHIobm9kZSwgeyBtb2RlOiAobW9kZSAmIDQwOTUpIHwgKG5vZGUubW9kZSAmIH40MDk1KSwgdGltZXN0YW1wOiBEYXRlLm5vdygpIH0pOwogICAgICB9LAogICAgICBsY2htb2Q6IGZ1bmN0aW9uIChwYXRoLCBtb2RlKSB7CiAgICAgICAgRlMuY2htb2QocGF0aCwgbW9kZSwgdHJ1ZSk7CiAgICAgIH0sCiAgICAgIGZjaG1vZDogZnVuY3Rpb24gKGZkLCBtb2RlKSB7CiAgICAgICAgdmFyIHN0cmVhbSA9IEZTLmdldFN0cmVhbShmZCk7CiAgICAgICAgaWYgKCFzdHJlYW0pIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVCQURGKQogICAgICAgIH0KICAgICAgICBGUy5jaG1vZChzdHJlYW0ubm9kZSwgbW9kZSk7CiAgICAgIH0sCiAgICAgIGNob3duOiBmdW5jdGlvbiAocGF0aCwgdWlkLCBnaWQsIGRvbnRGb2xsb3cpIHsKICAgICAgICB2YXIgbm9kZTsKICAgICAgICBpZiAodHlwZW9mIHBhdGggPT09ICdzdHJpbmcnKSB7CiAgICAgICAgICB2YXIgbG9va3VwID0gRlMubG9va3VwUGF0aChwYXRoLCB7IGZvbGxvdzogIWRvbnRGb2xsb3cgfSk7CiAgICAgICAgICBub2RlID0gbG9va3VwLm5vZGU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG5vZGUgPSBwYXRoOwogICAgICAgIH0KICAgICAgICBpZiAoIW5vZGUubm9kZV9vcHMuc2V0YXR0cikgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRVBFUk0pCiAgICAgICAgfQogICAgICAgIG5vZGUubm9kZV9vcHMuc2V0YXR0cihub2RlLCB7IHRpbWVzdGFtcDogRGF0ZS5ub3coKSB9KTsKICAgICAgfSwKICAgICAgbGNob3duOiBmdW5jdGlvbiAocGF0aCwgdWlkLCBnaWQpIHsKICAgICAgICBGUy5jaG93bihwYXRoLCB1aWQsIGdpZCwgdHJ1ZSk7CiAgICAgIH0sCiAgICAgIGZjaG93bjogZnVuY3Rpb24gKGZkLCB1aWQsIGdpZCkgewogICAgICAgIHZhciBzdHJlYW0gPSBGUy5nZXRTdHJlYW0oZmQpOwogICAgICAgIGlmICghc3RyZWFtKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FQkFERikKICAgICAgICB9CiAgICAgICAgRlMuY2hvd24oc3RyZWFtLm5vZGUsIHVpZCwgZ2lkKTsKICAgICAgfSwKICAgICAgdHJ1bmNhdGU6IGZ1bmN0aW9uIChwYXRoLCBsZW4pIHsKICAgICAgICBpZiAobGVuIDwgMCkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUlOVkFMKQogICAgICAgIH0KICAgICAgICB2YXIgbm9kZTsKICAgICAgICBpZiAodHlwZW9mIHBhdGggPT09ICdzdHJpbmcnKSB7CiAgICAgICAgICB2YXIgbG9va3VwID0gRlMubG9va3VwUGF0aChwYXRoLCB7IGZvbGxvdzogdHJ1ZSB9KTsKICAgICAgICAgIG5vZGUgPSBsb29rdXAubm9kZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbm9kZSA9IHBhdGg7CiAgICAgICAgfQogICAgICAgIGlmICghbm9kZS5ub2RlX29wcy5zZXRhdHRyKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FUEVSTSkKICAgICAgICB9CiAgICAgICAgaWYgKEZTLmlzRGlyKG5vZGUubW9kZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVJU0RJUikKICAgICAgICB9CiAgICAgICAgaWYgKCFGUy5pc0ZpbGUobm9kZS5tb2RlKSkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUlOVkFMKQogICAgICAgIH0KICAgICAgICB2YXIgZXJyID0gRlMubm9kZVBlcm1pc3Npb25zKG5vZGUsICd3Jyk7CiAgICAgICAgaWYgKGVycikgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoZXJyKQogICAgICAgIH0KICAgICAgICBub2RlLm5vZGVfb3BzLnNldGF0dHIobm9kZSwgeyBzaXplOiBsZW4sIHRpbWVzdGFtcDogRGF0ZS5ub3coKSB9KTsKICAgICAgfSwKICAgICAgZnRydW5jYXRlOiBmdW5jdGlvbiAoZmQsIGxlbikgewogICAgICAgIHZhciBzdHJlYW0gPSBGUy5nZXRTdHJlYW0oZmQpOwogICAgICAgIGlmICghc3RyZWFtKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FQkFERikKICAgICAgICB9CiAgICAgICAgaWYgKChzdHJlYW0uZmxhZ3MgJiAyMDk3MTU1KSA9PT0gMCkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUlOVkFMKQogICAgICAgIH0KICAgICAgICBGUy50cnVuY2F0ZShzdHJlYW0ubm9kZSwgbGVuKTsKICAgICAgfSwKICAgICAgdXRpbWU6IGZ1bmN0aW9uIChwYXRoLCBhdGltZSwgbXRpbWUpIHsKICAgICAgICB2YXIgbG9va3VwID0gRlMubG9va3VwUGF0aChwYXRoLCB7IGZvbGxvdzogdHJ1ZSB9KTsKICAgICAgICB2YXIgbm9kZSA9IGxvb2t1cC5ub2RlOwogICAgICAgIG5vZGUubm9kZV9vcHMuc2V0YXR0cihub2RlLCB7IHRpbWVzdGFtcDogTWF0aC5tYXgoYXRpbWUsIG10aW1lKSB9KTsKICAgICAgfSwKICAgICAgb3BlbjogZnVuY3Rpb24gKHBhdGgsIGZsYWdzLCBtb2RlLCBmZF9zdGFydCwgZmRfZW5kKSB7CiAgICAgICAgaWYgKHBhdGggPT09ICcnKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTk9FTlQpCiAgICAgICAgfQogICAgICAgIGZsYWdzID0gdHlwZW9mIGZsYWdzID09PSAnc3RyaW5nJyA/IEZTLm1vZGVTdHJpbmdUb0ZsYWdzKGZsYWdzKSA6IGZsYWdzOwogICAgICAgIG1vZGUgPSB0eXBlb2YgbW9kZSA9PT0gJ3VuZGVmaW5lZCcgPyA0MzggOiBtb2RlOwogICAgICAgIGlmIChmbGFncyAmIDY0KSB7CiAgICAgICAgICBtb2RlID0gKG1vZGUgJiA0MDk1KSB8IDMyNzY4OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBtb2RlID0gMDsKICAgICAgICB9CiAgICAgICAgdmFyIG5vZGU7CiAgICAgICAgaWYgKHR5cGVvZiBwYXRoID09PSAnb2JqZWN0JykgewogICAgICAgICAgbm9kZSA9IHBhdGg7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHBhdGggPSBQQVRILm5vcm1hbGl6ZShwYXRoKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHZhciBsb29rdXAgPSBGUy5sb29rdXBQYXRoKHBhdGgsIHsgZm9sbG93OiAhKGZsYWdzICYgMTMxMDcyKSB9KTsKICAgICAgICAgICAgbm9kZSA9IGxvb2t1cC5ub2RlOwogICAgICAgICAgfSBjYXRjaCAoZSkge30KICAgICAgICB9CiAgICAgICAgdmFyIGNyZWF0ZWQgPSBmYWxzZTsKICAgICAgICBpZiAoZmxhZ3MgJiA2NCkgewogICAgICAgICAgaWYgKG5vZGUpIHsKICAgICAgICAgICAgaWYgKGZsYWdzICYgMTI4KSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUVYSVNUKQogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBub2RlID0gRlMubWtub2QocGF0aCwgbW9kZSwgMCk7CiAgICAgICAgICAgIGNyZWF0ZWQgPSB0cnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoIW5vZGUpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVOT0VOVCkKICAgICAgICB9CiAgICAgICAgaWYgKEZTLmlzQ2hyZGV2KG5vZGUubW9kZSkpIHsKICAgICAgICAgIGZsYWdzICY9IH41MTI7CiAgICAgICAgfQogICAgICAgIGlmIChmbGFncyAmIDY1NTM2ICYmICFGUy5pc0Rpcihub2RlLm1vZGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTk9URElSKQogICAgICAgIH0KICAgICAgICBpZiAoIWNyZWF0ZWQpIHsKICAgICAgICAgIHZhciBlcnIgPSBGUy5tYXlPcGVuKG5vZGUsIGZsYWdzKTsKICAgICAgICAgIGlmIChlcnIpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoZXJyKQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoZmxhZ3MgJiA1MTIpIHsKICAgICAgICAgIEZTLnRydW5jYXRlKG5vZGUsIDApOwogICAgICAgIH0KICAgICAgICBmbGFncyAmPSB+KDEyOCB8IDUxMik7CiAgICAgICAgdmFyIHN0cmVhbSA9IEZTLmNyZWF0ZVN0cmVhbSgKICAgICAgICAgIHsKICAgICAgICAgICAgbm9kZTogbm9kZSwKICAgICAgICAgICAgcGF0aDogRlMuZ2V0UGF0aChub2RlKSwKICAgICAgICAgICAgZmxhZ3M6IGZsYWdzLAogICAgICAgICAgICBzZWVrYWJsZTogdHJ1ZSwKICAgICAgICAgICAgcG9zaXRpb246IDAsCiAgICAgICAgICAgIHN0cmVhbV9vcHM6IG5vZGUuc3RyZWFtX29wcywKICAgICAgICAgICAgdW5nb3R0ZW46IFtdLAogICAgICAgICAgICBlcnJvcjogZmFsc2UsCiAgICAgICAgICB9LAogICAgICAgICAgZmRfc3RhcnQsCiAgICAgICAgICBmZF9lbmQKICAgICAgICApOwogICAgICAgIGlmIChzdHJlYW0uc3RyZWFtX29wcy5vcGVuKSB7CiAgICAgICAgICBzdHJlYW0uc3RyZWFtX29wcy5vcGVuKHN0cmVhbSk7CiAgICAgICAgfQogICAgICAgIGlmIChNb2R1bGVbJ2xvZ1JlYWRGaWxlcyddICYmICEoZmxhZ3MgJiAxKSkgewogICAgICAgICAgaWYgKCFGUy5yZWFkRmlsZXMpIEZTLnJlYWRGaWxlcyA9IHt9OwogICAgICAgICAgaWYgKCEocGF0aCBpbiBGUy5yZWFkRmlsZXMpKSB7CiAgICAgICAgICAgIEZTLnJlYWRGaWxlc1twYXRoXSA9IDE7CiAgICAgICAgICAgIE1vZHVsZVsncHJpbnRFcnInXSgncmVhZCBmaWxlOiAnICsgcGF0aCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICBpZiAoRlMudHJhY2tpbmdEZWxlZ2F0ZVsnb25PcGVuRmlsZSddKSB7CiAgICAgICAgICAgIHZhciB0cmFja2luZ0ZsYWdzID0gMDsKICAgICAgICAgICAgaWYgKChmbGFncyAmIDIwOTcxNTUpICE9PSAxKSB7CiAgICAgICAgICAgICAgdHJhY2tpbmdGbGFncyB8PSBGUy50cmFja2luZy5vcGVuRmxhZ3MuUkVBRDsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoKGZsYWdzICYgMjA5NzE1NSkgIT09IDApIHsKICAgICAgICAgICAgICB0cmFja2luZ0ZsYWdzIHw9IEZTLnRyYWNraW5nLm9wZW5GbGFncy5XUklURTsKICAgICAgICAgICAgfQogICAgICAgICAgICBGUy50cmFja2luZ0RlbGVnYXRlWydvbk9wZW5GaWxlJ10ocGF0aCwgdHJhY2tpbmdGbGFncyk7CiAgICAgICAgICB9CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgY29uc29sZS5sb2coIkZTLnRyYWNraW5nRGVsZWdhdGVbJ29uT3BlbkZpbGUnXSgnIiArIHBhdGggKyAiJywgZmxhZ3MpIHRocmV3IGFuIGV4Y2VwdGlvbjogIiArIGUubWVzc2FnZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzdHJlYW0KICAgICAgfSwKICAgICAgY2xvc2U6IGZ1bmN0aW9uIChzdHJlYW0pIHsKICAgICAgICBpZiAoRlMuaXNDbG9zZWQoc3RyZWFtKSkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUJBREYpCiAgICAgICAgfQogICAgICAgIGlmIChzdHJlYW0uZ2V0ZGVudHMpIHN0cmVhbS5nZXRkZW50cyA9IG51bGw7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGlmIChzdHJlYW0uc3RyZWFtX29wcy5jbG9zZSkgewogICAgICAgICAgICBzdHJlYW0uc3RyZWFtX29wcy5jbG9zZShzdHJlYW0pOwogICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIHRocm93IGUKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgRlMuY2xvc2VTdHJlYW0oc3RyZWFtLmZkKTsKICAgICAgICB9CiAgICAgICAgc3RyZWFtLmZkID0gbnVsbDsKICAgICAgfSwKICAgICAgaXNDbG9zZWQ6IGZ1bmN0aW9uIChzdHJlYW0pIHsKICAgICAgICByZXR1cm4gc3RyZWFtLmZkID09PSBudWxsCiAgICAgIH0sCiAgICAgIGxsc2VlazogZnVuY3Rpb24gKHN0cmVhbSwgb2Zmc2V0LCB3aGVuY2UpIHsKICAgICAgICBpZiAoRlMuaXNDbG9zZWQoc3RyZWFtKSkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUJBREYpCiAgICAgICAgfQogICAgICAgIGlmICghc3RyZWFtLnNlZWthYmxlIHx8ICFzdHJlYW0uc3RyZWFtX29wcy5sbHNlZWspIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVTUElQRSkKICAgICAgICB9CiAgICAgICAgc3RyZWFtLnBvc2l0aW9uID0gc3RyZWFtLnN0cmVhbV9vcHMubGxzZWVrKHN0cmVhbSwgb2Zmc2V0LCB3aGVuY2UpOwogICAgICAgIHN0cmVhbS51bmdvdHRlbiA9IFtdOwogICAgICAgIHJldHVybiBzdHJlYW0ucG9zaXRpb24KICAgICAgfSwKICAgICAgcmVhZDogZnVuY3Rpb24gKHN0cmVhbSwgYnVmZmVyLCBvZmZzZXQsIGxlbmd0aCwgcG9zaXRpb24pIHsKICAgICAgICBpZiAobGVuZ3RoIDwgMCB8fCBwb3NpdGlvbiA8IDApIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVJTlZBTCkKICAgICAgICB9CiAgICAgICAgaWYgKEZTLmlzQ2xvc2VkKHN0cmVhbSkpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVCQURGKQogICAgICAgIH0KICAgICAgICBpZiAoKHN0cmVhbS5mbGFncyAmIDIwOTcxNTUpID09PSAxKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FQkFERikKICAgICAgICB9CiAgICAgICAgaWYgKEZTLmlzRGlyKHN0cmVhbS5ub2RlLm1vZGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FSVNESVIpCiAgICAgICAgfQogICAgICAgIGlmICghc3RyZWFtLnN0cmVhbV9vcHMucmVhZCkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUlOVkFMKQogICAgICAgIH0KICAgICAgICB2YXIgc2Vla2luZyA9IHR5cGVvZiBwb3NpdGlvbiAhPT0gJ3VuZGVmaW5lZCc7CiAgICAgICAgaWYgKCFzZWVraW5nKSB7CiAgICAgICAgICBwb3NpdGlvbiA9IHN0cmVhbS5wb3NpdGlvbjsKICAgICAgICB9IGVsc2UgaWYgKCFzdHJlYW0uc2Vla2FibGUpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVTUElQRSkKICAgICAgICB9CiAgICAgICAgdmFyIGJ5dGVzUmVhZCA9IHN0cmVhbS5zdHJlYW1fb3BzLnJlYWQoc3RyZWFtLCBidWZmZXIsIG9mZnNldCwgbGVuZ3RoLCBwb3NpdGlvbik7CiAgICAgICAgaWYgKCFzZWVraW5nKSBzdHJlYW0ucG9zaXRpb24gKz0gYnl0ZXNSZWFkOwogICAgICAgIHJldHVybiBieXRlc1JlYWQKICAgICAgfSwKICAgICAgd3JpdGU6IGZ1bmN0aW9uIChzdHJlYW0sIGJ1ZmZlciwgb2Zmc2V0LCBsZW5ndGgsIHBvc2l0aW9uLCBjYW5Pd24pIHsKICAgICAgICBpZiAobGVuZ3RoIDwgMCB8fCBwb3NpdGlvbiA8IDApIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVJTlZBTCkKICAgICAgICB9CiAgICAgICAgaWYgKEZTLmlzQ2xvc2VkKHN0cmVhbSkpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVCQURGKQogICAgICAgIH0KICAgICAgICBpZiAoKHN0cmVhbS5mbGFncyAmIDIwOTcxNTUpID09PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FQkFERikKICAgICAgICB9CiAgICAgICAgaWYgKEZTLmlzRGlyKHN0cmVhbS5ub2RlLm1vZGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FSVNESVIpCiAgICAgICAgfQogICAgICAgIGlmICghc3RyZWFtLnN0cmVhbV9vcHMud3JpdGUpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVJTlZBTCkKICAgICAgICB9CiAgICAgICAgaWYgKHN0cmVhbS5mbGFncyAmIDEwMjQpIHsKICAgICAgICAgIEZTLmxsc2VlayhzdHJlYW0sIDAsIDIpOwogICAgICAgIH0KICAgICAgICB2YXIgc2Vla2luZyA9IHR5cGVvZiBwb3NpdGlvbiAhPT0gJ3VuZGVmaW5lZCc7CiAgICAgICAgaWYgKCFzZWVraW5nKSB7CiAgICAgICAgICBwb3NpdGlvbiA9IHN0cmVhbS5wb3NpdGlvbjsKICAgICAgICB9IGVsc2UgaWYgKCFzdHJlYW0uc2Vla2FibGUpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVTUElQRSkKICAgICAgICB9CiAgICAgICAgdmFyIGJ5dGVzV3JpdHRlbiA9IHN0cmVhbS5zdHJlYW1fb3BzLndyaXRlKHN0cmVhbSwgYnVmZmVyLCBvZmZzZXQsIGxlbmd0aCwgcG9zaXRpb24sIGNhbk93bik7CiAgICAgICAgaWYgKCFzZWVraW5nKSBzdHJlYW0ucG9zaXRpb24gKz0gYnl0ZXNXcml0dGVuOwogICAgICAgIHRyeSB7CiAgICAgICAgICBpZiAoc3RyZWFtLnBhdGggJiYgRlMudHJhY2tpbmdEZWxlZ2F0ZVsnb25Xcml0ZVRvRmlsZSddKSBGUy50cmFja2luZ0RlbGVnYXRlWydvbldyaXRlVG9GaWxlJ10oc3RyZWFtLnBhdGgpOwogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIGNvbnNvbGUubG9nKCJGUy50cmFja2luZ0RlbGVnYXRlWydvbldyaXRlVG9GaWxlJ10oJyIgKyBwYXRoICsgIicpIHRocmV3IGFuIGV4Y2VwdGlvbjogIiArIGUubWVzc2FnZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBieXRlc1dyaXR0ZW4KICAgICAgfSwKICAgICAgYWxsb2NhdGU6IGZ1bmN0aW9uIChzdHJlYW0sIG9mZnNldCwgbGVuZ3RoKSB7CiAgICAgICAgaWYgKEZTLmlzQ2xvc2VkKHN0cmVhbSkpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVCQURGKQogICAgICAgIH0KICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBsZW5ndGggPD0gMCkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUlOVkFMKQogICAgICAgIH0KICAgICAgICBpZiAoKHN0cmVhbS5mbGFncyAmIDIwOTcxNTUpID09PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FQkFERikKICAgICAgICB9CiAgICAgICAgaWYgKCFGUy5pc0ZpbGUoc3RyZWFtLm5vZGUubW9kZSkgJiYgIUZTLmlzRGlyKHN0cmVhbS5ub2RlLm1vZGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTk9ERVYpCiAgICAgICAgfQogICAgICAgIGlmICghc3RyZWFtLnN0cmVhbV9vcHMuYWxsb2NhdGUpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVPUE5PVFNVUFApCiAgICAgICAgfQogICAgICAgIHN0cmVhbS5zdHJlYW1fb3BzLmFsbG9jYXRlKHN0cmVhbSwgb2Zmc2V0LCBsZW5ndGgpOwogICAgICB9LAogICAgICBtbWFwOiBmdW5jdGlvbiAoc3RyZWFtLCBidWZmZXIsIG9mZnNldCwgbGVuZ3RoLCBwb3NpdGlvbiwgcHJvdCwgZmxhZ3MpIHsKICAgICAgICBpZiAoKHN0cmVhbS5mbGFncyAmIDIwOTcxNTUpID09PSAxKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FQUNDRVMpCiAgICAgICAgfQogICAgICAgIGlmICghc3RyZWFtLnN0cmVhbV9vcHMubW1hcCkgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRU5PREVWKQogICAgICAgIH0KICAgICAgICByZXR1cm4gc3RyZWFtLnN0cmVhbV9vcHMubW1hcChzdHJlYW0sIGJ1ZmZlciwgb2Zmc2V0LCBsZW5ndGgsIHBvc2l0aW9uLCBwcm90LCBmbGFncykKICAgICAgfSwKICAgICAgbXN5bmM6IGZ1bmN0aW9uIChzdHJlYW0sIGJ1ZmZlciwgb2Zmc2V0LCBsZW5ndGgsIG1tYXBGbGFncykgewogICAgICAgIGlmICghc3RyZWFtIHx8ICFzdHJlYW0uc3RyZWFtX29wcy5tc3luYykgewogICAgICAgICAgcmV0dXJuIDAKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHN0cmVhbS5zdHJlYW1fb3BzLm1zeW5jKHN0cmVhbSwgYnVmZmVyLCBvZmZzZXQsIGxlbmd0aCwgbW1hcEZsYWdzKQogICAgICB9LAogICAgICBtdW5tYXA6IGZ1bmN0aW9uIChzdHJlYW0pIHsKICAgICAgICByZXR1cm4gMAogICAgICB9LAogICAgICBpb2N0bDogZnVuY3Rpb24gKHN0cmVhbSwgY21kLCBhcmcpIHsKICAgICAgICBpZiAoIXN0cmVhbS5zdHJlYW1fb3BzLmlvY3RsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTk9UVFkpCiAgICAgICAgfQogICAgICAgIHJldHVybiBzdHJlYW0uc3RyZWFtX29wcy5pb2N0bChzdHJlYW0sIGNtZCwgYXJnKQogICAgICB9LAogICAgICByZWFkRmlsZTogZnVuY3Rpb24gKHBhdGgsIG9wdHMpIHsKICAgICAgICBvcHRzID0gb3B0cyB8fCB7fTsKICAgICAgICBvcHRzLmZsYWdzID0gb3B0cy5mbGFncyB8fCAncic7CiAgICAgICAgb3B0cy5lbmNvZGluZyA9IG9wdHMuZW5jb2RpbmcgfHwgJ2JpbmFyeSc7CiAgICAgICAgaWYgKG9wdHMuZW5jb2RpbmcgIT09ICd1dGY4JyAmJiBvcHRzLmVuY29kaW5nICE9PSAnYmluYXJ5JykgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGVuY29kaW5nIHR5cGUgIicgKyBvcHRzLmVuY29kaW5nICsgJyInKQogICAgICAgIH0KICAgICAgICB2YXIgcmV0OwogICAgICAgIHZhciBzdHJlYW0gPSBGUy5vcGVuKHBhdGgsIG9wdHMuZmxhZ3MpOwogICAgICAgIHZhciBzdGF0ID0gRlMuc3RhdChwYXRoKTsKICAgICAgICB2YXIgbGVuZ3RoID0gc3RhdC5zaXplOwogICAgICAgIHZhciBidWYgPSBuZXcgVWludDhBcnJheShsZW5ndGgpOwogICAgICAgIEZTLnJlYWQoc3RyZWFtLCBidWYsIDAsIGxlbmd0aCwgMCk7CiAgICAgICAgaWYgKG9wdHMuZW5jb2RpbmcgPT09ICd1dGY4JykgewogICAgICAgICAgcmV0ID0gVVRGOEFycmF5VG9TdHJpbmcoYnVmLCAwKTsKICAgICAgICB9IGVsc2UgaWYgKG9wdHMuZW5jb2RpbmcgPT09ICdiaW5hcnknKSB7CiAgICAgICAgICByZXQgPSBidWY7CiAgICAgICAgfQogICAgICAgIEZTLmNsb3NlKHN0cmVhbSk7CiAgICAgICAgcmV0dXJuIHJldAogICAgICB9LAogICAgICB3cml0ZUZpbGU6IGZ1bmN0aW9uIChwYXRoLCBkYXRhLCBvcHRzKSB7CiAgICAgICAgb3B0cyA9IG9wdHMgfHwge307CiAgICAgICAgb3B0cy5mbGFncyA9IG9wdHMuZmxhZ3MgfHwgJ3cnOwogICAgICAgIHZhciBzdHJlYW0gPSBGUy5vcGVuKHBhdGgsIG9wdHMuZmxhZ3MsIG9wdHMubW9kZSk7CiAgICAgICAgaWYgKHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJykgewogICAgICAgICAgdmFyIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGxlbmd0aEJ5dGVzVVRGOChkYXRhKSArIDEpOwogICAgICAgICAgdmFyIGFjdHVhbE51bUJ5dGVzID0gc3RyaW5nVG9VVEY4QXJyYXkoZGF0YSwgYnVmLCAwLCBidWYubGVuZ3RoKTsKICAgICAgICAgIEZTLndyaXRlKHN0cmVhbSwgYnVmLCAwLCBhY3R1YWxOdW1CeXRlcywgdW5kZWZpbmVkLCBvcHRzLmNhbk93bik7CiAgICAgICAgfSBlbHNlIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcoZGF0YSkpIHsKICAgICAgICAgIEZTLndyaXRlKHN0cmVhbSwgZGF0YSwgMCwgZGF0YS5ieXRlTGVuZ3RoLCB1bmRlZmluZWQsIG9wdHMuY2FuT3duKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBkYXRhIHR5cGUnKQogICAgICAgIH0KICAgICAgICBGUy5jbG9zZShzdHJlYW0pOwogICAgICB9LAogICAgICBjd2Q6IGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gRlMuY3VycmVudFBhdGgKICAgICAgfSwKICAgICAgY2hkaXI6IGZ1bmN0aW9uIChwYXRoKSB7CiAgICAgICAgdmFyIGxvb2t1cCA9IEZTLmxvb2t1cFBhdGgocGF0aCwgeyBmb2xsb3c6IHRydWUgfSk7CiAgICAgICAgaWYgKGxvb2t1cC5ub2RlID09PSBudWxsKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FTk9FTlQpCiAgICAgICAgfQogICAgICAgIGlmICghRlMuaXNEaXIobG9va3VwLm5vZGUubW9kZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVOT1RESVIpCiAgICAgICAgfQogICAgICAgIHZhciBlcnIgPSBGUy5ub2RlUGVybWlzc2lvbnMobG9va3VwLm5vZGUsICd4Jyk7CiAgICAgICAgaWYgKGVycikgewogICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoZXJyKQogICAgICAgIH0KICAgICAgICBGUy5jdXJyZW50UGF0aCA9IGxvb2t1cC5wYXRoOwogICAgICB9LAogICAgICBjcmVhdGVEZWZhdWx0RGlyZWN0b3JpZXM6IGZ1bmN0aW9uICgpIHsKICAgICAgICBGUy5ta2RpcignL3RtcCcpOwogICAgICAgIEZTLm1rZGlyKCcvaG9tZScpOwogICAgICAgIEZTLm1rZGlyKCcvaG9tZS93ZWJfdXNlcicpOwogICAgICB9LAogICAgICBjcmVhdGVEZWZhdWx0RGV2aWNlczogZnVuY3Rpb24gKCkgewogICAgICAgIEZTLm1rZGlyKCcvZGV2Jyk7CiAgICAgICAgRlMucmVnaXN0ZXJEZXZpY2UoRlMubWFrZWRldigxLCAzKSwgewogICAgICAgICAgcmVhZDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICByZXR1cm4gMAogICAgICAgICAgfSwKICAgICAgICAgIHdyaXRlOiBmdW5jdGlvbiAoc3RyZWFtLCBidWZmZXIsIG9mZnNldCwgbGVuZ3RoLCBwb3MpIHsKICAgICAgICAgICAgcmV0dXJuIGxlbmd0aAogICAgICAgICAgfSwKICAgICAgICB9KTsKICAgICAgICBGUy5ta2RldignL2Rldi9udWxsJywgRlMubWFrZWRldigxLCAzKSk7CiAgICAgICAgVFRZLnJlZ2lzdGVyKEZTLm1ha2VkZXYoNSwgMCksIFRUWS5kZWZhdWx0X3R0eV9vcHMpOwogICAgICAgIFRUWS5yZWdpc3RlcihGUy5tYWtlZGV2KDYsIDApLCBUVFkuZGVmYXVsdF90dHkxX29wcyk7CiAgICAgICAgRlMubWtkZXYoJy9kZXYvdHR5JywgRlMubWFrZWRldig1LCAwKSk7CiAgICAgICAgRlMubWtkZXYoJy9kZXYvdHR5MScsIEZTLm1ha2VkZXYoNiwgMCkpOwogICAgICAgIHZhciByYW5kb21fZGV2aWNlOwogICAgICAgIGlmICh0eXBlb2YgY3J5cHRvICE9PSAndW5kZWZpbmVkJykgewogICAgICAgICAgdmFyIHJhbmRvbUJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KDEpOwogICAgICAgICAgcmFuZG9tX2RldmljZSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhyYW5kb21CdWZmZXIpOwogICAgICAgICAgICByZXR1cm4gcmFuZG9tQnVmZmVyWzBdCiAgICAgICAgICB9OwogICAgICAgIH0gZWxzZSBpZiAoRU5WSVJPTk1FTlRfSVNfTk9ERSkgewogICAgICAgICAgcmFuZG9tX2RldmljZSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgcmV0dXJuIHJlcXVpcmUoJ2NyeXB0bycpWydyYW5kb21CeXRlcyddKDEpWzBdCiAgICAgICAgICB9OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByYW5kb21fZGV2aWNlID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgICByZXR1cm4gKE1hdGgucmFuZG9tKCkgKiAyNTYpIHwgMAogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgRlMuY3JlYXRlRGV2aWNlKCcvZGV2JywgJ3JhbmRvbScsIHJhbmRvbV9kZXZpY2UpOwogICAgICAgIEZTLmNyZWF0ZURldmljZSgnL2RldicsICd1cmFuZG9tJywgcmFuZG9tX2RldmljZSk7CiAgICAgICAgRlMubWtkaXIoJy9kZXYvc2htJyk7CiAgICAgICAgRlMubWtkaXIoJy9kZXYvc2htL3RtcCcpOwogICAgICB9LAogICAgICBjcmVhdGVTcGVjaWFsRGlyZWN0b3JpZXM6IGZ1bmN0aW9uICgpIHsKICAgICAgICBGUy5ta2RpcignL3Byb2MnKTsKICAgICAgICBGUy5ta2RpcignL3Byb2Mvc2VsZicpOwogICAgICAgIEZTLm1rZGlyKCcvcHJvYy9zZWxmL2ZkJyk7CiAgICAgICAgRlMubW91bnQoCiAgICAgICAgICB7CiAgICAgICAgICAgIG1vdW50OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgdmFyIG5vZGUgPSBGUy5jcmVhdGVOb2RlKCcvcHJvYy9zZWxmJywgJ2ZkJywgMTYzODQgfCA1MTEsIDczKTsKICAgICAgICAgICAgICBub2RlLm5vZGVfb3BzID0gewogICAgICAgICAgICAgICAgbG9va3VwOiBmdW5jdGlvbiAocGFyZW50LCBuYW1lKSB7CiAgICAgICAgICAgICAgICAgIHZhciBmZCA9ICtuYW1lOwogICAgICAgICAgICAgICAgICB2YXIgc3RyZWFtID0gRlMuZ2V0U3RyZWFtKGZkKTsKICAgICAgICAgICAgICAgICAgaWYgKCFzdHJlYW0pIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKEVSUk5PX0NPREVTLkVCQURGKQogICAgICAgICAgICAgICAgICB2YXIgcmV0ID0gewogICAgICAgICAgICAgICAgICAgIHBhcmVudDogbnVsbCwKICAgICAgICAgICAgICAgICAgICBtb3VudDogeyBtb3VudHBvaW50OiAnZmFrZScgfSwKICAgICAgICAgICAgICAgICAgICBub2RlX29wczogewogICAgICAgICAgICAgICAgICAgICAgcmVhZGxpbms6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmVhbS5wYXRoCiAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgIHJldC5wYXJlbnQgPSByZXQ7CiAgICAgICAgICAgICAgICAgIHJldHVybiByZXQKICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICByZXR1cm4gbm9kZQogICAgICAgICAgICB9LAogICAgICAgICAgfSwKICAgICAgICAgIHt9LAogICAgICAgICAgJy9wcm9jL3NlbGYvZmQnCiAgICAgICAgKTsKICAgICAgfSwKICAgICAgY3JlYXRlU3RhbmRhcmRTdHJlYW1zOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgaWYgKE1vZHVsZVsnc3RkaW4nXSkgewogICAgICAgICAgRlMuY3JlYXRlRGV2aWNlKCcvZGV2JywgJ3N0ZGluJywgTW9kdWxlWydzdGRpbiddKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgRlMuc3ltbGluaygnL2Rldi90dHknLCAnL2Rldi9zdGRpbicpOwogICAgICAgIH0KICAgICAgICBpZiAoTW9kdWxlWydzdGRvdXQnXSkgewogICAgICAgICAgRlMuY3JlYXRlRGV2aWNlKCcvZGV2JywgJ3N0ZG91dCcsIG51bGwsIE1vZHVsZVsnc3Rkb3V0J10pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBGUy5zeW1saW5rKCcvZGV2L3R0eScsICcvZGV2L3N0ZG91dCcpOwogICAgICAgIH0KICAgICAgICBpZiAoTW9kdWxlWydzdGRlcnInXSkgewogICAgICAgICAgRlMuY3JlYXRlRGV2aWNlKCcvZGV2JywgJ3N0ZGVycicsIG51bGwsIE1vZHVsZVsnc3RkZXJyJ10pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBGUy5zeW1saW5rKCcvZGV2L3R0eTEnLCAnL2Rldi9zdGRlcnInKTsKICAgICAgICB9CiAgICAgICAgdmFyIHN0ZGluID0gRlMub3BlbignL2Rldi9zdGRpbicsICdyJyk7CiAgICAgICAgYXNzZXJ0KHN0ZGluLmZkID09PSAwLCAnaW52YWxpZCBoYW5kbGUgZm9yIHN0ZGluICgnICsgc3RkaW4uZmQgKyAnKScpOwogICAgICAgIHZhciBzdGRvdXQgPSBGUy5vcGVuKCcvZGV2L3N0ZG91dCcsICd3Jyk7CiAgICAgICAgYXNzZXJ0KHN0ZG91dC5mZCA9PT0gMSwgJ2ludmFsaWQgaGFuZGxlIGZvciBzdGRvdXQgKCcgKyBzdGRvdXQuZmQgKyAnKScpOwogICAgICAgIHZhciBzdGRlcnIgPSBGUy5vcGVuKCcvZGV2L3N0ZGVycicsICd3Jyk7CiAgICAgICAgYXNzZXJ0KHN0ZGVyci5mZCA9PT0gMiwgJ2ludmFsaWQgaGFuZGxlIGZvciBzdGRlcnIgKCcgKyBzdGRlcnIuZmQgKyAnKScpOwogICAgICB9LAogICAgICBlbnN1cmVFcnJub0Vycm9yOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgaWYgKEZTLkVycm5vRXJyb3IpIHJldHVybgogICAgICAgIEZTLkVycm5vRXJyb3IgPSBmdW5jdGlvbiBFcnJub0Vycm9yKGVycm5vLCBub2RlKSB7CiAgICAgICAgICB0aGlzLm5vZGUgPSBub2RlOwogICAgICAgICAgdGhpcy5zZXRFcnJubyA9IGZ1bmN0aW9uIChlcnJubykgewogICAgICAgICAgICB0aGlzLmVycm5vID0gZXJybm87CiAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBFUlJOT19DT0RFUykgewogICAgICAgICAgICAgIGlmIChFUlJOT19DT0RFU1trZXldID09PSBlcnJubykgewogICAgICAgICAgICAgICAgdGhpcy5jb2RlID0ga2V5OwogICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH07CiAgICAgICAgICB0aGlzLnNldEVycm5vKGVycm5vKTsKICAgICAgICAgIHRoaXMubWVzc2FnZSA9IEVSUk5PX01FU1NBR0VTW2Vycm5vXTsKICAgICAgICAgIGlmICh0aGlzLnN0YWNrKSBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3N0YWNrJywgeyB2YWx1ZTogbmV3IEVycm9yKCkuc3RhY2ssIHdyaXRhYmxlOiB0cnVlIH0pOwogICAgICAgIH07CiAgICAgICAgRlMuRXJybm9FcnJvci5wcm90b3R5cGUgPSBuZXcgRXJyb3IoKTsKICAgICAgICBGUy5FcnJub0Vycm9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEZTLkVycm5vRXJyb3IKICAgICAgICA7W0VSUk5PX0NPREVTLkVOT0VOVF0uZm9yRWFjaChmdW5jdGlvbiAoY29kZSkgewogICAgICAgICAgRlMuZ2VuZXJpY0Vycm9yc1tjb2RlXSA9IG5ldyBGUy5FcnJub0Vycm9yKGNvZGUpOwogICAgICAgICAgRlMuZ2VuZXJpY0Vycm9yc1tjb2RlXS5zdGFjayA9ICc8Z2VuZXJpYyBlcnJvciwgbm8gc3RhY2s+JzsKICAgICAgICB9KTsKICAgICAgfSwKICAgICAgc3RhdGljSW5pdDogZnVuY3Rpb24gKCkgewogICAgICAgIEZTLmVuc3VyZUVycm5vRXJyb3IoKTsKICAgICAgICBGUy5uYW1lVGFibGUgPSBuZXcgQXJyYXkoNDA5Nik7CiAgICAgICAgRlMubW91bnQoTUVNRlMsIHt9LCAnLycpOwogICAgICAgIEZTLmNyZWF0ZURlZmF1bHREaXJlY3RvcmllcygpOwogICAgICAgIEZTLmNyZWF0ZURlZmF1bHREZXZpY2VzKCk7CiAgICAgICAgRlMuY3JlYXRlU3BlY2lhbERpcmVjdG9yaWVzKCk7CiAgICAgICAgRlMuZmlsZXN5c3RlbXMgPSB7IE1FTUZTOiBNRU1GUywgSURCRlM6IElEQkZTLCBOT0RFRlM6IE5PREVGUywgV09SS0VSRlM6IFdPUktFUkZTIH07CiAgICAgIH0sCiAgICAgIGluaXQ6IGZ1bmN0aW9uIChpbnB1dCwgb3V0cHV0LCBlcnJvcikgewogICAgICAgIGFzc2VydCgKICAgICAgICAgICFGUy5pbml0LmluaXRpYWxpemVkLAogICAgICAgICAgJ0ZTLmluaXQgd2FzIHByZXZpb3VzbHkgY2FsbGVkLiBJZiB5b3Ugd2FudCB0byBpbml0aWFsaXplIGxhdGVyIHdpdGggY3VzdG9tIHBhcmFtZXRlcnMsIHJlbW92ZSBhbnkgZWFybGllciBjYWxscyAobm90ZSB0aGF0IG9uZSBpcyBhdXRvbWF0aWNhbGx5IGFkZGVkIHRvIHRoZSBnZW5lcmF0ZWQgY29kZSknCiAgICAgICAgKTsKICAgICAgICBGUy5pbml0LmluaXRpYWxpemVkID0gdHJ1ZTsKICAgICAgICBGUy5lbnN1cmVFcnJub0Vycm9yKCk7CiAgICAgICAgTW9kdWxlWydzdGRpbiddID0gaW5wdXQgfHwgTW9kdWxlWydzdGRpbiddOwogICAgICAgIE1vZHVsZVsnc3Rkb3V0J10gPSBvdXRwdXQgfHwgTW9kdWxlWydzdGRvdXQnXTsKICAgICAgICBNb2R1bGVbJ3N0ZGVyciddID0gZXJyb3IgfHwgTW9kdWxlWydzdGRlcnInXTsKICAgICAgICBGUy5jcmVhdGVTdGFuZGFyZFN0cmVhbXMoKTsKICAgICAgfSwKICAgICAgcXVpdDogZnVuY3Rpb24gKCkgewogICAgICAgIEZTLmluaXQuaW5pdGlhbGl6ZWQgPSBmYWxzZTsKICAgICAgICB2YXIgZmZsdXNoID0gTW9kdWxlWydfZmZsdXNoJ107CiAgICAgICAgaWYgKGZmbHVzaCkgZmZsdXNoKDApOwogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgRlMuc3RyZWFtcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgdmFyIHN0cmVhbSA9IEZTLnN0cmVhbXNbaV07CiAgICAgICAgICBpZiAoIXN0cmVhbSkgewogICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgfQogICAgICAgICAgRlMuY2xvc2Uoc3RyZWFtKTsKICAgICAgICB9CiAgICAgIH0sCiAgICAgIGdldE1vZGU6IGZ1bmN0aW9uIChjYW5SZWFkLCBjYW5Xcml0ZSkgewogICAgICAgIHZhciBtb2RlID0gMDsKICAgICAgICBpZiAoY2FuUmVhZCkgbW9kZSB8PSAyOTIgfCA3MzsKICAgICAgICBpZiAoY2FuV3JpdGUpIG1vZGUgfD0gMTQ2OwogICAgICAgIHJldHVybiBtb2RlCiAgICAgIH0sCiAgICAgIGpvaW5QYXRoOiBmdW5jdGlvbiAocGFydHMsIGZvcmNlUmVsYXRpdmUpIHsKICAgICAgICB2YXIgcGF0aCA9IFBBVEguam9pbi5hcHBseShudWxsLCBwYXJ0cyk7CiAgICAgICAgaWYgKGZvcmNlUmVsYXRpdmUgJiYgcGF0aFswXSA9PSAnLycpIHBhdGggPSBwYXRoLnN1YnN0cigxKTsKICAgICAgICByZXR1cm4gcGF0aAogICAgICB9LAogICAgICBhYnNvbHV0ZVBhdGg6IGZ1bmN0aW9uIChyZWxhdGl2ZSwgYmFzZSkgewogICAgICAgIHJldHVybiBQQVRILnJlc29sdmUoYmFzZSwgcmVsYXRpdmUpCiAgICAgIH0sCiAgICAgIHN0YW5kYXJkaXplUGF0aDogZnVuY3Rpb24gKHBhdGgpIHsKICAgICAgICByZXR1cm4gUEFUSC5ub3JtYWxpemUocGF0aCkKICAgICAgfSwKICAgICAgZmluZE9iamVjdDogZnVuY3Rpb24gKHBhdGgsIGRvbnRSZXNvbHZlTGFzdExpbmspIHsKICAgICAgICB2YXIgcmV0ID0gRlMuYW5hbHl6ZVBhdGgocGF0aCwgZG9udFJlc29sdmVMYXN0TGluayk7CiAgICAgICAgaWYgKHJldC5leGlzdHMpIHsKICAgICAgICAgIHJldHVybiByZXQub2JqZWN0CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIF9fX3NldEVyck5vKHJldC5lcnJvcik7CiAgICAgICAgICByZXR1cm4gbnVsbAogICAgICAgIH0KICAgICAgfSwKICAgICAgYW5hbHl6ZVBhdGg6IGZ1bmN0aW9uIChwYXRoLCBkb250UmVzb2x2ZUxhc3RMaW5rKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHZhciBsb29rdXAgPSBGUy5sb29rdXBQYXRoKHBhdGgsIHsgZm9sbG93OiAhZG9udFJlc29sdmVMYXN0TGluayB9KTsKICAgICAgICAgIHBhdGggPSBsb29rdXAucGF0aDsKICAgICAgICB9IGNhdGNoIChlKSB7fQogICAgICAgIHZhciByZXQgPSB7CiAgICAgICAgICBpc1Jvb3Q6IGZhbHNlLAogICAgICAgICAgZXhpc3RzOiBmYWxzZSwKICAgICAgICAgIGVycm9yOiAwLAogICAgICAgICAgbmFtZTogbnVsbCwKICAgICAgICAgIHBhdGg6IG51bGwsCiAgICAgICAgICBvYmplY3Q6IG51bGwsCiAgICAgICAgICBwYXJlbnRFeGlzdHM6IGZhbHNlLAogICAgICAgICAgcGFyZW50UGF0aDogbnVsbCwKICAgICAgICAgIHBhcmVudE9iamVjdDogbnVsbCwKICAgICAgICB9OwogICAgICAgIHRyeSB7CiAgICAgICAgICB2YXIgbG9va3VwID0gRlMubG9va3VwUGF0aChwYXRoLCB7IHBhcmVudDogdHJ1ZSB9KTsKICAgICAgICAgIHJldC5wYXJlbnRFeGlzdHMgPSB0cnVlOwogICAgICAgICAgcmV0LnBhcmVudFBhdGggPSBsb29rdXAucGF0aDsKICAgICAgICAgIHJldC5wYXJlbnRPYmplY3QgPSBsb29rdXAubm9kZTsKICAgICAgICAgIHJldC5uYW1lID0gUEFUSC5iYXNlbmFtZShwYXRoKTsKICAgICAgICAgIGxvb2t1cCA9IEZTLmxvb2t1cFBhdGgocGF0aCwgeyBmb2xsb3c6ICFkb250UmVzb2x2ZUxhc3RMaW5rIH0pOwogICAgICAgICAgcmV0LmV4aXN0cyA9IHRydWU7CiAgICAgICAgICByZXQucGF0aCA9IGxvb2t1cC5wYXRoOwogICAgICAgICAgcmV0Lm9iamVjdCA9IGxvb2t1cC5ub2RlOwogICAgICAgICAgcmV0Lm5hbWUgPSBsb29rdXAubm9kZS5uYW1lOwogICAgICAgICAgcmV0LmlzUm9vdCA9IGxvb2t1cC5wYXRoID09PSAnLyc7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgcmV0LmVycm9yID0gZS5lcnJubzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldAogICAgICB9LAogICAgICBjcmVhdGVGb2xkZXI6IGZ1bmN0aW9uIChwYXJlbnQsIG5hbWUsIGNhblJlYWQsIGNhbldyaXRlKSB7CiAgICAgICAgdmFyIHBhdGggPSBQQVRILmpvaW4yKHR5cGVvZiBwYXJlbnQgPT09ICdzdHJpbmcnID8gcGFyZW50IDogRlMuZ2V0UGF0aChwYXJlbnQpLCBuYW1lKTsKICAgICAgICB2YXIgbW9kZSA9IEZTLmdldE1vZGUoY2FuUmVhZCwgY2FuV3JpdGUpOwogICAgICAgIHJldHVybiBGUy5ta2RpcihwYXRoLCBtb2RlKQogICAgICB9LAogICAgICBjcmVhdGVQYXRoOiBmdW5jdGlvbiAocGFyZW50LCBwYXRoLCBjYW5SZWFkLCBjYW5Xcml0ZSkgewogICAgICAgIHBhcmVudCA9IHR5cGVvZiBwYXJlbnQgPT09ICdzdHJpbmcnID8gcGFyZW50IDogRlMuZ2V0UGF0aChwYXJlbnQpOwogICAgICAgIHZhciBwYXJ0cyA9IHBhdGguc3BsaXQoJy8nKS5yZXZlcnNlKCk7CiAgICAgICAgd2hpbGUgKHBhcnRzLmxlbmd0aCkgewogICAgICAgICAgdmFyIHBhcnQgPSBwYXJ0cy5wb3AoKTsKICAgICAgICAgIGlmICghcGFydCkgY29udGludWUKICAgICAgICAgIHZhciBjdXJyZW50ID0gUEFUSC5qb2luMihwYXJlbnQsIHBhcnQpOwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgRlMubWtkaXIoY3VycmVudCk7CiAgICAgICAgICB9IGNhdGNoIChlKSB7fQogICAgICAgICAgcGFyZW50ID0gY3VycmVudDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGN1cnJlbnQKICAgICAgfSwKICAgICAgY3JlYXRlRmlsZTogZnVuY3Rpb24gKHBhcmVudCwgbmFtZSwgcHJvcGVydGllcywgY2FuUmVhZCwgY2FuV3JpdGUpIHsKICAgICAgICB2YXIgcGF0aCA9IFBBVEguam9pbjIodHlwZW9mIHBhcmVudCA9PT0gJ3N0cmluZycgPyBwYXJlbnQgOiBGUy5nZXRQYXRoKHBhcmVudCksIG5hbWUpOwogICAgICAgIHZhciBtb2RlID0gRlMuZ2V0TW9kZShjYW5SZWFkLCBjYW5Xcml0ZSk7CiAgICAgICAgcmV0dXJuIEZTLmNyZWF0ZShwYXRoLCBtb2RlKQogICAgICB9LAogICAgICBjcmVhdGVEYXRhRmlsZTogZnVuY3Rpb24gKHBhcmVudCwgbmFtZSwgZGF0YSwgY2FuUmVhZCwgY2FuV3JpdGUsIGNhbk93bikgewogICAgICAgIHZhciBwYXRoID0gbmFtZSA/IFBBVEguam9pbjIodHlwZW9mIHBhcmVudCA9PT0gJ3N0cmluZycgPyBwYXJlbnQgOiBGUy5nZXRQYXRoKHBhcmVudCksIG5hbWUpIDogcGFyZW50OwogICAgICAgIHZhciBtb2RlID0gRlMuZ2V0TW9kZShjYW5SZWFkLCBjYW5Xcml0ZSk7CiAgICAgICAgdmFyIG5vZGUgPSBGUy5jcmVhdGUocGF0aCwgbW9kZSk7CiAgICAgICAgaWYgKGRhdGEpIHsKICAgICAgICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycpIHsKICAgICAgICAgICAgdmFyIGFyciA9IG5ldyBBcnJheShkYXRhLmxlbmd0aCk7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBkYXRhLmxlbmd0aDsgaSA8IGxlbjsgKytpKSBhcnJbaV0gPSBkYXRhLmNoYXJDb2RlQXQoaSk7CiAgICAgICAgICAgIGRhdGEgPSBhcnI7CiAgICAgICAgICB9CiAgICAgICAgICBGUy5jaG1vZChub2RlLCBtb2RlIHwgMTQ2KTsKICAgICAgICAgIHZhciBzdHJlYW0gPSBGUy5vcGVuKG5vZGUsICd3Jyk7CiAgICAgICAgICBGUy53cml0ZShzdHJlYW0sIGRhdGEsIDAsIGRhdGEubGVuZ3RoLCAwLCBjYW5Pd24pOwogICAgICAgICAgRlMuY2xvc2Uoc3RyZWFtKTsKICAgICAgICAgIEZTLmNobW9kKG5vZGUsIG1vZGUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbm9kZQogICAgICB9LAogICAgICBjcmVhdGVEZXZpY2U6IGZ1bmN0aW9uIChwYXJlbnQsIG5hbWUsIGlucHV0LCBvdXRwdXQpIHsKICAgICAgICB2YXIgcGF0aCA9IFBBVEguam9pbjIodHlwZW9mIHBhcmVudCA9PT0gJ3N0cmluZycgPyBwYXJlbnQgOiBGUy5nZXRQYXRoKHBhcmVudCksIG5hbWUpOwogICAgICAgIHZhciBtb2RlID0gRlMuZ2V0TW9kZSghIWlucHV0LCAhIW91dHB1dCk7CiAgICAgICAgaWYgKCFGUy5jcmVhdGVEZXZpY2UubWFqb3IpIEZTLmNyZWF0ZURldmljZS5tYWpvciA9IDY0OwogICAgICAgIHZhciBkZXYgPSBGUy5tYWtlZGV2KEZTLmNyZWF0ZURldmljZS5tYWpvcisrLCAwKTsKICAgICAgICBGUy5yZWdpc3RlckRldmljZShkZXYsIHsKICAgICAgICAgIG9wZW46IGZ1bmN0aW9uIChzdHJlYW0pIHsKICAgICAgICAgICAgc3RyZWFtLnNlZWthYmxlID0gZmFsc2U7CiAgICAgICAgICB9LAogICAgICAgICAgY2xvc2U6IGZ1bmN0aW9uIChzdHJlYW0pIHsKICAgICAgICAgICAgaWYgKG91dHB1dCAmJiBvdXRwdXQuYnVmZmVyICYmIG91dHB1dC5idWZmZXIubGVuZ3RoKSB7CiAgICAgICAgICAgICAgb3V0cHV0KDEwKTsKICAgICAgICAgICAgfQogICAgICAgICAgfSwKICAgICAgICAgIHJlYWQ6IGZ1bmN0aW9uIChzdHJlYW0sIGJ1ZmZlciwgb2Zmc2V0LCBsZW5ndGgsIHBvcykgewogICAgICAgICAgICB2YXIgYnl0ZXNSZWFkID0gMDsKICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgICAgIHZhciByZXN1bHQ7CiAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHJlc3VsdCA9IGlucHV0KCk7CiAgICAgICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUlPKQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAocmVzdWx0ID09PSB1bmRlZmluZWQgJiYgYnl0ZXNSZWFkID09PSAwKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FQUdBSU4pCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IG51bGwgfHwgcmVzdWx0ID09PSB1bmRlZmluZWQpIGJyZWFrCiAgICAgICAgICAgICAgYnl0ZXNSZWFkKys7CiAgICAgICAgICAgICAgYnVmZmVyW29mZnNldCArIGldID0gcmVzdWx0OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChieXRlc1JlYWQpIHsKICAgICAgICAgICAgICBzdHJlYW0ubm9kZS50aW1lc3RhbXAgPSBEYXRlLm5vdygpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBieXRlc1JlYWQKICAgICAgICAgIH0sCiAgICAgICAgICB3cml0ZTogZnVuY3Rpb24gKHN0cmVhbSwgYnVmZmVyLCBvZmZzZXQsIGxlbmd0aCwgcG9zKSB7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgb3V0cHV0KGJ1ZmZlcltvZmZzZXQgKyBpXSk7CiAgICAgICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUlPKQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAobGVuZ3RoKSB7CiAgICAgICAgICAgICAgc3RyZWFtLm5vZGUudGltZXN0YW1wID0gRGF0ZS5ub3coKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gaQogICAgICAgICAgfSwKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gRlMubWtkZXYocGF0aCwgbW9kZSwgZGV2KQogICAgICB9LAogICAgICBjcmVhdGVMaW5rOiBmdW5jdGlvbiAocGFyZW50LCBuYW1lLCB0YXJnZXQsIGNhblJlYWQsIGNhbldyaXRlKSB7CiAgICAgICAgdmFyIHBhdGggPSBQQVRILmpvaW4yKHR5cGVvZiBwYXJlbnQgPT09ICdzdHJpbmcnID8gcGFyZW50IDogRlMuZ2V0UGF0aChwYXJlbnQpLCBuYW1lKTsKICAgICAgICByZXR1cm4gRlMuc3ltbGluayh0YXJnZXQsIHBhdGgpCiAgICAgIH0sCiAgICAgIGZvcmNlTG9hZEZpbGU6IGZ1bmN0aW9uIChvYmopIHsKICAgICAgICBpZiAob2JqLmlzRGV2aWNlIHx8IG9iai5pc0ZvbGRlciB8fCBvYmoubGluayB8fCBvYmouY29udGVudHMpIHJldHVybiB0cnVlCiAgICAgICAgdmFyIHN1Y2Nlc3MgPSB0cnVlOwogICAgICAgIGlmICh0eXBlb2YgWE1MSHR0cFJlcXVlc3QgIT09ICd1bmRlZmluZWQnKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoCiAgICAgICAgICAgICdMYXp5IGxvYWRpbmcgc2hvdWxkIGhhdmUgYmVlbiBwZXJmb3JtZWQgKGNvbnRlbnRzIHNldCkgaW4gY3JlYXRlTGF6eUZpbGUsIGJ1dCBpdCB3YXMgbm90LiBMYXp5IGxvYWRpbmcgb25seSB3b3JrcyBpbiB3ZWIgd29ya2Vycy4gVXNlIC0tZW1iZWQtZmlsZSBvciAtLXByZWxvYWQtZmlsZSBpbiBlbWNjIG9uIHRoZSBtYWluIHRocmVhZC4nCiAgICAgICAgICApCiAgICAgICAgfSBlbHNlIGlmIChNb2R1bGVbJ3JlYWQnXSkgewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgb2JqLmNvbnRlbnRzID0gaW50QXJyYXlGcm9tU3RyaW5nKE1vZHVsZVsncmVhZCddKG9iai51cmwpLCB0cnVlKTsKICAgICAgICAgICAgb2JqLnVzZWRCeXRlcyA9IG9iai5jb250ZW50cy5sZW5ndGg7CiAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIHN1Y2Nlc3MgPSBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgbG9hZCB3aXRob3V0IHJlYWQoKSBvciBYTUxIdHRwUmVxdWVzdC4nKQogICAgICAgIH0KICAgICAgICBpZiAoIXN1Y2Nlc3MpIF9fX3NldEVyck5vKEVSUk5PX0NPREVTLkVJTyk7CiAgICAgICAgcmV0dXJuIHN1Y2Nlc3MKICAgICAgfSwKICAgICAgY3JlYXRlTGF6eUZpbGU6IGZ1bmN0aW9uIChwYXJlbnQsIG5hbWUsIHVybCwgY2FuUmVhZCwgY2FuV3JpdGUpIHsKICAgICAgICBmdW5jdGlvbiBMYXp5VWludDhBcnJheSgpIHsKICAgICAgICAgIHRoaXMubGVuZ3RoS25vd24gPSBmYWxzZTsKICAgICAgICAgIHRoaXMuY2h1bmtzID0gW107CiAgICAgICAgfQogICAgICAgIExhenlVaW50OEFycmF5LnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiBMYXp5VWludDhBcnJheV9nZXQoaWR4KSB7CiAgICAgICAgICBpZiAoaWR4ID4gdGhpcy5sZW5ndGggLSAxIHx8IGlkeCA8IDApIHsKICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZAogICAgICAgICAgfQogICAgICAgICAgdmFyIGNodW5rT2Zmc2V0ID0gaWR4ICUgdGhpcy5jaHVua1NpemU7CiAgICAgICAgICB2YXIgY2h1bmtOdW0gPSAoaWR4IC8gdGhpcy5jaHVua1NpemUpIHwgMDsKICAgICAgICAgIHJldHVybiB0aGlzLmdldHRlcihjaHVua051bSlbY2h1bmtPZmZzZXRdCiAgICAgICAgfTsKICAgICAgICBMYXp5VWludDhBcnJheS5wcm90b3R5cGUuc2V0RGF0YUdldHRlciA9IGZ1bmN0aW9uIExhenlVaW50OEFycmF5X3NldERhdGFHZXR0ZXIoZ2V0dGVyKSB7CiAgICAgICAgICB0aGlzLmdldHRlciA9IGdldHRlcjsKICAgICAgICB9OwogICAgICAgIExhenlVaW50OEFycmF5LnByb3RvdHlwZS5jYWNoZUxlbmd0aCA9IGZ1bmN0aW9uIExhenlVaW50OEFycmF5X2NhY2hlTGVuZ3RoKCkgewogICAgICAgICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpOwogICAgICAgICAgeGhyLm9wZW4oJ0hFQUQnLCB1cmwsIGZhbHNlKTsKICAgICAgICAgIHhoci5zZW5kKG51bGwpOwogICAgICAgICAgaWYgKCEoKHhoci5zdGF0dXMgPj0gMjAwICYmIHhoci5zdGF0dXMgPCAzMDApIHx8IHhoci5zdGF0dXMgPT09IDMwNCkpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiQ291bGRuJ3QgbG9hZCAiICsgdXJsICsgJy4gU3RhdHVzOiAnICsgeGhyLnN0YXR1cykKICAgICAgICAgIHZhciBkYXRhbGVuZ3RoID0gTnVtYmVyKHhoci5nZXRSZXNwb25zZUhlYWRlcignQ29udGVudC1sZW5ndGgnKSk7CiAgICAgICAgICB2YXIgaGVhZGVyOwogICAgICAgICAgdmFyIGhhc0J5dGVTZXJ2aW5nID0gKGhlYWRlciA9IHhoci5nZXRSZXNwb25zZUhlYWRlcignQWNjZXB0LVJhbmdlcycpKSAmJiBoZWFkZXIgPT09ICdieXRlcyc7CiAgICAgICAgICB2YXIgdXNlc0d6aXAgPSAoaGVhZGVyID0geGhyLmdldFJlc3BvbnNlSGVhZGVyKCdDb250ZW50LUVuY29kaW5nJykpICYmIGhlYWRlciA9PT0gJ2d6aXAnOwogICAgICAgICAgdmFyIGNodW5rU2l6ZSA9IDEwMjQgKiAxMDI0OwogICAgICAgICAgaWYgKCFoYXNCeXRlU2VydmluZykgY2h1bmtTaXplID0gZGF0YWxlbmd0aDsKICAgICAgICAgIHZhciBkb1hIUiA9IGZ1bmN0aW9uIChmcm9tLCB0bykgewogICAgICAgICAgICBpZiAoZnJvbSA+IHRvKSB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgcmFuZ2UgKCcgKyBmcm9tICsgJywgJyArIHRvICsgJykgb3Igbm8gYnl0ZXMgcmVxdWVzdGVkIScpCiAgICAgICAgICAgIGlmICh0byA+IGRhdGFsZW5ndGggLSAxKSB0aHJvdyBuZXcgRXJyb3IoJ29ubHkgJyArIGRhdGFsZW5ndGggKyAnIGJ5dGVzIGF2YWlsYWJsZSEgcHJvZ3JhbW1lciBlcnJvciEnKQogICAgICAgICAgICB2YXIgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7CiAgICAgICAgICAgIHhoci5vcGVuKCdHRVQnLCB1cmwsIGZhbHNlKTsKICAgICAgICAgICAgaWYgKGRhdGFsZW5ndGggIT09IGNodW5rU2l6ZSkgeGhyLnNldFJlcXVlc3RIZWFkZXIoJ1JhbmdlJywgJ2J5dGVzPScgKyBmcm9tICsgJy0nICsgdG8pOwogICAgICAgICAgICBpZiAodHlwZW9mIFVpbnQ4QXJyYXkgIT0gJ3VuZGVmaW5lZCcpIHhoci5yZXNwb25zZVR5cGUgPSAnYXJyYXlidWZmZXInOwogICAgICAgICAgICBpZiAoeGhyLm92ZXJyaWRlTWltZVR5cGUpIHsKICAgICAgICAgICAgICB4aHIub3ZlcnJpZGVNaW1lVHlwZSgndGV4dC9wbGFpbjsgY2hhcnNldD14LXVzZXItZGVmaW5lZCcpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHhoci5zZW5kKG51bGwpOwogICAgICAgICAgICBpZiAoISgoeGhyLnN0YXR1cyA+PSAyMDAgJiYgeGhyLnN0YXR1cyA8IDMwMCkgfHwgeGhyLnN0YXR1cyA9PT0gMzA0KSkKICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkNvdWxkbid0IGxvYWQgIiArIHVybCArICcuIFN0YXR1czogJyArIHhoci5zdGF0dXMpCiAgICAgICAgICAgIGlmICh4aHIucmVzcG9uc2UgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheSh4aHIucmVzcG9uc2UgfHwgW10pCiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmV0dXJuIGludEFycmF5RnJvbVN0cmluZyh4aHIucmVzcG9uc2VUZXh0IHx8ICcnLCB0cnVlKQogICAgICAgICAgICB9CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIGxhenlBcnJheSA9IHRoaXM7CiAgICAgICAgICBsYXp5QXJyYXkuc2V0RGF0YUdldHRlcihmdW5jdGlvbiAoY2h1bmtOdW0pIHsKICAgICAgICAgICAgdmFyIHN0YXJ0ID0gY2h1bmtOdW0gKiBjaHVua1NpemU7CiAgICAgICAgICAgIHZhciBlbmQgPSAoY2h1bmtOdW0gKyAxKSAqIGNodW5rU2l6ZSAtIDE7CiAgICAgICAgICAgIGVuZCA9IE1hdGgubWluKGVuZCwgZGF0YWxlbmd0aCAtIDEpOwogICAgICAgICAgICBpZiAodHlwZW9mIGxhenlBcnJheS5jaHVua3NbY2h1bmtOdW1dID09PSAndW5kZWZpbmVkJykgewogICAgICAgICAgICAgIGxhenlBcnJheS5jaHVua3NbY2h1bmtOdW1dID0gZG9YSFIoc3RhcnQsIGVuZCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHR5cGVvZiBsYXp5QXJyYXkuY2h1bmtzW2NodW5rTnVtXSA9PT0gJ3VuZGVmaW5lZCcpIHRocm93IG5ldyBFcnJvcignZG9YSFIgZmFpbGVkIScpCiAgICAgICAgICAgIHJldHVybiBsYXp5QXJyYXkuY2h1bmtzW2NodW5rTnVtXQogICAgICAgICAgfSk7CiAgICAgICAgICBpZiAodXNlc0d6aXAgfHwgIWRhdGFsZW5ndGgpIHsKICAgICAgICAgICAgY2h1bmtTaXplID0gZGF0YWxlbmd0aCA9IDE7CiAgICAgICAgICAgIGRhdGFsZW5ndGggPSB0aGlzLmdldHRlcigwKS5sZW5ndGg7CiAgICAgICAgICAgIGNodW5rU2l6ZSA9IGRhdGFsZW5ndGg7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdMYXp5RmlsZXMgb24gZ3ppcCBmb3JjZXMgZG93bmxvYWQgb2YgdGhlIHdob2xlIGZpbGUgd2hlbiBsZW5ndGggaXMgYWNjZXNzZWQnKTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuX2xlbmd0aCA9IGRhdGFsZW5ndGg7CiAgICAgICAgICB0aGlzLl9jaHVua1NpemUgPSBjaHVua1NpemU7CiAgICAgICAgICB0aGlzLmxlbmd0aEtub3duID0gdHJ1ZTsKICAgICAgICB9OwogICAgICAgIGlmICh0eXBlb2YgWE1MSHR0cFJlcXVlc3QgIT09ICd1bmRlZmluZWQnKSB7CiAgICAgICAgICBpZiAoIUVOVklST05NRU5UX0lTX1dPUktFUikKICAgICAgICAgICAgdGhyb3cgJ0Nhbm5vdCBkbyBzeW5jaHJvbm91cyBiaW5hcnkgWEhScyBvdXRzaWRlIHdlYndvcmtlcnMgaW4gbW9kZXJuIGJyb3dzZXJzLiBVc2UgLS1lbWJlZC1maWxlIG9yIC0tcHJlbG9hZC1maWxlIGluIGVtY2MnCiAgICAgICAgICB2YXIgbGF6eUFycmF5ID0gbmV3IExhenlVaW50OEFycmF5KCk7CiAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhsYXp5QXJyYXksIHsKICAgICAgICAgICAgbGVuZ3RoOiB7CiAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICBpZiAoIXRoaXMubGVuZ3RoS25vd24pIHsKICAgICAgICAgICAgICAgICAgdGhpcy5jYWNoZUxlbmd0aCgpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2xlbmd0aAogICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGNodW5rU2l6ZTogewogICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgaWYgKCF0aGlzLmxlbmd0aEtub3duKSB7CiAgICAgICAgICAgICAgICAgIHRoaXMuY2FjaGVMZW5ndGgoKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9jaHVua1NpemUKICAgICAgICAgICAgICB9LAogICAgICAgICAgICB9LAogICAgICAgICAgfSk7CiAgICAgICAgICB2YXIgcHJvcGVydGllcyA9IHsgaXNEZXZpY2U6IGZhbHNlLCBjb250ZW50czogbGF6eUFycmF5IH07CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciBwcm9wZXJ0aWVzID0geyBpc0RldmljZTogZmFsc2UsIHVybDogdXJsIH07CiAgICAgICAgfQogICAgICAgIHZhciBub2RlID0gRlMuY3JlYXRlRmlsZShwYXJlbnQsIG5hbWUsIHByb3BlcnRpZXMsIGNhblJlYWQsIGNhbldyaXRlKTsKICAgICAgICBpZiAocHJvcGVydGllcy5jb250ZW50cykgewogICAgICAgICAgbm9kZS5jb250ZW50cyA9IHByb3BlcnRpZXMuY29udGVudHM7CiAgICAgICAgfSBlbHNlIGlmIChwcm9wZXJ0aWVzLnVybCkgewogICAgICAgICAgbm9kZS5jb250ZW50cyA9IG51bGw7CiAgICAgICAgICBub2RlLnVybCA9IHByb3BlcnRpZXMudXJsOwogICAgICAgIH0KICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhub2RlLCB7CiAgICAgICAgICB1c2VkQnl0ZXM6IHsKICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGVudHMubGVuZ3RoCiAgICAgICAgICAgIH0sCiAgICAgICAgICB9LAogICAgICAgIH0pOwogICAgICAgIHZhciBzdHJlYW1fb3BzID0ge307CiAgICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhub2RlLnN0cmVhbV9vcHMpOwogICAgICAgIGtleXMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgICB2YXIgZm4gPSBub2RlLnN0cmVhbV9vcHNba2V5XTsKICAgICAgICAgIHN0cmVhbV9vcHNba2V5XSA9IGZ1bmN0aW9uIGZvcmNlTG9hZExhenlGaWxlKCkgewogICAgICAgICAgICBpZiAoIUZTLmZvcmNlTG9hZEZpbGUobm9kZSkpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FSU8pCiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGZuLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgICAgICAgIH07CiAgICAgICAgfSk7CiAgICAgICAgc3RyZWFtX29wcy5yZWFkID0gZnVuY3Rpb24gc3RyZWFtX29wc19yZWFkKHN0cmVhbSwgYnVmZmVyLCBvZmZzZXQsIGxlbmd0aCwgcG9zaXRpb24pIHsKICAgICAgICAgIGlmICghRlMuZm9yY2VMb2FkRmlsZShub2RlKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FSU8pCiAgICAgICAgICB9CiAgICAgICAgICB2YXIgY29udGVudHMgPSBzdHJlYW0ubm9kZS5jb250ZW50czsKICAgICAgICAgIGlmIChwb3NpdGlvbiA+PSBjb250ZW50cy5sZW5ndGgpIHJldHVybiAwCiAgICAgICAgICB2YXIgc2l6ZSA9IE1hdGgubWluKGNvbnRlbnRzLmxlbmd0aCAtIHBvc2l0aW9uLCBsZW5ndGgpOwogICAgICAgICAgYXNzZXJ0KHNpemUgPj0gMCk7CiAgICAgICAgICBpZiAoY29udGVudHMuc2xpY2UpIHsKICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKICAgICAgICAgICAgICBidWZmZXJbb2Zmc2V0ICsgaV0gPSBjb250ZW50c1twb3NpdGlvbiArIGldOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNpemU7IGkrKykgewogICAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXQgKyBpXSA9IGNvbnRlbnRzLmdldChwb3NpdGlvbiArIGkpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gc2l6ZQogICAgICAgIH07CiAgICAgICAgbm9kZS5zdHJlYW1fb3BzID0gc3RyZWFtX29wczsKICAgICAgICByZXR1cm4gbm9kZQogICAgICB9LAogICAgICBjcmVhdGVQcmVsb2FkZWRGaWxlOiBmdW5jdGlvbiAoCiAgICAgICAgcGFyZW50LAogICAgICAgIG5hbWUsCiAgICAgICAgdXJsLAogICAgICAgIGNhblJlYWQsCiAgICAgICAgY2FuV3JpdGUsCiAgICAgICAgb25sb2FkLAogICAgICAgIG9uZXJyb3IsCiAgICAgICAgZG9udENyZWF0ZUZpbGUsCiAgICAgICAgY2FuT3duLAogICAgICAgIHByZUZpbmlzaAogICAgICApIHsKICAgICAgICBCcm93c2VyLmluaXQoKTsKICAgICAgICB2YXIgZnVsbG5hbWUgPSBuYW1lID8gUEFUSC5yZXNvbHZlKFBBVEguam9pbjIocGFyZW50LCBuYW1lKSkgOiBwYXJlbnQ7CiAgICAgICAgZnVuY3Rpb24gcHJvY2Vzc0RhdGEoYnl0ZUFycmF5KSB7CiAgICAgICAgICBmdW5jdGlvbiBmaW5pc2goYnl0ZUFycmF5KSB7CiAgICAgICAgICAgIGlmIChwcmVGaW5pc2gpIHByZUZpbmlzaCgpOwogICAgICAgICAgICBpZiAoIWRvbnRDcmVhdGVGaWxlKSB7CiAgICAgICAgICAgICAgRlMuY3JlYXRlRGF0YUZpbGUocGFyZW50LCBuYW1lLCBieXRlQXJyYXksIGNhblJlYWQsIGNhbldyaXRlLCBjYW5Pd24pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChvbmxvYWQpIG9ubG9hZCgpOwogICAgICAgICAgICByZW1vdmVSdW5EZXBlbmRlbmN5KCk7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgaGFuZGxlZCA9IGZhbHNlOwogICAgICAgICAgTW9kdWxlWydwcmVsb2FkUGx1Z2lucyddLmZvckVhY2goZnVuY3Rpb24gKHBsdWdpbikgewogICAgICAgICAgICBpZiAoaGFuZGxlZCkgcmV0dXJuCiAgICAgICAgICAgIGlmIChwbHVnaW5bJ2NhbkhhbmRsZSddKGZ1bGxuYW1lKSkgewogICAgICAgICAgICAgIHBsdWdpblsnaGFuZGxlJ10oYnl0ZUFycmF5LCBmdWxsbmFtZSwgZmluaXNoLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICBpZiAob25lcnJvcikgb25lcnJvcigpOwogICAgICAgICAgICAgICAgcmVtb3ZlUnVuRGVwZW5kZW5jeSgpOwogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKICAgICAgICAgIGlmICghaGFuZGxlZCkgZmluaXNoKGJ5dGVBcnJheSk7CiAgICAgICAgfQogICAgICAgIGFkZFJ1bkRlcGVuZGVuY3koKTsKICAgICAgICBpZiAodHlwZW9mIHVybCA9PSAnc3RyaW5nJykgewogICAgICAgICAgQnJvd3Nlci5hc3luY0xvYWQoCiAgICAgICAgICAgIHVybCwKICAgICAgICAgICAgZnVuY3Rpb24gKGJ5dGVBcnJheSkgewogICAgICAgICAgICAgIHByb2Nlc3NEYXRhKGJ5dGVBcnJheSk7CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIG9uZXJyb3IKICAgICAgICAgICk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHByb2Nlc3NEYXRhKHVybCk7CiAgICAgICAgfQogICAgICB9LAogICAgICBpbmRleGVkREI6IGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gd2luZG93LmluZGV4ZWREQiB8fCB3aW5kb3cubW96SW5kZXhlZERCIHx8IHdpbmRvdy53ZWJraXRJbmRleGVkREIgfHwgd2luZG93Lm1zSW5kZXhlZERCCiAgICAgIH0sCiAgICAgIERCX05BTUU6IGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gJ0VNX0ZTXycgKyB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWUKICAgICAgfSwKICAgICAgREJfVkVSU0lPTjogMjAsCiAgICAgIERCX1NUT1JFX05BTUU6ICdGSUxFX0RBVEEnLAogICAgICBzYXZlRmlsZXNUb0RCOiBmdW5jdGlvbiAocGF0aHMsIG9ubG9hZCwgb25lcnJvcikgewogICAgICAgIG9ubG9hZCA9IG9ubG9hZCB8fCBmdW5jdGlvbiAoKSB7fTsKICAgICAgICBvbmVycm9yID0gb25lcnJvciB8fCBmdW5jdGlvbiAoKSB7fTsKICAgICAgICB2YXIgaW5kZXhlZERCID0gRlMuaW5kZXhlZERCKCk7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHZhciBvcGVuUmVxdWVzdCA9IGluZGV4ZWREQi5vcGVuKEZTLkRCX05BTUUoKSwgRlMuREJfVkVSU0lPTik7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgcmV0dXJuIG9uZXJyb3IoZSkKICAgICAgICB9CiAgICAgICAgb3BlblJlcXVlc3Qub251cGdyYWRlbmVlZGVkID0gZnVuY3Rpb24gb3BlblJlcXVlc3Rfb251cGdyYWRlbmVlZGVkKCkgewogICAgICAgICAgY29uc29sZS5sb2coJ2NyZWF0aW5nIGRiJyk7CiAgICAgICAgICB2YXIgZGIgPSBvcGVuUmVxdWVzdC5yZXN1bHQ7CiAgICAgICAgICBkYi5jcmVhdGVPYmplY3RTdG9yZShGUy5EQl9TVE9SRV9OQU1FKTsKICAgICAgICB9OwogICAgICAgIG9wZW5SZXF1ZXN0Lm9uc3VjY2VzcyA9IGZ1bmN0aW9uIG9wZW5SZXF1ZXN0X29uc3VjY2VzcygpIHsKICAgICAgICAgIHZhciBkYiA9IG9wZW5SZXF1ZXN0LnJlc3VsdDsKICAgICAgICAgIHZhciB0cmFuc2FjdGlvbiA9IGRiLnRyYW5zYWN0aW9uKFtGUy5EQl9TVE9SRV9OQU1FXSwgJ3JlYWR3cml0ZScpOwogICAgICAgICAgdmFyIGZpbGVzID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUoRlMuREJfU1RPUkVfTkFNRSk7CiAgICAgICAgICB2YXIgb2sgPSAwLAogICAgICAgICAgICBmYWlsID0gMCwKICAgICAgICAgICAgdG90YWwgPSBwYXRocy5sZW5ndGg7CiAgICAgICAgICBmdW5jdGlvbiBmaW5pc2goKSB7CiAgICAgICAgICAgIGlmIChmYWlsID09IDApIG9ubG9hZCgpOwogICAgICAgICAgICBlbHNlIG9uZXJyb3IoKTsKICAgICAgICAgIH0KICAgICAgICAgIHBhdGhzLmZvckVhY2goZnVuY3Rpb24gKHBhdGgpIHsKICAgICAgICAgICAgdmFyIHB1dFJlcXVlc3QgPSBmaWxlcy5wdXQoRlMuYW5hbHl6ZVBhdGgocGF0aCkub2JqZWN0LmNvbnRlbnRzLCBwYXRoKTsKICAgICAgICAgICAgcHV0UmVxdWVzdC5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiBwdXRSZXF1ZXN0X29uc3VjY2VzcygpIHsKICAgICAgICAgICAgICBvaysrOwogICAgICAgICAgICAgIGlmIChvayArIGZhaWwgPT0gdG90YWwpIGZpbmlzaCgpOwogICAgICAgICAgICB9OwogICAgICAgICAgICBwdXRSZXF1ZXN0Lm9uZXJyb3IgPSBmdW5jdGlvbiBwdXRSZXF1ZXN0X29uZXJyb3IoKSB7CiAgICAgICAgICAgICAgZmFpbCsrOwogICAgICAgICAgICAgIGlmIChvayArIGZhaWwgPT0gdG90YWwpIGZpbmlzaCgpOwogICAgICAgICAgICB9OwogICAgICAgICAgfSk7CiAgICAgICAgICB0cmFuc2FjdGlvbi5vbmVycm9yID0gb25lcnJvcjsKICAgICAgICB9OwogICAgICAgIG9wZW5SZXF1ZXN0Lm9uZXJyb3IgPSBvbmVycm9yOwogICAgICB9LAogICAgICBsb2FkRmlsZXNGcm9tREI6IGZ1bmN0aW9uIChwYXRocywgb25sb2FkLCBvbmVycm9yKSB7CiAgICAgICAgb25sb2FkID0gb25sb2FkIHx8IGZ1bmN0aW9uICgpIHt9OwogICAgICAgIG9uZXJyb3IgPSBvbmVycm9yIHx8IGZ1bmN0aW9uICgpIHt9OwogICAgICAgIHZhciBpbmRleGVkREIgPSBGUy5pbmRleGVkREIoKTsKICAgICAgICB0cnkgewogICAgICAgICAgdmFyIG9wZW5SZXF1ZXN0ID0gaW5kZXhlZERCLm9wZW4oRlMuREJfTkFNRSgpLCBGUy5EQl9WRVJTSU9OKTsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICByZXR1cm4gb25lcnJvcihlKQogICAgICAgIH0KICAgICAgICBvcGVuUmVxdWVzdC5vbnVwZ3JhZGVuZWVkZWQgPSBvbmVycm9yOwogICAgICAgIG9wZW5SZXF1ZXN0Lm9uc3VjY2VzcyA9IGZ1bmN0aW9uIG9wZW5SZXF1ZXN0X29uc3VjY2VzcygpIHsKICAgICAgICAgIHZhciBkYiA9IG9wZW5SZXF1ZXN0LnJlc3VsdDsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHZhciB0cmFuc2FjdGlvbiA9IGRiLnRyYW5zYWN0aW9uKFtGUy5EQl9TVE9SRV9OQU1FXSwgJ3JlYWRvbmx5Jyk7CiAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIG9uZXJyb3IoZSk7CiAgICAgICAgICAgIHJldHVybgogICAgICAgICAgfQogICAgICAgICAgdmFyIGZpbGVzID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUoRlMuREJfU1RPUkVfTkFNRSk7CiAgICAgICAgICB2YXIgb2sgPSAwLAogICAgICAgICAgICBmYWlsID0gMCwKICAgICAgICAgICAgdG90YWwgPSBwYXRocy5sZW5ndGg7CiAgICAgICAgICBmdW5jdGlvbiBmaW5pc2goKSB7CiAgICAgICAgICAgIGlmIChmYWlsID09IDApIG9ubG9hZCgpOwogICAgICAgICAgICBlbHNlIG9uZXJyb3IoKTsKICAgICAgICAgIH0KICAgICAgICAgIHBhdGhzLmZvckVhY2goZnVuY3Rpb24gKHBhdGgpIHsKICAgICAgICAgICAgdmFyIGdldFJlcXVlc3QgPSBmaWxlcy5nZXQocGF0aCk7CiAgICAgICAgICAgIGdldFJlcXVlc3Qub25zdWNjZXNzID0gZnVuY3Rpb24gZ2V0UmVxdWVzdF9vbnN1Y2Nlc3MoKSB7CiAgICAgICAgICAgICAgaWYgKEZTLmFuYWx5emVQYXRoKHBhdGgpLmV4aXN0cykgewogICAgICAgICAgICAgICAgRlMudW5saW5rKHBhdGgpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBGUy5jcmVhdGVEYXRhRmlsZShQQVRILmRpcm5hbWUocGF0aCksIFBBVEguYmFzZW5hbWUocGF0aCksIGdldFJlcXVlc3QucmVzdWx0LCB0cnVlLCB0cnVlLCB0cnVlKTsKICAgICAgICAgICAgICBvaysrOwogICAgICAgICAgICAgIGlmIChvayArIGZhaWwgPT0gdG90YWwpIGZpbmlzaCgpOwogICAgICAgICAgICB9OwogICAgICAgICAgICBnZXRSZXF1ZXN0Lm9uZXJyb3IgPSBmdW5jdGlvbiBnZXRSZXF1ZXN0X29uZXJyb3IoKSB7CiAgICAgICAgICAgICAgZmFpbCsrOwogICAgICAgICAgICAgIGlmIChvayArIGZhaWwgPT0gdG90YWwpIGZpbmlzaCgpOwogICAgICAgICAgICB9OwogICAgICAgICAgfSk7CiAgICAgICAgICB0cmFuc2FjdGlvbi5vbmVycm9yID0gb25lcnJvcjsKICAgICAgICB9OwogICAgICAgIG9wZW5SZXF1ZXN0Lm9uZXJyb3IgPSBvbmVycm9yOwogICAgICB9LAogICAgfTsKICAgIHZhciBTWVNDQUxMUyA9IHsKICAgICAgREVGQVVMVF9QT0xMTUFTSzogNSwKICAgICAgbWFwcGluZ3M6IHt9LAogICAgICB1bWFzazogNTExLAogICAgICBjYWxjdWxhdGVBdDogZnVuY3Rpb24gKGRpcmZkLCBwYXRoKSB7CiAgICAgICAgaWYgKHBhdGhbMF0gIT09ICcvJykgewogICAgICAgICAgdmFyIGRpcjsKICAgICAgICAgIGlmIChkaXJmZCA9PT0gLTEwMCkgewogICAgICAgICAgICBkaXIgPSBGUy5jd2QoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHZhciBkaXJzdHJlYW0gPSBGUy5nZXRTdHJlYW0oZGlyZmQpOwogICAgICAgICAgICBpZiAoIWRpcnN0cmVhbSkgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUJBREYpCiAgICAgICAgICAgIGRpciA9IGRpcnN0cmVhbS5wYXRoOwogICAgICAgICAgfQogICAgICAgICAgcGF0aCA9IFBBVEguam9pbjIoZGlyLCBwYXRoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHBhdGgKICAgICAgfSwKICAgICAgZG9TdGF0OiBmdW5jdGlvbiAoZnVuYywgcGF0aCwgYnVmKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHZhciBzdGF0ID0gZnVuYyhwYXRoKTsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICBpZiAoZSAmJiBlLm5vZGUgJiYgUEFUSC5ub3JtYWxpemUocGF0aCkgIT09IFBBVEgubm9ybWFsaXplKEZTLmdldFBhdGgoZS5ub2RlKSkpIHsKICAgICAgICAgICAgcmV0dXJuIC1FUlJOT19DT0RFUy5FTk9URElSCiAgICAgICAgICB9CiAgICAgICAgICB0aHJvdyBlCiAgICAgICAgfQogICAgICAgIEhFQVAzMltidWYgPj4gMl0gPSBzdGF0LmRldjsKICAgICAgICBIRUFQMzJbKGJ1ZiArIDQpID4+IDJdID0gMDsKICAgICAgICBIRUFQMzJbKGJ1ZiArIDgpID4+IDJdID0gc3RhdC5pbm87CiAgICAgICAgSEVBUDMyWyhidWYgKyAxMikgPj4gMl0gPSBzdGF0Lm1vZGU7CiAgICAgICAgSEVBUDMyWyhidWYgKyAxNikgPj4gMl0gPSBzdGF0Lm5saW5rOwogICAgICAgIEhFQVAzMlsoYnVmICsgMjApID4+IDJdID0gc3RhdC51aWQ7CiAgICAgICAgSEVBUDMyWyhidWYgKyAyNCkgPj4gMl0gPSBzdGF0LmdpZDsKICAgICAgICBIRUFQMzJbKGJ1ZiArIDI4KSA+PiAyXSA9IHN0YXQucmRldjsKICAgICAgICBIRUFQMzJbKGJ1ZiArIDMyKSA+PiAyXSA9IDA7CiAgICAgICAgSEVBUDMyWyhidWYgKyAzNikgPj4gMl0gPSBzdGF0LnNpemU7CiAgICAgICAgSEVBUDMyWyhidWYgKyA0MCkgPj4gMl0gPSA0MDk2OwogICAgICAgIEhFQVAzMlsoYnVmICsgNDQpID4+IDJdID0gc3RhdC5ibG9ja3M7CiAgICAgICAgSEVBUDMyWyhidWYgKyA0OCkgPj4gMl0gPSAoc3RhdC5hdGltZS5nZXRUaW1lKCkgLyAxZTMpIHwgMDsKICAgICAgICBIRUFQMzJbKGJ1ZiArIDUyKSA+PiAyXSA9IDA7CiAgICAgICAgSEVBUDMyWyhidWYgKyA1NikgPj4gMl0gPSAoc3RhdC5tdGltZS5nZXRUaW1lKCkgLyAxZTMpIHwgMDsKICAgICAgICBIRUFQMzJbKGJ1ZiArIDYwKSA+PiAyXSA9IDA7CiAgICAgICAgSEVBUDMyWyhidWYgKyA2NCkgPj4gMl0gPSAoc3RhdC5jdGltZS5nZXRUaW1lKCkgLyAxZTMpIHwgMDsKICAgICAgICBIRUFQMzJbKGJ1ZiArIDY4KSA+PiAyXSA9IDA7CiAgICAgICAgSEVBUDMyWyhidWYgKyA3MikgPj4gMl0gPSBzdGF0LmlubzsKICAgICAgICByZXR1cm4gMAogICAgICB9LAogICAgICBkb01zeW5jOiBmdW5jdGlvbiAoYWRkciwgc3RyZWFtLCBsZW4sIGZsYWdzKSB7CiAgICAgICAgdmFyIGJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KEhFQVBVOC5zdWJhcnJheShhZGRyLCBhZGRyICsgbGVuKSk7CiAgICAgICAgRlMubXN5bmMoc3RyZWFtLCBidWZmZXIsIDAsIGxlbiwgZmxhZ3MpOwogICAgICB9LAogICAgICBkb01rZGlyOiBmdW5jdGlvbiAocGF0aCwgbW9kZSkgewogICAgICAgIHBhdGggPSBQQVRILm5vcm1hbGl6ZShwYXRoKTsKICAgICAgICBpZiAocGF0aFtwYXRoLmxlbmd0aCAtIDFdID09PSAnLycpIHBhdGggPSBwYXRoLnN1YnN0cigwLCBwYXRoLmxlbmd0aCAtIDEpOwogICAgICAgIEZTLm1rZGlyKHBhdGgsIG1vZGUsIDApOwogICAgICAgIHJldHVybiAwCiAgICAgIH0sCiAgICAgIGRvTWtub2Q6IGZ1bmN0aW9uIChwYXRoLCBtb2RlLCBkZXYpIHsKICAgICAgICBzd2l0Y2ggKG1vZGUgJiA2MTQ0MCkgewogICAgICAgICAgY2FzZSAzMjc2ODoKICAgICAgICAgIGNhc2UgODE5MjoKICAgICAgICAgIGNhc2UgMjQ1NzY6CiAgICAgICAgICBjYXNlIDQwOTY6CiAgICAgICAgICBjYXNlIDQ5MTUyOgogICAgICAgICAgICBicmVhawogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgcmV0dXJuIC1FUlJOT19DT0RFUy5FSU5WQUwKICAgICAgICB9CiAgICAgICAgRlMubWtub2QocGF0aCwgbW9kZSwgZGV2KTsKICAgICAgICByZXR1cm4gMAogICAgICB9LAogICAgICBkb1JlYWRsaW5rOiBmdW5jdGlvbiAocGF0aCwgYnVmLCBidWZzaXplKSB7CiAgICAgICAgaWYgKGJ1ZnNpemUgPD0gMCkgcmV0dXJuIC1FUlJOT19DT0RFUy5FSU5WQUwKICAgICAgICB2YXIgcmV0ID0gRlMucmVhZGxpbmsocGF0aCk7CiAgICAgICAgdmFyIGxlbiA9IE1hdGgubWluKGJ1ZnNpemUsIGxlbmd0aEJ5dGVzVVRGOChyZXQpKTsKICAgICAgICB2YXIgZW5kQ2hhciA9IEhFQVA4W2J1ZiArIGxlbl07CiAgICAgICAgc3RyaW5nVG9VVEY4KHJldCwgYnVmLCBidWZzaXplICsgMSk7CiAgICAgICAgSEVBUDhbYnVmICsgbGVuXSA9IGVuZENoYXI7CiAgICAgICAgcmV0dXJuIGxlbgogICAgICB9LAogICAgICBkb0FjY2VzczogZnVuY3Rpb24gKHBhdGgsIGFtb2RlKSB7CiAgICAgICAgaWYgKGFtb2RlICYgfjcpIHsKICAgICAgICAgIHJldHVybiAtRVJSTk9fQ09ERVMuRUlOVkFMCiAgICAgICAgfQogICAgICAgIHZhciBub2RlOwogICAgICAgIHZhciBsb29rdXAgPSBGUy5sb29rdXBQYXRoKHBhdGgsIHsgZm9sbG93OiB0cnVlIH0pOwogICAgICAgIG5vZGUgPSBsb29rdXAubm9kZTsKICAgICAgICB2YXIgcGVybXMgPSAnJzsKICAgICAgICBpZiAoYW1vZGUgJiA0KSBwZXJtcyArPSAncic7CiAgICAgICAgaWYgKGFtb2RlICYgMikgcGVybXMgKz0gJ3cnOwogICAgICAgIGlmIChhbW9kZSAmIDEpIHBlcm1zICs9ICd4JzsKICAgICAgICBpZiAocGVybXMgJiYgRlMubm9kZVBlcm1pc3Npb25zKG5vZGUsIHBlcm1zKSkgewogICAgICAgICAgcmV0dXJuIC1FUlJOT19DT0RFUy5FQUNDRVMKICAgICAgICB9CiAgICAgICAgcmV0dXJuIDAKICAgICAgfSwKICAgICAgZG9EdXA6IGZ1bmN0aW9uIChwYXRoLCBmbGFncywgc3VnZ2VzdEZEKSB7CiAgICAgICAgdmFyIHN1Z2dlc3QgPSBGUy5nZXRTdHJlYW0oc3VnZ2VzdEZEKTsKICAgICAgICBpZiAoc3VnZ2VzdCkgRlMuY2xvc2Uoc3VnZ2VzdCk7CiAgICAgICAgcmV0dXJuIEZTLm9wZW4ocGF0aCwgZmxhZ3MsIDAsIHN1Z2dlc3RGRCwgc3VnZ2VzdEZEKS5mZAogICAgICB9LAogICAgICBkb1JlYWR2OiBmdW5jdGlvbiAoc3RyZWFtLCBpb3YsIGlvdmNudCwgb2Zmc2V0KSB7CiAgICAgICAgdmFyIHJldCA9IDA7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpb3ZjbnQ7IGkrKykgewogICAgICAgICAgdmFyIHB0ciA9IEhFQVAzMlsoaW92ICsgaSAqIDgpID4+IDJdOwogICAgICAgICAgdmFyIGxlbiA9IEhFQVAzMlsoaW92ICsgKGkgKiA4ICsgNCkpID4+IDJdOwogICAgICAgICAgdmFyIGN1cnIgPSBGUy5yZWFkKHN0cmVhbSwgSEVBUDgsIHB0ciwgbGVuLCBvZmZzZXQpOwogICAgICAgICAgaWYgKGN1cnIgPCAwKSByZXR1cm4gLTEKICAgICAgICAgIHJldCArPSBjdXJyOwogICAgICAgICAgaWYgKGN1cnIgPCBsZW4pIGJyZWFrCiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQKICAgICAgfSwKICAgICAgZG9Xcml0ZXY6IGZ1bmN0aW9uIChzdHJlYW0sIGlvdiwgaW92Y250LCBvZmZzZXQpIHsKICAgICAgICB2YXIgcmV0ID0gMDsKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlvdmNudDsgaSsrKSB7CiAgICAgICAgICB2YXIgcHRyID0gSEVBUDMyWyhpb3YgKyBpICogOCkgPj4gMl07CiAgICAgICAgICB2YXIgbGVuID0gSEVBUDMyWyhpb3YgKyAoaSAqIDggKyA0KSkgPj4gMl07CiAgICAgICAgICB2YXIgY3VyciA9IEZTLndyaXRlKHN0cmVhbSwgSEVBUDgsIHB0ciwgbGVuLCBvZmZzZXQpOwogICAgICAgICAgaWYgKGN1cnIgPCAwKSByZXR1cm4gLTEKICAgICAgICAgIHJldCArPSBjdXJyOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0CiAgICAgIH0sCiAgICAgIHZhcmFyZ3M6IDAsCiAgICAgIGdldDogZnVuY3Rpb24gKHZhcmFyZ3MpIHsKICAgICAgICBTWVNDQUxMUy52YXJhcmdzICs9IDQ7CiAgICAgICAgdmFyIHJldCA9IEhFQVAzMlsoU1lTQ0FMTFMudmFyYXJncyAtIDQpID4+IDJdOwogICAgICAgIHJldHVybiByZXQKICAgICAgfSwKICAgICAgZ2V0U3RyOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIHJldCA9IFBvaW50ZXJfc3RyaW5naWZ5KFNZU0NBTExTLmdldCgpKTsKICAgICAgICByZXR1cm4gcmV0CiAgICAgIH0sCiAgICAgIGdldFN0cmVhbUZyb21GRDogZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBzdHJlYW0gPSBGUy5nZXRTdHJlYW0oU1lTQ0FMTFMuZ2V0KCkpOwogICAgICAgIGlmICghc3RyZWFtKSB0aHJvdyBuZXcgRlMuRXJybm9FcnJvcihFUlJOT19DT0RFUy5FQkFERikKICAgICAgICByZXR1cm4gc3RyZWFtCiAgICAgIH0sCiAgICAgIGdldFNvY2tldEZyb21GRDogZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBzb2NrZXQgPSBTT0NLRlMuZ2V0U29ja2V0KFNZU0NBTExTLmdldCgpKTsKICAgICAgICBpZiAoIXNvY2tldCkgdGhyb3cgbmV3IEZTLkVycm5vRXJyb3IoRVJSTk9fQ09ERVMuRUJBREYpCiAgICAgICAgcmV0dXJuIHNvY2tldAogICAgICB9LAogICAgICBnZXRTb2NrZXRBZGRyZXNzOiBmdW5jdGlvbiAoYWxsb3dOdWxsKSB7CiAgICAgICAgdmFyIGFkZHJwID0gU1lTQ0FMTFMuZ2V0KCksCiAgICAgICAgICBhZGRybGVuID0gU1lTQ0FMTFMuZ2V0KCk7CiAgICAgICAgaWYgKGFsbG93TnVsbCAmJiBhZGRycCA9PT0gMCkgcmV0dXJuIG51bGwKICAgICAgICB2YXIgaW5mbyA9IF9fcmVhZF9zb2NrYWRkcihhZGRycCwgYWRkcmxlbik7CiAgICAgICAgaWYgKGluZm8uZXJybm8pIHRocm93IG5ldyBGUy5FcnJub0Vycm9yKGluZm8uZXJybm8pCiAgICAgICAgaW5mby5hZGRyID0gRE5TLmxvb2t1cF9hZGRyKGluZm8uYWRkcikgfHwgaW5mby5hZGRyOwogICAgICAgIHJldHVybiBpbmZvCiAgICAgIH0sCiAgICAgIGdldDY0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIGxvdyA9IFNZU0NBTExTLmdldCgpLAogICAgICAgICAgaGlnaCA9IFNZU0NBTExTLmdldCgpOwogICAgICAgIGlmIChsb3cgPj0gMCkgYXNzZXJ0KGhpZ2ggPT09IDApOwogICAgICAgIGVsc2UgYXNzZXJ0KGhpZ2ggPT09IC0xKTsKICAgICAgICByZXR1cm4gbG93CiAgICAgIH0sCiAgICAgIGdldFplcm86IGZ1bmN0aW9uICgpIHsKICAgICAgICBhc3NlcnQoU1lTQ0FMTFMuZ2V0KCkgPT09IDApOwogICAgICB9LAogICAgfTsKICAgIGZ1bmN0aW9uIF9fX3N5c2NhbGwxNDAod2hpY2gsIHZhcmFyZ3MpIHsKICAgICAgU1lTQ0FMTFMudmFyYXJncyA9IHZhcmFyZ3M7CiAgICAgIHRyeSB7CiAgICAgICAgdmFyIHN0cmVhbSA9IFNZU0NBTExTLmdldFN0cmVhbUZyb21GRCgpLAogICAgICAgICAgb2Zmc2V0X2hpZ2ggPSBTWVNDQUxMUy5nZXQoKSwKICAgICAgICAgIG9mZnNldF9sb3cgPSBTWVNDQUxMUy5nZXQoKSwKICAgICAgICAgIHJlc3VsdCA9IFNZU0NBTExTLmdldCgpLAogICAgICAgICAgd2hlbmNlID0gU1lTQ0FMTFMuZ2V0KCk7CiAgICAgICAgdmFyIG9mZnNldCA9IG9mZnNldF9sb3c7CiAgICAgICAgRlMubGxzZWVrKHN0cmVhbSwgb2Zmc2V0LCB3aGVuY2UpOwogICAgICAgIEhFQVAzMltyZXN1bHQgPj4gMl0gPSBzdHJlYW0ucG9zaXRpb247CiAgICAgICAgaWYgKHN0cmVhbS5nZXRkZW50cyAmJiBvZmZzZXQgPT09IDAgJiYgd2hlbmNlID09PSAwKSBzdHJlYW0uZ2V0ZGVudHMgPSBudWxsOwogICAgICAgIHJldHVybiAwCiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIEZTID09PSAndW5kZWZpbmVkJyB8fCAhKGUgaW5zdGFuY2VvZiBGUy5FcnJub0Vycm9yKSkgYWJvcnQoZSk7CiAgICAgICAgcmV0dXJuIC1lLmVycm5vCiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIF9fX3N5c2NhbGwxNDUod2hpY2gsIHZhcmFyZ3MpIHsKICAgICAgU1lTQ0FMTFMudmFyYXJncyA9IHZhcmFyZ3M7CiAgICAgIHRyeSB7CiAgICAgICAgdmFyIHN0cmVhbSA9IFNZU0NBTExTLmdldFN0cmVhbUZyb21GRCgpLAogICAgICAgICAgaW92ID0gU1lTQ0FMTFMuZ2V0KCksCiAgICAgICAgICBpb3ZjbnQgPSBTWVNDQUxMUy5nZXQoKTsKICAgICAgICByZXR1cm4gU1lTQ0FMTFMuZG9SZWFkdihzdHJlYW0sIGlvdiwgaW92Y250KQogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgaWYgKHR5cGVvZiBGUyA9PT0gJ3VuZGVmaW5lZCcgfHwgIShlIGluc3RhbmNlb2YgRlMuRXJybm9FcnJvcikpIGFib3J0KGUpOwogICAgICAgIHJldHVybiAtZS5lcnJubwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBfX19zeXNjYWxsMTQ2KHdoaWNoLCB2YXJhcmdzKSB7CiAgICAgIFNZU0NBTExTLnZhcmFyZ3MgPSB2YXJhcmdzOwogICAgICB0cnkgewogICAgICAgIHZhciBzdHJlYW0gPSBTWVNDQUxMUy5nZXRTdHJlYW1Gcm9tRkQoKSwKICAgICAgICAgIGlvdiA9IFNZU0NBTExTLmdldCgpLAogICAgICAgICAgaW92Y250ID0gU1lTQ0FMTFMuZ2V0KCk7CiAgICAgICAgcmV0dXJuIFNZU0NBTExTLmRvV3JpdGV2KHN0cmVhbSwgaW92LCBpb3ZjbnQpCiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIEZTID09PSAndW5kZWZpbmVkJyB8fCAhKGUgaW5zdGFuY2VvZiBGUy5FcnJub0Vycm9yKSkgYWJvcnQoZSk7CiAgICAgICAgcmV0dXJuIC1lLmVycm5vCiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIF9fX3N5c2NhbGwxODMod2hpY2gsIHZhcmFyZ3MpIHsKICAgICAgU1lTQ0FMTFMudmFyYXJncyA9IHZhcmFyZ3M7CiAgICAgIHRyeSB7CiAgICAgICAgdmFyIGJ1ZiA9IFNZU0NBTExTLmdldCgpLAogICAgICAgICAgc2l6ZSA9IFNZU0NBTExTLmdldCgpOwogICAgICAgIGlmIChzaXplID09PSAwKSByZXR1cm4gLUVSUk5PX0NPREVTLkVJTlZBTAogICAgICAgIHZhciBjd2QgPSBGUy5jd2QoKTsKICAgICAgICB2YXIgY3dkTGVuZ3RoSW5CeXRlcyA9IGxlbmd0aEJ5dGVzVVRGOChjd2QpOwogICAgICAgIGlmIChzaXplIDwgY3dkTGVuZ3RoSW5CeXRlcyArIDEpIHJldHVybiAtRVJSTk9fQ09ERVMuRVJBTkdFCiAgICAgICAgc3RyaW5nVG9VVEY4KGN3ZCwgYnVmLCBzaXplKTsKICAgICAgICByZXR1cm4gYnVmCiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIEZTID09PSAndW5kZWZpbmVkJyB8fCAhKGUgaW5zdGFuY2VvZiBGUy5FcnJub0Vycm9yKSkgYWJvcnQoZSk7CiAgICAgICAgcmV0dXJuIC1lLmVycm5vCiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIF9fX3N5c2NhbGwxOTgod2hpY2gsIHZhcmFyZ3MpIHsKICAgICAgU1lTQ0FMTFMudmFyYXJncyA9IHZhcmFyZ3M7CiAgICAgIHRyeSB7CiAgICAgICAgdmFyIHBhdGggPSBTWVNDQUxMUy5nZXRTdHIoKSwKICAgICAgICAgIG93bmVyID0gU1lTQ0FMTFMuZ2V0KCksCiAgICAgICAgICBncm91cCA9IFNZU0NBTExTLmdldCgpOwogICAgICAgIEZTLmNob3duKHBhdGgsIG93bmVyLCBncm91cCk7CiAgICAgICAgcmV0dXJuIDAKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmICh0eXBlb2YgRlMgPT09ICd1bmRlZmluZWQnIHx8ICEoZSBpbnN0YW5jZW9mIEZTLkVycm5vRXJyb3IpKSBhYm9ydChlKTsKICAgICAgICByZXR1cm4gLWUuZXJybm8KICAgICAgfQogICAgfQogICAgdmFyIFBST0NJTkZPID0geyBwcGlkOiAxLCBwaWQ6IDQyLCBzaWQ6IDQyLCBwZ2lkOiA0MiB9OwogICAgZnVuY3Rpb24gX19fc3lzY2FsbDIwKHdoaWNoLCB2YXJhcmdzKSB7CiAgICAgIFNZU0NBTExTLnZhcmFyZ3MgPSB2YXJhcmdzOwogICAgICB0cnkgewogICAgICAgIHJldHVybiBQUk9DSU5GTy5waWQKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmICh0eXBlb2YgRlMgPT09ICd1bmRlZmluZWQnIHx8ICEoZSBpbnN0YW5jZW9mIEZTLkVycm5vRXJyb3IpKSBhYm9ydChlKTsKICAgICAgICByZXR1cm4gLWUuZXJybm8KICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gX19fc3lzY2FsbDYod2hpY2gsIHZhcmFyZ3MpIHsKICAgICAgU1lTQ0FMTFMudmFyYXJncyA9IHZhcmFyZ3M7CiAgICAgIHRyeSB7CiAgICAgICAgdmFyIHN0cmVhbSA9IFNZU0NBTExTLmdldFN0cmVhbUZyb21GRCgpOwogICAgICAgIEZTLmNsb3NlKHN0cmVhbSk7CiAgICAgICAgcmV0dXJuIDAKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmICh0eXBlb2YgRlMgPT09ICd1bmRlZmluZWQnIHx8ICEoZSBpbnN0YW5jZW9mIEZTLkVycm5vRXJyb3IpKSBhYm9ydChlKTsKICAgICAgICByZXR1cm4gLWUuZXJybm8KICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gX19fc3lzY2FsbDYwKHdoaWNoLCB2YXJhcmdzKSB7CiAgICAgIFNZU0NBTExTLnZhcmFyZ3MgPSB2YXJhcmdzOwogICAgICB0cnkgewogICAgICAgIHZhciBtYXNrID0gU1lTQ0FMTFMuZ2V0KCk7CiAgICAgICAgdmFyIG9sZCA9IFNZU0NBTExTLnVtYXNrOwogICAgICAgIFNZU0NBTExTLnVtYXNrID0gbWFzazsKICAgICAgICByZXR1cm4gb2xkCiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIEZTID09PSAndW5kZWZpbmVkJyB8fCAhKGUgaW5zdGFuY2VvZiBGUy5FcnJub0Vycm9yKSkgYWJvcnQoZSk7CiAgICAgICAgcmV0dXJuIC1lLmVycm5vCiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIF9fX3N5c2NhbGw4Myh3aGljaCwgdmFyYXJncykgewogICAgICBTWVNDQUxMUy52YXJhcmdzID0gdmFyYXJnczsKICAgICAgdHJ5IHsKICAgICAgICB2YXIgdGFyZ2V0ID0gU1lTQ0FMTFMuZ2V0U3RyKCksCiAgICAgICAgICBsaW5rcGF0aCA9IFNZU0NBTExTLmdldFN0cigpOwogICAgICAgIEZTLnN5bWxpbmsodGFyZ2V0LCBsaW5rcGF0aCk7CiAgICAgICAgcmV0dXJuIDAKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmICh0eXBlb2YgRlMgPT09ICd1bmRlZmluZWQnIHx8ICEoZSBpbnN0YW5jZW9mIEZTLkVycm5vRXJyb3IpKSBhYm9ydChlKTsKICAgICAgICByZXR1cm4gLWUuZXJybm8KICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gX19fc3lzY2FsbDkxKHdoaWNoLCB2YXJhcmdzKSB7CiAgICAgIFNZU0NBTExTLnZhcmFyZ3MgPSB2YXJhcmdzOwogICAgICB0cnkgewogICAgICAgIHZhciBhZGRyID0gU1lTQ0FMTFMuZ2V0KCksCiAgICAgICAgICBsZW4gPSBTWVNDQUxMUy5nZXQoKTsKICAgICAgICB2YXIgaW5mbyA9IFNZU0NBTExTLm1hcHBpbmdzW2FkZHJdOwogICAgICAgIGlmICghaW5mbykgcmV0dXJuIDAKICAgICAgICBpZiAobGVuID09PSBpbmZvLmxlbikgewogICAgICAgICAgdmFyIHN0cmVhbSA9IEZTLmdldFN0cmVhbShpbmZvLmZkKTsKICAgICAgICAgIFNZU0NBTExTLmRvTXN5bmMoYWRkciwgc3RyZWFtLCBsZW4sIGluZm8uZmxhZ3MpOwogICAgICAgICAgRlMubXVubWFwKHN0cmVhbSk7CiAgICAgICAgICBTWVNDQUxMUy5tYXBwaW5nc1thZGRyXSA9IG51bGw7CiAgICAgICAgICBpZiAoaW5mby5hbGxvY2F0ZWQpIHsKICAgICAgICAgICAgX2ZyZWUoaW5mby5tYWxsb2MpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gMAogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgaWYgKHR5cGVvZiBGUyA9PT0gJ3VuZGVmaW5lZCcgfHwgIShlIGluc3RhbmNlb2YgRlMuRXJybm9FcnJvcikpIGFib3J0KGUpOwogICAgICAgIHJldHVybiAtZS5lcnJubwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBfX191bmxvY2soKSB7fQogICAgdmFyIHN0cnVjdFJlZ2lzdHJhdGlvbnMgPSB7fTsKICAgIGZ1bmN0aW9uIHJ1bkRlc3RydWN0b3JzKGRlc3RydWN0b3JzKSB7CiAgICAgIHdoaWxlIChkZXN0cnVjdG9ycy5sZW5ndGgpIHsKICAgICAgICB2YXIgcHRyID0gZGVzdHJ1Y3RvcnMucG9wKCk7CiAgICAgICAgdmFyIGRlbCA9IGRlc3RydWN0b3JzLnBvcCgpOwogICAgICAgIGRlbChwdHIpOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBzaW1wbGVSZWFkVmFsdWVGcm9tUG9pbnRlcihwb2ludGVyKSB7CiAgICAgIHJldHVybiB0aGlzWydmcm9tV2lyZVR5cGUnXShIRUFQVTMyW3BvaW50ZXIgPj4gMl0pCiAgICB9CiAgICB2YXIgYXdhaXRpbmdEZXBlbmRlbmNpZXMgPSB7fTsKICAgIHZhciByZWdpc3RlcmVkVHlwZXMgPSB7fTsKICAgIHZhciB0eXBlRGVwZW5kZW5jaWVzID0ge307CiAgICB2YXIgY2hhcl8wID0gNDg7CiAgICB2YXIgY2hhcl85ID0gNTc7CiAgICBmdW5jdGlvbiBtYWtlTGVnYWxGdW5jdGlvbk5hbWUobmFtZSkgewogICAgICBpZiAodW5kZWZpbmVkID09PSBuYW1lKSB7CiAgICAgICAgcmV0dXJuICdfdW5rbm93bicKICAgICAgfQogICAgICBuYW1lID0gbmFtZS5yZXBsYWNlKC9bXmEtekEtWjAtOV9dL2csICckJyk7CiAgICAgIHZhciBmID0gbmFtZS5jaGFyQ29kZUF0KDApOwogICAgICBpZiAoZiA+PSBjaGFyXzAgJiYgZiA8PSBjaGFyXzkpIHsKICAgICAgICByZXR1cm4gJ18nICsgbmFtZQogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBuYW1lCiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIGNyZWF0ZU5hbWVkRnVuY3Rpb24obmFtZSwgYm9keSkgewogICAgICBuYW1lID0gbWFrZUxlZ2FsRnVuY3Rpb25OYW1lKG5hbWUpOwogICAgICByZXR1cm4gbmV3IEZ1bmN0aW9uKAogICAgICAgICdib2R5JywKICAgICAgICAncmV0dXJuIGZ1bmN0aW9uICcgKyBuYW1lICsgJygpIHtcbicgKyAnICAgICJ1c2Ugc3RyaWN0IjsnICsgJyAgICByZXR1cm4gYm9keS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuJyArICd9O1xuJwogICAgICApKGJvZHkpCiAgICB9CiAgICBmdW5jdGlvbiBleHRlbmRFcnJvcihiYXNlRXJyb3JUeXBlLCBlcnJvck5hbWUpIHsKICAgICAgdmFyIGVycm9yQ2xhc3MgPSBjcmVhdGVOYW1lZEZ1bmN0aW9uKGVycm9yTmFtZSwgZnVuY3Rpb24gKG1lc3NhZ2UpIHsKICAgICAgICB0aGlzLm5hbWUgPSBlcnJvck5hbWU7CiAgICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTsKICAgICAgICB2YXIgc3RhY2sgPSBuZXcgRXJyb3IobWVzc2FnZSkuc3RhY2s7CiAgICAgICAgaWYgKHN0YWNrICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHRoaXMuc3RhY2sgPSB0aGlzLnRvU3RyaW5nKCkgKyAnXG4nICsgc3RhY2sucmVwbGFjZSgvXkVycm9yKDpbXlxuXSopP1xuLywgJycpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGVycm9yQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShiYXNlRXJyb3JUeXBlLnByb3RvdHlwZSk7CiAgICAgIGVycm9yQ2xhc3MucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gZXJyb3JDbGFzczsKICAgICAgZXJyb3JDbGFzcy5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgaWYgKHRoaXMubWVzc2FnZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5uYW1lCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiB0aGlzLm5hbWUgKyAnOiAnICsgdGhpcy5tZXNzYWdlCiAgICAgICAgfQogICAgICB9OwogICAgICByZXR1cm4gZXJyb3JDbGFzcwogICAgfQogICAgdmFyIEludGVybmFsRXJyb3IgPSB1bmRlZmluZWQ7CiAgICBmdW5jdGlvbiB0aHJvd0ludGVybmFsRXJyb3IobWVzc2FnZSkgewogICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihtZXNzYWdlKQogICAgfQogICAgZnVuY3Rpb24gd2hlbkRlcGVuZGVudFR5cGVzQXJlUmVzb2x2ZWQobXlUeXBlcywgZGVwZW5kZW50VHlwZXMsIGdldFR5cGVDb252ZXJ0ZXJzKSB7CiAgICAgIG15VHlwZXMuZm9yRWFjaChmdW5jdGlvbiAodHlwZSkgewogICAgICAgIHR5cGVEZXBlbmRlbmNpZXNbdHlwZV0gPSBkZXBlbmRlbnRUeXBlczsKICAgICAgfSk7CiAgICAgIGZ1bmN0aW9uIG9uQ29tcGxldGUodHlwZUNvbnZlcnRlcnMpIHsKICAgICAgICB2YXIgbXlUeXBlQ29udmVydGVycyA9IGdldFR5cGVDb252ZXJ0ZXJzKHR5cGVDb252ZXJ0ZXJzKTsKICAgICAgICBpZiAobXlUeXBlQ29udmVydGVycy5sZW5ndGggIT09IG15VHlwZXMubGVuZ3RoKSB7CiAgICAgICAgICB0aHJvd0ludGVybmFsRXJyb3IoJ01pc21hdGNoZWQgdHlwZSBjb252ZXJ0ZXIgY291bnQnKTsKICAgICAgICB9CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBteVR5cGVzLmxlbmd0aDsgKytpKSB7CiAgICAgICAgICByZWdpc3RlclR5cGUobXlUeXBlc1tpXSwgbXlUeXBlQ29udmVydGVyc1tpXSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHZhciB0eXBlQ29udmVydGVycyA9IG5ldyBBcnJheShkZXBlbmRlbnRUeXBlcy5sZW5ndGgpOwogICAgICB2YXIgdW5yZWdpc3RlcmVkVHlwZXMgPSBbXTsKICAgICAgdmFyIHJlZ2lzdGVyZWQgPSAwOwogICAgICBkZXBlbmRlbnRUeXBlcy5mb3JFYWNoKGZ1bmN0aW9uIChkdCwgaSkgewogICAgICAgIGlmIChyZWdpc3RlcmVkVHlwZXMuaGFzT3duUHJvcGVydHkoZHQpKSB7CiAgICAgICAgICB0eXBlQ29udmVydGVyc1tpXSA9IHJlZ2lzdGVyZWRUeXBlc1tkdF07CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHVucmVnaXN0ZXJlZFR5cGVzLnB1c2goZHQpOwogICAgICAgICAgaWYgKCFhd2FpdGluZ0RlcGVuZGVuY2llcy5oYXNPd25Qcm9wZXJ0eShkdCkpIHsKICAgICAgICAgICAgYXdhaXRpbmdEZXBlbmRlbmNpZXNbZHRdID0gW107CiAgICAgICAgICB9CiAgICAgICAgICBhd2FpdGluZ0RlcGVuZGVuY2llc1tkdF0ucHVzaChmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIHR5cGVDb252ZXJ0ZXJzW2ldID0gcmVnaXN0ZXJlZFR5cGVzW2R0XTsKICAgICAgICAgICAgKytyZWdpc3RlcmVkOwogICAgICAgICAgICBpZiAocmVnaXN0ZXJlZCA9PT0gdW5yZWdpc3RlcmVkVHlwZXMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgb25Db21wbGV0ZSh0eXBlQ29udmVydGVycyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGlmICgwID09PSB1bnJlZ2lzdGVyZWRUeXBlcy5sZW5ndGgpIHsKICAgICAgICBvbkNvbXBsZXRlKHR5cGVDb252ZXJ0ZXJzKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gX19lbWJpbmRfZmluYWxpemVfdmFsdWVfb2JqZWN0KHN0cnVjdFR5cGUpIHsKICAgICAgdmFyIHJlZyA9IHN0cnVjdFJlZ2lzdHJhdGlvbnNbc3RydWN0VHlwZV07CiAgICAgIGRlbGV0ZSBzdHJ1Y3RSZWdpc3RyYXRpb25zW3N0cnVjdFR5cGVdOwogICAgICB2YXIgcmF3Q29uc3RydWN0b3IgPSByZWcucmF3Q29uc3RydWN0b3I7CiAgICAgIHZhciByYXdEZXN0cnVjdG9yID0gcmVnLnJhd0Rlc3RydWN0b3I7CiAgICAgIHZhciBmaWVsZFJlY29yZHMgPSByZWcuZmllbGRzOwogICAgICB2YXIgZmllbGRUeXBlcyA9IGZpZWxkUmVjb3JkcwogICAgICAgIC5tYXAoZnVuY3Rpb24gKGZpZWxkKSB7CiAgICAgICAgICByZXR1cm4gZmllbGQuZ2V0dGVyUmV0dXJuVHlwZQogICAgICAgIH0pCiAgICAgICAgLmNvbmNhdCgKICAgICAgICAgIGZpZWxkUmVjb3Jkcy5tYXAoZnVuY3Rpb24gKGZpZWxkKSB7CiAgICAgICAgICAgIHJldHVybiBmaWVsZC5zZXR0ZXJBcmd1bWVudFR5cGUKICAgICAgICAgIH0pCiAgICAgICAgKTsKICAgICAgd2hlbkRlcGVuZGVudFR5cGVzQXJlUmVzb2x2ZWQoW3N0cnVjdFR5cGVdLCBmaWVsZFR5cGVzLCBmdW5jdGlvbiAoZmllbGRUeXBlcykgewogICAgICAgIHZhciBmaWVsZHMgPSB7fTsKICAgICAgICBmaWVsZFJlY29yZHMuZm9yRWFjaChmdW5jdGlvbiAoZmllbGQsIGkpIHsKICAgICAgICAgIHZhciBmaWVsZE5hbWUgPSBmaWVsZC5maWVsZE5hbWU7CiAgICAgICAgICB2YXIgZ2V0dGVyUmV0dXJuVHlwZSA9IGZpZWxkVHlwZXNbaV07CiAgICAgICAgICB2YXIgZ2V0dGVyID0gZmllbGQuZ2V0dGVyOwogICAgICAgICAgdmFyIGdldHRlckNvbnRleHQgPSBmaWVsZC5nZXR0ZXJDb250ZXh0OwogICAgICAgICAgdmFyIHNldHRlckFyZ3VtZW50VHlwZSA9IGZpZWxkVHlwZXNbaSArIGZpZWxkUmVjb3Jkcy5sZW5ndGhdOwogICAgICAgICAgdmFyIHNldHRlciA9IGZpZWxkLnNldHRlcjsKICAgICAgICAgIHZhciBzZXR0ZXJDb250ZXh0ID0gZmllbGQuc2V0dGVyQ29udGV4dDsKICAgICAgICAgIGZpZWxkc1tmaWVsZE5hbWVdID0gewogICAgICAgICAgICByZWFkOiBmdW5jdGlvbiAocHRyKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGdldHRlclJldHVyblR5cGVbJ2Zyb21XaXJlVHlwZSddKGdldHRlcihnZXR0ZXJDb250ZXh0LCBwdHIpKQogICAgICAgICAgICB9LAogICAgICAgICAgICB3cml0ZTogZnVuY3Rpb24gKHB0ciwgbykgewogICAgICAgICAgICAgIHZhciBkZXN0cnVjdG9ycyA9IFtdOwogICAgICAgICAgICAgIHNldHRlcihzZXR0ZXJDb250ZXh0LCBwdHIsIHNldHRlckFyZ3VtZW50VHlwZVsndG9XaXJlVHlwZSddKGRlc3RydWN0b3JzLCBvKSk7CiAgICAgICAgICAgICAgcnVuRGVzdHJ1Y3RvcnMoZGVzdHJ1Y3RvcnMpOwogICAgICAgICAgICB9LAogICAgICAgICAgfTsKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gWwogICAgICAgICAgewogICAgICAgICAgICBuYW1lOiByZWcubmFtZSwKICAgICAgICAgICAgZnJvbVdpcmVUeXBlOiBmdW5jdGlvbiAocHRyKSB7CiAgICAgICAgICAgICAgdmFyIHJ2ID0ge307CiAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBmaWVsZHMpIHsKICAgICAgICAgICAgICAgIHJ2W2ldID0gZmllbGRzW2ldLnJlYWQocHRyKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmF3RGVzdHJ1Y3RvcihwdHIpOwogICAgICAgICAgICAgIHJldHVybiBydgogICAgICAgICAgICB9LAogICAgICAgICAgICB0b1dpcmVUeXBlOiBmdW5jdGlvbiAoZGVzdHJ1Y3RvcnMsIG8pIHsKICAgICAgICAgICAgICBmb3IgKHZhciBmaWVsZE5hbWUgaW4gZmllbGRzKSB7CiAgICAgICAgICAgICAgICBpZiAoIShmaWVsZE5hbWUgaW4gbykpIHsKICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignTWlzc2luZyBmaWVsZCcpCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHZhciBwdHIgPSByYXdDb25zdHJ1Y3RvcigpOwogICAgICAgICAgICAgIGZvciAoZmllbGROYW1lIGluIGZpZWxkcykgewogICAgICAgICAgICAgICAgZmllbGRzW2ZpZWxkTmFtZV0ud3JpdGUocHRyLCBvW2ZpZWxkTmFtZV0pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoZGVzdHJ1Y3RvcnMgIT09IG51bGwpIHsKICAgICAgICAgICAgICAgIGRlc3RydWN0b3JzLnB1c2gocmF3RGVzdHJ1Y3RvciwgcHRyKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIHB0cgogICAgICAgICAgICB9LAogICAgICAgICAgICBhcmdQYWNrQWR2YW5jZTogOCwKICAgICAgICAgICAgcmVhZFZhbHVlRnJvbVBvaW50ZXI6IHNpbXBsZVJlYWRWYWx1ZUZyb21Qb2ludGVyLAogICAgICAgICAgICBkZXN0cnVjdG9yRnVuY3Rpb246IHJhd0Rlc3RydWN0b3IsCiAgICAgICAgICB9LAogICAgICAgIF0KICAgICAgfSk7CiAgICB9CiAgICBmdW5jdGlvbiBnZXRTaGlmdEZyb21TaXplKHNpemUpIHsKICAgICAgc3dpdGNoIChzaXplKSB7CiAgICAgICAgY2FzZSAxOgogICAgICAgICAgcmV0dXJuIDAKICAgICAgICBjYXNlIDI6CiAgICAgICAgICByZXR1cm4gMQogICAgICAgIGNhc2UgNDoKICAgICAgICAgIHJldHVybiAyCiAgICAgICAgY2FzZSA4OgogICAgICAgICAgcmV0dXJuIDMKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biB0eXBlIHNpemU6ICcgKyBzaXplKQogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBlbWJpbmRfaW5pdF9jaGFyQ29kZXMoKSB7CiAgICAgIHZhciBjb2RlcyA9IG5ldyBBcnJheSgyNTYpOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDI1NjsgKytpKSB7CiAgICAgICAgY29kZXNbaV0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGkpOwogICAgICB9CiAgICAgIGVtYmluZF9jaGFyQ29kZXMgPSBjb2RlczsKICAgIH0KICAgIHZhciBlbWJpbmRfY2hhckNvZGVzID0gdW5kZWZpbmVkOwogICAgZnVuY3Rpb24gcmVhZExhdGluMVN0cmluZyhwdHIpIHsKICAgICAgdmFyIHJldCA9ICcnOwogICAgICB2YXIgYyA9IHB0cjsKICAgICAgd2hpbGUgKEhFQVBVOFtjXSkgewogICAgICAgIHJldCArPSBlbWJpbmRfY2hhckNvZGVzW0hFQVBVOFtjKytdXTsKICAgICAgfQogICAgICByZXR1cm4gcmV0CiAgICB9CiAgICB2YXIgQmluZGluZ0Vycm9yID0gdW5kZWZpbmVkOwogICAgZnVuY3Rpb24gdGhyb3dCaW5kaW5nRXJyb3IobWVzc2FnZSkgewogICAgICB0aHJvdyBuZXcgQmluZGluZ0Vycm9yKG1lc3NhZ2UpCiAgICB9CiAgICBmdW5jdGlvbiByZWdpc3RlclR5cGUocmF3VHlwZSwgcmVnaXN0ZXJlZEluc3RhbmNlLCBvcHRpb25zKSB7CiAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9OwogICAgICBpZiAoISgnYXJnUGFja0FkdmFuY2UnIGluIHJlZ2lzdGVyZWRJbnN0YW5jZSkpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZWdpc3RlclR5cGUgcmVnaXN0ZXJlZEluc3RhbmNlIHJlcXVpcmVzIGFyZ1BhY2tBZHZhbmNlJykKICAgICAgfQogICAgICB2YXIgbmFtZSA9IHJlZ2lzdGVyZWRJbnN0YW5jZS5uYW1lOwogICAgICBpZiAoIXJhd1R5cGUpIHsKICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigndHlwZSAiJyArIG5hbWUgKyAnIiBtdXN0IGhhdmUgYSBwb3NpdGl2ZSBpbnRlZ2VyIHR5cGVpZCBwb2ludGVyJyk7CiAgICAgIH0KICAgICAgaWYgKHJlZ2lzdGVyZWRUeXBlcy5oYXNPd25Qcm9wZXJ0eShyYXdUeXBlKSkgewogICAgICAgIGlmIChvcHRpb25zLmlnbm9yZUR1cGxpY2F0ZVJlZ2lzdHJhdGlvbnMpIHsKICAgICAgICAgIHJldHVybgogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiQ2Fubm90IHJlZ2lzdGVyIHR5cGUgJyIgKyBuYW1lICsgIicgdHdpY2UiKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmVnaXN0ZXJlZFR5cGVzW3Jhd1R5cGVdID0gcmVnaXN0ZXJlZEluc3RhbmNlOwogICAgICBkZWxldGUgdHlwZURlcGVuZGVuY2llc1tyYXdUeXBlXTsKICAgICAgaWYgKGF3YWl0aW5nRGVwZW5kZW5jaWVzLmhhc093blByb3BlcnR5KHJhd1R5cGUpKSB7CiAgICAgICAgdmFyIGNhbGxiYWNrcyA9IGF3YWl0aW5nRGVwZW5kZW5jaWVzW3Jhd1R5cGVdOwogICAgICAgIGRlbGV0ZSBhd2FpdGluZ0RlcGVuZGVuY2llc1tyYXdUeXBlXTsKICAgICAgICBjYWxsYmFja3MuZm9yRWFjaChmdW5jdGlvbiAoY2IpIHsKICAgICAgICAgIGNiKCk7CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIF9fZW1iaW5kX3JlZ2lzdGVyX2Jvb2wocmF3VHlwZSwgbmFtZSwgc2l6ZSwgdHJ1ZVZhbHVlLCBmYWxzZVZhbHVlKSB7CiAgICAgIHZhciBzaGlmdCA9IGdldFNoaWZ0RnJvbVNpemUoc2l6ZSk7CiAgICAgIG5hbWUgPSByZWFkTGF0aW4xU3RyaW5nKG5hbWUpOwogICAgICByZWdpc3RlclR5cGUocmF3VHlwZSwgewogICAgICAgIG5hbWU6IG5hbWUsCiAgICAgICAgZnJvbVdpcmVUeXBlOiBmdW5jdGlvbiAod3QpIHsKICAgICAgICAgIHJldHVybiAhIXd0CiAgICAgICAgfSwKICAgICAgICB0b1dpcmVUeXBlOiBmdW5jdGlvbiAoZGVzdHJ1Y3RvcnMsIG8pIHsKICAgICAgICAgIHJldHVybiBvID8gdHJ1ZVZhbHVlIDogZmFsc2VWYWx1ZQogICAgICAgIH0sCiAgICAgICAgYXJnUGFja0FkdmFuY2U6IDgsCiAgICAgICAgcmVhZFZhbHVlRnJvbVBvaW50ZXI6IGZ1bmN0aW9uIChwb2ludGVyKSB7CiAgICAgICAgICB2YXIgaGVhcDsKICAgICAgICAgIGlmIChzaXplID09PSAxKSB7CiAgICAgICAgICAgIGhlYXAgPSBIRUFQODsKICAgICAgICAgIH0gZWxzZSBpZiAoc2l6ZSA9PT0gMikgewogICAgICAgICAgICBoZWFwID0gSEVBUDE2OwogICAgICAgICAgfSBlbHNlIGlmIChzaXplID09PSA0KSB7CiAgICAgICAgICAgIGhlYXAgPSBIRUFQMzI7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGJvb2xlYW4gdHlwZSBzaXplOiAnICsgbmFtZSkKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzWydmcm9tV2lyZVR5cGUnXShoZWFwW3BvaW50ZXIgPj4gc2hpZnRdKQogICAgICAgIH0sCiAgICAgICAgZGVzdHJ1Y3RvckZ1bmN0aW9uOiBudWxsLAogICAgICB9KTsKICAgIH0KICAgIGZ1bmN0aW9uIENsYXNzSGFuZGxlX2lzQWxpYXNPZihvdGhlcikgewogICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgQ2xhc3NIYW5kbGUpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlCiAgICAgIH0KICAgICAgaWYgKCEob3RoZXIgaW5zdGFuY2VvZiBDbGFzc0hhbmRsZSkpIHsKICAgICAgICByZXR1cm4gZmFsc2UKICAgICAgfQogICAgICB2YXIgbGVmdENsYXNzID0gdGhpcy4kJC5wdHJUeXBlLnJlZ2lzdGVyZWRDbGFzczsKICAgICAgdmFyIGxlZnQgPSB0aGlzLiQkLnB0cjsKICAgICAgdmFyIHJpZ2h0Q2xhc3MgPSBvdGhlci4kJC5wdHJUeXBlLnJlZ2lzdGVyZWRDbGFzczsKICAgICAgdmFyIHJpZ2h0ID0gb3RoZXIuJCQucHRyOwogICAgICB3aGlsZSAobGVmdENsYXNzLmJhc2VDbGFzcykgewogICAgICAgIGxlZnQgPSBsZWZ0Q2xhc3MudXBjYXN0KGxlZnQpOwogICAgICAgIGxlZnRDbGFzcyA9IGxlZnRDbGFzcy5iYXNlQ2xhc3M7CiAgICAgIH0KICAgICAgd2hpbGUgKHJpZ2h0Q2xhc3MuYmFzZUNsYXNzKSB7CiAgICAgICAgcmlnaHQgPSByaWdodENsYXNzLnVwY2FzdChyaWdodCk7CiAgICAgICAgcmlnaHRDbGFzcyA9IHJpZ2h0Q2xhc3MuYmFzZUNsYXNzOwogICAgICB9CiAgICAgIHJldHVybiBsZWZ0Q2xhc3MgPT09IHJpZ2h0Q2xhc3MgJiYgbGVmdCA9PT0gcmlnaHQKICAgIH0KICAgIGZ1bmN0aW9uIHNoYWxsb3dDb3B5SW50ZXJuYWxQb2ludGVyKG8pIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBjb3VudDogby5jb3VudCwKICAgICAgICBkZWxldGVTY2hlZHVsZWQ6IG8uZGVsZXRlU2NoZWR1bGVkLAogICAgICAgIHByZXNlcnZlUG9pbnRlck9uRGVsZXRlOiBvLnByZXNlcnZlUG9pbnRlck9uRGVsZXRlLAogICAgICAgIHB0cjogby5wdHIsCiAgICAgICAgcHRyVHlwZTogby5wdHJUeXBlLAogICAgICAgIHNtYXJ0UHRyOiBvLnNtYXJ0UHRyLAogICAgICAgIHNtYXJ0UHRyVHlwZTogby5zbWFydFB0clR5cGUsCiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIHRocm93SW5zdGFuY2VBbHJlYWR5RGVsZXRlZChvYmopIHsKICAgICAgZnVuY3Rpb24gZ2V0SW5zdGFuY2VUeXBlTmFtZShoYW5kbGUpIHsKICAgICAgICByZXR1cm4gaGFuZGxlLiQkLnB0clR5cGUucmVnaXN0ZXJlZENsYXNzLm5hbWUKICAgICAgfQogICAgICB0aHJvd0JpbmRpbmdFcnJvcihnZXRJbnN0YW5jZVR5cGVOYW1lKG9iaikgKyAnIGluc3RhbmNlIGFscmVhZHkgZGVsZXRlZCcpOwogICAgfQogICAgZnVuY3Rpb24gQ2xhc3NIYW5kbGVfY2xvbmUoKSB7CiAgICAgIGlmICghdGhpcy4kJC5wdHIpIHsKICAgICAgICB0aHJvd0luc3RhbmNlQWxyZWFkeURlbGV0ZWQodGhpcyk7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuJCQucHJlc2VydmVQb2ludGVyT25EZWxldGUpIHsKICAgICAgICB0aGlzLiQkLmNvdW50LnZhbHVlICs9IDE7CiAgICAgICAgcmV0dXJuIHRoaXMKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgY2xvbmUgPSBPYmplY3QuY3JlYXRlKE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzKSwgeyAkJDogeyB2YWx1ZTogc2hhbGxvd0NvcHlJbnRlcm5hbFBvaW50ZXIodGhpcy4kJCkgfSB9KTsKICAgICAgICBjbG9uZS4kJC5jb3VudC52YWx1ZSArPSAxOwogICAgICAgIGNsb25lLiQkLmRlbGV0ZVNjaGVkdWxlZCA9IGZhbHNlOwogICAgICAgIHJldHVybiBjbG9uZQogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBydW5EZXN0cnVjdG9yKGhhbmRsZSkgewogICAgICB2YXIgJCQgPSBoYW5kbGUuJCQ7CiAgICAgIGlmICgkJC5zbWFydFB0cikgewogICAgICAgICQkLnNtYXJ0UHRyVHlwZS5yYXdEZXN0cnVjdG9yKCQkLnNtYXJ0UHRyKTsKICAgICAgfSBlbHNlIHsKICAgICAgICAkJC5wdHJUeXBlLnJlZ2lzdGVyZWRDbGFzcy5yYXdEZXN0cnVjdG9yKCQkLnB0cik7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIENsYXNzSGFuZGxlX2RlbGV0ZSgpIHsKICAgICAgaWYgKCF0aGlzLiQkLnB0cikgewogICAgICAgIHRocm93SW5zdGFuY2VBbHJlYWR5RGVsZXRlZCh0aGlzKTsKICAgICAgfQogICAgICBpZiAodGhpcy4kJC5kZWxldGVTY2hlZHVsZWQgJiYgIXRoaXMuJCQucHJlc2VydmVQb2ludGVyT25EZWxldGUpIHsKICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcignT2JqZWN0IGFscmVhZHkgc2NoZWR1bGVkIGZvciBkZWxldGlvbicpOwogICAgICB9CiAgICAgIHRoaXMuJCQuY291bnQudmFsdWUgLT0gMTsKICAgICAgdmFyIHRvRGVsZXRlID0gMCA9PT0gdGhpcy4kJC5jb3VudC52YWx1ZTsKICAgICAgaWYgKHRvRGVsZXRlKSB7CiAgICAgICAgcnVuRGVzdHJ1Y3Rvcih0aGlzKTsKICAgICAgfQogICAgICBpZiAoIXRoaXMuJCQucHJlc2VydmVQb2ludGVyT25EZWxldGUpIHsKICAgICAgICB0aGlzLiQkLnNtYXJ0UHRyID0gdW5kZWZpbmVkOwogICAgICAgIHRoaXMuJCQucHRyID0gdW5kZWZpbmVkOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBDbGFzc0hhbmRsZV9pc0RlbGV0ZWQoKSB7CiAgICAgIHJldHVybiAhdGhpcy4kJC5wdHIKICAgIH0KICAgIHZhciBkZWxheUZ1bmN0aW9uID0gdW5kZWZpbmVkOwogICAgdmFyIGRlbGV0aW9uUXVldWUgPSBbXTsKICAgIGZ1bmN0aW9uIGZsdXNoUGVuZGluZ0RlbGV0ZXMoKSB7CiAgICAgIHdoaWxlIChkZWxldGlvblF1ZXVlLmxlbmd0aCkgewogICAgICAgIHZhciBvYmogPSBkZWxldGlvblF1ZXVlLnBvcCgpOwogICAgICAgIG9iai4kJC5kZWxldGVTY2hlZHVsZWQgPSBmYWxzZTsKICAgICAgICBvYmpbJ2RlbGV0ZSddKCk7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIENsYXNzSGFuZGxlX2RlbGV0ZUxhdGVyKCkgewogICAgICBpZiAoIXRoaXMuJCQucHRyKSB7CiAgICAgICAgdGhyb3dJbnN0YW5jZUFscmVhZHlEZWxldGVkKHRoaXMpOwogICAgICB9CiAgICAgIGlmICh0aGlzLiQkLmRlbGV0ZVNjaGVkdWxlZCAmJiAhdGhpcy4kJC5wcmVzZXJ2ZVBvaW50ZXJPbkRlbGV0ZSkgewogICAgICAgIHRocm93QmluZGluZ0Vycm9yKCdPYmplY3QgYWxyZWFkeSBzY2hlZHVsZWQgZm9yIGRlbGV0aW9uJyk7CiAgICAgIH0KICAgICAgZGVsZXRpb25RdWV1ZS5wdXNoKHRoaXMpOwogICAgICBpZiAoZGVsZXRpb25RdWV1ZS5sZW5ndGggPT09IDEgJiYgZGVsYXlGdW5jdGlvbikgewogICAgICAgIGRlbGF5RnVuY3Rpb24oZmx1c2hQZW5kaW5nRGVsZXRlcyk7CiAgICAgIH0KICAgICAgdGhpcy4kJC5kZWxldGVTY2hlZHVsZWQgPSB0cnVlOwogICAgICByZXR1cm4gdGhpcwogICAgfQogICAgZnVuY3Rpb24gaW5pdF9DbGFzc0hhbmRsZSgpIHsKICAgICAgQ2xhc3NIYW5kbGUucHJvdG90eXBlWydpc0FsaWFzT2YnXSA9IENsYXNzSGFuZGxlX2lzQWxpYXNPZjsKICAgICAgQ2xhc3NIYW5kbGUucHJvdG90eXBlWydjbG9uZSddID0gQ2xhc3NIYW5kbGVfY2xvbmU7CiAgICAgIENsYXNzSGFuZGxlLnByb3RvdHlwZVsnZGVsZXRlJ10gPSBDbGFzc0hhbmRsZV9kZWxldGU7CiAgICAgIENsYXNzSGFuZGxlLnByb3RvdHlwZVsnaXNEZWxldGVkJ10gPSBDbGFzc0hhbmRsZV9pc0RlbGV0ZWQ7CiAgICAgIENsYXNzSGFuZGxlLnByb3RvdHlwZVsnZGVsZXRlTGF0ZXInXSA9IENsYXNzSGFuZGxlX2RlbGV0ZUxhdGVyOwogICAgfQogICAgZnVuY3Rpb24gQ2xhc3NIYW5kbGUoKSB7fQogICAgdmFyIHJlZ2lzdGVyZWRQb2ludGVycyA9IHt9OwogICAgZnVuY3Rpb24gZW5zdXJlT3ZlcmxvYWRUYWJsZShwcm90bywgbWV0aG9kTmFtZSwgaHVtYW5OYW1lKSB7CiAgICAgIGlmICh1bmRlZmluZWQgPT09IHByb3RvW21ldGhvZE5hbWVdLm92ZXJsb2FkVGFibGUpIHsKICAgICAgICB2YXIgcHJldkZ1bmMgPSBwcm90b1ttZXRob2ROYW1lXTsKICAgICAgICBwcm90b1ttZXRob2ROYW1lXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgIGlmICghcHJvdG9bbWV0aG9kTmFtZV0ub3ZlcmxvYWRUYWJsZS5oYXNPd25Qcm9wZXJ0eShhcmd1bWVudHMubGVuZ3RoKSkgewogICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigKICAgICAgICAgICAgICAiRnVuY3Rpb24gJyIgKwogICAgICAgICAgICAgICAgaHVtYW5OYW1lICsKICAgICAgICAgICAgICAgICInIGNhbGxlZCB3aXRoIGFuIGludmFsaWQgbnVtYmVyIG9mIGFyZ3VtZW50cyAoIiArCiAgICAgICAgICAgICAgICBhcmd1bWVudHMubGVuZ3RoICsKICAgICAgICAgICAgICAgICcpIC0gZXhwZWN0cyBvbmUgb2YgKCcgKwogICAgICAgICAgICAgICAgcHJvdG9bbWV0aG9kTmFtZV0ub3ZlcmxvYWRUYWJsZSArCiAgICAgICAgICAgICAgICAnKSEnCiAgICAgICAgICAgICk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gcHJvdG9bbWV0aG9kTmFtZV0ub3ZlcmxvYWRUYWJsZVthcmd1bWVudHMubGVuZ3RoXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpCiAgICAgICAgfTsKICAgICAgICBwcm90b1ttZXRob2ROYW1lXS5vdmVybG9hZFRhYmxlID0gW107CiAgICAgICAgcHJvdG9bbWV0aG9kTmFtZV0ub3ZlcmxvYWRUYWJsZVtwcmV2RnVuYy5hcmdDb3VudF0gPSBwcmV2RnVuYzsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gZXhwb3NlUHVibGljU3ltYm9sKG5hbWUsIHZhbHVlLCBudW1Bcmd1bWVudHMpIHsKICAgICAgaWYgKE1vZHVsZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICAgIGlmICgKICAgICAgICAgIHVuZGVmaW5lZCA9PT0gbnVtQXJndW1lbnRzIHx8CiAgICAgICAgICAodW5kZWZpbmVkICE9PSBNb2R1bGVbbmFtZV0ub3ZlcmxvYWRUYWJsZSAmJiB1bmRlZmluZWQgIT09IE1vZHVsZVtuYW1lXS5vdmVybG9hZFRhYmxlW251bUFyZ3VtZW50c10pCiAgICAgICAgKSB7CiAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiQ2Fubm90IHJlZ2lzdGVyIHB1YmxpYyBuYW1lICciICsgbmFtZSArICInIHR3aWNlIik7CiAgICAgICAgfQogICAgICAgIGVuc3VyZU92ZXJsb2FkVGFibGUoTW9kdWxlLCBuYW1lLCBuYW1lKTsKICAgICAgICBpZiAoTW9kdWxlLmhhc093blByb3BlcnR5KG51bUFyZ3VtZW50cykpIHsKICAgICAgICAgIHRocm93QmluZGluZ0Vycm9yKAogICAgICAgICAgICAnQ2Fubm90IHJlZ2lzdGVyIG11bHRpcGxlIG92ZXJsb2FkcyBvZiBhIGZ1bmN0aW9uIHdpdGggdGhlIHNhbWUgbnVtYmVyIG9mIGFyZ3VtZW50cyAoJyArIG51bUFyZ3VtZW50cyArICcpIScKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIE1vZHVsZVtuYW1lXS5vdmVybG9hZFRhYmxlW251bUFyZ3VtZW50c10gPSB2YWx1ZTsKICAgICAgfSBlbHNlIHsKICAgICAgICBNb2R1bGVbbmFtZV0gPSB2YWx1ZTsKICAgICAgICBpZiAodW5kZWZpbmVkICE9PSBudW1Bcmd1bWVudHMpIHsKICAgICAgICAgIE1vZHVsZVtuYW1lXS5udW1Bcmd1bWVudHMgPSBudW1Bcmd1bWVudHM7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBSZWdpc3RlcmVkQ2xhc3MoCiAgICAgIG5hbWUsCiAgICAgIGNvbnN0cnVjdG9yLAogICAgICBpbnN0YW5jZVByb3RvdHlwZSwKICAgICAgcmF3RGVzdHJ1Y3RvciwKICAgICAgYmFzZUNsYXNzLAogICAgICBnZXRBY3R1YWxUeXBlLAogICAgICB1cGNhc3QsCiAgICAgIGRvd25jYXN0CiAgICApIHsKICAgICAgdGhpcy5uYW1lID0gbmFtZTsKICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGNvbnN0cnVjdG9yOwogICAgICB0aGlzLmluc3RhbmNlUHJvdG90eXBlID0gaW5zdGFuY2VQcm90b3R5cGU7CiAgICAgIHRoaXMucmF3RGVzdHJ1Y3RvciA9IHJhd0Rlc3RydWN0b3I7CiAgICAgIHRoaXMuYmFzZUNsYXNzID0gYmFzZUNsYXNzOwogICAgICB0aGlzLmdldEFjdHVhbFR5cGUgPSBnZXRBY3R1YWxUeXBlOwogICAgICB0aGlzLnVwY2FzdCA9IHVwY2FzdDsKICAgICAgdGhpcy5kb3duY2FzdCA9IGRvd25jYXN0OwogICAgICB0aGlzLnB1cmVWaXJ0dWFsRnVuY3Rpb25zID0gW107CiAgICB9CiAgICBmdW5jdGlvbiB1cGNhc3RQb2ludGVyKHB0ciwgcHRyQ2xhc3MsIGRlc2lyZWRDbGFzcykgewogICAgICB3aGlsZSAocHRyQ2xhc3MgIT09IGRlc2lyZWRDbGFzcykgewogICAgICAgIGlmICghcHRyQ2xhc3MudXBjYXN0KSB7CiAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcignRXhwZWN0ZWQgbnVsbCBvciBpbnN0YW5jZSBvZiAnICsgZGVzaXJlZENsYXNzLm5hbWUgKyAnLCBnb3QgYW4gaW5zdGFuY2Ugb2YgJyArIHB0ckNsYXNzLm5hbWUpOwogICAgICAgIH0KICAgICAgICBwdHIgPSBwdHJDbGFzcy51cGNhc3QocHRyKTsKICAgICAgICBwdHJDbGFzcyA9IHB0ckNsYXNzLmJhc2VDbGFzczsKICAgICAgfQogICAgICByZXR1cm4gcHRyCiAgICB9CiAgICBmdW5jdGlvbiBjb25zdE5vU21hcnRQdHJSYXdQb2ludGVyVG9XaXJlVHlwZShkZXN0cnVjdG9ycywgaGFuZGxlKSB7CiAgICAgIGlmIChoYW5kbGUgPT09IG51bGwpIHsKICAgICAgICBpZiAodGhpcy5pc1JlZmVyZW5jZSkgewogICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoJ251bGwgaXMgbm90IGEgdmFsaWQgJyArIHRoaXMubmFtZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiAwCiAgICAgIH0KICAgICAgaWYgKCFoYW5kbGUuJCQpIHsKICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcignQ2Fubm90IHBhc3MgIicgKyBfZW1iaW5kX3JlcHIoaGFuZGxlKSArICciIGFzIGEgJyArIHRoaXMubmFtZSk7CiAgICAgIH0KICAgICAgaWYgKCFoYW5kbGUuJCQucHRyKSB7CiAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoJ0Nhbm5vdCBwYXNzIGRlbGV0ZWQgb2JqZWN0IGFzIGEgcG9pbnRlciBvZiB0eXBlICcgKyB0aGlzLm5hbWUpOwogICAgICB9CiAgICAgIHZhciBoYW5kbGVDbGFzcyA9IGhhbmRsZS4kJC5wdHJUeXBlLnJlZ2lzdGVyZWRDbGFzczsKICAgICAgdmFyIHB0ciA9IHVwY2FzdFBvaW50ZXIoaGFuZGxlLiQkLnB0ciwgaGFuZGxlQ2xhc3MsIHRoaXMucmVnaXN0ZXJlZENsYXNzKTsKICAgICAgcmV0dXJuIHB0cgogICAgfQogICAgZnVuY3Rpb24gZ2VuZXJpY1BvaW50ZXJUb1dpcmVUeXBlKGRlc3RydWN0b3JzLCBoYW5kbGUpIHsKICAgICAgdmFyIHB0cjsKICAgICAgaWYgKGhhbmRsZSA9PT0gbnVsbCkgewogICAgICAgIGlmICh0aGlzLmlzUmVmZXJlbmNlKSB7CiAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcignbnVsbCBpcyBub3QgYSB2YWxpZCAnICsgdGhpcy5uYW1lKTsKICAgICAgICB9CiAgICAgICAgaWYgKHRoaXMuaXNTbWFydFBvaW50ZXIpIHsKICAgICAgICAgIHB0ciA9IHRoaXMucmF3Q29uc3RydWN0b3IoKTsKICAgICAgICAgIGlmIChkZXN0cnVjdG9ycyAhPT0gbnVsbCkgewogICAgICAgICAgICBkZXN0cnVjdG9ycy5wdXNoKHRoaXMucmF3RGVzdHJ1Y3RvciwgcHRyKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBwdHIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIDAKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCFoYW5kbGUuJCQpIHsKICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcignQ2Fubm90IHBhc3MgIicgKyBfZW1iaW5kX3JlcHIoaGFuZGxlKSArICciIGFzIGEgJyArIHRoaXMubmFtZSk7CiAgICAgIH0KICAgICAgaWYgKCFoYW5kbGUuJCQucHRyKSB7CiAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoJ0Nhbm5vdCBwYXNzIGRlbGV0ZWQgb2JqZWN0IGFzIGEgcG9pbnRlciBvZiB0eXBlICcgKyB0aGlzLm5hbWUpOwogICAgICB9CiAgICAgIGlmICghdGhpcy5pc0NvbnN0ICYmIGhhbmRsZS4kJC5wdHJUeXBlLmlzQ29uc3QpIHsKICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigKICAgICAgICAgICdDYW5ub3QgY29udmVydCBhcmd1bWVudCBvZiB0eXBlICcgKwogICAgICAgICAgICAoaGFuZGxlLiQkLnNtYXJ0UHRyVHlwZSA/IGhhbmRsZS4kJC5zbWFydFB0clR5cGUubmFtZSA6IGhhbmRsZS4kJC5wdHJUeXBlLm5hbWUpICsKICAgICAgICAgICAgJyB0byBwYXJhbWV0ZXIgdHlwZSAnICsKICAgICAgICAgICAgdGhpcy5uYW1lCiAgICAgICAgKTsKICAgICAgfQogICAgICB2YXIgaGFuZGxlQ2xhc3MgPSBoYW5kbGUuJCQucHRyVHlwZS5yZWdpc3RlcmVkQ2xhc3M7CiAgICAgIHB0ciA9IHVwY2FzdFBvaW50ZXIoaGFuZGxlLiQkLnB0ciwgaGFuZGxlQ2xhc3MsIHRoaXMucmVnaXN0ZXJlZENsYXNzKTsKICAgICAgaWYgKHRoaXMuaXNTbWFydFBvaW50ZXIpIHsKICAgICAgICBpZiAodW5kZWZpbmVkID09PSBoYW5kbGUuJCQuc21hcnRQdHIpIHsKICAgICAgICAgIHRocm93QmluZGluZ0Vycm9yKCdQYXNzaW5nIHJhdyBwb2ludGVyIHRvIHNtYXJ0IHBvaW50ZXIgaXMgaWxsZWdhbCcpOwogICAgICAgIH0KICAgICAgICBzd2l0Y2ggKHRoaXMuc2hhcmluZ1BvbGljeSkgewogICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICBpZiAoaGFuZGxlLiQkLnNtYXJ0UHRyVHlwZSA9PT0gdGhpcykgewogICAgICAgICAgICAgIHB0ciA9IGhhbmRsZS4kJC5zbWFydFB0cjsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigKICAgICAgICAgICAgICAgICdDYW5ub3QgY29udmVydCBhcmd1bWVudCBvZiB0eXBlICcgKwogICAgICAgICAgICAgICAgICAoaGFuZGxlLiQkLnNtYXJ0UHRyVHlwZSA/IGhhbmRsZS4kJC5zbWFydFB0clR5cGUubmFtZSA6IGhhbmRsZS4kJC5wdHJUeXBlLm5hbWUpICsKICAgICAgICAgICAgICAgICAgJyB0byBwYXJhbWV0ZXIgdHlwZSAnICsKICAgICAgICAgICAgICAgICAgdGhpcy5uYW1lCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhawogICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICBwdHIgPSBoYW5kbGUuJCQuc21hcnRQdHI7CiAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgIGlmIChoYW5kbGUuJCQuc21hcnRQdHJUeXBlID09PSB0aGlzKSB7CiAgICAgICAgICAgICAgcHRyID0gaGFuZGxlLiQkLnNtYXJ0UHRyOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHZhciBjbG9uZWRIYW5kbGUgPSBoYW5kbGVbJ2Nsb25lJ10oKTsKICAgICAgICAgICAgICBwdHIgPSB0aGlzLnJhd1NoYXJlKAogICAgICAgICAgICAgICAgcHRyLAogICAgICAgICAgICAgICAgX19lbXZhbF9yZWdpc3RlcihmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgIGNsb25lZEhhbmRsZVsnZGVsZXRlJ10oKTsKICAgICAgICAgICAgICAgIH0pCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBpZiAoZGVzdHJ1Y3RvcnMgIT09IG51bGwpIHsKICAgICAgICAgICAgICAgIGRlc3RydWN0b3JzLnB1c2godGhpcy5yYXdEZXN0cnVjdG9yLCBwdHIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhawogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoJ1Vuc3VwcG9ydGluZyBzaGFyaW5nIHBvbGljeScpOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gcHRyCiAgICB9CiAgICBmdW5jdGlvbiBub25Db25zdE5vU21hcnRQdHJSYXdQb2ludGVyVG9XaXJlVHlwZShkZXN0cnVjdG9ycywgaGFuZGxlKSB7CiAgICAgIGlmIChoYW5kbGUgPT09IG51bGwpIHsKICAgICAgICBpZiAodGhpcy5pc1JlZmVyZW5jZSkgewogICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoJ251bGwgaXMgbm90IGEgdmFsaWQgJyArIHRoaXMubmFtZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiAwCiAgICAgIH0KICAgICAgaWYgKCFoYW5kbGUuJCQpIHsKICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcignQ2Fubm90IHBhc3MgIicgKyBfZW1iaW5kX3JlcHIoaGFuZGxlKSArICciIGFzIGEgJyArIHRoaXMubmFtZSk7CiAgICAgIH0KICAgICAgaWYgKCFoYW5kbGUuJCQucHRyKSB7CiAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoJ0Nhbm5vdCBwYXNzIGRlbGV0ZWQgb2JqZWN0IGFzIGEgcG9pbnRlciBvZiB0eXBlICcgKyB0aGlzLm5hbWUpOwogICAgICB9CiAgICAgIGlmIChoYW5kbGUuJCQucHRyVHlwZS5pc0NvbnN0KSB7CiAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IGFyZ3VtZW50IG9mIHR5cGUgJyArIGhhbmRsZS4kJC5wdHJUeXBlLm5hbWUgKyAnIHRvIHBhcmFtZXRlciB0eXBlICcgKyB0aGlzLm5hbWUpOwogICAgICB9CiAgICAgIHZhciBoYW5kbGVDbGFzcyA9IGhhbmRsZS4kJC5wdHJUeXBlLnJlZ2lzdGVyZWRDbGFzczsKICAgICAgdmFyIHB0ciA9IHVwY2FzdFBvaW50ZXIoaGFuZGxlLiQkLnB0ciwgaGFuZGxlQ2xhc3MsIHRoaXMucmVnaXN0ZXJlZENsYXNzKTsKICAgICAgcmV0dXJuIHB0cgogICAgfQogICAgZnVuY3Rpb24gUmVnaXN0ZXJlZFBvaW50ZXJfZ2V0UG9pbnRlZShwdHIpIHsKICAgICAgaWYgKHRoaXMucmF3R2V0UG9pbnRlZSkgewogICAgICAgIHB0ciA9IHRoaXMucmF3R2V0UG9pbnRlZShwdHIpOwogICAgICB9CiAgICAgIHJldHVybiBwdHIKICAgIH0KICAgIGZ1bmN0aW9uIFJlZ2lzdGVyZWRQb2ludGVyX2Rlc3RydWN0b3IocHRyKSB7CiAgICAgIGlmICh0aGlzLnJhd0Rlc3RydWN0b3IpIHsKICAgICAgICB0aGlzLnJhd0Rlc3RydWN0b3IocHRyKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gUmVnaXN0ZXJlZFBvaW50ZXJfZGVsZXRlT2JqZWN0KGhhbmRsZSkgewogICAgICBpZiAoaGFuZGxlICE9PSBudWxsKSB7CiAgICAgICAgaGFuZGxlWydkZWxldGUnXSgpOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBkb3duY2FzdFBvaW50ZXIocHRyLCBwdHJDbGFzcywgZGVzaXJlZENsYXNzKSB7CiAgICAgIGlmIChwdHJDbGFzcyA9PT0gZGVzaXJlZENsYXNzKSB7CiAgICAgICAgcmV0dXJuIHB0cgogICAgICB9CiAgICAgIGlmICh1bmRlZmluZWQgPT09IGRlc2lyZWRDbGFzcy5iYXNlQ2xhc3MpIHsKICAgICAgICByZXR1cm4gbnVsbAogICAgICB9CiAgICAgIHZhciBydiA9IGRvd25jYXN0UG9pbnRlcihwdHIsIHB0ckNsYXNzLCBkZXNpcmVkQ2xhc3MuYmFzZUNsYXNzKTsKICAgICAgaWYgKHJ2ID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIG51bGwKICAgICAgfQogICAgICByZXR1cm4gZGVzaXJlZENsYXNzLmRvd25jYXN0KHJ2KQogICAgfQogICAgZnVuY3Rpb24gZ2V0SW5oZXJpdGVkSW5zdGFuY2VDb3VudCgpIHsKICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHJlZ2lzdGVyZWRJbnN0YW5jZXMpLmxlbmd0aAogICAgfQogICAgZnVuY3Rpb24gZ2V0TGl2ZUluaGVyaXRlZEluc3RhbmNlcygpIHsKICAgICAgdmFyIHJ2ID0gW107CiAgICAgIGZvciAodmFyIGsgaW4gcmVnaXN0ZXJlZEluc3RhbmNlcykgewogICAgICAgIGlmIChyZWdpc3RlcmVkSW5zdGFuY2VzLmhhc093blByb3BlcnR5KGspKSB7CiAgICAgICAgICBydi5wdXNoKHJlZ2lzdGVyZWRJbnN0YW5jZXNba10pOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gcnYKICAgIH0KICAgIGZ1bmN0aW9uIHNldERlbGF5RnVuY3Rpb24oZm4pIHsKICAgICAgZGVsYXlGdW5jdGlvbiA9IGZuOwogICAgICBpZiAoZGVsZXRpb25RdWV1ZS5sZW5ndGggJiYgZGVsYXlGdW5jdGlvbikgewogICAgICAgIGRlbGF5RnVuY3Rpb24oZmx1c2hQZW5kaW5nRGVsZXRlcyk7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIGluaXRfZW1iaW5kKCkgewogICAgICBNb2R1bGVbJ2dldEluaGVyaXRlZEluc3RhbmNlQ291bnQnXSA9IGdldEluaGVyaXRlZEluc3RhbmNlQ291bnQ7CiAgICAgIE1vZHVsZVsnZ2V0TGl2ZUluaGVyaXRlZEluc3RhbmNlcyddID0gZ2V0TGl2ZUluaGVyaXRlZEluc3RhbmNlczsKICAgICAgTW9kdWxlWydmbHVzaFBlbmRpbmdEZWxldGVzJ10gPSBmbHVzaFBlbmRpbmdEZWxldGVzOwogICAgICBNb2R1bGVbJ3NldERlbGF5RnVuY3Rpb24nXSA9IHNldERlbGF5RnVuY3Rpb247CiAgICB9CiAgICB2YXIgcmVnaXN0ZXJlZEluc3RhbmNlcyA9IHt9OwogICAgZnVuY3Rpb24gZ2V0QmFzZXN0UG9pbnRlcihjbGFzc18sIHB0cikgewogICAgICBpZiAocHRyID09PSB1bmRlZmluZWQpIHsKICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigncHRyIHNob3VsZCBub3QgYmUgdW5kZWZpbmVkJyk7CiAgICAgIH0KICAgICAgd2hpbGUgKGNsYXNzXy5iYXNlQ2xhc3MpIHsKICAgICAgICBwdHIgPSBjbGFzc18udXBjYXN0KHB0cik7CiAgICAgICAgY2xhc3NfID0gY2xhc3NfLmJhc2VDbGFzczsKICAgICAgfQogICAgICByZXR1cm4gcHRyCiAgICB9CiAgICBmdW5jdGlvbiBnZXRJbmhlcml0ZWRJbnN0YW5jZShjbGFzc18sIHB0cikgewogICAgICBwdHIgPSBnZXRCYXNlc3RQb2ludGVyKGNsYXNzXywgcHRyKTsKICAgICAgcmV0dXJuIHJlZ2lzdGVyZWRJbnN0YW5jZXNbcHRyXQogICAgfQogICAgZnVuY3Rpb24gbWFrZUNsYXNzSGFuZGxlKHByb3RvdHlwZSwgcmVjb3JkKSB7CiAgICAgIGlmICghcmVjb3JkLnB0clR5cGUgfHwgIXJlY29yZC5wdHIpIHsKICAgICAgICB0aHJvd0ludGVybmFsRXJyb3IoJ21ha2VDbGFzc0hhbmRsZSByZXF1aXJlcyBwdHIgYW5kIHB0clR5cGUnKTsKICAgICAgfQogICAgICB2YXIgaGFzU21hcnRQdHJUeXBlID0gISFyZWNvcmQuc21hcnRQdHJUeXBlOwogICAgICB2YXIgaGFzU21hcnRQdHIgPSAhIXJlY29yZC5zbWFydFB0cjsKICAgICAgaWYgKGhhc1NtYXJ0UHRyVHlwZSAhPT0gaGFzU21hcnRQdHIpIHsKICAgICAgICB0aHJvd0ludGVybmFsRXJyb3IoJ0JvdGggc21hcnRQdHJUeXBlIGFuZCBzbWFydFB0ciBtdXN0IGJlIHNwZWNpZmllZCcpOwogICAgICB9CiAgICAgIHJlY29yZC5jb3VudCA9IHsgdmFsdWU6IDEgfTsKICAgICAgcmV0dXJuIE9iamVjdC5jcmVhdGUocHJvdG90eXBlLCB7ICQkOiB7IHZhbHVlOiByZWNvcmQgfSB9KQogICAgfQogICAgZnVuY3Rpb24gUmVnaXN0ZXJlZFBvaW50ZXJfZnJvbVdpcmVUeXBlKHB0cikgewogICAgICB2YXIgcmF3UG9pbnRlciA9IHRoaXMuZ2V0UG9pbnRlZShwdHIpOwogICAgICBpZiAoIXJhd1BvaW50ZXIpIHsKICAgICAgICB0aGlzLmRlc3RydWN0b3IocHRyKTsKICAgICAgICByZXR1cm4gbnVsbAogICAgICB9CiAgICAgIHZhciByZWdpc3RlcmVkSW5zdGFuY2UgPSBnZXRJbmhlcml0ZWRJbnN0YW5jZSh0aGlzLnJlZ2lzdGVyZWRDbGFzcywgcmF3UG9pbnRlcik7CiAgICAgIGlmICh1bmRlZmluZWQgIT09IHJlZ2lzdGVyZWRJbnN0YW5jZSkgewogICAgICAgIGlmICgwID09PSByZWdpc3RlcmVkSW5zdGFuY2UuJCQuY291bnQudmFsdWUpIHsKICAgICAgICAgIHJlZ2lzdGVyZWRJbnN0YW5jZS4kJC5wdHIgPSByYXdQb2ludGVyOwogICAgICAgICAgcmVnaXN0ZXJlZEluc3RhbmNlLiQkLnNtYXJ0UHRyID0gcHRyOwogICAgICAgICAgcmV0dXJuIHJlZ2lzdGVyZWRJbnN0YW5jZVsnY2xvbmUnXSgpCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciBydiA9IHJlZ2lzdGVyZWRJbnN0YW5jZVsnY2xvbmUnXSgpOwogICAgICAgICAgdGhpcy5kZXN0cnVjdG9yKHB0cik7CiAgICAgICAgICByZXR1cm4gcnYKICAgICAgICB9CiAgICAgIH0KICAgICAgZnVuY3Rpb24gbWFrZURlZmF1bHRIYW5kbGUoKSB7CiAgICAgICAgaWYgKHRoaXMuaXNTbWFydFBvaW50ZXIpIHsKICAgICAgICAgIHJldHVybiBtYWtlQ2xhc3NIYW5kbGUodGhpcy5yZWdpc3RlcmVkQ2xhc3MuaW5zdGFuY2VQcm90b3R5cGUsIHsKICAgICAgICAgICAgcHRyVHlwZTogdGhpcy5wb2ludGVlVHlwZSwKICAgICAgICAgICAgcHRyOiByYXdQb2ludGVyLAogICAgICAgICAgICBzbWFydFB0clR5cGU6IHRoaXMsCiAgICAgICAgICAgIHNtYXJ0UHRyOiBwdHIsCiAgICAgICAgICB9KQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gbWFrZUNsYXNzSGFuZGxlKHRoaXMucmVnaXN0ZXJlZENsYXNzLmluc3RhbmNlUHJvdG90eXBlLCB7IHB0clR5cGU6IHRoaXMsIHB0cjogcHRyIH0pCiAgICAgICAgfQogICAgICB9CiAgICAgIHZhciBhY3R1YWxUeXBlID0gdGhpcy5yZWdpc3RlcmVkQ2xhc3MuZ2V0QWN0dWFsVHlwZShyYXdQb2ludGVyKTsKICAgICAgdmFyIHJlZ2lzdGVyZWRQb2ludGVyUmVjb3JkID0gcmVnaXN0ZXJlZFBvaW50ZXJzW2FjdHVhbFR5cGVdOwogICAgICBpZiAoIXJlZ2lzdGVyZWRQb2ludGVyUmVjb3JkKSB7CiAgICAgICAgcmV0dXJuIG1ha2VEZWZhdWx0SGFuZGxlLmNhbGwodGhpcykKICAgICAgfQogICAgICB2YXIgdG9UeXBlOwogICAgICBpZiAodGhpcy5pc0NvbnN0KSB7CiAgICAgICAgdG9UeXBlID0gcmVnaXN0ZXJlZFBvaW50ZXJSZWNvcmQuY29uc3RQb2ludGVyVHlwZTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0b1R5cGUgPSByZWdpc3RlcmVkUG9pbnRlclJlY29yZC5wb2ludGVyVHlwZTsKICAgICAgfQogICAgICB2YXIgZHAgPSBkb3duY2FzdFBvaW50ZXIocmF3UG9pbnRlciwgdGhpcy5yZWdpc3RlcmVkQ2xhc3MsIHRvVHlwZS5yZWdpc3RlcmVkQ2xhc3MpOwogICAgICBpZiAoZHAgPT09IG51bGwpIHsKICAgICAgICByZXR1cm4gbWFrZURlZmF1bHRIYW5kbGUuY2FsbCh0aGlzKQogICAgICB9CiAgICAgIGlmICh0aGlzLmlzU21hcnRQb2ludGVyKSB7CiAgICAgICAgcmV0dXJuIG1ha2VDbGFzc0hhbmRsZSh0b1R5cGUucmVnaXN0ZXJlZENsYXNzLmluc3RhbmNlUHJvdG90eXBlLCB7CiAgICAgICAgICBwdHJUeXBlOiB0b1R5cGUsCiAgICAgICAgICBwdHI6IGRwLAogICAgICAgICAgc21hcnRQdHJUeXBlOiB0aGlzLAogICAgICAgICAgc21hcnRQdHI6IHB0ciwKICAgICAgICB9KQogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBtYWtlQ2xhc3NIYW5kbGUodG9UeXBlLnJlZ2lzdGVyZWRDbGFzcy5pbnN0YW5jZVByb3RvdHlwZSwgeyBwdHJUeXBlOiB0b1R5cGUsIHB0cjogZHAgfSkKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gaW5pdF9SZWdpc3RlcmVkUG9pbnRlcigpIHsKICAgICAgUmVnaXN0ZXJlZFBvaW50ZXIucHJvdG90eXBlLmdldFBvaW50ZWUgPSBSZWdpc3RlcmVkUG9pbnRlcl9nZXRQb2ludGVlOwogICAgICBSZWdpc3RlcmVkUG9pbnRlci5wcm90b3R5cGUuZGVzdHJ1Y3RvciA9IFJlZ2lzdGVyZWRQb2ludGVyX2Rlc3RydWN0b3I7CiAgICAgIFJlZ2lzdGVyZWRQb2ludGVyLnByb3RvdHlwZVsnYXJnUGFja0FkdmFuY2UnXSA9IDg7CiAgICAgIFJlZ2lzdGVyZWRQb2ludGVyLnByb3RvdHlwZVsncmVhZFZhbHVlRnJvbVBvaW50ZXInXSA9IHNpbXBsZVJlYWRWYWx1ZUZyb21Qb2ludGVyOwogICAgICBSZWdpc3RlcmVkUG9pbnRlci5wcm90b3R5cGVbJ2RlbGV0ZU9iamVjdCddID0gUmVnaXN0ZXJlZFBvaW50ZXJfZGVsZXRlT2JqZWN0OwogICAgICBSZWdpc3RlcmVkUG9pbnRlci5wcm90b3R5cGVbJ2Zyb21XaXJlVHlwZSddID0gUmVnaXN0ZXJlZFBvaW50ZXJfZnJvbVdpcmVUeXBlOwogICAgfQogICAgZnVuY3Rpb24gUmVnaXN0ZXJlZFBvaW50ZXIoCiAgICAgIG5hbWUsCiAgICAgIHJlZ2lzdGVyZWRDbGFzcywKICAgICAgaXNSZWZlcmVuY2UsCiAgICAgIGlzQ29uc3QsCiAgICAgIGlzU21hcnRQb2ludGVyLAogICAgICBwb2ludGVlVHlwZSwKICAgICAgc2hhcmluZ1BvbGljeSwKICAgICAgcmF3R2V0UG9pbnRlZSwKICAgICAgcmF3Q29uc3RydWN0b3IsCiAgICAgIHJhd1NoYXJlLAogICAgICByYXdEZXN0cnVjdG9yCiAgICApIHsKICAgICAgdGhpcy5uYW1lID0gbmFtZTsKICAgICAgdGhpcy5yZWdpc3RlcmVkQ2xhc3MgPSByZWdpc3RlcmVkQ2xhc3M7CiAgICAgIHRoaXMuaXNSZWZlcmVuY2UgPSBpc1JlZmVyZW5jZTsKICAgICAgdGhpcy5pc0NvbnN0ID0gaXNDb25zdDsKICAgICAgdGhpcy5pc1NtYXJ0UG9pbnRlciA9IGlzU21hcnRQb2ludGVyOwogICAgICB0aGlzLnBvaW50ZWVUeXBlID0gcG9pbnRlZVR5cGU7CiAgICAgIHRoaXMuc2hhcmluZ1BvbGljeSA9IHNoYXJpbmdQb2xpY3k7CiAgICAgIHRoaXMucmF3R2V0UG9pbnRlZSA9IHJhd0dldFBvaW50ZWU7CiAgICAgIHRoaXMucmF3Q29uc3RydWN0b3IgPSByYXdDb25zdHJ1Y3RvcjsKICAgICAgdGhpcy5yYXdTaGFyZSA9IHJhd1NoYXJlOwogICAgICB0aGlzLnJhd0Rlc3RydWN0b3IgPSByYXdEZXN0cnVjdG9yOwogICAgICBpZiAoIWlzU21hcnRQb2ludGVyICYmIHJlZ2lzdGVyZWRDbGFzcy5iYXNlQ2xhc3MgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGlmIChpc0NvbnN0KSB7CiAgICAgICAgICB0aGlzWyd0b1dpcmVUeXBlJ10gPSBjb25zdE5vU21hcnRQdHJSYXdQb2ludGVyVG9XaXJlVHlwZTsKICAgICAgICAgIHRoaXMuZGVzdHJ1Y3RvckZ1bmN0aW9uID0gbnVsbDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhpc1sndG9XaXJlVHlwZSddID0gbm9uQ29uc3ROb1NtYXJ0UHRyUmF3UG9pbnRlclRvV2lyZVR5cGU7CiAgICAgICAgICB0aGlzLmRlc3RydWN0b3JGdW5jdGlvbiA9IG51bGw7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHRoaXNbJ3RvV2lyZVR5cGUnXSA9IGdlbmVyaWNQb2ludGVyVG9XaXJlVHlwZTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gcmVwbGFjZVB1YmxpY1N5bWJvbChuYW1lLCB2YWx1ZSwgbnVtQXJndW1lbnRzKSB7CiAgICAgIGlmICghTW9kdWxlLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgICAgdGhyb3dJbnRlcm5hbEVycm9yKCdSZXBsYWNpbmcgbm9uZXhpc3RhbnQgcHVibGljIHN5bWJvbCcpOwogICAgICB9CiAgICAgIGlmICh1bmRlZmluZWQgIT09IE1vZHVsZVtuYW1lXS5vdmVybG9hZFRhYmxlICYmIHVuZGVmaW5lZCAhPT0gbnVtQXJndW1lbnRzKSB7CiAgICAgICAgTW9kdWxlW25hbWVdLm92ZXJsb2FkVGFibGVbbnVtQXJndW1lbnRzXSA9IHZhbHVlOwogICAgICB9IGVsc2UgewogICAgICAgIE1vZHVsZVtuYW1lXSA9IHZhbHVlOwogICAgICAgIE1vZHVsZVtuYW1lXS5hcmdDb3VudCA9IG51bUFyZ3VtZW50czsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gZW1iaW5kX19yZXF1aXJlRnVuY3Rpb24oc2lnbmF0dXJlLCByYXdGdW5jdGlvbikgewogICAgICBzaWduYXR1cmUgPSByZWFkTGF0aW4xU3RyaW5nKHNpZ25hdHVyZSk7CiAgICAgIGZ1bmN0aW9uIG1ha2VEeW5DYWxsZXIoZHluQ2FsbCkgewogICAgICAgIHZhciBhcmdzID0gW107CiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBzaWduYXR1cmUubGVuZ3RoOyArK2kpIHsKICAgICAgICAgIGFyZ3MucHVzaCgnYScgKyBpKTsKICAgICAgICB9CiAgICAgICAgdmFyIG5hbWUgPSAnZHluQ2FsbF8nICsgc2lnbmF0dXJlICsgJ18nICsgcmF3RnVuY3Rpb247CiAgICAgICAgdmFyIGJvZHkgPSAncmV0dXJuIGZ1bmN0aW9uICcgKyBuYW1lICsgJygnICsgYXJncy5qb2luKCcsICcpICsgJykge1xuJzsKICAgICAgICBib2R5ICs9ICcgICAgcmV0dXJuIGR5bkNhbGwocmF3RnVuY3Rpb24nICsgKGFyZ3MubGVuZ3RoID8gJywgJyA6ICcnKSArIGFyZ3Muam9pbignLCAnKSArICcpO1xuJzsKICAgICAgICBib2R5ICs9ICd9O1xuJzsKICAgICAgICByZXR1cm4gbmV3IEZ1bmN0aW9uKCdkeW5DYWxsJywgJ3Jhd0Z1bmN0aW9uJywgYm9keSkoZHluQ2FsbCwgcmF3RnVuY3Rpb24pCiAgICAgIH0KICAgICAgdmFyIGZwOwogICAgICBpZiAoTW9kdWxlWydGVU5DVElPTl9UQUJMRV8nICsgc2lnbmF0dXJlXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZnAgPSBNb2R1bGVbJ0ZVTkNUSU9OX1RBQkxFXycgKyBzaWduYXR1cmVdW3Jhd0Z1bmN0aW9uXTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YgRlVOQ1RJT05fVEFCTEUgIT09ICd1bmRlZmluZWQnKSB7CiAgICAgICAgZnAgPSBGVU5DVElPTl9UQUJMRVtyYXdGdW5jdGlvbl07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIGRjID0gTW9kdWxlWydhc20nXVsnZHluQ2FsbF8nICsgc2lnbmF0dXJlXTsKICAgICAgICBpZiAoZGMgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgZGMgPSBNb2R1bGVbJ2FzbSddWydkeW5DYWxsXycgKyBzaWduYXR1cmUucmVwbGFjZSgvZi9nLCAnZCcpXTsKICAgICAgICAgIGlmIChkYyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHRocm93QmluZGluZ0Vycm9yKCdObyBkeW5DYWxsIGludm9rZXIgZm9yIHNpZ25hdHVyZTogJyArIHNpZ25hdHVyZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZwID0gbWFrZUR5bkNhbGxlcihkYyk7CiAgICAgIH0KICAgICAgaWYgKHR5cGVvZiBmcCAhPT0gJ2Z1bmN0aW9uJykgewogICAgICAgIHRocm93QmluZGluZ0Vycm9yKCd1bmtub3duIGZ1bmN0aW9uIHBvaW50ZXIgd2l0aCBzaWduYXR1cmUgJyArIHNpZ25hdHVyZSArICc6ICcgKyByYXdGdW5jdGlvbik7CiAgICAgIH0KICAgICAgcmV0dXJuIGZwCiAgICB9CiAgICB2YXIgVW5ib3VuZFR5cGVFcnJvciA9IHVuZGVmaW5lZDsKICAgIGZ1bmN0aW9uIGdldFR5cGVOYW1lKHR5cGUpIHsKICAgICAgdmFyIHB0ciA9IF9fX2dldFR5cGVOYW1lKHR5cGUpOwogICAgICB2YXIgcnYgPSByZWFkTGF0aW4xU3RyaW5nKHB0cik7CiAgICAgIF9mcmVlKHB0cik7CiAgICAgIHJldHVybiBydgogICAgfQogICAgZnVuY3Rpb24gdGhyb3dVbmJvdW5kVHlwZUVycm9yKG1lc3NhZ2UsIHR5cGVzKSB7CiAgICAgIHZhciB1bmJvdW5kVHlwZXMgPSBbXTsKICAgICAgdmFyIHNlZW4gPSB7fTsKICAgICAgZnVuY3Rpb24gdmlzaXQodHlwZSkgewogICAgICAgIGlmIChzZWVuW3R5cGVdKSB7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgaWYgKHJlZ2lzdGVyZWRUeXBlc1t0eXBlXSkgewogICAgICAgICAgcmV0dXJuCiAgICAgICAgfQogICAgICAgIGlmICh0eXBlRGVwZW5kZW5jaWVzW3R5cGVdKSB7CiAgICAgICAgICB0eXBlRGVwZW5kZW5jaWVzW3R5cGVdLmZvckVhY2godmlzaXQpOwogICAgICAgICAgcmV0dXJuCiAgICAgICAgfQogICAgICAgIHVuYm91bmRUeXBlcy5wdXNoKHR5cGUpOwogICAgICAgIHNlZW5bdHlwZV0gPSB0cnVlOwogICAgICB9CiAgICAgIHR5cGVzLmZvckVhY2godmlzaXQpOwogICAgICB0aHJvdyBuZXcgVW5ib3VuZFR5cGVFcnJvcihtZXNzYWdlICsgJzogJyArIHVuYm91bmRUeXBlcy5tYXAoZ2V0VHlwZU5hbWUpLmpvaW4oWycsICddKSkKICAgIH0KICAgIGZ1bmN0aW9uIF9fZW1iaW5kX3JlZ2lzdGVyX2NsYXNzKAogICAgICByYXdUeXBlLAogICAgICByYXdQb2ludGVyVHlwZSwKICAgICAgcmF3Q29uc3RQb2ludGVyVHlwZSwKICAgICAgYmFzZUNsYXNzUmF3VHlwZSwKICAgICAgZ2V0QWN0dWFsVHlwZVNpZ25hdHVyZSwKICAgICAgZ2V0QWN0dWFsVHlwZSwKICAgICAgdXBjYXN0U2lnbmF0dXJlLAogICAgICB1cGNhc3QsCiAgICAgIGRvd25jYXN0U2lnbmF0dXJlLAogICAgICBkb3duY2FzdCwKICAgICAgbmFtZSwKICAgICAgZGVzdHJ1Y3RvclNpZ25hdHVyZSwKICAgICAgcmF3RGVzdHJ1Y3RvcgogICAgKSB7CiAgICAgIG5hbWUgPSByZWFkTGF0aW4xU3RyaW5nKG5hbWUpOwogICAgICBnZXRBY3R1YWxUeXBlID0gZW1iaW5kX19yZXF1aXJlRnVuY3Rpb24oZ2V0QWN0dWFsVHlwZVNpZ25hdHVyZSwgZ2V0QWN0dWFsVHlwZSk7CiAgICAgIGlmICh1cGNhc3QpIHsKICAgICAgICB1cGNhc3QgPSBlbWJpbmRfX3JlcXVpcmVGdW5jdGlvbih1cGNhc3RTaWduYXR1cmUsIHVwY2FzdCk7CiAgICAgIH0KICAgICAgaWYgKGRvd25jYXN0KSB7CiAgICAgICAgZG93bmNhc3QgPSBlbWJpbmRfX3JlcXVpcmVGdW5jdGlvbihkb3duY2FzdFNpZ25hdHVyZSwgZG93bmNhc3QpOwogICAgICB9CiAgICAgIHJhd0Rlc3RydWN0b3IgPSBlbWJpbmRfX3JlcXVpcmVGdW5jdGlvbihkZXN0cnVjdG9yU2lnbmF0dXJlLCByYXdEZXN0cnVjdG9yKTsKICAgICAgdmFyIGxlZ2FsRnVuY3Rpb25OYW1lID0gbWFrZUxlZ2FsRnVuY3Rpb25OYW1lKG5hbWUpOwogICAgICBleHBvc2VQdWJsaWNTeW1ib2wobGVnYWxGdW5jdGlvbk5hbWUsIGZ1bmN0aW9uICgpIHsKICAgICAgICB0aHJvd1VuYm91bmRUeXBlRXJyb3IoJ0Nhbm5vdCBjb25zdHJ1Y3QgJyArIG5hbWUgKyAnIGR1ZSB0byB1bmJvdW5kIHR5cGVzJywgW2Jhc2VDbGFzc1Jhd1R5cGVdKTsKICAgICAgfSk7CiAgICAgIHdoZW5EZXBlbmRlbnRUeXBlc0FyZVJlc29sdmVkKAogICAgICAgIFtyYXdUeXBlLCByYXdQb2ludGVyVHlwZSwgcmF3Q29uc3RQb2ludGVyVHlwZV0sCiAgICAgICAgYmFzZUNsYXNzUmF3VHlwZSA/IFtiYXNlQ2xhc3NSYXdUeXBlXSA6IFtdLAogICAgICAgIGZ1bmN0aW9uIChiYXNlKSB7CiAgICAgICAgICBiYXNlID0gYmFzZVswXTsKICAgICAgICAgIHZhciBiYXNlQ2xhc3M7CiAgICAgICAgICB2YXIgYmFzZVByb3RvdHlwZTsKICAgICAgICAgIGlmIChiYXNlQ2xhc3NSYXdUeXBlKSB7CiAgICAgICAgICAgIGJhc2VDbGFzcyA9IGJhc2UucmVnaXN0ZXJlZENsYXNzOwogICAgICAgICAgICBiYXNlUHJvdG90eXBlID0gYmFzZUNsYXNzLmluc3RhbmNlUHJvdG90eXBlOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYmFzZVByb3RvdHlwZSA9IENsYXNzSGFuZGxlLnByb3RvdHlwZTsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBjb25zdHJ1Y3RvciA9IGNyZWF0ZU5hbWVkRnVuY3Rpb24obGVnYWxGdW5jdGlvbk5hbWUsIGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzKSAhPT0gaW5zdGFuY2VQcm90b3R5cGUpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgQmluZGluZ0Vycm9yKCJVc2UgJ25ldycgdG8gY29uc3RydWN0ICIgKyBuYW1lKQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IHJlZ2lzdGVyZWRDbGFzcy5jb25zdHJ1Y3Rvcl9ib2R5KSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEJpbmRpbmdFcnJvcihuYW1lICsgJyBoYXMgbm8gYWNjZXNzaWJsZSBjb25zdHJ1Y3RvcicpCiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGJvZHkgPSByZWdpc3RlcmVkQ2xhc3MuY29uc3RydWN0b3JfYm9keVthcmd1bWVudHMubGVuZ3RoXTsKICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gYm9keSkgewogICAgICAgICAgICAgIHRocm93IG5ldyBCaW5kaW5nRXJyb3IoCiAgICAgICAgICAgICAgICAnVHJpZWQgdG8gaW52b2tlIGN0b3Igb2YgJyArCiAgICAgICAgICAgICAgICAgIG5hbWUgKwogICAgICAgICAgICAgICAgICAnIHdpdGggaW52YWxpZCBudW1iZXIgb2YgcGFyYW1ldGVycyAoJyArCiAgICAgICAgICAgICAgICAgIGFyZ3VtZW50cy5sZW5ndGggKwogICAgICAgICAgICAgICAgICAnKSAtIGV4cGVjdGVkICgnICsKICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMocmVnaXN0ZXJlZENsYXNzLmNvbnN0cnVjdG9yX2JvZHkpLnRvU3RyaW5nKCkgKwogICAgICAgICAgICAgICAgICAnKSBwYXJhbWV0ZXJzIGluc3RlYWQhJwogICAgICAgICAgICAgICkKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gYm9keS5hcHBseSh0aGlzLCBhcmd1bWVudHMpCiAgICAgICAgICB9KTsKICAgICAgICAgIHZhciBpbnN0YW5jZVByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoYmFzZVByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogY29uc3RydWN0b3IgfSB9KTsKICAgICAgICAgIGNvbnN0cnVjdG9yLnByb3RvdHlwZSA9IGluc3RhbmNlUHJvdG90eXBlOwogICAgICAgICAgdmFyIHJlZ2lzdGVyZWRDbGFzcyA9IG5ldyBSZWdpc3RlcmVkQ2xhc3MoCiAgICAgICAgICAgIG5hbWUsCiAgICAgICAgICAgIGNvbnN0cnVjdG9yLAogICAgICAgICAgICBpbnN0YW5jZVByb3RvdHlwZSwKICAgICAgICAgICAgcmF3RGVzdHJ1Y3RvciwKICAgICAgICAgICAgYmFzZUNsYXNzLAogICAgICAgICAgICBnZXRBY3R1YWxUeXBlLAogICAgICAgICAgICB1cGNhc3QsCiAgICAgICAgICAgIGRvd25jYXN0CiAgICAgICAgICApOwogICAgICAgICAgdmFyIHJlZmVyZW5jZUNvbnZlcnRlciA9IG5ldyBSZWdpc3RlcmVkUG9pbnRlcihuYW1lLCByZWdpc3RlcmVkQ2xhc3MsIHRydWUsIGZhbHNlLCBmYWxzZSk7CiAgICAgICAgICB2YXIgcG9pbnRlckNvbnZlcnRlciA9IG5ldyBSZWdpc3RlcmVkUG9pbnRlcihuYW1lICsgJyonLCByZWdpc3RlcmVkQ2xhc3MsIGZhbHNlLCBmYWxzZSwgZmFsc2UpOwogICAgICAgICAgdmFyIGNvbnN0UG9pbnRlckNvbnZlcnRlciA9IG5ldyBSZWdpc3RlcmVkUG9pbnRlcihuYW1lICsgJyBjb25zdConLCByZWdpc3RlcmVkQ2xhc3MsIGZhbHNlLCB0cnVlLCBmYWxzZSk7CiAgICAgICAgICByZWdpc3RlcmVkUG9pbnRlcnNbcmF3VHlwZV0gPSB7IHBvaW50ZXJUeXBlOiBwb2ludGVyQ29udmVydGVyLCBjb25zdFBvaW50ZXJUeXBlOiBjb25zdFBvaW50ZXJDb252ZXJ0ZXIgfTsKICAgICAgICAgIHJlcGxhY2VQdWJsaWNTeW1ib2wobGVnYWxGdW5jdGlvbk5hbWUsIGNvbnN0cnVjdG9yKTsKICAgICAgICAgIHJldHVybiBbcmVmZXJlbmNlQ29udmVydGVyLCBwb2ludGVyQ29udmVydGVyLCBjb25zdFBvaW50ZXJDb252ZXJ0ZXJdCiAgICAgICAgfQogICAgICApOwogICAgfQogICAgZnVuY3Rpb24gaGVhcDMyVmVjdG9yVG9BcnJheShjb3VudCwgZmlyc3RFbGVtZW50KSB7CiAgICAgIHZhciBhcnJheSA9IFtdOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgICBhcnJheS5wdXNoKEhFQVAzMlsoZmlyc3RFbGVtZW50ID4+IDIpICsgaV0pOwogICAgICB9CiAgICAgIHJldHVybiBhcnJheQogICAgfQogICAgZnVuY3Rpb24gX19lbWJpbmRfcmVnaXN0ZXJfY2xhc3NfY29uc3RydWN0b3IoCiAgICAgIHJhd0NsYXNzVHlwZSwKICAgICAgYXJnQ291bnQsCiAgICAgIHJhd0FyZ1R5cGVzQWRkciwKICAgICAgaW52b2tlclNpZ25hdHVyZSwKICAgICAgaW52b2tlciwKICAgICAgcmF3Q29uc3RydWN0b3IKICAgICkgewogICAgICB2YXIgcmF3QXJnVHlwZXMgPSBoZWFwMzJWZWN0b3JUb0FycmF5KGFyZ0NvdW50LCByYXdBcmdUeXBlc0FkZHIpOwogICAgICBpbnZva2VyID0gZW1iaW5kX19yZXF1aXJlRnVuY3Rpb24oaW52b2tlclNpZ25hdHVyZSwgaW52b2tlcik7CiAgICAgIHdoZW5EZXBlbmRlbnRUeXBlc0FyZVJlc29sdmVkKFtdLCBbcmF3Q2xhc3NUeXBlXSwgZnVuY3Rpb24gKGNsYXNzVHlwZSkgewogICAgICAgIGNsYXNzVHlwZSA9IGNsYXNzVHlwZVswXTsKICAgICAgICB2YXIgaHVtYW5OYW1lID0gJ2NvbnN0cnVjdG9yICcgKyBjbGFzc1R5cGUubmFtZTsKICAgICAgICBpZiAodW5kZWZpbmVkID09PSBjbGFzc1R5cGUucmVnaXN0ZXJlZENsYXNzLmNvbnN0cnVjdG9yX2JvZHkpIHsKICAgICAgICAgIGNsYXNzVHlwZS5yZWdpc3RlcmVkQ2xhc3MuY29uc3RydWN0b3JfYm9keSA9IFtdOwogICAgICAgIH0KICAgICAgICBpZiAodW5kZWZpbmVkICE9PSBjbGFzc1R5cGUucmVnaXN0ZXJlZENsYXNzLmNvbnN0cnVjdG9yX2JvZHlbYXJnQ291bnQgLSAxXSkgewogICAgICAgICAgdGhyb3cgbmV3IEJpbmRpbmdFcnJvcigKICAgICAgICAgICAgJ0Nhbm5vdCByZWdpc3RlciBtdWx0aXBsZSBjb25zdHJ1Y3RvcnMgd2l0aCBpZGVudGljYWwgbnVtYmVyIG9mIHBhcmFtZXRlcnMgKCcgKwogICAgICAgICAgICAgIChhcmdDb3VudCAtIDEpICsKICAgICAgICAgICAgICAiKSBmb3IgY2xhc3MgJyIgKwogICAgICAgICAgICAgIGNsYXNzVHlwZS5uYW1lICsKICAgICAgICAgICAgICAiJyEgT3ZlcmxvYWQgcmVzb2x1dGlvbiBpcyBjdXJyZW50bHkgb25seSBwZXJmb3JtZWQgdXNpbmcgdGhlIHBhcmFtZXRlciBjb3VudCwgbm90IGFjdHVhbCB0eXBlIGluZm8hIgogICAgICAgICAgKQogICAgICAgIH0KICAgICAgICBjbGFzc1R5cGUucmVnaXN0ZXJlZENsYXNzLmNvbnN0cnVjdG9yX2JvZHlbYXJnQ291bnQgLSAxXSA9IGZ1bmN0aW9uIHVuYm91bmRUeXBlSGFuZGxlcigpIHsKICAgICAgICAgIHRocm93VW5ib3VuZFR5cGVFcnJvcignQ2Fubm90IGNvbnN0cnVjdCAnICsgY2xhc3NUeXBlLm5hbWUgKyAnIGR1ZSB0byB1bmJvdW5kIHR5cGVzJywgcmF3QXJnVHlwZXMpOwogICAgICAgIH07CiAgICAgICAgd2hlbkRlcGVuZGVudFR5cGVzQXJlUmVzb2x2ZWQoW10sIHJhd0FyZ1R5cGVzLCBmdW5jdGlvbiAoYXJnVHlwZXMpIHsKICAgICAgICAgIGNsYXNzVHlwZS5yZWdpc3RlcmVkQ2xhc3MuY29uc3RydWN0b3JfYm9keVthcmdDb3VudCAtIDFdID0gZnVuY3Rpb24gY29uc3RydWN0b3JfYm9keSgpIHsKICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggIT09IGFyZ0NvdW50IC0gMSkgewogICAgICAgICAgICAgIHRocm93QmluZGluZ0Vycm9yKGh1bWFuTmFtZSArICcgY2FsbGVkIHdpdGggJyArIGFyZ3VtZW50cy5sZW5ndGggKyAnIGFyZ3VtZW50cywgZXhwZWN0ZWQgJyArIChhcmdDb3VudCAtIDEpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgZGVzdHJ1Y3RvcnMgPSBbXTsKICAgICAgICAgICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJnQ291bnQpOwogICAgICAgICAgICBhcmdzWzBdID0gcmF3Q29uc3RydWN0b3I7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJnQ291bnQ7ICsraSkgewogICAgICAgICAgICAgIGFyZ3NbaV0gPSBhcmdUeXBlc1tpXVsndG9XaXJlVHlwZSddKGRlc3RydWN0b3JzLCBhcmd1bWVudHNbaSAtIDFdKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgcHRyID0gaW52b2tlci5hcHBseShudWxsLCBhcmdzKTsKICAgICAgICAgICAgcnVuRGVzdHJ1Y3RvcnMoZGVzdHJ1Y3RvcnMpOwogICAgICAgICAgICByZXR1cm4gYXJnVHlwZXNbMF1bJ2Zyb21XaXJlVHlwZSddKHB0cikKICAgICAgICAgIH07CiAgICAgICAgICByZXR1cm4gW10KICAgICAgICB9KTsKICAgICAgICByZXR1cm4gW10KICAgICAgfSk7CiAgICB9CiAgICBmdW5jdGlvbiBuZXdfKGNvbnN0cnVjdG9yLCBhcmd1bWVudExpc3QpIHsKICAgICAgaWYgKCEoY29uc3RydWN0b3IgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCduZXdfIGNhbGxlZCB3aXRoIGNvbnN0cnVjdG9yIHR5cGUgJyArIHR5cGVvZiBjb25zdHJ1Y3RvciArICcgd2hpY2ggaXMgbm90IGEgZnVuY3Rpb24nKQogICAgICB9CiAgICAgIHZhciBkdW1teSA9IGNyZWF0ZU5hbWVkRnVuY3Rpb24oY29uc3RydWN0b3IubmFtZSB8fCAndW5rbm93bkZ1bmN0aW9uTmFtZScsIGZ1bmN0aW9uICgpIHt9KTsKICAgICAgZHVtbXkucHJvdG90eXBlID0gY29uc3RydWN0b3IucHJvdG90eXBlOwogICAgICB2YXIgb2JqID0gbmV3IGR1bW15KCk7CiAgICAgIHZhciByID0gY29uc3RydWN0b3IuYXBwbHkob2JqLCBhcmd1bWVudExpc3QpOwogICAgICByZXR1cm4gciBpbnN0YW5jZW9mIE9iamVjdCA/IHIgOiBvYmoKICAgIH0KICAgIGZ1bmN0aW9uIGNyYWZ0SW52b2tlckZ1bmN0aW9uKGh1bWFuTmFtZSwgYXJnVHlwZXMsIGNsYXNzVHlwZSwgY3BwSW52b2tlckZ1bmMsIGNwcFRhcmdldEZ1bmMpIHsKICAgICAgdmFyIGFyZ0NvdW50ID0gYXJnVHlwZXMubGVuZ3RoOwogICAgICBpZiAoYXJnQ291bnQgPCAyKSB7CiAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoImFyZ1R5cGVzIGFycmF5IHNpemUgbWlzbWF0Y2ghIE11c3QgYXQgbGVhc3QgZ2V0IHJldHVybiB2YWx1ZSBhbmQgJ3RoaXMnIHR5cGVzISIpOwogICAgICB9CiAgICAgIHZhciBpc0NsYXNzTWV0aG9kRnVuYyA9IGFyZ1R5cGVzWzFdICE9PSBudWxsICYmIGNsYXNzVHlwZSAhPT0gbnVsbDsKICAgICAgdmFyIG5lZWRzRGVzdHJ1Y3RvclN0YWNrID0gZmFsc2U7CiAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJnVHlwZXMubGVuZ3RoOyArK2kpIHsKICAgICAgICBpZiAoYXJnVHlwZXNbaV0gIT09IG51bGwgJiYgYXJnVHlwZXNbaV0uZGVzdHJ1Y3RvckZ1bmN0aW9uID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIG5lZWRzRGVzdHJ1Y3RvclN0YWNrID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrCiAgICAgICAgfQogICAgICB9CiAgICAgIHZhciByZXR1cm5zID0gYXJnVHlwZXNbMF0ubmFtZSAhPT0gJ3ZvaWQnOwogICAgICB2YXIgYXJnc0xpc3QgPSAnJzsKICAgICAgdmFyIGFyZ3NMaXN0V2lyZWQgPSAnJzsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdDb3VudCAtIDI7ICsraSkgewogICAgICAgIGFyZ3NMaXN0ICs9IChpICE9PSAwID8gJywgJyA6ICcnKSArICdhcmcnICsgaTsKICAgICAgICBhcmdzTGlzdFdpcmVkICs9IChpICE9PSAwID8gJywgJyA6ICcnKSArICdhcmcnICsgaSArICdXaXJlZCc7CiAgICAgIH0KICAgICAgdmFyIGludm9rZXJGbkJvZHkgPQogICAgICAgICdyZXR1cm4gZnVuY3Rpb24gJyArCiAgICAgICAgbWFrZUxlZ2FsRnVuY3Rpb25OYW1lKGh1bWFuTmFtZSkgKwogICAgICAgICcoJyArCiAgICAgICAgYXJnc0xpc3QgKwogICAgICAgICcpIHtcbicgKwogICAgICAgICdpZiAoYXJndW1lbnRzLmxlbmd0aCAhPT0gJyArCiAgICAgICAgKGFyZ0NvdW50IC0gMikgKwogICAgICAgICcpIHtcbicgKwogICAgICAgICJ0aHJvd0JpbmRpbmdFcnJvcignZnVuY3Rpb24gIiArCiAgICAgICAgaHVtYW5OYW1lICsKICAgICAgICAiIGNhbGxlZCB3aXRoICcgKyBhcmd1bWVudHMubGVuZ3RoICsgJyBhcmd1bWVudHMsIGV4cGVjdGVkICIgKwogICAgICAgIChhcmdDb3VudCAtIDIpICsKICAgICAgICAiIGFyZ3MhJyk7XG4iICsKICAgICAgICAnfVxuJzsKICAgICAgaWYgKG5lZWRzRGVzdHJ1Y3RvclN0YWNrKSB7CiAgICAgICAgaW52b2tlckZuQm9keSArPSAndmFyIGRlc3RydWN0b3JzID0gW107XG4nOwogICAgICB9CiAgICAgIHZhciBkdG9yU3RhY2sgPSBuZWVkc0Rlc3RydWN0b3JTdGFjayA/ICdkZXN0cnVjdG9ycycgOiAnbnVsbCc7CiAgICAgIHZhciBhcmdzMSA9IFsndGhyb3dCaW5kaW5nRXJyb3InLCAnaW52b2tlcicsICdmbicsICdydW5EZXN0cnVjdG9ycycsICdyZXRUeXBlJywgJ2NsYXNzUGFyYW0nXTsKICAgICAgdmFyIGFyZ3MyID0gW3Rocm93QmluZGluZ0Vycm9yLCBjcHBJbnZva2VyRnVuYywgY3BwVGFyZ2V0RnVuYywgcnVuRGVzdHJ1Y3RvcnMsIGFyZ1R5cGVzWzBdLCBhcmdUeXBlc1sxXV07CiAgICAgIGlmIChpc0NsYXNzTWV0aG9kRnVuYykgewogICAgICAgIGludm9rZXJGbkJvZHkgKz0gJ3ZhciB0aGlzV2lyZWQgPSBjbGFzc1BhcmFtLnRvV2lyZVR5cGUoJyArIGR0b3JTdGFjayArICcsIHRoaXMpO1xuJzsKICAgICAgfQogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ0NvdW50IC0gMjsgKytpKSB7CiAgICAgICAgaW52b2tlckZuQm9keSArPQogICAgICAgICAgJ3ZhciBhcmcnICsKICAgICAgICAgIGkgKwogICAgICAgICAgJ1dpcmVkID0gYXJnVHlwZScgKwogICAgICAgICAgaSArCiAgICAgICAgICAnLnRvV2lyZVR5cGUoJyArCiAgICAgICAgICBkdG9yU3RhY2sgKwogICAgICAgICAgJywgYXJnJyArCiAgICAgICAgICBpICsKICAgICAgICAgICcpOyAvLyAnICsKICAgICAgICAgIGFyZ1R5cGVzW2kgKyAyXS5uYW1lICsKICAgICAgICAgICdcbic7CiAgICAgICAgYXJnczEucHVzaCgnYXJnVHlwZScgKyBpKTsKICAgICAgICBhcmdzMi5wdXNoKGFyZ1R5cGVzW2kgKyAyXSk7CiAgICAgIH0KICAgICAgaWYgKGlzQ2xhc3NNZXRob2RGdW5jKSB7CiAgICAgICAgYXJnc0xpc3RXaXJlZCA9ICd0aGlzV2lyZWQnICsgKGFyZ3NMaXN0V2lyZWQubGVuZ3RoID4gMCA/ICcsICcgOiAnJykgKyBhcmdzTGlzdFdpcmVkOwogICAgICB9CiAgICAgIGludm9rZXJGbkJvZHkgKz0KICAgICAgICAocmV0dXJucyA/ICd2YXIgcnYgPSAnIDogJycpICsgJ2ludm9rZXIoZm4nICsgKGFyZ3NMaXN0V2lyZWQubGVuZ3RoID4gMCA/ICcsICcgOiAnJykgKyBhcmdzTGlzdFdpcmVkICsgJyk7XG4nOwogICAgICBpZiAobmVlZHNEZXN0cnVjdG9yU3RhY2spIHsKICAgICAgICBpbnZva2VyRm5Cb2R5ICs9ICdydW5EZXN0cnVjdG9ycyhkZXN0cnVjdG9ycyk7XG4nOwogICAgICB9IGVsc2UgewogICAgICAgIGZvciAodmFyIGkgPSBpc0NsYXNzTWV0aG9kRnVuYyA/IDEgOiAyOyBpIDwgYXJnVHlwZXMubGVuZ3RoOyArK2kpIHsKICAgICAgICAgIHZhciBwYXJhbU5hbWUgPSBpID09PSAxID8gJ3RoaXNXaXJlZCcgOiAnYXJnJyArIChpIC0gMikgKyAnV2lyZWQnOwogICAgICAgICAgaWYgKGFyZ1R5cGVzW2ldLmRlc3RydWN0b3JGdW5jdGlvbiAhPT0gbnVsbCkgewogICAgICAgICAgICBpbnZva2VyRm5Cb2R5ICs9IHBhcmFtTmFtZSArICdfZHRvcignICsgcGFyYW1OYW1lICsgJyk7IC8vICcgKyBhcmdUeXBlc1tpXS5uYW1lICsgJ1xuJzsKICAgICAgICAgICAgYXJnczEucHVzaChwYXJhbU5hbWUgKyAnX2R0b3InKTsKICAgICAgICAgICAgYXJnczIucHVzaChhcmdUeXBlc1tpXS5kZXN0cnVjdG9yRnVuY3Rpb24pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBpZiAocmV0dXJucykgewogICAgICAgIGludm9rZXJGbkJvZHkgKz0gJ3ZhciByZXQgPSByZXRUeXBlLmZyb21XaXJlVHlwZShydik7XG4nICsgJ3JldHVybiByZXQ7XG4nOwogICAgICB9CiAgICAgIGludm9rZXJGbkJvZHkgKz0gJ31cbic7CiAgICAgIGFyZ3MxLnB1c2goaW52b2tlckZuQm9keSk7CiAgICAgIHZhciBpbnZva2VyRnVuY3Rpb24gPSBuZXdfKEZ1bmN0aW9uLCBhcmdzMSkuYXBwbHkobnVsbCwgYXJnczIpOwogICAgICByZXR1cm4gaW52b2tlckZ1bmN0aW9uCiAgICB9CiAgICBmdW5jdGlvbiBfX2VtYmluZF9yZWdpc3Rlcl9jbGFzc19mdW5jdGlvbigKICAgICAgcmF3Q2xhc3NUeXBlLAogICAgICBtZXRob2ROYW1lLAogICAgICBhcmdDb3VudCwKICAgICAgcmF3QXJnVHlwZXNBZGRyLAogICAgICBpbnZva2VyU2lnbmF0dXJlLAogICAgICByYXdJbnZva2VyLAogICAgICBjb250ZXh0LAogICAgICBpc1B1cmVWaXJ0dWFsCiAgICApIHsKICAgICAgdmFyIHJhd0FyZ1R5cGVzID0gaGVhcDMyVmVjdG9yVG9BcnJheShhcmdDb3VudCwgcmF3QXJnVHlwZXNBZGRyKTsKICAgICAgbWV0aG9kTmFtZSA9IHJlYWRMYXRpbjFTdHJpbmcobWV0aG9kTmFtZSk7CiAgICAgIHJhd0ludm9rZXIgPSBlbWJpbmRfX3JlcXVpcmVGdW5jdGlvbihpbnZva2VyU2lnbmF0dXJlLCByYXdJbnZva2VyKTsKICAgICAgd2hlbkRlcGVuZGVudFR5cGVzQXJlUmVzb2x2ZWQoW10sIFtyYXdDbGFzc1R5cGVdLCBmdW5jdGlvbiAoY2xhc3NUeXBlKSB7CiAgICAgICAgY2xhc3NUeXBlID0gY2xhc3NUeXBlWzBdOwogICAgICAgIHZhciBodW1hbk5hbWUgPSBjbGFzc1R5cGUubmFtZSArICcuJyArIG1ldGhvZE5hbWU7CiAgICAgICAgaWYgKGlzUHVyZVZpcnR1YWwpIHsKICAgICAgICAgIGNsYXNzVHlwZS5yZWdpc3RlcmVkQ2xhc3MucHVyZVZpcnR1YWxGdW5jdGlvbnMucHVzaChtZXRob2ROYW1lKTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gdW5ib3VuZFR5cGVzSGFuZGxlcigpIHsKICAgICAgICAgIHRocm93VW5ib3VuZFR5cGVFcnJvcignQ2Fubm90IGNhbGwgJyArIGh1bWFuTmFtZSArICcgZHVlIHRvIHVuYm91bmQgdHlwZXMnLCByYXdBcmdUeXBlcyk7CiAgICAgICAgfQogICAgICAgIHZhciBwcm90byA9IGNsYXNzVHlwZS5yZWdpc3RlcmVkQ2xhc3MuaW5zdGFuY2VQcm90b3R5cGU7CiAgICAgICAgdmFyIG1ldGhvZCA9IHByb3RvW21ldGhvZE5hbWVdOwogICAgICAgIGlmICgKICAgICAgICAgIHVuZGVmaW5lZCA9PT0gbWV0aG9kIHx8CiAgICAgICAgICAodW5kZWZpbmVkID09PSBtZXRob2Qub3ZlcmxvYWRUYWJsZSAmJiBtZXRob2QuY2xhc3NOYW1lICE9PSBjbGFzc1R5cGUubmFtZSAmJiBtZXRob2QuYXJnQ291bnQgPT09IGFyZ0NvdW50IC0gMikKICAgICAgICApIHsKICAgICAgICAgIHVuYm91bmRUeXBlc0hhbmRsZXIuYXJnQ291bnQgPSBhcmdDb3VudCAtIDI7CiAgICAgICAgICB1bmJvdW5kVHlwZXNIYW5kbGVyLmNsYXNzTmFtZSA9IGNsYXNzVHlwZS5uYW1lOwogICAgICAgICAgcHJvdG9bbWV0aG9kTmFtZV0gPSB1bmJvdW5kVHlwZXNIYW5kbGVyOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBlbnN1cmVPdmVybG9hZFRhYmxlKHByb3RvLCBtZXRob2ROYW1lLCBodW1hbk5hbWUpOwogICAgICAgICAgcHJvdG9bbWV0aG9kTmFtZV0ub3ZlcmxvYWRUYWJsZVthcmdDb3VudCAtIDJdID0gdW5ib3VuZFR5cGVzSGFuZGxlcjsKICAgICAgICB9CiAgICAgICAgd2hlbkRlcGVuZGVudFR5cGVzQXJlUmVzb2x2ZWQoW10sIHJhd0FyZ1R5cGVzLCBmdW5jdGlvbiAoYXJnVHlwZXMpIHsKICAgICAgICAgIHZhciBtZW1iZXJGdW5jdGlvbiA9IGNyYWZ0SW52b2tlckZ1bmN0aW9uKGh1bWFuTmFtZSwgYXJnVHlwZXMsIGNsYXNzVHlwZSwgcmF3SW52b2tlciwgY29udGV4dCk7CiAgICAgICAgICBpZiAodW5kZWZpbmVkID09PSBwcm90b1ttZXRob2ROYW1lXS5vdmVybG9hZFRhYmxlKSB7CiAgICAgICAgICAgIG1lbWJlckZ1bmN0aW9uLmFyZ0NvdW50ID0gYXJnQ291bnQgLSAyOwogICAgICAgICAgICBwcm90b1ttZXRob2ROYW1lXSA9IG1lbWJlckZ1bmN0aW9uOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcHJvdG9bbWV0aG9kTmFtZV0ub3ZlcmxvYWRUYWJsZVthcmdDb3VudCAtIDJdID0gbWVtYmVyRnVuY3Rpb247CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gW10KICAgICAgICB9KTsKICAgICAgICByZXR1cm4gW10KICAgICAgfSk7CiAgICB9CiAgICB2YXIgZW12YWxfZnJlZV9saXN0ID0gW107CiAgICB2YXIgZW12YWxfaGFuZGxlX2FycmF5ID0gW3t9LCB7IHZhbHVlOiB1bmRlZmluZWQgfSwgeyB2YWx1ZTogbnVsbCB9LCB7IHZhbHVlOiB0cnVlIH0sIHsgdmFsdWU6IGZhbHNlIH1dOwogICAgZnVuY3Rpb24gX19lbXZhbF9kZWNyZWYoaGFuZGxlKSB7CiAgICAgIGlmIChoYW5kbGUgPiA0ICYmIDAgPT09IC0tZW12YWxfaGFuZGxlX2FycmF5W2hhbmRsZV0ucmVmY291bnQpIHsKICAgICAgICBlbXZhbF9oYW5kbGVfYXJyYXlbaGFuZGxlXSA9IHVuZGVmaW5lZDsKICAgICAgICBlbXZhbF9mcmVlX2xpc3QucHVzaChoYW5kbGUpOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBjb3VudF9lbXZhbF9oYW5kbGVzKCkgewogICAgICB2YXIgY291bnQgPSAwOwogICAgICBmb3IgKHZhciBpID0gNTsgaSA8IGVtdmFsX2hhbmRsZV9hcnJheS5sZW5ndGg7ICsraSkgewogICAgICAgIGlmIChlbXZhbF9oYW5kbGVfYXJyYXlbaV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgKytjb3VudDsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIGNvdW50CiAgICB9CiAgICBmdW5jdGlvbiBnZXRfZmlyc3RfZW12YWwoKSB7CiAgICAgIGZvciAodmFyIGkgPSA1OyBpIDwgZW12YWxfaGFuZGxlX2FycmF5Lmxlbmd0aDsgKytpKSB7CiAgICAgICAgaWYgKGVtdmFsX2hhbmRsZV9hcnJheVtpXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICByZXR1cm4gZW12YWxfaGFuZGxlX2FycmF5W2ldCiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBudWxsCiAgICB9CiAgICBmdW5jdGlvbiBpbml0X2VtdmFsKCkgewogICAgICBNb2R1bGVbJ2NvdW50X2VtdmFsX2hhbmRsZXMnXSA9IGNvdW50X2VtdmFsX2hhbmRsZXM7CiAgICAgIE1vZHVsZVsnZ2V0X2ZpcnN0X2VtdmFsJ10gPSBnZXRfZmlyc3RfZW12YWw7CiAgICB9CiAgICBmdW5jdGlvbiBfX2VtdmFsX3JlZ2lzdGVyKHZhbHVlKSB7CiAgICAgIHN3aXRjaCAodmFsdWUpIHsKICAgICAgICBjYXNlIHVuZGVmaW5lZDogewogICAgICAgICAgcmV0dXJuIDEKICAgICAgICB9CiAgICAgICAgY2FzZSBudWxsOiB7CiAgICAgICAgICByZXR1cm4gMgogICAgICAgIH0KICAgICAgICBjYXNlIHRydWU6IHsKICAgICAgICAgIHJldHVybiAzCiAgICAgICAgfQogICAgICAgIGNhc2UgZmFsc2U6IHsKICAgICAgICAgIHJldHVybiA0CiAgICAgICAgfQogICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgIHZhciBoYW5kbGUgPSBlbXZhbF9mcmVlX2xpc3QubGVuZ3RoID8gZW12YWxfZnJlZV9saXN0LnBvcCgpIDogZW12YWxfaGFuZGxlX2FycmF5Lmxlbmd0aDsKICAgICAgICAgIGVtdmFsX2hhbmRsZV9hcnJheVtoYW5kbGVdID0geyByZWZjb3VudDogMSwgdmFsdWU6IHZhbHVlIH07CiAgICAgICAgICByZXR1cm4gaGFuZGxlCiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBfX2VtYmluZF9yZWdpc3Rlcl9lbXZhbChyYXdUeXBlLCBuYW1lKSB7CiAgICAgIG5hbWUgPSByZWFkTGF0aW4xU3RyaW5nKG5hbWUpOwogICAgICByZWdpc3RlclR5cGUocmF3VHlwZSwgewogICAgICAgIG5hbWU6IG5hbWUsCiAgICAgICAgZnJvbVdpcmVUeXBlOiBmdW5jdGlvbiAoaGFuZGxlKSB7CiAgICAgICAgICB2YXIgcnYgPSBlbXZhbF9oYW5kbGVfYXJyYXlbaGFuZGxlXS52YWx1ZTsKICAgICAgICAgIF9fZW12YWxfZGVjcmVmKGhhbmRsZSk7CiAgICAgICAgICByZXR1cm4gcnYKICAgICAgICB9LAogICAgICAgIHRvV2lyZVR5cGU6IGZ1bmN0aW9uIChkZXN0cnVjdG9ycywgdmFsdWUpIHsKICAgICAgICAgIHJldHVybiBfX2VtdmFsX3JlZ2lzdGVyKHZhbHVlKQogICAgICAgIH0sCiAgICAgICAgYXJnUGFja0FkdmFuY2U6IDgsCiAgICAgICAgcmVhZFZhbHVlRnJvbVBvaW50ZXI6IHNpbXBsZVJlYWRWYWx1ZUZyb21Qb2ludGVyLAogICAgICAgIGRlc3RydWN0b3JGdW5jdGlvbjogbnVsbCwKICAgICAgfSk7CiAgICB9CiAgICBmdW5jdGlvbiBfZW1iaW5kX3JlcHIodikgewogICAgICBpZiAodiA9PT0gbnVsbCkgewogICAgICAgIHJldHVybiAnbnVsbCcKICAgICAgfQogICAgICB2YXIgdCA9IHR5cGVvZiB2OwogICAgICBpZiAodCA9PT0gJ29iamVjdCcgfHwgdCA9PT0gJ2FycmF5JyB8fCB0ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgcmV0dXJuIHYudG9TdHJpbmcoKQogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiAnJyArIHYKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gZmxvYXRSZWFkVmFsdWVGcm9tUG9pbnRlcihuYW1lLCBzaGlmdCkgewogICAgICBzd2l0Y2ggKHNoaWZ0KSB7CiAgICAgICAgY2FzZSAyOgogICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChwb2ludGVyKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzWydmcm9tV2lyZVR5cGUnXShIRUFQRjMyW3BvaW50ZXIgPj4gMl0pCiAgICAgICAgICB9CiAgICAgICAgY2FzZSAzOgogICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChwb2ludGVyKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzWydmcm9tV2lyZVR5cGUnXShIRUFQRjY0W3BvaW50ZXIgPj4gM10pCiAgICAgICAgICB9CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZmxvYXQgdHlwZTogJyArIG5hbWUpCiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIF9fZW1iaW5kX3JlZ2lzdGVyX2Zsb2F0KHJhd1R5cGUsIG5hbWUsIHNpemUpIHsKICAgICAgdmFyIHNoaWZ0ID0gZ2V0U2hpZnRGcm9tU2l6ZShzaXplKTsKICAgICAgbmFtZSA9IHJlYWRMYXRpbjFTdHJpbmcobmFtZSk7CiAgICAgIHJlZ2lzdGVyVHlwZShyYXdUeXBlLCB7CiAgICAgICAgbmFtZTogbmFtZSwKICAgICAgICBmcm9tV2lyZVR5cGU6IGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIHZhbHVlCiAgICAgICAgfSwKICAgICAgICB0b1dpcmVUeXBlOiBmdW5jdGlvbiAoZGVzdHJ1Y3RvcnMsIHZhbHVlKSB7CiAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJyAmJiB0eXBlb2YgdmFsdWUgIT09ICdib29sZWFuJykgewogICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY29udmVydCAiJyArIF9lbWJpbmRfcmVwcih2YWx1ZSkgKyAnIiB0byAnICsgdGhpcy5uYW1lKQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHZhbHVlCiAgICAgICAgfSwKICAgICAgICBhcmdQYWNrQWR2YW5jZTogOCwKICAgICAgICByZWFkVmFsdWVGcm9tUG9pbnRlcjogZmxvYXRSZWFkVmFsdWVGcm9tUG9pbnRlcihuYW1lLCBzaGlmdCksCiAgICAgICAgZGVzdHJ1Y3RvckZ1bmN0aW9uOiBudWxsLAogICAgICB9KTsKICAgIH0KICAgIGZ1bmN0aW9uIGludGVnZXJSZWFkVmFsdWVGcm9tUG9pbnRlcihuYW1lLCBzaGlmdCwgc2lnbmVkKSB7CiAgICAgIHN3aXRjaCAoc2hpZnQpIHsKICAgICAgICBjYXNlIDA6CiAgICAgICAgICByZXR1cm4gc2lnbmVkCiAgICAgICAgICAgID8gZnVuY3Rpb24gcmVhZFM4RnJvbVBvaW50ZXIocG9pbnRlcikgewogICAgICAgICAgICAgICAgcmV0dXJuIEhFQVA4W3BvaW50ZXJdCiAgICAgICAgICAgICAgfQogICAgICAgICAgICA6IGZ1bmN0aW9uIHJlYWRVOEZyb21Qb2ludGVyKHBvaW50ZXIpIHsKICAgICAgICAgICAgICAgIHJldHVybiBIRUFQVThbcG9pbnRlcl0KICAgICAgICAgICAgICB9CiAgICAgICAgY2FzZSAxOgogICAgICAgICAgcmV0dXJuIHNpZ25lZAogICAgICAgICAgICA/IGZ1bmN0aW9uIHJlYWRTMTZGcm9tUG9pbnRlcihwb2ludGVyKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gSEVBUDE2W3BvaW50ZXIgPj4gMV0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDogZnVuY3Rpb24gcmVhZFUxNkZyb21Qb2ludGVyKHBvaW50ZXIpIHsKICAgICAgICAgICAgICAgIHJldHVybiBIRUFQVTE2W3BvaW50ZXIgPj4gMV0KICAgICAgICAgICAgICB9CiAgICAgICAgY2FzZSAyOgogICAgICAgICAgcmV0dXJuIHNpZ25lZAogICAgICAgICAgICA/IGZ1bmN0aW9uIHJlYWRTMzJGcm9tUG9pbnRlcihwb2ludGVyKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gSEVBUDMyW3BvaW50ZXIgPj4gMl0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDogZnVuY3Rpb24gcmVhZFUzMkZyb21Qb2ludGVyKHBvaW50ZXIpIHsKICAgICAgICAgICAgICAgIHJldHVybiBIRUFQVTMyW3BvaW50ZXIgPj4gMl0KICAgICAgICAgICAgICB9CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gaW50ZWdlciB0eXBlOiAnICsgbmFtZSkKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gX19lbWJpbmRfcmVnaXN0ZXJfaW50ZWdlcihwcmltaXRpdmVUeXBlLCBuYW1lLCBzaXplLCBtaW5SYW5nZSwgbWF4UmFuZ2UpIHsKICAgICAgbmFtZSA9IHJlYWRMYXRpbjFTdHJpbmcobmFtZSk7CiAgICAgIGlmIChtYXhSYW5nZSA9PT0gLTEpIHsKICAgICAgICBtYXhSYW5nZSA9IDQyOTQ5NjcyOTU7CiAgICAgIH0KICAgICAgdmFyIHNoaWZ0ID0gZ2V0U2hpZnRGcm9tU2l6ZShzaXplKTsKICAgICAgdmFyIGZyb21XaXJlVHlwZSA9IGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgIHJldHVybiB2YWx1ZQogICAgICB9OwogICAgICBpZiAobWluUmFuZ2UgPT09IDApIHsKICAgICAgICB2YXIgYml0c2hpZnQgPSAzMiAtIDggKiBzaXplOwogICAgICAgIGZyb21XaXJlVHlwZSA9IGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgICAgcmV0dXJuICh2YWx1ZSA8PCBiaXRzaGlmdCkgPj4+IGJpdHNoaWZ0CiAgICAgICAgfTsKICAgICAgfQogICAgICB2YXIgaXNVbnNpZ25lZFR5cGUgPSBuYW1lLmluZGV4T2YoJ3Vuc2lnbmVkJykgIT0gLTE7CiAgICAgIHJlZ2lzdGVyVHlwZShwcmltaXRpdmVUeXBlLCB7CiAgICAgICAgbmFtZTogbmFtZSwKICAgICAgICBmcm9tV2lyZVR5cGU6IGZyb21XaXJlVHlwZSwKICAgICAgICB0b1dpcmVUeXBlOiBmdW5jdGlvbiAoZGVzdHJ1Y3RvcnMsIHZhbHVlKSB7CiAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJyAmJiB0eXBlb2YgdmFsdWUgIT09ICdib29sZWFuJykgewogICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY29udmVydCAiJyArIF9lbWJpbmRfcmVwcih2YWx1ZSkgKyAnIiB0byAnICsgdGhpcy5uYW1lKQogICAgICAgICAgfQogICAgICAgICAgaWYgKHZhbHVlIDwgbWluUmFuZ2UgfHwgdmFsdWUgPiBtYXhSYW5nZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKAogICAgICAgICAgICAgICdQYXNzaW5nIGEgbnVtYmVyICInICsKICAgICAgICAgICAgICAgIF9lbWJpbmRfcmVwcih2YWx1ZSkgKwogICAgICAgICAgICAgICAgJyIgZnJvbSBKUyBzaWRlIHRvIEMvQysrIHNpZGUgdG8gYW4gYXJndW1lbnQgb2YgdHlwZSAiJyArCiAgICAgICAgICAgICAgICBuYW1lICsKICAgICAgICAgICAgICAgICciLCB3aGljaCBpcyBvdXRzaWRlIHRoZSB2YWxpZCByYW5nZSBbJyArCiAgICAgICAgICAgICAgICBtaW5SYW5nZSArCiAgICAgICAgICAgICAgICAnLCAnICsKICAgICAgICAgICAgICAgIG1heFJhbmdlICsKICAgICAgICAgICAgICAgICddIScKICAgICAgICAgICAgKQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGlzVW5zaWduZWRUeXBlID8gdmFsdWUgPj4+IDAgOiB2YWx1ZSB8IDAKICAgICAgICB9LAogICAgICAgIGFyZ1BhY2tBZHZhbmNlOiA4LAogICAgICAgIHJlYWRWYWx1ZUZyb21Qb2ludGVyOiBpbnRlZ2VyUmVhZFZhbHVlRnJvbVBvaW50ZXIobmFtZSwgc2hpZnQsIG1pblJhbmdlICE9PSAwKSwKICAgICAgICBkZXN0cnVjdG9yRnVuY3Rpb246IG51bGwsCiAgICAgIH0pOwogICAgfQogICAgZnVuY3Rpb24gX19lbWJpbmRfcmVnaXN0ZXJfbWVtb3J5X3ZpZXcocmF3VHlwZSwgZGF0YVR5cGVJbmRleCwgbmFtZSkgewogICAgICB2YXIgdHlwZU1hcHBpbmcgPSBbCiAgICAgICAgSW50OEFycmF5LAogICAgICAgIFVpbnQ4QXJyYXksCiAgICAgICAgSW50MTZBcnJheSwKICAgICAgICBVaW50MTZBcnJheSwKICAgICAgICBJbnQzMkFycmF5LAogICAgICAgIFVpbnQzMkFycmF5LAogICAgICAgIEZsb2F0MzJBcnJheSwKICAgICAgICBGbG9hdDY0QXJyYXksCiAgICAgIF07CiAgICAgIHZhciBUQSA9IHR5cGVNYXBwaW5nW2RhdGFUeXBlSW5kZXhdOwogICAgICBmdW5jdGlvbiBkZWNvZGVNZW1vcnlWaWV3KGhhbmRsZSkgewogICAgICAgIGhhbmRsZSA9IGhhbmRsZSA+PiAyOwogICAgICAgIHZhciBoZWFwID0gSEVBUFUzMjsKICAgICAgICB2YXIgc2l6ZSA9IGhlYXBbaGFuZGxlXTsKICAgICAgICB2YXIgZGF0YSA9IGhlYXBbaGFuZGxlICsgMV07CiAgICAgICAgcmV0dXJuIG5ldyBUQShoZWFwWydidWZmZXInXSwgZGF0YSwgc2l6ZSkKICAgICAgfQogICAgICBuYW1lID0gcmVhZExhdGluMVN0cmluZyhuYW1lKTsKICAgICAgcmVnaXN0ZXJUeXBlKAogICAgICAgIHJhd1R5cGUsCiAgICAgICAgeyBuYW1lOiBuYW1lLCBmcm9tV2lyZVR5cGU6IGRlY29kZU1lbW9yeVZpZXcsIGFyZ1BhY2tBZHZhbmNlOiA4LCByZWFkVmFsdWVGcm9tUG9pbnRlcjogZGVjb2RlTWVtb3J5VmlldyB9LAogICAgICAgIHsgaWdub3JlRHVwbGljYXRlUmVnaXN0cmF0aW9uczogdHJ1ZSB9CiAgICAgICk7CiAgICB9CiAgICBmdW5jdGlvbiBfX2VtYmluZF9yZWdpc3Rlcl9zdGRfc3RyaW5nKHJhd1R5cGUsIG5hbWUpIHsKICAgICAgbmFtZSA9IHJlYWRMYXRpbjFTdHJpbmcobmFtZSk7CiAgICAgIHJlZ2lzdGVyVHlwZShyYXdUeXBlLCB7CiAgICAgICAgbmFtZTogbmFtZSwKICAgICAgICBmcm9tV2lyZVR5cGU6IGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgICAgdmFyIGxlbmd0aCA9IEhFQVBVMzJbdmFsdWUgPj4gMl07CiAgICAgICAgICB2YXIgYSA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgICBhW2ldID0gU3RyaW5nLmZyb21DaGFyQ29kZShIRUFQVThbdmFsdWUgKyA0ICsgaV0pOwogICAgICAgICAgfQogICAgICAgICAgX2ZyZWUodmFsdWUpOwogICAgICAgICAgcmV0dXJuIGEuam9pbignJykKICAgICAgICB9LAogICAgICAgIHRvV2lyZVR5cGU6IGZ1bmN0aW9uIChkZXN0cnVjdG9ycywgdmFsdWUpIHsKICAgICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7CiAgICAgICAgICAgIHZhbHVlID0gbmV3IFVpbnQ4QXJyYXkodmFsdWUpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gZ2V0VEFFbGVtZW50KHRhLCBpbmRleCkgewogICAgICAgICAgICByZXR1cm4gdGFbaW5kZXhdCiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBnZXRTdHJpbmdFbGVtZW50KHN0cmluZywgaW5kZXgpIHsKICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5jaGFyQ29kZUF0KGluZGV4KQogICAgICAgICAgfQogICAgICAgICAgdmFyIGdldEVsZW1lbnQ7CiAgICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7CiAgICAgICAgICAgIGdldEVsZW1lbnQgPSBnZXRUQUVsZW1lbnQ7CiAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgVWludDhDbGFtcGVkQXJyYXkpIHsKICAgICAgICAgICAgZ2V0RWxlbWVudCA9IGdldFRBRWxlbWVudDsKICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUgaW5zdGFuY2VvZiBJbnQ4QXJyYXkpIHsKICAgICAgICAgICAgZ2V0RWxlbWVudCA9IGdldFRBRWxlbWVudDsKICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykgewogICAgICAgICAgICBnZXRFbGVtZW50ID0gZ2V0U3RyaW5nRWxlbWVudDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRocm93QmluZGluZ0Vycm9yKCdDYW5ub3QgcGFzcyBub24tc3RyaW5nIHRvIHN0ZDo6c3RyaW5nJyk7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgbGVuZ3RoID0gdmFsdWUubGVuZ3RoOwogICAgICAgICAgdmFyIHB0ciA9IF9tYWxsb2MoNCArIGxlbmd0aCk7CiAgICAgICAgICBIRUFQVTMyW3B0ciA+PiAyXSA9IGxlbmd0aDsKICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgdmFyIGNoYXJDb2RlID0gZ2V0RWxlbWVudCh2YWx1ZSwgaSk7CiAgICAgICAgICAgIGlmIChjaGFyQ29kZSA+IDI1NSkgewogICAgICAgICAgICAgIF9mcmVlKHB0cik7CiAgICAgICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoJ1N0cmluZyBoYXMgVVRGLTE2IGNvZGUgdW5pdHMgdGhhdCBkbyBub3QgZml0IGluIDggYml0cycpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIEhFQVBVOFtwdHIgKyA0ICsgaV0gPSBjaGFyQ29kZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChkZXN0cnVjdG9ycyAhPT0gbnVsbCkgewogICAgICAgICAgICBkZXN0cnVjdG9ycy5wdXNoKF9mcmVlLCBwdHIpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHB0cgogICAgICAgIH0sCiAgICAgICAgYXJnUGFja0FkdmFuY2U6IDgsCiAgICAgICAgcmVhZFZhbHVlRnJvbVBvaW50ZXI6IHNpbXBsZVJlYWRWYWx1ZUZyb21Qb2ludGVyLAogICAgICAgIGRlc3RydWN0b3JGdW5jdGlvbjogZnVuY3Rpb24gKHB0cikgewogICAgICAgICAgX2ZyZWUocHRyKTsKICAgICAgICB9LAogICAgICB9KTsKICAgIH0KICAgIGZ1bmN0aW9uIF9fZW1iaW5kX3JlZ2lzdGVyX3N0ZF93c3RyaW5nKHJhd1R5cGUsIGNoYXJTaXplLCBuYW1lKSB7CiAgICAgIG5hbWUgPSByZWFkTGF0aW4xU3RyaW5nKG5hbWUpOwogICAgICB2YXIgZ2V0SGVhcCwgc2hpZnQ7CiAgICAgIGlmIChjaGFyU2l6ZSA9PT0gMikgewogICAgICAgIGdldEhlYXAgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gSEVBUFUxNgogICAgICAgIH07CiAgICAgICAgc2hpZnQgPSAxOwogICAgICB9IGVsc2UgaWYgKGNoYXJTaXplID09PSA0KSB7CiAgICAgICAgZ2V0SGVhcCA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBIRUFQVTMyCiAgICAgICAgfTsKICAgICAgICBzaGlmdCA9IDI7CiAgICAgIH0KICAgICAgcmVnaXN0ZXJUeXBlKHJhd1R5cGUsIHsKICAgICAgICBuYW1lOiBuYW1lLAogICAgICAgIGZyb21XaXJlVHlwZTogZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgICAgICB2YXIgSEVBUCA9IGdldEhlYXAoKTsKICAgICAgICAgIHZhciBsZW5ndGggPSBIRUFQVTMyW3ZhbHVlID4+IDJdOwogICAgICAgICAgdmFyIGEgPSBuZXcgQXJyYXkobGVuZ3RoKTsKICAgICAgICAgIHZhciBzdGFydCA9ICh2YWx1ZSArIDQpID4+IHNoaWZ0OwogICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgICBhW2ldID0gU3RyaW5nLmZyb21DaGFyQ29kZShIRUFQW3N0YXJ0ICsgaV0pOwogICAgICAgICAgfQogICAgICAgICAgX2ZyZWUodmFsdWUpOwogICAgICAgICAgcmV0dXJuIGEuam9pbignJykKICAgICAgICB9LAogICAgICAgIHRvV2lyZVR5cGU6IGZ1bmN0aW9uIChkZXN0cnVjdG9ycywgdmFsdWUpIHsKICAgICAgICAgIHZhciBIRUFQID0gZ2V0SGVhcCgpOwogICAgICAgICAgdmFyIGxlbmd0aCA9IHZhbHVlLmxlbmd0aDsKICAgICAgICAgIHZhciBwdHIgPSBfbWFsbG9jKDQgKyBsZW5ndGggKiBjaGFyU2l6ZSk7CiAgICAgICAgICBIRUFQVTMyW3B0ciA+PiAyXSA9IGxlbmd0aDsKICAgICAgICAgIHZhciBzdGFydCA9IChwdHIgKyA0KSA+PiBzaGlmdDsKICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgSEVBUFtzdGFydCArIGldID0gdmFsdWUuY2hhckNvZGVBdChpKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChkZXN0cnVjdG9ycyAhPT0gbnVsbCkgewogICAgICAgICAgICBkZXN0cnVjdG9ycy5wdXNoKF9mcmVlLCBwdHIpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHB0cgogICAgICAgIH0sCiAgICAgICAgYXJnUGFja0FkdmFuY2U6IDgsCiAgICAgICAgcmVhZFZhbHVlRnJvbVBvaW50ZXI6IHNpbXBsZVJlYWRWYWx1ZUZyb21Qb2ludGVyLAogICAgICAgIGRlc3RydWN0b3JGdW5jdGlvbjogZnVuY3Rpb24gKHB0cikgewogICAgICAgICAgX2ZyZWUocHRyKTsKICAgICAgICB9LAogICAgICB9KTsKICAgIH0KICAgIGZ1bmN0aW9uIF9fZW1iaW5kX3JlZ2lzdGVyX3ZhbHVlX29iamVjdCgKICAgICAgcmF3VHlwZSwKICAgICAgbmFtZSwKICAgICAgY29uc3RydWN0b3JTaWduYXR1cmUsCiAgICAgIHJhd0NvbnN0cnVjdG9yLAogICAgICBkZXN0cnVjdG9yU2lnbmF0dXJlLAogICAgICByYXdEZXN0cnVjdG9yCiAgICApIHsKICAgICAgc3RydWN0UmVnaXN0cmF0aW9uc1tyYXdUeXBlXSA9IHsKICAgICAgICBuYW1lOiByZWFkTGF0aW4xU3RyaW5nKG5hbWUpLAogICAgICAgIHJhd0NvbnN0cnVjdG9yOiBlbWJpbmRfX3JlcXVpcmVGdW5jdGlvbihjb25zdHJ1Y3RvclNpZ25hdHVyZSwgcmF3Q29uc3RydWN0b3IpLAogICAgICAgIHJhd0Rlc3RydWN0b3I6IGVtYmluZF9fcmVxdWlyZUZ1bmN0aW9uKGRlc3RydWN0b3JTaWduYXR1cmUsIHJhd0Rlc3RydWN0b3IpLAogICAgICAgIGZpZWxkczogW10sCiAgICAgIH07CiAgICB9CiAgICBmdW5jdGlvbiBfX2VtYmluZF9yZWdpc3Rlcl92YWx1ZV9vYmplY3RfZmllbGQoCiAgICAgIHN0cnVjdFR5cGUsCiAgICAgIGZpZWxkTmFtZSwKICAgICAgZ2V0dGVyUmV0dXJuVHlwZSwKICAgICAgZ2V0dGVyU2lnbmF0dXJlLAogICAgICBnZXR0ZXIsCiAgICAgIGdldHRlckNvbnRleHQsCiAgICAgIHNldHRlckFyZ3VtZW50VHlwZSwKICAgICAgc2V0dGVyU2lnbmF0dXJlLAogICAgICBzZXR0ZXIsCiAgICAgIHNldHRlckNvbnRleHQKICAgICkgewogICAgICBzdHJ1Y3RSZWdpc3RyYXRpb25zW3N0cnVjdFR5cGVdLmZpZWxkcy5wdXNoKHsKICAgICAgICBmaWVsZE5hbWU6IHJlYWRMYXRpbjFTdHJpbmcoZmllbGROYW1lKSwKICAgICAgICBnZXR0ZXJSZXR1cm5UeXBlOiBnZXR0ZXJSZXR1cm5UeXBlLAogICAgICAgIGdldHRlcjogZW1iaW5kX19yZXF1aXJlRnVuY3Rpb24oZ2V0dGVyU2lnbmF0dXJlLCBnZXR0ZXIpLAogICAgICAgIGdldHRlckNvbnRleHQ6IGdldHRlckNvbnRleHQsCiAgICAgICAgc2V0dGVyQXJndW1lbnRUeXBlOiBzZXR0ZXJBcmd1bWVudFR5cGUsCiAgICAgICAgc2V0dGVyOiBlbWJpbmRfX3JlcXVpcmVGdW5jdGlvbihzZXR0ZXJTaWduYXR1cmUsIHNldHRlciksCiAgICAgICAgc2V0dGVyQ29udGV4dDogc2V0dGVyQ29udGV4dCwKICAgICAgfSk7CiAgICB9CiAgICBmdW5jdGlvbiBfX2VtYmluZF9yZWdpc3Rlcl92b2lkKHJhd1R5cGUsIG5hbWUpIHsKICAgICAgbmFtZSA9IHJlYWRMYXRpbjFTdHJpbmcobmFtZSk7CiAgICAgIHJlZ2lzdGVyVHlwZShyYXdUeXBlLCB7CiAgICAgICAgaXNWb2lkOiB0cnVlLAogICAgICAgIG5hbWU6IG5hbWUsCiAgICAgICAgYXJnUGFja0FkdmFuY2U6IDAsCiAgICAgICAgZnJvbVdpcmVUeXBlOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkCiAgICAgICAgfSwKICAgICAgICB0b1dpcmVUeXBlOiBmdW5jdGlvbiAoZGVzdHJ1Y3RvcnMsIG8pIHsKICAgICAgICAgIHJldHVybiB1bmRlZmluZWQKICAgICAgICB9LAogICAgICB9KTsKICAgIH0KICAgIGZ1bmN0aW9uIF9hYm9ydCgpIHsKICAgICAgTW9kdWxlWydhYm9ydCddKCk7CiAgICB9CiAgICB2YXIgX2Vudmlyb24gPSBTVEFUSUNUT1A7CiAgICBTVEFUSUNUT1AgKz0gMTY7CiAgICBmdW5jdGlvbiBfX19idWlsZEVudmlyb25tZW50KGVudikgewogICAgICB2YXIgTUFYX0VOVl9WQUxVRVMgPSA2NDsKICAgICAgdmFyIFRPVEFMX0VOVl9TSVpFID0gMTAyNDsKICAgICAgdmFyIHBvb2xQdHI7CiAgICAgIHZhciBlbnZQdHI7CiAgICAgIGlmICghX19fYnVpbGRFbnZpcm9ubWVudC5jYWxsZWQpIHsKICAgICAgICBfX19idWlsZEVudmlyb25tZW50LmNhbGxlZCA9IHRydWU7CiAgICAgICAgRU5WWydVU0VSJ10gPSBFTlZbJ0xPR05BTUUnXSA9ICd3ZWJfdXNlcic7CiAgICAgICAgRU5WWydQQVRIJ10gPSAnLyc7CiAgICAgICAgRU5WWydQV0QnXSA9ICcvJzsKICAgICAgICBFTlZbJ0hPTUUnXSA9ICcvaG9tZS93ZWJfdXNlcic7CiAgICAgICAgRU5WWydMQU5HJ10gPSAnQy5VVEYtOCc7CiAgICAgICAgRU5WWydfJ10gPSBNb2R1bGVbJ3RoaXNQcm9ncmFtJ107CiAgICAgICAgcG9vbFB0ciA9IHN0YXRpY0FsbG9jKFRPVEFMX0VOVl9TSVpFKTsKICAgICAgICBlbnZQdHIgPSBzdGF0aWNBbGxvYyhNQVhfRU5WX1ZBTFVFUyAqIDQpOwogICAgICAgIEhFQVAzMltlbnZQdHIgPj4gMl0gPSBwb29sUHRyOwogICAgICAgIEhFQVAzMltfZW52aXJvbiA+PiAyXSA9IGVudlB0cjsKICAgICAgfSBlbHNlIHsKICAgICAgICBlbnZQdHIgPSBIRUFQMzJbX2Vudmlyb24gPj4gMl07CiAgICAgICAgcG9vbFB0ciA9IEhFQVAzMltlbnZQdHIgPj4gMl07CiAgICAgIH0KICAgICAgdmFyIHN0cmluZ3MgPSBbXTsKICAgICAgdmFyIHRvdGFsU2l6ZSA9IDA7CiAgICAgIGZvciAodmFyIGtleSBpbiBlbnYpIHsKICAgICAgICBpZiAodHlwZW9mIGVudltrZXldID09PSAnc3RyaW5nJykgewogICAgICAgICAgdmFyIGxpbmUgPSBrZXkgKyAnPScgKyBlbnZba2V5XTsKICAgICAgICAgIHN0cmluZ3MucHVzaChsaW5lKTsKICAgICAgICAgIHRvdGFsU2l6ZSArPSBsaW5lLmxlbmd0aDsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKHRvdGFsU2l6ZSA+IFRPVEFMX0VOVl9TSVpFKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFbnZpcm9ubWVudCBzaXplIGV4Y2VlZGVkIFRPVEFMX0VOVl9TSVpFIScpCiAgICAgIH0KICAgICAgdmFyIHB0clNpemUgPSA0OwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0cmluZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgbGluZSA9IHN0cmluZ3NbaV07CiAgICAgICAgd3JpdGVBc2NpaVRvTWVtb3J5KGxpbmUsIHBvb2xQdHIpOwogICAgICAgIEhFQVAzMlsoZW52UHRyICsgaSAqIHB0clNpemUpID4+IDJdID0gcG9vbFB0cjsKICAgICAgICBwb29sUHRyICs9IGxpbmUubGVuZ3RoICsgMTsKICAgICAgfQogICAgICBIRUFQMzJbKGVudlB0ciArIHN0cmluZ3MubGVuZ3RoICogcHRyU2l6ZSkgPj4gMl0gPSAwOwogICAgfQogICAgdmFyIEVOViA9IHt9OwogICAgZnVuY3Rpb24gX2dldGVudihuYW1lKSB7CiAgICAgIGlmIChuYW1lID09PSAwKSByZXR1cm4gMAogICAgICBuYW1lID0gUG9pbnRlcl9zdHJpbmdpZnkobmFtZSk7CiAgICAgIGlmICghRU5WLmhhc093blByb3BlcnR5KG5hbWUpKSByZXR1cm4gMAogICAgICBpZiAoX2dldGVudi5yZXQpIF9mcmVlKF9nZXRlbnYucmV0KTsKICAgICAgX2dldGVudi5yZXQgPSBhbGxvY2F0ZVVURjgoRU5WW25hbWVdKTsKICAgICAgcmV0dXJuIF9nZXRlbnYucmV0CiAgICB9CiAgICBmdW5jdGlvbiBfZ2V0Z3JuYW0oKSB7CiAgICAgIE1vZHVsZVsncHJpbnRFcnInXSgnbWlzc2luZyBmdW5jdGlvbjogZ2V0Z3JuYW0nKTsKICAgICAgYWJvcnQoLTEpOwogICAgfQogICAgZnVuY3Rpb24gX2dldHB3bmFtKCkgewogICAgICB0aHJvdyAnZ2V0cHduYW06IFRPRE8nCiAgICB9CiAgICBmdW5jdGlvbiBfanNDbG9zZSgpIHsKICAgICAgcmV0dXJuIGpzQVBJLmNsb3NlLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0KICAgIGZ1bmN0aW9uIF9qc0NyZWF0ZShmaWxlbmFtZSkgewogICAgICByZXR1cm4ganNBUEkuY3JlYXRlLmNhbGwobnVsbCwgVVRGMzJUb1N0cmluZyhmaWxlbmFtZSkpCiAgICB9CiAgICBmdW5jdGlvbiBfanNPcGVuKGZpbGVuYW1lKSB7CiAgICAgIHJldHVybiBqc0FQSS5vcGVuLmNhbGwobnVsbCwgVVRGMzJUb1N0cmluZyhmaWxlbmFtZSkpCiAgICB9CiAgICBmdW5jdGlvbiBfanNSZWFkKCkgewogICAgICByZXR1cm4ganNBUEkucmVhZC5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICB9CiAgICBmdW5jdGlvbiBfanNTZWVrKGZkLCBvZmZzZXQsIG1ldGhvZCkgewogICAgICByZXR1cm4ganNBUEkuc2Vlay5jYWxsKG51bGwsIGZkLCBvZmZzZXQsIFVURjhUb1N0cmluZyhtZXRob2QpKQogICAgfQogICAgZnVuY3Rpb24gX2pzVGVsbCgpIHsKICAgICAgcmV0dXJuIGpzQVBJLnRlbGwuYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfQogICAgZnVuY3Rpb24gX2pzV3JpdGUoKSB7CiAgICAgIHJldHVybiBqc0FQSS53cml0ZS5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICB9CiAgICBmdW5jdGlvbiBfbGx2bV9laF90eXBlaWRfZm9yKHR5cGUpIHsKICAgICAgcmV0dXJuIHR5cGUKICAgIH0KICAgIHZhciBfX190bV9jdXJyZW50ID0gU1RBVElDVE9QOwogICAgU1RBVElDVE9QICs9IDQ4OwogICAgYWxsb2NhdGUoaW50QXJyYXlGcm9tU3RyaW5nKCdHTVQnKSwgJ2k4JywgQUxMT0NfU1RBVElDKTsKICAgIHZhciBfdHpuYW1lID0gU1RBVElDVE9QOwogICAgU1RBVElDVE9QICs9IDE2OwogICAgdmFyIF9kYXlsaWdodCA9IFNUQVRJQ1RPUDsKICAgIFNUQVRJQ1RPUCArPSAxNjsKICAgIHZhciBfdGltZXpvbmUgPSBTVEFUSUNUT1A7CiAgICBTVEFUSUNUT1AgKz0gMTY7CiAgICBmdW5jdGlvbiBfdHpzZXQoKSB7CiAgICAgIGlmIChfdHpzZXQuY2FsbGVkKSByZXR1cm4KICAgICAgX3R6c2V0LmNhbGxlZCA9IHRydWU7CiAgICAgIEhFQVAzMltfdGltZXpvbmUgPj4gMl0gPSBuZXcgRGF0ZSgpLmdldFRpbWV6b25lT2Zmc2V0KCkgKiA2MDsKICAgICAgdmFyIHdpbnRlciA9IG5ldyBEYXRlKDJlMywgMCwgMSk7CiAgICAgIHZhciBzdW1tZXIgPSBuZXcgRGF0ZSgyZTMsIDYsIDEpOwogICAgICBIRUFQMzJbX2RheWxpZ2h0ID4+IDJdID0gTnVtYmVyKHdpbnRlci5nZXRUaW1lem9uZU9mZnNldCgpICE9IHN1bW1lci5nZXRUaW1lem9uZU9mZnNldCgpKTsKICAgICAgZnVuY3Rpb24gZXh0cmFjdFpvbmUoZGF0ZSkgewogICAgICAgIHZhciBtYXRjaCA9IGRhdGUudG9UaW1lU3RyaW5nKCkubWF0Y2goL1woKFtBLVphLXogXSspXCkkLyk7CiAgICAgICAgcmV0dXJuIG1hdGNoID8gbWF0Y2hbMV0gOiAnR01UJwogICAgICB9CiAgICAgIHZhciB3aW50ZXJOYW1lID0gZXh0cmFjdFpvbmUod2ludGVyKTsKICAgICAgdmFyIHN1bW1lck5hbWUgPSBleHRyYWN0Wm9uZShzdW1tZXIpOwogICAgICB2YXIgd2ludGVyTmFtZVB0ciA9IGFsbG9jYXRlKGludEFycmF5RnJvbVN0cmluZyh3aW50ZXJOYW1lKSwgJ2k4JywgQUxMT0NfTk9STUFMKTsKICAgICAgdmFyIHN1bW1lck5hbWVQdHIgPSBhbGxvY2F0ZShpbnRBcnJheUZyb21TdHJpbmcoc3VtbWVyTmFtZSksICdpOCcsIEFMTE9DX05PUk1BTCk7CiAgICAgIGlmIChzdW1tZXIuZ2V0VGltZXpvbmVPZmZzZXQoKSA8IHdpbnRlci5nZXRUaW1lem9uZU9mZnNldCgpKSB7CiAgICAgICAgSEVBUDMyW190em5hbWUgPj4gMl0gPSB3aW50ZXJOYW1lUHRyOwogICAgICAgIEhFQVAzMlsoX3R6bmFtZSArIDQpID4+IDJdID0gc3VtbWVyTmFtZVB0cjsKICAgICAgfSBlbHNlIHsKICAgICAgICBIRUFQMzJbX3R6bmFtZSA+PiAyXSA9IHN1bW1lck5hbWVQdHI7CiAgICAgICAgSEVBUDMyWyhfdHpuYW1lICsgNCkgPj4gMl0gPSB3aW50ZXJOYW1lUHRyOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBfbG9jYWx0aW1lX3IodGltZSwgdG1QdHIpIHsKICAgICAgX3R6c2V0KCk7CiAgICAgIHZhciBkYXRlID0gbmV3IERhdGUoSEVBUDMyW3RpbWUgPj4gMl0gKiAxZTMpOwogICAgICBIRUFQMzJbdG1QdHIgPj4gMl0gPSBkYXRlLmdldFNlY29uZHMoKTsKICAgICAgSEVBUDMyWyh0bVB0ciArIDQpID4+IDJdID0gZGF0ZS5nZXRNaW51dGVzKCk7CiAgICAgIEhFQVAzMlsodG1QdHIgKyA4KSA+PiAyXSA9IGRhdGUuZ2V0SG91cnMoKTsKICAgICAgSEVBUDMyWyh0bVB0ciArIDEyKSA+PiAyXSA9IGRhdGUuZ2V0RGF0ZSgpOwogICAgICBIRUFQMzJbKHRtUHRyICsgMTYpID4+IDJdID0gZGF0ZS5nZXRNb250aCgpOwogICAgICBIRUFQMzJbKHRtUHRyICsgMjApID4+IDJdID0gZGF0ZS5nZXRGdWxsWWVhcigpIC0gMTkwMDsKICAgICAgSEVBUDMyWyh0bVB0ciArIDI0KSA+PiAyXSA9IGRhdGUuZ2V0RGF5KCk7CiAgICAgIHZhciBzdGFydCA9IG5ldyBEYXRlKGRhdGUuZ2V0RnVsbFllYXIoKSwgMCwgMSk7CiAgICAgIHZhciB5ZGF5ID0gKChkYXRlLmdldFRpbWUoKSAtIHN0YXJ0LmdldFRpbWUoKSkgLyAoMWUzICogNjAgKiA2MCAqIDI0KSkgfCAwOwogICAgICBIRUFQMzJbKHRtUHRyICsgMjgpID4+IDJdID0geWRheTsKICAgICAgSEVBUDMyWyh0bVB0ciArIDM2KSA+PiAyXSA9IC0oZGF0ZS5nZXRUaW1lem9uZU9mZnNldCgpICogNjApOwogICAgICB2YXIgc3VtbWVyT2Zmc2V0ID0gbmV3IERhdGUoMmUzLCA2LCAxKS5nZXRUaW1lem9uZU9mZnNldCgpOwogICAgICB2YXIgd2ludGVyT2Zmc2V0ID0gc3RhcnQuZ2V0VGltZXpvbmVPZmZzZXQoKTsKICAgICAgdmFyIGRzdCA9IChzdW1tZXJPZmZzZXQgIT0gd2ludGVyT2Zmc2V0ICYmIGRhdGUuZ2V0VGltZXpvbmVPZmZzZXQoKSA9PSBNYXRoLm1pbih3aW50ZXJPZmZzZXQsIHN1bW1lck9mZnNldCkpIHwgMDsKICAgICAgSEVBUDMyWyh0bVB0ciArIDMyKSA+PiAyXSA9IGRzdDsKICAgICAgdmFyIHpvbmVQdHIgPSBIRUFQMzJbKF90em5hbWUgKyAoZHN0ID8gNCA6IDApKSA+PiAyXTsKICAgICAgSEVBUDMyWyh0bVB0ciArIDQwKSA+PiAyXSA9IHpvbmVQdHI7CiAgICAgIHJldHVybiB0bVB0cgogICAgfQogICAgZnVuY3Rpb24gX2xvY2FsdGltZSh0aW1lKSB7CiAgICAgIHJldHVybiBfbG9jYWx0aW1lX3IodGltZSwgX19fdG1fY3VycmVudCkKICAgIH0KICAgIGZ1bmN0aW9uIF9lbXNjcmlwdGVuX21lbWNweV9iaWcoZGVzdCwgc3JjLCBudW0pIHsKICAgICAgSEVBUFU4LnNldChIRUFQVTguc3ViYXJyYXkoc3JjLCBzcmMgKyBudW0pLCBkZXN0KTsKICAgICAgcmV0dXJuIGRlc3QKICAgIH0KICAgIGZ1bmN0aW9uIF9ta3RpbWUodG1QdHIpIHsKICAgICAgX3R6c2V0KCk7CiAgICAgIHZhciBkYXRlID0gbmV3IERhdGUoCiAgICAgICAgSEVBUDMyWyh0bVB0ciArIDIwKSA+PiAyXSArIDE5MDAsCiAgICAgICAgSEVBUDMyWyh0bVB0ciArIDE2KSA+PiAyXSwKICAgICAgICBIRUFQMzJbKHRtUHRyICsgMTIpID4+IDJdLAogICAgICAgIEhFQVAzMlsodG1QdHIgKyA4KSA+PiAyXSwKICAgICAgICBIRUFQMzJbKHRtUHRyICsgNCkgPj4gMl0sCiAgICAgICAgSEVBUDMyW3RtUHRyID4+IDJdLAogICAgICAgIDAKICAgICAgKTsKICAgICAgdmFyIGRzdCA9IEhFQVAzMlsodG1QdHIgKyAzMikgPj4gMl07CiAgICAgIHZhciBndWVzc2VkT2Zmc2V0ID0gZGF0ZS5nZXRUaW1lem9uZU9mZnNldCgpOwogICAgICB2YXIgc3RhcnQgPSBuZXcgRGF0ZShkYXRlLmdldEZ1bGxZZWFyKCksIDAsIDEpOwogICAgICB2YXIgc3VtbWVyT2Zmc2V0ID0gbmV3IERhdGUoMmUzLCA2LCAxKS5nZXRUaW1lem9uZU9mZnNldCgpOwogICAgICB2YXIgd2ludGVyT2Zmc2V0ID0gc3RhcnQuZ2V0VGltZXpvbmVPZmZzZXQoKTsKICAgICAgdmFyIGRzdE9mZnNldCA9IE1hdGgubWluKHdpbnRlck9mZnNldCwgc3VtbWVyT2Zmc2V0KTsKICAgICAgaWYgKGRzdCA8IDApIHsKICAgICAgICBIRUFQMzJbKHRtUHRyICsgMzIpID4+IDJdID0gTnVtYmVyKHN1bW1lck9mZnNldCAhPSB3aW50ZXJPZmZzZXQgJiYgZHN0T2Zmc2V0ID09IGd1ZXNzZWRPZmZzZXQpOwogICAgICB9IGVsc2UgaWYgKGRzdCA+IDAgIT0gKGRzdE9mZnNldCA9PSBndWVzc2VkT2Zmc2V0KSkgewogICAgICAgIHZhciBub25Ec3RPZmZzZXQgPSBNYXRoLm1heCh3aW50ZXJPZmZzZXQsIHN1bW1lck9mZnNldCk7CiAgICAgICAgdmFyIHRydWVPZmZzZXQgPSBkc3QgPiAwID8gZHN0T2Zmc2V0IDogbm9uRHN0T2Zmc2V0OwogICAgICAgIGRhdGUuc2V0VGltZShkYXRlLmdldFRpbWUoKSArICh0cnVlT2Zmc2V0IC0gZ3Vlc3NlZE9mZnNldCkgKiA2ZTQpOwogICAgICB9CiAgICAgIEhFQVAzMlsodG1QdHIgKyAyNCkgPj4gMl0gPSBkYXRlLmdldERheSgpOwogICAgICB2YXIgeWRheSA9ICgoZGF0ZS5nZXRUaW1lKCkgLSBzdGFydC5nZXRUaW1lKCkpIC8gKDFlMyAqIDYwICogNjAgKiAyNCkpIHwgMDsKICAgICAgSEVBUDMyWyh0bVB0ciArIDI4KSA+PiAyXSA9IHlkYXk7CiAgICAgIHJldHVybiAoZGF0ZS5nZXRUaW1lKCkgLyAxZTMpIHwgMAogICAgfQogICAgdmFyIFBUSFJFQURfU1BFQ0lGSUMgPSB7fTsKICAgIGZ1bmN0aW9uIF9wdGhyZWFkX2dldHNwZWNpZmljKGtleSkgewogICAgICByZXR1cm4gUFRIUkVBRF9TUEVDSUZJQ1trZXldIHx8IDAKICAgIH0KICAgIHZhciBQVEhSRUFEX1NQRUNJRklDX05FWFRfS0VZID0gMTsKICAgIGZ1bmN0aW9uIF9wdGhyZWFkX2tleV9jcmVhdGUoa2V5LCBkZXN0cnVjdG9yKSB7CiAgICAgIGlmIChrZXkgPT0gMCkgewogICAgICAgIHJldHVybiBFUlJOT19DT0RFUy5FSU5WQUwKICAgICAgfQogICAgICBIRUFQMzJba2V5ID4+IDJdID0gUFRIUkVBRF9TUEVDSUZJQ19ORVhUX0tFWTsKICAgICAgUFRIUkVBRF9TUEVDSUZJQ1tQVEhSRUFEX1NQRUNJRklDX05FWFRfS0VZXSA9IDA7CiAgICAgIFBUSFJFQURfU1BFQ0lGSUNfTkVYVF9LRVkrKzsKICAgICAgcmV0dXJuIDAKICAgIH0KICAgIGZ1bmN0aW9uIF9wdGhyZWFkX29uY2UocHRyLCBmdW5jKSB7CiAgICAgIGlmICghX3B0aHJlYWRfb25jZS5zZWVuKSBfcHRocmVhZF9vbmNlLnNlZW4gPSB7fTsKICAgICAgaWYgKHB0ciBpbiBfcHRocmVhZF9vbmNlLnNlZW4pIHJldHVybgogICAgICBNb2R1bGVbJ2R5bkNhbGxfdiddKGZ1bmMpOwogICAgICBfcHRocmVhZF9vbmNlLnNlZW5bcHRyXSA9IDE7CiAgICB9CiAgICBmdW5jdGlvbiBfcHRocmVhZF9zZXRzcGVjaWZpYyhrZXksIHZhbHVlKSB7CiAgICAgIGlmICghKGtleSBpbiBQVEhSRUFEX1NQRUNJRklDKSkgewogICAgICAgIHJldHVybiBFUlJOT19DT0RFUy5FSU5WQUwKICAgICAgfQogICAgICBQVEhSRUFEX1NQRUNJRklDW2tleV0gPSB2YWx1ZTsKICAgICAgcmV0dXJuIDAKICAgIH0KICAgIGZ1bmN0aW9uIF90aW1lKHB0cikgewogICAgICB2YXIgcmV0ID0gKERhdGUubm93KCkgLyAxZTMpIHwgMDsKICAgICAgaWYgKHB0cikgewogICAgICAgIEhFQVAzMltwdHIgPj4gMl0gPSByZXQ7CiAgICAgIH0KICAgICAgcmV0dXJuIHJldAogICAgfQogICAgRlMuc3RhdGljSW5pdCgpOwogICAgX19BVElOSVRfXy51bnNoaWZ0KGZ1bmN0aW9uICgpIHsKICAgICAgaWYgKCFNb2R1bGVbJ25vRlNJbml0J10gJiYgIUZTLmluaXQuaW5pdGlhbGl6ZWQpIEZTLmluaXQoKTsKICAgIH0pOwogICAgX19BVE1BSU5fXy5wdXNoKGZ1bmN0aW9uICgpIHsKICAgICAgRlMuaWdub3JlUGVybWlzc2lvbnMgPSBmYWxzZTsKICAgIH0pOwogICAgX19BVEVYSVRfXy5wdXNoKGZ1bmN0aW9uICgpIHsKICAgICAgRlMucXVpdCgpOwogICAgfSk7CiAgICBfX0FUSU5JVF9fLnVuc2hpZnQoZnVuY3Rpb24gKCkgewogICAgfSk7CiAgICBfX0FURVhJVF9fLnB1c2goZnVuY3Rpb24gKCkgewogICAgfSk7CiAgICBJbnRlcm5hbEVycm9yID0gTW9kdWxlWydJbnRlcm5hbEVycm9yJ10gPSBleHRlbmRFcnJvcihFcnJvciwgJ0ludGVybmFsRXJyb3InKTsKICAgIGVtYmluZF9pbml0X2NoYXJDb2RlcygpOwogICAgQmluZGluZ0Vycm9yID0gTW9kdWxlWydCaW5kaW5nRXJyb3InXSA9IGV4dGVuZEVycm9yKEVycm9yLCAnQmluZGluZ0Vycm9yJyk7CiAgICBpbml0X0NsYXNzSGFuZGxlKCk7CiAgICBpbml0X1JlZ2lzdGVyZWRQb2ludGVyKCk7CiAgICBpbml0X2VtYmluZCgpOwogICAgVW5ib3VuZFR5cGVFcnJvciA9IE1vZHVsZVsnVW5ib3VuZFR5cGVFcnJvciddID0gZXh0ZW5kRXJyb3IoRXJyb3IsICdVbmJvdW5kVHlwZUVycm9yJyk7CiAgICBpbml0X2VtdmFsKCk7CiAgICBfX19idWlsZEVudmlyb25tZW50KEVOVik7CiAgICBEWU5BTUlDVE9QX1BUUiA9IHN0YXRpY0FsbG9jKDQpOwogICAgU1RBQ0tfQkFTRSA9IFNUQUNLVE9QID0gYWxpZ25NZW1vcnkoU1RBVElDVE9QKTsKICAgIFNUQUNLX01BWCA9IFNUQUNLX0JBU0UgKyBUT1RBTF9TVEFDSzsKICAgIERZTkFNSUNfQkFTRSA9IGFsaWduTWVtb3J5KFNUQUNLX01BWCk7CiAgICBIRUFQMzJbRFlOQU1JQ1RPUF9QVFIgPj4gMl0gPSBEWU5BTUlDX0JBU0U7CiAgICBzdGF0aWNTZWFsZWQgPSB0cnVlOwogICAgZnVuY3Rpb24gaW50QXJyYXlGcm9tU3RyaW5nKHN0cmluZ3ksIGRvbnRBZGROdWxsLCBsZW5ndGgpIHsKICAgICAgdmFyIGxlbiA9IGxlbmd0aCA+IDAgPyBsZW5ndGggOiBsZW5ndGhCeXRlc1VURjgoc3RyaW5neSkgKyAxOwogICAgICB2YXIgdThhcnJheSA9IG5ldyBBcnJheShsZW4pOwogICAgICB2YXIgbnVtQnl0ZXNXcml0dGVuID0gc3RyaW5nVG9VVEY4QXJyYXkoc3RyaW5neSwgdThhcnJheSwgMCwgdThhcnJheS5sZW5ndGgpOwogICAgICBpZiAoZG9udEFkZE51bGwpIHU4YXJyYXkubGVuZ3RoID0gbnVtQnl0ZXNXcml0dGVuOwogICAgICByZXR1cm4gdThhcnJheQogICAgfQogICAgTW9kdWxlWyd3YXNtVGFibGVTaXplJ10gPSAzMTY7CiAgICBNb2R1bGVbJ3dhc21NYXhUYWJsZVNpemUnXSA9IDMxNjsKICAgIGZ1bmN0aW9uIGludm9rZV9pKGluZGV4KSB7CiAgICAgIHRyeSB7CiAgICAgICAgcmV0dXJuIE1vZHVsZVsnZHluQ2FsbF9pJ10oaW5kZXgpCiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIGUgIT09ICdudW1iZXInICYmIGUgIT09ICdsb25nam1wJykgdGhyb3cgZQogICAgICAgIE1vZHVsZVsnc2V0VGhyZXcnXSgxLCAwKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gaW52b2tlX2lpKGluZGV4LCBhMSkgewogICAgICB0cnkgewogICAgICAgIHJldHVybiBNb2R1bGVbJ2R5bkNhbGxfaWknXShpbmRleCwgYTEpCiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIGUgIT09ICdudW1iZXInICYmIGUgIT09ICdsb25nam1wJykgdGhyb3cgZQogICAgICAgIE1vZHVsZVsnc2V0VGhyZXcnXSgxLCAwKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gaW52b2tlX2lpaShpbmRleCwgYTEsIGEyKSB7CiAgICAgIHRyeSB7CiAgICAgICAgcmV0dXJuIE1vZHVsZVsnZHluQ2FsbF9paWknXShpbmRleCwgYTEsIGEyKQogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgaWYgKHR5cGVvZiBlICE9PSAnbnVtYmVyJyAmJiBlICE9PSAnbG9uZ2ptcCcpIHRocm93IGUKICAgICAgICBNb2R1bGVbJ3NldFRocmV3J10oMSwgMCk7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIGludm9rZV9paWlpKGluZGV4LCBhMSwgYTIsIGEzKSB7CiAgICAgIHRyeSB7CiAgICAgICAgcmV0dXJuIE1vZHVsZVsnZHluQ2FsbF9paWlpJ10oaW5kZXgsIGExLCBhMiwgYTMpCiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIGUgIT09ICdudW1iZXInICYmIGUgIT09ICdsb25nam1wJykgdGhyb3cgZQogICAgICAgIE1vZHVsZVsnc2V0VGhyZXcnXSgxLCAwKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gaW52b2tlX2lpaWlpKGluZGV4LCBhMSwgYTIsIGEzLCBhNCkgewogICAgICB0cnkgewogICAgICAgIHJldHVybiBNb2R1bGVbJ2R5bkNhbGxfaWlpaWknXShpbmRleCwgYTEsIGEyLCBhMywgYTQpCiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIGUgIT09ICdudW1iZXInICYmIGUgIT09ICdsb25nam1wJykgdGhyb3cgZQogICAgICAgIE1vZHVsZVsnc2V0VGhyZXcnXSgxLCAwKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gaW52b2tlX2lpaWlpaWkoaW5kZXgsIGExLCBhMiwgYTMsIGE0LCBhNSwgYTYpIHsKICAgICAgdHJ5IHsKICAgICAgICByZXR1cm4gTW9kdWxlWydkeW5DYWxsX2lpaWlpaWknXShpbmRleCwgYTEsIGEyLCBhMywgYTQsIGE1LCBhNikKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmICh0eXBlb2YgZSAhPT0gJ251bWJlcicgJiYgZSAhPT0gJ2xvbmdqbXAnKSB0aHJvdyBlCiAgICAgICAgTW9kdWxlWydzZXRUaHJldyddKDEsIDApOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBpbnZva2VfaWlpaWlpaWlpaShpbmRleCwgYTEsIGEyLCBhMywgYTQsIGE1LCBhNiwgYTcsIGE4LCBhOSkgewogICAgICB0cnkgewogICAgICAgIHJldHVybiBNb2R1bGVbJ2R5bkNhbGxfaWlpaWlpaWlpaSddKGluZGV4LCBhMSwgYTIsIGEzLCBhNCwgYTUsIGE2LCBhNywgYTgsIGE5KQogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgaWYgKHR5cGVvZiBlICE9PSAnbnVtYmVyJyAmJiBlICE9PSAnbG9uZ2ptcCcpIHRocm93IGUKICAgICAgICBNb2R1bGVbJ3NldFRocmV3J10oMSwgMCk7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIGludm9rZV9paWlpaWlqaWkoaW5kZXgsIGExLCBhMiwgYTMsIGE0LCBhNSwgYTYsIGE3LCBhOCwgYTkpIHsKICAgICAgdHJ5IHsKICAgICAgICByZXR1cm4gTW9kdWxlWydkeW5DYWxsX2lpaWlpaWppaSddKGluZGV4LCBhMSwgYTIsIGEzLCBhNCwgYTUsIGE2LCBhNywgYTgsIGE5KQogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgaWYgKHR5cGVvZiBlICE9PSAnbnVtYmVyJyAmJiBlICE9PSAnbG9uZ2ptcCcpIHRocm93IGUKICAgICAgICBNb2R1bGVbJ3NldFRocmV3J10oMSwgMCk7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIGludm9rZV9pamooaW5kZXgsIGExLCBhMiwgYTMsIGE0KSB7CiAgICAgIHRyeSB7CiAgICAgICAgcmV0dXJuIE1vZHVsZVsnZHluQ2FsbF9pamonXShpbmRleCwgYTEsIGEyLCBhMywgYTQpCiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIGUgIT09ICdudW1iZXInICYmIGUgIT09ICdsb25nam1wJykgdGhyb3cgZQogICAgICAgIE1vZHVsZVsnc2V0VGhyZXcnXSgxLCAwKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gaW52b2tlX2ppKGluZGV4LCBhMSkgewogICAgICB0cnkgewogICAgICAgIHJldHVybiBNb2R1bGVbJ2R5bkNhbGxfamknXShpbmRleCwgYTEpCiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIGUgIT09ICdudW1iZXInICYmIGUgIT09ICdsb25nam1wJykgdGhyb3cgZQogICAgICAgIE1vZHVsZVsnc2V0VGhyZXcnXSgxLCAwKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gaW52b2tlX3YoaW5kZXgpIHsKICAgICAgdHJ5IHsKICAgICAgICBNb2R1bGVbJ2R5bkNhbGxfdiddKGluZGV4KTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmICh0eXBlb2YgZSAhPT0gJ251bWJlcicgJiYgZSAhPT0gJ2xvbmdqbXAnKSB0aHJvdyBlCiAgICAgICAgTW9kdWxlWydzZXRUaHJldyddKDEsIDApOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBpbnZva2VfdmkoaW5kZXgsIGExKSB7CiAgICAgIHRyeSB7CiAgICAgICAgTW9kdWxlWydkeW5DYWxsX3ZpJ10oaW5kZXgsIGExKTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmICh0eXBlb2YgZSAhPT0gJ251bWJlcicgJiYgZSAhPT0gJ2xvbmdqbXAnKSB0aHJvdyBlCiAgICAgICAgTW9kdWxlWydzZXRUaHJldyddKDEsIDApOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBpbnZva2VfdmlpKGluZGV4LCBhMSwgYTIpIHsKICAgICAgdHJ5IHsKICAgICAgICBNb2R1bGVbJ2R5bkNhbGxfdmlpJ10oaW5kZXgsIGExLCBhMik7CiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIGUgIT09ICdudW1iZXInICYmIGUgIT09ICdsb25nam1wJykgdGhyb3cgZQogICAgICAgIE1vZHVsZVsnc2V0VGhyZXcnXSgxLCAwKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gaW52b2tlX3ZpaWkoaW5kZXgsIGExLCBhMiwgYTMpIHsKICAgICAgdHJ5IHsKICAgICAgICBNb2R1bGVbJ2R5bkNhbGxfdmlpaSddKGluZGV4LCBhMSwgYTIsIGEzKTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmICh0eXBlb2YgZSAhPT0gJ251bWJlcicgJiYgZSAhPT0gJ2xvbmdqbXAnKSB0aHJvdyBlCiAgICAgICAgTW9kdWxlWydzZXRUaHJldyddKDEsIDApOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBpbnZva2VfdmlpaWkoaW5kZXgsIGExLCBhMiwgYTMsIGE0KSB7CiAgICAgIHRyeSB7CiAgICAgICAgTW9kdWxlWydkeW5DYWxsX3ZpaWlpJ10oaW5kZXgsIGExLCBhMiwgYTMsIGE0KTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmICh0eXBlb2YgZSAhPT0gJ251bWJlcicgJiYgZSAhPT0gJ2xvbmdqbXAnKSB0aHJvdyBlCiAgICAgICAgTW9kdWxlWydzZXRUaHJldyddKDEsIDApOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBpbnZva2VfdmlpaWlpKGluZGV4LCBhMSwgYTIsIGEzLCBhNCwgYTUpIHsKICAgICAgdHJ5IHsKICAgICAgICBNb2R1bGVbJ2R5bkNhbGxfdmlpaWlpJ10oaW5kZXgsIGExLCBhMiwgYTMsIGE0LCBhNSk7CiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIGUgIT09ICdudW1iZXInICYmIGUgIT09ICdsb25nam1wJykgdGhyb3cgZQogICAgICAgIE1vZHVsZVsnc2V0VGhyZXcnXSgxLCAwKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gaW52b2tlX3ZpaWlpaWkoaW5kZXgsIGExLCBhMiwgYTMsIGE0LCBhNSwgYTYpIHsKICAgICAgdHJ5IHsKICAgICAgICBNb2R1bGVbJ2R5bkNhbGxfdmlpaWlpaSddKGluZGV4LCBhMSwgYTIsIGEzLCBhNCwgYTUsIGE2KTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmICh0eXBlb2YgZSAhPT0gJ251bWJlcicgJiYgZSAhPT0gJ2xvbmdqbXAnKSB0aHJvdyBlCiAgICAgICAgTW9kdWxlWydzZXRUaHJldyddKDEsIDApOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBpbnZva2VfdmlpaWlpaWlpaShpbmRleCwgYTEsIGEyLCBhMywgYTQsIGE1LCBhNiwgYTcsIGE4LCBhOSkgewogICAgICB0cnkgewogICAgICAgIE1vZHVsZVsnZHluQ2FsbF92aWlpaWlpaWlpJ10oaW5kZXgsIGExLCBhMiwgYTMsIGE0LCBhNSwgYTYsIGE3LCBhOCwgYTkpOwogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgaWYgKHR5cGVvZiBlICE9PSAnbnVtYmVyJyAmJiBlICE9PSAnbG9uZ2ptcCcpIHRocm93IGUKICAgICAgICBNb2R1bGVbJ3NldFRocmV3J10oMSwgMCk7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIGludm9rZV92aWlpaWlpaWlpaShpbmRleCwgYTEsIGEyLCBhMywgYTQsIGE1LCBhNiwgYTcsIGE4LCBhOSwgYTEwKSB7CiAgICAgIHRyeSB7CiAgICAgICAgTW9kdWxlWydkeW5DYWxsX3ZpaWlpaWlpaWlpJ10oaW5kZXgsIGExLCBhMiwgYTMsIGE0LCBhNSwgYTYsIGE3LCBhOCwgYTksIGExMCk7CiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIGUgIT09ICdudW1iZXInICYmIGUgIT09ICdsb25nam1wJykgdGhyb3cgZQogICAgICAgIE1vZHVsZVsnc2V0VGhyZXcnXSgxLCAwKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gaW52b2tlX3ZpaihpbmRleCwgYTEsIGEyLCBhMykgewogICAgICB0cnkgewogICAgICAgIE1vZHVsZVsnZHluQ2FsbF92aWonXShpbmRleCwgYTEsIGEyLCBhMyk7CiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAodHlwZW9mIGUgIT09ICdudW1iZXInICYmIGUgIT09ICdsb25nam1wJykgdGhyb3cgZQogICAgICAgIE1vZHVsZVsnc2V0VGhyZXcnXSgxLCAwKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gaW52b2tlX3ZpamkoaW5kZXgsIGExLCBhMiwgYTMsIGE0KSB7CiAgICAgIHRyeSB7CiAgICAgICAgTW9kdWxlWydkeW5DYWxsX3ZpamknXShpbmRleCwgYTEsIGEyLCBhMywgYTQpOwogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgaWYgKHR5cGVvZiBlICE9PSAnbnVtYmVyJyAmJiBlICE9PSAnbG9uZ2ptcCcpIHRocm93IGUKICAgICAgICBNb2R1bGVbJ3NldFRocmV3J10oMSwgMCk7CiAgICAgIH0KICAgIH0KICAgIE1vZHVsZS5hc21HbG9iYWxBcmcgPSB7fTsKICAgIE1vZHVsZS5hc21MaWJyYXJ5QXJnID0gewogICAgICBhYm9ydDogYWJvcnQsCiAgICAgIGVubGFyZ2VNZW1vcnk6IGVubGFyZ2VNZW1vcnksCiAgICAgIGdldFRvdGFsTWVtb3J5OiBnZXRUb3RhbE1lbW9yeSwKICAgICAgYWJvcnRPbkNhbm5vdEdyb3dNZW1vcnk6IGFib3J0T25DYW5ub3RHcm93TWVtb3J5LAogICAgICBpbnZva2VfaTogaW52b2tlX2ksCiAgICAgIGludm9rZV9paTogaW52b2tlX2lpLAogICAgICBpbnZva2VfaWlpOiBpbnZva2VfaWlpLAogICAgICBpbnZva2VfaWlpaTogaW52b2tlX2lpaWksCiAgICAgIGludm9rZV9paWlpaTogaW52b2tlX2lpaWlpLAogICAgICBpbnZva2VfaWlpaWlpaTogaW52b2tlX2lpaWlpaWksCiAgICAgIGludm9rZV9paWlpaWlpaWlpOiBpbnZva2VfaWlpaWlpaWlpaSwKICAgICAgaW52b2tlX2lpaWlpaWppaTogaW52b2tlX2lpaWlpaWppaSwKICAgICAgaW52b2tlX2lqajogaW52b2tlX2lqaiwKICAgICAgaW52b2tlX2ppOiBpbnZva2VfamksCiAgICAgIGludm9rZV92OiBpbnZva2VfdiwKICAgICAgaW52b2tlX3ZpOiBpbnZva2VfdmksCiAgICAgIGludm9rZV92aWk6IGludm9rZV92aWksCiAgICAgIGludm9rZV92aWlpOiBpbnZva2VfdmlpaSwKICAgICAgaW52b2tlX3ZpaWlpOiBpbnZva2VfdmlpaWksCiAgICAgIGludm9rZV92aWlpaWk6IGludm9rZV92aWlpaWksCiAgICAgIGludm9rZV92aWlpaWlpOiBpbnZva2VfdmlpaWlpaSwKICAgICAgaW52b2tlX3ZpaWlpaWlpaWk6IGludm9rZV92aWlpaWlpaWlpLAogICAgICBpbnZva2VfdmlpaWlpaWlpaWk6IGludm9rZV92aWlpaWlpaWlpaSwKICAgICAgaW52b2tlX3ZpajogaW52b2tlX3ZpaiwKICAgICAgaW52b2tlX3Zpamk6IGludm9rZV92aWppLAogICAgICBfX19jeGFfYWxsb2NhdGVfZXhjZXB0aW9uOiBfX19jeGFfYWxsb2NhdGVfZXhjZXB0aW9uLAogICAgICBfX19jeGFfYmVnaW5fY2F0Y2g6IF9fX2N4YV9iZWdpbl9jYXRjaCwKICAgICAgX19fY3hhX2VuZF9jYXRjaDogX19fY3hhX2VuZF9jYXRjaCwKICAgICAgX19fY3hhX2ZpbmRfbWF0Y2hpbmdfY2F0Y2hfMjogX19fY3hhX2ZpbmRfbWF0Y2hpbmdfY2F0Y2hfMiwKICAgICAgX19fY3hhX2ZpbmRfbWF0Y2hpbmdfY2F0Y2hfMzogX19fY3hhX2ZpbmRfbWF0Y2hpbmdfY2F0Y2hfMywKICAgICAgX19fY3hhX2ZpbmRfbWF0Y2hpbmdfY2F0Y2hfNDogX19fY3hhX2ZpbmRfbWF0Y2hpbmdfY2F0Y2hfNCwKICAgICAgX19fY3hhX2ZyZWVfZXhjZXB0aW9uOiBfX19jeGFfZnJlZV9leGNlcHRpb24sCiAgICAgIF9fX2N4YV90aHJvdzogX19fY3hhX3Rocm93LAogICAgICBfX19sb2NrOiBfX19sb2NrLAogICAgICBfX19tYXBfZmlsZTogX19fbWFwX2ZpbGUsCiAgICAgIF9fX3Jlc3VtZUV4Y2VwdGlvbjogX19fcmVzdW1lRXhjZXB0aW9uLAogICAgICBfX19zZXRFcnJObzogX19fc2V0RXJyTm8sCiAgICAgIF9fX3N5c2NhbGwxNDA6IF9fX3N5c2NhbGwxNDAsCiAgICAgIF9fX3N5c2NhbGwxNDU6IF9fX3N5c2NhbGwxNDUsCiAgICAgIF9fX3N5c2NhbGwxNDY6IF9fX3N5c2NhbGwxNDYsCiAgICAgIF9fX3N5c2NhbGwxODM6IF9fX3N5c2NhbGwxODMsCiAgICAgIF9fX3N5c2NhbGwxOTg6IF9fX3N5c2NhbGwxOTgsCiAgICAgIF9fX3N5c2NhbGwyMDogX19fc3lzY2FsbDIwLAogICAgICBfX19zeXNjYWxsNjogX19fc3lzY2FsbDYsCiAgICAgIF9fX3N5c2NhbGw2MDogX19fc3lzY2FsbDYwLAogICAgICBfX19zeXNjYWxsODM6IF9fX3N5c2NhbGw4MywKICAgICAgX19fc3lzY2FsbDkxOiBfX19zeXNjYWxsOTEsCiAgICAgIF9fX3VubG9jazogX19fdW5sb2NrLAogICAgICBfX2VtYmluZF9maW5hbGl6ZV92YWx1ZV9vYmplY3Q6IF9fZW1iaW5kX2ZpbmFsaXplX3ZhbHVlX29iamVjdCwKICAgICAgX19lbWJpbmRfcmVnaXN0ZXJfYm9vbDogX19lbWJpbmRfcmVnaXN0ZXJfYm9vbCwKICAgICAgX19lbWJpbmRfcmVnaXN0ZXJfY2xhc3M6IF9fZW1iaW5kX3JlZ2lzdGVyX2NsYXNzLAogICAgICBfX2VtYmluZF9yZWdpc3Rlcl9jbGFzc19jb25zdHJ1Y3RvcjogX19lbWJpbmRfcmVnaXN0ZXJfY2xhc3NfY29uc3RydWN0b3IsCiAgICAgIF9fZW1iaW5kX3JlZ2lzdGVyX2NsYXNzX2Z1bmN0aW9uOiBfX2VtYmluZF9yZWdpc3Rlcl9jbGFzc19mdW5jdGlvbiwKICAgICAgX19lbWJpbmRfcmVnaXN0ZXJfZW12YWw6IF9fZW1iaW5kX3JlZ2lzdGVyX2VtdmFsLAogICAgICBfX2VtYmluZF9yZWdpc3Rlcl9mbG9hdDogX19lbWJpbmRfcmVnaXN0ZXJfZmxvYXQsCiAgICAgIF9fZW1iaW5kX3JlZ2lzdGVyX2ludGVnZXI6IF9fZW1iaW5kX3JlZ2lzdGVyX2ludGVnZXIsCiAgICAgIF9fZW1iaW5kX3JlZ2lzdGVyX21lbW9yeV92aWV3OiBfX2VtYmluZF9yZWdpc3Rlcl9tZW1vcnlfdmlldywKICAgICAgX19lbWJpbmRfcmVnaXN0ZXJfc3RkX3N0cmluZzogX19lbWJpbmRfcmVnaXN0ZXJfc3RkX3N0cmluZywKICAgICAgX19lbWJpbmRfcmVnaXN0ZXJfc3RkX3dzdHJpbmc6IF9fZW1iaW5kX3JlZ2lzdGVyX3N0ZF93c3RyaW5nLAogICAgICBfX2VtYmluZF9yZWdpc3Rlcl92YWx1ZV9vYmplY3Q6IF9fZW1iaW5kX3JlZ2lzdGVyX3ZhbHVlX29iamVjdCwKICAgICAgX19lbWJpbmRfcmVnaXN0ZXJfdmFsdWVfb2JqZWN0X2ZpZWxkOiBfX2VtYmluZF9yZWdpc3Rlcl92YWx1ZV9vYmplY3RfZmllbGQsCiAgICAgIF9fZW1iaW5kX3JlZ2lzdGVyX3ZvaWQ6IF9fZW1iaW5kX3JlZ2lzdGVyX3ZvaWQsCiAgICAgIF9hYm9ydDogX2Fib3J0LAogICAgICBfZW1zY3JpcHRlbl9tZW1jcHlfYmlnOiBfZW1zY3JpcHRlbl9tZW1jcHlfYmlnLAogICAgICBfZ2V0ZW52OiBfZ2V0ZW52LAogICAgICBfZ2V0Z3JuYW06IF9nZXRncm5hbSwKICAgICAgX2dldHB3bmFtOiBfZ2V0cHduYW0sCiAgICAgIF9qc0Nsb3NlOiBfanNDbG9zZSwKICAgICAgX2pzQ3JlYXRlOiBfanNDcmVhdGUsCiAgICAgIF9qc09wZW46IF9qc09wZW4sCiAgICAgIF9qc1JlYWQ6IF9qc1JlYWQsCiAgICAgIF9qc1NlZWs6IF9qc1NlZWssCiAgICAgIF9qc1RlbGw6IF9qc1RlbGwsCiAgICAgIF9qc1dyaXRlOiBfanNXcml0ZSwKICAgICAgX2xsdm1fZWhfdHlwZWlkX2ZvcjogX2xsdm1fZWhfdHlwZWlkX2ZvciwKICAgICAgX2xvY2FsdGltZTogX2xvY2FsdGltZSwKICAgICAgX21rdGltZTogX21rdGltZSwKICAgICAgX3B0aHJlYWRfZ2V0c3BlY2lmaWM6IF9wdGhyZWFkX2dldHNwZWNpZmljLAogICAgICBfcHRocmVhZF9rZXlfY3JlYXRlOiBfcHRocmVhZF9rZXlfY3JlYXRlLAogICAgICBfcHRocmVhZF9vbmNlOiBfcHRocmVhZF9vbmNlLAogICAgICBfcHRocmVhZF9zZXRzcGVjaWZpYzogX3B0aHJlYWRfc2V0c3BlY2lmaWMsCiAgICAgIF90aW1lOiBfdGltZSwKICAgICAgRFlOQU1JQ1RPUF9QVFI6IERZTkFNSUNUT1BfUFRSLAogICAgICBTVEFDS1RPUDogU1RBQ0tUT1AsCiAgICB9OwogICAgdmFyIGFzbSA9IE1vZHVsZVsnYXNtJ10oTW9kdWxlLmFzbUdsb2JhbEFyZywgTW9kdWxlLmFzbUxpYnJhcnlBcmcsIGJ1ZmZlcik7CiAgICBNb2R1bGVbJ2FzbSddID0gYXNtOwogICAgdmFyIF9fR0xPQkFMX19zdWJfSV9iaW5kX2NwcCA9IChNb2R1bGVbJ19fR0xPQkFMX19zdWJfSV9iaW5kX2NwcCddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnX19HTE9CQUxfX3N1Yl9JX2JpbmRfY3BwJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICB2YXIgX19HTE9CQUxfX3N1Yl9JX2JyaWRnZV9jcHAgPSAoTW9kdWxlWydfX0dMT0JBTF9fc3ViX0lfYnJpZGdlX2NwcCddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnX19HTE9CQUxfX3N1Yl9JX2JyaWRnZV9jcHAnXS5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICB9KTsKICAgIHZhciBfX0dMT0JBTF9fc3ViX0lfY3JjX2NwcCA9IChNb2R1bGVbJ19fR0xPQkFMX19zdWJfSV9jcmNfY3BwJ10gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBNb2R1bGVbJ2FzbSddWydfX0dMT0JBTF9fc3ViX0lfY3JjX2NwcCddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgdmFyIF9fR0xPQkFMX19zdWJfSV9nbG9iYWxfY3BwID0gKE1vZHVsZVsnX19HTE9CQUxfX3N1Yl9JX2dsb2JhbF9jcHAnXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ19fR0xPQkFMX19zdWJfSV9nbG9iYWxfY3BwJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICAoTW9kdWxlWydfX19jeGFfY2FuX2NhdGNoJ10gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBNb2R1bGVbJ2FzbSddWydfX19jeGFfY2FuX2NhdGNoJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICAoTW9kdWxlWydfX19jeGFfaXNfcG9pbnRlcl90eXBlJ10gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBNb2R1bGVbJ2FzbSddWydfX19jeGFfaXNfcG9pbnRlcl90eXBlJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICAoTW9kdWxlWydfX19lcnJub19sb2NhdGlvbiddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnX19fZXJybm9fbG9jYXRpb24nXS5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICB9KTsKICAgIHZhciBfX19nZXRUeXBlTmFtZSA9IChNb2R1bGVbJ19fX2dldFR5cGVOYW1lJ10gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBNb2R1bGVbJ2FzbSddWydfX19nZXRUeXBlTmFtZSddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgdmFyIF9lbXNjcmlwdGVuX3JlcGxhY2VfbWVtb3J5ID0gKE1vZHVsZVsnX2Vtc2NyaXB0ZW5fcmVwbGFjZV9tZW1vcnknXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ19lbXNjcmlwdGVuX3JlcGxhY2VfbWVtb3J5J10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICB2YXIgX2ZyZWUgPSAoTW9kdWxlWydfZnJlZSddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnX2ZyZWUnXS5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICB9KTsKICAgIHZhciBfbWFsbG9jID0gKE1vZHVsZVsnX21hbGxvYyddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnX21hbGxvYyddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgdmFyIHNldFRlbXBSZXQwID0gKE1vZHVsZVsnc2V0VGVtcFJldDAnXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ3NldFRlbXBSZXQwJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICAoTW9kdWxlWydzZXRUaHJldyddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnc2V0VGhyZXcnXS5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICB9KTsKICAgIHZhciBzdGFja0FsbG9jID0gKE1vZHVsZVsnc3RhY2tBbGxvYyddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnc3RhY2tBbGxvYyddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgKE1vZHVsZVsnZHluQ2FsbF9kaWknXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ2R5bkNhbGxfZGlpJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICAoTW9kdWxlWydkeW5DYWxsX2knXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ2R5bkNhbGxfaSddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgKE1vZHVsZVsnZHluQ2FsbF9paSddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnZHluQ2FsbF9paSddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgKE1vZHVsZVsnZHluQ2FsbF9paWknXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ2R5bkNhbGxfaWlpJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICAoTW9kdWxlWydkeW5DYWxsX2lpaWknXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ2R5bkNhbGxfaWlpaSddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgKE1vZHVsZVsnZHluQ2FsbF9paWlpaSddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnZHluQ2FsbF9paWlpaSddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgKE1vZHVsZVsnZHluQ2FsbF9paWlpaWknXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ2R5bkNhbGxfaWlpaWlpJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICAoTW9kdWxlWydkeW5DYWxsX2lpaWlpaWknXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ2R5bkNhbGxfaWlpaWlpaSddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgKE1vZHVsZVsnZHluQ2FsbF9paWlpaWlpaWlpJ10gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBNb2R1bGVbJ2FzbSddWydkeW5DYWxsX2lpaWlpaWlpaWknXS5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICB9KTsKICAgIChNb2R1bGVbJ2R5bkNhbGxfaWlpaWlpamlpJ10gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBNb2R1bGVbJ2FzbSddWydkeW5DYWxsX2lpaWlpaWppaSddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgKE1vZHVsZVsnZHluQ2FsbF9pamonXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ2R5bkNhbGxfaWpqJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICAoTW9kdWxlWydkeW5DYWxsX2ppJ10gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBNb2R1bGVbJ2FzbSddWydkeW5DYWxsX2ppJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICAoTW9kdWxlWydkeW5DYWxsX3YnXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ2R5bkNhbGxfdiddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgKE1vZHVsZVsnZHluQ2FsbF92aSddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnZHluQ2FsbF92aSddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgKE1vZHVsZVsnZHluQ2FsbF92aWknXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ2R5bkNhbGxfdmlpJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICAoTW9kdWxlWydkeW5DYWxsX3ZpaWQnXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ2R5bkNhbGxfdmlpZCddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgKE1vZHVsZVsnZHluQ2FsbF92aWlpJ10gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBNb2R1bGVbJ2FzbSddWydkeW5DYWxsX3ZpaWknXS5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICB9KTsKICAgIChNb2R1bGVbJ2R5bkNhbGxfdmlpaWknXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIE1vZHVsZVsnYXNtJ11bJ2R5bkNhbGxfdmlpaWknXS5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICB9KTsKICAgIChNb2R1bGVbJ2R5bkNhbGxfdmlpaWlpJ10gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBNb2R1bGVbJ2FzbSddWydkeW5DYWxsX3ZpaWlpaSddLmFwcGx5KG51bGwsIGFyZ3VtZW50cykKICAgIH0pOwogICAgKE1vZHVsZVsnZHluQ2FsbF92aWlpaWlpJ10gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBNb2R1bGVbJ2FzbSddWydkeW5DYWxsX3ZpaWlpaWknXS5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICB9KTsKICAgIChNb2R1bGVbJ2R5bkNhbGxfdmlpaWlpaWlpaSddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnZHluQ2FsbF92aWlpaWlpaWlpJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICAoTW9kdWxlWydkeW5DYWxsX3ZpaWlpaWlpaWlpJ10gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBNb2R1bGVbJ2FzbSddWydkeW5DYWxsX3ZpaWlpaWlpaWlpJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICAoTW9kdWxlWydkeW5DYWxsX3ZpaiddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnZHluQ2FsbF92aWonXS5hcHBseShudWxsLCBhcmd1bWVudHMpCiAgICB9KTsKICAgIChNb2R1bGVbJ2R5bkNhbGxfdmlqaSddID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gTW9kdWxlWydhc20nXVsnZHluQ2FsbF92aWppJ10uYXBwbHkobnVsbCwgYXJndW1lbnRzKQogICAgfSk7CiAgICBNb2R1bGVbJ2FzbSddID0gYXNtOwogICAgZnVuY3Rpb24gRXhpdFN0YXR1cyhzdGF0dXMpIHsKICAgICAgdGhpcy5uYW1lID0gJ0V4aXRTdGF0dXMnOwogICAgICB0aGlzLm1lc3NhZ2UgPSAnUHJvZ3JhbSB0ZXJtaW5hdGVkIHdpdGggZXhpdCgnICsgc3RhdHVzICsgJyknOwogICAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICAgIH0KICAgIEV4aXRTdGF0dXMucHJvdG90eXBlID0gbmV3IEVycm9yKCk7CiAgICBFeGl0U3RhdHVzLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEV4aXRTdGF0dXM7CiAgICB2YXIgaW5pdGlhbFN0YWNrVG9wOwogICAgZGVwZW5kZW5jaWVzRnVsZmlsbGVkID0gZnVuY3Rpb24gcnVuQ2FsbGVyKCkgewogICAgICBpZiAoIU1vZHVsZVsnY2FsbGVkUnVuJ10pIHJ1bigpOwogICAgICBpZiAoIU1vZHVsZVsnY2FsbGVkUnVuJ10pIGRlcGVuZGVuY2llc0Z1bGZpbGxlZCA9IHJ1bkNhbGxlcjsKICAgIH07CiAgICBmdW5jdGlvbiBydW4oYXJncykgewogICAgICBhcmdzID0gYXJncyB8fCBNb2R1bGVbJ2FyZ3VtZW50cyddOwogICAgICBpZiAocnVuRGVwZW5kZW5jaWVzID4gMCkgewogICAgICAgIHJldHVybgogICAgICB9CiAgICAgIHByZVJ1bigpOwogICAgICBpZiAocnVuRGVwZW5kZW5jaWVzID4gMCkgcmV0dXJuCiAgICAgIGlmIChNb2R1bGVbJ2NhbGxlZFJ1biddKSByZXR1cm4KICAgICAgZnVuY3Rpb24gZG9SdW4oKSB7CiAgICAgICAgaWYgKE1vZHVsZVsnY2FsbGVkUnVuJ10pIHJldHVybgogICAgICAgIE1vZHVsZVsnY2FsbGVkUnVuJ10gPSB0cnVlOwogICAgICAgIGlmIChBQk9SVCkgcmV0dXJuCiAgICAgICAgZW5zdXJlSW5pdFJ1bnRpbWUoKTsKICAgICAgICBwcmVNYWluKCk7CiAgICAgICAgaWYgKE1vZHVsZVsnb25SdW50aW1lSW5pdGlhbGl6ZWQnXSkgTW9kdWxlWydvblJ1bnRpbWVJbml0aWFsaXplZCddKCk7CiAgICAgICAgcG9zdFJ1bigpOwogICAgICB9CiAgICAgIGlmIChNb2R1bGVbJ3NldFN0YXR1cyddKSB7CiAgICAgICAgTW9kdWxlWydzZXRTdGF0dXMnXSgnUnVubmluZy4uLicpOwogICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgewogICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIE1vZHVsZVsnc2V0U3RhdHVzJ10oJycpOwogICAgICAgICAgfSwgMSk7CiAgICAgICAgICBkb1J1bigpOwogICAgICAgIH0sIDEpOwogICAgICB9IGVsc2UgewogICAgICAgIGRvUnVuKCk7CiAgICAgIH0KICAgIH0KICAgIE1vZHVsZVsncnVuJ10gPSBydW47CiAgICBmdW5jdGlvbiBleGl0KHN0YXR1cywgaW1wbGljaXQpIHsKICAgICAgaWYgKGltcGxpY2l0ICYmIE1vZHVsZVsnbm9FeGl0UnVudGltZSddICYmIHN0YXR1cyA9PT0gMCkgewogICAgICAgIHJldHVybgogICAgICB9CiAgICAgIGlmIChNb2R1bGVbJ25vRXhpdFJ1bnRpbWUnXSkgOyBlbHNlIHsKICAgICAgICBBQk9SVCA9IHRydWU7CiAgICAgICAgU1RBQ0tUT1AgPSBpbml0aWFsU3RhY2tUb3A7CiAgICAgICAgZXhpdFJ1bnRpbWUoKTsKICAgICAgICBpZiAoTW9kdWxlWydvbkV4aXQnXSkgTW9kdWxlWydvbkV4aXQnXShzdGF0dXMpOwogICAgICB9CiAgICAgIGlmIChFTlZJUk9OTUVOVF9JU19OT0RFKSB7CiAgICAgICAgcHJvY2Vzc1snZXhpdCddKHN0YXR1cyk7CiAgICAgIH0KICAgICAgTW9kdWxlWydxdWl0J10oc3RhdHVzLCBuZXcgRXhpdFN0YXR1cyhzdGF0dXMpKTsKICAgIH0KICAgIE1vZHVsZVsnZXhpdCddID0gZXhpdDsKICAgIGZ1bmN0aW9uIGFib3J0KHdoYXQpIHsKICAgICAgaWYgKE1vZHVsZVsnb25BYm9ydCddKSB7CiAgICAgICAgTW9kdWxlWydvbkFib3J0J10od2hhdCk7CiAgICAgIH0KICAgICAgaWYgKHdoYXQgIT09IHVuZGVmaW5lZCkgewogICAgICAgIE1vZHVsZS5wcmludCh3aGF0KTsKICAgICAgICBNb2R1bGUucHJpbnRFcnIod2hhdCk7CiAgICAgICAgd2hhdCA9IEpTT04uc3RyaW5naWZ5KHdoYXQpOwogICAgICB9IGVsc2UgewogICAgICAgIHdoYXQgPSAnJzsKICAgICAgfQogICAgICBBQk9SVCA9IHRydWU7CiAgICAgIHRocm93ICdhYm9ydCgnICsgd2hhdCArICcpLiBCdWlsZCB3aXRoIC1zIEFTU0VSVElPTlM9MSBmb3IgbW9yZSBpbmZvLicKICAgIH0KICAgIE1vZHVsZVsnYWJvcnQnXSA9IGFib3J0OwogICAgaWYgKE1vZHVsZVsncHJlSW5pdCddKSB7CiAgICAgIGlmICh0eXBlb2YgTW9kdWxlWydwcmVJbml0J10gPT0gJ2Z1bmN0aW9uJykgTW9kdWxlWydwcmVJbml0J10gPSBbTW9kdWxlWydwcmVJbml0J11dOwogICAgICB3aGlsZSAoTW9kdWxlWydwcmVJbml0J10ubGVuZ3RoID4gMCkgewogICAgICAgIE1vZHVsZVsncHJlSW5pdCddLnBvcCgpKCk7CiAgICAgIH0KICAgIH0KICAgIE1vZHVsZVsnbm9FeGl0UnVudGltZSddID0gdHJ1ZTsKICAgIHJ1bigpOwoKICAgIHJldHVybiB1bnBhY2sKICB9OwogIC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKICAvKioKICAgKiBSZXR1cm5zIGEgUHJvbWlzZSBjb250YWluaW5nIHRoZSByYXIgZXh0cmFjdG9yIGZvciB0aGUgZ2l2ZW4gZmlsZW5hbWUuCiAgICogQHByaXZhdGUKICAgKi8KICBmdW5jdGlvbiBnZXRFeHRyYWN0b3IodXJsKSB7CiAgICByZXR1cm4gZmV0Y2gobmV3IFJlcXVlc3QodXJsKSkKICAgICAgLnRoZW4oKHJlc3BvbnNlKSA9PiB7CiAgICAgICAgaWYgKHJlc3BvbnNlLm9rKSByZXR1cm4gcmVzcG9uc2UuYXJyYXlCdWZmZXIoKQogICAgICAgIGVsc2UgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCc0MDQgRXJyb3I6IEZpbGUgbm90IGZvdW5kLicpCiAgICAgICAgfQogICAgICB9KQogICAgICAudGhlbigoYnVmZmVyKSA9PiB1bnBhY2tCcmlkZ2UuY3JlYXRlRXh0cmFjdG9yRnJvbURhdGEoYnVmZmVyKSkKICB9CgogIC8qKgogICAqICBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgZm9ybWF0dGVkIGNvbnRlbnRzIG9mIHRoZSBnaXZlbiBmaWxlLgogICAqIEBwcml2YXRlCiAgICovCiAgZnVuY3Rpb24gZXh0cmFjdCh7IHJlc291cmNlSWQsIHVybCB9KSB7CiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgewogICAgICBpZiAoIXVucGFja0JyaWRnZSkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigndW5wYWNrQnJpZGdlIG5vdCBkZXRlY3RlZCcpCiAgICAgIH0KICAgICAgaWYgKCF1bnBhY2spIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3VucGFjayBub3QgZGV0ZWN0ZWQnKQogICAgICB9CgogICAgICBnZXRFeHRyYWN0b3IodXJsKS50aGVuKAogICAgICAgIChleHRyYWN0b3IpID0+IHsKICAgICAgICAgIC8vIHJldHVybiBleHRyYWN0b3IuZXh0cmFjdEFsbCgpOwogICAgICAgICAgcmVzb2x2ZShleHRyYWN0b3IuZXh0cmFjdEFsbCgpKTsKICAgICAgICB9LAogICAgICAgIChlcnIpID0+IHsKICAgICAgICAgIHJlamVjdChlcnIpOwogICAgICAgIH0KICAgICAgKTsKICAgIH0pCiAgfQoKICAvKioKICAgKiBMaXN0ZW4gZm9yIG1lc3NhZ2VzIHNlbnQgdG8gdGhlIHdvcmtlci4KICAgKiBAcHJpdmF0ZQogICAqLwogIGZ1bmN0aW9uIGhhbmRsZU1lc3NhZ2UoZGF0YSwgcG9zdE1lc3NhZ2UpIHsKICAgIGlmIChkYXRhLnR5cGUgPT0gJ2luaXQnKSB7CiAgICAgIHVucGFjayA9IGluaXR1bnBhY2soZGF0YS5idWZmZXIpOwogICAgICB1bnBhY2sub25SdW50aW1lSW5pdGlhbGl6ZWQgPSAoKSA9PiB7CiAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlOiAnV0FTTV9MT0FERUQnIH0pOwogICAgICB9OwogICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT0gJ2ZldGNoJykgewogICAgICBleHRyYWN0KGRhdGEpLnRoZW4oCiAgICAgICAgKHVucGFja2VkKSA9PiB7CiAgICAgICAgICByZXR1cm5EYXRhKGRhdGEsIHVucGFja2VkLCBwb3N0TWVzc2FnZSk7CiAgICAgICAgfSwKICAgICAgICAoZXJyKSA9PiB7CiAgICAgICAgICBjb25zdCByZXN1bHQgPSB7CiAgICAgICAgICAgIHRhc2tJZDogZGF0YS50YXNrSWQsCiAgICAgICAgICAgIHR5cGU6ICdFUlJPUicsCiAgICAgICAgICAgIHJlc291cmNlSWQ6IGRhdGEucmVzb3VyY2VJZCwKICAgICAgICAgICAgdXJsOiBkYXRhLnVybCwKICAgICAgICAgIH07CiAgICAgICAgICBwb3N0TWVzc2FnZShyZXN1bHQpOwogICAgICAgIH0KICAgICAgKTsKICAgIH0gZWxzZSBpZiAoZGF0YS50eXBlID09ICd1bnBhY2snKSB7CiAgICAgIGNvbnN0IHsgYnVmZmVyIH0gPSBkYXRhOwoKICAgICAgaWYgKCF1bnBhY2tCcmlkZ2UpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3VucGFja0JyaWRnZSBub3QgZGV0ZWN0ZWQnKQogICAgICB9CiAgICAgIGlmICghdW5wYWNrKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bnBhY2sgbm90IGRldGVjdGVkJykKICAgICAgfQoKICAgICAgY29uc3QgZXh0cmFjdG9yID0gdW5wYWNrQnJpZGdlLmNyZWF0ZUV4dHJhY3RvckZyb21EYXRhKGJ1ZmZlcik7CiAgICAgIGNvbnN0IHVucGFja2VkID0gZXh0cmFjdG9yLmV4dHJhY3RBbGwoKTsKICAgICAgcmV0dXJuRGF0YShkYXRhLCB1bnBhY2tlZCwgcG9zdE1lc3NhZ2UpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gcmV0dXJuRGF0YShkYXRhLCB1bnBhY2tlZCwgcG9zdE1lc3NhZ2UpIHsKICAgIGNvbnN0IFtzdGF0ZSwgbGlzdF0gPSB1bnBhY2tlZDsKICAgIGlmIChzdGF0ZS5zdGF0ZSA9PSAnRkFJTCcpIHsKICAgICAgY29uc3QgcmVzdWx0ID0gewogICAgICAgIHRhc2tJZDogZGF0YS50YXNrSWQsCiAgICAgICAgdHlwZTogJ0VSUk9SJywKICAgICAgICByZWFzb246IHN0YXRlLnJlYXNvbiwKICAgICAgICBtc2c6IHN0YXRlLm1zZywKICAgICAgICByZXNvdXJjZUlkOiBkYXRhLnJlc291cmNlSWQsCiAgICAgICAgdXJsOiBkYXRhLnVybCwKICAgICAgfTsKICAgICAgcG9zdE1lc3NhZ2UocmVzdWx0KTsKICAgICAgcmV0dXJuCiAgICB9CiAgICBjb25zdCByZXN1bHQgPSB7CiAgICAgIHRhc2tJZDogZGF0YS50YXNrSWQsCiAgICAgIHR5cGU6ICdGSU5JU0hFRCcsCiAgICAgIHJlc291cmNlSWQ6IGRhdGEucmVzb3VyY2VJZCwKICAgICAgZW50cmllczoge30sCiAgICB9OwoKICAgIGNvbnN0IHRyYW5zZmVyYWJsZXMgPSBbXTsKICAgIGlmIChsaXN0ICYmIGxpc3QuZmlsZXMpIHsKICAgICAgZm9yIChjb25zdCBmaWxlIG9mIGxpc3QuZmlsZXMpIHsKICAgICAgICByZXN1bHQuZW50cmllc1tmaWxlLmZpbGVIZWFkZXIubmFtZV0gPSBmaWxlLmV4dHJhY3RbMV07CiAgICAgICAgdHJhbnNmZXJhYmxlcy5wdXNoKGZpbGUuZXh0cmFjdFsxXS5idWZmZXIpOwogICAgICB9CiAgICB9CiAgICBwb3N0TWVzc2FnZShyZXN1bHQsIHRyYW5zZmVyYWJsZXMpOwogIH0KCiAgZ2xvYmFsVGhpcy5vbm1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHsKICAgIGhhbmRsZU1lc3NhZ2UoZXZlbnQuZGF0YSwgc2VsZi5wb3N0TWVzc2FnZSk7CiAgfTsKCiAgLyoqCiAgICogV2hlbiB0aGUgV0FTTSBydW50aW1lIGhhcyBiZWVuIGluaXRpYWxpemVkIG9uIHRoZSB1bnBhY2suanMgbW9kdWxlLCBzZW5kIGEgbWVzc2FnZSBpbmRpY2F0aW5nCiAgICogdGhhdCB0aGUgbGlicmFyeSBpcyByZWFkeS4KICAgKi8KICAvLyA8IS0tIHByZXR0aWVyLWlnbm9yZS1lbmQgLS0+CgogIGV4cG9ydHMuaGFuZGxlTWVzc2FnZSA9IGhhbmRsZU1lc3NhZ2U7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7CgogIHJldHVybiBleHBvcnRzOwoKfSkoe30pOwoK",null,!1);class ArchiveUnpackerMainThread{constructor(){const A=Buffer.from(unpackBase64Str,"base64");WebAssembly.compile(A).then((A=>{console.log("WebAssembly.compile",A)})),handleMessage$1({type:"init",buffer:A},(()=>{}))}addTask(A,g){return new Promise((g=>{handleMessage$1(A,(A=>{g(A)}))}))}terminate(){}}class ArchiveUnpackerWorkerPool extends WorkerPool{uint8Array;constructor(){super(!0),this.uint8Array=Uint8Array.from(atob(unpackBase64Str),(A=>A.charCodeAt(0)))}constructWorker(){return new Promise((A=>{const g=new WorkerFactory$2;g.onmessage=I=>{"WASM_LOADED"==I.data.type&&A(g)},g.postMessage({type:"init",buffer:this.uint8Array.buffer})}))}}let archiveUnpackerWorkerPool;archiveUnpackerWorkerPool="Node"==SystemDesc.OS?new ArchiveUnpackerMainThread:new ArchiveUnpackerWorkerPool;class ArchiveUnpackerPlugin extends ResourceLoaderPlugin{getType(){return"archive"}async loadFile(A){try{const g=await fetch(A);if(!g?.ok)throw new Error(`ArchiveUnpackerPlugin.loadFile: ${g.status} - ${g.statusText} : ${A}`);const I=await g.arrayBuffer();if(!I)throw new Error("Buffer is null");return await this.extractFile(I)}catch(A){throw A}}async extractFile(A){return new Promise(((g,I)=>{const C=A.byteLength;archiveUnpackerWorkerPool.addTask({type:"unpack",resourceId:C,buffer:A},[A]).then((A=>{"FINISHED"===A.type?g(A.entries):"ERROR"===A.type&&I(new Error(`Unable to open archive. The file may be corrupt: ${C}`))}))}))}}class JsonLoaderPlugin extends ResourceLoaderPlugin{getType(){return"json"}async loadFile(A){try{const g=await fetch(A);if(!g?.ok)throw new Error(`JsonLoaderPlugin.loadFile: ${g.status} - ${g.statusText} : ${A}`);return await g.json()}catch(A){throw A}}}class TextLoaderPlugin extends ResourceLoaderPlugin{getType(){return"text"}async loadFile(A){try{const g=await fetch(A);if(!g?.ok)throw new Error(`TextLoaderPlugin.loadFile: ${g.status} - ${g.statusText} : ${A}`);return await g.text()}catch(A){throw A}}}class BinaryLoaderPlugin extends ResourceLoaderPlugin{getType(){return"binary"}async loadFile(A){try{const g=await fetch(A);if(!g?.ok)throw new Error(`BinaryLoaderPlugin.loadFile: ${g.status} - ${g.statusText} : ${A}`);return await g.arrayBuffer()}catch(A){throw A}}}const MAX_LOAD_COUNT=1e3;class ResourceLoader extends EventEmitter{totalWork=0;doneWork=0;baseUrl="";plugins={};systemUrls={};commonResources={};loadCount=0;queue=[];cache;constructor(){super();const A="https://storage.googleapis.com/zea-engine-resources";this.systemUrls["ZeaEngine/Vive.vla"]=A+"/Vive.vla",this.systemUrls["ZeaEngine/Oculus.vla"]=A+"/Oculus.vla"}registerPlugin(A){this.plugins[A.getType()]=A}async loadFile(A,g,I=!0){const C=this.plugins[A];if(!C)throw new Error(`There's no plugin registered for the type of file "${A}". Did you add the plugins script? See: https://docs.zea.live/zea-engine/#/adding-default-plugins`);if(I&&this.incrementWorkload(),this.cache){const A=await this.cache.get(g);if(A)return I&&this.incrementWorkDone(),A}if(!(this.loadCount<1e3)){return new Promise(((A,e)=>{this.queue.push((()=>{this.loadCount++;C.loadFile(g).then((C=>{for(this.loadCount--,I&&this.incrementWorkDone(),this.emit("loaded",{url:g});this.loadCount<1e3&&this.queue.length>0;){this.queue.pop()()}A(C)}),(A=>{I&&this.incrementWorkDone(),e(A)}))}))}))}this.loadCount++;try{const A=C.loadFile(g);return A.then((A=>{for(this.cache&&this.cache.set(g,A),this.loadCount--,I&&this.incrementWorkDone(),this.emit("loaded",{url:g});this.loadCount<1e3&&this.queue.length>0;){this.queue.pop()()}}),(()=>{I&&this.incrementWorkDone()})),A}catch(A){throw I&&this.incrementWorkDone(),A}}getCommonResource(A){return this.commonResources[A]}setCommonResource(A,g){this.commonResources[A]=g}resetProgress(){this.totalWork=0,this.doneWork=0}incrementWorkload(A=1){this.totalWork+=A;const g=this.doneWork/this.totalWork*100;this.emit("progressIncremented",new ProgressEvent(g))}incrementWorkDone(A=1){this.doneWork+=A;const g=this.doneWork/this.totalWork*100;this.emit("progressIncremented",new ProgressEvent(g)),this.doneWork>this.totalWork&&console.warn("Mismatch between work loaded and work done.")}}const resourceLoader=new ResourceLoader,archiveUnpackerPlugin=new ArchiveUnpackerPlugin;resourceLoader.registerPlugin(archiveUnpackerPlugin);const jsonLoaderPlugin=new JsonLoaderPlugin;resourceLoader.registerPlugin(jsonLoaderPlugin);const textLoaderPlugin=new TextLoaderPlugin;resourceLoader.registerPlugin(textLoaderPlugin);const binaryLoaderPlugin=new BinaryLoaderPlugin;resourceLoader.registerPlugin(binaryLoaderPlugin);class IndexDBCache{name;objStoreName;version;db;constructor(A,g,I){this.name=A,this.objStoreName=g,this.version=I}async init(){return new Promise((A=>{const g=globalThis.indexedDB.open(this.name,this.version);g.onerror=()=>{console.error("IndexedDB Failed")},g.onsuccess=()=>{this.db=g.result,A()},g.onupgradeneeded=A=>{this.db=g.result,A.oldVersion&&A.oldVersion!=A.newVersion&&this.db.deleteObjectStore(this.objStoreName),this.db.createObjectStore(this.objStoreName,{keyPath:"key"})}}))}get(A){return new Promise(((g,I)=>{const C=this.db.transaction(this.objStoreName,"readonly").objectStore(this.objStoreName).get(A);C.onerror=A=>{I(A)},C.onsuccess=()=>{C.result?g(C.result.value):g(null)}}))}set(A,g){return new Promise(((I,C)=>{const e=this.db.transaction(this.objStoreName,"readwrite").objectStore(this.objStoreName).put({key:A,value:g});e.onsuccess=()=>{I()},e.onerror=A=>{C(A)}}))}}class Version{major=0;minor=0;patch=0;branch="";constructor(A){if("string"==typeof A){const g=A.split("-"),I=g[0].split(".");this.major=parseInt(I[0]),this.minor=I.length>1?parseInt(I[1]):0,this.patch=I.length>2?parseInt(I[2]):0,2==g.length&&(this.branch=g[1])}else if(Array.isArray(A)){const g=A;this.major=g[0],this.minor=g.length>1?g[1]:0,this.patch=g.length>2?g[2]:0}}compare(A){const g=[this.major,this.minor,this.patch];for(let I=0;I<3;I++)if(g[I]!==A[I])return g[I]-A[I];return 0}asArray(){return[this.major,this.minor,this.patch]}toString(){return`v${this.major}.${this.minor}.${this.patch}`+(""!=this.branch?`-${this.branch}`:"")}}class BinReader{__data;__byteOffset;__dataView;__isMobileDevice;utf8decoder;constructor(A,g=0,I=!0){this.__data=A,this.__byteOffset=g,this.__dataView=new DataView(this.__data),this.__isMobileDevice=I,this.utf8decoder=new TextDecoder}get isMobileDevice(){return this.__isMobileDevice}get data(){return this.__data}get byteLength(){return this.__dataView.byteLength}get remainingByteLength(){return this.__dataView.byteLength-this.__byteOffset}pos(){return this.__byteOffset}seek(A){this.__byteOffset=A}advance(A){this.__byteOffset+=A}loadUInt8(){const A=this.__dataView.getUint8(this.__byteOffset);return this.__byteOffset+=1,A}loadUInt16(){const A=this.__dataView.getUint16(this.__byteOffset,!0);return this.__byteOffset+=2,A}loadUInt32(){const A=this.__dataView.getUint32(this.__byteOffset,!0);return this.__byteOffset+=4,A}loadSInt32(){const A=this.__dataView.getInt32(this.__byteOffset,!0);return this.__byteOffset+=4,A}loadFloat16(){const A=this.loadUInt16();return MathFunctions.decode16BitFloat(A)}loadUFloat16(){const A=this.loadFloat16();return A<0?2048-A:A}loadFloat16From2xUInt8(){throw Error("loadFloat16From2xUInt8 not implemented!")}loadUInt32From2xUFloat16(){return this.loadUFloat16()+4096*this.loadUFloat16()}loadSInt32From2xFloat16(){return this.loadFloat16()+2048*this.loadFloat16()}loadFloat32(){const A=this.__dataView.getFloat32(this.__byteOffset,!0);return this.__byteOffset+=4,A}loadInt8Array(A,g=!0){let I;return null==A&&(A=this.loadUInt32()),g?(I=new Int8Array(this.__data.slice(this.__byteOffset,this.__byteOffset+A)),I.length!=A&&console.log("broken")):I=new Int8Array(this.__data,this.__byteOffset,A),this.__byteOffset+=A,I}loadUInt8Array(A,g=!0){let I;return null==A&&(A=this.loadUInt32()),g?(I=new Uint8Array(this.__data.slice(this.__byteOffset,this.__byteOffset+A)),I.length!=A&&console.log("broken")):I=new Uint8Array(this.__data,this.__byteOffset,A),this.__byteOffset+=A,I}loadUInt16Array(A,g=!0){if(null==A&&(A=this.loadUInt32()),0==A)return new Uint16Array;let I;if(this.readPad(2),this.__isMobileDevice){I=new Uint16Array(A);for(let g=0;g<A;g++)I[g]=this.__dataView.getUint16(this.__byteOffset,!0),this.__byteOffset+=2}else g?(I=new Uint16Array(this.__data.slice(this.__byteOffset,this.__byteOffset+2*A)),I.length!=A&&console.log("broken")):I=new Uint16Array(this.__data,this.__byteOffset,A),this.__byteOffset+=2*A;return I}loadUInt32Array(A,g=!0){if(null==A&&(A=this.loadUInt32()),0==A)return new Uint32Array;let I;if(this.readPad(4),this.__isMobileDevice){I=new Uint32Array(A);for(let g=0;g<A;g++)I[g]=this.__dataView.getUint32(this.__byteOffset,!0),this.__byteOffset+=4}else g?(I=new Uint32Array(this.__data.slice(this.__byteOffset,this.__byteOffset+4*A)),I.length!=A&&console.log("broken")):I=new Uint32Array(this.__data,this.__byteOffset,A),this.__byteOffset+=4*A;return I}loadFloat32Array(A,g=!0){if(null==A&&(A=this.loadUInt32()),0==A)return new Float32Array;let I;if(this.readPad(4),this.__isMobileDevice){I=new Float32Array(A);for(let g=0;g<A;g++)I[g]=this.__dataView.getFloat32(this.__byteOffset,!0),this.__byteOffset+=4}else I=g?new Float32Array(this.__data.slice(this.__byteOffset,this.__byteOffset+4*A)):new Float32Array(this.__data,this.__byteOffset,A),this.__byteOffset+=4*A;return I}loadStr(){const A=this.loadUInt32(),g=new Uint8Array(this.__data,this.__byteOffset,A);return this.__byteOffset+=A,this.utf8decoder.decode(g)}loadStrArray(){const A=this.loadUInt32(),g=[];for(let I=0;I<A;I++)g[I]=this.loadStr();return g}loadSInt32Vec2(){const A=this.loadSInt32(),g=this.loadSInt32();return new Vec2(A,g)}loadUInt32Vec2(){const A=this.loadUInt32(),g=this.loadUInt32();return new Vec2(A,g)}loadFloat16Vec2(){const A=this.loadFloat16(),g=this.loadFloat16();return new Vec2(A,g)}loadFloat32Vec2(){const A=this.loadFloat32(),g=this.loadFloat32();return new Vec2(A,g)}loadFloat16Vec3(){const A=this.loadFloat16(),g=this.loadFloat16(),I=this.loadFloat16();return new Vec3(A,g,I)}loadFloat32Vec3(){const A=this.loadFloat32(),g=this.loadFloat32(),I=this.loadFloat32();return new Vec3(A,g,I)}loadFloat16Quat(){const A=this.loadFloat16(),g=this.loadFloat16(),I=this.loadFloat16(),C=this.loadFloat16();return new Quat(A,g,I,C)}loadFloat32Quat(){const A=this.loadFloat32(),g=this.loadFloat32(),I=this.loadFloat32(),C=this.loadFloat32();return new Quat(A,g,I,C)}loadRGBFloat32Color(){const A=this.loadFloat32(),g=this.loadFloat32(),I=this.loadFloat32();return new Color(A,g,I)}loadRGBAFloat32Color(){const A=this.loadFloat32(),g=this.loadFloat32(),I=this.loadFloat32(),C=this.loadFloat32();return new Color(A,g,I,C)}loadRGBUInt8Color(){const A=this.loadUInt8(),g=this.loadUInt8(),I=this.loadUInt8();return new Color(A/255,g/255,I/255)}loadRGBAUInt8Color(){const A=this.loadUInt8(),g=this.loadUInt8(),I=this.loadUInt8(),C=this.loadUInt8();return new Color(A/255,g/255,I/255,C/255)}loadBox2(){return new Box2(this.loadFloat32Vec2(),this.loadFloat32Vec2())}loadBox3(){return new Box3(this.loadFloat32Vec3(),this.loadFloat32Vec3())}readPad(A){const g=this.__byteOffset%A;0!=g&&(this.__byteOffset+=A-g)}}class BinWriter{__data;__byteOffset;__reserved;__dataView;constructor(A=0){this.__data=new ArrayBuffer(A),this.__byteOffset=0,this.__reserved=A,this.__dataView=new DataView(this.__data)}pos(){return this.__byteOffset}seek(A){this.__byteOffset=A}seekEnd(){this.__byteOffset=this.__reserved}getBuffer(){if(this.__data.byteLength==this.__byteOffset)return this.__data;return new Uint8Array(this.__data).slice(0,this.__byteOffset).buffer}__grow(){const A=2*(this.__reserved>0?this.__reserved:1),g=new ArrayBuffer(A),I=new Uint8Array(g),C=new Uint8Array(this.__data);I.set(C),this.__data=g,this.__dataView=new DataView(this.__data),this.__reserved=A}__reserve(A){this.__byteOffset+A>this.__reserved&&this.__grow()}__offset(A){this.__byteOffset+=A,this.__byteOffset>this.__reserved&&this.__grow()}writeUInt8(A){this.__reserve(1),this.__dataView.setUint8(this.__byteOffset,A),this.__offset(1)}writeUInt16(A){this.__reserve(2),this.__dataView.setUint16(this.__byteOffset,A,!0),this.__offset(2)}writeUInt32(A){this.__reserve(4),this.__dataView.setUint32(this.__byteOffset,A,!0),this.__offset(4)}writeSInt32(A){this.__reserve(4),this.__dataView.setInt32(this.__byteOffset,A,!0),this.__offset(4)}writeFloat16(A){const g=MathFunctions.encode16BitFloat(A);this.writeUInt16(g)}writeFloat32(A){this.__reserve(4),this.__dataView.setFloat32(this.__byteOffset,A,!0),this.__offset(4)}writeUInt8Array(A,g=!0){const I=(A.length,A.length);this.__reserve(I+(g?4:0)),g&&this.writeUInt32(I);for(let g=0;g<I;g++)this.writeUInt8(A[g])}writeUInt16Array(A,g=!0){const I=(A.length,A.length);this.__reserve(2*I+(g?4:0)),g&&this.writeUInt32(I);for(let g=0;g<I;g++)this.writeUInt16(A[g])}writeUInt32Array(A,g=!0){const I=(A.length,A.length);this.__reserve(4*I+(g?4:0)),g&&this.writeUInt32(I);for(let g=0;g<I;g++)this.writeUInt32(A[g])}writeFloat32Array(A,g=!0){const I=(A.length,A.length);this.__reserve(4*I+(g?4:0)),g&&this.writeUInt32(I);for(let g=0;g<I;g++)this.writeFloat32(A[g])}writeStr(A,g=!0){const I=A.length;this.__reserve(4*I+(g?4:0)),g&&this.writeUInt32(I);for(let g=0;g<I;g++)this.writeFloat32(A.charCodeAt(g))}writeSInt32Vec2(A){this.writeSInt32(A.x),this.writeSInt32(A.y)}writeUInt32Vec2(A){this.writeUInt32(A.x),this.writeUInt32(A.y)}writeFloat16Vec2(A){this.writeFloat16(A.x),this.writeFloat16(A.y)}writeFloat32Vec2(A){this.writeFloat32(A.x),this.writeFloat32(A.y)}writeFloat16Vec3(A){this.writeFloat16(A.x),this.writeFloat16(A.y),this.writeFloat16(A.z)}writeFloat32Vec3(A){this.writeFloat32(A.x),this.writeFloat32(A.y),this.writeFloat32(A.z)}writeFloat16Quat(A){this.writeFloat16(A.x),this.writeFloat16(A.y),this.writeFloat16(A.z),this.writeFloat16(A.w)}writeFloat32Quat(A){this.writeFloat32(A.x),this.writeFloat32(A.y),this.writeFloat32(A.z),this.writeFloat32(A.w)}writeRGBFloat32Color(A){this.writeFloat32(A.r),this.writeFloat32(A.g),this.writeFloat32(A.b)}writeRGBAFloat32Color(A){this.writeFloat32(A.r),this.writeFloat32(A.g),this.writeFloat32(A.b),this.writeFloat32(A.a)}writeRGBUInt8Color(A){this.writeUInt8(A.r),this.writeUInt8(A.g),this.writeUInt8(A.b)}writeRGBAUInt8Color(A){this.writeUInt8(A.r),this.writeUInt8(A.g),this.writeUInt8(A.b),this.writeUInt8(A.a)}writeBox2(A){this.writeFloat32Vec2(A.p0),this.writeFloat32Vec2(A.p1)}writeBox3(A){this.writeFloat32Vec3(A.p0),this.writeFloat32Vec3(A.p1)}writePadd(A){const g=A-this.__byteOffset;this.__reserve(g),this.__offset(g)}writeAlignment(A){const g=this.__byteOffset%A;0!=g&&(this.__reserve(A-g),this.__offset(A-g))}}class CloneContext{assetItem;constructor(){this.assetItem=null}}var OperatorOutputMode,ColorSpace;!function(A){A[A.OP_WRITE=0]="OP_WRITE",A[A.OP_READ_WRITE=1]="OP_READ_WRITE"}(OperatorOutputMode||(OperatorOutputMode={}));class Parameter extends BaseItem{#C;dirty=!1;boundInputs=[];boundOutputs=[];cleaning=!1;dirtyOpIndex=0;firstOP_WRITE=0;dataType;constructor(A="",g,I){super(A),this.#C=g,this.dataType=I}getDataType(){return this.dataType}bindOperatorInput(A){this.boundInputs.push(A)}unbindOperatorInput(A){const g=this.boundInputs.indexOf(A);this.boundInputs.splice(g,1)}bindOperatorOutput(A,g=-1){-1==g&&(g=this.boundOutputs.length),this.boundOutputs.splice(g,0,A);for(let A=g;A<this.boundOutputs.length;A++)this.boundOutputs[A].setParamBindIndex(A);return this.__findFirstOP_WRITE(),this.dirtyOpIndex=this.boundOutputs.length,this.setDirty(g),g}unbindOperatorOutput(A){const g=A.getParamBindIndex();this.boundOutputs.splice(g,1);for(let A=g;A<this.boundOutputs.length;A++)this.boundOutputs[A].setParamBindIndex(A);return this.__findFirstOP_WRITE(),this.dirtyOpIndex=this.boundOutputs.length,this.setDirty(Math.max(0,g-1)),g}__findFirstOP_WRITE(){if(this.firstOP_WRITE=this.boundOutputs.length,this.boundOutputs.length>0)for(this.firstOP_WRITE--;this.firstOP_WRITE>0&&this.boundOutputs[this.firstOP_WRITE].getMode()!=OperatorOutputMode.OP_WRITE;this.firstOP_WRITE--);}isDrivenByOperator(){return 0==this.firstOP_WRITE&&this.boundOutputs.length>0}setDirty(A){if(A<this.dirtyOpIndex){let g=this.firstOP_WRITE;if(g<=A){for(this.dirtyOpIndex=g,g++;g<this.boundOutputs.length;g++)g!=A&&this.boundOutputs[g].getOperator().setDirty();for(let A=0;A<this.boundInputs.length;A++)this.boundInputs[A].setDirty();return this.emit("valueChanged"),!0}}return!1}isDirty(){return this.dirtyOpIndex<this.boundOutputs.length}getDirtyBindingIndex(){return this.dirtyOpIndex}setCleanFromOp(A,g){if(g!=this.dirtyOpIndex)if(g<this.dirtyOpIndex)console.log("Parameter is cleaned when it was already clean to that point in the stack:",this.getPath());else if(this.boundOutputs[g].getMode()!=OperatorOutputMode.OP_WRITE){const A=this.getClassName(),I=this.boundOutputs[g].getOperator(),C=I.constructor.name;throw new Error(`Parameter: ${A} with name: ${this.getName()} is not cleaning all outputs during evaluation of op: ${C} with name: ${I.name}`)}this.#C=A,this.dirtyOpIndex=g+1}getValueFromOp(A){return this.dirtyOpIndex<A&&this._clean(A),this.#C}_clean(A){if(this.cleaning)throw new Error(`Cycle detected when cleaning: ${this.getPath()}. Operators need to be rebound to fix errors`);for(this.cleaning=!0;this.dirtyOpIndex<A;){const A=this.dirtyOpIndex;if(this.boundOutputs[this.dirtyOpIndex].getOperator().evaluate(),A==this.dirtyOpIndex){const A=this.boundOutputs[this.dirtyOpIndex].getOperator(),g=A.constructor.name;console.warn(`Operator: ${g} with name: ${A.name} is not cleaning its outputs during evaluation`),this.dirtyOpIndex++}}this.cleaning=!1}getValue(){return this.dirtyOpIndex<this.boundOutputs.length&&this._clean(this.boundOutputs.length),this.#C}setValue(A){if(void 0===A)throw"undefined was passed into the set value for param:"+this.getName();if(this.boundOutputs.length>0)for(let g=this.boundOutputs.length-1;g>=0;g--){const I=this.boundOutputs[g];if(A=I.backPropagateValue(A),0==I.getMode())return}if("object"==typeof A||this.#C!=A){this.#C=A;for(let A=0;A<this.boundInputs.length;A++)this.boundInputs[A].paramValueChanged();this.emit("valueChanged")}}get value(){return this.getValue()}set value(A){this.setValue(A)}loadValue(A){this.#C=A}copyFrom(A,g){this.loadValue(A.value)}readBinary(A,g){console.warn(`TODO: Parameter: ${this.constructor.name} with name: ${this.name} does not implement readBinary`)}getPath(){return this.ownerItem instanceof BaseItem?[...this.ownerItem.getPath(),this.name]:[this.name]}resolvePath(A,g=0){if(0==g&&("."!=A[0]&&A[0]!=this.name||g++),".."==A[g]){if(this.ownerItem)return this.ownerItem.resolvePath(A,g+1);throw Error("this.ownerItem is undefined")}if(g==A.length)return this;if("value"==A[g]&&this.#C instanceof BaseItem)return this.#C.resolvePath(A,g+1);throw new Error("Invalid path:"+A+"["+g+"]. Path does not resolve to a BaseItem")}destroy(){console.warn("nothing destroyed. This method was not overwritten in subclass")}}class NumberParameter extends Parameter{range;step;constructor(A="",g=0,I,C){super(A,g,"Number"),this.range=I,this.step=C}getRange(){return this.range}setRange(A){this.range=A}getStep(){return this.step}setStep(A){this.step=A}setValue(A){if("number"!=typeof A)throw new Error("value provided is not a number. Check the source of this value");super.setValue(A)}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value}}fromJSON(A,g){this.value=A.value}readBinary(A,g){this.value=A.loadFloat32()}clone(){return new NumberParameter(this.name,this.value,this.range,this.step)}}class Float32Parameter extends NumberParameter{readBinary(A,g){this.value=A.loadFloat32()}}class SInt32Parameter extends NumberParameter{readBinary(A,g){this.value=A.loadSInt32()}}class UInt32Parameter extends NumberParameter{readBinary(A,g){this.value=A.loadUInt32()}}class AngleParameter extends Float32Parameter{}Registry.register("NumberParameter",NumberParameter),Registry.register("Property_SInt32",SInt32Parameter),Registry.register("Property_UInt32",UInt32Parameter),Registry.register("Property_Float32",Float32Parameter),Registry.register("AngleParameter",AngleParameter);class MultiChoiceParameter extends NumberParameter{choices;constructor(A,g,I=[]){super(A,g,[0,I.length],1),this.choices=I}getChoices(){return this.choices}setValue(A){if("string"==typeof A){const g=this.choices.indexOf(A);-1===g?console.error(`Invalid value for MultiChoiceParameter: ${A}. choices are: ${this.choices}.`):super.setValue(g)}else super.setValue(A)}clone(){return new MultiChoiceParameter(this.name,this.value,this.choices)}}Registry.register("MultiChoiceParameter",MultiChoiceParameter);class BooleanParameter extends Parameter{constructor(A="",g){super(A,null!=g&&g,"Boolean")}setValue(A){if("boolean"!=typeof A)throw new Error("value provided is not a boolean. Check the source of this value");super.setValue(A)}readBinary(A,g){this.value=0!=A.loadUInt8()}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value}}fromJSON(A,g){this.value=A.value}clone(){return new BooleanParameter(this.name,this.value)}}Registry.register("BooleanParameter",BooleanParameter),Registry.register("Property_Boolean",BooleanParameter);class Vec2Parameter extends Parameter{range;constructor(A="",g,I){super(A,g||new Vec2,"Vec2"),this.range=I}getRange(){return this.range}setRange(A){this.range=A,this.emit("rangeChanged",{range:A})}setValue(A){if(!(A instanceof Vec2))throw new Error("value provided is not an instance of a 'Vec2' class. Check the source of this value");super.setValue(A)}readBinary(A,g){this.value?.readBinary(A)}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value?.toJSON()}}fromJSON(A,g){const I=new Vec2;I.fromJSON(A.value),this.value=I,A.name&&(this.name=A.name)}clone(){const A=new Vec2Parameter(this.name,this.value?.clone());return this.range&&A.setRange(this.range),A}}Registry.register("Vec2Parameter",Vec2Parameter),Registry.register("Property_Vec2_32f",Vec2Parameter);class Vec3Parameter extends Parameter{range;constructor(A="",g,I){super(A,g||new Vec3,"Vec3"),this.range=I}setValue(A){if(!(A instanceof Vec3))throw new Error("value provided is not an instance of a 'Vec2' class. Check the source of this value");super.setValue(A)}readBinary(A,g){this.value?.readBinary(A)}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value?.toJSON()}}fromJSON(A,g){const I=new Vec3;I.fromJSON(A.value),this.value=I,A.name&&(this.name=A.name)}clone(){return new Vec3Parameter(this.name,this.value?.clone())}}Registry.register("Vec3Parameter",Vec3Parameter),Registry.register("Property_Vec3_32f",Vec3Parameter);class Vec4Parameter extends Parameter{constructor(A="",g){super(A,g||new Vec4,"Vec4")}setValue(A){if(!(A instanceof Vec4))throw new Error("value provided is not an instance of a 'Vec4' class. Check the source of this value");super.setValue(A)}readBinary(A,g){this.value?.readBinary(A)}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value?.toJSON()}}fromJSON(A,g){const I=new Vec4;I.fromJSON(A.value),this.value=I,A.name&&(this.name=A.name)}clone(){return new Vec4Parameter(this.name,this.value?.clone())}}Registry.register("Vec4Parameter",Vec4Parameter),Registry.register("Property_Vec4_32f",Vec4Parameter);class Box2Parameter extends Parameter{constructor(A="",g){super(A,g||new Box2,"Box2")}setValue(A){if(!(A instanceof Box2))throw new Error("value provided is not an instance of a 'Box2' class. Check the source of this value");super.setValue(A)}readBinary(A,g){this.value.p0.readBinary(A),this.value.p1.readBinary(A)}toJSON(A){return{type:this.getClassName(),name:this.name,value:{p0:this.value.p0.toJSON(),p1:this.value.p1.toJSON()}}}fromJSON(A,g){this.value.p0.fromJSON(A.p0),this.value.p1.fromJSON(A.p1)}clone(){return new Box2Parameter(this.name,this.value?.clone())}}Registry.register("Box2Parameter",Box2Parameter),Registry.register("Property_Box2_32f",Box2Parameter);class Box3Parameter extends Parameter{constructor(A="",g){super(A,g||new Box3,"Box3")}setValue(A){if(!(A instanceof Box3))throw new Error("value provided is not an instance of a 'Box3' class. Check the source of this value");super.setValue(A)}readBinary(A,g){this.value.p0.readBinary(A),this.value.p1.readBinary(A)}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value.toJSON()}}fromJSON(A,g){A.value&&this.value.fromJSON(A.value)}clone(){return new Box3Parameter(this.name,this.value?.clone())}}Registry.register("Box3Parameter",Box3Parameter),Registry.register("Property_Box3_32f",Box3Parameter);class ColorParameter extends Parameter{constructor(A="",g){super(A,g||new Color,"Color")}setValue(A){if(!(A instanceof Color))throw new Error("value provided is not an instance of a 'Color' class. Check the source of this value");super.setValue(A)}readBinary(A,g){const I=A.loadRGBAFloat32Color();I.applyGamma(2.2),this.value=I}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value?.toJSON()}}fromJSON(A,g){this.value?.fromJSON(A.value)}clone(){return new ColorParameter(this.name,this.value?.clone())}}Registry.register("ColorParameter",ColorParameter),Registry.register("Property_Color_32f",ColorParameter);class QuatParameter extends Parameter{constructor(A="",g){super(A,g||new Quat,"Quat")}setValue(A){if(!(A instanceof Quat))throw new Error("value provided is not an instance of a 'Quat' class. Check the source of this value");super.setValue(A)}readBinary(A,g){this.value?.readBinary(A)}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value?.toJSON()}}fromJSON(A,g){const I=new Quat;I.fromJSON(A.value),this.value=I}clone(){return new QuatParameter(this.name,this.value?.clone())}}Registry.register("QuatParameter",QuatParameter),Registry.register("Property_Quat_32f",QuatParameter);class Mat3Parameter extends Parameter{constructor(A="",g){super(A,g||new Mat3,"Mat3")}setValue(A){if(!(A instanceof Mat3))throw new Error("value provided is not an instance of a 'Mat3' class. Check the source of this value");super.setValue(A)}readBinary(A,g){this.value?.readBinary(A)}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value?.toJSON()}}fromJSON(A,g){const I=new Mat3;I.fromJSON(A.value),this.value=I}clone(){return new Mat3Parameter(this.name,this.value?.clone())}}Registry.register("Mat3Parameter",Mat3Parameter),Registry.register("Property_Mat3_32f",Mat3Parameter);class Mat4Parameter extends Parameter{constructor(A="",g){super(A,g||new Mat4,"Mat4")}setValue(A){if(!(A instanceof Mat4))throw new Error("value provided is not an instance of a 'Mat4' class. Check the source of this value");super.setValue(A)}readBinary(A,g){this.value?.readBinary(A)}toJSON(A){return{type:this.getClassName(),value:this.value?.toJSON()}}fromJSON(A,g){const I=new Mat4;I.fromJSON(A.value),this.value=I}clone(){return new Mat4Parameter(this.name,this.value?.clone())}}Registry.register("Mat4Parameter",Mat4Parameter),Registry.register("Property_Mat4_32f",Mat4Parameter);class XfoParameter extends Parameter{constructor(A="",g){super(A,g||new Xfo,"Xfo")}setValue(A){if(!(A instanceof Xfo))throw new Error("value provided is not an instance of a 'Xfo' class. Check the source of this value");super.setValue(A)}readBinary(A,g){this.value.readBinary(A)}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value.toJSON()}}fromJSON(A,g){const I=new Xfo;I.fromJSON(A.value),this.value=I,A.name&&(this.name=A.name)}clone(){return new XfoParameter(this.name,this.value.clone())}}Registry.register("XfoParameter",XfoParameter),Registry.register("Property_Xfo_32f",XfoParameter);class BaseImage extends ParameterOwner{width=0;height=0;format="RGB";type="UNSIGNED_BYTE";loaded=!1;mipMapped=!0;wrapS="REPEAT";wrapT="REPEAT";minFilter="LINEAR";magFilter="LINEAR";constructor(A="Image"){super(A),this.on("parameterValueChanged",(()=>{this.emit("updated")}))}isLoaded(){return this.loaded}getParams(){return{type:this.type,format:this.format,width:this.width,height:this.height,wrapS:this.wrapS,wrapT:this.wrapT,minFilter:this.minFilter,magFilter:this.magFilter,mipMapped:this.mipMapped}}}class ImageParameter extends Parameter{constructor(A="",g){super(A,g,"BaseImage")}setValue(A){if(!(A instanceof BaseImage))throw new Error("value provided is not an instance of 'BaseImage' class. Check the source of this value");super.setValue(A)}toJSON(A){const g={type:this.getClassName(),name:this.name};return this.value&&(g.imageType=this.value.getClassName(),g.value=this.value.toJSON()),g}fromJSON(A,g){A.imageType&&(this.value=Registry.constructClass(A.imageType),A.value&&this.value?.fromJSON(A.value,g))}clone(){return new ImageParameter(this.name,this.value)}}Registry.register("ImageParameter",ImageParameter);class StringParameter extends Parameter{multiLine;constructor(A="",g=""){super(A,g,"String"),this.multiLine=!1}setMultiLine(A){this.multiLine=A}getMultiLine(){return this.multiLine}setValue(A){if("string"!=typeof A)throw new Error("value provided is not a string. Check the source of this value");super.setValue(A)}readBinary(A,g){this.value=A.loadStr()}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value}}fromJSON(A,g){const I=A.value??"";this.value!=I&&(this.value=I)}clone(){return new StringParameter(this.name,this.value)}}Registry.register("StringParameter",StringParameter),Registry.register("Property_String",StringParameter);class StringListParameter extends Parameter{constructor(A="",g=[]){super(A,g,"String[]")}setValue(A){if(!Array.isArray(A))throw new Error("value provided is not an array. Check the source of this value");super.setValue(A)}readBinary(A,g){this.value=A.loadStrArray()}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value}}fromJSON(A,g){this.value=A.value}clone(){return new StringListParameter(this.name,this.value)}}Registry.register("StringListParameter",StringListParameter),Registry.register("Property_StringList",StringListParameter);class Float32ArrayParameter extends Parameter{constructor(A="",g=new Float32Array){super(A,g,"Float[]")}readBinary(A,g){this.value=A.loadFloat32Array()}toJSON(A){return{type:this.getClassName(),name:this.name,value:this.value}}fromJSON(A,g){this.value=A.value}clone(){return new Float32ArrayParameter(this.name,this.value)}}Registry.register("Float32ArrayParameter",Float32ArrayParameter),Registry.register("Property_Float32Array",Float32ArrayParameter);class ListParameter extends Parameter{constructor(A="",g){super(A,[],g)}filter(A){return!0}getCount(){return this.value?.length||0}getElement(A){if(this.value)return this.value[A]}setElement(A,g){this.value||(this.value=[]),this.value[A]=g,this.emit("valueChanged")}addElement(A){if((A||0==A)&&this.filter(A))return this.value||(this.value=[]),this.value.push(A),this.emit("elementAdded",{elem:A,index:this.value.length-1}),this.emit("valueChanged"),A}removeElement(A){this.value||(this.value=[]);const g=this.value[A];this.value.splice(A,1),this.emit("elementRemoved",{elem:g,index:A}),this.emit("valueChanged")}insertElement(A,g){this.value&&this.filter(g)&&(this.value.splice(A,0,g),this.emit("elementAdded",{elem:g,index:A}),this.emit("valueChanged"))}setValue(A){if(!Array.isArray(A))throw new Error("value provided is not an array. Check the source of this value");super.setValue(A)}toJSON(A){const g=[];if(this.value)for(const I of this.value)"string"==typeof this.dataType?g.push(I):g.push(I.toJSON(A));return{type:this.getClassName(),name:this.name,value:g}}fromJSON(A,g){if(null==A.items)return void console.warn("Invalid Parameter JSON");const I=[];for(let C=0;C<A.items.length;C++){let e;if("string"==typeof this.dataType)e=A.items[C];else{if(!this.dataType)throw"No DataType";e=Registry.constructClass(this.dataType),e.fromJSON(A.items[C],g)}I.push(e),this.emit("elementAdded",{elem:e,index:this.value.length-1})}this.value=I}clone(){const A=this.value?this.value.slice(0):[];if(!this.dataType)throw"This parameter does not have a DataType";const g=new ListParameter(this.name,this.dataType);return g.setValue(A),g}destroy(){if(this.value)for(let A=0;A<this.value.length;A++)this.value[A]instanceof Parameter&&this.value[A].destroy(),this.removeElement(A)}}Registry.register("ListParameter",ListParameter);class StructParameter extends Parameter{members;constructor(A){super(A,{},"Struct"),this.members=[]}addMember(A){return this.value&&(this.value[A.getName()]=A.value),A.on("valueChanged",(()=>{this.value&&(this.value[A.getName()]=A.value)})),this.members.push(A),this.emit("valueChanged"),A}getParameter(A){for(const g of this.members)if(g.getName()==A)return g}getMember(A){return this.getParameter(A)}getMemberNames(){const A=[];for(let g=0;g<this.members.length;g++){const I=this.members[g];null!=I&&(A[g]=I.getName())}return A}toJSON(A){const g=[];for(const I of this.members)g.push(I.toJSON(A));return{type:this.getClassName(),name:this.name,members:g}}fromJSON(A,g){if(null!=A.members){for(let I=0;I<A.members.length;I++)A.members[I]&&this.members[I].fromJSON(A.members[I],g);this.name=A.name}else console.warn("Invalid Parameter JSON")}clone(){return new StructParameter(this.name)}destroy(){for(const A of this.members)A.destroy()}}Registry.register("StructParameter",StructParameter);class OperatorOutput{name;mode;op=null;param;paramBindIndex;detached;constructor(A,g=OperatorOutputMode.OP_WRITE){this.name=A,this.mode=g,this.param=void 0,this.paramBindIndex=-1,this.detached=!1}setOperator(A){this.op=A}getOperator(){return this.op}getMode(){return this.mode}isConnected(){return null!=this.param}getParam(){return this.param}setParam(A,g=-1){this.param&&this.param.unbindOperatorOutput(this),this.param=A,this.param&&(this.paramBindIndex=this.param.bindOperatorOutput(this,g))}getParamBindIndex(){return this.paramBindIndex}setParamBindIndex(A){this.paramBindIndex=A}setDirty(){this.param&&this.param.setDirty(this.paramBindIndex)}getValue(){if(this.param)return this.param.getValueFromOp(this.paramBindIndex);throw new Error("Cannot call getValue on OperatorOutput that is not connected:",this.name)}backPropagateValue(A){return this.op&&(A=this.op.backPropagateValue(A)),A}setClean(A){this.param&&this.param.setCleanFromOp(A,this.paramBindIndex)}toJSON(A){const g=this.param?this.param.getPath():"";return{name:this.name,paramPath:A&&A.makeRelative?A.makeRelative(g):g,paramBindIndex:this.paramBindIndex}}fromJSON(A,g){A.paramPath&&g?.resolvePath(A.paramPath,(g=>{this.setParam(g,A.paramBindIndex)}),(g=>{console.warn("OperatorOutput: '"+this.name+"'. Unable to connect to:"+A.paramPath)}))}detach(){this.detached=!0,this.paramBindIndex=this.param?this.param.unbindOperatorOutput(this):-1}reattach(){this.detached=!1,this.param&&(this.paramBindIndex=this.param.bindOperatorOutput(this,this.paramBindIndex))}rebind(){this.param&&(this.param.unbindOperatorOutput(this),this.paramBindIndex=this.param.bindOperatorOutput(this))}}class BooleanOperatorOutput extends OperatorOutput{}class NumberOperatorOutput extends OperatorOutput{}class Vec2OperatorOutput extends OperatorOutput{}class Vec3OperatorOutput extends OperatorOutput{}class Vec4OperatorOutput extends OperatorOutput{}class ColorOperatorOutput extends OperatorOutput{}class QuatOperatorOutput extends OperatorOutput{}class XfoOperatorOutput extends OperatorOutput{}class Mat3OperatorOutput extends OperatorOutput{}class Mat4OperatorOutput extends OperatorOutput{}class Operator{name;inputs;outputs;constructor(A=""){this.name=A,this.inputs=new Map,this.outputs=new Map}setDirty(){this.outputs.forEach((A=>A.setDirty()))}addInput(A){return A.setOperator(this),this.inputs.set(A.name,A),this.setDirty(),A}removeInput(A){"string"==typeof A&&(A=this.getInput(A)),A.getParam()&&A.setParam(void 0),this.inputs.delete(A.name)}getNumInputs(){return this.inputs.size}getInputByIndex(A){return Array.from(this.inputs.values())[A]}getInput(A){const g=this.inputs.get(A);if(!g)throw`Couldn't find an Input with the name of '${A}'`;return g}addOutput(A){return A.setOperator(this),this.outputs.set(A.name,A),this.setDirty(),A}removeOutput(A){if("string"==typeof A&&(A=this.getOutput(A)),!(A instanceof OperatorOutput))throw new Error("removeOutput only accepts string or OperatorInput");A.getParam()&&A.setParam(),this.outputs.delete(A.name)}getNumOutputs(){return this.outputs.size}getOutputByIndex(A){return Array.from(this.outputs.values())[A]}getOutput(A){const g=this.outputs.get(A);if(!g)throw new Error(`Couldn't find an Output with the name of '${A}'`);return g}evaluate(){throw new Error("Not yet implemented")}backPropagateValue(A){return A}detach(){this.inputs.forEach((A=>A.detach())),this.outputs.forEach((A=>A.detach()))}reattach(){this.inputs.forEach((A=>A.reattach())),this.outputs.forEach((A=>A.reattach()))}rebind(){this.outputs.forEach((A=>A.rebind()))}}class OperatorInput{name;op;param;detached=!1;constructor(A){this.name=A}setOperator(A){this.op=A}getOperator(){return this.op}isConnected(){return null!=this.param}getParam(){return this.param}paramValueChanged(){this.op&&this.op.setDirty()}setParam(A){this.param&&this.param.unbindOperatorInput(this),this.param=A,this.param&&this.param.bindOperatorInput(this),this.op&&this.op.setDirty()}getValue(){if(this.param)return this.param.value;throw new Error("Unable to getValue")}setValue(A){this.param&&this.param.setValue(A)}setDirty(){this.op&&this.op.setDirty()}toJSON(A){const g=this.param?this.param.getPath():[],I=A&&A.makeRelative?A.makeRelative(g):g;return{name:this.name,paramPath:I}}fromJSON(A,g){A.paramPath&&g?.resolvePath(A.paramPath,(A=>{this.setParam(A)}),(()=>{console.warn("OperatorInput: '"+this.name+"'. Unable to connect to:"+A.paramPath)}))}detach(){this.param&&this.param.unbindOperatorInput(this)}reattach(){this.detached=!1,this.param&&this.param.bindOperatorInput(this)}}class BooleanOperatorInput extends OperatorInput{}class NumberOperatorInput extends OperatorInput{}class Vec2OperatorInput extends OperatorInput{}class Vec3OperatorInput extends OperatorInput{}class Vec4OperatorInput extends OperatorInput{}class ColorOperatorInput extends OperatorInput{}class QuatOperatorInput extends OperatorInput{}class XfoOperatorInput extends OperatorInput{}class Mat3OperatorInput extends OperatorInput{}class Mat4OperatorInput extends OperatorInput{}class CalcGlobalXfoOperator extends Operator{parentGlobal=new XfoOperatorInput("ParentGlobal");localXfo=new XfoOperatorInput("LocalXfo");globalXfo=new XfoOperatorOutput("GlobalXfo");constructor(A,g){super("CalcGlobalXfoOperator"),this.localXfo.setParam(g),this.globalXfo.setParam(A),this.addInput(this.parentGlobal),this.addInput(this.localXfo),this.addOutput(this.globalXfo)}backPropagateValue(A){if(this.parentGlobal.isConnected()){const g=this.parentGlobal.getValue();this.localXfo.setValue(g.inverse().multiply(A))}else this.localXfo.setValue(A)}evaluate(){const A=this.localXfo.getValue();if(this.parentGlobal.isConnected()){const g=this.parentGlobal.getValue();this.globalXfo.setClean(g.multiply(A))}else this.globalXfo.setClean(A)}}class BoundingBoxParameter extends Box3Parameter{treeItem;dirty=!0;constructor(A="",g){super(A),this.treeItem=g}setDirty(A){return this.dirty||(this.dirty=!0,this.emit("valueChanged")),!0}getValue(){return this.dirty&&(this.value=this.treeItem.cleanBoundingBox(),this.dirty=!1),super.getValue()}clone(){const A=new BoundingBoxParameter(this.name,this.treeItem);return A.value=this.value?.clone(),A}isDrivenByOperator(){return!0}loadValue(A){this.value=A.clone()}}Registry.register("BoundingBoxParameter",BoundingBoxParameter);class TreeItem extends ParameterOwner{disableBoundingBox=!1;__childItems=[];__childItemsEventHandlers=[];childItemsMapping={};childItemsMappingCorrupt=!1;globalXfoParam=new XfoParameter("GlobalXfo",new Xfo);localXfoParam=new XfoParameter("LocalXfo",new Xfo);boundingBoxParam=new BoundingBoxParameter("BoundingBox",this);visibleParam=new BooleanParameter("Visible",!0);pickableParam=new BooleanParameter("Pickable",!0);opacityParam=new NumberParameter("Opacity",1,[0,1]);highlightMapping={};highlights=[];#e=!0;#i=!0;visibleCounter=1;pickableCounter=1;opacity=1;inheritedOpacityValues=new Map;globalXfoOp;constructor(A){super(A),this.addParameter(this.visibleParam),this.addParameter(this.pickableParam),this.addParameter(this.opacityParam),this.addParameter(this.localXfoParam),this.addParameter(this.globalXfoParam),this.addParameter(this.boundingBoxParam),this.globalXfoOp=new CalcGlobalXfoOperator(this.globalXfoParam,this.localXfoParam),this.globalXfoParam.on("valueChanged",(A=>{this.setBoundingBoxDirty(),this.emit("globalXfoChanged",A)})),this.visibleParam.on("valueChanged",(()=>{this.visibleCounter+=this.visibleParam.value?1:-1,this.updateVisibility()})),this.pickableParam.on("valueChanged",(()=>{this.pickableCounter+=this.pickableParam.value?1:-1,this.updatePickable()})),this.opacityParam.on("valueChanged",(()=>{this.updateOpacity()}))}setOwner(A){if(A&&!(A instanceof TreeItem))throw new Error("cannot setOwner");if(this.ownerItem&&this.ownerItem instanceof TreeItem){this.ownerItem.isVisible()||this.visibleCounter++,this.ownerItem.isPickable()||this.pickableCounter++;const A=this.ownerItem.getChildIndex(this);A>=0&&this.ownerItem.unbindChild(A,this)}super.setOwner(A),this.ownerItem?this.ownerItem instanceof TreeItem&&(this.ownerItem.isVisible()||this.visibleCounter--,this.ownerItem.isPickable()||this.pickableCounter--,this.globalXfoOp.getInput("ParentGlobal").setParam(this.ownerItem.globalXfoParam)):this.globalXfoOp.getInput("ParentGlobal").setParam(void 0),this.updateVisibility()}getParentItem(){return this.getOwner()}setParentItem(A){this.setOwner(A)}get parent(){return this.getOwner()}set parent(A){this.setOwner(A)}isVisible(){return this.visibleCounter>0}setVisible(A){this.visibleParam.value=A}propagateVisibility(A){this.visibleCounter+=A,this.updateVisibility()}updateVisibility(){const A=this.visibleCounter>0;if(A!=this.#e){this.#e=A;for(const A of this.__childItems)A.propagateVisibility(this.#e?1:-1);return this.emit("visibilityChanged",new StateChangedEvent(A)),this.ownerItem instanceof TreeItem&&this.ownerItem.setBoundingBoxDirty(),!0}return!1}isPickable(){return this.pickableCounter>0}propagatePickable(A){this.pickableCounter+=A,this.updatePickable()}updatePickable(){const A=this.pickableCounter>0;if(A!=this.#i){this.#i=A;for(const A of this.__childItems)A.propagatePickable(this.#i?1:-1);return this.emit("pickabilityChanged",new StateChangedEvent(A)),!0}return!1}isOpaque(){return this.opacity>.999}setInheritedOpacity(A,g){this.inheritedOpacityValues.set(A,g),this.updateOpacity()}updateOpacity(){let A=1;this.inheritedOpacityValues.forEach((g=>{g<A&&(A=g)}));const g=this.opacity>.999;this.opacity=this.opacityParam.value*A;for(const A of this.__childItems)A.setInheritedOpacity(this,this.opacity);const I=this.opacity>.999;this.emit("opacityChanged",new OpacityStateChangedEvent(I,g!=I))}addHighlight(A,g,I=!0){if(A in this.highlightMapping)if(this.highlights[this.highlights.length-1]!=A){const I=this.highlights.indexOf(A);this.highlights.splice(I,1),this.highlights.push(A),this.emit("highlightChanged",{name:A,color:g})}else this.highlightMapping[A].isEqual(g)||(this.highlightMapping[A]=g,this.emit("highlightChanged",{name:A,color:g}));else this.highlights.push(A),this.highlightMapping[A]=g,this.emit("highlightChanged",{name:A,color:g});I&&this.__childItems.forEach((C=>{C.addHighlight(A,g,I)}))}removeHighlight(A,g=!0){if(A in this.highlightMapping){if(this.highlights[this.highlights.length-1]==A)if(this.highlights.pop(),delete this.highlightMapping[A],this.highlights.length>0){const A=this.highlights[this.highlights.length-1],g=this.highlightMapping[A];this.emit("highlightChanged",{name:A,color:g})}else this.emit("highlightChanged");else{const g=this.highlights.indexOf(A);this.highlights.splice(g,1),delete this.highlightMapping[A]}g&&this.__childItems.forEach((I=>{I.removeHighlight(A,g)}))}}getHighlight(){return 0==this.highlights.length?null:this.highlightMapping[this.highlights[this.highlights.length-1]]}getHighlightName(){return 0==this.highlights.length?null:this.highlights[this.highlights.length-1]}isHighlighted(){return this.highlights.length>0}cleanBoundingBox(){const A=new Box3;return this.__childItems.forEach((g=>{if(g.isVisible()&&g.isPickable()){const I=g.boundingBoxParam.value;I&&A.addBox3(I)}})),A}setBoundingBoxDirty(){this.boundingBoxParam&&this.boundingBoxParam.setDirty(-1),this.ownerItem instanceof TreeItem&&this.ownerItem.setBoundingBoxDirty()}getChildren(){return this.__childItems}getNumChildren(){return this.__childItems.length}get numChildren(){return this.__childItems.length}generateUniqueName(A){for(;null!=this.childItemsMapping[A.toLocaleLowerCase()];){const g=/(\d+)$/i,I=A.match(g);let C=1;I&&(C=parseInt(I[1])+1,A=A.replace(g,"")),A+=`${C}`.padStart(2,"0")}return A}updateChildNameMapping(A){for(let g=A;g<this.__childItems.length;g++){const A=this.__childItems[g].name.toLocaleLowerCase();this.childItemsMapping[A]=g}}childNameChanged(A){if(this.childItemsMappingCorrupt)this.updateChildNameMapping(0),this.childItemsMappingCorrupt=!1;else{const g=A.oldName.toLocaleLowerCase(),I=A.newName.toLocaleLowerCase(),C=this.childItemsMapping[g];null!=this.childItemsMapping[I]&&(this.childItemsMappingCorrupt=!0),delete this.childItemsMapping[g],this.childItemsMapping[I]=C}}insertChild(A,g,I=!1,C=!0){let e=A.name,i=e.toLocaleLowerCase();if(i in this.childItemsMapping){if(!C)throw new Error("Item '"+e+"' is already a child of :"+this.getPath());e=this.generateUniqueName(e),i=e.toLocaleLowerCase(),A.setName(e)}if(!(A instanceof TreeItem))throw new Error("Object is is not a tree item :"+A);const t={};let o;return t.nameChanged=A.on("nameChanged",(A=>{this.childNameChanged(A)})),I&&(o=A.globalXfoParam.value),this.setBoundingBoxDirty(),this.highlights.forEach((g=>{A.addHighlight(g,this.highlightMapping[g],!0)})),A.setInheritedOpacity(this,this.opacity),this.__childItems.splice(g,0,A),this.__childItemsEventHandlers.splice(g,0,t),this.childItemsMapping[i]&&(this.childItemsMappingCorrupt=!0),this.childItemsMapping[i]=g,this.updateChildNameMapping(g+1),A.setOwner(this),I&&(A.globalXfoParam.value=o),this.emit("childAdded",new ChildAddedEvent(g,A)),A}addChild(A,g=!0,I=!0){const C=this.__childItems.length;return this.insertChild(A,C,g,I),A}getChild(A){return this.__childItems[A]}getChildByName(A){const g=this.childItemsMapping[A.toLocaleLowerCase()];return null!=g?this.__childItems[g]:null}getChildNames(){const A=[];for(let g=0;g<this.__childItems.length;g++){const I=this.__childItems[g];null!=I&&(A[g]=I.getName())}return A}unbindChild(A,g){const I=this.__childItemsEventHandlers[A];g.off("nameChanged",I.nameChanged),this.__childItems.splice(A,1),this.__childItemsEventHandlers.splice(A,1),delete this.childItemsMapping[g.name.toLocaleLowerCase()],this.updateChildNameMapping(A),this.setBoundingBoxDirty(),this.emit("childRemoved",{childItem:g,index:A})}removeChild(A){const g=this.__childItems[A];g&&(this.unbindChild(A,g),g.setOwner(void 0))}removeChildByName(A){const g=this.childItemsMapping[A.toLocaleLowerCase()];if(null!=g)return this.removeChild(g)}removeChildByHandle(A){const g=this.__childItems.indexOf(A);if(-1==g)throw new Error("Error in removeChildByHandle. Child not found:"+A.getName());this.removeChild(g)}removeAllChildren(){let A=this.__childItems.length;for(;A--;)this.removeChild(A);this.setBoundingBoxDirty()}getChildIndex(A){return this.__childItems.indexOf(A)}resolvePath(A,g=0){if(0==g&&("."!=A[0]&&A[0]!=this.name||g++),".."==A[g]){if(this.ownerItem)return this.ownerItem.resolvePath(A,g+1);throw Error("this.ownerItem is undefined")}if(g==A.length)return this;const I=A[g],C=this.getChildByName(I);return C?C.resolvePath(A,g+1):super.resolvePath(A,g)}traverse(A,g=!0){const I=(A,g)=>{const I=A.getChildren();for(const A of I)A&&C(A,g)},C=(g,C)=>{0!=A(g,C)&&I(g,C+1)};g?C(this,1):I(this,0)}onPointerDown(A){this.emit("pointerDown",A),A.propagating&&this.ownerItem instanceof TreeItem&&this.ownerItem.onPointerDown(A)}onPointerUp(A){this.emit("pointerUp",A),A.propagating&&this.ownerItem instanceof TreeItem&&this.ownerItem.onPointerUp(A)}onPointerMove(A){this.emit("pointerMove",A),A.propagating&&this.ownerItem instanceof TreeItem&&this.ownerItem.onPointerMove(A)}onPointerEnter(A){this.emit("pointerEnter",A),A.propagating&&this.ownerItem instanceof TreeItem&&this.ownerItem.onPointerEnter(A)}onPointerLeave(A){this.emit("pointerLeave",A),A.propagating&&this.ownerItem instanceof TreeItem&&this.ownerItem.onPointerLeave(A)}onPointerClick(A){this.emit("pointerClick",A),A.propagating&&this.ownerItem instanceof TreeItem&&this.ownerItem.onPointerClick(A)}onPointerDoubleClick(A){this.emit("pointerDoubleClick",A),A.propagating&&this.ownerItem instanceof TreeItem&&this.ownerItem.onPointerDoubleClick(A)}onPointerLongPress(A){this.emit("pointerLongPress",A),A.propagating&&this.ownerItem instanceof TreeItem&&this.ownerItem.onPointerLongPress(A)}onWheel(A){this.emit("mouseWheel",A),A.propagating&&this.ownerItem instanceof TreeItem&&this.ownerItem.onWheel(A)}onTouchCancel(A){this.emit("touchCancel",A),A.propagating&&this.ownerItem instanceof TreeItem&&this.ownerItem.onTouchCancel(A)}toJSON(A){let g=super.toJSON(A);const I={};for(const g of this.__childItems)if(g){const C=g.toJSON(A);C&&(I[g.getName()]=C)}return Object.keys(I).length>0&&(g?g.children=I:g={name:this.name,children:I}),g}fromJSON(A,g,I){if(super.fromJSON(A,g),null!=A.children){const I=A.children;if(Array.isArray(I))for(const A of I){let I=this.getChildByName(A.name);I?I.fromJSON(A,g):A.type&&(I=Registry.constructClass(A.type),I&&(I.fromJSON(A,g),this.addChild(I,!1,!1)))}else for(const A in I){const C=I[A];let e=this.getChildByName(A);e?e.fromJSON(C,g):C.type&&(e=Registry.constructClass(C.type),e&&(e.fromJSON(C,g),this.addChild(e,!1,!1)))}}}readBinary(A,g){super.readBinary(A,g);const I=A.loadUInt8();2&I||this.setVisible(!1);if(4&I){const g=new Xfo;if(g.tr=A.loadFloat32Vec3(),g.ori=A.loadFloat32Quat(),32&I)g.sc=A.loadFloat32Vec3();else{const I=A.loadFloat32();g.sc.set(I,I,I)}this.localXfoParam.value=g}8&I&&this.boundingBoxParam.loadValue(new Box3(A.loadFloat32Vec3(),A.loadFloat32Vec3()));const C=A.loadUInt32();if(C>0){const I=A.loadUInt32Array(C);for(let e=0;e<C;e++)try{A.seek(I[e]);let C=A.loadStr();const i=Registry.constructClass(C);if(!i){const g=A.loadStr();console.warn("Unable to construct child:"+g+" of type:"+C);continue}A.seek(I[e]),i.readBinary(A,g),this.addChild(i,!1,!0)}catch(A){console.warn("Error loading tree item: ",A)}}}clone(A){const g=new TreeItem("");return g.copyFrom(this,A),g}copyFrom(A,g){if(!(A instanceof TreeItem))throw new Error("cannot copy from src");super.copyFrom(A,g),this.visibleCounter=this.visibleParam.value?1:0,this.updateVisibility(),this.updateOpacity(),this.removeAllChildren(),A.getChildren().forEach((A=>{A&&this.addChild(A.clone(g),!1,!1)}))}}Registry.register("TreeItem",TreeItem);class TreeItemParameter extends Parameter{filterFn;listenerIDs={};constructor(A="",g){super(A,null,"TreeItem"),this.filterFn=g}emitTreeItemGlobalXfoChanged(A){this.emit("treeItemGlobalXfoChanged",A)}setFilterFn(A){this.filterFn=A}getFilterFn(){return this.filterFn}setValue(A){if(!(A instanceof TreeItem))throw new Error("value provided is not an instance of a 'TreeItem' class. Check the source of this value");this.filterFn&&!this.filterFn(A)||this.value!==A&&(this.value&&this.value.off("globalXfoChanged",this.listenerIDs.globalXfoChanged),super.setValue(A),this.value&&(this.listenerIDs.globalXfoChanged=this.value.on("globalXfoChanged",(A=>{this.emitTreeItemGlobalXfoChanged(A)}))))}toJSON(A){return{type:this.getClassName(),name:this.name,value:A.makeRelative(this.value?.getPath())}}fromJSON(A,g){null!=A.value?g.resolvePath(A.value,(A=>{this.setValue(A)}),(()=>{console.warn("Unable to resolve tree item parameter value:"+A.paramPath)})):console.warn("Invalid Parameter JSON")}clone(A){const g=new TreeItemParameter(this.name,this.filterFn);return this.value&&g.setValue(this.value.clone(A)),g}}Registry.register("TreeItemParameter",TreeItemParameter);class ItemEvent extends BaseEvent{item;index;constructor(A,g){super(),this.index=g,this.item=A}}class ItemSetParameter extends Parameter{filterFn;constructor(A="",g){super(A,new Set,"TreeItem"),this.filterFn=g}setFilterFn(A){this.filterFn=A}getFilterFn(){return this.filterFn}getItem(A){return Array.from(this.value)[A]}addItem(A,g=!0){if(!this.filterFn||this.filterFn(A)){if(this.value.has(A))return-1;{this.value.add(A);const I=Array.from(this.value).indexOf(A);return this.emit("itemAdded",new ItemEvent(A,I)),g&&this.emit("valueChanged"),I}}console.warn("ItemSet __filterFn rejecting item:",A.getPath())}addItems(A,g=!0){A.forEach((A=>this.addItem(A,!1))),g&&this.emit("valueChanged")}removeItem(A,g=!0){const I=Array.from(this.value)[A];return this.value.delete(I),this.emit("itemRemoved",new ItemEvent(I,A)),g&&this.emit("valueChanged"),I}setItems(A,g=!0){const I=Array.from(this.value);for(let g=I.length-1;g>=0;g--){const C=I[g];A.has(C)||this.removeItem(g,!1)}for(const g of A)this.value.has(g)||this.addItem(g,!1);g&&this.emit("valueChanged")}clearItems(A=!0){this.value.clear(),A&&this.emit("valueChanged")}getNumItems(){return this.value.size}toJSON(A){this.value||(this.value=new Set);const g=[];for(const I of this.value){const C=I.getPath();g.push(A&&A.makeRelative?A.makeRelative(C):C)}return{type:this.getClassName(),name:this.name,value:g}}fromJSON(A,g){if(!g||!g.resolvePath)throw new Error("Unable to load JSON on a ItemSetParameter without a load context");A.value.forEach((A=>{g.resolvePath(A,(A=>{this.addItem(A,!1)}),(()=>{console.warn("BaseGroup: '"+this.getName()+"'. Unable to load item:"+A)}))}))}clone(){return new ItemSetParameter(this.name,this.filterFn)}}Registry.register("ItemSetParameter",ItemSetParameter);class MaterialFloatParam extends NumberParameter{image;constructor(A="",g,I){super(A,g,I)}getImage(){return this.image}setImage(A){const g=()=>{this.emit("textureDisconnected")};A?(null!=this.image&&this.image!==A&&g(),this.image=A,this.emit("textureConnected"),this.emit("valueChanged")):null!=this.image&&(g(),this.image=void 0,this.emit("textureDisconnected"))}setValue(A){if("number"!=typeof A&&!(A instanceof BaseImage))throw new Error("value provided is not of type number of an instance of 'BaseImage' class. Check the source of this value");A instanceof BaseImage?this.setImage(A):super.setValue(A)}readBinary(A,g){super.readBinary(A,g);const I=A.loadStr();""!=I&&(console.log("Load Texture"),this.setImage(g.assetItem.materialLibrary.getImage(I)))}clone(){return new MaterialFloatParam(this.name,this.value,this.range)}}Registry.register("MaterialFloatParam",MaterialFloatParam),function(A){A.Gamma="Gamma",A.Linear="Linear"}(ColorSpace||(ColorSpace={}));class MaterialColorParam extends ColorParameter{listenerIDs={};image;colorSpace=ColorSpace.Gamma;constructor(A,g){super(A,g)}getImage(){return this.image}imageUpdated(){this.emit("valueChanged")}setImage(A){const g=()=>{this.image&&(this.image.off("updated",this.listenerIDs.updated),this.image=void 0),this.emit("textureDisconnected")};A?(null!=this.image&&this.image!==A&&g(),this.image=A,this.listenerIDs.updated=this.image.on("updated",(()=>{this.imageUpdated()})),this.emit("textureConnected"),this.emit("valueChanged")):null!=this.image&&(g(),this.image=void 0,this.emit("textureDisconnected"))}setValue(A){if(!(A instanceof BaseImage||A instanceof Color))throw new Error("value provided is not an instance of a 'Color' or 'BaseImage' class. Check the source of this value");A instanceof BaseImage?this.setImage(A):super.setValue(A)}readBinary(A,g){super.readBinary(A,g);const I=A.loadStr();""!=I&&this.setImage(g.assetItem.materialLibrary.getImage(I)),this.colorSpace=ColorSpace.Linear}toJSON(A){const g=super.toJSON(A);return g.colorSpace=this.colorSpace,g}fromJSON(A,g){super.fromJSON(A,g),this.colorSpace=ColorSpace[A.colorSpace]??ColorSpace.Gamma}clone(){const A=new MaterialColorParam(this.name,this.value?.clone());return A.colorSpace=this.colorSpace,A}}Registry.register("MaterialColorParam",MaterialColorParam);class Material extends ParameterOwner{__isOpaque=!0;__isTextured=!1;__shaderName="";libraryIndex=-1;constructor(A,g){super(A),g&&this.setShaderName(g)}getShaderName(){return this.__shaderName}setShaderName(A){if(this.__shaderName==A)return;this.__shaderName=A;const g=Registry.getClassDefinition(A).getMaterialTemplate();if(!g)throw new Error("Error setting Shader. Material template not registered found:"+A);const I={};let C=g.getNumParameters();for(;C--;){const A=g.getParameterByIndex(C);this.getParameter(A.getName())||this.addParameter(A.clone()),I[A.getName()]=!0}for(const A of this.params)I[A.getName()]||this.removeParameter(A.getName());this.__shaderName=A,this.__checkOpacity({});const e=new ShaderNameChangedEvent(A);this.emit("shaderNameChanged",e)}removeAllTextures(){for(const A of this.params)A instanceof MaterialColorParam?A.getImage()&&A.setImage(null):A instanceof MaterialFloatParam&&A.getImage()&&A.setImage(null)}getPath(){return null==this.ownerItem?[this.name]:this.ownerItem instanceof Parameter?[...this.ownerItem.getPath(),"value"]:[...this.ownerItem.getPath(),this.name]}getParamTextures(){const A={};for(const g of this.params)g instanceof MaterialColorParam?g.getImage()&&(A[g.getName()]=g.getImage()):g instanceof MaterialFloatParam&&g.getImage()&&(A[g.getName()]=g.getImage());return A}isOpaque(){return this.__isOpaque}__checkOpacity(A){let g=!0;try{this.getShaderClass().isOpaque()||(g=!1)}catch(A){}if(g){const A=this.getParameter("Opacity");if(A&&(A.value<.99||A instanceof MaterialFloatParam&&A.getImage()))g=!1;else{const A=this.getParameter("BaseColor");if(A){if(A instanceof MaterialColorParam){const I=A.getImage();I&&"RGBA"==I.format&&(g=!1)}if(g&&A.value){A.value.a<1&&(g=!1)}}}}if(g!=this.__isOpaque){this.__isOpaque=g;const A=new OpacityStateChangedEvent(g,!0);this.emit("opacityChanged",A),this.emit("transparencyChanged",A)}}isTextured(){return this.__isTextured}__checkTextures(A){const g=A||{};let I=!1;for(const A of this.params)if(A instanceof MaterialColorParam){if(A.getImage()){I=!0;break}}else if(A instanceof MaterialFloatParam&&A.getImage()){I=!0;break}if(I!=this.__isTextured){this.__isTextured=I;let A=new TexturedChangedEvent(I,g);this.emit("texturedChanged",A)}}parameterValueChanged(A){this.__checkOpacity(A),this.__checkTextures(A),super.parameterValueChanged(A)}getShaderClass(){return Registry.getClassDefinition(this.getShaderName())}toJSON(A){const g=super.toJSON(A);return g.shader=this.__shaderName,g}fromJSON(A,g={}){A.shader?(this.setShaderName(A.shader),super.fromJSON(A,g),this.__checkOpacity(),this.__checkTextures()):console.warn("Invalid Material JSON")}readBinary(A,g){let I=A.loadStr();"StandardMaterial"==I&&(I="StandardSurfaceShader"),"TransparentMaterial"==I&&(I="StandardSurfaceShader"),this.setShaderName(I),super.readBinary(A,g),this.__checkOpacity(),this.__checkTextures()}clone(A){const g=new Material("clone","");return g.copyFrom(this,A),g}copyFrom(A,g){if(!(A instanceof Material))throw new Error("cannot copy from src");this.setShaderName(A.getShaderName()),super.copyFrom(A,g)}}Registry.register("Material",Material);class MaterialParameter extends Parameter{listenerIDs={};constructor(A="",g=null){super(A,null,"Material"),g&&this.setValue(g)}valueParameterValueChanged(A){this.emit("valueParameterValueChanged",A)}setValue(A){if(null!=A&&!(A instanceof Material))throw new Error("value provided is not an instance of a 'Material' class. Check the source of this value");this.value!==A&&(this.value&&(this.value.setOwner(null),this.value.off("parameterValueChanged",this.listenerIDs.parameterValueChanged)),super.setValue(A),this.value&&(this.value.setOwner(this),this.listenerIDs.parameterValueChanged=this.value.on("parameterValueChanged",(A=>{this.valueParameterValueChanged(A)}))))}loadValue(A){this.value&&(this.value.setOwner(null),this.value.off("parameterValueChanged",this.listenerIDs.parameterValueChanged)),super.loadValue(A),this.value&&(this.value.setOwner(this),this.listenerIDs.parameterValueChanged=this.value.on("parameterValueChanged",(A=>{this.valueParameterValueChanged(A)})))}toJSON(A){const g={type:this.getClassName(),name:this.name};return this.value&&(this.value.libraryIndex>=0?g.libraryIndex=this.value.libraryIndex:g.value=this.value.toJSON(A)),g}fromJSON(A,g){if(null!=A.libraryIndex){if(g&&g.assetItem){const I=g.assetItem.getMaterialLibrary().getMaterial(A.libraryIndex);I&&this.setValue(I)}}else if(A.value)if(this.value&&this.value.getClassName()==A.value.type)this.value.fromJSON(A.value);else{const I=Registry.constructClass(A.value.type);A.value&&I.fromJSON(A.value,g),this.setValue(I)}}clone(){return new MaterialParameter(this.name,this.value)}}function approxEqual(A,g){for(let I=0;I<A.length;I++)if(Math.abs(g[I]-A[I])>.001)return!1;return!0}Registry.register("MaterialParameter",MaterialParameter);const resizeArray=(A,g)=>{if(A instanceof Uint8Array){const I=new Uint8Array(g);return I.set(A),I}if(A instanceof Int8Array){const I=new Int8Array(g);return I.set(A),I}if(A instanceof Uint16Array){const I=new Uint16Array(g);return I.set(A),I}{const I=new Float32Array(g);return I.set(A),I}};class Attribute extends BaseClass{dataTypeName;stride;initValue=Number.NaN;normalized;data;mesh;splitValues=[];splits={};constructor(A,g,I=Number.NaN){super(),this.dataTypeName=A,this.stride=g,this.initValue=I,this.init()}init(){this.data=new Float32Array(0),this.initRange(0)}setMesh(A){this.mesh=A}asArray(){return this.data}getDataTypeName(){return this.dataTypeName}getCount(){return this.data.length/this.stride}get count(){return this.data.length/this.stride}setCount(A){const g=this.data.length,I=A*this.stride;I>g?(this.data=resizeArray(this.data,I),this.initRange(g)):I<g&&(this.data=this.data.slice(0,I)),this.splits={},this.splitValues=[]}initRange(A){for(let g=A;g<this.data.length;g++)this.data[g]=this.initValue}isInitialized(A){for(let g=0;g<A.length;g++)if(A[g]!=this.initValue)return!0;return!1}get numElements(){return this.stride}getFloat32Value(A){return this.data[A]}setFloat32Value(A,g){this.data[A]=g}getValues(A){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/this.stride);const g=A*this.stride;return this.data.subarray(g,g+this.stride)}setValues(A,g){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/this.stride);const I=A*this.stride;this.data.set(g,I)}merge(A,g=new Xfo){const I=this.data.length,C=A.data.length,e=new Float32Array(I+C);e.set(this.data,0);for(let g=0;g<C;g++)e[I+g]=A.data[g];this.data=e,this.splitValues=[...this.splitValues,...A.splitValues]}getSplits(){return this.splits}getFaceVertexValue_array(A,g){const I=this.mesh.getFaceVertexIndex(A,g);return I in this.splits&&A in this.splits[I]?this.splitValues[this.splits[I][A]]:this.data.subarray(I*this.stride,(I+1)*this.stride)}setFaceVertexValue_array(A,g,I){const C=this.mesh.getFaceVertexIndex(A,g);this.setFaceVertexValue_ByVertexIndex(A,C,I)}setFaceVertexValue_ByVertexIndex(A,g,I){const C=this.data.subarray(g*this.stride,(g+1)*this.stride);if(this.isInitialized(C))if(approxEqual(C,I));else{if(g in this.splits){const C=this.splits[g];for(const g in C){const e=C[g];if(approxEqual(this.splitValues[e],I))return void(C[A]=e)}if(A in this.splits[g])return void(this.splitValues[this.splits[g][A]]=I)}else this.splits[g]={};this.splits[g][A]=this.splitValues.length,this.splitValues.push(I)}else C.set(I)}setSplitVertexValue_array(A,g,I){if(A in this.splits||(this.splits[A]={}),g in this.splits[A]){if(approxEqual(this.splitValues[this.splits[A][g]],I))return;console.warn("Face Vertex Already Split with different value")}this.splits[A][g]=this.splitValues.length,this.splitValues.push(I)}setSplitVertexValues(A,g,I){A in this.splits||(this.splits[A]={});const C=this.splitValues.length;this.splitValues.push(I);for(const I of g)this.splits[A][I]=C}generateSplitValues(A,g){if(0==g)return this.data;const I=this.getCount(),C=resizeArray(this.data,(I+g)*this.stride);for(const g in A){const e=A[g];for(const A in e){const i=I+e[A];if(g in this.splits&&A in this.splits[g]){const I=this.splits[g][A],e=this.splitValues[I];for(let A=0;A<e.length;A++)C[i*this.stride+A]=e[A]}else{const A=parseInt(g);for(let g=0;g<this.stride;g++)C[i*this.stride+g]=this.data[A*this.stride+g]}}}return C}toJSON(A){return{data:Array.from(this.data),dataType:this.dataTypeName,length:this.data.length/this.stride}}fromJSON(A){const g=A.data;for(let A=0;A<g.length;A++)this.data[A]=g[A]}loadSplitValues(A){const g=A.loadUInt32Array();if(0==g.length)return;let I=0,C=0;for(;;){const A=g[I++],e=g[I++],i={};for(let A=0;A<e;A++){const A=g[I++],e=g[I++];i[A]=e,e>=C&&(C=e+1)}if(this.splits[A]=i,I>=g.length)break}const e=this.stride,i=A.loadFloat32Array(C*e);this.splitValues=[];for(let A=0;A<C;A++){const g=i.slice(A*e,A*e+e);this.splitValues.push(g)}}toString(){return JSON.stringify(this.toJSON(),null,2)}genBuffer(){return{values:this.data,count:this.getCount(),dimension:this.stride,dataType:this.dataTypeName,normalized:this.normalized}}}class Vec2Attribute extends Attribute{constructor(A="Vec2"){super(A,2),this.normalized=!1}getValue(A){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const g=A*this.stride;return new Vec2(this.data[g],this.data[g+1])}setValue(A,g){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const I=A*this.stride;this.data.set(g.asArray(),I)}getFaceVertexValue(A,g){const I=this.getFaceVertexValue_array(A,g);return new Vec2(I[0],I[1])}setFaceVertexValue(A,g,I){this.setFaceVertexValue_array(A,g,Float32Array.from(I.asArray()))}setSplitVertexValue(A,g,I){this.setSplitVertexValue_array(A,g,Float32Array.from(I.asArray()))}merge(A,g=new Xfo){const I=this.getCount(),C=A.getCount();this.setCount(I+C);for(let g=0;g<C;g++)this.setValue(I+g,A.getValue(g));this.splitValues=[...this.splitValues,...A.splitValues]}}Registry.register("Vec2Attribute",Vec2Attribute);const mapIn$2=A=>MathFunctions.encode16BitFloat(A),mapOut$2=A=>MathFunctions.decode16BitFloat(A);class Vec2f16Attribute extends Vec2Attribute{constructor(){super("Vec2f16")}init(){this.data=new Uint16Array(0),this.initRange(0)}initRange(A){for(let g=A;g<this.data.length;g++)this.data[g]=mapIn$2(Number.NaN)}isInitialized(A){for(let g=0;g<A.length;g++)if(Number.isFinite(mapOut$2(A[g])))return!0;return!1}getValue(A){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const g=A*this.stride,I=this.data.subarray(g,g+this.stride);return new Vec2(mapOut$2(I[0]),mapOut$2(I[1]))}setValue(A,g){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const I=A*this.stride,C=this.data.subarray(I,I+this.stride);C[0]=mapIn$2(g.x),C[1]=mapIn$2(g.y)}getFaceVertexValue(A,g){const I=this.getFaceVertexValue_array(A,g);return new Vec2(mapOut$2(I[0]),mapOut$2(I[1]))}setFaceVertexValue(A,g,I){const C=new Uint16Array(2);C[0]=mapIn$2(I.x),C[1]=mapIn$2(I.y),this.setFaceVertexValue_array(A,g,C)}}class Vec3Ref{data;constructor(A){this.data=A}get x(){return this.data[0]}set x(A){this.data[0]=A}get y(){return this.data[1]}set y(A){this.data[1]=A}get z(){return this.data[2]}set z(A){this.data[2]=A}set(A,g,I){this.data[0]=A,this.data[1]=g,this.data[2]=I}}class Vec3Attribute extends Attribute{constructor(A="Vec3"){super(A,3),this.normalized=!1}getValue(A){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const g=A*this.stride;return new Vec3(this.data[g+0],this.data[g+1],this.data[g+2])}getValueRef(A){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const g=A*this.stride;return new Vec3Ref(this.data.subarray(g,g+3))}setValue(A,g){this.setValues(A,g.asArray())}getFaceVertexValue(A,g){const I=this.getFaceVertexValue_array(A,g);return new Vec3(I[0],I[1],I[2])}setFaceVertexValue(A,g,I){this.setFaceVertexValue_array(A,g,Float32Array.from(I.asArray()))}setSplitVertexValue(A,g,I){this.setSplitVertexValue_array(A,g,Float32Array.from(I.asArray()))}merge(A,g=new Xfo){const I=this.getCount(),C=A.getCount();this.setCount(I+C);for(let e=0;e<C;e++)this.setValue(I+e,g.transformVec3(A.getValue(e)))}}Registry.register("Vec3Attribute",Vec3Attribute);class Vec3f8Ref{data;constructor(A){this.data=A}get x(){return MathFunctions.decode16BitFloat(this.data[0])}set x(A){this.data[0]=MathFunctions.encode16BitFloat(A)}get y(){return MathFunctions.decode16BitFloat(this.data[1])}set y(A){this.data[1]=MathFunctions.encode16BitFloat(A)}get z(){return MathFunctions.decode16BitFloat(this.data[2])}set z(A){this.data[2]=MathFunctions.encode16BitFloat(A)}set(A,g,I){this.data[0]=MathFunctions.encode16BitFloat(A),this.data[1]=MathFunctions.encode16BitFloat(g),this.data[2]=MathFunctions.encode16BitFloat(I)}}const mapIn$1=(A,g)=>MathFunctions.remap(A,g[0],g[1],-127,127),mapOut$1=(A,g)=>MathFunctions.remap(A,-127,127,g[0],g[1]);class Vec3f8Attribute extends Vec3Attribute{valueRange;constructor(A=[-1,1]){super("Vec3f8"),this.valueRange=A}init(){this.data=new Int8Array(0),this.initRange(0)}initRange(A){for(let g=A;g<this.data.length;g++)this.data[g]=mapIn$1(Number.NaN,this.valueRange)}isInitialized(A){for(let g=0;g<A.length;g++)if(Number.isFinite(mapOut$1(A[g],this.valueRange)))return!0;return!1}getValue(A){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const g=A*this.stride,I=this.data.subarray(g,g+this.stride);return new Vec3(mapOut$1(I[0],this.valueRange),mapOut$1(I[1],this.valueRange),mapOut$1(I[2],this.valueRange))}getValueRef(A){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const g=A*this.stride;return new Vec3f8Ref(this.data.subarray(g,g+3))}setValue(A,g){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const I=A*this.stride,C=this.data.subarray(I,I+this.stride);C[0]=mapIn$1(g.x,this.valueRange),C[1]=mapIn$1(g.y,this.valueRange),C[2]=mapIn$1(g.z,this.valueRange)}getFaceVertexValue(A,g){const I=this.getFaceVertexValue_array(A,g);return new Vec3(mapOut$1(I[0],this.valueRange),mapOut$1(I[1],this.valueRange),mapOut$1(I[2],this.valueRange))}setFaceVertexValue(A,g,I){const C=new Int8Array(3);C[0]=mapIn$1(I.x,this.valueRange),C[1]=mapIn$1(I.y,this.valueRange),C[2]=mapIn$1(I.z,this.valueRange),this.setFaceVertexValue_array(A,g,C)}setSplitVertexValues(A,g,I){super.setSplitVertexValues(A,g,I.map((A=>mapIn$1(A,this.valueRange)),this.valueRange))}}const mapIn=A=>MathFunctions.encode16BitFloat(A),mapOut=A=>MathFunctions.decode16BitFloat(A);class Vec3f16Ref{data;constructor(A){this.data=A}get x(){return mapOut(this.data[0])}set x(A){this.data[0]=mapIn(A)}get y(){return mapOut(this.data[1])}set y(A){this.data[1]=mapIn(A)}get z(){return mapOut(this.data[2])}set z(A){this.data[2]=mapIn(A)}set(A,g,I){this.data[0]=mapIn(A),this.data[1]=mapIn(g),this.data[2]=mapIn(I)}}class Vec3f16Attribute extends Vec3Attribute{constructor(){super("Vec3f16")}init(){this.data=new Uint16Array(0),this.initRange(0)}initRange(A){for(let g=A;g<this.data.length;g++)this.data[g]=mapIn(Number.NaN)}isInitialized(A){for(let g=0;g<A.length;g++)if(Number.isFinite(mapOut(A[g])))return!0;return!1}getValue(A){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const g=A*this.stride,I=this.data.subarray(g,g+this.stride);return new Vec3(mapOut(I[0]),mapOut(I[1]),mapOut(I[2]))}getValueRef(A){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const g=A*this.stride;return new Vec3f16Ref(this.data.subarray(g,g+3))}setValue(A,g){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const I=A*this.stride,C=this.data.subarray(I,I+this.stride);C[0]=mapIn(g.x),C[1]=mapIn(g.y),C[2]=mapIn(g.z)}getFaceVertexValue(A,g){const I=this.getFaceVertexValue_array(A,g);return new Vec3(mapOut(I[0]),mapOut(I[1]),mapOut(I[2]))}setFaceVertexValue(A,g,I){const C=new Uint16Array(3);C[0]=mapIn(I.x),C[1]=mapIn(I.y),C[2]=mapIn(I.z),this.setFaceVertexValue_array(A,g,C)}setSplitVertexValues(A,g,I){super.setSplitVertexValues(A,g,I.map((A=>mapIn(A))))}}class ColorAttribute extends Attribute{constructor(){super("Color",4),this.normalized=!1}getValue(A){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const g=A*this.stride;return new Color(this.data[g+0],this.data[g+1],this.data[g+2],this.data[g+3])}setValue(A,g){this.setValues(A,g.asArray())}getFaceVertexValue(A,g){const I=this.getFaceVertexValue_array(A,g);return new Color(I[0],I[1],I[2],I[3])}setFaceVertexValue(A,g,I){this.setFaceVertexValue_array(A,g,Float32Array.from(I.asArray()))}setSplitVertexValue(A,g,I){this.setSplitVertexValue_array(A,g,Float32Array.from(I.asArray()))}merge(A,g=new Xfo){const I=this.getCount(),C=A.getCount();this.setCount(I+C);for(let g=0;g<C;g++)this.setValue(I+g,A.getValue(g));this.splitValues=[...this.splitValues,...A.splitValues]}}Registry.register("ColorAttribute",ColorAttribute);const parse8BitPositionsArray=(A,g,I,C,e)=>{for(let i=A[0];i<A[1];i++){const A=new Vec3(C[3*i+0]/255,C[3*i+1]/255,C[3*i+2]/255);A.multiplyInPlace(I),A.addInPlace(g),e.setValue(i,A)}},parse16BitPositionsArray=(A,g,I,C,e)=>{for(let i=A[0];i<A[1];i++){const A=new Vec3(C[3*i+0]/65535,C[3*i+1]/65535,C[3*i+2]/65535);A.multiplyInPlace(I),A.addInPlace(g),e.setValue(i,A)}},parse8BitNormalsArray=(A,g,I,C,e)=>{I.isNull()&&I.set(1,1,1);for(let i=A[0];i<A[1];i++){const A=new Vec3(C[3*i+0]/255,C[3*i+1]/255,C[3*i+2]/255);A.multiplyInPlace(I),A.addInPlace(g),A.normalizeInPlace(),e.setValue(i,A)}},parse8BitTextureCoordsArray=(A,g,I,C,e)=>{for(let i=A[0];i<A[1];i++){const A=new Vec2(C[2*i+0]/255,C[2*i+1]/255);A.multiplyInPlace(I),A.addInPlace(g),e.setValue(i,A)}},parse16BitTextureCoordsArray=(A,g,I,C,e)=>{for(let i=A[0];i<A[1];i++){const A=new Vec2(C[2*i+0]/65535,C[2*i+1]/65535);A.multiplyInPlace(I),A.addInPlace(g),e.setValue(i,A)}};class BaseGeom extends ParameterOwner{boundingBox=new Box3;boundingBoxDirty=!0;__metaData=new Map;#t=0;__vertexAttributes=new Map;debugColor=new Color(1,0,0,1);constructor(){super(),this.addVertexAttribute("positions",new Vec3f16Attribute)}getPath(){return null==this.ownerItem?[this.name]:this.ownerItem instanceof Parameter?[...this.ownerItem.getPath(),"value"]:[...this.ownerItem.getPath(),this.name]}clear(){this.setNumVertices(0)}addVertexAttribute(A,g){g.setCount(this.#t),this.__vertexAttributes.set(A,g)}hasVertexAttribute(A){return this.__vertexAttributes.has(A)}getVertexAttribute(A){return this.__vertexAttributes.get(A)}getVertexAttributes(){const A={};for(const[g,I]of this.__vertexAttributes.entries())A[g]=I;return A}get positions(){return this.__vertexAttributes.get("positions")}numVertices(){return this.#t}getNumVertices(){return this.#t}setNumVertices(A){this.#t=A,this.__vertexAttributes.forEach((A=>A.setCount(this.#t))),this.setBoundingBoxDirty()}getBoundingBox(){return this.boundingBoxDirty&&this.updateBoundingBox(),this.boundingBox}setBoundingBoxDirty(){this.boundingBoxDirty=!0,this.emit("boundingBoxChanged")}updateBoundingBox(){const A=this.positions,g=new Box3;if(A){const I=A.getCount();for(let C=0;C<I;C++)g.addPoint(A.getValue(C))}this.boundingBox=g,this.boundingBoxDirty=!1}merge(A,g=new Xfo){const I=this.getNumVertices(),C=A.getNumVertices();for(const[I,C]of this.__vertexAttributes){const e=A.getVertexAttribute(I);e&&("positions"==I?C.merge(e,g):"normals"==I&&C.merge(e,new Xfo(new Vec3,g.ori)))}this.setNumVertices(I+C),this.updateBoundingBox()}genBuffers(A){const g={};for(const[A,I]of this.__vertexAttributes)g[A]=I.genBuffer();return{numVertices:this.numVertices(),attrBuffers:g}}freeBuffers(){}loadBaseGeomBinary(A,g){this.name=A.loadStr();const I=A.loadUInt8();this.debugColor=A.loadRGBFloat32Color();const C=A.loadUInt32();let e,i;this.boundingBox.set(A.loadFloat32Vec3(),A.loadFloat32Vec3()),2&I&&(e=this.getVertexAttribute("normals"),e||(e=new Vec3f8Attribute,this.addVertexAttribute("normals",e))),4&I&&(i=this.getVertexAttribute("texCoords"),i||(i=new Vec2f16Attribute,this.addVertexAttribute("texCoords",i)));const t=A.loadUInt32();if(0==t){this.positions.data=A.loadUInt16Array(3*C),e&&(e.data=A.loadInt8Array(3*C)),i&&(i.data=A.loadUInt16Array(2*C)),this.setNumVertices(C)}else if(1==t){this.addVertexAttribute("positions",new Vec3Attribute),this.setNumVertices(C);const I=this.positions;{const e=this.boundingBox;if(g.versions["zea-engine"].compare([3,9,1])>=0){const g=A.loadUInt16Array(3*C,!1);parse16BitPositionsArray([0,C],e.p0,e.diagonal(),g,I)}else{const g=A.loadUInt8Array(3*C,!1);parse8BitPositionsArray([0,C],e.p0,e.diagonal(),g,I)}}if(e){const g=new Box3(A.loadFloat32Vec3(),A.loadFloat32Vec3()),I=A.loadUInt8Array(3*C,!1);parse8BitNormalsArray([0,C],g.p0,g.diagonal(),I,e),e.loadSplitValues(A)}if(i){const I=new Box2(A.loadFloat32Vec2(),A.loadFloat32Vec2());if(g.versions["zea-engine"].compare([3,9,1])>=0){const g=A.loadUInt16Array(2*C,!1);parse16BitTextureCoordsArray([0,C],I.p0,I.diagonal(),g,i)}else{const g=A.loadUInt8Array(2*C,!1);parse8BitTextureCoordsArray([0,C],I.p0,I.diagonal(),g,i)}i.loadSplitValues(A)}}else{this.addVertexAttribute("positions",new Vec3Attribute),this.setNumVertices(C);const I=this.positions,o=[];let a,B=0;for(let g=0;g<t;g++){const g=A.loadUInt32(),I={range:[B,B+g],bbox:new Box3(A.loadFloat32Vec3(),A.loadFloat32Vec3()),normalsRange:new Box3,texCoordsRange:new Box2};e&&I.normalsRange.set(A.loadFloat32Vec3(),A.loadFloat32Vec3()),i&&I.texCoordsRange.set(A.loadFloat32Vec2(),A.loadFloat32Vec2()),o.push(I),B+=g}a=g.versions["zea-engine"].compare([3,9,1])>=0?A.loadUInt16Array(3*C,!1):A.loadUInt8Array(3*C,!1);let s=null,l=null;e&&(s=A.loadUInt8Array(3*C,!1)),i&&(l=A.loadUInt8Array(2*C,!1));for(let A=0;A<t;A++){{const C=o[A].bbox;g.versions["zea-engine"].compare([3,9,1])>=0?parse16BitPositionsArray(o[A].range,C.p0,C.diagonal(),a,I):parse8BitPositionsArray(o[A].range,C.p0,C.diagonal(),a,I)}if(s){const g=o[A].normalsRange;parse8BitNormalsArray(o[A].range,g.p0,g.diagonal(),s,e)}if(l){const I=o[A].texCoordsRange;g.versions["zea-engine"].compare([3,9,1])>=0?parse16BitTextureCoordsArray([0,C],I.p0,I.diagonal(),l,i):parse8BitTextureCoordsArray(o[A].range,I.p0,I.diagonal(),l,i)}}e&&e.loadSplitValues(A),i&&i.loadSplitValues(A)}this.boundingBoxDirty=!1}toJSON(A){const g=super.toJSON(A);A&&A.skipTopology||(g.numVertices=this.#t||0);const I={};for(const[g,C]of this.__vertexAttributes.entries())A&&"skipAttributes"in A&&A.skipAttributes.includes(g)||(I[g]=C.toJSON(A));return g.vertexAttributes=I,g}fromJSON(A,g){this.clear(),super.fromJSON(A,g),this.setNumVertices(A.numVertices);for(const g in A.vertexAttributes){let I=this.__vertexAttributes.get(g);const C=A.vertexAttributes[g];if(!I||I.dataTypeName!=C.dataType){switch(C.dataType){case"Vec2":I=new Vec2Attribute;break;case"Vec2f16":I=new Vec2f16Attribute;break;case"Vec3":I=new Vec3Attribute;break;case"Vec3f16":I=new Vec3f16Attribute;break;case"Vec3f8":I=new Vec3f8Attribute;break;case"Color":I=new ColorAttribute;break;default:throw"Invalid Vectex Type: "+I.dataTypeName}I.setCount(this.#t),this.addVertexAttribute(g,I)}I?I.fromJSON(C):console.warn("attr undefined, cannot execute fromJSON()")}this.emit("geomDataTopologyChanged")}toString(){return JSON.stringify(this.toJSON(),null,2)}}class Vec4Attribute extends Attribute{constructor(){super("Vec4",4),this.normalized=!1}getValue(A){if(A>=this.data.length/this.stride)throw new Error("Invalid vertex index:"+A+". Num Vertices:"+this.data.length/3);const g=A*this.stride;return new Vec4(this.data[g+0],this.data[g+1],this.data[g+2],this.data[g+3])}setValue(A,g){this.setValues(A,g.asArray())}getFaceVertexValue(A,g){const I=this.getFaceVertexValue_array(A,g);return new Vec4(I[0],I[1],I[2],I[3])}setFaceVertexValue(A,g,I){this.setFaceVertexValue_array(A,g,Float32Array.from(I.asArray()))}setSplitVertexValue(A,g,I){this.setSplitVertexValue_array(A,g,Float32Array.from(I.asArray()))}merge(A,g=new Xfo){const I=this.getCount(),C=A.getCount();this.setCount(I+C);for(let g=0;g<C;g++)this.setValue(I+g,A.getValue(g));this.splitValues=[...this.splitValues,...A.splitValues]}}Registry.register("Vec4Attribute",Vec4Attribute);class Points extends BaseGeom{constructor(){super()}clear(){this.setNumVertices(0),this.emit("geomDataTopologyChanged")}readBinary(A,g){super.loadBaseGeomBinary(A,g),this.emit("geomDataChanged")}}Registry.register("Points",Points);class ImageArrayParameter extends Parameter{constructor(A="",g=[]){super(A,g,"BaseImage[]")}toJSON(A){const g={type:this.getClassName(),name:this.name,images:this.value.map((A=>({imageType:A?.getClassName(),value:A?.toJSON()})))};return g}fromJSON(A,g){if(A.images){const I=A.images;this.value=I.map((A=>{const I=Registry.constructClass(A.imageType);return I&&A.value&&I.fromJSON(A.value,g),I}))}}clone(){return new ImageArrayParameter(this.name,this.value)}}Registry.register("ImageArrayParameter",ImageArrayParameter);class FatPoints extends Points{sprites=new ImageArrayParameter("Sprites");constructor(){super(),this.addVertexAttribute("sizes",new Attribute("Float32",1,1)),this.addVertexAttribute("colors",new ColorAttribute),this.addVertexAttribute("spriteIndices",new Attribute("Float32",1,-1)),this.addParameter(this.sprites)}}Registry.register("FatPoints",FatPoints);class Lines extends BaseGeom{__indices;constructor(){super(),this.__indices=new Uint32Array}clear(){this.setNumSegments(0),this.setNumVertices(0),this.emit("geomDataTopologyChanged")}getIndices(){return this.__indices}getNumSegments(){return this.__indices.length/2}getNumLineSegments(){return this.__indices.length/2}setNumSegments(A){if(A>this.getNumSegments()){const g=new Uint32Array(2*A);g.set(this.__indices),this.__indices=g}else this.__indices=this.__indices.slice(0,2*A)}setSegmentVertexIndices(A,g,I){if(A>=this.__indices.length/2)throw new Error("Invalid line index:"+A+". Num Segments:"+this.__indices.length/2);this.__indices[2*A+0]=g,this.__indices[2*A+1]=I}getSegmentVertexIndex(A,g){return A<this.getNumSegments()?this.__indices[2*A+g]:-1}merge(A,g=new Xfo){const I=this.getNumVertices();super.merge(A,g);const C=A.__indices,e=new Uint32Array(this.__indices.length+C.length);e.set(this.__indices,0),e.set(C.map((A=>A+I)),this.__indices.length),this.__indices=e}genBuffers(A){const g=super.genBuffers();let I;return I=g.numVertices<Math.pow(2,8)?new Uint8Array(this.__indices):g.numVertices<Math.pow(2,16)?new Uint16Array(this.__indices):this.__indices,g.indices=I,g}readBinary(A,g){super.loadBaseGeomBinary(A,g),this.setNumSegments(A.loadUInt32());const I=A.loadUInt8();1==I?this.__indices=A.loadUInt8Array():2==I?this.__indices=A.loadUInt16Array():4==I&&(this.__indices=A.loadUInt32Array()),this.emit("geomDataChanged")}toJSON(A){const g=super.toJSON(A);return A&&A.skipTopology||(g.indices=Array.from(this.__indices)),g}fromJSON(A,g){super.fromJSON(A,g),A.indices&&(this.__indices=Uint32Array.from(A.indices))}}Registry.register("Lines",Lines);class Mesh extends BaseGeom{faceCounts;faceVertexIndices;__logTopologyWarnings;__edgeAttributes;__faceAttributes;numEdges;edgeVerts;edgeAngles;edgeVecs;edgeFaces;faceEdges;vertexEdges;constructor(){super(),this.edgeFaces=[],this.faceEdges=[[]],this.faceCounts=[],this.faceVertexIndices=new Uint32Array,this.__logTopologyWarnings=!1,this.__edgeAttributes=new Map,this.__faceAttributes=new Map,this.numEdges=0,this.edgeVerts=[],this.vertexEdges=[],this.edgeAngles=new Float32Array,this.edgeVecs=[]}clear(){super.clear(),this.edgeVerts=[],this.vertexEdges=[],this.numEdges=0,this.edgeAngles=new Float32Array,this.emit("geomDataTopologyChanged")}addVertexAttribute(A,g){super.addVertexAttribute(A,g),g.setMesh(this)}getFaceCounts(){return this.faceCounts}getNumFaces(){return 0==this.faceCounts.length?0:this.faceCounts.reduce(((A,g)=>A+g))}getNumTriangles(){let A=0,g=1;for(const I of this.faceCounts)A+=I*g,g++;return A}setFaceCounts(A){let g=0,I=3;for(const C of A)g+=C*I,I++;if(0==this.getNumFaces())this.faceVertexIndices=new Uint32Array(g);else{const C=new Uint32Array(g);let e=0,i=0;g=0,I=3,A.forEach(((A,g)=>{const t=e+Math.min(A,this.faceCounts[g])*I;C.set(this.faceVertexIndices.slice(e,t),i),e+=this.faceCounts[g]*I,i+=A*I,I++})),this.faceVertexIndices=C}this.faceCounts=A}getNumFaceVertices(){let A=0;return this.faceCounts.forEach(((g,I)=>{A+=g*(I+3)})),A}getFaceVertexCount(A){let g=0,I=0;return this.faceCounts.some(((C,e)=>(g+=C,g>A&&(I=e+3,!0)))),I}getFaceVertexOffset(A){let g=0,I=0;return this.faceCounts.some(((C,e)=>g+C>A?(I+=(A-g)*(e+3),!0):(g+=C,I+=C*(e+3),!1))),I}setFaceVertexIndices(A,g){const I=this.getFaceVertexCount(A);if(g.length!=I)throw new Error(`Invalid indices for face:${A} vertexIndices:${g}. Expected ${I} indices`);const C=this.getFaceVertexOffset(A);this.faceVertexIndices.set(g,C)}addFace(A){const g=[...this.faceCounts];if(g.length<=A.length-3){for(let I=g.length;I<A.length-3;I++)g[I]=0;g[A.length-3]=1}else g[A.length-3]++;this.setFaceCounts(g);let I=0,C=0;return this.faceCounts.some(((g,e)=>e+3==A.length?(I+=g-1,C+=(g-1)*(e+3),!0):(I+=g,C+=g*(e+3),!1))),this.faceVertexIndices.set(A,C),I}getFaceVertexIndices(A){const g=[],I=this.getFaceVertexOffset(A),C=this.getFaceVertexCount(A);for(let A=0;A<C;A++)g.push(this.faceVertexIndices[I+A]);return g}getFaceVertexIndex(A,g){const I=this.getFaceVertexOffset(A);return this.faceVertexIndices[I+g]}addFaceAttribute(A,g){return g.setCount(this.getNumFaces()),this.__faceAttributes.set(A,g),g}hasFaceAttribute(A){return this.__faceAttributes.has(A)}getFaceAttribute(A){return this.__faceAttributes.get(A)}addEdgeAttribute(A,g){g.setCount(this.numEdges),this.__edgeAttributes.set(A,g)}hasEdgeAttribute(A){return this.__edgeAttributes.has(A)}getEdgeAttribute(A){return this.__edgeAttributes.get(A)}genTopologyInfo(){let A={};this.vertexEdges=[],this.edgeFaces=[],this.edgeVerts=[],this.faceEdges=[],this.numEdges=0;const g=this.positions,I=(I,C)=>{let e=I,i=C;if(i<e){const A=e;e=i,i=A}const t=e+">"+i;if(t in A)return A[t];const o=g.getValue(e),a=g.getValue(i).subtract(o),B={edgeIndex:this.edgeFaces.length/2,edgeVec:a};return A[t]=B,this.edgeFaces.push(-1),this.edgeFaces.push(-1),this.edgeVerts.push(e),this.edgeVerts.push(i),this.numEdges++,B},C=(A,g,C)=>{const e=I(A,g).edgeIndex;if(g<A){const A=2*e+0;this.__logTopologyWarnings&&-1!=this.edgeFaces[A]&&console.warn("Edge poly 0 already set. Mesh is non-manifold."),this.edgeFaces[A]=C}else{const A=2*e+1;this.__logTopologyWarnings&&-1!=this.edgeFaces[A]&&console.warn("Edge poly 1 already set. Mesh is non-manifold."),this.edgeFaces[A]=C}C in this.faceEdges||(this.faceEdges[C]=[]),this.faceEdges[C].push(e),null==this.vertexEdges[A]&&(this.vertexEdges[A]=new Set),null==this.vertexEdges[g]&&(this.vertexEdges[g]=new Set),this.vertexEdges[A].add(e),this.vertexEdges[g].add(e)},e=this.getNumFaces();for(let A=0;A<e;A++){const g=this.getFaceVertexIndices(A);for(let I=0;I<g.length;I++){C(g[I],g[(I+1)%g.length],A)}}}computeFaceNormals(){const A=this.positions,g=new Vec3f8Attribute;this.addFaceAttribute("normals",g);const I=this.getNumFaces();for(let C=0;C<I;C++){const I=this.getFaceVertexIndices(C),e=A.getValue(I[0]);let i=A.getValue(I[1]);const t=new Vec3;for(let g=2;g<I.length;g++){const C=A.getValue(I[g]),o=i.subtract(e),a=C.subtract(e);t.addInPlace(o.cross(a).normalize()),i=C}t.lengthSquared()<Number.EPSILON||g.setValue(C,t.normalize())}}calculateEdgeAngles(){0==this.vertexEdges.length&&this.genTopologyInfo(),this.computeFaceNormals();const A=this.positions,g=this.getFaceAttribute("normals");this.edgeVecs=[],this.edgeAngles=new Float32Array(this.numEdges);for(let I=0;I<this.edgeFaces.length;I+=2){const C=this.edgeVerts[I],e=this.edgeVerts[I+1],i=A.getValue(e).subtract(A.getValue(C));i.normalizeInPlace(),this.edgeVecs.push(i);const t=this.edgeFaces[I],o=this.edgeFaces[I+1];if(-1==t||-1==o){this.edgeAngles[I/2]=2*Math.PI;continue}const a=g.getValue(t),B=g.getValue(o);this.edgeAngles[I/2]=a.angleTo(B)}}computeVertexNormals(A=1){this.calculateEdgeAngles();const g=this.getFaceAttribute("normals"),I=new Vec3f8Attribute;this.addVertexAttribute("normals",I);const C=(A,g)=>{I.setValue(A,g)},e=(A,g)=>{let I,C;const e=this.faceEdges[A];for(const A of e)(this.edgeVerts[2*A]==g||this.edgeVerts[2*A+1]==g)&&(I?C=this.edgeVecs[A]:I=this.edgeVecs[A]);return[I,C]};for(let t=0;t<this.vertexEdges.length;t++){if(null==this.vertexEdges[t])continue;const o=this.vertexEdges[t],a=[],B=A=>{let g=!1;for(const I of a)if(g=I.includes(A),g)break;g||a.push([A])};for(const g of o){const I=this.edgeFaces[2*g],C=this.edgeFaces[2*g+1];if(-1!=I&&-1!=C&&this.edgeAngles[g]<A){let A=-1,g=-1;for(let e=0;e<a.length;e++)-1==A&&a[e].includes(I)&&(A=e),-1==g&&a[e].includes(C)&&(g=e);-1==A&&-1==g?a.push([I,C]):-1!=A&&-1!=g?A!=g&&(a[A]=a[A].concat(a[g]),a.splice(g,1)):(-1==A&&a[g].push(I),-1==g&&a[A].push(C))}else-1!=I&&B(I),-1!=C&&B(C)}a.sort(((A,g)=>A.length<g.length?1:A.length>g.length?-1:0));let s=!0;for(const A of a){const o=new Vec3;for(const I of A){const A=e(I,t);let C;A[0]&&A[1]?(C=A[0].angleTo(A[1]),o.addInPlace((i=I,g.getValue(i)).scale(C))):console.warn("variable weight is undefined because faceEdges[0] or faceEdges[1] is undefined")}o.normalizeInPlace(),s?(C(t,o),s=!1):I.setSplitVertexValues(t,A,o.asArray())}}var i;return I}computeHardEdgesIndices(A=1){0==this.edgeVerts.length&&this.calculateEdgeAngles();const g=[],I=A=>{g.push(this.edgeVerts[A]),g.push(this.edgeVerts[A+1])};for(let g=0;g<this.edgeAngles.length;g++)this.edgeAngles[g]>A&&I(2*g);return Uint32Array.from(g)}merge(A,g=new Xfo){const I=this.getNumVertices();super.merge(A,g);const C=A.faceVertexIndices,e=new Uint32Array(this.faceVertexIndices.length+C.length),i=A.getFaceCounts();let t=0,o=0,a=0;const B=Math.max(this.faceCounts.length,i.length);for(let A=0;A<B;A++){if(this.faceCounts.length>A){const g=this.faceCounts[A]*(A+3);e.set(this.faceVertexIndices.slice(t,t+g),a),t+=g,a+=g}if(i.length>A){const g=i[A]*(A+3);e.set(C.slice(o,o+g).map((A=>A+I)),a),o+=g,a+=g,this.faceCounts.length==A&&(this.faceCounts[A]=0),this.faceCounts[A]+=i[A]}}this.faceVertexIndices=e}genBuffers(A){const g={};let I=0;for(const[,A]of this.__vertexAttributes){const C=A.getSplits();for(const A in C){A in g||(g[A]={});const e=C[A];for(const C in e){const e=parseInt(C);e in g[A]||(g[A][e]=I,I++)}}}const C=this.positions.getCount(),e=C+I;let i;A&&0==A.includeIndices||(i=this.generateTriangulatedIndices(e,C,g));const t={};for(const[A,C]of this.__vertexAttributes){let e;e=0==I?C.asArray():C.generateSplitValues(g,I);const i=C.stride,o=e.length/i;t[A]={values:e,count:o,dimension:i,normalized:"normals"==A,dataType:C.getDataTypeName()}}return{numVertices:this.numVertices(),numRenderVerts:e,indices:i,attrBuffers:t}}computeNumTriangles(){let A=3,g=0;for(const I of this.faceCounts)g+=I*(A-2),A++;return g}generateTriangulatedIndices(A,g,I){const C=this.computeNumTriangles();let e;e=A<Math.pow(2,8)?new Uint8Array(3*C):A<Math.pow(2,16)?new Uint16Array(3*C):new Uint32Array(3*C);let i=0;const t=function(A,C){A in I&&C in I[A]&&(A=g+I[A][C]),e[i]=A,i++},o=this.getNumFaces();for(let A=0;A<o;A++){const g=this.getFaceVertexIndices(A);for(let I=0;I<g.length;I++)I>=3&&(t(g[0],A),t(g[I-1],A)),t(g[I],A)}return e}readBinary(A,g){super.loadBaseGeomBinary(A,g),this.setFaceCounts(Array.from(A.loadUInt32Array()));const I=this.getNumFaces(),C=A.loadUInt8Array(I,!1),e=A.loadSInt32Vec2(),i=A.loadUInt8();let t;if(1==i)t=A.loadUInt8Array(void 0,!1);else if(2==i)t=A.loadUInt16Array(void 0,!1);else{if(4!=i)throw Error("faceVertexIndexDeltas undefined");t=A.loadUInt32Array(void 0,!1)}let o=3,a=0;const B=this.faceCounts.map(((A,g)=>{const I=a;return a+=A*o,o++,I}));let s=0,l=0;const n=[];for(let A=0;A<I;A++){const g=C[A],I=B[g],i=g+3;n[A]=I;for(let g=0;g<i;g++){const C=I+g,i=t[s+g]+e.x;if(0==A)this.faceVertexIndices[C]=i;else{let I=n[A-1];I+=g<l?g:l-1,this.faceVertexIndices[C]=this.faceVertexIndices[I]+i}}s+=i,B[g]+=i,l=i}this.hasVertexAttribute("normals")||this.computeVertexNormals(),this.emit("geomDataChanged")}toJSON(A){const g=super.toJSON(A);return A&&A.skipTopology||(g.faceCounts=Array.from(this.faceCounts),g.faceVertexIndices=Array.from(this.faceVertexIndices)),g}fromJSON(A,g){super.fromJSON(A,g),A.faceCounts&&(this.faceCounts=A.faceCounts),A.faceVertexIndices&&(this.faceVertexIndices=Uint32Array.from(A.faceVertexIndices))}}Registry.register("Mesh",Mesh);class BaseProxy extends RefCounted{name;buffers;boundingBox;numVertices=0;libraryIndex=-1;constructor(A){super(),A&&(this.name=A.name,this.buffers=A.geomBuffers,this.boundingBox=new Box3,this.boundingBox.p0.fromJSON(A.bbox.p0),this.boundingBox.p1.fromJSON(A.bbox.p1),this.numVertices=this.buffers.numVertices)}get positions(){return this.buffers.attrBuffers.positions}getNumVertices(){return this.numVertices}getBoundingBox(){return this.boundingBox}genBuffers(){return this.buffers}freeBuffers(){for(const A in this.buffers.attrBuffers){this.buffers.attrBuffers[A].values=null}this.buffers.indices&&(this.buffers.indices=null)}toJSON(A){return{geomBuffers:this.buffers}}fromJSON(A,g){this.buffers=A.geomBuffers}copyFrom(A,g){this.buffers={...A.buffers},this.name=A.name,this.boundingBox=A.boundingBox,this.numVertices=this.buffers.numVertices}}class PointsProxy extends BaseProxy{constructor(A){super(A)}}class LinesProxy extends BaseProxy{numLineSegments=0;constructor(A){super(A),A&&(this.numLineSegments=this.buffers.indices.length/2)}getNumLineSegments(){return this.numLineSegments}clone(A){const g=new LinesProxy;return g.copyFrom(this,A),g}copyFrom(A,g){super.copyFrom(A,g),this.numLineSegments=this.buffers.indices.length/2}}class MeshProxy extends BaseProxy{numTriangles=0;constructor(A){super(A),A&&(this.numTriangles=this.buffers.indices.length/3)}getNumTriangles(){return this.numTriangles}clone(A){const g=new MeshProxy;return g.copyFrom(this,A),g}copyFrom(A,g){super.copyFrom(A,g),this.numTriangles=this.buffers.indices.length/3}}class SubGeom extends ParameterOwner{}Registry.register("SubGeom",SubGeom);class CompoundGeom extends BaseProxy{materials=[];subGeoms=[];counts;materialGroupsDirty=!1;constructor(A,g){if(super(A),A){this.counts=A.geomBuffers.counts;const I=g.getMaterials();A.geomBuffers.materialLibraryIndices.forEach(((A,g)=>{this.materials[g]=I[A]})),delete A.geomBuffers.materialLibraryIndices,this.buffers.materials=this.materials}}getNumSubGeoms(){return this.buffers.numSubGeoms}getNumFaces(){return this.buffers.subGeomCounts.TRIANGLES.length}getNumEdges(){return this.buffers.subGeomCounts.LINES.length}getNumTriangles(){return this.counts.TRIANGLES/3}getNumLineSegments(){return this.counts.LINES/2}getNumPoints(){return this.counts.POINTS}getSubGeomMaterial(A){const g=this.buffers.subGeomMaterialIndices[A]-1;if(-1!=g)return this.materials[g]}setSubGeomMaterial(A,g){if(g){let I=this.materials.indexOf(g);if(-1==I&&(I=this.materials.length,this.materials[I]=g),0==this.buffers.subGeomMaterialIndices.length&&(this.buffers.subGeomMaterialIndices=new Uint8Array(this.buffers.numSubGeoms)),this.materials.length>255&&this.buffers.subGeomMaterialIndices instanceof Uint8Array){const A=new Uint16Array(this.buffers.numSubGeoms);for(let g=0;g<this.buffers.subGeomMaterialIndices.length;g++)A[g]=this.buffers.subGeomMaterialIndices[g];this.buffers.subGeomMaterialIndices=A}this.buffers.subGeomMaterialIndices[A]=I+1}else this.buffers.subGeomMaterialIndices&&this.buffers.subGeomMaterialIndices[A]&&(this.buffers.subGeomMaterialIndices[A]=0);this.materialGroupsDirty=!0,this.emit("materialsChanged")}assignSubGeomMaterial(A,g){this.setSubGeomMaterial(A,g)}clearMaterials(){this.materials.splice(0,this.materials.length),this.buffers.subGeomMaterialIndices=this.buffers.subGeomMaterialIndices.map((()=>0)),this.emit("materialsChanged")}calcMaterialGroups(){const A={};if(0==this.buffers.subGeomMaterialIndices.length){this.buffers.materialSubGeoms={};let A=0;for(let g in this.buffers.counts){const I=this.buffers.counts[g];I>0&&(this.buffers.materialSubGeoms[g]=[{materialId:-1,offset:A,count:I}]),A+=I}return}let g=0,I=-99,C=null;for(let e=0;e<this.buffers.numSubGeoms;e++){let i,t=0;e<this.buffers.subGeomCounts.TRIANGLES.length?(A.TRIANGLES||(A.TRIANGLES=[]),i="TRIANGLES"):e<this.buffers.subGeomCounts.TRIANGLES.length+this.buffers.subGeomCounts.LINES.length?(t=this.buffers.subGeomCounts.TRIANGLES.length,i="LINES",A.LINES||(A.LINES=[])):(t=this.buffers.subGeomCounts.TRIANGLES.length+this.buffers.subGeomCounts.LINES.length,i="POINTS",A.POINTS||(A.POINTS=[]));const o=this.buffers.subGeomMaterialIndices[e];if(I!=o){for(I=o,C={materialId:o-1,offset:g,count:0};e<this.buffers.numSubGeoms&&I==this.buffers.subGeomMaterialIndices[e];e++){if(e-t==this.buffers.subGeomCounts[i].length){I=-99;break}C.count+=this.buffers.subGeomCounts[i][e-t]}g+=C.count,A[i].push(C),e--}}this.buffers.materialSubGeoms=A}genBuffers(){return this.materialGroupsDirty&&this.calcMaterialGroups(),this.buffers}toJSON(A){const g={materialPaths:this.materials.map((A=>A.path))};return g}fromJSON(A,g){if(this.counts=A.geomBuffers.counts,A.materialPaths&&g){const I=A.materialPaths;this.materials=[],I.forEach(((A,I)=>{g.resolvePath(A,(A=>{A instanceof Material&&(this.materials[I]=A)}),(()=>{}))}))}this.buffers.materials=this.materials,this.materialGroupsDirty=!0}loadMetadata(A,g){A.loadUInt32Array().forEach(((I,C)=>{const e=new SubGeom;A.seek(I),e.readBinary(A,g),this.subGeoms[C]=e}))}clone(A){const g=new CompoundGeom;return g.copyFrom(this,A),g}copyFrom(A,g){super.copyFrom(A,g),this.buffers={...A.buffers},this.buffers.subGeomMaterialIndices&&(this.buffers.subGeomMaterialIndices=new Uint8Array(this.buffers.numSubGeoms),this.buffers.subGeomMaterialIndices.set(A.buffers.subGeomMaterialIndices)),this.counts=A.counts,this.materials=A.materials,this.buffers.materials=this.materials,this.subGeoms=A.subGeoms,this.libraryIndex=A.libraryIndex}}Registry.register("CompoundGeom",CompoundGeom);class ProceduralPoints extends Points{dirtyTopology;dirtyVertices;topologyParams;constructor(){super(),this.dirtyTopology=!0,this.dirtyVertices=!0,this.topologyParams=[]}parameterValueChanged(A){this.setBoundingBoxDirty(),this.topologyParams.includes(A.param.getName())?(this.dirtyTopology=!0,this.emit("geomDataTopologyChanged")):(this.dirtyVertices=!0,this.setBoundingBoxDirty(),this.emit("geomDataChanged")),super.parameterValueChanged(A)}update(){this.dirtyTopology?(this.rebuild(),this.dirtyTopology=!1,this.dirtyVertices=!1,this.rebuild()):this.dirtyVertices&&(this.dirtyVertices=!1,this.resize(),this.dirtyVertices=!1)}getBoundingBox(){return this.update(),super.getBoundingBox()}getNumVertices(){return this.update(),super.getNumVertices()}genBuffers(A){return this.update(),super.genBuffers(A)}toJSON(A){A||(A={}),A.skipTopology=!0,A.skipAttributes=["positions","normals","texCoords"];const g=super.toJSON(A);return A.skipTopology=!1,A.skipAttributes=[],g}}class ProceduralLines extends Lines{dirtyTopology;dirtyVertices;topologyParams;constructor(){super(),this.dirtyTopology=!0,this.dirtyVertices=!0,this.topologyParams=[]}parameterValueChanged(A){this.setBoundingBoxDirty(),this.topologyParams.includes(A.param.getName())?(this.dirtyTopology=!0,this.emit("geomDataTopologyChanged")):(this.dirtyVertices=!0,this.setBoundingBoxDirty(),this.emit("geomDataChanged")),super.parameterValueChanged(A)}update(){this.dirtyTopology?(this.rebuild(),this.dirtyTopology=!1,this.dirtyVertices=!1,this.rebuild()):this.dirtyVertices&&(this.resize(),this.dirtyVertices=!1,this.resize())}getBoundingBox(){return this.update(),super.getBoundingBox()}getNumVertices(){return this.update(),super.getNumVertices()}genBuffers(A){return this.update(),super.genBuffers()}toJSON(A){A||(A={}),A.skipTopology=!0,A.skipAttributes=["positions","normals","texCoords"];const g=super.toJSON(A);return A.skipTopology=!1,A.skipAttributes=[],g}}class ProceduralMesh extends Mesh{dirtyTopology;dirtyVertices;topologyParams;constructor(){super(),this.dirtyTopology=!0,this.dirtyVertices=!0,this.topologyParams=[]}parameterValueChanged(A){this.setBoundingBoxDirty(),this.topologyParams.includes(A.param.getName())?(this.dirtyTopology=!0,this.emit("geomDataTopologyChanged")):(this.dirtyVertices=!0,this.setBoundingBoxDirty(),this.emit("geomDataChanged")),super.parameterValueChanged(A)}update(){this.dirtyTopology?(this.vertexEdges=[],this.dirtyTopology=!1,this.dirtyVertices=!1,this.rebuild()):this.dirtyVertices&&(this.dirtyVertices=!1,this.resize())}getBoundingBox(){return this.update(),super.getBoundingBox()}getNumVertices(){return this.update(),super.getNumVertices()}computeVertexNormals(A=1){return this.update(),super.computeVertexNormals(A)}computeHardEdgesIndices(A=1){return this.update(),super.computeHardEdgesIndices(A)}genBuffers(A){return this.update(),super.genBuffers(A)}toJSON(A){A||(A={}),A.skipTopology=!0,A.skipAttributes=["positions","normals","texCoords"];const g=super.toJSON(A);return A.skipTopology=!1,A.skipAttributes=[],g}}class PointGrid extends ProceduralPoints{sizeXParam=new NumberParameter("SizeX",1,[0,Number.MAX_VALUE]);sizeYParam=new NumberParameter("SizeY",1,[0,Number.MAX_VALUE]);divisionsXParam=new NumberParameter("XDivisions",1,[0,Number.MAX_VALUE],1);divisionsYParam=new NumberParameter("YDivisions",1,[0,Number.MAX_VALUE],1);constructor(A=1,g=1,I=1,C=1){if(super(),this.topologyParams=[],isNaN(A)||isNaN(g)||isNaN(I)||isNaN(C))throw new Error("Invalid geom args");this.addParameter(this.sizeXParam),this.addParameter(this.sizeYParam),this.addParameter(this.divisionsXParam),this.addParameter(this.divisionsYParam),this.sizeXParam.value=A,this.sizeYParam.value=g,this.divisionsXParam.value=I,this.divisionsYParam.value=C,this.topologyParams.push("XDivisions"),this.topologyParams.push("YDivisions")}rebuild(){const A=Math.round(this.divisionsXParam.value),g=Math.round(this.divisionsYParam.value);this.setNumVertices(A*g);const I=this.getVertexAttribute("texCoords");if(I)for(let C=0;C<g;C++){const e=C/(g-1);for(let g=0;g<A;g++){const i=g/(A-1);I.setValue(C*A+g,new Vec2(i,e))}}this.resize()}resize(){const A=Math.round(this.divisionsXParam.value),g=Math.round(this.divisionsYParam.value),I=this.sizeXParam.value,C=this.sizeYParam.value,e=this.positions;if(e)for(let i=0;i<g;i++){const t=(i/(g-1)-.5)*C;for(let g=0;g<A;g++){const C=(g/(A-1)-.5)*I;e.setValue(i*A+g,new Vec3(C,t,0))}}}}Registry.register("PointGrid",PointGrid);class Rect extends ProceduralLines{sizeXParam=new NumberParameter("SizeX",1,[0,Number.MAX_VALUE]);sizeYParam=new NumberParameter("SizeY",1,[0,Number.MAX_VALUE]);constructor(A=1,g=1){if(super(),isNaN(A)||isNaN(g))throw new Error("Invalid geom args");this.addParameter(this.sizeXParam),this.addParameter(this.sizeYParam),this.sizeXParam.value=A,this.sizeYParam.value=g,this.rebuild()}rebuild(){this.setNumVertices(4),this.setNumSegments(4),this.setSegmentVertexIndices(0,0,1),this.setSegmentVertexIndices(1,1,2),this.setSegmentVertexIndices(2,2,3),this.setSegmentVertexIndices(3,3,0),this.resize(!1)}resize(){const A=this.sizeXParam.value,g=this.sizeYParam.value,I=this.positions;I&&(I.setValue(0,new Vec3(-.5*A,-.5*g,0)),I.setValue(1,new Vec3(.5*A,-.5*g,0)),I.setValue(2,new Vec3(.5*A,.5*g,0)),I.setValue(3,new Vec3(-.5*A,.5*g,0)))}}Registry.register("Rect",Rect);class Circle extends ProceduralLines{angleParam=new AngleParameter("Angle",2*Math.PI,[0,2*Math.PI]);sidesParam=new NumberParameter("Sides",6,[0,Number.MAX_VALUE],1);radiusParam=new NumberParameter("Radius",1,[0,Number.MAX_VALUE]);constructor(A=1,g=32,I=2*Math.PI){if(super(),this.topologyParams=[],isNaN(A)||isNaN(g))throw new Error("Invalid geom args");this.radiusParam.value=A,this.sidesParam.value=g,this.angleParam.value=I,this.addParameter(this.radiusParam),this.addParameter(this.angleParam),this.addParameter(this.sidesParam),this.topologyParams.push("Angle"),this.topologyParams.push("Sides")}rebuild(){const A=this.angleParam.value,g=Math.round(this.sidesParam.value),I=A<2*Math.PI?g+1:g;this.setNumVertices(I),this.setNumSegments(g);for(let A=0;A<g;A++)this.setSegmentVertexIndices(A,A,(A+1)%I);this.resize()}resize(){const A=this.radiusParam.value,g=this.angleParam.value,I=g/(g<2*Math.PI?this.positions.count-1:this.positions.count);for(let g=0;g<this.positions.count;g++)this.positions.setValue(g,new Vec3(Math.cos(I*g)*A,Math.sin(I*g)*A,0))}}Registry.register("Circle",Circle);class Cross extends ProceduralLines{sizeParam=new NumberParameter("Size",1,[0,Number.MAX_VALUE]);constructor(A=1){if(super(),isNaN(A))throw new Error("Invalid geom args");this.addParameter(this.sizeParam),this.sizeParam.value=A}rebuild(){this.setNumVertices(6),this.setNumSegments(3),this.setSegmentVertexIndices(0,0,1),this.setSegmentVertexIndices(1,2,3),this.setSegmentVertexIndices(2,4,5),this.resize()}resize(){const A=this.sizeParam.value,g=this.positions;g&&(g.setValue(0,new Vec3(-.5*A,0,0)),g.setValue(1,new Vec3(.5*A,0,0)),g.setValue(2,new Vec3(0,.5*A,0)),g.setValue(3,new Vec3(0,-.5*A,0)),g.setValue(4,new Vec3(0,0,.5*A)),g.setValue(5,new Vec3(0,0,-.5*A)))}}Registry.register("Cross",Cross);class LinesCuboid extends ProceduralLines{baseZAtZeroParam=new BooleanParameter("BaseZAtZero",!1);sizeXParam=new NumberParameter("SizeX",1,[0,Number.MAX_VALUE]);sizeYParam=new NumberParameter("SizeY",1,[0,Number.MAX_VALUE]);sizeZParam=new NumberParameter("SizeZ",1,[0,Number.MAX_VALUE]);constructor(A=1,g=1,I=1,C=!1){super(),this.addParameter(this.sizeXParam),this.addParameter(this.sizeYParam),this.addParameter(this.sizeZParam),this.addParameter(this.baseZAtZeroParam),this.sizeXParam.value=A,this.sizeYParam.value=g,this.sizeZParam.value=I,this.baseZAtZeroParam.value=C}rebuild(){this.setNumVertices(8),this.setNumSegments(12),this.setSegmentVertexIndices(0,0,1),this.setSegmentVertexIndices(1,1,2),this.setSegmentVertexIndices(2,2,3),this.setSegmentVertexIndices(3,3,0),this.setSegmentVertexIndices(4,4,5),this.setSegmentVertexIndices(5,5,6),this.setSegmentVertexIndices(6,6,7),this.setSegmentVertexIndices(7,7,4),this.setSegmentVertexIndices(8,0,4),this.setSegmentVertexIndices(9,1,5),this.setSegmentVertexIndices(10,2,6),this.setSegmentVertexIndices(11,3,7),this.resize()}resize(){const A=this.sizeXParam.value,g=this.sizeYParam.value,I=this.sizeZParam.value,C=this.baseZAtZeroParam.value,e=this.positions;if(e){let i=.5;C&&(i=1),e.setValue(0,new Vec3(.5*A,-.5*g,i*I)),e.setValue(1,new Vec3(.5*A,.5*g,i*I)),e.setValue(2,new Vec3(-.5*A,.5*g,i*I)),e.setValue(3,new Vec3(-.5*A,-.5*g,i*I)),i=-.5,C&&(i=0),e.setValue(4,new Vec3(.5*A,-.5*g,i*I)),e.setValue(5,new Vec3(.5*A,.5*g,i*I)),e.setValue(6,new Vec3(-.5*A,.5*g,i*I)),e.setValue(7,new Vec3(-.5*A,-.5*g,i*I))}}}Registry.register("LinesCuboid",LinesCuboid);class LinesSphere extends ProceduralLines{radiusParam=new NumberParameter("Radius",6,[0,Number.MAX_VALUE]);sidesParam=new NumberParameter("Sides",12,[0,Number.MAX_VALUE],1);constructor(A=1,g=32){if(super(),this.topologyParams=[],isNaN(A)||isNaN(g))throw new Error("Invalid geom args");this.addParameter(this.radiusParam),this.addParameter(this.sidesParam),this.radiusParam.value=A,this.sidesParam.value=g,this.topologyParams.push("Sides")}rebuild(){const A=this.sidesParam.value;this.setNumVertices(3*A),this.setNumSegments(3*A);const g=g=>{for(let I=0;I<A;I++)this.setSegmentVertexIndices(I+g,I+g,(I+1)%A+g)};g(0),g(A),g(2*A),this.resize()}resize(){const A=this.radiusParam.value,g=this.sidesParam.value,I=2*Math.PI/g,C=this.positions;if(C)for(let e=0;e<g;e++)C.setValue(e,new Vec3(Math.cos(I*e)*A,Math.sin(I*e)*A,0)),C.setValue(e+g,new Vec3(Math.cos(I*e)*A,0,Math.sin(I*e)*A)),C.setValue(e+2*g,new Vec3(0,Math.cos(I*e)*A,Math.sin(I*e)*A))}}Registry.register("LinesSphere",LinesSphere);class LinesCylinder extends ProceduralLines{baseZAtZeroParam=new BooleanParameter("BaseZAtZero",!0);heightParam=new NumberParameter("Height",1,[0,Number.MAX_VALUE]);radiusParam=new NumberParameter("Radius",6,[0,Number.MAX_VALUE]);loopsParam=new NumberParameter("Loops",6,[0,Number.MAX_VALUE],1);sidesParam=new NumberParameter("Sides",12,[0,Number.MAX_VALUE],1);constructor(A=.5,g=1,I=32,C=2,e=!1){if(super(),this.topologyParams=[],isNaN(A)||isNaN(g)||isNaN(I)||isNaN(C))throw new Error("Invalid geom args");this.radiusParam.value=A,this.heightParam.value=g,this.sidesParam.value=I>=3?I:3,this.loopsParam.value=C>=2?C:2,this.baseZAtZeroParam.value=e,this.addParameter(this.radiusParam),this.addParameter(this.heightParam),this.addParameter(this.sidesParam),this.addParameter(this.loopsParam),this.addParameter(this.baseZAtZeroParam),this.topologyParams.push("Sides"),this.topologyParams.push("Loops")}rebuild(){const A=Math.round(this.sidesParam.value),g=Math.round(this.loopsParam.value);let I=A*g,C=A*g+g;this.setNumVertices(I),this.setNumSegments(C);let e=0;for(let I=0;I<g;I++){for(let g=0;g<A;g++){const C=A*I+g,i=A*I+(g+1)%A;this.setSegmentVertexIndices(e++,C,i)}if(I>0){{const g=(I-1)*A,C=I*A;this.setSegmentVertexIndices(e++,g,C)}{const g=(I-1)*A+Math.floor(.5*A),C=I*A+Math.floor(.5*A);this.setSegmentVertexIndices(e++,g,C)}}}this.resize()}resize(){const A=Math.round(this.sidesParam.value),g=Math.round(this.loopsParam.value),I=this.radiusParam.value,C=this.heightParam.value;let e=0,i=.5;this.baseZAtZeroParam.value&&(i=0);const t=this.positions;if(t)for(let o=0;o<g;o++){const a=o/(g-1)*C-C*i;for(let g=0;g<A;g++){const C=g/A*2*Math.PI;t.setValue(e,new Vec3(Math.sin(C)*I,Math.cos(C)*I,a)),e++}}this.dirtyTopology=!1,this.dirtyVertices=!1}}Registry.register("LinesCylinder",LinesCylinder);class Grid extends ProceduralLines{sizeXParam=new NumberParameter("SizeX",1,[0,Number.MAX_VALUE]);sizeYParam=new NumberParameter("SizeY",1,[0,Number.MAX_VALUE]);divisionsXParam=new NumberParameter("XDivisions",1,[0,Number.MAX_VALUE],1);divisionsYParam=new NumberParameter("YDivisions",1,[0,Number.MAX_VALUE],1);skipCenterLinesParam=new BooleanParameter("SkipCenterLines",!1);constructor(A=1,g=1,I=10,C=10,e=!1){if(super(),this.topologyParams=[],isNaN(A)||isNaN(g)||isNaN(I)||isNaN(C))throw new Error("Invalid geom args");this.addParameter(this.sizeXParam),this.addParameter(this.sizeYParam),this.addParameter(this.divisionsXParam),this.addParameter(this.divisionsYParam),this.addParameter(this.skipCenterLinesParam),this.sizeXParam.value=A,this.sizeYParam.value=g,this.divisionsXParam.value=I,this.divisionsYParam.value=C,this.skipCenterLinesParam.value=e,this.topologyParams.push("XDivisions"),this.topologyParams.push("YDivisions"),this.topologyParams.push("SkipCenterLines")}rebuild(){const A=this.divisionsXParam.value,g=this.divisionsYParam.value,I=this.skipCenterLinesParam.value&&A%2==0&&g%2==0;this.setNumVertices(2*(A+g+2-(I?1:0))),this.setNumSegments(A+g+2-(I?1:0));let C=0;for(let g=0;g<=A;g++){if(I&&g==A/2)continue;const e=2*C,i=2*C+1;this.setSegmentVertexIndices(C,e,i),C++}for(let e=0;e<=g;e++){if(I&&e==A/2)continue;const g=2*C,i=2*C+1;this.setSegmentVertexIndices(C,g,i),C++}this.resize()}resize(){const A=this.positions,g=this.divisionsXParam.value,I=this.divisionsYParam.value,C=this.sizeXParam.value,e=this.sizeYParam.value,i=this.skipCenterLinesParam.value&&g%2==0&&I%2==0;let t=0;for(let I=0;I<=g;I++){if(i&&I==g/2)continue;const o=2*t,a=2*t+1,B=(I/g-.5)*C;A&&(A.setValue(o,new Vec3(B,-.5*e,0)),A.setValue(a,new Vec3(B,.5*e,0))),t++}for(let o=0;o<=I;o++){if(i&&o==g/2)continue;const a=2*t,B=2*t+1,s=(o/I-.5)*e;A&&(A.setValue(a,new Vec3(-.5*C,s,0)),A.setValue(B,new Vec3(.5*C,s,0))),t++}}}Registry.register("Grid",Grid);class Cone extends ProceduralMesh{capParam=new BooleanParameter("Cap",!0);detailParam=new NumberParameter("Detail",6,[0,Number.MAX_VALUE],1);heightParam=new NumberParameter("Height",1,[0,Number.MAX_VALUE]);radiusParam=new NumberParameter("Radius",6,[0,Number.MAX_VALUE]);constructor(A=.5,g=1,I=32,C=!0,e=!0,i=!0){if(super(),this.topologyParams=[],isNaN(A)||isNaN(g)||isNaN(I))throw new Error("Invalid geom args");this.radiusParam.value=A,this.heightParam.value=g,this.detailParam.value=I,this.capParam.value=C,this.addParameter(this.radiusParam),this.addParameter(this.heightParam),this.addParameter(this.detailParam),this.addParameter(this.capParam),e&&this.addVertexAttribute("normals",new Vec3f8Attribute),i&&this.addVertexAttribute("texCoords",new Vec2f16Attribute),this.topologyParams.push("Detail"),this.topologyParams.push("Cap")}rebuild(){const A=Math.round(this.detailParam.value),g=this.radiusParam.value,I=this.heightParam.value,C=this.capParam.value;let e=A+1;C&&(e+=1),this.setNumVertices(e);const i=A,t=A+1,o=this.positions;if(o){o.setValue(i,new Vec3(0,0,I));for(let I=0;I<A;I++){const C=-I/A*2*Math.PI;o.setValue(I,new Vec3(g*Math.cos(C),g*Math.sin(C),0))}C&&o.setValue(t,new Vec3(0,0,0))}this.setFaceCounts([A+(C?A:0)]);for(let g=0;g<A;g++){const I=(g+1)%A;this.setFaceVertexIndices(g,[I,g,i])}if(C)for(let g=0;g<A;g++){const I=(g+1)%A;this.setFaceVertexIndices(A+g,[g,I,t])}const a=this.getVertexAttribute("texCoords");if(a){let g=0;for(let I=0;I<A;I++)"setFaceVertexValue"in a&&(a.setFaceVertexValue(g,0,new Vec2((I+1)/A,0)),a.setFaceVertexValue(g,1,new Vec2(I/A,0)),a.setFaceVertexValue(g,2,new Vec2((I+.5)/A,1)));if(C)for(let I=0;I<A;I++)a.setFaceVertexValue(g,0,new Vec2(I/A,0)),a.setFaceVertexValue(g,1,new Vec2((I+1)/A,0)),a.setFaceVertexValue(g,2,new Vec2((I+.5)/A,1)),g++}this.resize()}resize(){const A=Math.round(this.detailParam.value),g=this.radiusParam.value,I=this.heightParam.value,C=A,e=A+1,i=this.positions;if(i){i.setValue(C,new Vec3(0,0,I));for(let I=0;I<A;I++){const C=-I/A*2*Math.PI;i.setValue(I,new Vec3(g*Math.cos(C),g*Math.sin(C),0))}this.capParam.value&&i.setValue(e,new Vec3(0,0,0))}this.dirtyTopology=!1,this.dirtyVertices=!1;this.getVertexAttribute("normals")&&this.computeVertexNormals()}}Registry.register("Cone",Cone);class Cuboid extends ProceduralMesh{baseZAtZeroParam=new BooleanParameter("BaseZAtZero",!1);sizeXParam=new NumberParameter("SizeX",1,[0,Number.MAX_VALUE]);sizeYParam=new NumberParameter("SizeY",1,[0,Number.MAX_VALUE]);sizeZParam=new NumberParameter("SizeZ",1,[0,Number.MAX_VALUE]);constructor(A=1,g=1,I=1,C=!1){if(super(),isNaN(A)||isNaN(g)||isNaN(I))throw new Error("Invalid geom args");this.addParameter(this.sizeXParam),this.addParameter(this.sizeYParam),this.addParameter(this.sizeZParam),this.addParameter(this.baseZAtZeroParam),this.sizeXParam.value=A,this.sizeYParam.value=g,this.sizeZParam.value=I,this.baseZAtZeroParam.value=C,this.setFaceCounts([0,6]),this.setFaceVertexIndices(0,[0,1,2,3]),this.setFaceVertexIndices(1,[7,6,5,4]),this.setFaceVertexIndices(2,[1,0,4,5]),this.setFaceVertexIndices(3,[3,2,6,7]),this.setFaceVertexIndices(4,[0,3,7,4]),this.setFaceVertexIndices(5,[2,1,5,6]),this.setNumVertices(8),this.addVertexAttribute("normals",new Vec3f8Attribute)}rebuild(){const A=this.getVertexAttribute("normals");if(A)for(let g=0;g<6;g++){let I;switch(g){case 0:I=new Vec3(0,0,1);break;case 1:I=new Vec3(0,0,-1);break;case 2:I=new Vec3(1,0,0);break;case 3:I=new Vec3(-1,0,0);break;case 4:I=new Vec3(0,-1,0);break;default:I=new Vec3(0,1,0)}A.setFaceVertexValue(g,0,I),A.setFaceVertexValue(g,1,I),A.setFaceVertexValue(g,2,I),A.setFaceVertexValue(g,3,I)}this.resize()}resize(){const A=this.sizeXParam.value,g=this.sizeYParam.value,I=this.sizeZParam.value,C=this.baseZAtZeroParam.value;let e=.5;const i=this.positions;C&&(e=1),i&&(i.setValue(0,new Vec3(.5*A,-.5*g,e*I)),i.setValue(1,new Vec3(.5*A,.5*g,e*I)),i.setValue(2,new Vec3(-.5*A,.5*g,e*I)),i.setValue(3,new Vec3(-.5*A,-.5*g,e*I)),e=-.5,C&&(e=0),i.setValue(4,new Vec3(.5*A,-.5*g,e*I)),i.setValue(5,new Vec3(.5*A,.5*g,e*I)),i.setValue(6,new Vec3(-.5*A,.5*g,e*I)),i.setValue(7,new Vec3(-.5*A,-.5*g,e*I)))}}Registry.register("Cuboid",Cuboid);class Cylinder extends ProceduralMesh{baseZAtZeroParam=new BooleanParameter("BaseZAtZero",!0);capsParam=new BooleanParameter("Caps",!0);heightParam=new NumberParameter("Height",1,[0,Number.MAX_VALUE]);radiusParam=new NumberParameter("Radius",6,[0,Number.MAX_VALUE]);loopsParam=new NumberParameter("Loops",6,[0,Number.MAX_VALUE],1);sidesParam=new NumberParameter("Sides",12,[0,Number.MAX_VALUE],1);constructor(A=.5,g=1,I=32,C=2,e=!0,i=!1,t=!0,o=!0){if(super(),this.topologyParams=[],isNaN(A)||isNaN(g)||isNaN(I)||isNaN(C))throw new Error("Invalid geom args");this.radiusParam.value=A,this.heightParam.value=g,this.sidesParam.value=I>=3?I:3,this.loopsParam.value=C>=2?C:2,this.capsParam.value=e,this.baseZAtZeroParam.value=i,this.addParameter(this.radiusParam),this.addParameter(this.heightParam),this.addParameter(this.sidesParam),this.addParameter(this.loopsParam),this.addParameter(this.capsParam),this.addParameter(this.baseZAtZeroParam),t&&this.addVertexAttribute("normals",new Vec2f16Attribute),o&&this.addVertexAttribute("texCoords",new Vec3f8Attribute),this.topologyParams.push("Sides"),this.topologyParams.push("Loops"),this.topologyParams.push("Caps")}rebuild(){const A=Math.round(this.sidesParam.value),g=Math.round(this.loopsParam.value),I=this.capsParam.value;let C=A*g;I&&(C+=2),this.setNumVertices(C),I?this.setFaceCounts([2*A,A]):this.setFaceCounts([0,A]);let e=0;if(I){for(let g=0;g<A;g++){const I=C-1,i=g,t=(g+1)%A;this.setFaceVertexIndices(e++,[I,i,t])}for(let I=0;I<A;I++){const i=A*(g-1)+I,t=C-2,o=A*(g-1)+(I+1)%A;this.setFaceVertexIndices(e++,[i,t,o])}}for(let I=0;I<g-1;I++)for(let g=0;g<A;g++){const C=A*I+(g+1)%A,i=A*I+g,t=A*(I+1)+g,o=A*(I+1)+(g+1)%A;this.setFaceVertexIndices(e++,[C,i,t,o])}const i=this.getVertexAttribute("normals");if(i){if(e=0,I){const g=new Vec3(0,0,-1);for(let I=0;I<A;I++)i.setFaceVertexValue(e,0,g),i.setFaceVertexValue(e,1,g),i.setFaceVertexValue(e,2,g),e++;g.set(0,0,1);for(let I=0;I<A;I++)i.setFaceVertexValue(e,0,g),i.setFaceVertexValue(e,1,g),i.setFaceVertexValue(e,2,g),e++}for(let I=0;I<g-1;I++)for(let g=0;g<A;g++){let I=g/A*2*Math.PI;const C=new Vec3(Math.sin(I),Math.cos(I),0);i.setFaceVertexValue(e,0,C),i.setFaceVertexValue(e,1,C),I=(g+1)/A*2*Math.PI;const t=new Vec3(Math.sin(I),Math.cos(I),0);i.setFaceVertexValue(e,2,t),i.setFaceVertexValue(e,3,t),e++}}const t=this.getVertexAttribute("texCoords");if(t){if(e=0,I){for(let g=0;g<A;g++)t.setFaceVertexValue(e,0,new Vec2(g/A,0)),t.setFaceVertexValue(e,1,new Vec2((g+1)/A,0)),t.setFaceVertexValue(e,2,new Vec2((g+.5)/A,1)),e++;for(let g=0;g<A;g++)t.setFaceVertexValue(e,0,new Vec2(g/A,0)),t.setFaceVertexValue(e,1,new Vec2((g+1)/A,0)),t.setFaceVertexValue(e,2,new Vec2((g+.5)/A,1)),e++}for(let g=0;g<A;g++)t.setFaceVertexValue(e,0,new Vec2((g+1)/A,0)),t.setFaceVertexValue(e,2,new Vec2((g+1)/A,1)),t.setFaceVertexValue(e,1,new Vec2(g/A,0)),t.setFaceVertexValue(e,3,new Vec2(g/A,1)),e++}this.resize()}resize(){const A=Math.round(this.sidesParam.value),g=Math.round(this.loopsParam.value),I=this.radiusParam.value,C=this.heightParam.value,e=this.capsParam.value,i=this.baseZAtZeroParam.value;let t=A*g;e&&(t+=2);let o=0,a=.5;i&&(a=0);const B=this.positions;if(B){for(let e=0;e<g;e++){const i=e/(g-1)*C-C*a;for(let g=0;g<A;g++){const C=g/A*2*Math.PI;B.setValue(o,new Vec3(Math.sin(C)*I,Math.cos(C)*I,i)),o++}}e&&(B.setValue(t-1,new Vec3(0,0,C*(i?0:-.5))),B.setValue(t-2,new Vec3(0,0,C*(i?1:.5))))}this.dirtyTopology=!1,this.dirtyVertices=!1;this.getVertexAttribute("normals")&&this.computeVertexNormals()}}Registry.register("Cylinder",Cylinder);class Disc extends ProceduralMesh{radiusParam=new NumberParameter("Radius",6,[0,Number.MAX_VALUE]);sidesParam=new NumberParameter("Sides",12,[0,Number.MAX_VALUE],1);constructor(A=.5,g=32){if(super(),this.topologyParams=[],isNaN(A)||isNaN(g))throw new Error("Invalid geom args");this.addParameter(this.radiusParam),this.addParameter(this.sidesParam),this.radiusParam.value=A,this.sidesParam.value=g,this.addVertexAttribute("texCoords",new Vec2f16Attribute),this.addVertexAttribute("normals",new Vec3f8Attribute),this.topologyParams.push("Sides")}rebuild(){const A=Math.round(this.sidesParam.value);this.setNumVertices(A+1),this.setFaceCounts([A]);const g=this.positions;g&&g.setValue(0,new Vec3(0,0,0));for(let g=0;g<A;g++){const I=g%A+1,C=(g+1)%A+1;this.setFaceVertexIndices(g,[0,I,C])}const I=this.getVertexAttribute("normals");if(I){const g=new Vec3(0,0,1);I.setValue(0,g);for(let C=0;C<A;C++)I.setValue(C+1,g)}const C=this.getVertexAttribute("texCoords");if(C){C.setValue(0,new Vec2(.5,.5));for(let g=0;g<A;g++){const I=g/A*2*Math.PI;C.setValue(g+1,new Vec2(.5*Math.sin(I)+.5,.5*Math.cos(I)+.5))}}this.resize()}resize(){const A=Math.round(this.sidesParam.value),g=this.radiusParam.value,I=this.positions;if(I)for(let C=0;C<A;C++){const e=C/A*2*Math.PI;I.setValue(C+1,new Vec3(Math.sin(e)*g,Math.cos(e)*g,0))}}}Registry.register("Disc",Disc);class Plane extends ProceduralMesh{sizeXParam=new NumberParameter("SizeX",1,[0,Number.MAX_VALUE]);sizeYParam=new NumberParameter("SizeY",1,[0,Number.MAX_VALUE]);detailXParam=new NumberParameter("DetailX",1,[0,Number.MAX_VALUE],1);detailYParam=new NumberParameter("DetailY",1,[0,Number.MAX_VALUE],1);constructor(A=1,g=1,I=1,C=1,e=!0,i=!0){if(super(),this.topologyParams=[],isNaN(A)||isNaN(g)||isNaN(I)||isNaN(C))throw new Error("Invalid geom args");this.addParameter(this.sizeXParam),this.addParameter(this.sizeYParam),this.addParameter(this.detailXParam),this.addParameter(this.detailYParam),this.sizeXParam.value=A,this.sizeYParam.value=g,this.detailXParam.value=I,this.detailYParam.value=C,e&&this.addVertexAttribute("normals",new Vec3f8Attribute),i&&this.addVertexAttribute("texCoords",new Vec2f16Attribute),this.topologyParams.push("DetailX"),this.topologyParams.push("DetailY")}rebuild(){const A=this.detailXParam.value,g=this.detailYParam.value;this.setNumVertices((A+1)*(g+1)),this.setFaceCounts([0,A*g]);let I=0;for(let C=0;C<g;C++)for(let g=0;g<A;g++){const e=(A+1)*(C+1)+g,i=(A+1)*C+g,t=(A+1)*C+(g+1),o=(A+1)*(C+1)+(g+1);this.setFaceVertexIndices(I,[e,i,t,o]),I+=1}let C=0;const e=this.getVertexAttribute("normals");if(e)for(let I=0;I<=g;I++)for(let g=0;g<=A;g++)e.setValue(C,new Vec3(0,0,1)),C++;C=0;const i=this.getVertexAttribute("texCoords");if(i)for(let I=0;I<=g;I++){const e=I/g;for(let g=0;g<=A;g++){const I=g/A;i.setValue(C,new Vec2(I,e)),C++}}this.resize()}resize(){const A=this.sizeXParam.value,g=this.sizeYParam.value,I=this.detailXParam.value,C=this.detailYParam.value,e=this.positions;if(!e)return;let i=0;for(let t=0;t<=C;t++){const o=(t/C-.5)*g;for(let g=0;g<=I;g++){const C=(g/I-.5)*A;e.setValue(i,new Vec3(C,o,0)),i++}}}}Registry.register("Plane",Plane);class Sphere extends ProceduralMesh{radiusParam=new NumberParameter("Radius",1,[0,Number.MAX_VALUE]);sidesParam=new NumberParameter("Sides",12,[0,Number.MAX_VALUE],1);loopsParam=new NumberParameter("Loops",6,[0,Number.MAX_VALUE],1);constructor(A=1,g=12,I=12,C=!0,e=!0){if(super(),isNaN(A)||isNaN(g)||isNaN(I))throw new Error("Invalid geom args");this.addParameter(this.radiusParam),this.addParameter(this.sidesParam),this.addParameter(this.loopsParam),this.radiusParam.value=A,this.sidesParam.value=g,this.loopsParam.value=I,C&&this.addVertexAttribute("normals",new Vec3f8Attribute),e&&this.addVertexAttribute("texCoords",new Vec2f16Attribute),this.topologyParams.push("Sides"),this.topologyParams.push("Loops")}rebuild(){const A=this.radiusParam.value,g=Math.round(this.sidesParam.value),I=Math.round(this.loopsParam.value),C=2+g*I,e=2*g,i=g*I;this.setNumVertices(C),this.setFaceCounts([e,i]);const t=this.positions,o=this.getVertexAttribute("normals"),a=new Vec3(0,0,1);let B=0;if(!t)return;t.setValue(B,new Vec3(0,0,A)),o&&o.setValue(B,new Vec3(0,0,1)),B++;for(let C=0;C<I;C++){const e=(C+1)/(I+1)*Math.PI;for(let I=0;I<g;I++){const C=-I/g*2*Math.PI;a.set(Math.sin(e)*Math.cos(C),Math.sin(e)*Math.sin(C),Math.cos(e)),t.setValue(B,a.scale(A)),o&&o.setValue(B,a),B++}}t.setValue(B,new Vec3(0,0,-A)),o&&o.setValue(B,new Vec3(0,0,-1)),B++;const s=this.getVertexAttribute("texCoords");let l=0;for(let A=0;A<g;A++){const C=0,e=(A+1)%g+1,i=A+1;if(this.setFaceVertexIndices(l,[C,e,i]),s){const C=new Vec2(.5,0),e=new Vec2((A+1)/(g-1),1/(I+1)),i=new Vec2(A/(g-1),1/(I+1));s.setFaceVertexValue(l,0,C),s.setFaceVertexValue(l,1,e),s.setFaceVertexValue(l,2,i)}l++}for(let A=0;A<g;A++){const e=C-1,i=g*(I-1)+(A+1)%g+1,t=g*(I-1)+A+1;if(this.setFaceVertexIndices(l,[e,t,i]),s){const C=new Vec2(.5,1),e=new Vec2((A+1)/(g-1),1-1/(I+1)),i=new Vec2(A/(g-1),1-1/(I+1));s.setFaceVertexValue(l,0,C),s.setFaceVertexValue(l,1,e),s.setFaceVertexValue(l,2,i)}l++}for(let A=0;A<I-1;A++)for(let C=0;C<g;C++){const e=g*A+C+1,i=g*A+(C+1)%g+1,t=g*(A+1)+(C+1)%g+1,o=g*(A+1)+C+1;this.setFaceVertexIndices(l,[e,i,t,o]),s&&(s.setFaceVertexValue(l,0,new Vec2(C/g,(A+1)/I)),s.setFaceVertexValue(l,1,new Vec2((C+1)/g,(A+1)/I)),s.setFaceVertexValue(l,2,new Vec2((C+1)/g,(A+2)/I)),s.setFaceVertexValue(l,3,new Vec2(C/g,(A+2)/I))),l++}}resize(){const A=this.radiusParam.value,g=Math.round(this.sidesParam.value),I=Math.round(this.loopsParam.value);if(!g||!I)return void console.warn("resize() failed");const C=this.positions,e=this.getVertexAttribute("normals");let i=0;const t=new Vec3(0,0,1);C.setValue(i,new Vec3(0,0,A)),e&&e.setValue(i,new Vec3(0,0,1)),i++;for(let o=0;o<I;o++){const a=(o+1)/(I+1)*Math.PI;for(let I=0;I<g;I++){const o=-I/g*2*Math.PI;t.set(Math.sin(a)*Math.cos(o),Math.sin(a)*Math.sin(o),Math.cos(a)),C.setValue(i,t.scale(A)),e&&e.setValue(i,t),i++}}C.setValue(i,new Vec3(0,0,-A)),e&&e.setValue(i,new Vec3(0,0,-1)),i++}}Registry.register("Sphere",Sphere);class Torus extends ProceduralMesh{innerRadiusParam=new NumberParameter("InnerRadius",1,[0,Number.MAX_VALUE]);outerRadiusParam=new NumberParameter("OuterRadius",1,[0,Number.MAX_VALUE]);arcAngleParam=new AngleParameter("ArcAngle",2*Math.PI,[0,2*Math.PI]);detailParam=new NumberParameter("Detail",12,[0,Number.MAX_VALUE],1);constructor(A=.5,g=3,I=32,C=2*Math.PI){if(super(),isNaN(A)||isNaN(g)||isNaN(I))throw new Error("Invalid geom args");this.addParameter(this.innerRadiusParam),this.addParameter(this.outerRadiusParam),this.addParameter(this.arcAngleParam),this.addParameter(this.detailParam),this.innerRadiusParam.value=A,this.outerRadiusParam.value=g,this.detailParam.value=I>=3?I:33,this.arcAngleParam.value=C,this.addVertexAttribute("texCoords",new Vec2f16Attribute),this.addVertexAttribute("normals",new Vec3f8Attribute),this.topologyParams.push("Detail"),this.topologyParams.push("ArcAngle")}rebuild(){const A=this.arcAngleParam.value<2*Math.PI,g=Math.round(this.detailParam.value),I=g,C=2*g+(A?1:0),e=I*C;this.setNumVertices(e),this.setFaceCounts([0,I*C]);const i=this.getVertexAttribute("texCoords");if(i){let g=0;for(let e=0;e<(A?C-1:C);e++)for(let A=0;A<I;A++){const t=(e+1)%C,o=(A+1)%I,a=I*e+A,B=I*e+o,s=I*t+o,l=I*t+A;this.setFaceVertexIndices(g,[a,B,s,l]),i.setFaceVertexValue(g,0,new Vec2(e/C,A/C)),i.setFaceVertexValue(g,1,new Vec2(e/C,(A+1)/C)),i.setFaceVertexValue(g,2,new Vec2((e+1)/C,(A+1)/C)),i.setFaceVertexValue(g,3,new Vec2((e+1)/C,A/C)),g++}}this.resize()}resize(){const A=this.innerRadiusParam.value,g=this.outerRadiusParam.value,I=this.arcAngleParam.value,C=Math.round(this.detailParam.value),e=I<2*Math.PI,i=C,t=2*C+(e?1:0),o=this.positions,a=this.getVertexAttribute("normals");if(!o||!a)return;let B=0;for(let C=0;C<t;C++){const s=-C/(e?t-1:t)*I,l=Math.cos(s),n=Math.sin(s);for(let I=0;I<i;I++){const C=I/i*2*Math.PI,e=Math.sin(C),t=Math.cos(C),s=g+t*A;o.setValue(B,new Vec3(l*s,n*s,A*e)),a.setValue(B,new Vec3(l*t,n*t,e)),B++}}}}Registry.register("Torus",Torus);class GeometryParameter extends Parameter{listenerIDs={};constructor(A="",g=null){super(A,null,"Geometry"),g&&this.setValue(g)}emitBoundingBoxDirtied(A){this.emit("boundingBoxChanged",A)}setValue(A){if(!(null==A||A instanceof BaseGeom||A instanceof BaseProxy))throw new Error("value provided is not an instance of a 'BaseGeom' or 'BaseProxy' class. Check the source of this value");this.value!==A&&(this.value&&(this.value instanceof BaseGeom?this.value.setOwner(null):this.value instanceof BaseProxy&&this.value.removeRef(this),this.value.off("boundingBoxChanged",this.listenerIDs.boundingBoxChanged)),super.setValue(A),this.value instanceof BaseGeom?this.value.setOwner(this):this.value instanceof BaseProxy&&this.value.addRef(this),this.listenerIDs.boundingBoxChanged=this.value.on("boundingBoxChanged",(A=>{this.emitBoundingBoxDirtied(A)})))}loadValue(A){this.setValue(A)}toJSON(A){const g={type:this.getClassName(),name:this.name},I=this.value;return I instanceof BaseProxy?g.libraryIndex=I.libraryIndex:g.value=I?.toJSON(A),g}fromJSON(A,g){if(A.name&&(this.name=A.name),null!=A.libraryIndex){const I=g.assetItem.geomLibrary.getGeom(A.libraryIndex);this.setValue(I)}else if(null!=A.value)if(this.value&&this.value.getClassName()==A.value.type)this.value.fromJSON(A.value,g),this.emit("valueChanged");else{const I=Registry.constructClass(A.value.type);I.fromJSON(A.value,g),this.setValue(I)}}clone(){return new GeometryParameter(this.name,this.value)}}Registry.register("GeometryParameter",GeometryParameter);class DataImage extends BaseImage{__data=new Uint8Array(4);constructor(A){super(A),this.format="RGBA",this.type="UNSIGNED_BYTE",this.width=1,this.height=1}isLoaded(){return this.loaded}isStream(){return!1}setData(A,g,I){this.__data!=I&&(this.width=A,this.height=g,this.__data=I,this.loaded?this.emit("updated"):(this.loaded=!0,this.emit("loaded")))}getParams(){const A=super.getParams();return A.data=this.__data,A}}Registry.register("DataImage2D",DataImage),Registry.register("DataImage",DataImage);const imageDataLibrary$1={};class FileImage extends BaseImage{crossOrigin;url;__data=null;constructor(A,g="",I={}){super(A),this.type="UNSIGNED_BYTE",this.crossOrigin="anonymous",g&&""!=g&&this.load(g)}setCrossOrigin(A){this.crossOrigin=A}getDOMElement(){return this.__data}load(A,g="RGB"){return new Promise(((I,C)=>{if(!g){const I=A.lastIndexOf(".");if(-1!=I){".png"==A.substring(I).toLowerCase()&&(g="RGBA")}}this.format=g,this.loaded=!1;const e=()=>{this.url=A,this.width=this.__data.width,this.height=this.__data.height,this.loaded=!0,this.emit("loaded"),I()};A in imageDataLibrary$1?(this.__data=imageDataLibrary$1[A],this.__data.complete?e():(this.__data.addEventListener("load",e),this.__data.addEventListener("error",C))):(this.__data=new Image,this.__data.crossOrigin=this.crossOrigin,this.__data.src=A,this.__data.addEventListener("load",e),this.__data.addEventListener("error",C),imageDataLibrary$1[A]=this.__data)}))}setImageURL(A,g="RGB"){this.load(A,g)}getParams(){const A=super.getParams();return this.loaded&&(A.data=this.__data),A}readBinary(A,g){this.setName(A.loadStr());const I=A.loadStr();if("string"==typeof I&&""!=I){const A=g.url.substring(0,g.url.lastIndexOf("/"));this.load(A+"/"+I)}}}class FileImage2D extends FileImage{constructor(A,g={}){console.warn("FileImage2D is becoming deprecated in favor of simple FileImage"),super(A,g)}}Registry.register("FileImage2D",FileImage),Registry.register("FileImage",FileImage);class LDRImage extends FileImage{constructor(A,g,I){super(A,g,I)}}Registry.register("LDRImage",LDRImage);class HDRImage extends BaseImage{exposure=1;hdrTint=new Color(1,1,1,1);__data;constructor(A,g={}){let I;super(A),null!=A&&A.includes(".")&&(I=A,this.setName(A.substring(A.lastIndexOf("/")+1,A.lastIndexOf(".")))),this.type="HDR",I&&this.load(I)}__decodeData(A){return new Promise(((g,I)=>{const C=A.ldr,e=A.cdm,i=new Blob([C.buffer]),t=new Image;t.onload=()=>{this.width=t.width,this.height=t.height,this.__data={ldr:t,cdm:e},this.loaded?this.emit("updated"):(this.loaded=!0,this.emit("loaded")),g()},t.src=URL.createObjectURL(i)}))}load(A){return this.loaded=!1,new Promise(((g,I)=>{const C=A.lastIndexOf("/")>-1?A.substring(A.lastIndexOf("/")+1):"",e=C.substring(0,C.lastIndexOf("."));""==this.getName()&&this.setName(e),this.type="FLOAT",resourceLoader.loadFile("archive",A).then((A=>{if(!A.ldr||!A.cdm)for(const g in A)g.endsWith(".jpg")?(A.ldr=A[g],delete A[g]):g.endsWith(".bin")&&(A.cdm=A[g],delete A[g]);this.__decodeData(A).then((()=>{g()}))}),(A=>{this.emit("error",A),I(A)}))}))}isStream(){return!1}getParams(){const A=super.getParams();return this.loaded&&(A.data=this.__data,A.exposure=this.exposure),A}setHDRTint(A){this.hdrTint=A}getHDRTint(){return this.hdrTint}readBinary(A,g){this.setName(A.loadStr());let I=A.loadStr();"string"==typeof I&&""!=I&&this.load(I)}}Registry.register("HDRImage",HDRImage);class LDRVideo extends FileImage{videoElem=new HTMLVideoElement;muteParam=new BooleanParameter("Mute",!1);loopParam=new BooleanParameter("Loop",!0);spatializeAudioParam=new BooleanParameter("SpatializeAudio",!0);refDistanceParam=new NumberParameter("refDistance",2);maxDistanceParam=new NumberParameter("maxDistance",1e4);rolloffFactorParam=new NumberParameter("rolloffFactor",1);coneInnerAngleParam=new NumberParameter("coneInnerAngle",360);coneOuterAngleParam=new NumberParameter("coneOuterAngle",0);coneOuterGainParam=new NumberParameter("coneOuterGain",1);gainParam=new NumberParameter("Gain",2);constructor(A,g,I){super(A,g,I),this.format="RGB",this.type="UNSIGNED_BYTE",this.addParameter(this.muteParam),this.addParameter(this.loopParam),this.addParameter(this.spatializeAudioParam),this.addParameter(this.refDistanceParam),this.addParameter(this.maxDistanceParam),this.addParameter(this.rolloffFactorParam),this.addParameter(this.coneInnerAngleParam),this.addParameter(this.coneOuterAngleParam),this.addParameter(this.coneOuterGainParam),this.addParameter(this.gainParam).setRange([0,5])}getAudioSource(){return this.videoElem}load(A,g="RGB"){return new Promise(((g,I)=>{resourceLoader.incrementWorkload(1),this.videoElem.style.display="none",this.videoElem.preload="auto",this.videoElem.crossOrigin="anonymous",document.body.appendChild(this.videoElem),this.videoElem.addEventListener("loadedmetadata",(()=>{this.videoElem.muted=this.muteParam.value,this.muteParam.on("valueChanged",(()=>{this.videoElem.muted=this.muteParam.value})),this.videoElem.loop=this.loopParam.value,this.loopParam.on("valueChanged",(()=>{this.videoElem.loop=this.loopParam.value})),this.width=this.videoElem.videoHeight,this.height=this.videoElem.videoWidth,this.loaded=!0,resourceLoader.incrementWorkDone(1),this.emit("loaded"),g(C);let A=0;const I=()=>{if(this.videoElem.paused||this.videoElem.ended)return;const g=Math.floor(29.97*this.videoElem.currentTime);A!=g&&(this.emit("updated"),A=g),setTimeout(I,20)};I()}),!1),this.videoElem.src=A;const C=this.videoElem.play();void 0!==C&&C.then((A=>{console.log("Autoplay started!")})).catch((()=>{console.log("Autoplay was prevented.")}))}))}getParams(){const A=super.getParams();return this.loaded&&(A.data=this.videoElem),A}}function ByteStream(A){this.data=A,this.pos=0}function DataParser(A){this.stream=new ByteStream(A),this.output={}}function bitsToNum(A){return A.reduce((function(A,g){return 2*A+g}),0)}Registry.register("LDRVideo",LDRVideo),ByteStream.prototype.readByte=function(){return this.data[this.pos++]},ByteStream.prototype.peekByte=function(){return this.data[this.pos]},ByteStream.prototype.readBytes=function(A){for(var g=new Array(A),I=0;I<A;I++)g[I]=this.readByte();return g},ByteStream.prototype.peekBytes=function(A){for(var g=new Array(A),I=0;I<A;I++)g[I]=this.data[this.pos+I];return g},ByteStream.prototype.readString=function(A){for(var g="",I=0;I<A;I++)g+=String.fromCharCode(this.readByte());return g},ByteStream.prototype.readBitArray=function(){for(var A=[],g=this.readByte(),I=7;I>=0;I--)A.push(!!(g&1<<I));return A},ByteStream.prototype.readUnsigned=function(A){var g=this.readBytes(2);return A?(g[1]<<8)+g[0]:(g[0]<<8)+g[1]},DataParser.prototype.parse=function(A){return this.parseParts(this.output,A),this.output},DataParser.prototype.parseParts=function(A,g){for(var I=0;I<g.length;I++){var C=g[I];this.parsePart(A,C)}},DataParser.prototype.parsePart=function(A,g){var I,C=g.label;if(!g.requires||g.requires(this.stream,this.output,A))if(g.loop){for(var e=[];g.loop(this.stream);){var i={};this.parseParts(i,g.parts),e.push(i)}A[C]=e}else g.parts?(I={},this.parseParts(I,g.parts),A[C]=I):g.parser?(I=g.parser(this.stream,this.output,A),g.skip||(A[C]=I)):g.bits&&(A[C]=this.parseBits(g.bits))},DataParser.prototype.parseBits=function(A){var g={},I=this.stream.readBitArray();for(var C in A){var e=A[C];e.length?g[C]=bitsToNum(I.slice(e.index,e.index+e.length)):g[C]=I[e.index]}return g};var Parsers={readByte:function(){return function(A){return A.readByte()}},readBytes:function(A){return function(g){return g.readBytes(A)}},readString:function(A){return function(g){return g.readString(A)}},readUnsigned:function(A){return function(g){return g.readUnsigned(A)}},readArray:function(A,g){return function(I,C,e){for(var i=g(I,C,e),t=new Array(i),o=0;o<i;o++)t[o]=I.readBytes(A);return t}}},subBlocks={label:"blocks",parser:function(A){for(var g=[],I=A.readByte();0!==I;I=A.readByte())g=g.concat(A.readBytes(I));return g}},gce={label:"gce",requires:function(A){var g=A.peekBytes(2);return 33===g[0]&&249===g[1]},parts:[{label:"codes",parser:Parsers.readBytes(2),skip:!0},{label:"byteSize",parser:Parsers.readByte()},{label:"extras",bits:{future:{index:0,length:3},disposal:{index:3,length:3},userInput:{index:6},transparentColorGiven:{index:7}}},{label:"delay",parser:Parsers.readUnsigned(!0)},{label:"transparentColorIndex",parser:Parsers.readByte()},{label:"terminator",parser:Parsers.readByte(),skip:!0}]},image={label:"image",requires:function(A){return 44===A.peekByte()},parts:[{label:"code",parser:Parsers.readByte(),skip:!0},{label:"descriptor",parts:[{label:"left",parser:Parsers.readUnsigned(!0)},{label:"top",parser:Parsers.readUnsigned(!0)},{label:"width",parser:Parsers.readUnsigned(!0)},{label:"height",parser:Parsers.readUnsigned(!0)},{label:"lct",bits:{exists:{index:0},interlaced:{index:1},sort:{index:2},future:{index:3,length:2},size:{index:5,length:3}}}]},{label:"lct",requires:function(A,g,I){return I.descriptor.lct.exists},parser:Parsers.readArray(3,(function(A,g,I){return Math.pow(2,I.descriptor.lct.size+1)}))},{label:"data",parts:[{label:"minCodeSize",parser:Parsers.readByte()},subBlocks]}]},text={label:"text",requires:function(A){var g=A.peekBytes(2);return 33===g[0]&&1===g[1]},parts:[{label:"codes",parser:Parsers.readBytes(2),skip:!0},{label:"blockSize",parser:Parsers.readByte()},{label:"preData",parser:function(A,g,I){return A.readBytes(I.text.blockSize)}},subBlocks]},application={label:"application",requires:function(A,g,I){var C=A.peekBytes(2);return 33===C[0]&&255===C[1]},parts:[{label:"codes",parser:Parsers.readBytes(2),skip:!0},{label:"blockSize",parser:Parsers.readByte()},{label:"id",parser:function(A,g,I){return A.readString(I.blockSize)}},subBlocks]},comment={label:"comment",requires:function(A,g,I){var C=A.peekBytes(2);return 33===C[0]&&254===C[1]},parts:[{label:"codes",parser:Parsers.readBytes(2),skip:!0},subBlocks]},frames={label:"frames",parts:[gce,application,comment,image,text],loop:function(A){var g=A.peekByte();return 33===g||44===g}},schemaGIF=[{label:"header",parts:[{label:"signature",parser:Parsers.readString(3)},{label:"version",parser:Parsers.readString(3)}]},{label:"lsd",parts:[{label:"width",parser:Parsers.readUnsigned(!0)},{label:"height",parser:Parsers.readUnsigned(!0)},{label:"gct",bits:{exists:{index:0},resolution:{index:1,length:3},sort:{index:4},size:{index:5,length:3}}},{label:"backgroundColorIndex",parser:Parsers.readByte()},{label:"pixelAspectRatio",parser:Parsers.readByte()}]},{label:"gct",requires:function(A,g){return g.lsd.gct.exists},parser:Parsers.readArray(3,(function(A,g){return Math.pow(2,g.lsd.gct.size+1)}))},frames],gifSchema=schemaGIF;function GIF(A){var g=new DataParser(new Uint8Array(A));this.raw=g.parse(gifSchema),this.raw.hasImages=!1;for(var I=0;I<this.raw.frames.length;I++)if(this.raw.frames[I].image){this.raw.hasImages=!0;break}}GIF.prototype.decompressFrame=function(A,g){if(A>=this.raw.frames.length)return null;var I=this.raw.frames[A];if(I.image){var C=I.image.descriptor.width*I.image.descriptor.height,e=function(A,g,I){var C,e,i,t,o,a,B,s,l,n,d,r,c,h,G,m,b=4096,Z=-1,u=I,y=new Array(I),E=new Array(b),Q=new Array(b),V=new Array(b+1);for(o=(e=1<<(r=A))+1,C=e+2,B=Z,i=(1<<(t=r+1))-1,l=0;l<e;l++)E[l]=0,Q[l]=l;for(d=s=c=h=m=G=0,n=0;n<u;){if(0===h){if(s<t){d+=g[G]<<s,s+=8,G++;continue}if(l=d&i,d>>=t,s-=t,l>C||l==o)break;if(l==e){i=(1<<(t=r+1))-1,C=e+2,B=Z;continue}if(B==Z){V[h++]=Q[l],B=l,c=l;continue}for(a=l,l==C&&(V[h++]=c,l=B);l>e;)V[h++]=Q[l],l=E[l];c=255&Q[l],V[h++]=c,C<b&&(E[C]=B,Q[C]=c,!(++C&i)&&C<b&&(t++,i+=C)),B=a}h--,y[m++]=V[h],n++}for(n=m;n<u;n++)y[n]=0;return y}(I.image.data.minCodeSize,I.image.data.blocks,C);I.image.descriptor.lct.interlaced&&(e=function(A,g){for(var I=new Array(A.length),C=A.length/g,e=function(C,e){var i=A.slice(e*g,(e+1)*g);I.splice.apply(I,[C*g,g].concat(i))},i=[0,4,2,1],t=[8,8,4,2],o=0,a=0;a<4;a++)for(var B=i[a];B<C;B+=t[a])e(B,o),o++;return I}(e,I.image.descriptor.width));var i={pixels:e,dims:{top:I.image.descriptor.top,left:I.image.descriptor.left,width:I.image.descriptor.width,height:I.image.descriptor.height}};return I.image.descriptor.lct&&I.image.descriptor.lct.exists?i.colorTable=I.image.lct:i.colorTable=this.raw.gct,I.gce&&(i.delay=10*(I.gce.delay||10),i.disposalType=I.gce.extras.disposal,I.gce.extras.transparentColorGiven&&(i.transparentIndex=I.gce.transparentColorIndex)),g&&(i.patch=function(A){for(var g=A.pixels.length,I=new Uint8ClampedArray(4*g),C=0;C<g;C++){var e=4*C,i=A.pixels[C],t=A.colorTable[i];I[e]=t[0],I[e+1]=t[1],I[e+2]=t[2],I[e+3]=i!==A.transparentIndex?255:0}return I}(i)),i}return null},GIF.prototype.decompressFrames=function(A){for(var g=[],I=0;I<this.raw.frames.length;I++){this.raw.frames[I].image&&g.push(this.decompressFrame(I,A))}return g};const imageDataLibrary={};class GIFImage extends FileImage{__streamAtlas;play;stop;__resourcePromise;__unpackedData;streamAtlasDescParam=new Vec4Parameter("StreamAtlasDesc");streamAtlasIndexParam=new NumberParameter("StreamAtlasIndex",0);constructor(A,g="",I={}){super(A,g,I),this.format="RGBA",this.type="UNSIGNED_BYTE",this.__streamAtlas=!0,this.addParameter(this.streamAtlasDescParam),this.addParameter(this.streamAtlasIndexParam);const C=this.streamAtlasIndexParam;let e;C.setRange([0,1]);let i=0;const t=A=>{C.value=i,e&&setTimeout((()=>t(A)),this.getFrameDelay(i)),i=(i+1)%A};this.play=()=>{this.__resourcePromise.then((()=>{e=!0;let A=C.getRange();if(!A)return void console.warn("numFrames is null");const g=A[1];t(g)}))},this.stop=()=>{e=!1}}getFrameDelay(A){return 10*this.__unpackedData.frameDelays[A]}load(A,g="RGB"){return A in imageDataLibrary?(this.__resourcePromise=imageDataLibrary[A],this.__resourcePromise):(this.__resourcePromise=new Promise(((g,I)=>{resourceLoader.incrementWorkload(1),loadBinfile(A,(I=>{console.warn("Unpacking Gif client side:"+A);const C=performance.now(),e=new GIF(I).decompressFrames(!0),i=Math.sqrt(e.length),t=[i,i];MathFunctions.fract(i)>0&&(t[0]=Math.floor(t[0]+1),MathFunctions.fract(i)>.5?t[1]=Math.floor(t[1]+1):t[1]=Math.floor(t[1]));const o=e[0].dims.width,a=e[0].dims.height,B=document.createElement("canvas"),s=B.getContext("2d"),l=document.createElement("canvas"),n=l.getContext("2d");l.width=o,l.height=a;const d=document.createElement("canvas"),r=d.getContext("2d");let c;d.width=t[0]*o,d.height=t[1]*a;const h=[],G=(A,g)=>{const I=A.dims;h.push(A.delay/10),c&&I.width==c.width&&I.height==c.height||(B.width=I.width,B.height=I.height,c=s?.createImageData(I.width,I.height)),c.data.set(A.patch),s?.putImageData(c,0,0),2==A.disposalType&&n?.clearRect(0,0,l.width,l.height),n?.drawImage(B,I.left,I.top),r?.drawImage(l,g%t[0]*o,Math.floor(g/t[0])*a)};for(let A=0;A<e.length;A++)G(e[A],A);resourceLoader.incrementWorkDone(1);const m=r?.getImageData(0,0,d.width,d.height),b=performance.now()-C;console.log(`Decode GIF '${A}' time:`+b),g({width:d.width,height:d.height,atlasSize:t,frameRange:[0,e.length],frameDelays:h,imageData:m})}),(g=>{const C="Unable to Load URL:"+g+":"+A;console.warn(C),I(C)}))})),imageDataLibrary[A]=this.__resourcePromise,this.__resourcePromise.then((A=>{this.width=A.width,this.height=A.height,this.streamAtlasDescParam.value=new Vec4(A.atlasSize[0],A.atlasSize[1],0,0),this.streamAtlasIndexParam.setRange(A.frameRange),this.__unpackedData=A,this.__data=A.imageData,this.loaded=!0,this.emit("loaded")})),this.__resourcePromise)}}Registry.register("GIFImage",GIFImage);class EnvMap extends HDRImage{utf8decoder;shCoeffs;luminanceData;headlightModeParam=new BooleanParameter("HeadLightMode",!1);constructor(A,g={}){super(A,g),this.addParameter(this.headlightModeParam),this.utf8decoder=new TextDecoder,this.shCoeffs=[]}__decodeData(A){const g=A.samples;if(g&&(this.luminanceData=JSON.parse(this.utf8decoder.decode(g)),this.luminanceData.shCoeffs))for(let A=0;A<9;A++)this.shCoeffs[A]=new Color(this.luminanceData.shCoeffs[3*A+0],this.luminanceData.shCoeffs[3*A+1],this.luminanceData.shCoeffs[3*A+2]);return super.__decodeData(A)}dirToLuminance(A){const g=A.x,I=A.y,C=A.z,e=this.shCoeffs[0].scale(.886227);return e.addInPlace(this.shCoeffs[1].scale(1.023328*I)),e.addInPlace(this.shCoeffs[2].scale(1.023328*C)),e.addInPlace(this.shCoeffs[3].scale(1.023328*g)),e.addInPlace(this.shCoeffs[4].scale(.858086*g*I)),e.addInPlace(this.shCoeffs[5].scale(.858086*I*C)),e.addInPlace(this.shCoeffs[6].scale(.743125*C*C-.247708)),e.addInPlace(this.shCoeffs[7].scale(.858086*g*C)),e.addInPlace(this.shCoeffs[8].scale(.429043*(g*g-I*I))),e.luminance()}}function getLanguage(){if("Node"==SystemDesc.OS)return"en";const A=new URLSearchParams(globalThis.location.search);if(A.has("lang"))return A.get("lang");const g=globalThis.navigator;let I,C;const e=A=>A.startsWith("en")?"En":A.startsWith("es")?"Es":A.startsWith("fr")?"Fr":A.startsWith("gb")||A.startsWith("de")?"Gb":A;if(Array.isArray(g.languages))for(I=0;I<g.languages.length;I++)if(C=g.languages[I],C&&C.length)return e(C);return null}Registry.register("EnvMap",EnvMap);class LabelManager extends EventEmitter{__language;__foundLabelLibraries;__labelLibraries;constructor(){super(),this.__labelLibraries={},this.__language=getLanguage(),this.__foundLabelLibraries={}}loadLibrary(A,g){const I=A.substring(0,A.lastIndexOf("."));if(this.__foundLabelLibraries[I]=g,A.endsWith(".labels"))loadTextfile(g,(A=>{this.__labelLibraries[I]=JSON.parse(A),this.emit("labelLibraryLoaded",{library:I})}));else if(A.endsWith(".xlsx")){const A=globalThis.XLSX;loadBinfile(g,(g=>{const C=new Uint8Array(g),e=A.read(C,{type:"array"}),i={};e.SheetNames.forEach((function(g){A.utils.sheet_to_json(e.Sheets[g],{}).forEach((function(A){const g=A.Identifier;delete A.Identifier,i[g]=A}))})),this.__labelLibraries[I]=i,this.emit("labelLibraryLoaded",{library:I})}))}}isLibraryFound(A){return A in this.__foundLabelLibraries}isLibraryLoaded(A){return A in this.__labelLibraries}getLabelText(A,g){const I=this.__labelLibraries[A];if(!I)throw new Error("LabelLibrary: '"+A+"' not found in LabelManager. Found: ["+Object.keys(this.__labelLibraries)+"]");const C=I[g];if(!C)throw new Error("Label: '"+g+"' not found in LabelLibrary: '"+A+"'. Found: ["+Object.keys(I)+"]");const e=C[this.__language];if(!e){if(C.En)return C.En;throw new Error("labelText: '"+this.__language+"' not found in Label. Found: ["+Object.keys(C)+"]")}return e}setLabelText(A,g,I){let C=this.__labelLibraries[A];C||(C={},this.__labelLibraries[A]=C);let e=C[g];e||(e={},C[g]=e),e[this.__language]=I}setLanguage(A){this.__language=A}}const labelManager=new LabelManager;function roundRect(A,g,I,C,e,i,t=!1,o=!0,a){if(void 0===o&&(o=!0),void 0===i&&(i=5),"number"==typeof i)i={tl:i,tr:i,br:i,bl:i};else{const A={tl:0,tr:0,br:0,bl:0};for(const g in A)i[g]=i[g]||A[g]}A.beginPath(),A.moveTo(g+i.tl,I),A.lineTo(g+C-i.tr,I),A.quadraticCurveTo(g+C,I,g+C,I+i.tr),A.lineTo(g+C,I+e-i.br),A.quadraticCurveTo(g+C,I+e,g+C-i.br,I+e),A.lineTo(g+i.bl,I+e),A.quadraticCurveTo(g,I+e,g,I+e-i.bl),A.lineTo(g,I+i.tl),A.quadraticCurveTo(g,I,g+i.tl,I),A.closePath(),t&&A.fill(),o&&(A.lineWidth=a,A.stroke())}class Label extends DataImage{needsRender;canvasElem;requestedReRender=!1;marginParam;borderRadiusParam;libraryParam=new StringParameter("Library");textParam=new StringParameter("Text","");fontColorParam=new ColorParameter("FontColor",new Color(0,0,0));fontSizeParam=new NumberParameter("FontSize",22);fontParam=new StringParameter("Font","Helvetica");borderWidthParam=new NumberParameter("BorderWidth",2);outlineParam=new BooleanParameter("Outline",!1);outlineColorParam=new ColorParameter("OutlineColor",new Color(0,0,0));backgroundParam=new BooleanParameter("Background",!0);backgroundColorParam=new ColorParameter("BackgroundColor",new Color("#FBC02D"));fillBackgroundParam=new BooleanParameter("FillBackground",!0);strokeBackgroundOutlineParam=new BooleanParameter("StrokeBackgroundOutline",!0);constructor(A,g){super(A),this.canvasElem=document.createElement("canvas");this.marginParam=new NumberParameter("Margin",11),this.borderRadiusParam=new NumberParameter("BorderRadius",11),this.addParameter(this.marginParam),this.addParameter(this.borderRadiusParam),this.addParameter(this.libraryParam),this.addParameter(this.textParam),this.addParameter(this.fontColorParam),this.addParameter(this.fontSizeParam),this.addParameter(this.fontParam),this.addParameter(this.borderWidthParam),this.addParameter(this.outlineParam),this.addParameter(this.outlineColorParam),this.addParameter(this.backgroundParam),this.addParameter(this.backgroundColorParam),this.addParameter(this.fillBackgroundParam),this.addParameter(this.strokeBackgroundOutlineParam);this.on("nameChanged",(()=>{this.loadLabelData()})),g&&(this.libraryParam.value=g),this.requestedReRender=!1,this.needsRender=!1,this.loadLabelData()}__parameterValueChanged(A){super.parameterValueChanged(A),this.requestedReRender||(this.requestedReRender=!0,this.loadLabelData())}loadLabelData(){Promise.all([(()=>new Promise((A=>{const g=this.libraryParam.value;if(""==g)return void A();if(!labelManager.isLibraryFound(g))return console.warn("Label Library not found:",g),void A();const I=()=>{try{const A=this.getName(),I=labelManager.getLabelText(g,A);this.textParam.value=I}catch(A){console.warn(A)}A()};labelManager.isLibraryLoaded(g)?I():labelManager.on("labelLibraryLoaded",(A=>{A.library==g&&I()}))})))(),(()=>new Promise((A=>{if(null!=document.fonts){const g=this.fontParam.value,I=this.fontSizeParam.value;document.fonts.load(I+'px "'+g+'"').then((()=>{A()}))}else A()})))()]).then((()=>{this.requestedReRender=!1,this.needsRender=!0,this.loaded?this.emit("updated"):(this.loaded=!0,this.emit("loaded"))}))}renderLabelToImage(){const A=this.canvasElem.getContext("2d",{alpha:!0});let g=this.textParam.value;""==g&&(g=this.getName());const I=this.fontParam.value,C=this.fontColorParam.value,e=this.fontSizeParam.value,i=this.marginParam.value,t=this.borderWidthParam.value,o=this.borderRadiusParam.value,a=this.outlineParam.value,B=this.outlineColorParam.value,s=this.backgroundParam.value,l=this.backgroundColorParam.value,n=this.fillBackgroundParam.value,d=this.strokeBackgroundOutlineParam.value,r=i+t,c=g.split("\n");A.font=e+'px "'+I+'"';let h=0;c.forEach((g=>{h=Math.max(A.measureText(g).width,h)}));const G=e;this.width=Math.ceil(h+2*r),this.height=Math.ceil(G*c.length+2*r),A.canvas.width=this.width,A.canvas.height=this.height,this.canvasElem.width=this.width,this.canvasElem.height=this.height,A.fillStyle="rgba(0, 0, 0, 0.0)",A.fillRect(0,0,this.width,this.height),s&&(A.fillStyle=l.toHex(),A.strokeStyle=B.toHex(),roundRect(A,t,t,this.width-2*t,this.height-2*t,o,n,d,t)),A.font=e+'px "'+I+'"',A.textAlign="left",A.fillStyle=C.toHex(),A.textBaseline="hanging",c.forEach(((g,I)=>{A.fillText(g,r,r+I*G)})),a&&(A.strokeStyle=B.toHex(),A.lineWidth=1.5,A.strokeText(g,r,r)),this.__data=A.getImageData(0,0,this.width,this.height),this.needsRender=!1,this.emit("labelRendered",{width:this.width,height:this.height,data:this.__data})}getParams(){return this.needsRender&&this.renderLabelToImage(),super.getParams()}}Registry.register("Label",Label);class VideoStreamImage2D extends BaseImage{__data;__intervalId;constructor(){super("")}connectWebcam(A,g,I=!1){const C={width:A,height:g,frameRate:{ideal:60,max:60}};C.facingMode=I?{exact:"environment"}:{facingMode:"user"};const e=document.createElement("video");e.style.display="none",e.preload="auto",e.crossOrigin="anonymous",document.body.appendChild(e),navigator.mediaDevices.getUserMedia({audio:!1,video:C}).then((A=>{e.srcObject=A,e.onloadedmetadata=A=>{e.play(),this.width=e.videoWidth,this.height=e.videoHeight,console.log("Webcam:["+this.width+", "+this.height+"]"),this.__data=e,this.loaded=!0,this.emit("loaded");let g=0;const I=()=>{if(e.paused||e.ended)return;const A=Math.floor(60*e.currentTime);g!=A&&(this.emit("updated"),g=A),setTimeout(I,20)};I()}})).catch((function(A){}))}setVideoStream(A){this.loaded=!1,this.width=A.videoWidth,this.height=A.videoHeight,this.start(),this.__data=A,this.loaded=!0,this.emit("loaded")}stop(){clearInterval(this.__intervalId)}start(){this.__intervalId=setInterval((()=>{this.emit("updated")}),20)}isLoaded(){return this.loaded}getParams(){return{type:this.type,format:this.format,width:this.width,height:this.height,data:this.__data}}}Registry.register("VideoStreamImage2D",VideoStreamImage2D);class FatLinesMaterial extends Material{baseColorParam=new MaterialColorParam("BaseColor",new Color(1,1,.5));opacityParam=new NumberParameter("Opacity",1);lineThicknessParam=new NumberParameter("LineThickness",.01);overlayParam=new NumberParameter("Overlay",0);constructor(A){super(A),this.__shaderName="FatLinesShader",this.addParameter(this.baseColorParam),this.addParameter(this.opacityParam),this.addParameter(this.overlayParam),this.addParameter(this.lineThicknessParam)}isTextured(){return!0}}Registry.register("FatLinesMaterial",FatLinesMaterial);class FatPointsMaterial extends Material{baseColorParam=new MaterialColorParam("BaseColor",new Color(1,1,1));pointSizeParam=new NumberParameter("PointSize",1);borderWidthParam=new NumberParameter("BorderWidth",.2);overlayParam=new NumberParameter("Overlay",0);constructor(A){super(A),this.__shaderName="FatPointsShader",this.addParameter(this.baseColorParam),this.addParameter(this.pointSizeParam),this.addParameter(this.borderWidthParam),this.addParameter(this.overlayParam)}clone(A){const g=new FatPointsMaterial;return g.copyFrom(this,A),g}}Registry.register("FatPointsMaterial",FatPointsMaterial);class FlatSurfaceMaterial extends Material{baseColorParam=new MaterialColorParam("BaseColor",new Color(1,1,.5));overlayParam=new MaterialFloatParam("Overlay",0);constructor(A){super(A),this.__shaderName="FlatSurfaceShader",this.addParameter(this.baseColorParam),this.addParameter(this.overlayParam)}clone(A){const g=new FlatSurfaceMaterial;return g.copyFrom(this,A),g}}Registry.register("FlatSurfaceMaterial",FlatSurfaceMaterial);class LinesMaterial extends Material{baseColorParam=new MaterialColorParam("BaseColor",new Color(1,1,.5));opacityParam=new MaterialFloatParam("Opacity",.7,[0,1]);overlayParam=new MaterialFloatParam("Overlay",1e-6);constructor(A){super(A),this.__shaderName="LinesShader",this.addParameter(this.baseColorParam),this.addParameter(this.opacityParam),this.addParameter(this.overlayParam)}clone(A){const g=new LinesMaterial;return g.copyFrom(this,A),g}}Registry.register("LinesMaterial",LinesMaterial);class PointsMaterial extends Material{baseColorParam=new MaterialColorParam("BaseColor",new Color(1,1,.5));pointSizeParam=new MaterialFloatParam("PointSize",2);overlayParam=new MaterialFloatParam("Overlay",2e-5);constructor(A){super(A),this.__shaderName="PointsShader",this.addParameter(this.baseColorParam),this.addParameter(this.pointSizeParam),this.addParameter(this.overlayParam)}clone(A){const g=new PointsMaterial;return g.copyFrom(this,A),g}}Registry.register("PointsMaterial",PointsMaterial);class ScreenSpaceMaterial extends Material{baseColorParam=new MaterialColorParam("BaseColor",new Color(1,1,.5));constructor(A){super(A),this.__shaderName="ScreenSpaceShader",this.addParameter(this.baseColorParam)}clone(A){const g=new ScreenSpaceMaterial;return g.copyFrom(this,A),g}}Registry.register("ScreenSpaceMaterial",ScreenSpaceMaterial);class SimpleSurfaceMaterial extends Material{baseColorParam=new MaterialColorParam("BaseColor",new Color(1,1,.5));opacityParam=new MaterialFloatParam("Opacity",1,[0,1]);emissiveStrengthParam=new MaterialFloatParam("EmissiveStrength",0,[0,1]);constructor(A){super(A),this.__shaderName="SimpleSurfaceShader",this.addParameter(this.baseColorParam),this.addParameter(this.opacityParam),this.addParameter(this.emissiveStrengthParam)}clone(A){const g=new SimpleSurfaceMaterial;return g.copyFrom(this,A),g}}Registry.register("SimpleSurfaceMaterial",SimpleSurfaceMaterial);class StandardSurfaceMaterial extends Material{baseColorParam=new MaterialColorParam("BaseColor",new Color(1,1,.5));normalParam=new MaterialColorParam("Normal",new Color(1,1,.5));ambientOcclusion=new MaterialFloatParam("AmbientOcclusion",1,[0,1]);metallicParam=new MaterialFloatParam("Metallic",.05,[0,1]);roughnessParam=new MaterialFloatParam("Roughness",.5,[0,1]);reflectanceParam=new MaterialFloatParam("Reflectance",.5,[0,1]);emissiveStrengthParam=new MaterialFloatParam("EmissiveStrength",0,[0,1]);opacityParam=new MaterialFloatParam("Opacity",1,[0,1]);edgeWeightParam=new MaterialFloatParam("EdgeWeight",.7,[0,1]);overlayParam=new MaterialFloatParam("Overlay",0,[0,1]);edgeColorParam=new MaterialColorParam("EdgeColor",new Color(.1,.1,.1,.8));pointColorParam=new MaterialColorParam("PointColor",new Color(.1,.1,.1));pointSizeParam=new MaterialFloatParam("PointSize",4,[0,Number.MAX_VALUE]);constructor(A){super(A),this.__shaderName="StandardSurfaceShader",this.addParameter(this.baseColorParam),this.addParameter(this.normalParam),this.addParameter(this.ambientOcclusion),this.addParameter(this.metallicParam),this.addParameter(this.roughnessParam),this.addParameter(this.reflectanceParam),this.addParameter(this.emissiveStrengthParam),this.addParameter(this.opacityParam),this.addParameter(this.edgeWeightParam),this.addParameter(this.overlayParam),this.addParameter(this.edgeColorParam),this.addParameter(this.pointColorParam),this.addParameter(this.pointSizeParam)}clone(A){const g=new StandardSurfaceMaterial;return g.copyFrom(this,A),g}}Registry.register("StandardSurfaceMaterial",StandardSurfaceMaterial);class VertexColorMaterial extends Material{constructor(A){super(A),this.__shaderName="VertexColorShader"}clone(A){const g=new VertexColorMaterial;return g.copyFrom(this,A),g}static supportsInstancing(){return!1}}Registry.register("VertexColorMaterial",VertexColorMaterial);class MaskMaterial extends SimpleSurfaceMaterial{constructor(A){super(A),this.baseColorParam.value=new Color(1,0,0,.2)}clone(A){const g=new MaskMaterial;return g.copyFrom(this,A),g}}Registry.register("MaskMaterial",MaskMaterial);class EnvProjectionMaterial extends Material{projectionCenter=new Vec3Parameter("projectionCenter",new Vec3(0,0,1.7));constructor(A){super(A),this.__shaderName="EnvProjectionShader",this.addParameter(this.projectionCenter)}clone(A){const g=new EnvProjectionMaterial;return g.copyFrom(this,A),g}isTextured(){return!0}}Registry.register("EnvProjectionMaterial",EnvProjectionMaterial);class InstanceItem extends TreeItem{srcTreePath=[];srcTree=null;constructor(A){super(A)}setSrcTree(A){this.srcTree=A;const g=new CloneContext,I=this.srcTree.clone(g);I.localXfoParam.value=new Xfo,this.addChild(I,!1,!1)}getSrcTree(){return this.srcTree}readBinary(A,g){super.readBinary(A,g),this.srcTreePath=A.loadStrArray(),this.srcTreePath.length>0&&g.resolvePath(this.srcTreePath,(A=>{this.setSrcTree(A)}),(A=>{console.warn(`Error loading InstanceItem: ${this.getPath()}, unable to resolve: ${this.srcTreePath}. `+A.message)}))}clone(A){const g=new InstanceItem;return g.copyFrom(this,A),g}copyFrom(A,g){if(!(A instanceof InstanceItem))throw new Error("cannot copy from src");super.copyFrom(A,g),this.srcTreePath=A.srcTreePath,this.srcTreePath.length>0&&0==this.getNumChildren()&&A.once("childAdded",(A=>{const g=A.childItem;this.setSrcTree(g)}))}}Registry.register("InstanceItem",InstanceItem);class BaseGeomItem extends TreeItem{overlay;cutAway;cutAwayVector;cutAwayDist;layers;materialParam=new MaterialParameter("Material");constructor(A){super(A),this.addParameter(this.materialParam),this.overlay=!1,this.cutAway=!1,this.cutAwayVector=new Vec3(0,0,0),this.cutAwayDist=0,this.layers=[]}setOverlay(A){this.overlay=A}isOverlay(){return this.overlay}addLayer(A){this.layers.push(A)}getLayers(){return this.layers}isCutawayEnabled(){return this.cutAway}setCutawayEnabled(A){this.cutAway=A,this.emit("cutAwayChanged")}getCutVector(){return this.cutAwayVector}setCutVector(A){this.cutAwayVector=A,this.emit("cutAwayChanged")}getCutDist(){return this.cutAwayDist}setCutDist(A){this.cutAwayDist=A,this.emit("cutAwayChanged")}readBinary(A,g){if(super.readBinary(A,g),g.versions["zea-engine"].compare([0,0,4])>=0){const I=A.loadStr();let C=g.assetItem.getMaterialLibrary().getMaterial(I);if(C||(C=new Material(I,"SimpleSurfaceShader"),C.getParameter("BaseColor").loadValue(Color.random(.25)),g.assetItem.getMaterialLibrary().addMaterial(C)),this.materialParam.loadValue(C),this.layers=A.loadStrArray(),this.layers.length>0)for(const A of this.layers)g.addGeomToLayer(this,A)}}}let calculatePreciseBoundingBoxes=!1;class CalcGeomMatOperator extends Operator{globalXfo=new XfoOperatorInput("GlobalXfo");geomOffsetXfo=new XfoOperatorInput("GeomOffsetXfo");geomMat=new Mat4OperatorOutput("GeomMat");constructor(A,g,I){super("CalcGeomMatOperator"),this.globalXfo.setParam(A),this.geomOffsetXfo.setParam(g),this.geomMat.setParam(I),this.addInput(this.globalXfo),this.addInput(this.geomOffsetXfo),this.addOutput(this.geomMat)}evaluate(){const A=this.globalXfo.getValue().toMat4(),g=this.geomOffsetXfo.getValue().toMat4();this.geomMat.setClean(A.multiply(g))}}class GeomItem extends BaseGeomItem{listenerIDs={};geomBBox;geomIndex=-1;assetItem=null;calcGeomMatOperator;cullable=!0;geomOffsetXfoParam=new XfoParameter("GeomOffsetXfo");geomParam=new GeometryParameter("Geometry");geomMatParam=new Mat4Parameter("GeomMat");constructor(A,g,I,C){super(A),this.addParameter(this.geomParam),this.addParameter(this.geomOffsetXfoParam),this.addParameter(this.geomMatParam);const e=()=>{this.setBoundingBoxDirty()};this.geomParam.on("valueChanged",e),this.geomParam.on("boundingBoxChanged",e),this.calcGeomMatOperator=new CalcGeomMatOperator(this.globalXfoParam,this.geomOffsetXfoParam,this.geomMatParam),g&&this.geomParam.loadValue(g),I&&this.materialParam.loadValue(I),C&&(this.localXfoParam.value=C)}cleanBoundingBox(){if(this.disableBoundingBox)return new Box3;const A=super.cleanBoundingBox();if(this.geomBBox){const g=this.geomMatParam.value;A.addPoint(g.transformVec3(this.geomBBox.p0)),A.addPoint(g.transformVec3(this.geomBBox.p1))}else{const g=this.geomParam.value;if(g)if(calculatePreciseBoundingBoxes){const I=this.geomMatParam.value,C=g.genBuffers();if(g instanceof BaseProxy){const e=C.attrBuffers.positions.values,i=A=>{const g=3*A,I=new Vec3;return I.fromArray(e.subarray(g,g+3)),I};for(let C=0;C<g.getNumVertices();C++)A.addPoint(I.transformVec3(i(C)))}else{const C=g.getVertexAttribute("positions");for(let e=0;e<g.getNumVertices();e++)A.addPoint(I.transformVec3(C.getValue(e)))}}else A.addBox3(g.getBoundingBox(),this.geomMatParam.value)}return A}fromJSON(A,g){super.fromJSON(A,g)}readBinary(A,g){super.readBinary(A,g);const I=A.loadUInt8(),C=A.loadUInt32(),e=g.assetItem.getGeometryLibrary();this.geomIndex=C,this.assetItem=g.assetItem;const i=e.getGeom(C);if(i)this.geomParam.loadValue(i);else{const A=A=>{const{range:I}=A;if(C>=I[0]&&C<I[1]){const A=e.getGeom(C);A?this.geomParam.value=A:console.warn("Geom not loaded:",this.getName()),e.off("rangeLoaded",g)}},g=e.on("rangeLoaded",A)}if(4&I&&(this.geomOffsetXfoParam.value=new Xfo(A.loadFloat32Vec3(),A.loadFloat32Quat(),A.loadFloat32Vec3())),g.versions["zea-engine"].compare([0,0,4])<0){if(I&8){const I=g.assetItem.getMaterialLibrary(),C=A.loadStr();let e=I.getMaterial(C);e||(console.warn("Geom :'"+this.name+"' Material not found:"+C),e=I.getMaterial("Default")),this.materialParam.loadValue(e)}else this.materialParam.loadValue(g.assetItem.getMaterialLibrary().getMaterial("Default"))}g.versions["zea-engine"].compare([3,0,0])<0?A.loadFloat32Vec2():this.geomBBox=new Box3(A.loadFloat32Vec3(),A.loadFloat32Vec3())}toString(A){return JSON.stringify(this.toJSON(A),null,2)}clone(A){const g=new GeomItem;return g.copyFrom(this,A),g}copyFrom(A,g){if(!(A instanceof GeomItem))throw new Error("cannot copy from src");if(super.copyFrom(A,g),this.geomOffsetXfoParam.value=A.geomOffsetXfoParam.value,!A.geomParam.value&&-1!=A.geomIndex){const g=A.assetItem.getGeometryLibrary();this.assetItem=A.assetItem,this.geomIndex=A.geomIndex,this.geomBBox=A.geomBBox;const I=A=>{const{range:I}=A;if(this.geomIndex>=I[0]&&this.geomIndex<I[1]){const A=g.getGeom(this.geomIndex);A?this.geomParam.value=A:console.warn("Geom not loaded:",this.getName()),g.off("rangeLoaded",this.listenerIDs.rangeLoaded)}};this.listenerIDs.rangeLoaded=g.on("rangeLoaded",I)}this.geomMatParam.setDirty(0)}static setCalculatePreciseBoundingBoxes(A){calculatePreciseBoundingBoxes=A}}Registry.register("GeomItem",GeomItem);class CompoundGeomLoader extends BaseGeom{numSubGeoms=0;indices=new Uint8Array(0);offsets={};counts={};materialSubGeoms={};subGeomOffsets={};subGeomCounts={};materialLibraryIndices=new Uint32Array(0);subGeomMaterialIndices=new Uint8Array(0);constructor(){super()}genBuffers(){const A={};for(const[g,I]of this.__vertexAttributes)A[g]=I.genBuffer();const g=this.numVertices();return{numVertices:g,numRenderVerts:g,indices:this.indices,attrBuffers:A,offsets:this.offsets,counts:this.counts,numSubGeoms:this.numSubGeoms,subGeomOffsets:this.subGeomOffsets,subGeomCounts:this.subGeomCounts,materialLibraryIndices:this.materialLibraryIndices,subGeomMaterialIndices:this.subGeomMaterialIndices,materialSubGeoms:this.materialSubGeoms}}readBinary(A,g){super.loadBaseGeomBinary(A,g);const I=A.loadUInt32Array(3);this.offsets.TRIANGLES=0,this.counts.TRIANGLES=I[0],this.offsets.LINES=I[0],this.counts.LINES=I[1],this.offsets.POINTS=I[0]+I[1],this.counts.POINTS=I[2];const C=A.loadUInt8();1==C?this.indices=A.loadUInt8Array():2==C?this.indices=A.loadUInt16Array():4==C&&(this.indices=A.loadUInt32Array());const e=A.loadUInt8();let i;if(1==e)i=A.loadUInt8Array();else if(2==e)i=A.loadUInt16Array();else{if(4!=e)throw Error("subGeomOffsets undefined");i=A.loadUInt32Array()}const t=new Uint32Array(i.length);let o=0;for(let A=0;A<i.length;A++)t[A]=o,o+=i[A];this.subGeomOffsets.TRIANGLES=t,this.subGeomCounts.TRIANGLES=i;const a=A.loadUInt8();let B;if(1==a)B=A.loadUInt8Array();else if(2==a)B=A.loadUInt16Array();else{if(4!=a)throw Error("subGeomOffsets undefined");B=A.loadUInt32Array()}const s=new Uint32Array(B.length);for(let A=0;A<B.length;A++)s[A]=o,o+=B[A];this.subGeomOffsets.LINES=s,this.subGeomCounts.LINES=B;const l=A.loadUInt32(),n=new Uint32Array(l),d=new Uint8Array(l);for(let A=0;A<l;A++)n[A]=o,d[A]=1,o++;this.subGeomOffsets.POINTS=n,this.subGeomCounts.POINTS=d,g.versions["zea-engine"].compare([3,11,0])>0?this.numSubGeoms=i.length+B.length+l:this.numSubGeoms=i.length+B.length;const r=A.loadUInt32();if(r>0){this.materialLibraryIndices=A.loadUInt32Array(r),this.subGeomMaterialIndices=A.loadUInt8Array(this.numSubGeoms);let g=0,I=-99,C=null;for(let A=0;A<this.numSubGeoms;A++){let e,i=0;A<this.subGeomCounts.TRIANGLES.length?(this.materialSubGeoms.TRIANGLES||(this.materialSubGeoms.TRIANGLES=[]),e="TRIANGLES"):A<this.subGeomCounts.TRIANGLES.length+this.subGeomCounts.LINES.length?(i=this.subGeomCounts.TRIANGLES.length,e="LINES",this.materialSubGeoms.LINES||(this.materialSubGeoms.LINES=[])):(i=this.subGeomCounts.TRIANGLES.length+this.subGeomCounts.LINES.length,e="POINTS",this.materialSubGeoms.POINTS||(this.materialSubGeoms.POINTS=[]));const t=this.subGeomMaterialIndices[A];if(I!=t){for(I=t,C={materialId:t-1,offset:g,count:0};A<this.numSubGeoms&&I==this.subGeomMaterialIndices[A];A++){if(A-i==this.subGeomCounts[e].length){I=-99;break}C.count+=this.subGeomCounts[e][A-i]}g+=C.count,this.materialSubGeoms[e].push(C),A--}}this.subGeomCounts.POINTS.length>0&&!this.materialSubGeoms.POINTS&&(this.materialSubGeoms.POINTS=[{materialId:-1,offset:g,count:this.subGeomCounts.POINTS.length}])}else{this.materialSubGeoms={};let A=0;for(let g in this.counts){const I=this.counts[g];I>0&&(this.materialSubGeoms[g]=[{materialId:-1,offset:A,count:I}]),A+=I}}this.emit("geomDataChanged",{})}}const parseGeomsBinary=(A,g)=>{for(const g in A.context.versions){const I=A.context.versions[g],C=new Version("");C.major=I.major,C.minor=I.minor,C.patch=I.patch,C.branch=I.branch,A.context.versions[g]=C}const I=[],C=A.byteOffset,e=[];for(let g=A.geomsRange[0];g<A.geomsRange[1];g++){const i=new BinReader(A.bufferSlice,A.toc[g]-C,A.isMobileDevice),t=i.loadStr(),o=i.pos();let a;switch(t){case"Points":a=new Points;break;case"Lines":a=new Lines;break;case"Mesh":a=new Mesh;break;case"CompoundGeom":a=new CompoundGeomLoader;break;default:throw new Error("Unsupported Geom type:"+t)}try{i.seek(o),a.readBinary(i,A.context)}catch(A){console.warn("Error loading:"+a.name+"\n:"+A),I.push({});continue}const B=a.genBuffers(A.genBuffersOpts);B.indices&&e.push(B.indices.buffer);for(const A in B.attrBuffers){const g=B.attrBuffers[A];e.push(g.values.buffer)}if(B.materialLibraryIndices&&e.push(B.materialLibraryIndices.buffer),B.subGeomMaterialIndices&&e.push(B.subGeomMaterialIndices.buffer),B.subGeomOffsets)for(let A in B.subGeomOffsets)e.push(B.subGeomOffsets[A].buffer);I.push({name:a.name,type:t,geomBuffers:B,bbox:a.getBoundingBox()})}g({taskId:A.taskId,geomLibraryId:A.geomLibraryId,geomFileID:A.geomFileID,geomIndexOffset:A.geomIndexOffset,geomsRange:A.geomsRange,geomDatas:I},e)},handleMessage=function(A,g){parseGeomsBinary(A,((A,I)=>{g(A,I)}))};void 0===globalThis.document&&(globalThis.onmessage=function(A){A.data?A.data.context&&handleMessage(A.data,self.postMessage):console.warn("GeomLibrary worker.postMessage failed. data was lost on the way to the web worker.")});var WorkerFactory$1=createBase64WorkerFactory("Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwp2YXIgd29ya2VyX2NvZGUgPSAoZnVuY3Rpb24gKGV4cG9ydHMpIHsKICAgICd1c2Ugc3RyaWN0JzsKCiAgICAvKioKICAgICAqIFN0cmluZyBmdW5jdGlvbnMKICAgICAqCiAgICAgKi8KICAgIGNsYXNzIFN0cmluZ0Z1bmN0aW9ucyB7CiAgICAgICAgLyoqCiAgICAgICAgICogUmVwbGFjZXMgYWxsIG1hdGNoZXMgaW4gYSBzdHJpbmcuCiAgICAgICAgICoKICAgICAgICAgKiBAc3RhdGljCiAgICAgICAgICogQHBhcmFtIHN0ciAtCiAgICAgICAgICogQHBhcmFtIHBhdHRlcm4gLQogICAgICAgICAqIEBwYXJhbSByZXBsYWNlbWVudCAtCiAgICAgICAgICogQHJldHVybiAtCiAgICAgICAgICovCiAgICAgICAgc3RhdGljIHJlcGxhY2VBbGwoc3RyLCBwYXR0ZXJuLCByZXBsYWNlbWVudCkgewogICAgICAgICAgICByZXR1cm4gc3RyLnJlcGxhY2UobmV3IFJlZ0V4cChwYXR0ZXJuLCAnZycpLCByZXBsYWNlbWVudCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgSlNPTiBvYmplY3QgYXMgYSBmb3JtYXR0ZWQgc3RyaW5nLCBidXQgdGhlIG51bWVyaWMgdmFsdWVzIGFyZSBmaXhlZCB0byB0aGUgc3BlY2lmaWVkIHByZWNpc2lvbi4KICAgICAgICAgKgogICAgICAgICAqIEBzdGF0aWMKICAgICAgICAgKiBAcGFyYW0gdmFsIC0KICAgICAgICAgKiBAcGFyYW0gc3BhY2UgLQogICAgICAgICAqIEBwYXJhbSBwcmVjaXNpb24gLQogICAgICAgICAqIEByZXR1cm4gLQogICAgICAgICAqLwogICAgICAgIHN0YXRpYyBzdHJpbmdpZnlKU09OV2l0aEZpeGVkUHJlY2lzaW9uKHZhbCwgc3BhY2UgPSAwLCBwcmVjaXNpb24gPSA1KSB7CiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWwsIChfLCB2YWwpID0+IHsKICAgICAgICAgICAgICAgIHJldHVybiB2YWwgPyAodmFsLnRvRml4ZWQgPyBOdW1iZXIodmFsLnRvRml4ZWQocHJlY2lzaW9uKSkgOiB2YWwpIDogdmFsOwogICAgICAgICAgICB9LCBzcGFjZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRyYW5zZm9ybXMgdGhlIGdpdmVuIHN0cmluZyBpbnRvIGEgbnVtZXJpYyB2YWx1ZS4KICAgICAgICAgKgogICAgICAgICAqIEBzdGF0aWMKICAgICAgICAgKiBAcGFyYW0gc3RyIC0KICAgICAgICAgKiBAcmV0dXJuIC0KICAgICAgICAgKi8KICAgICAgICBzdGF0aWMgaGFzaFN0cihzdHIpIHsKICAgICAgICAgICAgbGV0IGhhc2ggPSAwOwogICAgICAgICAgICBsZXQgaTsKICAgICAgICAgICAgbGV0IGNocjsKICAgICAgICAgICAgbGV0IGxlbjsKICAgICAgICAgICAgaWYgKHN0ci5sZW5ndGggPT09IDApCiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDsKICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gc3RyLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7CiAgICAgICAgICAgICAgICBjaHIgPSBzdHIuY2hhckNvZGVBdChpKTsKICAgICAgICAgICAgICAgIGhhc2ggPSAoaGFzaCA8PCA1KSAtIGhhc2ggKyBjaHI7CiAgICAgICAgICAgICAgICBoYXNoIHw9IDA7IC8vIENvbnZlcnQgdG8gMzJiaXQgaW50ZWdlcgogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBNYXRoLmFicyhoYXNoKTsKICAgICAgICB9CiAgICB9CgogICAgLyoqCiAgICAgKiBSZXByZXNlbnRpbmcgYSBWZWMyKHR3by1kaW1lbnNpb25hbCBmbG9hdGluZyBwb2ludCB2ZWN0b3IpLiBBIFZlYzIgaXMgZm9yIHJlcHJlc2VudGluZyAyIGRpbWVuc2lvbmFsIHZhbHVlcywgc3VjaCBhcyBzY3JlZW4gY29vcmRpbmF0ZXMgb3IgcGl4ZWwgY29vcmRpbmF0ZXMgd2l0aGluIGFuIGltYWdlLgogICAgICoKICAgICAqIE1hdGggdHlwZXMgaW50ZXJuYWxseSBzdG9yZSB2YWx1ZXMgaW4ge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Zsb2F0MzJBcnJheXxGbG9hdDMyQXJyYXl9IGFuZAogICAgICogZXhwb3NlIGdldHRlcnMgYW5kIHNldHRlcnMgZm9yIHRoZSBjb21wb25lbnQgdmFsdWVzLgogICAgICoKICAgICAqLwogICAgY2xhc3MgVmVjMiB7CiAgICAgICAgeDsKICAgICAgICB5OwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYSBWZWMyLgogICAgICAgICAqCiAgICAgICAgICogYGBgamF2YXNjcmlwdAogICAgICAgICAqICBjb25zdCBteVZlYzIgPSBuZXcgVmVjMigxLjIsIDMuNCkKICAgICAgICAgKiBgYGAKICAgICAgICAgKgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKHggPSAwLCB5ID0gMCkgewogICAgICAgICAgICB0aGlzLnggPSB4OwogICAgICAgICAgICB0aGlzLnkgPSB5OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXR0ZXIgZnJvbSBzY2FsYXIgY29tcG9uZW50cy4KICAgICAgICAgKiBAcGFyYW0geCAtIFRoZSB4IGNvbXBvbmVudC4KICAgICAgICAgKiBAcGFyYW0geSAgLSBUaGUgeSBjb21wb25lbnQuCiAgICAgICAgICovCiAgICAgICAgc2V0KHgsIHkpIHsKICAgICAgICAgICAgdGhpcy54ID0geDsKICAgICAgICAgICAgdGhpcy55ID0geTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmVwbGFjZXMgdGhpcyBWZWMyIGRhdGEgd2l0aCB0aGUgVmVjMiBkYXRhIHBhc3NlZCBhcyBwYXJhbWV0ZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjMiB0byBzZXQgZnJvbS4KICAgICAgICAgKi8KICAgICAgICBzZXRGcm9tT3RoZXIob3RoZXIpIHsKICAgICAgICAgICAgdGhpcy54ID0gb3RoZXIueDsKICAgICAgICAgICAgdGhpcy55ID0gb3RoZXIueTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2hlY2tzIGlmIHRoaXMgVmVjMiBjb250YWlucyB0aGUgc2FtZSB2YWx1ZXMgYXMgdGhlIG90aGVyIFZlYzIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjMiB0byBjb21wYXJlIHdpdGguCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYHRydWVgIGlmIGFyZSB0aGUgc2FtZSBWZWN0b3IsIG90aGVyd2lzZSwgYGZhbHNlYC4KICAgICAgICAgKi8KICAgICAgICBpc0VxdWFsKG90aGVyKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnggPT0gb3RoZXIueCAmJiB0aGlzLnkgPT0gb3RoZXIueTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2hlY2tzIGlmIHRoaXMgVmVjMiBpcyBkaWZmZXJlbnQgZnJvbSBhbm90aGVyIFZlYzIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjMiB0byBjb21wYXJlIHdpdGguCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYHRydWVgIGlmIHRoZSBWZWMycyBhcmUgZGlmZmVyZW50LCBvdGhlcndpc2UsIGBmYWxzZWAuCiAgICAgICAgICovCiAgICAgICAgbm90RXF1YWwob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMueCAhPSBvdGhlci54ICYmIHRoaXMueSAhPSBvdGhlci55OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBWZWMyIGlzIGFwcHJveGltYXRlbHkgdGhlIHNhbWUgYXMgb3RoZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjMiB0byBjb21wYXJlIHdpdGguCiAgICAgICAgICogQHBhcmFtIHByZWNpc2lvbiAtIFRoZSBwcmVjaXNpb24gdG8gd2hpY2ggdGhlIHZhbHVlcyBtdXN0IG1hdGNoLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRydWUgb3IgZmFsc2UuCiAgICAgICAgICovCiAgICAgICAgYXBwcm94RXF1YWwob3RoZXIsIHByZWNpc2lvbiA9IE51bWJlci5FUFNJTE9OKSB7CiAgICAgICAgICAgIHJldHVybiBNYXRoLmFicyh0aGlzLnggLSBvdGhlci54KSA8IHByZWNpc2lvbiAmJiBNYXRoLmFicyh0aGlzLnkgLSBvdGhlci55KSA8IHByZWNpc2lvbjsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQWRkcyBvdGhlciB0byB0aGlzIFZlYzIgYW5kIHJldHVybnMgdGhlIHJlc3VsdCBhcyBhIG5ldyBWZWMyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzIgdG8gYWRkLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzIuCiAgICAgICAgICovCiAgICAgICAgYWRkKG90aGVyKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMih0aGlzLnggKyBvdGhlci54LCB0aGlzLnkgKyBvdGhlci55KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQWRkcyBhIFZlYzIgdG8gdGhpcyBWZWMyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzIgdG8gYWRkLgogICAgICAgICAqLwogICAgICAgIGFkZEluUGxhY2Uob3RoZXIpIHsKICAgICAgICAgICAgdGhpcy54ICs9IG90aGVyLng7CiAgICAgICAgICAgIHRoaXMueSArPSBvdGhlci55OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTdWJ0cmFjdHMgYSBWZWMyIGZyb20gdGhpcyBWZWMyIGFuZCByZXR1cm5zIHRoZSByZXN1bHQgYXMgYSBuZXcgVmVjMi4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWMyIHRvIHN1YnRyYWN0LgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzIuCiAgICAgICAgICovCiAgICAgICAgc3VidHJhY3Qob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMyKHRoaXMueCAtIG90aGVyLngsIHRoaXMueSAtIG90aGVyLnkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTdWJ0cmFjdHMgYSBWZWMyIGZyb20gdGhpcyBWZWMyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzIgdG8gc3VidHJhY3QuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgVmVjMi4KICAgICAgICAgKi8KICAgICAgICBzdWJ0cmFjdEluUGxhY2Uob3RoZXIpIHsKICAgICAgICAgICAgdGhpcy54IC09IG90aGVyLng7CiAgICAgICAgICAgIHRoaXMueSAtPSBvdGhlci55OwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2NhbGVzIHRoaXMgVmVjMiBieSBzY2FsYXIgYW5kIHJldHVybnMgdGhlIHJlc3VsdCBhcyBhIG5ldyBWZWMyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHNjYWxhciAtIFRoZSBzY2FsYXIgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgVmVjMi4KICAgICAgICAgKi8KICAgICAgICBzY2FsZShzY2FsYXIpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMyKHRoaXMueCAqIHNjYWxhciwgdGhpcy55ICogc2NhbGFyKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2NhbGVzIHRoaXMgVmVjMiBieSBzY2FsYXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc2NhbGFyIC0gVGhlIHNjYWxhciB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzY2FsZUluUGxhY2Uoc2NhbGFyKSB7CiAgICAgICAgICAgIHRoaXMueCAqPSBzY2FsYXI7CiAgICAgICAgICAgIHRoaXMueSAqPSBzY2FsYXI7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEludmVydHMgdGhpcyBWZWMyIGFuZCByZXR1cm5zIHRoZSByZXN1bHQgYXMgYSBuZXcgVmVjMi4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzIuCiAgICAgICAgICovCiAgICAgICAgaW52ZXJ0KCkgewogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzIoMS4wIC8gdGhpcy54LCAxLjAgLyB0aGlzLnkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBJbnZlcnRzIHRoaXMgVmVjMi4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGludmVydEluUGxhY2UoKSB7CiAgICAgICAgICAgIHRoaXMueCA9IDEuMCAvIHRoaXMueDsKICAgICAgICAgICAgdGhpcy55ID0gMS4wIC8gdGhpcy55OwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogTXVsdGlwbGllcyBhIFZlYzIgd2l0aCB0aGlzIFZlYzIgYW5kIHJldHVybnMgdGhlIHJlc3VsdCBhcyBhIG5ldyBWZWMyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzIgdG8gbXVsdGlwbHkgd2l0aC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBWZWMyLgogICAgICAgICAqLwogICAgICAgIG11bHRpcGx5KG90aGVyKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMih0aGlzLnggKiBvdGhlci54LCB0aGlzLnkgKiBvdGhlci55KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogTXVsdGlwbGllcyBhIFZlYzIgd2l0aCB0aGlzIFZlYzIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjMiB0byBtdWx0aXBseSB3aXRoLgogICAgICAgICAqLwogICAgICAgIG11bHRpcGx5SW5QbGFjZShvdGhlcikgewogICAgICAgICAgICB0aGlzLnggKj0gb3RoZXIueDsKICAgICAgICAgICAgdGhpcy55ICo9IG90aGVyLnk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgbGVuZ3RoIG9mIHRoaXMgVmVjMi4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBsZW5ndGggc3F1YXJlZC4KICAgICAgICAgKi8KICAgICAgICBsZW5ndGhTcXVhcmVkKCkgewogICAgICAgICAgICBjb25zdCB4ID0gdGhpcy54OwogICAgICAgICAgICBjb25zdCB5ID0gdGhpcy55OwogICAgICAgICAgICByZXR1cm4geCAqIHggKyB5ICogeTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsY3VsYXRlcyB0aGUgbGVuZ3RoIG9mIHRoaXMgVmVjMi4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBsZW5ndGguCiAgICAgICAgICovCiAgICAgICAgbGVuZ3RoKCkgewogICAgICAgICAgICByZXR1cm4gTWF0aC5zcXJ0KHRoaXMubGVuZ3RoU3F1YXJlZCgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsY3VsYXRlcyB0aGUgZGlzdGFuY2UgdG8gYW5vdGhlciB2ZWN0b3IuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGRpc3RhbmNlIGJldHdlZW4gdmVjdG9ycy4KICAgICAgICAgKi8KICAgICAgICBkaXN0YW5jZVRvKG90aGVyKSB7CiAgICAgICAgICAgIGNvbnN0IHggPSB0aGlzLnggLSBvdGhlci54OwogICAgICAgICAgICBjb25zdCB5ID0gdGhpcy55IC0gb3RoZXIueTsKICAgICAgICAgICAgcmV0dXJuIE1hdGguc3FydCh4ICogeCArIHkgKiB5KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogTm9ybWFsaXplcyB0aGUgVmVjMiBhbmQgcmV0dXJucyBpdCBhcyBhIG5ldyBWZWMyLgogICAgICAgICAqIE11bHRpcGxpZXMgY29vcmRpbmF0ZXMgdmFsdWUgYnkgdGhlIGludmVyc2Ugb2YgdGhlIHZlY3RvciBsZW5ndGguCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgVmVjMiBub3JtYWxpemVkLgogICAgICAgICAqLwogICAgICAgIG5vcm1hbGl6ZSgpIHsKICAgICAgICAgICAgY29uc3QgeCA9IHRoaXMueDsKICAgICAgICAgICAgY29uc3QgeSA9IHRoaXMueTsKICAgICAgICAgICAgbGV0IGxlbiA9IHggKiB4ICsgeSAqIHk7CiAgICAgICAgICAgIGlmIChsZW4gPCBOdW1iZXIuRVBTSUxPTikgewogICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMyKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/CiAgICAgICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMyKHggKiBsZW4sIHkgKiBsZW4pOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBOb3JtYWxpemVzIHRoaXMgVmVjMiBtdWx0aXBseWluZyBjb29yZGluYXRlIHZhbHVlcyBieSB0aGUgaW52ZXJzZSBvZiB0aGUgdmVjdG9yIGxlbmd0aC4KICAgICAgICAgKi8KICAgICAgICBub3JtYWxpemVJblBsYWNlKCkgewogICAgICAgICAgICBjb25zdCB4ID0gdGhpcy54OwogICAgICAgICAgICBjb25zdCB5ID0gdGhpcy55OwogICAgICAgICAgICBsZXQgbGVuID0geCAqIHggKyB5ICogeTsKICAgICAgICAgICAgaWYgKGxlbiA8IE51bWJlci5FUFNJTE9OKSB7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGVuID0gMSAvIE1hdGguc3FydChsZW4pOwogICAgICAgICAgICB0aGlzLnNldCh4ICogbGVuLCB5ICogbGVuKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsY3VsYXRlcyB0aGUgZG90IHByb2R1Y3Qgb2YgdGhpcyBWZWMyIGFnYWluc3QgYW5vdGhlciBWZWMyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzIgdG8gY29tcGFyZSB3aXRoLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBkb3QgcHJvZHVjdC4KICAgICAgICAgKi8KICAgICAgICBkb3Qob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMueCAqIG90aGVyLnggKyB0aGlzLnkgKiBvdGhlci55OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDYWxjdWxhdGVzIHRoZSBjcm9zcyBwcm9kdWN0IG9mIHRoaXMgVmVjMiBhZ2FpbnN0IGFub3RoZXIgVmVjMi4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWMyIHRvIGNvbXBhcmUgd2l0aC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgY3Jvc3MgcHJvZHVjdC4KICAgICAgICAgKi8KICAgICAgICBjcm9zcyhvdGhlcikgewogICAgICAgICAgICAvLyBqdXN0IGNhbGN1bGF0ZSB0aGUgei1jb21wb25lbnQKICAgICAgICAgICAgcmV0dXJuIHRoaXMueCAqIG90aGVyLnkgLSB0aGlzLnkgKiBvdGhlci54OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBhbmdsZSBiZXR3ZWVuIHRoaXMgVmVjMiBhbmQgb3RoZXIgYXNzdW1pbmcgYm90aCBhcmUgbm9ybWFsaXplZCB2ZWN0b3JzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzIgdG8gY29tcGFyZSB3aXRoLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBhbmdsZSBpbiByYWRpYW5zLgogICAgICAgICAqLwogICAgICAgIGFuZ2xlVG8ob3RoZXIpIHsKICAgICAgICAgICAgY29uc3QgY29zaW5lID0gdGhpcy5ub3JtYWxpemUoKS5kb3Qob3RoZXIubm9ybWFsaXplKCkpOwogICAgICAgICAgICBpZiAoY29zaW5lID4gMS4wKQogICAgICAgICAgICAgICAgcmV0dXJuIDAuMDsKICAgICAgICAgICAgZWxzZSBpZiAoY29zaW5lIDwgLTEuMCkKICAgICAgICAgICAgICAgIHJldHVybiBNYXRoLlBJOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICByZXR1cm4gTWF0aC5hY29zKGNvc2luZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIGFuZ2xlIGJldHdlZW4gdGhpcyBWZWMyIGFuZCBvdGhlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWMyIHRvIGNvbXBhcmUgd2l0aC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgYW5nbGUgaW4gcmFkaWFucy4KICAgICAgICAgKi8KICAgICAgICBzaWduZWRBbmdsZVRvKG90aGVyKSB7CiAgICAgICAgICAgIGNvbnN0IGFuZ2xlID0gdGhpcy5hbmdsZVRvKG90aGVyKTsKICAgICAgICAgICAgaWYgKHRoaXMuY3Jvc3Mob3RoZXIpIDwgMC4wKQogICAgICAgICAgICAgICAgcmV0dXJuIC1hbmdsZTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgcmV0dXJuIGFuZ2xlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSb3RhdGVzIGEgVmVjMiBpbiBhIGNsb2Nrd2lzZSBkaXJlY3Rpb24gYW5kIHJldHVybnMgYSBuZXcgcm90YXRlZCBWZWMyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGFuZ2xlIC0gVGhlIGFuZ2xlIG9mIHJvdGF0aW9uLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSByb3RhdGVkIHZlY3Rvci4KICAgICAgICAgKi8KICAgICAgICByb3RhdGUoYW5nbGUpIHsKICAgICAgICAgICAgY29uc3QgY29zQSA9IE1hdGguY29zKGFuZ2xlKTsKICAgICAgICAgICAgY29uc3Qgc2luQSA9IE1hdGguc2luKGFuZ2xlKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMyKHRoaXMueCAqIGNvc0EgLSB0aGlzLnkgKiBzaW5BLCB0aGlzLnggKiBzaW5BICsgdGhpcy55ICogY29zQSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFBlcmZvcm1zIGEgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0aGlzIFZlYzIgYW5kIG90aGVyIFZlYzIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjMiB0byBpbnRlcnBvbGF0ZSBiZXR3ZWVuLgogICAgICAgICAqIEBwYXJhbSB0IC0gSW50ZXJwb2xhdGlvbiBhbW91bnQgYmV0d2VlbiB0aGUgdHdvIGlucHV0cy4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBWZWMyLgogICAgICAgICAqLwogICAgICAgIGxlcnAob3RoZXIsIHQpIHsKICAgICAgICAgICAgY29uc3QgYXggPSB0aGlzLng7CiAgICAgICAgICAgIGNvbnN0IGF5ID0gdGhpcy55OwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzIoYXggKyB0ICogKG90aGVyLnggLSBheCksIGF5ICsgdCAqIChvdGhlci55IC0gYXkpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogR2VuZXJhdGVzIGEgcmFuZG9tIHZlY3RvciB3aXRoIHRoZSBnaXZlbiBzY2FsZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBzY2FsZSAtIExlbmd0aCBvZiB0aGUgcmVzdWx0aW5nIHZlY3Rvci4gSWYgb21pdHRlZCwgYSB1bml0IHZlY3RvciB3aWxsIGJlIHJldHVybmVkLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldFJhbmRvbURpcihzY2FsZSA9IDEuMCkgewogICAgICAgICAgICBjb25zdCByID0gTWF0aC5yYW5kb20oKSAqIDIuMCAqIE1hdGguUEk7CiAgICAgICAgICAgIHRoaXMueCA9IE1hdGguY29zKHIpICogc2NhbGU7CiAgICAgICAgICAgIHRoaXMueSA9IE1hdGguc2luKHIpICogc2NhbGU7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSYW5kb21pemVzIHRoZSBzY2FsZSBvZiB0aGlzIFZlYzIgY29vcmRpbmF0ZXMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc2NhbGUgLSBUaGUgc2NhbGUgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0UmFuZG9tKHNjYWxlID0gMS4wKSB7CiAgICAgICAgICAgIHRoaXMueCA9IE1hdGgucmFuZG9tKCkgKiBzY2FsZTsKICAgICAgICAgICAgdGhpcy55ID0gTWF0aC5yYW5kb20oKSAqIHNjYWxlOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2xvbmVzIHRoaXMgVmVjMiBhbmQgcmV0dXJucyBhIG5ldyBWZWMyLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgVmVjMi4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMyKHRoaXMueCwgdGhpcy55KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBjdXJyZW50IFZlYzIgZGF0YSBhcyBhcnJheS4gT2Z0ZW4gdXNlZCB0byBwYXNzIHR5cGVzIHRvIHRoZSBHUFUuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhcyBhbiBhcnJheS4KICAgICAgICAgKi8KICAgICAgICBhc0FycmF5KCkgewogICAgICAgICAgICByZXR1cm4gW3RoaXMueCwgdGhpcy55XTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0dGVyIGZyb20gYW4gYXJyYXkuCiAgICAgICAgICovCiAgICAgICAgZnJvbUFycmF5KHZhbHMpIHsKICAgICAgICAgICAgdGhpcy54ID0gdmFsc1swXTsKICAgICAgICAgICAgdGhpcy55ID0gdmFsc1sxXTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIFZlYzMgdG8gYSBzdHJpbmcgaW4gSlNPTiBmb3JtYXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICB0b1N0cmluZygpIHsKICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5ldy1jYXAKICAgICAgICAgICAgcmV0dXJuIFN0cmluZ0Z1bmN0aW9ucy5zdHJpbmdpZnlKU09OV2l0aEZpeGVkUHJlY2lzaW9uKHRoaXMudG9KU09OKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBFbmNvZGVzIFZlYzIgQ2xhc3MgYXMgYSBKU09OIG9iamVjdCBmb3IgcGVyc2lzdGVuY2UuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIHRvSlNPTigpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIHg6IHRoaXMueCwKICAgICAgICAgICAgICAgIHk6IHRoaXMueSwKICAgICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogRGVjb2RlcyBhIEpTT04gb2JqZWN0IHRvIHNldCB0aGUgc3RhdGUgb2YgdGhpcyBjbGFzcy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBqIC0gVGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIGZyb21KU09OKGopIHsKICAgICAgICAgICAgdGhpcy54ID0gai54OwogICAgICAgICAgICB0aGlzLnkgPSBqLnk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIExvYWRzIHRoZSBzdGF0ZSBvZiB0aGUgdmFsdWUgZnJvbSBhIGJpbmFyeSByZWFkZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICByZWFkQmluYXJ5KHJlYWRlcikgewogICAgICAgICAgICB0aGlzLnggPSByZWFkZXIubG9hZEZsb2F0MzIoKTsKICAgICAgICAgICAgdGhpcy55ID0gcmVhZGVyLmxvYWRGbG9hdDMyKCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZSB0aGUgaW50ZXJzZWN0aW9uIHBvaW50IG9mIDIgMmQgbGluZXMsIHJldHVybmluZyB0aGUgcGFyYW1ldGVycyB2YWx1ZXMgZm9yIGVhY2ggbGluZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBwMCAtIFRoZSBwb2ludCBvZiB0aGUgZmlyc3QgbGluZQogICAgICAgICAqIEBwYXJhbSBkMCAtIFRoZSBkaXJlY3Rpb24gb2YgdGhlIGZpcnN0IGxpbmUKICAgICAgICAgKiBAcGFyYW0gcDEgLSBUaGUgcG9pbnQgb2YgdGhlIHNlY29uZCBsaW5lCiAgICAgICAgICogQHBhcmFtIGQxIC0gVGhlIGRpcmVjdGlvbiBvZiB0aGUgc2Vjb25kIGxpbmUKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhbiBhcnJheSBjb250YWluaW5nIDIgcGFyYW1ldGVyIHZhbHVlcyBmb3IgdGhlIDIgbGluZXMuCiAgICAgICAgICovCiAgICAgICAgc3RhdGljIGludGVyc2VjdGlvbk9mTGluZXMocDEsIHAyLCBwMywgcDQpIHsKICAgICAgICAgICAgLy8gaHR0cHM6Ly9kaXJhc2suY29tL3Bvc3RzL0phdmFTY3JpcHQtaG93LXRvLWNhbGN1bGF0ZS1pbnRlcnNlY3Rpb24tcG9pbnQtb2YtdHdvLWxpbmVzLWZvci1naXZlbi00LXBvaW50cy1WanZuQWoKICAgICAgICAgICAgLy8gZG93biBwYXJ0IG9mIGludGVyc2VjdGlvbiBwb2ludCBmb3JtdWxhCiAgICAgICAgICAgIGNvbnN0IGQxID0gKHAxLnggLSBwMi54KSAqIChwMy55IC0gcDQueSk7IC8vICh4MSAtIHgyKSAqICh5MyAtIHk0KQogICAgICAgICAgICBjb25zdCBkMiA9IChwMS55IC0gcDIueSkgKiAocDMueCAtIHA0LngpOyAvLyAoeTEgLSB5MikgKiAoeDMgLSB4NCkKICAgICAgICAgICAgY29uc3QgZCA9IGQxIC0gZDI7CiAgICAgICAgICAgIGlmIChkID09IDApIHsKICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIHVwcGVyIHBhcnQgb2YgaW50ZXJzZWN0aW9uIHBvaW50IGZvcm11bGEKICAgICAgICAgICAgY29uc3QgdTEgPSBwMS54ICogcDIueSAtIHAxLnkgKiBwMi54OyAvLyAoeDEgKiB5MiAtIHkxICogeDIpCiAgICAgICAgICAgIGNvbnN0IHU0ID0gcDMueCAqIHA0LnkgLSBwMy55ICogcDQueDsgLy8gKHgzICogeTQgLSB5MyAqIHg0KQogICAgICAgICAgICBjb25zdCB1MnggPSBwMy54IC0gcDQueDsgLy8gKHgzIC0geDQpCiAgICAgICAgICAgIGNvbnN0IHUzeCA9IHAxLnggLSBwMi54OyAvLyAoeDEgLSB4MikKICAgICAgICAgICAgY29uc3QgdTJ5ID0gcDMueSAtIHA0Lnk7IC8vICh5MyAtIHk0KQogICAgICAgICAgICBjb25zdCB1M3kgPSBwMS55IC0gcDIueTsgLy8gKHkxIC0geTIpCiAgICAgICAgICAgIC8vIGludGVyc2VjdGlvbiBwb2ludCBmb3JtdWxhCiAgICAgICAgICAgIGNvbnN0IHB4ID0gKHUxICogdTJ4IC0gdTN4ICogdTQpIC8gZDsKICAgICAgICAgICAgY29uc3QgcHkgPSAodTEgKiB1MnkgLSB1M3kgKiB1NCkgLyBkOwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzIocHgsIHB5KTsKICAgICAgICB9CiAgICAgICAgaXNWYWxpZCgpIHsKICAgICAgICAgICAgZm9yIChjb25zdCB2IG9mIHRoaXMuYXNBcnJheSgpKSB7CiAgICAgICAgICAgICAgICBpZiAodiA9PSBJbmZpbml0eSB8fCBpc05hTih2KSkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIHRocmVlIGRpbWVuc2lvbmFsIGNvb3JkaW5hdGUsIHN1Y2ggYXMgM0Qgc2NlbmUgdmFsdWVzLCBvciBtZXNoIHZlcnRleCBwb3NpdGlvbnMuCiAgICAgKi8KICAgIGNsYXNzIFZlYzMgewogICAgICAgIHg7CiAgICAgICAgeTsKICAgICAgICB6OwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYSBWZWMzLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKHggPSAwLCB5ID0gMCwgeiA9IDApIHsKICAgICAgICAgICAgdGhpcy54ID0geDsKICAgICAgICAgICAgdGhpcy55ID0geTsKICAgICAgICAgICAgdGhpcy56ID0gejsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0dGVyIGZvciBgeHlgIHN3aXp6ZWwuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgeHkgY29tcG9uZW50cyBhcyBhIFZlYzIuCiAgICAgICAgICovCiAgICAgICAgZ2V0IHh5KCkgewogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzIodGhpcy54LCB0aGlzLnkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBHZXR0ZXIgZm9yIGB5emAgc3dpenplbC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSB5eiBjb21wb25lbnRzIGFzIGEgVmVjMi4KICAgICAgICAgKi8KICAgICAgICBnZXQgeXooKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMih0aGlzLnksIHRoaXMueik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHRlciBmcm9tIHNjYWxhciBjb21wb25lbnRzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHggLSBUaGUgeCBjb21wb25lbnQuCiAgICAgICAgICogQHBhcmFtIHkgLSBUaGUgeSBjb21wb25lbnQuCiAgICAgICAgICogQHBhcmFtIHogLSBUaGUgeSBjb21wb25lbnQuCiAgICAgICAgICovCiAgICAgICAgc2V0KHgsIHksIHopIHsKICAgICAgICAgICAgdGhpcy54ID0geDsKICAgICAgICAgICAgdGhpcy55ID0geSAhPT0gdW5kZWZpbmVkID8geSA6IHg7CiAgICAgICAgICAgIHRoaXMueiA9IHogIT09IHVuZGVmaW5lZCA/IHogOiB4OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHRoZSBzdGF0ZSBvZiBhIFZlYzMgT2JqZWN0IGZyb20gYW5vdGhlciBWZWMzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzMgdG8gc2V0IGZyb20uCiAgICAgICAgICovCiAgICAgICAgc2V0RnJvbU90aGVyKG90aGVyKSB7CiAgICAgICAgICAgIHRoaXMueCA9IG90aGVyLng7CiAgICAgICAgICAgIHRoaXMueSA9IG90aGVyLnk7CiAgICAgICAgICAgIHRoaXMueiA9IG90aGVyLno7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENoZWNrcyBpZiB0aGUgY29vcmRpbmF0ZXMgb2YgdGhpcyBWZWMzIGFyZSAwIDAgMC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgY29vcmRpbmF0ZXMgYXJlKDAsIDAsIDApLCBvdGhlcndpc2UsIGBmYWxzZWAuCiAgICAgICAgICovCiAgICAgICAgaXNOdWxsKCkgewogICAgICAgICAgICByZXR1cm4gTWF0aC5hYnModGhpcy54KSA8IE51bWJlci5FUFNJTE9OICYmIE1hdGguYWJzKHRoaXMueSkgPCBOdW1iZXIuRVBTSUxPTiAmJiBNYXRoLmFicyh0aGlzLnopIDwgTnVtYmVyLkVQU0lMT047CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENoZWNrcyBpZiB0aGUgY29vcmRpbmF0ZXMgb2YgdGhpcyBWZWMzIGFyZSAxIDEgMS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgY29vcmRpbmF0ZXMgYXJlKDEsIDEsIDEpLCBvdGhlcndpc2UsIGBmYWxzZWAuCiAgICAgICAgICovCiAgICAgICAgaXMxMTEoKSB7CiAgICAgICAgICAgIHJldHVybiAoTWF0aC5hYnMoMS4wIC0gdGhpcy54KSA8IE51bWJlci5FUFNJTE9OICYmCiAgICAgICAgICAgICAgICBNYXRoLmFicygxLjAgLSB0aGlzLnkpIDwgTnVtYmVyLkVQU0lMT04gJiYKICAgICAgICAgICAgICAgIE1hdGguYWJzKDEuMCAtIHRoaXMueikgPCBOdW1iZXIuRVBTSUxPTik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENoZWNrcyBpZiB0aGlzIFZlYzMgY29udGFpbnMgdGhlIHNhbWUgdmFsdWVzIGFzIHRoZSBvdGhlciBWZWMzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzMgdG8gY29tcGFyZSB3aXRoLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgdmFsdWVzIGFyZSB0aGUgc2FtZSwgb3RoZXJ3aXNlLCBgZmFsc2VgLgogICAgICAgICAqLwogICAgICAgIGlzRXF1YWwob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMueCA9PSBvdGhlci54ICYmIHRoaXMueSA9PSBvdGhlci55ICYmIHRoaXMueiA9PSBvdGhlci56OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDaGVja3MgaWYgdGhpcyBWZWMyIGlzIGRpZmZlcmVudCBmcm9tIGFub3RoZXIgVmVjMi4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWMzIHRvIGNvbXBhcmUgd2l0aC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIFZlYzNzIGFyZSBkaWZmZXJlbnQsIG90aGVyd2lzZSwgYGZhbHNlYC4KICAgICAgICAgKi8KICAgICAgICBub3RFcXVhbChvdGhlcikgewogICAgICAgICAgICByZXR1cm4gdGhpcy54ICE9IG90aGVyLnggJiYgdGhpcy55ICE9IG90aGVyLnkgJiYgdGhpcy56ICE9IG90aGVyLno7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIFZlYzIgaXMgYXBwcm94aW1hdGVseSB0aGUgc2FtZSBhcyBvdGhlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWMzIHRvIGNvbXBhcmUgd2l0aC4KICAgICAgICAgKiBAcGFyYW0gcHJlY2lzaW9uIC0gVGhlIHByZWNpc2lvbiB0byB3aGljaCB0aGUgdmFsdWVzIG11c3QgbWF0Y2guCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdHJ1ZSBvciBmYWxzZS4KICAgICAgICAgKi8KICAgICAgICBhcHByb3hFcXVhbChvdGhlciwgcHJlY2lzaW9uID0gTnVtYmVyLkVQU0lMT04pIHsKICAgICAgICAgICAgcmV0dXJuIChNYXRoLmFicyh0aGlzLnggLSBvdGhlci54KSA8IHByZWNpc2lvbiAmJgogICAgICAgICAgICAgICAgTWF0aC5hYnModGhpcy55IC0gb3RoZXIueSkgPCBwcmVjaXNpb24gJiYKICAgICAgICAgICAgICAgIE1hdGguYWJzKHRoaXMueiAtIG90aGVyLnopIDwgcHJlY2lzaW9uKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQWRkcyBvdGhlciB0byB0aGlzIFZlYzMgYW5kIHJldHVybiB0aGUgcmVzdWx0IGFzIGEgbmV3IFZlYzMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjMyB0byBhZGQuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgVmVjMy4KICAgICAgICAgKi8KICAgICAgICBhZGQob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMzKHRoaXMueCArIG90aGVyLngsIHRoaXMueSArIG90aGVyLnksIHRoaXMueiArIG90aGVyLnopOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBBZGRzIG90aGVyIHRvIHRoaXMgVmVjMy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWMzIHRvIGFkZC4KICAgICAgICAgKi8KICAgICAgICBhZGRJblBsYWNlKG90aGVyKSB7CiAgICAgICAgICAgIHRoaXMueCArPSBvdGhlci54OwogICAgICAgICAgICB0aGlzLnkgKz0gb3RoZXIueTsKICAgICAgICAgICAgdGhpcy56ICs9IG90aGVyLno7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFN1YnRyYWN0cyBvdGhlciBmcm9tIHRoaXMgVmVjMyBhbmQgcmV0dXJucyB0aGUgcmVzdWx0IGFzIGEgbmV3IFZlYzMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjMyB0byBzdWJ0cmFjdC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBWZWMzLgogICAgICAgICAqLwogICAgICAgIHN1YnRyYWN0KG90aGVyKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyh0aGlzLnggLSBvdGhlci54LCB0aGlzLnkgLSBvdGhlci55LCB0aGlzLnogLSBvdGhlci56KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU3VidHJhY3RzIG90aGVyIGZyb20gdGhpcyBWZWMzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzMgdG8gc3VidHJhY3QuCiAgICAgICAgICovCiAgICAgICAgc3VidHJhY3RJblBsYWNlKG90aGVyKSB7CiAgICAgICAgICAgIHRoaXMueCAtPSBvdGhlci54OwogICAgICAgICAgICB0aGlzLnkgLT0gb3RoZXIueTsKICAgICAgICAgICAgdGhpcy56IC09IG90aGVyLno7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIE11bHRpcGxpZXMgdHdvIFZlYzNzIGFuZCByZXR1cm5zIHRoZSByZXN1bHQgYXMgYSBuZXcgVmVjMy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWMzIHRvIG11bHRpcGx5IHdpdGguCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgVmVjMy4KICAgICAgICAgKi8KICAgICAgICBtdWx0aXBseShvdGhlcikgewogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzModGhpcy54ICogb3RoZXIueCwgdGhpcy55ICogb3RoZXIueSwgdGhpcy56ICogb3RoZXIueik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIE11bHRpcGxpZXMgdHdvIFZlYzNzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzMgdG8gbXVsdGlwbHkgd2l0aC4KICAgICAgICAgKi8KICAgICAgICBtdWx0aXBseUluUGxhY2Uob3RoZXIpIHsKICAgICAgICAgICAgdGhpcy54ICo9IG90aGVyLng7CiAgICAgICAgICAgIHRoaXMueSAqPSBvdGhlci55OwogICAgICAgICAgICB0aGlzLnogKj0gb3RoZXIuejsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogRGl2aWRlcyB0d28gVmVjM3MgYW5kIHJldHVybnMgdGhlIHJlc3VsdCBhcyBhIG5ldyBWZWMzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHZlYzMgLSBUaGUgb3RoZXIgVmVjMyB0byBkaXZpZGUgYnkuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgVmVjMy4KICAgICAgICAgKi8KICAgICAgICBkaXZpZGUodmVjMykgewogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzModGhpcy54IC8gdmVjMy54LCB0aGlzLnkgLyB2ZWMzLnksIHRoaXMueiAvIHZlYzMueik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIERpdmlkZXMgdHdvIFZlYzNzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHZlYzMgLSBUaGUgb3RoZXIgVmVjMyB0byBkaXZpZGUgYnkuCiAgICAgICAgICovCiAgICAgICAgZGl2aWRlSW5QbGFjZSh2ZWMzKSB7CiAgICAgICAgICAgIHRoaXMueCAvPSB2ZWMzLng7CiAgICAgICAgICAgIHRoaXMueSAvPSB2ZWMzLnk7CiAgICAgICAgICAgIHRoaXMueiAvPSB2ZWMzLno7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNjYWxlcyB0aGlzIFZlYzMgYnkgc2NhbGFyIGFuZCByZXR1cm5zIHRoZSByZXN1bHQgYXMgYSBuZXcgVmVjMy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBzY2FsYXIgLSBUaGUgc2NhbGFyIHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzMuCiAgICAgICAgICovCiAgICAgICAgc2NhbGUoc2NhbGFyKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyh0aGlzLnggKiBzY2FsYXIsIHRoaXMueSAqIHNjYWxhciwgdGhpcy56ICogc2NhbGFyKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2NhbGVzIHRoaXMgVmVjMyBieSBzY2FsYXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc2NhbGFyIC0gVGhlIHNjYWxhciB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzY2FsZUluUGxhY2Uoc2NhbGFyKSB7CiAgICAgICAgICAgIHRoaXMueCAqPSBzY2FsYXI7CiAgICAgICAgICAgIHRoaXMueSAqPSBzY2FsYXI7CiAgICAgICAgICAgIHRoaXMueiAqPSBzY2FsYXI7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIE5lZ2F0ZXMgdGhpcyBWZWMzICh4ID0gLXgsIHkgPSAteSBhbmQgeiA9IC16KSwgYnV0IHJldHVybnMgdGhlIHJlc3VsdCBhcyBhIG5ldyBWZWMzLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgVmVjMy4KICAgICAgICAgKi8KICAgICAgICBuZWdhdGUoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMygtdGhpcy54LCAtdGhpcy55LCAtdGhpcy56KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgaW52ZXJzZSBvZiB0aGlzIFZlYzMsIGJ1dCByZXR1cm5zLiB0aGUgcmVzdWx0IGFzIGEgbmV3IFZlYzMKICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzMuCiAgICAgICAgICovCiAgICAgICAgaW52ZXJzZSgpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMzKDEuMCAvIHRoaXMueCwgMS4wIC8gdGhpcy55LCAxLjAgLyB0aGlzLnopOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDYWxjdWxhdGVzIHRoZSBzcXVhcmVkIGxlbmd0aCBvZiB0aGlzIFZlYzMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgbGVuZ3RoLgogICAgICAgICAqLwogICAgICAgIGxlbmd0aFNxdWFyZWQoKSB7CiAgICAgICAgICAgIGNvbnN0IHggPSB0aGlzLng7CiAgICAgICAgICAgIGNvbnN0IHkgPSB0aGlzLnk7CiAgICAgICAgICAgIGNvbnN0IHogPSB0aGlzLno7CiAgICAgICAgICAgIHJldHVybiB4ICogeCArIHkgKiB5ICsgeiAqIHo7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiB0aGlzIFZlYzMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgbGVuZ3RoLgogICAgICAgICAqLwogICAgICAgIGxlbmd0aCgpIHsKICAgICAgICAgICAgcmV0dXJuIE1hdGguc3FydCh0aGlzLmxlbmd0aFNxdWFyZWQoKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIGRpc3RhbmNlIHRvIGFub3RoZXIgVmVjMy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWMzIHRvIGNhbGN1bGF0ZSB0aGUgZGlzdGFuY2UgdG8uCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGRpc3RhbmNlIGJldHdlZW4gdmVjdG9ycy4KICAgICAgICAgKi8KICAgICAgICBkaXN0YW5jZVRvKG90aGVyKSB7CiAgICAgICAgICAgIGNvbnN0IHggPSB0aGlzLnggLSBvdGhlci54OwogICAgICAgICAgICBjb25zdCB5ID0gdGhpcy55IC0gb3RoZXIueTsKICAgICAgICAgICAgY29uc3QgeiA9IHRoaXMueiAtIG90aGVyLno7CiAgICAgICAgICAgIHJldHVybiBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSArIHogKiB6KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogTm9ybWFsaXplcyB0aGUgVmVjMyBhbmQgcmV0dXJucyBpdCBhcyBhIG5ldyBWZWMzLgogICAgICAgICAqIE11bHRpcGxpZXMgY29vcmRpbmF0ZXMgdmFsdWUgYnkgdGhlIGludmVyc2Ugb2YgdGhlIHZlY3RvciBsZW5ndGguCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgVmVjMyBub3JtYWxpemVkLgogICAgICAgICAqLwogICAgICAgIG5vcm1hbGl6ZSgpIHsKICAgICAgICAgICAgbGV0IGxlbiA9IHRoaXMueCAqIHRoaXMueCArIHRoaXMueSAqIHRoaXMueSArIHRoaXMueiAqIHRoaXMuejsKICAgICAgICAgICAgaWYgKGxlbiA8IE51bWJlci5FUFNJTE9OKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZlYzMoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBUT0RPOiBldmFsdWF0ZSB1c2Ugb2YgZ2xtX2ludnNxcnQgaGVyZT8KICAgICAgICAgICAgbGVuID0gMS4wIC8gTWF0aC5zcXJ0KGxlbik7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyh0aGlzLnggKiBsZW4sIHRoaXMueSAqIGxlbiwgdGhpcy56ICogbGVuKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogTm9ybWFsaXplcyB0aGlzIFZlYzMgbXVsdGlwbHlpbmcgY29vcmRpbmF0ZSB2YWx1ZXMgYnkgdGhlIGludmVyc2Ugb2YgdGhlIHZlY3RvciBsZW5ndGguCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBub3JtYWxpemVJblBsYWNlKCkgewogICAgICAgICAgICBsZXQgbGVuID0gdGhpcy54ICogdGhpcy54ICsgdGhpcy55ICogdGhpcy55ICsgdGhpcy56ICogdGhpcy56OwogICAgICAgICAgICBpZiAobGVuIDwgTnVtYmVyLkVQU0lMT04pIHsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZW4gPSBNYXRoLnNxcnQobGVuKTsKICAgICAgICAgICAgY29uc3QgdG1wID0gMS4wIC8gbGVuOwogICAgICAgICAgICB0aGlzLnggKj0gdG1wOwogICAgICAgICAgICB0aGlzLnkgKj0gdG1wOwogICAgICAgICAgICB0aGlzLnogKj0gdG1wOwogICAgICAgICAgICByZXR1cm4gbGVuOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGFuZCByZXR1cm5zIGEgbmV3IFZlYzMgd2l0aCB0aGUgbmV3IGNvb3JkaW5hdGVzKGNhbGN1bGF0ZWQgd2l0aCB0aGlzIFZlYzMgY29vcmRpbmF0ZXMgYW5kIHRoZSBzcGVjaWZpZWQgbGVuZ3RoKS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBsZW5ndGggLSBUaGUgbGVuZ3RoIHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlc2l6ZShsZW5ndGgpIHsKICAgICAgICAgICAgY29uc3QgY3VyckxlbiA9IHRoaXMueCAqIHRoaXMueCArIHRoaXMueSAqIHRoaXMueSArIHRoaXMueiAqIHRoaXMuejsKICAgICAgICAgICAgaWYgKGN1cnJMZW4gPCBOdW1iZXIuRVBTSUxPTikgewogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IHNjbCA9IGxlbmd0aCAvIE1hdGguc3FydChjdXJyTGVuKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMzKHRoaXMueCAqIHNjbCwgdGhpcy55ICogc2NsLCB0aGlzLnogKiBzY2wpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBNb2RpZmllcyBjdXJyZW50IGNvb3JkaW5hdGVzIHVzaW5nIHRoZSBzcGVjaWZpZWQgbGVuZ3RoLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGxlbmd0aCAtIFRoZSBsZW5ndGggdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgcmVzaXplSW5QbGFjZShsZW5ndGgpIHsKICAgICAgICAgICAgY29uc3QgY3VyckxlbiA9IHRoaXMueCAqIHRoaXMueCArIHRoaXMueSAqIHRoaXMueSArIHRoaXMueiAqIHRoaXMuejsKICAgICAgICAgICAgaWYgKGN1cnJMZW4gPCBOdW1iZXIuRVBTSUxPTikgewogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IHNjbCA9IGxlbmd0aCAvIE1hdGguc3FydChjdXJyTGVuKTsKICAgICAgICAgICAgdGhpcy54ICo9IHNjbDsKICAgICAgICAgICAgdGhpcy55ICo9IHNjbDsKICAgICAgICAgICAgdGhpcy56ICo9IHNjbDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsY3VsYXRlcyB0aGUgZG90IHByb2R1Y3Qgb2YgdGhpcyBWZWMzIGFnYWluc3QgYW5vdGhlciBWZWMzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzMgdG8gY29tcGFyZSB3aXRoLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBkb3QgcHJvZHVjdC4KICAgICAgICAgKi8KICAgICAgICBkb3Qob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMueCAqIG90aGVyLnggKyB0aGlzLnkgKiBvdGhlci55ICsgdGhpcy56ICogb3RoZXIuejsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsY3VsYXRlcyB0aGUgY3Jvc3MgcHJvZHVjdCBvZiB0d28gVmVjM3MgYW5kIHJldHVybnMgdGhlIHJlc3VsdCBhcyBhIG5ldyBWZWMzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzMgdG8gY2FsY3VsYXRlIHdpdGguCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGNyb3NzIHByb2R1Y3QgYXMgYSBuZXcgVmVjMy4KICAgICAgICAgKi8KICAgICAgICBjcm9zcyhvdGhlcikgewogICAgICAgICAgICBjb25zdCBheCA9IHRoaXMueDsKICAgICAgICAgICAgY29uc3QgYXkgPSB0aGlzLnk7CiAgICAgICAgICAgIGNvbnN0IGF6ID0gdGhpcy56OwogICAgICAgICAgICBjb25zdCBieCA9IG90aGVyLng7CiAgICAgICAgICAgIGNvbnN0IGJ5ID0gb3RoZXIueTsKICAgICAgICAgICAgY29uc3QgYnogPSBvdGhlci56OwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzMoYXkgKiBieiAtIGF6ICogYnksIGF6ICogYnggLSBheCAqIGJ6LCBheCAqIGJ5IC0gYXkgKiBieCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIGFuZ2xlIGJldHdlZW4gdGhpcyBWZWMzIGFuZCBiLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzMgdG8gY29tcGFyZSB3aXRoLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBhbmdsZSBpbiByYWRpYW5zLgogICAgICAgICAqLwogICAgICAgIGFuZ2xlVG8ob3RoZXIpIHsKICAgICAgICAgICAgY29uc3QgY29zaW5lID0gdGhpcy5kb3Qob3RoZXIpOwogICAgICAgICAgICBpZiAoY29zaW5lID4gMS4wKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHJldHVybiBNYXRoLmFjb3MoY29zaW5lKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBQZXJmb3JtcyBhIGxpbmVhciBpbnRlcnBvbGF0aW9uIGJldHdlZW4gdGhpcyBWZWMzIGFuZCBvdGhlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWMzIHRvIGludGVycG9sYXRlIHRvd2FyZHMuCiAgICAgICAgICogQHBhcmFtIHQgLSBJbnRlcnBvbGF0aW9uIHJhdGlvLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzMuCiAgICAgICAgICovCiAgICAgICAgbGVycChvdGhlciwgdCkgewogICAgICAgICAgICBjb25zdCBheCA9IHRoaXMueDsKICAgICAgICAgICAgY29uc3QgYXkgPSB0aGlzLnk7CiAgICAgICAgICAgIGNvbnN0IGF6ID0gdGhpcy56OwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzMoYXggKyB0ICogKG90aGVyLnggLSBheCksIGF5ICsgdCAqIChvdGhlci55IC0gYXkpLCBheiArIHQgKiAob3RoZXIueiAtIGF6KSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYSBuZXcgVmVjMyB3aG9zZSBjb21wb25lbnQgdmFsdWVzIGFyZSB0aGUgYWJzIG9mIHRoaXMgVmVjM3MgY29tcG9uZW50IHZhbHVlcy4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzMuCiAgICAgICAgICovCiAgICAgICAgYWJzKCkgewogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzMoTWF0aC5hYnModGhpcy54KSwgTWF0aC5hYnModGhpcy55KSwgTWF0aC5hYnModGhpcy56KSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIHZlY3RvciBhIHJhbmRvbSB2ZWN0b3Igb24gdGhlIHN1cmZhY2Ugb2YgYSBzcGhlcmUgd2l0aCB0aGUgcmFkaXVzIG9mIHRoZSBnaXZlbiBzY2FsZSB2YWx1ZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBzY2FsZSAtIFRoZSByYWRpdXMgb2YgdGhlIHN1cmZhY2Ugc3BoZXJlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmFuZG9tIFZlYzMuCiAgICAgICAgICovCiAgICAgICAgc2V0UmFuZG9tRGlyKHNjYWxlID0gMS4wKSB7CiAgICAgICAgICAgIGNvbnN0IHIgPSBNYXRoLnJhbmRvbSgpICogMi4wICogTWF0aC5QSTsKICAgICAgICAgICAgY29uc3QgeiA9IE1hdGgucmFuZG9tKCkgKiAyLjAgLSAxLjA7CiAgICAgICAgICAgIGNvbnN0IHpTY2FsZSA9IE1hdGguc3FydCgxLjAgLSB6ICogeikgKiBzY2FsZTsKICAgICAgICAgICAgdGhpcy54ID0gTWF0aC5jb3MocikgKiB6U2NhbGU7CiAgICAgICAgICAgIHRoaXMueSA9IE1hdGguc2luKHIpICogelNjYWxlOwogICAgICAgICAgICB0aGlzLnogPSB6ICogc2NhbGU7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBHZW5lcmF0ZXMgYSByYW5kb20gdmVjdG9yIGFueXdoZXJlIGluIHRoZSBzcGhlcmUgZGVmaW5lZCBieSB0aGUgcHJvdmlkZWQgc2NhbGUgdmFsdWUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc2NhbGUgLSBUaGUgcmFkaXVzIG9mIHRoZSBib3VuZGluZyBzcGhlcmUuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByYW5kb20gVmVjMy4KICAgICAgICAgKi8KICAgICAgICBzZXRSYW5kb20oc2NhbGUgPSAxLjApIHsKICAgICAgICAgICAgdGhpcy54ID0gKE1hdGgucmFuZG9tKCkgLSAwLjUpICogc2NhbGU7CiAgICAgICAgICAgIHRoaXMueSA9IChNYXRoLnJhbmRvbSgpIC0gMC41KSAqIHNjYWxlOwogICAgICAgICAgICB0aGlzLnogPSAoTWF0aC5yYW5kb20oKSAtIDAuNSkgKiBzY2FsZTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENsb25lcyB0aGlzIFZlYzMgYW5kIHJldHVybnMgYSBuZXcgVmVjMy4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzMuCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyh0aGlzLngsIHRoaXMueSwgdGhpcy56KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgdHlwZSBhcyBhbiBhcnJheS4gT2Z0ZW4gdXNlZCB0byBwYXNzIHR5cGVzIHRvIHRoZSBHUFUuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhcyBhbiBhcnJheS4KICAgICAgICAgKi8KICAgICAgICBhc0FycmF5KCkgewogICAgICAgICAgICByZXR1cm4gW3RoaXMueCwgdGhpcy55LCB0aGlzLnpdOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXR0ZXIgZnJvbSBhbiBhcnJheS4KICAgICAgICAgKi8KICAgICAgICBmcm9tQXJyYXkodmFscykgewogICAgICAgICAgICB0aGlzLnggPSB2YWxzWzBdOwogICAgICAgICAgICB0aGlzLnkgPSB2YWxzWzFdOwogICAgICAgICAgICB0aGlzLnogPSB2YWxzWzFdOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQZXJzaXN0ZW5jZQogICAgICAgIC8qKgogICAgICAgICAqIENvbnZlcnRzIHRoaXMgVmVjMyB0byBhIHN0cmluZyBpbiBKU09OIGZvcm1hdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHRvU3RyaW5nKCkgewogICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbmV3LWNhcAogICAgICAgICAgICByZXR1cm4gU3RyaW5nRnVuY3Rpb25zLnN0cmluZ2lmeUpTT05XaXRoRml4ZWRQcmVjaXNpb24odGhpcy50b0pTT04oKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEVuY29kZXMgVmVjMyBDbGFzcyBhcyBhIEpTT04gb2JqZWN0IGZvciBwZXJzaXN0ZW5jZS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUganNvbiBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgdG9KU09OKCkgewogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgeDogdGhpcy54LAogICAgICAgICAgICAgICAgeTogdGhpcy55LAogICAgICAgICAgICAgICAgejogdGhpcy56LAogICAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBEZWNvZGVzIGEgSlNPTiBvYmplY3QgdG8gc2V0IHRoZSBzdGF0ZSBvZiB0aGlzIGNsYXNzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGogLSBUaGUganNvbiBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgZnJvbUpTT04oaikgewogICAgICAgICAgICB0aGlzLnggPSBqLng7CiAgICAgICAgICAgIHRoaXMueSA9IGoueTsKICAgICAgICAgICAgdGhpcy56ID0gai56OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBMb2FkcyB0aGUgc3RhdGUgb2YgdGhlIHZhbHVlIGZyb20gYSBiaW5hcnkgcmVhZGVyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHJlYWRlciAtIFRoZSByZWFkZXIgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgcmVhZEJpbmFyeShyZWFkZXIpIHsKICAgICAgICAgICAgdGhpcy54ID0gcmVhZGVyLmxvYWRGbG9hdDMyKCk7CiAgICAgICAgICAgIHRoaXMueSA9IHJlYWRlci5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICB0aGlzLnogPSByZWFkZXIubG9hZEZsb2F0MzIoKTsKICAgICAgICB9CiAgICAgICAgaXNWYWxpZCgpIHsKICAgICAgICAgICAgZm9yIChjb25zdCB2IG9mIHRoaXMuYXNBcnJheSgpKSB7CiAgICAgICAgICAgICAgICBpZiAodiA9PSBJbmZpbml0eSB8fCBpc05hTih2KSkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIC8qIGVzbGludC1kaXNhYmxlIG5ldy1jYXAgKi8KICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIGZvdXItZGltZW5zaW9uYWwgY29vcmRpbmF0ZS4KICAgICAqIE1hdGggdHlwZXMgaW50ZXJuYWxseSBzdG9yZSB2YWx1ZXMgaW4ge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Zsb2F0MzJBcnJheXxGbG9hdDMyQXJyYXl9IGFuZAogICAgICogZXhwb3NlIGdldHRlcnMgYW5kIHNldHRlcnMgZm9yIHRoZSBjb21wb25lbnQgdmFsdWVzLgogICAgICoKICAgICAqLwogICAgY2xhc3MgVmVjNCB7CiAgICAgICAgeDsKICAgICAgICB5OwogICAgICAgIHo7CiAgICAgICAgdzsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGEgVmVjNC4KICAgICAgICAgKgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKHggPSAwLCB5ID0gMCwgeiA9IDAsIHcgPSAwKSB7CiAgICAgICAgICAgIHRoaXMueCA9IHg7CiAgICAgICAgICAgIHRoaXMueSA9IHk7CiAgICAgICAgICAgIHRoaXMueiA9IHo7CiAgICAgICAgICAgIHRoaXMudyA9IHc7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHRlciBmb3IgYHh5emAgc3dpenplbC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSB6IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldCB4eXooKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyh0aGlzLngsIHRoaXMueSwgdGhpcy56KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0dGVyIGZyb20gc2NhbGFyIGNvbXBvbmVudHMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0geCAtIFRoZSB4IHZhbHVlLgogICAgICAgICAqIEBwYXJhbSB5ICAtIFRoZSB5IHZhbHVlLgogICAgICAgICAqIEBwYXJhbSB6ICAtIFRoZSB5IHZhbHVlLgogICAgICAgICAqIEBwYXJhbSB3ICAtIFRoZSB3IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldCh4LCB5LCB6LCB3KSB7CiAgICAgICAgICAgIHRoaXMueCA9IHg7CiAgICAgICAgICAgIHRoaXMueSA9IHk7CiAgICAgICAgICAgIHRoaXMueiA9IHo7CiAgICAgICAgICAgIHRoaXMudyA9IHc7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIHN0YXRlIG9mIGEgVmVjNCBPYmplY3QgZnJvbSBhbm90aGVyIFZlYzQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjNCB0byBzZXQgZnJvbS4KICAgICAgICAgKi8KICAgICAgICBzZXRGcm9tT3RoZXIob3RoZXIpIHsKICAgICAgICAgICAgdGhpcy54ID0gb3RoZXIueDsKICAgICAgICAgICAgdGhpcy55ID0gb3RoZXIueTsKICAgICAgICAgICAgdGhpcy56ID0gb3RoZXIuejsKICAgICAgICAgICAgdGhpcy53ID0gb3RoZXIudzsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2hlY2tzIGlmIHRoaXMgVmVjNCBjb250YWlucyB0aGUgc2FtZSB2YWx1ZXMgYXMgdGhlIG90aGVyIFZlYzQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjNCB0byBjb21wYXJlIHdpdGguCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdHJ1ZSBvciBmYWxzZS4KICAgICAgICAgKi8KICAgICAgICBpc0VxdWFsKG90aGVyKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnggPT0gb3RoZXIueCAmJiB0aGlzLnkgPT0gb3RoZXIueSAmJiB0aGlzLnogPT0gb3RoZXIueiAmJiB0aGlzLncgPT0gb3RoZXIudzsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2hlY2tzIGlmIHRoaXMgVmVjNCBpcyBkaWZmZXJlbnQgZnJvbSBhbm90aGVyIFZlYzQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjNCB0byBjb21wYXJlIHdpdGguCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdHJ1ZSBvciBmYWxzZS4KICAgICAgICAgKi8KICAgICAgICBub3RFcXVhbChvdGhlcikgewogICAgICAgICAgICByZXR1cm4gdGhpcy54ICE9IG90aGVyLnggJiYgdGhpcy55ICE9IG90aGVyLnkgJiYgdGhpcy56ICE9IG90aGVyLnogJiYgdGhpcy53ICE9IG90aGVyLnc7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIFZlYzQgaXMgYXBwcm94aW1hdGVseSB0aGUgc2FtZSBhcyBvdGhlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWM0IHRvIGNvbXBhcmUgd2l0aC4KICAgICAgICAgKiBAcGFyYW0gcHJlY2lzaW9uIC0gVGhlIHByZWNpc2lvbiB0byB3aGljaCB0aGUgdmFsdWVzIG11c3QgbWF0Y2guCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgYXBwcm94RXF1YWwob3RoZXIsIHByZWNpc2lvbiA9IE51bWJlci5FUFNJTE9OKSB7CiAgICAgICAgICAgIHJldHVybiAoTWF0aC5hYnModGhpcy54IC0gb3RoZXIueCkgPCBwcmVjaXNpb24gJiYKICAgICAgICAgICAgICAgIE1hdGguYWJzKHRoaXMueSAtIG90aGVyLnkpIDwgcHJlY2lzaW9uICYmCiAgICAgICAgICAgICAgICBNYXRoLmFicyh0aGlzLnogLSBvdGhlci56KSA8IHByZWNpc2lvbiAmJgogICAgICAgICAgICAgICAgTWF0aC5hYnModGhpcy53IC0gb3RoZXIudykgPCBwcmVjaXNpb24pOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBBZGRzIG90aGVyIHRvIHRoaXMgVmVjNCBhbmQgcmV0dXJucyB0aGUgcmVzdWx0IGFzIGEgbmV3IFZlYzQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjNCB0byBhZGQuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgVmVjNC4KICAgICAgICAgKi8KICAgICAgICBhZGQob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWM0KHRoaXMueCArIG90aGVyLngsIHRoaXMueSArIG90aGVyLnksIHRoaXMueiArIG90aGVyLnosIHRoaXMudyArIG90aGVyLncpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBBZGRzIG90aGVyIHRvIHRoaXMgVmVjNCBtdXRhdGluZyB0aGUgdmFsdWVzIG9mIHRoaXMgaW5zdGFuY2UKICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWM0IHRvIGFkZC4KICAgICAgICAgKi8KICAgICAgICBhZGRJblBsYWNlKG90aGVyKSB7CiAgICAgICAgICAgIHRoaXMueCArPSBvdGhlci54OwogICAgICAgICAgICB0aGlzLnkgKz0gb3RoZXIueTsKICAgICAgICAgICAgdGhpcy56ICs9IG90aGVyLno7CiAgICAgICAgICAgIHRoaXMudyArPSBvdGhlci53OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTdWJ0cmFjdHMgb3RoZXIgZnJvbSB0aGlzIFZlYzQgYW5kIHJldHVybnMgdGhlbiByZXN1bHQgYXMgYSBuZXcgVmVjNC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWM0IHRvIHN1YnRyYWN0LgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzQuCiAgICAgICAgICovCiAgICAgICAgc3VidHJhY3Qob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWM0KHRoaXMueCAtIG90aGVyLngsIHRoaXMueSAtIG90aGVyLnksIHRoaXMueiAtIG90aGVyLnosIHRoaXMudyAtIG90aGVyLncpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTdWJ0cmFjdHMgb3RoZXIgZnJvbSB0aGlzIFZlYzQgbXV0YXRpbmcgdGhlIHZhbHVlcyBvZiB0aGlzIGluc3RhbmNlCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjNCB0byBzdWJ0cmFjdC4KICAgICAgICAgKi8KICAgICAgICBzdWJ0cmFjdEluUGxhY2Uob3RoZXIpIHsKICAgICAgICAgICAgdGhpcy54IC09IG90aGVyLng7CiAgICAgICAgICAgIHRoaXMueSAtPSBvdGhlci55OwogICAgICAgICAgICB0aGlzLnogLT0gb3RoZXIuejsKICAgICAgICAgICAgdGhpcy53IC09IG90aGVyLnc7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIE11bHRpcGxpZXMgdHdvIFZlYzRzIGFuZCByZXR1cm5zIHRoZSByZXN1bHQgYXMgYSBuZXcgVmVjNC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWM0IHRvIG11bHRpcGx5IHdpdGguCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgVmVjNC4KICAgICAgICAgKi8KICAgICAgICBtdWx0aXBseShvdGhlcikgewogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzQodGhpcy54ICogb3RoZXIueCwgdGhpcy55ICogb3RoZXIueSwgdGhpcy56ICogb3RoZXIueiwgdGhpcy53ICogb3RoZXIudyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIE11bHRpcGxpZXMgdHdvIFZlYzRzIG11dGF0aW5nIHRoZSB2YWx1ZXMgb2YgdGhpcyBpbnN0YW5jZQogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzQgdG8gbXVsdGlwbHkgd2l0aC4KICAgICAgICAgKi8KICAgICAgICBtdWx0aXBseUluUGxhY2Uob3RoZXIpIHsKICAgICAgICAgICAgdGhpcy54ICo9IG90aGVyLng7CiAgICAgICAgICAgIHRoaXMueSAqPSBvdGhlci55OwogICAgICAgICAgICB0aGlzLnogKj0gb3RoZXIuejsKICAgICAgICAgICAgdGhpcy53ICo9IG90aGVyLnc7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIERpdmlkZXMgdHdvIFZlYzRzIGFuZCByZXR1cm5zIHRoZSByZXN1bHQgYXMgYSBuZXcgVmVjNC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWM0IHRvIGRpdmlkZSBieS4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBWZWM0LgogICAgICAgICAqLwogICAgICAgIGRpdmlkZShvdGhlcikgewogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzQodGhpcy54IC8gb3RoZXIueCwgdGhpcy55IC8gb3RoZXIueSwgdGhpcy56IC8gb3RoZXIueiwgdGhpcy53IC8gb3RoZXIudyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIERpdmlkZXMgdHdvIFZlYzRzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzQgdG8gZGl2aWRlIGJ5LgogICAgICAgICAqLwogICAgICAgIGRpdmlkZUluUGxhY2Uob3RoZXIpIHsKICAgICAgICAgICAgdGhpcy54IC89IG90aGVyLng7CiAgICAgICAgICAgIHRoaXMueSAvPSBvdGhlci55OwogICAgICAgICAgICB0aGlzLnogLz0gb3RoZXIuejsKICAgICAgICAgICAgdGhpcy53IC89IG90aGVyLnc7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNjYWxlcyB0aGlzIFZlYzQgYnkgc2NhbGFyIGFuZCByZXR1cm5zIHRoZSByZXN1bHQgYXMgYSBuZXcgVmVjNC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBzY2FsYXIgLSBUaGUgc2NhbGFyIHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNjYWxlKHNjYWxhcikgewogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzQodGhpcy54ICogc2NhbGFyLCB0aGlzLnkgKiBzY2FsYXIsIHRoaXMueiAqIHNjYWxhciwgdGhpcy53ICogc2NhbGFyKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2NhbGVzIHRoaXMgVmVjNCBieSBzY2FsYXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc2NhbGFyIC0gVGhlIHNjYWxhciB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzY2FsZUluUGxhY2Uoc2NhbGFyKSB7CiAgICAgICAgICAgIHRoaXMuc2V0KHRoaXMueCAqIHNjYWxhciwgdGhpcy55ICogc2NhbGFyLCB0aGlzLnogKiBzY2FsYXIsIHRoaXMudyAqIHNjYWxhcik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiB0aGlzIFZlYzQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgbGVuZ3RoLgogICAgICAgICAqLwogICAgICAgIGxlbmd0aCgpIHsKICAgICAgICAgICAgY29uc3QgeCA9IHRoaXMueDsKICAgICAgICAgICAgY29uc3QgeSA9IHRoaXMueTsKICAgICAgICAgICAgY29uc3QgeiA9IHRoaXMuejsKICAgICAgICAgICAgY29uc3QgdyA9IHRoaXMudzsKICAgICAgICAgICAgcmV0dXJuIE1hdGguc3FydCh4ICogeCArIHkgKiB5ICsgeiAqIHogKyB3ICogdyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgbGVuZ3RoIG9mIHRoaXMgVmVjNC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBsZW5ndGguCiAgICAgICAgICovCiAgICAgICAgbGVuZ3RoU3F1YXJlZCgpIHsKICAgICAgICAgICAgY29uc3QgeCA9IHRoaXMueDsKICAgICAgICAgICAgY29uc3QgeSA9IHRoaXMueTsKICAgICAgICAgICAgY29uc3QgeiA9IHRoaXMuejsKICAgICAgICAgICAgY29uc3QgdyA9IHRoaXMudzsKICAgICAgICAgICAgcmV0dXJuIHggKiB4ICsgeSAqIHkgKyB6ICogeiArIHcgKiB3OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBOb3JtYWxpemVzIHRoZSBWZWM0IGFuZCByZXR1cm5zIGl0IGFzIGEgbmV3IFZlYzQuCiAgICAgICAgICogTXVsdGlwbGllcyBjb29yZGluYXRlcyB2YWx1ZSBieSB0aGUgaW52ZXJzZSBvZiB0aGUgdmVjdG9yIGxlbmd0aC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBWZWM0IG5vcm1hbGl6ZWQuCiAgICAgICAgICovCiAgICAgICAgbm9ybWFsaXplKCkgewogICAgICAgICAgICBjb25zdCB4ID0gdGhpcy54OwogICAgICAgICAgICBjb25zdCB5ID0gdGhpcy55OwogICAgICAgICAgICBjb25zdCB6ID0gdGhpcy56OwogICAgICAgICAgICBjb25zdCB3ID0gdGhpcy53OwogICAgICAgICAgICBsZXQgbGVuID0geCAqIHggKyB5ICogeSArIHogKiB6ICsgdyAqIHc7CiAgICAgICAgICAgIGlmIChsZW4gPCBOdW1iZXIuRVBTSUxPTikgewogICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWM0KCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/CiAgICAgICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWM0KHggKiBsZW4sIHkgKiBsZW4sIHogKiBsZW4pOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBOb3JtYWxpemVzIHRoaXMgVmVjNCBtdWx0aXBseWluZyBjb29yZGluYXRlIHZhbHVlcyBieSB0aGUgaW52ZXJzZSBvZiB0aGUgdmVjdG9yIGxlbmd0aC4KICAgICAgICAgKi8KICAgICAgICBub3JtYWxpemVJblBsYWNlKCkgewogICAgICAgICAgICBjb25zdCB4ID0gdGhpcy54OwogICAgICAgICAgICBjb25zdCB5ID0gdGhpcy55OwogICAgICAgICAgICBjb25zdCB6ID0gdGhpcy56OwogICAgICAgICAgICBjb25zdCB3ID0gdGhpcy53OwogICAgICAgICAgICBsZXQgbGVuID0geCAqIHggKyB5ICogeSArIHogKiB6ICsgdyAqIHc7CiAgICAgICAgICAgIGlmIChsZW4gPCBOdW1iZXIuRVBTSUxPTikgewogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTsKICAgICAgICAgICAgdGhpcy5zZXQoeCAqIGxlbiwgeSAqIGxlbiwgeiAqIGxlbiwgdyAqIGxlbik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIGRvdCBwcm9kdWN0IG9mIHRoaXMgVmVjNCBhZ2FpbnN0IGFub3RoZXIgVmVjNC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWM0IHRvIGNvbXBhcmUgd2l0aC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgZG90IHByb2R1Y3QuCiAgICAgICAgICovCiAgICAgICAgZG90KG90aGVyKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnggKiBvdGhlci54ICsgdGhpcy55ICogb3RoZXIueSArIHRoaXMueiAqIG90aGVyLnogKyB0aGlzLncgKiBvdGhlci53OyAvLyBUT0RPOiBvdGhlci53IHVzZWQgdG8gYmUgYi53PwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDYWxjdWxhdGVzIHRoZSBjcm9zcyBwcm9kdWN0IG9mIHR3byBWZWM0cyBhbmQgcmV0dXJucyB0aGUgcmVzdWx0IGFzIGEgbmV3IFZlYzQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgVmVjNCB0byBjYWxjdWxhdGUgd2l0aC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgY3Jvc3MgcHJvZHVjdCBhcyBhIG5ldyBWZWM0LgogICAgICAgICAqLwogICAgICAgIGNyb3NzKG90aGVyKSB7CiAgICAgICAgICAgIGNvbnN0IGF4ID0gdGhpcy54OwogICAgICAgICAgICBjb25zdCBheSA9IHRoaXMueTsKICAgICAgICAgICAgY29uc3QgYXogPSB0aGlzLno7CiAgICAgICAgICAgIGNvbnN0IGF0ID0gdGhpcy53OwogICAgICAgICAgICBjb25zdCBieCA9IG90aGVyLng7CiAgICAgICAgICAgIGNvbnN0IGJ5ID0gb3RoZXIueTsKICAgICAgICAgICAgY29uc3QgYnogPSBvdGhlci56OwogICAgICAgICAgICBjb25zdCBidCA9IG90aGVyLnc7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjNChheSAqIGJ6IC0gYXogKiBieSwgYXogKiBidCAtIGF0ICogYnosIGF0ICogYnggLSBheCAqIGJ0LCBheCAqIGJ5IC0gYXkgKiBieCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIGFuZ2xlIGJldHdlZW4gdGhpcyBWZWM0IGFuZCBiLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFZlYzQgdG8gY29tcGFyZSB3aXRoLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBhbmdsZSBpbiByYWRpYW5zLgogICAgICAgICAqLwogICAgICAgIGFuZ2xlVG8ob3RoZXIpIHsKICAgICAgICAgICAgY29uc3QgdGVtcEEgPSB0aGlzLm5vcm1hbGl6ZSgpOwogICAgICAgICAgICBjb25zdCB0ZW1wQiA9IG90aGVyLm5vcm1hbGl6ZSgpOwogICAgICAgICAgICBjb25zdCBjb3NpbmUgPSB0ZW1wQS5kb3QodGVtcEIpOwogICAgICAgICAgICBpZiAoY29zaW5lID4gMS4wKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHJldHVybiBNYXRoLmFjb3MoY29zaW5lKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBQZXJmb3JtcyBhIGxpbmVhciBpbnRlcnBvbGF0aW9uIGJldHdlZW4gdGhpcyBWZWM0IGFuZCBvdGhlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWM0IHRvIGludGVycG9sYXRlIGJldHdlZW4uCiAgICAgICAgICogQHBhcmFtIHcgLSBJbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzQuCiAgICAgICAgICovCiAgICAgICAgbGVycChvdGhlciwgdCkgewogICAgICAgICAgICBjb25zdCBheCA9IHRoaXMueDsKICAgICAgICAgICAgY29uc3QgYXkgPSB0aGlzLnk7CiAgICAgICAgICAgIGNvbnN0IGF6ID0gdGhpcy56OwogICAgICAgICAgICBjb25zdCBhdCA9IHRoaXMudzsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWM0KGF4ICsgdCAqIChvdGhlci54IC0gYXgpLCBheSArIHQgKiAob3RoZXIueSAtIGF5KSwgYXogKyB0ICogKG90aGVyLnogLSBheiksIGF0ICsgdCAqIChvdGhlci53IC0gYXQpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogR2VuZXJhdGVzIGEgcmFuZG9tIHZlY3RvciB3aXRoIHRoZSBnaXZlbiBzY2FsZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBzY2FsZSAtIExlbmd0aCBvZiB0aGUgcmVzdWx0aW5nIHZlY3Rvci4gSWYgb21pdHRlZCwgYSB1bml0IHZlY3RvciB3aWxsIGJlIHJldHVybmVkLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIC8vIHJhbmRvbShzY2FsZSA9IDEuMCkgewogICAgICAgIC8vICAgY29uc3QgciA9IGdsTWF0cml4LlJBTkRPTSgpICogMi4wICogTWF0aC5QSQogICAgICAgIC8vICAgY29uc3QgeiA9IGdsTWF0cml4LlJBTkRPTSgpICogMi4wIC0gMS4wCiAgICAgICAgLy8gICBjb25zdCB6U2NhbGUgPSBNYXRoLnNxcnQoMS4wIC0geiAqIHopICogc2NhbGUKICAgICAgICAvLyAgIG91dFswXSA9IE1hdGguY29zKHIpICogelNjYWxlCiAgICAgICAgLy8gICBvdXRbMV0gPSBNYXRoLnNpbihyKSAqIHpTY2FsZQogICAgICAgIC8vICAgb3V0WzJdID0geiAqIHNjYWxlCiAgICAgICAgLy8gICByZXR1cm4gb3V0CiAgICAgICAgLy8gfQogICAgICAgIC8qKgogICAgICAgICAqIENsb25lcyB0aGlzIFZlYzQgYW5kIHJldHVybnMgYSBuZXcgVmVjNC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzQuCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjNCh0aGlzLngsIHRoaXMueSwgdGhpcy56LCB0aGlzLncpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIFZlYzQgaW50byBhIFZlYzMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgdmFsdWUgYXMgYSBuZXcgVmVjMy4KICAgICAgICAgKi8KICAgICAgICB0b1ZlYzMoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyh0aGlzLngsIHRoaXMueSwgdGhpcy56KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgdHlwZSBhcyBhbiBhcnJheS4gT2Z0ZW4gdXNlZCB0byBwYXNzIHR5cGVzIHRvIHRoZSBHUFUuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhcyBhbiBhcnJheS4KICAgICAgICAgKi8KICAgICAgICBhc0FycmF5KCkgewogICAgICAgICAgICByZXR1cm4gW3RoaXMueCwgdGhpcy55LCB0aGlzLnosIHRoaXMud107CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHRlciBmcm9tIGFuIGFycmF5LgogICAgICAgICAqLwogICAgICAgIGZyb21BcnJheSh2YWxzKSB7CiAgICAgICAgICAgIHRoaXMueCA9IHZhbHNbMF07CiAgICAgICAgICAgIHRoaXMueSA9IHZhbHNbMV07CiAgICAgICAgICAgIHRoaXMueiA9IHZhbHNbMV07CiAgICAgICAgICAgIHRoaXMudyA9IHZhbHNbMV07CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIFBlcnNpc3RlbmNlCiAgICAgICAgLyoqCiAgICAgICAgICogQ29udmVydHMgdGhpcyBWZWMzIHRvIGEgc3RyaW5nIGluIEpTT04gZm9ybWF0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgdG9TdHJpbmcoKSB7CiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuZXctY2FwCiAgICAgICAgICAgIHJldHVybiBTdHJpbmdGdW5jdGlvbnMuc3RyaW5naWZ5SlNPTldpdGhGaXhlZFByZWNpc2lvbih0aGlzLnRvSlNPTigpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHRvSlNPTiBtZXRob2QgZW5jb2RlcyB0aGlzIHR5cGUgYXMgYSBqc29uIG9iamVjdCBmb3IgcGVyc2lzdGVuY2UuCiAgICAgICAgICogQHJldHVybiAtIFRoZSBqc29uIG9iamVjdC4KICAgICAgICAgKi8KICAgICAgICB0b0pTT04oKSB7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICB4OiB0aGlzLngsCiAgICAgICAgICAgICAgICB5OiB0aGlzLnksCiAgICAgICAgICAgICAgICB6OiB0aGlzLnosCiAgICAgICAgICAgICAgICB3OiB0aGlzLncsCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIERlY29kZXMgYSBKU09OIG9iamVjdCB0byBzZXQgdGhlIHN0YXRlIG9mIHRoaXMgY2xhc3MuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaiAtIFRoZSBqc29uIG9iamVjdC4KICAgICAgICAgKi8KICAgICAgICBmcm9tSlNPTihqKSB7CiAgICAgICAgICAgIHRoaXMueCA9IGoueDsKICAgICAgICAgICAgdGhpcy55ID0gai55OwogICAgICAgICAgICB0aGlzLnogPSBqLno7CiAgICAgICAgICAgIHRoaXMudyA9IGoudzsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogTG9hZHMgdGhlIHN0YXRlIG9mIHRoZSB2YWx1ZSBmcm9tIGEgYmluYXJ5IHJlYWRlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSByZWFkZXIgLSBUaGUgcmVhZGVyIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyKSB7CiAgICAgICAgICAgIHRoaXMueCA9IHJlYWRlci5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICB0aGlzLnkgPSByZWFkZXIubG9hZEZsb2F0MzIoKTsKICAgICAgICAgICAgdGhpcy56ID0gcmVhZGVyLmxvYWRGbG9hdDMyKCk7CiAgICAgICAgICAgIHRoaXMudyA9IHJlYWRlci5sb2FkRmxvYXQzMigpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBWZXJpZmllcyBpZiB0aGUgdmFsdWVzIHN0b3JlZCBpbiB0aGlzIE1hdGggdHlwZSBhcmUgdmFsaWQgbnVtZXJpYyB2YWx1ZXMuCiAgICAgICAgICogUmV0dXJucyBgZmFsc2VgIElmIGF0IGxlYXN0IG9uZSBvZiB0aGUgdmFsdWVzIGlzIGVpdGhlciB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2lhL09iamV0b3NfZ2xvYmFsZXMvSW5maW5pdHl8SW5maW5pdHl9IG9yCiAgICAgICAgICoge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNpYS9PYmpldG9zX2dsb2JhbGVzL05hTnxOYU59LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIHJlc3VsdCBhcyBhIGJvb2xlYW4uCiAgICAgICAgICovCiAgICAgICAgaXNWYWxpZCgpIHsKICAgICAgICAgICAgZm9yIChjb25zdCB2IG9mIHRoaXMuYXNBcnJheSgpKSB7CiAgICAgICAgICAgICAgICBpZiAodiA9PSBJbmZpbml0eSB8fCBpc05hTih2KSkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIGxldCByZWdpc3RlcmVkQ2xhc3NlcyA9IHt9OwogICAgbGV0IGNsYXNzTmFtZXMgPSB7fTsKICAgIGxldCBjbGFzc0RlZmluaXRpb25zID0gW107CiAgICAvKioKICAgICAqIFJlZ2lzdHJ5IGlzIGEgc3RhdGljIGZhY3RvcnkgdGhhdCBoYW5kbGVzIHJlZ2lzdHJhdGlvbi9yZWNvbnN0cnVjdGlvbiBvZgogICAgICogY2xhc3NlcyBiYXNlcyBvbiBCYXNlQ2xhc3MuIFJlZ2lzdGVyZWQgY2xhc3NlcyBjYW4gdGhlbiBiZSBjb25zdHJ1Y3RlZCBieSB0aGUgUmVnaXN0cnkgYnkgbmFtZS4KICAgICAqCiAgICAgKiBOb3RlOiBjbGFzc05hbWUgaXMgcmVxdWlyZWQgYmVjYXVzZSBvbiBtaW5pZmljYXRpb24gcHJvY2VzcwogICAgICogdGhlIG5hbWUgb2YgY2xhc3NlcyBjaGFuZ2UgYW5kIHdlIGNhbid0IHNpbXBseSB1c2UgJy4uLi5jb25zdHJ1Y3Rvci5uYW1lJy4KICAgICAqIFNvLCB3ZSBuZWVkIGEgd2F5IG9mIHJlbGF0aW5nIG1pbmlmaWVkIGNsYXNzIG5hbWVzIHRvIHRoZSBvbmUgc3RvcmVkIGZvciBwZXJzaXN0ZW5jeS4KICAgICAqCiAgICAgKiBpLmUuCiAgICAgKiBgYGBqYXZhc2NyaXB0CiAgICAgKiAvLyBJbXBvcnQgcmVnaXN0cnkgY2xhc3MKICAgICAqIGNsYXNzIEZvbygpIGV4dGVuZHMgQmFzZUNsYXNzIHt9CiAgICAgKgogICAgICogUmVnaXN0cnkucmVnaXN0ZXIoJ0ZvbycsIEZvbykKICAgICAqIC8vIEluIGNhc2UgJ0ZvbycgY2xhc3MgZ2V0cyBpdHMgbmFtZSBjaGFuZ2VkIHRvICdjJyBvbiBtaW5pZmljYXRpb24sCiAgICAgKiAvLyBhbmQgdGhlIHBlcnNpc3RlZCBkYXRhIHR5cGUgaXMgJ0ZvbycsIHdlIHdvdWxkIGtub3cgaG93IHRvIHJlbGF0ZSB0aGVtLgogICAgICogYGBgCiAgICAgKgogICAgICogQHN0YXRpYwogICAgICogQGNsYXNzIFJlZ2lzdHJ5CiAgICAgKi8KICAgIGNsYXNzIFJlZ2lzdHJ5IHsKICAgICAgICAvKioKICAgICAgICAgKiBSZWdpc3RlcnMgYSBuZXcgY2xhc3MgdG8gdGhlIGZhY3RvcnkuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gY2xhc3NOYW1lIC0gTmFtZSBvZiB0aGUgcmVnaXN0ZXJlZCBjbGFzcwogICAgICAgICAqIEBwYXJhbSBjbGFzc0RlZiAtIENsYXNzIHJlcHJlc2VudGF0aW9uKENsYXNzIGZ1bmN0aW9uLCB0eXBlKQogICAgICAgICAqLwogICAgICAgIHN0YXRpYyByZWdpc3RlcihjbGFzc05hbWUsIGNsYXNzRGVmKSB7CiAgICAgICAgICAgIGlmIChjbGFzc05hbWUgaW4gcmVnaXN0ZXJlZENsYXNzZXMpIHsKICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgVGhlcmUncyBhIGNsYXNzIHJlZ2lzdGVyZWQgd2l0aCAnJHtjbGFzc05hbWV9JyBuYW1lLiBTZWNvbmQgcmVnaXN0cmF0aW9uIGZhaWxlZC5gKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBOb3RlOiBUbyBwcm92aWRlIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LCBzYW1lIGNsYXNzRGVmIGNhbiBiZSBzdG9yZWQgdW5kZXIgbXVsdGlwbGUgbmFtZXMuCiAgICAgICAgICAgIC8vIFRoYXRzIHRoZSByZWFzb24gYmVoaW5kIHVzaW5nIGluZGV4ZXMgaW5zdGVhZCBvZiB0aGUgY2xhc3NEZWYuCiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gY2xhc3NEZWZpbml0aW9ucy5sZW5ndGg7CiAgICAgICAgICAgIGNsYXNzRGVmaW5pdGlvbnMucHVzaChjbGFzc0RlZik7CiAgICAgICAgICAgIGNsYXNzTmFtZXNbaW5kZXhdID0gY2xhc3NOYW1lOwogICAgICAgICAgICByZWdpc3RlcmVkQ2xhc3Nlc1tjbGFzc05hbWVdID0gaW5kZXg7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgY2xhc3MgZGVmaW5pdGlvbiB1c2luZyB0aGUgbmFtZSBpdCB3YXMgcmVnaXN0ZXJlZCB3aXRoLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGNsYXNzTmFtZSAtIE5hbWUgb2YgdGhlIHJlZ2lzdGVyZWQgY2xhc3MKICAgICAgICAgKiBAcmV0dXJuIC0gQ2xhc3MgcmVwcmVzZW50YXRpb24oQ2xhc3MgZnVuY3Rpb24sIHR5cGUpCiAgICAgICAgICovCiAgICAgICAgc3RhdGljIGdldENsYXNzRGVmaW5pdGlvbihjbGFzc05hbWUpIHsKICAgICAgICAgICAgaWYgKCEoY2xhc3NOYW1lIGluIHJlZ2lzdGVyZWRDbGFzc2VzKSkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjbGFzc05hbWV9IGNsYXNzIGlzIG5vdCByZWdpc3RlcmVkYCk7CiAgICAgICAgICAgIHJldHVybiBjbGFzc0RlZmluaXRpb25zW3JlZ2lzdGVyZWRDbGFzc2VzW2NsYXNzTmFtZV1dOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIGNsYXNzIG5hbWUgcmVnaXN0ZXJlZCBmb3IgdGhlIGluc3RhbnRpYXRlZCBvYmplY3QuCiAgICAgICAgICogQHBhcmFtIGNsYXNzRGVmaW5pdGlvbiAtIENsYXNzIHR5cGUgZGVmaW5pdGlvbi4KICAgICAgICAgKiBAcmV0dXJuIC0gTmFtZSBvZiB0aGUgcmVnaXN0ZXJlZCBjbGFzcwogICAgICAgICAqLwogICAgICAgIHN0YXRpYyBnZXRDbGFzc05hbWUoY2xhc3NEZWZpbml0aW9uKSB7CiAgICAgICAgICAgIGNvbnN0IGNsYXNzSWQgPSBjbGFzc0RlZmluaXRpb25zLmluZGV4T2YoY2xhc3NEZWZpbml0aW9uKTsKICAgICAgICAgICAgaWYgKGNsYXNzSWQgPj0gMCAmJiBjbGFzc05hbWVzW2NsYXNzSWRdKQogICAgICAgICAgICAgICAgcmV0dXJuIGNsYXNzTmFtZXNbY2xhc3NJZF07CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgY2xhc3MgaXMgbm90IHJlZ2lzdGVyZWRgKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGZhY3RvcnkgZnVuY3Rpb24gdGhhdCBjb25zdHJ1Y3QgdGhlIGNsYXNzIHJlZ2lzdGVyZWQgdW5kZXIgdGhlIGdpdmVuIG5hbWUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gY2xhc3NOYW1lIC0gTmFtZSBvZiB0aGUgcmVnaXN0ZXJlZCBjbGFzcwogICAgICAgICAqIEByZXR1cm4gLSBJbnN0YW50aWF0ZWQgb2JqZWN0IG9mIHRoZSBzcGVjaWZpZWQgY2xhc3MKICAgICAgICAgKi8KICAgICAgICBzdGF0aWMgY29uc3RydWN0Q2xhc3MoY2xhc3NOYW1lKSB7CiAgICAgICAgICAgIGNvbnN0IGNsYXNzRGVmaW5pdGlvbiA9IGNsYXNzRGVmaW5pdGlvbnNbcmVnaXN0ZXJlZENsYXNzZXNbY2xhc3NOYW1lXV07CiAgICAgICAgICAgIGlmICghY2xhc3NEZWZpbml0aW9uKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NsYXNzTmFtZX0gY2xhc3MgaXMgbm90IHJlZ2lzdGVyZWRgKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBjbGFzc0RlZmluaXRpb24oKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogRm9yIHRlc3RpbmcgcHVycG9zZSBvbmx5LCBuZXZlciBjYWxsIHRoaXMgb3V0c2lkZSBvZiB0aGUgdGVzdCBzY29wZS4KICAgICAgICAgKgogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICovCiAgICAgICAgc3RhdGljIGZsdXNoKCkgewogICAgICAgICAgICByZWdpc3RlcmVkQ2xhc3NlcyA9IHt9OwogICAgICAgICAgICBjbGFzc05hbWVzID0ge307CiAgICAgICAgICAgIGNsYXNzRGVmaW5pdGlvbnMgPSBbXTsKICAgICAgICB9CiAgICB9CgogICAgLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqLwogICAgbGV0IGNvdW50ZXIgPSAwOwogICAgLyoqCiAgICAgKiBDbGFzcyByZXByZXNlbnRpbmcgYSBCYXNlQ2xhc3MuCiAgICAgKiBUaGUgQmFzZUNsYXNzIGlzIHRoZSBmb3VuZGF0aW9uIGNsYXNzIG9mIHRoZSBTY2VuZVRyZWUsIGFzIGFsbW9zdCBhbGwgY2xhc3NlcyBkZXJpdmUgZnJvbSBpdC4KICAgICAqLwogICAgY2xhc3MgQmFzZUNsYXNzIHsKICAgICAgICBfX2lkOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhbiBCYXNlQ2xhc3MuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgICAgIHRoaXMuX19pZCA9ICsrY291bnRlcjsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogRXZlcnkgaW5zdGFuY2Ugb2YgZWFjaCBjbGFzcyBiYXNlZCBvbiBCYXNlQ2xhc3MgaXMgYXNzaWduZWQgYSB1bmlxdWUgbnVtYmVyLgogICAgICAgICAqIFRoaXMgbnVtYmVyIGlzIG5vdCBwZXJzaXN0ZW50IGluIGJldHdlZW4gZGlmZmVyZW50IGxvYWRzIG9mIGEgc2NlbmUuCiAgICAgICAgICogUmV0dXJucyB0aGUgdW5pcXVlIGlkIG9mIHRoZSBvYmplY3QuCiAgICAgICAgICogQHJldHVybiAtIFRoZSBJZCBvZiB0aGUgb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIGdldElkKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fX2lkOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSB1bm1hbmdsZWQgbmFtZSBvZiB0aGUgY2xhc3MuCiAgICAgICAgICogQHJldHVybiAtIFRoZSBuYW1lIG9mIHRoZSBjbGFzcyBkZWZpbml0aW9uLgogICAgICAgICAqLwogICAgICAgIGdldENsYXNzTmFtZSgpIHsKICAgICAgICAgICAgcmV0dXJuIFJlZ2lzdHJ5LmdldENsYXNzTmFtZShPYmplY3QuZ2V0UHJvdG90eXBlT2YodGhpcykuY29uc3RydWN0b3IpOwogICAgICAgIH0KICAgIH0KCiAgICAvKiogQ2xhc3MgcmVwcmVzZW50aW5nIGEgQmFzZUV2ZW50LiAqLwogICAgY2xhc3MgQmFzZUV2ZW50IHsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgYW4gQmFzZUV2ZW50LgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKCkgeyB9CiAgICB9CgogICAgLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqLwogICAgLyoqCiAgICAgKiBQcm92aWRlcyBhbiBpbnRlcmZhY2UgZm9yIGVtaXR0aW5nIGV2ZW50cyB1bmRlciBnaXZlbiBuYW1lcywgYW5kIHJlZ2lzdGVyaW5nIGxpc3RlbmVycyB0byB0aG9zZSBldmVudHMuCiAgICAgKiBUaGlzIGlzIGEgYmFzZSBjbGFzcyBmb3IgbW9zdCBjbGFzc2VzIGluIHRoZSBTY2VuZSBUcmVlIGFuZCBSZW5kZXJlciwgZW5hYmxpbmcgb2JzZXJ2ZXJzIHRvIGxpc3RlbiB0byBjaGFuZ2VzIHRocm91Z2hvdXQgdGhlIHN5c3RlbS4KICAgICAqIFRoZSBpbnRlcmZhY2UgZXhwb3NlZCBpcyBzaW1pbGFyIHRvIFtFdmVudEVtaXR0ZXJdKGh0dHBzOi8vbm9kZWpzLm9yZy9hcGkvZXZlbnRzLmh0bWwjZXZlbnRzX2NsYXNzX2V2ZW50ZW1pdHRlcikgaW4gTm9kZS4KICAgICAqCiAgICAgKiBTaW1pbGFyIHRvIGhvdyB0aGUgRE9NIGV2ZW50IHN5c3RlbSBpbiB0aGUgYnJvd3NlciB3b3JrcywgZXZlbnRzIGFyZSByZWdpc3RlcmVkIGJ5IG5hbWUuCiAgICAgKiBFeGFtcGxlOiBSZWdpc3RlcmluZyBhIGxpc3RlbmVyIGZvciBhIGN1c3RvbSBldmVudCwgYW5kIHRoZW4gZW1pdHRpbmcgdGhhdCBldmVudC4KICAgICAqIGBgYGphdmFzY3JpcHQKICAgICAqICBjb25zdCBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKQogICAgICoKICAgICAqICBjb25zdCBldmVudElEID0gZWUub24oJ215RXZlbnQnLCAoZXZlbnQpID0+IHsKICAgICAqICAgIGNvbnNvbGUubG9nKCdNeSBFdmVudCB3YXMgZW1pdHRlZDonLCBldmVudCkKICAgICAqICB9KQogICAgICoKICAgICAqICBlZS5lbWl0KCdteUV2ZW50JywgeyBkYXRhOiA0MiB9KQogICAgICogIC8vIFdlIG5vIGxvbmdlciB3YW50IHRvIGxpc3RlbiB0byB0aGlzIGV2ZW50LCBzbyBsZXQncyByZW1vdmUgdGhlIGxpc3RlbmVyLgogICAgICogIGVlLm9mZignbXlFdmVudCcsIGV2ZW50SUQpCiAgICAgKiBgYGAKICAgICAqCiAgICAgKgogICAgICovCiAgICBjbGFzcyBFdmVudEVtaXR0ZXIgZXh0ZW5kcyBCYXNlQ2xhc3MgewogICAgICAgIGxpc3RlbmVycyA9IHt9OwogICAgICAgIC8qKgogICAgICAgICAqIEluaXRpYWxpemVzIGFuIGVtcHR5IGBsaXN0ZW5lcnNgIG1hcCB0aGF0IHdpbGwgaG9zdCBhbGwgdGhlIGV2ZW50cywKICAgICAgICAgKiB3aGljaCBpbXBsaWVzIHRoYXQgaXQgZG9lc24ndCBhbGxvdyBtdWx0aXBsZSBldmVudHMgd2l0aCB0aGUgc2FtZSBuYW1lLgogICAgICAgICAqCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgICAgIHN1cGVyKCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEFkZHMgYSBsaXN0ZW5lciBmdW5jdGlvbiBmb3IgYSBnaXZlbiBldmVudCBuYW1lLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudC4KICAgICAgICAgKiBAcGFyYW0gbGlzdGVuZXIgLSBUaGUgbGlzdGVuZXIgZnVuY3Rpb24oY2FsbGJhY2spLgogICAgICAgICAqIEByZXR1cm4gLSB0aGUgaWQgdGhhdCBjYW4gYmUgdXNlZCB0byByZW1vdmUgdGhlIGxpc3RlbmVyLgogICAgICAgICAqLwogICAgICAgIG9uKGV2ZW50TmFtZSwgbGlzdGVuZXIpIHsKICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcikgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIGxpc3RlbmVyLicpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICghdGhpcy5saXN0ZW5lcnNbZXZlbnROYW1lXSkgewogICAgICAgICAgICAgICAgdGhpcy5saXN0ZW5lcnNbZXZlbnROYW1lXSA9IFtdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVycyA9IHRoaXMubGlzdGVuZXJzW2V2ZW50TmFtZV07CiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaW5jbHVkZXMobGlzdGVuZXIpKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYExpc3RlbmVyICIke2xpc3RlbmVyLm5hbWV9IiBhbHJlYWR5IGNvbm5lY3RlZCB0byBldmVudCAiJHtldmVudE5hbWV9Ii5gKTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBUT0RPOiBEZXByZWNhdGUgYWxvbmdzaWRlICNhZGRMaXN0ZW5lci4KICAgICAgICAgICAgY29uc3QgaWQgPSBsaXN0ZW5lcnMubGVuZ3RoOwogICAgICAgICAgICBsaXN0ZW5lcnNbaWRdID0gbGlzdGVuZXI7CiAgICAgICAgICAgIHJldHVybiBpZDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2ltaWxhciB0byB0aGUgYG9uYCBtZXRob2Qgd2l0aCB0aGUgZGlmZmVyZW5jZSB0aGF0IHdoZW4gdGhlIGV2ZW50IGlzIHRyaWdnZXJlZCwKICAgICAgICAgKiBpdCBpcyBhdXRvbWF0aWNhbGx5IHVucmVnaXN0ZXJlZCBtZWFuaW5nIHRoYXQgdGhlIGV2ZW50IGxpc3RlbmVyIHdpbGwgYmUgdHJpZ2dlcmVkIGF0IG1vc3Qgb25lIHRpbWUuCiAgICAgICAgICoKICAgICAgICAgKiBVc2VmdWwgZm9yIGV2ZW50cyB0aGF0IHdlIGV4cGVjdCB0byB0cmlnZ2VyIG9uZSB0aW1lLCBzdWNoIGFzIHdoZW4gYXNzZXRzIGxvYWQuCiAgICAgICAgICogYGBgamF2YXNjcmlwdAogICAgICAgICAqIGNvbnN0IGFzc2V0ID0gbmV3IEFzc2V0KCk7CiAgICAgICAgICogYXNzZXQub25jZSgnbG9hZGVkJywgKCkgPT4gewogICAgICAgICAqICAgY29uc29sZS5sb2coIllheSEgdGhlIGFzc2V0IGlzIGxvYWRlZCIpCiAgICAgICAgICogfSkKICAgICAgICAgKiBgYGAKICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBldmVudE5hbWUgLSBUaGUgZXZlbnROYW1lIHZhbHVlCiAgICAgICAgICogQHBhcmFtIGxpc3RlbmVyIC0gVGhlIGxpc3RlbmVyIHZhbHVlCiAgICAgICAgICogQHJldHVybiAtIHRoZSBpZCB0aGF0IGNhbiBiZSB1c2VkIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuCiAgICAgICAgICovCiAgICAgICAgb25jZShldmVudE5hbWUsIGxpc3RlbmVyKSB7CiAgICAgICAgICAgIGNvbnN0IGNiID0gKGV2ZW50KSA9PiB7CiAgICAgICAgICAgICAgICB0aGlzLm9mZihldmVudE5hbWUsIGNiKTsKICAgICAgICAgICAgICAgIGxpc3RlbmVyKGV2ZW50KTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgcmV0dXJuIHRoaXMub24oZXZlbnROYW1lLCBjYik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJlbW92ZXMgYSBsaXN0ZW5lciBmcm9tIHRoZSBzcGVjaWZpZWQgZXZlbnQsIHVzaW5nIGVpdGhlciB0aGUgZnVuY3Rpb24gb3IgdGhlIGluZGV4IGlkLiBEZXBlbmRzIG9uIHdoYXQgaXMgcGFzc2VkIGluLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudC4KICAgICAgICAgKiBAcGFyYW0gbGlzdGVuZXJPcklkIC0gVGhlIGxpc3RlbmVyIGZ1bmN0aW9uIG9yIHRoZSBpZCBudW1iZXIgcmV0dXJuZWQgYnkgJ29uJy4KICAgICAgICAgKi8KICAgICAgICBvZmYoZXZlbnROYW1lLCBsaXN0ZW5lck9ySWQpIHsKICAgICAgICAgICAgaWYgKGxpc3RlbmVyT3JJZCA9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBjYWxsYmFjayBmdW5jdGlvbiAobGlzdGVuZXIpLicpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVycyA9IHRoaXMubGlzdGVuZXJzW2V2ZW50TmFtZV0gfHwgW107CiAgICAgICAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXJPcklkID09ICdudW1iZXInKSB7CiAgICAgICAgICAgICAgICBjb25zdCBpZCA9IGxpc3RlbmVyT3JJZDsKICAgICAgICAgICAgICAgIC8vIE5vdGU6IGRvIG5vdCBzcGxpY2UgdGhlIGFycmF5IGFzIHRoYXQgd291bGQgY2hhbmdlIHRoZSBpbmRleGVzIG9mIGV4aXN0aW5nIGxpc3RlbmVycy4KICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpZF0gPSBudWxsOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVyID0gbGlzdGVuZXJPcklkOwogICAgICAgICAgICBsaXN0ZW5lcnMuZm9yRWFjaCgoZSwgaSkgPT4gewogICAgICAgICAgICAgICAgaWYgKGUgPT09IGxpc3RlbmVyKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gTm90ZTogZG8gbm90IHNwbGljZSB0aGUgYXJyYXkgYXMgdGhhdCB3b3VsZCBjaGFuZ2UgdGhlIGluZGV4ZXMgb2YgZXhpc3RpbmcgbGlzdGVuZXJzLgogICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXSA9IG51bGw7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiByZW1vdmUgbGlzdGVuZXIgYnkgSUQgcmV0dXJuZWQgZnJvbSAjb24KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuCiAgICAgICAgICogQHBhcmFtIGlkIC0gVGhlIGlkIHJldHVybmVkIGJ5IGFkZExpc3RlbmVyCiAgICAgICAgICovCiAgICAgICAgcmVtb3ZlTGlzdGVuZXJCeUlkKGV2ZW50TmFtZSwgaWQpIHsKICAgICAgICAgICAgdGhpcy5vZmYoZXZlbnROYW1lLCBpZCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRyaWdnZXJzIGFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgaW4gYW4gZXZlbnQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50LgogICAgICAgICAqIEBwYXJhbSBldmVudCAtIFRoZSBkYXRhIHlvdSB3YW50IHRvIHBhc3MgZG93biB0byBhbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGFzIHBhcmFtZXRlci4KICAgICAgICAgKgogICAgICAgICAqLwogICAgICAgIGVtaXQoZXZlbnROYW1lLCBldmVudCA9IG5ldyBCYXNlRXZlbnQoKSkgewogICAgICAgICAgICBjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLmxpc3RlbmVyc1tldmVudE5hbWVdIHx8IFtdOwogICAgICAgICAgICBsaXN0ZW5lcnMuZm9yRWFjaCgoZm4pID0+IHsKICAgICAgICAgICAgICAgIC8vIFNraXAgZGlzY29ubmVjdGVkIGxpc3RlbmVycy4KICAgICAgICAgICAgICAgIGlmIChmbikgewogICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGZuKGV2ZW50KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfQogICAgfQoKICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi8KICAgIC8qKgogICAgICogTWF0aCBGdW5jdGlvbnMKICAgICAqLwogICAgY2xhc3MgTWF0aEZ1bmN0aW9ucyB7CiAgICAgICAgLyoqCiAgICAgICAgICogQ29udmVydHMgUmFkaWFucyB0byBEZWdyZWVzCiAgICAgICAgICoKICAgICAgICAgKiBAc3RhdGljCiAgICAgICAgICogQHBhcmFtIHJhZCAtIFJhZGlhbnMgdmFsdWUKICAgICAgICAgKiBAcmV0dXJuIC0gRGVncmVlcyBlcXVpdmFsZW50CiAgICAgICAgICovCiAgICAgICAgc3RhdGljIHJhZFRvRGVnKHJhZCkgewogICAgICAgICAgICByZXR1cm4gcmFkIC8gKE1hdGguUEkgLyAxODApOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDb252ZXJ0cyBEZWdyZWVzIHRvIFJhZGlhbnRzCiAgICAgICAgICoKICAgICAgICAgKiBAc3RhdGljCiAgICAgICAgICogQHBhcmFtIGRlZyAtIERlZ3JlZXMgdmFsdWUKICAgICAgICAgKiBAcmV0dXJuIC0gIFJhZGlhbnMgZXF1aXZhbGVudAogICAgICAgICAqLwogICAgICAgIHN0YXRpYyBkZWdUb1JhZChkZWcpIHsKICAgICAgICAgICAgcmV0dXJuIGRlZyAqIChNYXRoLlBJIC8gMTgwKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVmVyaWZpZXMgaWYgdGhlIHNwZWNpZmllZCBwYXJhbWV0ZXIgaXMgbnVtZXJpYy4KICAgICAgICAgKgogICAgICAgICAqIEBzdGF0aWMKICAgICAgICAgKiBAcGFyYW0gbnVtYmVyIC0gTnVtYmVyIHRvIHRlc3QKICAgICAgICAgKiBAcmV0dXJuIC0gYHRydWVgIHdoZW4gaXMgYSB2YWxpZCBudW1iZXIKICAgICAgICAgKi8KICAgICAgICBzdGF0aWMgaXNOdW1lcmljKG51bWJlcikgewogICAgICAgICAgICByZXR1cm4gIWlzTmFOKHBhcnNlRmxvYXQobnVtYmVyKSkgJiYgaXNGaW5pdGUobnVtYmVyKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogR2VuZXJhdGVzIGFuZCByZXR1cm5zIGEgcmFuZG9tIGludGVnZXIgd2l0aGluIHRoZSBzcGVjaWZpZWQgcmFuZ2UuCiAgICAgICAgICoKICAgICAgICAgKiBAc3RhdGljCiAgICAgICAgICogQHBhcmFtIG1pbiAtIExvd2VyIHZhbHVlIHJhbmRvbSBpbnQgY2FuIGJlLgogICAgICAgICAqIEBwYXJhbSBtYXggLSBIaWdoZXN0IHZhbHVlIHJhbmRvbSBpbnQgY2FuIGJlLgogICAgICAgICAqIEByZXR1cm4gLSBSYW5kb20gbnVtYmVyIGluc2lkZSByYW5nZS4KICAgICAgICAgKi8KICAgICAgICBzdGF0aWMgcmFuZG9tSW50KG1pbiwgbWF4KSB7CiAgICAgICAgICAgIG1pbiA9IE1hdGguY2VpbChtaW4pOwogICAgICAgICAgICBtYXggPSBNYXRoLmZsb29yKG1heCk7CiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAobWF4IC0gbWluKSkgKyBtaW47CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZXMgYSBsaW5lYWwgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byBpbnB1dHMgZm9yIHRoZSBzcGVjaWZpZWQgcGFyYW1ldGVyKHQpLgogICAgICAgICAqCiAgICAgICAgICogQHN0YXRpYwogICAgICAgICAqIEBwYXJhbSB2MCAtCiAgICAgICAgICogQHBhcmFtIHYxIC0KICAgICAgICAgKiBAcGFyYW0gdCAtCiAgICAgICAgICogQHJldHVybiAtCiAgICAgICAgICovCiAgICAgICAgc3RhdGljIGxlcnAodjAsIHYxLCB0KSB7CiAgICAgICAgICAgIHJldHVybiB2MCArIHQgKiAodjEgLSB2MCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJlc3RyaWN0cyB0aGUgc3BlY2lmaWVkIHZhbHVlIGJldHdlZW4gdHdvIG51bWJlcnMKICAgICAgICAgKgogICAgICAgICAqIEBzdGF0aWMKICAgICAgICAgKiBAcGFyYW0gdmFsdWUKICAgICAgICAgKiBAcGFyYW0gbWluCiAgICAgICAgICogQHBhcmFtIG1heAogICAgICAgICAqIEByZXR1cm4KICAgICAgICAgKi8KICAgICAgICBzdGF0aWMgY2xhbXAodmFsdWUsIG1pbiwgbWF4KSB7CiAgICAgICAgICAgIHJldHVybiBNYXRoLm1pbihNYXRoLm1heCh2YWx1ZSwgbWluKSwgbWF4KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgbmVhcmVzdCBwb3cgb2YgdHdvIHZhbHVlIG9mIHRoZSBzcGVjaWZpZWQgbnVtYmVyLgogICAgICAgICAqCiAgICAgICAgICogQHN0YXRpYwogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtCiAgICAgICAgICogQHJldHVybiAtCiAgICAgICAgICovCiAgICAgICAgc3RhdGljIG5lYXJlc3RQb3cyKHZhbHVlKSB7CiAgICAgICAgICAgIHJldHVybiBNYXRoLnBvdygyLCBNYXRoLnJvdW5kKE1hdGgubG9nKHZhbHVlKSAvIE1hdGgubG9nKDIpKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIG5lYXJlc3QgcG93IG9mIHRlbiB2YWx1ZSBvZiB0aGUgc3BlY2lmaWVkIG51bWJlci4KICAgICAgICAgKgogICAgICAgICAqIEBzdGF0aWMKICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLQogICAgICAgICAqIEByZXR1cm4gLQogICAgICAgICAqLwogICAgICAgIHN0YXRpYyBuZWFyZXN0UG93MTAodmFsdWUpIHsKICAgICAgICAgICAgcmV0dXJuIE1hdGgucG93KDEwLCBNYXRoLnJvdW5kKE1hdGgubG9nMTAodmFsdWUpIC8gTWF0aC5sb2cxMCgxMCkpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgbmV4dCBwb3cgb2YgdHdvIHZhbHVlIG9mIHRoZSBzcGVjaWZpZWQgbnVtYmVyLgogICAgICAgICAqCiAgICAgICAgICogQHN0YXRpYwogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtCiAgICAgICAgICogQHJldHVybiAtCiAgICAgICAgICovCiAgICAgICAgc3RhdGljIG5leHRQb3cyKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICh0aGlzLmZyYWN0KE1hdGgubG9nMih2YWx1ZSkpID09IDApIHsKICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZXQgZXhwID0gMDsKICAgICAgICAgICAgd2hpbGUgKHZhbHVlID4gMCkgewogICAgICAgICAgICAgICAgZXhwKys7CiAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlID4+IDE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIDEgPDwgZXhwOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBmcmFjdGlvbmFsIGNvbXBvbmVudCBvZiBhIG51bWJlcgogICAgICAgICAqCiAgICAgICAgICogQHN0YXRpYwogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtCiAgICAgICAgICogQHJldHVybiAtCiAgICAgICAgICovCiAgICAgICAgc3RhdGljIGZyYWN0KHZhbHVlKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSAwKQogICAgICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgICAgIGlmICh2YWx1ZSA8IDApIHsKICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA+IC0xLjApCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIC12YWx1ZTsKICAgICAgICAgICAgICAgIHJldHVybiAtdmFsdWUgJSBNYXRoLmZsb29yKC12YWx1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHZhbHVlIDwgMS4wKQogICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgICAgICByZXR1cm4gdmFsdWUgJSBNYXRoLmZsb29yKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogTW92ZXMgdGhlIHNwZWNpZmllZCB2YWx1ZSBmcm9tIG9uZSBudW1lcmljIGRvbWFpbihyYW5nZSkgdG8gYW5vdGhlci4KICAgICAgICAgKgogICAgICAgICAqIEBzdGF0aWMKICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLQogICAgICAgICAqIEBwYXJhbSBzdGFydDEgLQogICAgICAgICAqIEBwYXJhbSBlbmQxIC0KICAgICAgICAgKiBAcGFyYW0gc3RhcnQyIC0KICAgICAgICAgKiBAcGFyYW0gZW5kMiAtCiAgICAgICAgICogQHJldHVybiAtCiAgICAgICAgICovCiAgICAgICAgc3RhdGljIHJlbWFwKHZhbHVlLCBzdGFydDEsIGVuZDEsIHN0YXJ0MiwgZW5kMikgewogICAgICAgICAgICByZXR1cm4gc3RhcnQyICsgKGVuZDIgLSBzdGFydDIpICogKCh2YWx1ZSAtIHN0YXJ0MSkgLyAoZW5kMSAtIHN0YXJ0MSkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBQZXJmb3JtIEhlcm1pdGUgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2YWx1ZXMKICAgICAgICAgKgogICAgICAgICAqIEBzdGF0aWMKICAgICAgICAgKiBAcGFyYW0gZWRnZTAgLQogICAgICAgICAqIEBwYXJhbSBlZGdlMSAtCiAgICAgICAgICogQHBhcmFtIHggLQogICAgICAgICAqIEByZXR1cm4gLQogICAgICAgICAqLwogICAgICAgIHN0YXRpYyBzbW9vdGhTdGVwKGVkZ2UwLCBlZGdlMSwgeCkgewogICAgICAgICAgICBjb25zdCB0ID0gdGhpcy5jbGFtcCgoeCAtIGVkZ2UwKSAvIChlZGdlMSAtIGVkZ2UwKSwgMC4wLCAxLjApOwogICAgICAgICAgICByZXR1cm4gdCAqIHQgKiAoMy4wIC0gMi4wICogdCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFBlcmZvcm1zIC0gaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2YWx1ZXMKICAgICAgICAgKgogICAgICAgICAqIEBzdGF0aWMKICAgICAgICAgKiBAcGFyYW0gZWRnZTAgLQogICAgICAgICAqIEBwYXJhbSBlZGdlMSAtCiAgICAgICAgICogQHBhcmFtIHggLQogICAgICAgICAqIEByZXR1cm4gLQogICAgICAgICAqLwogICAgICAgIHN0YXRpYyBsaW5TdGVwKGVkZ2UwLCBlZGdlMSwgeCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5jbGFtcCgoeCAtIGVkZ2UwKSAvIChlZGdlMSAtIGVkZ2UwKSwgMC4wLCAxLjApOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBEZWNvZGVzIGEgRmxvYXQxNiBmcm9tIHR3byB1bnNpZ25lZCBJbnQ4CiAgICAgICAgICoKICAgICAgICAgKiBAc3RhdGljCiAgICAgICAgICogQHBhcmFtIGMgLSBBcnJheSB3aXRoIHRoZSB0d28gVUludDgKICAgICAgICAgKiBAcmV0dXJuIC0gRGVjb2RlZCBGbG9hdDE2CiAgICAgICAgICovCiAgICAgICAgc3RhdGljIGRlY29kZTE2Qml0RmxvYXRGcm9tMnhVSW50OChjKSB7CiAgICAgICAgICAgIGNvbnN0IGl4ID0gY1swXTsgLy8gMXN0IGJ5dGU6IDEgYml0IHNpZ25lZCBudW0sIDQgYml0cyBleHBvbmVudCwgMyBiaXRzIG1hbnRpc3NhIChNU0IpCiAgICAgICAgICAgIGNvbnN0IGl5ID0gY1sxXTsgLy8gMm5kIGJ5dGU6IDggYml0IG1hbnRpc3NhIChMU0IpCiAgICAgICAgICAgIGNvbnN0IHMgPSBpeCAmIDB4ODAgPyAxIDogLTE7IC8vIGdldCBiaXQgOAogICAgICAgICAgICBjb25zdCBpZXhwID0gKGl4ICYgMHg3OCkgPj4gMzsgLy8gbWFzayBiaXRzIDctNAogICAgICAgICAgICBjb25zdCBtc2IgPSBpeCAmIDB4NzsgLy8gbWFzayBiaXRzIDMtMQogICAgICAgICAgICBsZXQgbm9ybSA9IGlleHAgPT0gMCA/IDAgOiAyMDQ4OyAvLyBkaXN0aW5ndWlzaCBiZXR3ZWVuIG5vcm1hbGl6ZWQgYW5kIHN1Yi1ub3JtYWxpemVkIG51bWJlcnMKICAgICAgICAgICAgY29uc3QgbWFudGlzc2EgPSBub3JtICsgKG1zYiA8PCA4KSArIGl5OyAvLyBpbXBsaWNpdCBwcmVjZWRpbmcgMSBvciAwIGFkZGVkIGhlcmUKICAgICAgICAgICAgbm9ybSA9IGlleHAgPT0gMCA/IDEgOiAwOyAvLyBub3JtYWxpemF0aW9uIHRvZ2dsZQogICAgICAgICAgICBjb25zdCBleHBvbmVudCA9IE1hdGgucG93KDIsIGlleHAgKyBub3JtIC0gMTYpOyAvLyAtNSBmb3IgdGhlIHRoZSBleHBvbmVudCBiaWFzIGZyb20gMl4tNSB0byAyXjEwIHBsdXMgYW5vdGhlciAtMTEgZm9yIHRoZSBub3JtYWxpemVkIDEyIGJpdCBtYW50aXNzYQogICAgICAgICAgICBjb25zdCB2ID0gcyAqIG1hbnRpc3NhICogZXhwb25lbnQ7CiAgICAgICAgICAgIHJldHVybiB2OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBFbmNvZGVzIGFuIGFycmF5IG9mIHR3byB1bnNpZ25lZCBJbnQ4IHRvIGEgRmxvYXQxNgogICAgICAgICAqCiAgICAgICAgICogQHN0YXRpYwogICAgICAgICAqIEBwYXJhbSB2IC0gRmxvYXQxNiBudW1iZXIKICAgICAgICAgKiBAcmV0dXJuIC0gRW5jb2RlZCBVbnNpZ25lZCBJbnQ4IGFycmF5CiAgICAgICAgICovCiAgICAgICAgc3RhdGljIGVuY29kZTE2Qml0RmxvYXRJbnRvMnhVSW50OCh2KSB7CiAgICAgICAgICAgIGNvbnN0IGMgPSBuZXcgVWludDhBcnJheSgyKTsKICAgICAgICAgICAgLy8gY29uc3QgYyA9IFswLCAwXTsKICAgICAgICAgICAgY29uc3Qgc2lnbnVtID0gdiA+PSAwID8gMTI4IDogMDsKICAgICAgICAgICAgdiA9IE1hdGguYWJzKHYpOwogICAgICAgICAgICBsZXQgZXhwb25lbnQgPSAxNTsKICAgICAgICAgICAgbGV0IGxpbWl0ID0gMTAyNDsgLy8gY29uc2lkZXJpbmcgdGhlIGJpYXMgZnJvbSAyXi01IHRvIDJeMTAgKD09MTAyNCkKICAgICAgICAgICAgZm9yIChsZXQgZXhwID0gMTU7IGV4cCA+IDA7IGV4cC0tKSB7CiAgICAgICAgICAgICAgICBpZiAodiA8IGxpbWl0KSB7CiAgICAgICAgICAgICAgICAgICAgbGltaXQgLz0gMjsKICAgICAgICAgICAgICAgICAgICBleHBvbmVudC0tOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGxldCByZXN0OwogICAgICAgICAgICBpZiAoZXhwb25lbnQgPT0gMCkgewogICAgICAgICAgICAgICAgcmVzdCA9IHYgLyBsaW1pdCAvIDI7IC8vICJzdWItbm9ybWFsaXplIiBpbXBsaWNpdCBwcmVjZWRpbmcgMC4KICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHJlc3QgPSAodiAtIGxpbWl0KSAvIGxpbWl0OyAvLyBub3JtYWxpemUgYWNjb3JkaW5nbHkgdG8gaW1wbGljaXQgcHJlY2VkaW5nIDEuCiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgbWFudGlzc2EgPSBNYXRoLnJvdW5kKHJlc3QgKiAyMDQ4KTsgLy8gMjA0OCA9IDJeMTEgZm9yIHRoZSAoc3BsaXQpIDExIGJpdCBtYW50aXNzYQogICAgICAgICAgICBjb25zdCBtc2IgPSBtYW50aXNzYSAvIDI1NjsgLy8gdGhlIG1vc3Qgc2lnbmlmaWNhbnQgMyBiaXRzIGdvIGludG8gdGhlIGxvd2VyIHBhcnQgb2YgdGhlIGZpcnN0IGJ5dGUKICAgICAgICAgICAgY29uc3QgbHNiID0gbWFudGlzc2EgLSBtc2IgKiAyNTY7IC8vIHRoZXJlIGdvIHRoZSBvdGhlciA4IGJpdCBvZiB0aGUgbG93ZXIgc2lnbmlmaWNhbmNlCiAgICAgICAgICAgIGNbMF0gPSBzaWdudW0gKyBleHBvbmVudCAqIDggKyBtc2I7IC8vIGNvbG9yIG5vcm1hbGl6YXRpb24gZm9yIHRleHR1cmUyRAogICAgICAgICAgICBjWzFdID0gbHNiOwogICAgICAgICAgICBpZiAodiA+PSAyMDQ4KSB7CiAgICAgICAgICAgICAgICBjWzBdID0gMjU1OwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBjOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUcmFuc2Zvcm1zIGEgMTYgYml0IGZsb2F0IHRvIGFuIGVuY29kZWQgaW50ZWdlci4KICAgICAgICAgKgogICAgICAgICAqIEBzdGF0aWMKICAgICAgICAgKiBAcGFyYW0gdiAtIEZsb2F0MTYgbnVtYmVyIHRvIGVuY29kZQogICAgICAgICAqIEByZXR1cm4gLSBFbmNvZGVkIG51bWJlcgogICAgICAgICAqLwogICAgICAgIHN0YXRpYyBlbmNvZGUxNkJpdEZsb2F0KHYpIHsKICAgICAgICAgICAgY29uc3QgZmxvYXQzMkFycmF5ID0gbmV3IEZsb2F0MzJBcnJheSgxKTsKICAgICAgICAgICAgZmxvYXQzMkFycmF5WzBdID0gdjsKICAgICAgICAgICAgY29uc3QgaW50MzJWaWV3ID0gbmV3IEludDMyQXJyYXkoZmxvYXQzMkFycmF5LmJ1ZmZlcik7CiAgICAgICAgICAgIGNvbnN0IHRvVUludDE2ID0gKHgpID0+IHsKICAgICAgICAgICAgICAgIGxldCBiaXRzID0gKHggPj4gMTYpICYgMHg4MDAwOyAvKiBHZXQgdGhlIHNpZ24gKi8KICAgICAgICAgICAgICAgIGxldCBtID0gKHggPj4gMTIpICYgMHgwN2ZmOyAvKiBLZWVwIG9uZSBleHRyYSBiaXQgZm9yIHJvdW5kaW5nICovCiAgICAgICAgICAgICAgICBjb25zdCBlID0gKHggPj4gMjMpICYgMHhmZjsgLyogVXNpbmcgaW50IGlzIGZhc3RlciBoZXJlICovCiAgICAgICAgICAgICAgICAvKiBJZiB6ZXJvLCBvciBkZS1ub3JtYWwsIG9yIGV4cG9uZW50IHVuZGVyZmxvd3MgdG9vIG11Y2ggZm9yIGEgZGUtbm9ybWFsCiAgICAgICAgICAgICAgICAgKiBoYWxmLCByZXR1cm4gc2lnbmVkIHplcm8uICovCiAgICAgICAgICAgICAgICBpZiAoZSA8IDEwMykgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBiaXRzOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLyogSWYgTmFOLCByZXR1cm4gTmFOLiBJZiBJbmYgb3IgZXhwb25lbnQgb3ZlcmZsb3csIHJldHVybiBJbmYuICovCiAgICAgICAgICAgICAgICBpZiAoZSA+IDE0MikgewogICAgICAgICAgICAgICAgICAgIGJpdHMgfD0gMHg3YzAwOwogICAgICAgICAgICAgICAgICAgIC8qIElmIGV4cG9uZW50IHdhcyAweGZmIGFuZCBvbmUgbWFudGlzc2EgYml0IHdhcyBzZXQsIGl0IG1lYW5zIE5hTiwKICAgICAgICAgICAgICAgICAgICAgKiBub3QgSW5mLCBzbyBtYWtlIHN1cmUgd2Ugc2V0IG9uZSBtYW50aXNzYSBiaXQgdG9vLiAqLwogICAgICAgICAgICAgICAgICAgIGJpdHMgfD0gKGUgPT0gMjU1ID8gMCA6IDEpICYmIHggJiAweDAwN2ZmZmZmOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBiaXRzOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLyogSWYgZXhwb25lbnQgdW5kZXJmbG93cyBidXQgbm90IHRvbyBtdWNoLCByZXR1cm4gYSBkZS1ub3JtYWwgKi8KICAgICAgICAgICAgICAgIGlmIChlIDwgMTEzKSB7CiAgICAgICAgICAgICAgICAgICAgbSB8PSAweDA4MDA7CiAgICAgICAgICAgICAgICAgICAgLyogRXh0cmEgcm91bmRpbmcgbWF5IG92ZXJmbG93IGFuZCBzZXQgbWFudGlzc2EgdG8gMCBhbmQgZXhwb25lbnQKICAgICAgICAgICAgICAgICAgICAgKiB0byAxLCB3aGljaCBpcyBPSy4gKi8KICAgICAgICAgICAgICAgICAgICBiaXRzIHw9IChtID4+ICgxMTQgLSBlKSkgKyAoKG0gPj4gKDExMyAtIGUpKSAmIDEpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBiaXRzOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYml0cyB8PSAoKGUgLSAxMTIpIDw8IDEwKSB8IChtID4+IDEpOwogICAgICAgICAgICAgICAgLyogRXh0cmEgcm91bmRpbmcuIEFuIG92ZXJmbG93IHdpbGwgc2V0IG1hbnRpc3NhIHRvIDAgYW5kIGluY3JlbWVudAogICAgICAgICAgICAgICAgICogdGhlIGV4cG9uZW50LCB3aGljaCBpcyBPSy4gKi8KICAgICAgICAgICAgICAgIGJpdHMgKz0gbSAmIDE7CiAgICAgICAgICAgICAgICByZXR1cm4gYml0czsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgcmV0dXJuIHRvVUludDE2KGludDMyVmlld1swXSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEFzIG9wcG9zaXRlIG9mIHRoZSBgZW5jb2RlMTZCaXRGbG9hdGAgbWV0aG9kLCB0aGlzIHRha2VzIGFuIGVuY29kZWQgaW50ZWdlciB2YWx1ZSwKICAgICAgICAgKiBhbmQgcmV0dXJucyB0aGUgMTYgYml0IGZsb2F0LgogICAgICAgICAqCiAgICAgICAgICogQHN0YXRpYwogICAgICAgICAqIEBwYXJhbSBoIC0gRW5jb2RlZCBpbnRlZ2VyCiAgICAgICAgICogQHJldHVybiAtIERlY29kZWQgMTYgYml0IGZsb2F0LgogICAgICAgICAqLwogICAgICAgIHN0YXRpYyBkZWNvZGUxNkJpdEZsb2F0KGgpIHsKICAgICAgICAgICAgY29uc3QgcyA9IChoICYgMHg4MDAwKSA+PiAxNTsKICAgICAgICAgICAgY29uc3QgZSA9IChoICYgMHg3YzAwKSA+PiAxMDsKICAgICAgICAgICAgY29uc3QgZiA9IGggJiAweDAzZmY7CiAgICAgICAgICAgIGlmIChlID09IDApIHsKICAgICAgICAgICAgICAgIHJldHVybiAocyA/IC0xIDogMSkgKiBNYXRoLnBvdygyLCAtMTQpICogKGYgLyBNYXRoLnBvdygyLCAxMCkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYgKGUgPT0gMHgxZikgewogICAgICAgICAgICAgICAgcmV0dXJuIGYgPyBOYU4gOiAocyA/IC0xIDogMSkgKiBJbmZpbml0eTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gKHMgPyAtMSA6IDEpICogTWF0aC5wb3coMiwgZSAtIDE1KSAqICgxICsgZiAvIE1hdGgucG93KDIsIDEwKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRyYW5zZm9ybXMgYW4gYXJyYXkgb2YgRmxvYXQgMzIgdG8gYW4gYXJyYXkgb2YgdW5zaWduZWQgSW50MTYuCiAgICAgICAgICoKICAgICAgICAgKiBAc3RhdGljCiAgICAgICAgICogQHBhcmFtIGZsb2F0MzJBcnJheSAtCiAgICAgICAgICogQHJldHVybiAtIFVuc2lnbmVkIEludDE2IGFycmF5IHJlcHJlc2VudGF0aXZlIG9mIHRoZSBGbG9hdDMyQXJyYXkKICAgICAgICAgKi8KICAgICAgICBzdGF0aWMgY29udmVydEZsb2F0MzJBcnJheVRvVUludDE2QXJyYXkoZmxvYXQzMkFycmF5KSB7CiAgICAgICAgICAgIGNvbnN0IHVuaXQxNnMgPSBuZXcgVWludDE2QXJyYXkoZmxvYXQzMkFycmF5Lmxlbmd0aCk7CiAgICAgICAgICAgIGNvbnN0IGludDMyVmlldyA9IG5ldyBJbnQzMkFycmF5KGZsb2F0MzJBcnJheS5idWZmZXIpOwogICAgICAgICAgICBjb25zdCB0b1VJbnQxNiA9ICh4KSA9PiB7CiAgICAgICAgICAgICAgICBsZXQgYml0cyA9ICh4ID4+IDE2KSAmIDB4ODAwMDsgLyogR2V0IHRoZSBzaWduICovCiAgICAgICAgICAgICAgICBsZXQgbSA9ICh4ID4+IDEyKSAmIDB4MDdmZjsgLyogS2VlcCBvbmUgZXh0cmEgYml0IGZvciByb3VuZGluZyAqLwogICAgICAgICAgICAgICAgY29uc3QgZSA9ICh4ID4+IDIzKSAmIDB4ZmY7IC8qIFVzaW5nIGludCBpcyBmYXN0ZXIgaGVyZSAqLwogICAgICAgICAgICAgICAgLyogSWYgemVybywgb3IgZGUtbm9ybWFsLCBvciBleHBvbmVudCB1bmRlcmZsb3dzIHRvbyBtdWNoIGZvciBhIGRlLW5vcm1hbAogICAgICAgICAgICAgICAgICogaGFsZiwgcmV0dXJuIHNpZ25lZCB6ZXJvLiAqLwogICAgICAgICAgICAgICAgaWYgKGUgPCAxMDMpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gYml0czsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIC8qIElmIE5hTiwgcmV0dXJuIE5hTi4gSWYgSW5mIG9yIGV4cG9uZW50IG92ZXJmbG93LCByZXR1cm4gSW5mLiAqLwogICAgICAgICAgICAgICAgaWYgKGUgPiAxNDIpIHsKICAgICAgICAgICAgICAgICAgICBiaXRzIHw9IDB4N2MwMDsKICAgICAgICAgICAgICAgICAgICAvKiBJZiBleHBvbmVudCB3YXMgMHhmZiBhbmQgb25lIG1hbnRpc3NhIGJpdCB3YXMgc2V0LCBpdCBtZWFucyBOYU4sCiAgICAgICAgICAgICAgICAgICAgICogbm90IEluZiwgc28gbWFrZSBzdXJlIHdlIHNldCBvbmUgbWFudGlzc2EgYml0IHRvby4gKi8KICAgICAgICAgICAgICAgICAgICBiaXRzIHw9IChlID09IDI1NSA/IDAgOiAxKSAmJiB4ICYgMHgwMDdmZmZmZjsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gYml0czsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIC8qIElmIGV4cG9uZW50IHVuZGVyZmxvd3MgYnV0IG5vdCB0b28gbXVjaCwgcmV0dXJuIGEgZGUtbm9ybWFsICovCiAgICAgICAgICAgICAgICBpZiAoZSA8IDExMykgewogICAgICAgICAgICAgICAgICAgIG0gfD0gMHgwODAwOwogICAgICAgICAgICAgICAgICAgIC8qIEV4dHJhIHJvdW5kaW5nIG1heSBvdmVyZmxvdyBhbmQgc2V0IG1hbnRpc3NhIHRvIDAgYW5kIGV4cG9uZW50CiAgICAgICAgICAgICAgICAgICAgICogdG8gMSwgd2hpY2ggaXMgT0suICovCiAgICAgICAgICAgICAgICAgICAgYml0cyB8PSAobSA+PiAoMTE0IC0gZSkpICsgKChtID4+ICgxMTMgLSBlKSkgJiAxKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gYml0czsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJpdHMgfD0gKChlIC0gMTEyKSA8PCAxMCkgfCAobSA+PiAxKTsKICAgICAgICAgICAgICAgIC8qIEV4dHJhIHJvdW5kaW5nLiBBbiBvdmVyZmxvdyB3aWxsIHNldCBtYW50aXNzYSB0byAwIGFuZCBpbmNyZW1lbnQKICAgICAgICAgICAgICAgICAqIHRoZSBleHBvbmVudCwgd2hpY2ggaXMgT0suICovCiAgICAgICAgICAgICAgICBiaXRzICs9IG0gJiAxOwogICAgICAgICAgICAgICAgcmV0dXJuIGJpdHM7CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmxvYXQzMkFycmF5Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICB1bml0MTZzW2ldID0gdG9VSW50MTYoaW50MzJWaWV3W2ldKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdW5pdDE2czsKICAgICAgICB9CiAgICB9CgogICAgY2xhc3MgQ2hpbGRBZGRlZEV2ZW50IGV4dGVuZHMgQmFzZUV2ZW50IHsKICAgICAgICBpbmRleDsKICAgICAgICBjaGlsZEl0ZW07CiAgICAgICAgY29uc3RydWN0b3IoaW5kZXgsIGNoaWxkSXRlbSkgewogICAgICAgICAgICBzdXBlcigpOwogICAgICAgICAgICB0aGlzLmluZGV4ID0gaW5kZXg7CiAgICAgICAgICAgIHRoaXMuY2hpbGRJdGVtID0gY2hpbGRJdGVtOwogICAgICAgIH0KICAgIH0KCiAgICBjbGFzcyBOYW1lQ2hhbmdlZEV2ZW50IGV4dGVuZHMgQmFzZUV2ZW50IHsKICAgICAgICBvbGROYW1lOwogICAgICAgIG5ld05hbWU7CiAgICAgICAgY29uc3RydWN0b3Iob2xkTmFtZSwgbmV3TmFtZSkgewogICAgICAgICAgICBzdXBlcigpOwogICAgICAgICAgICB0aGlzLm9sZE5hbWUgPSBvbGROYW1lOwogICAgICAgICAgICB0aGlzLm5ld05hbWUgPSBuZXdOYW1lOwogICAgICAgIH0KICAgIH0KCiAgICBjbGFzcyBPcGFjaXR5U3RhdGVDaGFuZ2VkRXZlbnQgZXh0ZW5kcyBCYXNlRXZlbnQgewogICAgICAgIGlzT3BhcXVlOwogICAgICAgIGlzT3BhcXVlU3RhdGVDaGFuZ2VkOwogICAgICAgIGNvbnN0cnVjdG9yKGlzT3BhcXVlLCBpc09wYXF1ZVN0YXRlQ2hhbmdlZCkgewogICAgICAgICAgICBzdXBlcigpOwogICAgICAgICAgICB0aGlzLmlzT3BhcXVlID0gaXNPcGFxdWU7CiAgICAgICAgICAgIHRoaXMuaXNPcGFxdWVTdGF0ZUNoYW5nZWQgPSBpc09wYXF1ZVN0YXRlQ2hhbmdlZDsKICAgICAgICB9CiAgICB9CgogICAgY2xhc3MgUGFyYW1ldGVyQWRkZWRFdmVudCBleHRlbmRzIEJhc2VFdmVudCB7CiAgICAgICAgbmFtZTsKICAgICAgICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICAgICAgICAgIHN1cGVyKCk7CiAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICAgICAgfQogICAgfQoKICAgIGNsYXNzIFBhcmFtZXRlclJlbW92ZWRFdmVudCBleHRlbmRzIEJhc2VFdmVudCB7CiAgICAgICAgbmFtZTsKICAgICAgICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICAgICAgICAgIHN1cGVyKCk7CiAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICAgICAgfQogICAgfQoKICAgIGNsYXNzIFNlbGVjdGVkRXZlbnQgZXh0ZW5kcyBCYXNlRXZlbnQgewogICAgICAgIHNlbGVjdGVkOwogICAgICAgIGNvbnN0cnVjdG9yKHNlbGVjdGVkKSB7CiAgICAgICAgICAgIHN1cGVyKCk7CiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWQgPSBzZWxlY3RlZDsKICAgICAgICB9CiAgICB9CgogICAgY2xhc3MgU3RhdGVDaGFuZ2VkRXZlbnQgZXh0ZW5kcyBCYXNlRXZlbnQgewogICAgICAgIHN0YXRlOwogICAgICAgIGNvbnN0cnVjdG9yKHN0YXRlKSB7CiAgICAgICAgICAgIHN1cGVyKCk7CiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBzdGF0ZTsKICAgICAgICB9CiAgICB9CgogICAgLyoqCiAgICAgKiBDbGFzcyByZXByZXNlbnRpbmcgYSBjb2xvciBhcyA0IGZsb2F0aW5nIHBvaW50IHZhbHVlcy4KICAgICAqLwogICAgY2xhc3MgQ29sb3IgewogICAgICAgIHIgPSAwOwogICAgICAgIGcgPSAwOwogICAgICAgIGIgPSAwOwogICAgICAgIGEgPSAyNTU7CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlcyBhIGBDb2xvcmAgb2JqZWN0IHdpdGggYW4gUkdCQSBzdHJ1Y3R1cmUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gciAtIFRoZSByZWQgY2hhbm5lbCBvZiBhIGNvbG9yLgogICAgICAgICAqIEBwYXJhbSBnIC0gVGhlIGdyZWVuIGNoYW5uZWwgb2YgYSBjb2xvci4KICAgICAgICAgKiBAcGFyYW0gYiAtIFRoZSBibHVlIGNoYW5uZWwgb2YgYSBjb2xvci4KICAgICAgICAgKiBAcGFyYW0gYSAtIFRoZSBhbHBoYSAodHJhbnNwYXJlbmN5KSBjaGFubmVsIG9mIGEgY29sb3IuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IociA9IDAsIGcgPSAwLCBiID0gMCwgYSA9IDEuMCkgewogICAgICAgICAgICBpZiAodHlwZW9mIHIgPT0gJ3N0cmluZycpIHsKICAgICAgICAgICAgICAgIGlmIChyLnN0YXJ0c1dpdGgoJyMnKSkgewogICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0RnJvbUhleChyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0RnJvbUNTU0NvbG9yTmFtZShyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHRoaXMuciA9IHI7CiAgICAgICAgICAgICAgICB0aGlzLmcgPSBnOwogICAgICAgICAgICAgICAgdGhpcy5iID0gYjsKICAgICAgICAgICAgICAgIHRoaXMuYSA9IGE7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0dGVyIGZyb20gc2NhbGFyIGNvbXBvbmVudHMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gciAtIFRoZSByZWQgY2hhbm5lbC4KICAgICAgICAgKiBAcGFyYW0gZyAgLSBUaGUgZ3JlZW4gY2hhbm5lbC4KICAgICAgICAgKiBAcGFyYW0gYiAgLSBUaGUgYmx1ZSBjaGFubmVsLgogICAgICAgICAqIEBwYXJhbSBhICAtIFRoZSBhbHBoYSBjaGFubmVsLgogICAgICAgICAqLwogICAgICAgIHNldChyLCBnLCBiLCBhID0gMS4wKSB7CiAgICAgICAgICAgIHRoaXMuciA9IHI7CiAgICAgICAgICAgIHRoaXMuZyA9IGc7CiAgICAgICAgICAgIHRoaXMuYiA9IGI7CiAgICAgICAgICAgIHRoaXMuYSA9IGE7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgY3VycmVudCBjb2xvciBzdGF0ZSB3aXRoIGFub3RoZXIgYENvbG9yYCBvYmplY3QuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgY29sb3IgdG8gc2V0IGZyb20uCiAgICAgICAgICovCiAgICAgICAgc2V0RnJvbU90aGVyKG90aGVyKSB7CiAgICAgICAgICAgIHRoaXMuciA9IG90aGVyLnI7CiAgICAgICAgICAgIHRoaXMuZyA9IG90aGVyLmc7CiAgICAgICAgICAgIHRoaXMuYiA9IG90aGVyLmI7CiAgICAgICAgICAgIHRoaXMuYSA9IG90aGVyLmE7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHRlciBmcm9tIGFuIFJHQiBhcnJheS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldEFzUkdCQXJyYXkoKSB7CiAgICAgICAgICAgIHJldHVybiBbdGhpcy5yICogMjU1LCB0aGlzLmcgKiAyNTUsIHRoaXMuYiAqIDI1NV07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHRlciBmcm9tIGFuIFJHQiBkaWN0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0QXNSR0JEaWN0KCkgewogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgcjogdGhpcy5yICogMjU1LAogICAgICAgICAgICAgICAgZzogdGhpcy5nICogMjU1LAogICAgICAgICAgICAgICAgYjogdGhpcy5iICogMjU1LAogICAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXR0ZXIgZnJvbSBhIFJHQiB2YWx1ZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSByIC0gVGhlIHJlZCBjaGFubmVsLgogICAgICAgICAqIEBwYXJhbSBnICAtIFRoZSBncmVlbiBjaGFubmVsLgogICAgICAgICAqIEBwYXJhbSBiICAtIFRoZSBibHVlIGNoYW5uZWwuCiAgICAgICAgICogQHBhcmFtIGEgIC0gVGhlIGFscGhhIGNoYW5uZWwuCiAgICAgICAgICovCiAgICAgICAgc2V0RnJvbVJHQihyLCBnLCBiLCBhKSB7CiAgICAgICAgICAgIHRoaXMuciA9IHIgLyAyNTU7CiAgICAgICAgICAgIHRoaXMuZyA9IGcgLyAyNTU7CiAgICAgICAgICAgIHRoaXMuYiA9IGIgLyAyNTU7CiAgICAgICAgICAgIHRoaXMuYSA9IGEgPyBhIC8gMjU1IDogMS4wOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXR0ZXIgZnJvbSBhbiBSR0IgZGljdC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSB2YWxzIC0gVGhlIHZhbHMgcGFyYW0uCiAgICAgICAgICovCiAgICAgICAgc2V0RnJvbVJHQkRpY3QodmFscykgewogICAgICAgICAgICB0aGlzLnIgPSB2YWxzLnIgLyAyNTU7CiAgICAgICAgICAgIHRoaXMuZyA9IHZhbHMuZyAvIDI1NTsKICAgICAgICAgICAgdGhpcy5iID0gdmFscy5iIC8gMjU1OwogICAgICAgICAgICB0aGlzLmEgPSB2YWxzLmEgPT0gNCA/IHZhbHMuYSAvIDI1NSA6IDEuMDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0dGVyIGZyb20gYSBoZXhhZGVjaW1hbCB2YWx1ZS4KICAgICAgICAgKiBFLmcuICNmZjAwMDAKICAgICAgICAgKiBAcGFyYW0gaGV4IC0gVGhlIGhleCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRGcm9tSGV4KGhleCkgewogICAgICAgICAgICBmdW5jdGlvbiBoZXhUb1JnYihoZXgpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IC9eIz8oW2EtZlxkXXsyfSkoW2EtZlxkXXsyfSkoW2EtZlxkXXsyfSkkL2kuZXhlYyhoZXgpOwogICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdAogICAgICAgICAgICAgICAgICAgID8gewogICAgICAgICAgICAgICAgICAgICAgICByOiBwYXJzZUludChyZXN1bHRbMV0sIDE2KSwKICAgICAgICAgICAgICAgICAgICAgICAgZzogcGFyc2VJbnQocmVzdWx0WzJdLCAxNiksCiAgICAgICAgICAgICAgICAgICAgICAgIGI6IHBhcnNlSW50KHJlc3VsdFszXSwgMTYpLAogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICA6IG51bGw7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgcmdiID0gaGV4VG9SZ2IoaGV4KTsKICAgICAgICAgICAgaWYgKCFyZ2IpIHsKICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignSW52YWxpZCBoZXggY29kZTonICsgaGV4KTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnNldEZyb21SR0IocmdiLnIsIHJnYi5nLCByZ2IuYik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIENvbG9yIHZhbHVlcyBmcm9tIGEgQ1NTIGNvbG9yIG5hbWUuCiAgICAgICAgICogRS5nLiAicmVkIgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIENTUyBjb2xvciBuYW1lLgogICAgICAgICAqLwogICAgICAgIHNldEZyb21DU1NDb2xvck5hbWUobmFtZSkgewogICAgICAgICAgICBjb25zdCBjb2xvdXJOYW1lVG9IZXggPSAoY29sb3VyKSA9PiB7CiAgICAgICAgICAgICAgICBjb25zdCBjb2xvcnMgPSB7CiAgICAgICAgICAgICAgICAgICAgYWxpY2VibHVlOiAnI2YwZjhmZicsCiAgICAgICAgICAgICAgICAgICAgYW50aXF1ZXdoaXRlOiAnI2ZhZWJkNycsCiAgICAgICAgICAgICAgICAgICAgYXF1YTogJyMwMGZmZmYnLAogICAgICAgICAgICAgICAgICAgIGFxdWFtYXJpbmU6ICcjN2ZmZmQ0JywKICAgICAgICAgICAgICAgICAgICBhenVyZTogJyNmMGZmZmYnLAogICAgICAgICAgICAgICAgICAgIGJlaWdlOiAnI2Y1ZjVkYycsCiAgICAgICAgICAgICAgICAgICAgYmlzcXVlOiAnI2ZmZTRjNCcsCiAgICAgICAgICAgICAgICAgICAgYmxhY2s6ICcjMDAwMDAwJywKICAgICAgICAgICAgICAgICAgICBibGFuY2hlZGFsbW9uZDogJyNmZmViY2QnLAogICAgICAgICAgICAgICAgICAgIGJsdWU6ICcjMDAwMGZmJywKICAgICAgICAgICAgICAgICAgICBibHVldmlvbGV0OiAnIzhhMmJlMicsCiAgICAgICAgICAgICAgICAgICAgYnJvd246ICcjYTUyYTJhJywKICAgICAgICAgICAgICAgICAgICBidXJseXdvb2Q6ICcjZGViODg3JywKICAgICAgICAgICAgICAgICAgICBjYWRldGJsdWU6ICcjNWY5ZWEwJywKICAgICAgICAgICAgICAgICAgICBjaGFydHJldXNlOiAnIzdmZmYwMCcsCiAgICAgICAgICAgICAgICAgICAgY2hvY29sYXRlOiAnI2QyNjkxZScsCiAgICAgICAgICAgICAgICAgICAgY29yYWw6ICcjZmY3ZjUwJywKICAgICAgICAgICAgICAgICAgICBjb3JuZmxvd2VyYmx1ZTogJyM2NDk1ZWQnLAogICAgICAgICAgICAgICAgICAgIGNvcm5zaWxrOiAnI2ZmZjhkYycsCiAgICAgICAgICAgICAgICAgICAgY3JpbXNvbjogJyNkYzE0M2MnLAogICAgICAgICAgICAgICAgICAgIGN5YW46ICcjMDBmZmZmJywKICAgICAgICAgICAgICAgICAgICBkYXJrYmx1ZTogJyMwMDAwOGInLAogICAgICAgICAgICAgICAgICAgIGRhcmtjeWFuOiAnIzAwOGI4YicsCiAgICAgICAgICAgICAgICAgICAgZGFya2dvbGRlbnJvZDogJyNiODg2MGInLAogICAgICAgICAgICAgICAgICAgIGRhcmtncmF5OiAnI2E5YTlhOScsCiAgICAgICAgICAgICAgICAgICAgZGFya2dyZWVuOiAnIzAwNjQwMCcsCiAgICAgICAgICAgICAgICAgICAgZGFya2toYWtpOiAnI2JkYjc2YicsCiAgICAgICAgICAgICAgICAgICAgZGFya21hZ2VudGE6ICcjOGIwMDhiJywKICAgICAgICAgICAgICAgICAgICBkYXJrb2xpdmVncmVlbjogJyM1NTZiMmYnLAogICAgICAgICAgICAgICAgICAgIGRhcmtvcmFuZ2U6ICcjZmY4YzAwJywKICAgICAgICAgICAgICAgICAgICBkYXJrb3JjaGlkOiAnIzk5MzJjYycsCiAgICAgICAgICAgICAgICAgICAgZGFya3JlZDogJyM4YjAwMDAnLAogICAgICAgICAgICAgICAgICAgIGRhcmtzYWxtb246ICcjZTk5NjdhJywKICAgICAgICAgICAgICAgICAgICBkYXJrc2VhZ3JlZW46ICcjOGZiYzhmJywKICAgICAgICAgICAgICAgICAgICBkYXJrc2xhdGVibHVlOiAnIzQ4M2Q4YicsCiAgICAgICAgICAgICAgICAgICAgZGFya3NsYXRlZ3JheTogJyMyZjRmNGYnLAogICAgICAgICAgICAgICAgICAgIGRhcmt0dXJxdW9pc2U6ICcjMDBjZWQxJywKICAgICAgICAgICAgICAgICAgICBkYXJrdmlvbGV0OiAnIzk0MDBkMycsCiAgICAgICAgICAgICAgICAgICAgZGVlcHBpbms6ICcjZmYxNDkzJywKICAgICAgICAgICAgICAgICAgICBkZWVwc2t5Ymx1ZTogJyMwMGJmZmYnLAogICAgICAgICAgICAgICAgICAgIGRpbWdyYXk6ICcjNjk2OTY5JywKICAgICAgICAgICAgICAgICAgICBkb2RnZXJibHVlOiAnIzFlOTBmZicsCiAgICAgICAgICAgICAgICAgICAgZmlyZWJyaWNrOiAnI2IyMjIyMicsCiAgICAgICAgICAgICAgICAgICAgZmxvcmFsd2hpdGU6ICcjZmZmYWYwJywKICAgICAgICAgICAgICAgICAgICBmb3Jlc3RncmVlbjogJyMyMjhiMjInLAogICAgICAgICAgICAgICAgICAgIGZ1Y2hzaWE6ICcjZmYwMGZmJywKICAgICAgICAgICAgICAgICAgICBnYWluc2Jvcm86ICcjZGNkY2RjJywKICAgICAgICAgICAgICAgICAgICBnaG9zdHdoaXRlOiAnI2Y4ZjhmZicsCiAgICAgICAgICAgICAgICAgICAgZ29sZDogJyNmZmQ3MDAnLAogICAgICAgICAgICAgICAgICAgIGdvbGRlbnJvZDogJyNkYWE1MjAnLAogICAgICAgICAgICAgICAgICAgIGdyYXk6ICcjODA4MDgwJywKICAgICAgICAgICAgICAgICAgICBncmVlbjogJyMwMDgwMDAnLAogICAgICAgICAgICAgICAgICAgIGdyZWVueWVsbG93OiAnI2FkZmYyZicsCiAgICAgICAgICAgICAgICAgICAgaG9uZXlkZXc6ICcjZjBmZmYwJywKICAgICAgICAgICAgICAgICAgICBob3RwaW5rOiAnI2ZmNjliNCcsCiAgICAgICAgICAgICAgICAgICAgJ2luZGlhbnJlZCAnOiAnI2NkNWM1YycsCiAgICAgICAgICAgICAgICAgICAgaW5kaWdvOiAnIzRiMDA4MicsCiAgICAgICAgICAgICAgICAgICAgaXZvcnk6ICcjZmZmZmYwJywKICAgICAgICAgICAgICAgICAgICBraGFraTogJyNmMGU2OGMnLAogICAgICAgICAgICAgICAgICAgIGxhdmVuZGVyOiAnI2U2ZTZmYScsCiAgICAgICAgICAgICAgICAgICAgbGF2ZW5kZXJibHVzaDogJyNmZmYwZjUnLAogICAgICAgICAgICAgICAgICAgIGxhd25ncmVlbjogJyM3Y2ZjMDAnLAogICAgICAgICAgICAgICAgICAgIGxlbW9uY2hpZmZvbjogJyNmZmZhY2QnLAogICAgICAgICAgICAgICAgICAgIGxpZ2h0Ymx1ZTogJyNhZGQ4ZTYnLAogICAgICAgICAgICAgICAgICAgIGxpZ2h0Y29yYWw6ICcjZjA4MDgwJywKICAgICAgICAgICAgICAgICAgICBsaWdodGN5YW46ICcjZTBmZmZmJywKICAgICAgICAgICAgICAgICAgICBsaWdodGdvbGRlbnJvZHllbGxvdzogJyNmYWZhZDInLAogICAgICAgICAgICAgICAgICAgIGxpZ2h0Z3JleTogJyNkM2QzZDMnLAogICAgICAgICAgICAgICAgICAgIGxpZ2h0Z3JlZW46ICcjOTBlZTkwJywKICAgICAgICAgICAgICAgICAgICBsaWdodHBpbms6ICcjZmZiNmMxJywKICAgICAgICAgICAgICAgICAgICBsaWdodHNhbG1vbjogJyNmZmEwN2EnLAogICAgICAgICAgICAgICAgICAgIGxpZ2h0c2VhZ3JlZW46ICcjMjBiMmFhJywKICAgICAgICAgICAgICAgICAgICBsaWdodHNreWJsdWU6ICcjODdjZWZhJywKICAgICAgICAgICAgICAgICAgICBsaWdodHNsYXRlZ3JheTogJyM3Nzg4OTknLAogICAgICAgICAgICAgICAgICAgIGxpZ2h0c3RlZWxibHVlOiAnI2IwYzRkZScsCiAgICAgICAgICAgICAgICAgICAgbGlnaHR5ZWxsb3c6ICcjZmZmZmUwJywKICAgICAgICAgICAgICAgICAgICBsaW1lOiAnIzAwZmYwMCcsCiAgICAgICAgICAgICAgICAgICAgbGltZWdyZWVuOiAnIzMyY2QzMicsCiAgICAgICAgICAgICAgICAgICAgbGluZW46ICcjZmFmMGU2JywKICAgICAgICAgICAgICAgICAgICBtYWdlbnRhOiAnI2ZmMDBmZicsCiAgICAgICAgICAgICAgICAgICAgbWFyb29uOiAnIzgwMDAwMCcsCiAgICAgICAgICAgICAgICAgICAgbWVkaXVtYXF1YW1hcmluZTogJyM2NmNkYWEnLAogICAgICAgICAgICAgICAgICAgIG1lZGl1bWJsdWU6ICcjMDAwMGNkJywKICAgICAgICAgICAgICAgICAgICBtZWRpdW1vcmNoaWQ6ICcjYmE1NWQzJywKICAgICAgICAgICAgICAgICAgICBtZWRpdW1wdXJwbGU6ICcjOTM3MGQ4JywKICAgICAgICAgICAgICAgICAgICBtZWRpdW1zZWFncmVlbjogJyMzY2IzNzEnLAogICAgICAgICAgICAgICAgICAgIG1lZGl1bXNsYXRlYmx1ZTogJyM3YjY4ZWUnLAogICAgICAgICAgICAgICAgICAgIG1lZGl1bXNwcmluZ2dyZWVuOiAnIzAwZmE5YScsCiAgICAgICAgICAgICAgICAgICAgbWVkaXVtdHVycXVvaXNlOiAnIzQ4ZDFjYycsCiAgICAgICAgICAgICAgICAgICAgbWVkaXVtdmlvbGV0cmVkOiAnI2M3MTU4NScsCiAgICAgICAgICAgICAgICAgICAgbWlkbmlnaHRibHVlOiAnIzE5MTk3MCcsCiAgICAgICAgICAgICAgICAgICAgbWludGNyZWFtOiAnI2Y1ZmZmYScsCiAgICAgICAgICAgICAgICAgICAgbWlzdHlyb3NlOiAnI2ZmZTRlMScsCiAgICAgICAgICAgICAgICAgICAgbW9jY2FzaW46ICcjZmZlNGI1JywKICAgICAgICAgICAgICAgICAgICBuYXZham93aGl0ZTogJyNmZmRlYWQnLAogICAgICAgICAgICAgICAgICAgIG5hdnk6ICcjMDAwMDgwJywKICAgICAgICAgICAgICAgICAgICBvbGRsYWNlOiAnI2ZkZjVlNicsCiAgICAgICAgICAgICAgICAgICAgb2xpdmU6ICcjODA4MDAwJywKICAgICAgICAgICAgICAgICAgICBvbGl2ZWRyYWI6ICcjNmI4ZTIzJywKICAgICAgICAgICAgICAgICAgICBvcmFuZ2U6ICcjZmZhNTAwJywKICAgICAgICAgICAgICAgICAgICBvcmFuZ2VyZWQ6ICcjZmY0NTAwJywKICAgICAgICAgICAgICAgICAgICBvcmNoaWQ6ICcjZGE3MGQ2JywKICAgICAgICAgICAgICAgICAgICBwYWxlZ29sZGVucm9kOiAnI2VlZThhYScsCiAgICAgICAgICAgICAgICAgICAgcGFsZWdyZWVuOiAnIzk4ZmI5OCcsCiAgICAgICAgICAgICAgICAgICAgcGFsZXR1cnF1b2lzZTogJyNhZmVlZWUnLAogICAgICAgICAgICAgICAgICAgIHBhbGV2aW9sZXRyZWQ6ICcjZDg3MDkzJywKICAgICAgICAgICAgICAgICAgICBwYXBheWF3aGlwOiAnI2ZmZWZkNScsCiAgICAgICAgICAgICAgICAgICAgcGVhY2hwdWZmOiAnI2ZmZGFiOScsCiAgICAgICAgICAgICAgICAgICAgcGVydTogJyNjZDg1M2YnLAogICAgICAgICAgICAgICAgICAgIHBpbms6ICcjZmZjMGNiJywKICAgICAgICAgICAgICAgICAgICBwbHVtOiAnI2RkYTBkZCcsCiAgICAgICAgICAgICAgICAgICAgcG93ZGVyYmx1ZTogJyNiMGUwZTYnLAogICAgICAgICAgICAgICAgICAgIHB1cnBsZTogJyM4MDAwODAnLAogICAgICAgICAgICAgICAgICAgIHJlYmVjY2FwdXJwbGU6ICcjNjYzMzk5JywKICAgICAgICAgICAgICAgICAgICByZWQ6ICcjZmYwMDAwJywKICAgICAgICAgICAgICAgICAgICByb3N5YnJvd246ICcjYmM4ZjhmJywKICAgICAgICAgICAgICAgICAgICByb3lhbGJsdWU6ICcjNDE2OWUxJywKICAgICAgICAgICAgICAgICAgICBzYWRkbGVicm93bjogJyM4YjQ1MTMnLAogICAgICAgICAgICAgICAgICAgIHNhbG1vbjogJyNmYTgwNzInLAogICAgICAgICAgICAgICAgICAgIHNhbmR5YnJvd246ICcjZjRhNDYwJywKICAgICAgICAgICAgICAgICAgICBzZWFncmVlbjogJyMyZThiNTcnLAogICAgICAgICAgICAgICAgICAgIHNlYXNoZWxsOiAnI2ZmZjVlZScsCiAgICAgICAgICAgICAgICAgICAgc2llbm5hOiAnI2EwNTIyZCcsCiAgICAgICAgICAgICAgICAgICAgc2lsdmVyOiAnI2MwYzBjMCcsCiAgICAgICAgICAgICAgICAgICAgc2t5Ymx1ZTogJyM4N2NlZWInLAogICAgICAgICAgICAgICAgICAgIHNsYXRlYmx1ZTogJyM2YTVhY2QnLAogICAgICAgICAgICAgICAgICAgIHNsYXRlZ3JheTogJyM3MDgwOTAnLAogICAgICAgICAgICAgICAgICAgIHNub3c6ICcjZmZmYWZhJywKICAgICAgICAgICAgICAgICAgICBzcHJpbmdncmVlbjogJyMwMGZmN2YnLAogICAgICAgICAgICAgICAgICAgIHN0ZWVsYmx1ZTogJyM0NjgyYjQnLAogICAgICAgICAgICAgICAgICAgIHRhbjogJyNkMmI0OGMnLAogICAgICAgICAgICAgICAgICAgIHRlYWw6ICcjMDA4MDgwJywKICAgICAgICAgICAgICAgICAgICB0aGlzdGxlOiAnI2Q4YmZkOCcsCiAgICAgICAgICAgICAgICAgICAgdG9tYXRvOiAnI2ZmNjM0NycsCiAgICAgICAgICAgICAgICAgICAgdHVycXVvaXNlOiAnIzQwZTBkMCcsCiAgICAgICAgICAgICAgICAgICAgdmlvbGV0OiAnI2VlODJlZScsCiAgICAgICAgICAgICAgICAgICAgd2hlYXQ6ICcjZjVkZWIzJywKICAgICAgICAgICAgICAgICAgICB3aGl0ZTogJyNmZmZmZmYnLAogICAgICAgICAgICAgICAgICAgIHdoaXRlc21va2U6ICcjZjVmNWY1JywKICAgICAgICAgICAgICAgICAgICB5ZWxsb3c6ICcjZmZmZjAwJywKICAgICAgICAgICAgICAgICAgICB5ZWxsb3dncmVlbjogJyM5YWNkMzInLAogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHJldHVybiBjb2xvcnNbY29sb3VyLnRvTG93ZXJDYXNlKCldOwogICAgICAgICAgICAgICAgLy8gIGlmICh0eXBlb2YgY29sb3JzW2NvbG91ci50b0xvd2VyQ2FzZSgpXSAhPSAndW5kZWZpbmVkJykgcmV0dXJuIGNvbG9yc1tjb2xvdXIudG9Mb3dlckNhc2UoKV0KICAgICAgICAgICAgICAgIC8vIHJldHVybiBmYWxzZQogICAgICAgICAgICB9OwogICAgICAgICAgICBpZiAobmFtZS5zdGFydHNXaXRoKCcjJykpIHsKICAgICAgICAgICAgICAgIHRoaXMuc2V0RnJvbUhleChuYW1lKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIGNvbnN0IGhleENvbG9yID0gY29sb3VyTmFtZVRvSGV4KG5hbWUpOwogICAgICAgICAgICAgICAgaWYgKGhleENvbG9yKQogICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0RnJvbUhleChoZXhDb2xvcik7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgaGV4YWRlY2ltYWwgdmFsdWUgb2YgdGhpcyBjb2xvciwgaW5jbHVkaW5nIHRoZSBsZWFkaW5nICIjIiBjaGFyYWN0ZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgaGV4IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHRvSGV4KCkgewogICAgICAgICAgICBmdW5jdGlvbiBjb21wb25lbnRUb0hleChjKSB7CiAgICAgICAgICAgICAgICBjb25zdCBpbnQgPSBNYXRoLnJvdW5kKGMgKiAyNTUpOwogICAgICAgICAgICAgICAgY29uc3QgaGV4ID0gaW50LnRvU3RyaW5nKDE2KTsKICAgICAgICAgICAgICAgIHJldHVybiBoZXgubGVuZ3RoID09IDEgPyAnMCcgKyBoZXggOiBoZXg7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuICcjJyArIGNvbXBvbmVudFRvSGV4KHRoaXMucikgKyBjb21wb25lbnRUb0hleCh0aGlzLmcpICsgY29tcG9uZW50VG9IZXgodGhpcy5iKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2hlY2tzIGlmIHRoaXMgQ29sb3IgIGNvbnRhaW5zIHRoZSBzYW1lIHZhbHVlcyBhcyB0aGUgb3RoZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgQ29sb3IgdG8gY29tcGFyZSB3aXRoLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgdmFsdWVzIGFyZSB0aGUgc2FtZSwgb3RoZXJ3aXNlLCBgZmFsc2VgLgogICAgICAgICAqLwogICAgICAgIGlzRXF1YWwob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuciA9PSBvdGhlci5yICYmIHRoaXMuZyA9PSBvdGhlci5nICYmIHRoaXMuYiA9PSBvdGhlci5iICYmIHRoaXMuYSA9PSBvdGhlci5hOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBjb2xvciBpcyBOT1QgZXhhY3RseSB0aGUgc2FtZSBhcyBvdGhlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBjb2xvciB0byBjb21wYXJlIHdpdGguCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdHJ1ZSBvciBmYWxzZS4KICAgICAgICAgKi8KICAgICAgICBub3RFcXVhbHMob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuciAhPSBvdGhlci5yICYmIHRoaXMuZyAhPSBvdGhlci5nICYmIHRoaXMuYiAhPSBvdGhlci5iICYmIHRoaXMuYSAhPSBvdGhlci5hOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBjb2xvciBpcyBhcHByb3hpbWF0ZWx5IHRoZSBzYW1lIGFzIG90aGVyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIGNvbG9yIHRvIGNvbXBhcmUgd2l0aC4KICAgICAgICAgKiBAcGFyYW0gcHJlY2lzaW9uIC0gVGhlIHByZWNpc2lvbiB0byB3aGljaCB0aGUgdmFsdWVzIG11c3QgbWF0Y2guCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdHJ1ZSBvciBmYWxzZS4KICAgICAgICAgKi8KICAgICAgICBhcHByb3hFcXVhbChvdGhlciwgcHJlY2lzaW9uID0gTnVtYmVyLkVQU0lMT04pIHsKICAgICAgICAgICAgcmV0dXJuIChNYXRoLmFicyh0aGlzLnIgLSBvdGhlci5yKSA8IHByZWNpc2lvbiAmJgogICAgICAgICAgICAgICAgTWF0aC5hYnModGhpcy5nIC0gb3RoZXIuZykgPCBwcmVjaXNpb24gJiYKICAgICAgICAgICAgICAgIE1hdGguYWJzKHRoaXMuYiAtIG90aGVyLmIpIDwgcHJlY2lzaW9uICYmCiAgICAgICAgICAgICAgICBNYXRoLmFicyh0aGlzLmEgLSBvdGhlci5hKSA8IHByZWNpc2lvbik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYSBuZXcgQ29sb3Igd2hpY2ggaXMgdGhpcyBDb2xvciBhZGRlZCB0byBvdGhlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBjb2xvciB0byBhZGQuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgY29sb3IuCiAgICAgICAgICovCiAgICAgICAgYWRkKG90aGVyKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgQ29sb3IodGhpcy5yICsgb3RoZXIuciwgdGhpcy5nICsgb3RoZXIuZywgdGhpcy5iICsgb3RoZXIuYiwgdGhpcy5hICsgb3RoZXIuYSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFVwZGF0ZXMgdGhpcyBDb2xvciBieSBhZGRpbmcgdGhlIHZhbHVlcyBmcm9tIHRoZSBvdGhlciBjb2xvci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBjb2xvciB0byBhZGQuCiAgICAgICAgICovCiAgICAgICAgYWRkSW5QbGFjZShvdGhlcikgewogICAgICAgICAgICB0aGlzLnIgKz0gb3RoZXIucjsKICAgICAgICAgICAgdGhpcy5nICs9IG90aGVyLmc7CiAgICAgICAgICAgIHRoaXMuYiArPSBvdGhlci5iOwogICAgICAgICAgICB0aGlzLmEgKz0gb3RoZXIuYTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBhIG5ldyBjb2xvciB3aGljaCBpcyB0aGlzIGNvbG9yIHN1YnRyYWN0ZWQgZnJvbSBvdGhlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBjb2xvciB0byBzdWJ0cmFjdC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBjb2xvci4KICAgICAgICAgKi8KICAgICAgICBzdWJ0cmFjdChvdGhlcikgewogICAgICAgICAgICByZXR1cm4gbmV3IENvbG9yKHRoaXMuciAtIG90aGVyLnIsIHRoaXMuZyAtIG90aGVyLmcsIHRoaXMuYiAtIG90aGVyLmIsIHRoaXMuYSAtIG90aGVyLmEpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTY2FsZXMgdGhpcyBjb2xvciBieSBzY2FsYXIgYW5kIHJldHVybiB0aGUgcmVzdWx0IGFzIGEgbmV3IFZlYzQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc2NhbGFyIC0gVGhlIHNjYWxhciB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBjb2xvci4KICAgICAgICAgKi8KICAgICAgICBzY2FsZShzY2FsYXIpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBDb2xvcih0aGlzLnIgKiBzY2FsYXIsIHRoaXMuZyAqIHNjYWxhciwgdGhpcy5iICogc2NhbGFyLCB0aGlzLmEgKiBzY2FsYXIpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTY2FsZXMgdGhpcyBjb2xvciBieSBzY2FsYXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc2NhbGFyIC0gVGhlIHNjYWxhciB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzY2FsZUluUGxhY2Uoc2NhbGFyKSB7CiAgICAgICAgICAgIHRoaXMuciAqPSBzY2FsYXI7CiAgICAgICAgICAgIHRoaXMuZyAqPSBzY2FsYXI7CiAgICAgICAgICAgIHRoaXMuYiAqPSBzY2FsYXI7CiAgICAgICAgICAgIHRoaXMuYSAqPSBzY2FsYXI7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEFwcGx5IGdhbW1hIGNvcnJlY3Rpb24gdG8gdGhpcyBjb2xvcgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGdhbW1hIC0gVGhlIGdhbW1hIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGFwcGx5R2FtbWEoZ2FtbWEpIHsKICAgICAgICAgICAgdGhpcy5zZXQoTWF0aC5wb3codGhpcy5yLCBnYW1tYSksIE1hdGgucG93KHRoaXMuZywgZ2FtbWEpLCBNYXRoLnBvdyh0aGlzLmIsIGdhbW1hKSwgdGhpcy5hKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ29udmVydHMgdG8gbGluZWFyIGNvbG9yIHNwYWNlIGFuZCByZXR1cm5zIGEgbmV3IGNvbG9yCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gZ2FtbWEgLSBUaGUgZ2FtbWEgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgY29sb3IuCiAgICAgICAgICovCiAgICAgICAgdG9MaW5lYXIoZ2FtbWEgPSAyLjIpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBDb2xvcihNYXRoLnBvdyh0aGlzLnIsIGdhbW1hKSwgTWF0aC5wb3codGhpcy5nLCBnYW1tYSksIE1hdGgucG93KHRoaXMuYiwgZ2FtbWEpLCB0aGlzLmEpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiByZXR1cm5zIGEgbmV3IGNvbG9yIHZhbHVlIHZhbHVlIGlzIG1hcHBlZCBpbnRvIGEgZ2FtbWEgY3VydmUKICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBnYW1tYSAtIFRoZSBnYW1tYSB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBjb2xvci4KICAgICAgICAgKi8KICAgICAgICB0b0dhbW1hKGdhbW1hID0gMi4yKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgQ29sb3IoTWF0aC5wb3codGhpcy5yLCAxLjAgLyBnYW1tYSksIE1hdGgucG93KHRoaXMuZywgMS4wIC8gZ2FtbWEpLCBNYXRoLnBvdyh0aGlzLmIsIDEuMCAvIGdhbW1hKSwgdGhpcy5hKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsY3VsYXRlcyBhbmQgcmV0dXJucyB0aGUgbHVtaW5hbmNlIG9mIHRoZSBsaW5lYXIgUkdCIGNvbXBvbmVudHMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBsdW1pbmFuY2UoKSB7CiAgICAgICAgICAgIHJldHVybiAwLjIxMjYgKiB0aGlzLnIgKyAwLjcxNTIgKiB0aGlzLmcgKyAwLjA3MjIgKiB0aGlzLmI7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFBlcmZvcm1zIGEgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0aGlzIGNvbG9yIGFuZCBvdGhlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBjb2xvciB0byBpbnRlcnBvbGF0ZSBiZXR3ZWVuLgogICAgICAgICAqIEBwYXJhbSB0IC0gSW50ZXJwb2xhdGlvbiBhbW91bnQgYmV0d2VlbiB0aGUgdHdvIGlucHV0cy4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBjb2xvci4KICAgICAgICAgKi8KICAgICAgICBsZXJwKG90aGVyLCB0KSB7CiAgICAgICAgICAgIGNvbnN0IGFyID0gdGhpcy5yOwogICAgICAgICAgICBjb25zdCBhZyA9IHRoaXMuZzsKICAgICAgICAgICAgY29uc3QgYWIgPSB0aGlzLmI7CiAgICAgICAgICAgIGNvbnN0IGFhID0gdGhpcy5hOwogICAgICAgICAgICByZXR1cm4gbmV3IENvbG9yKGFyICsgdCAqIChvdGhlci5yIC0gYXIpLCBhZyArIHQgKiAob3RoZXIuZyAtIGFnKSwgYWIgKyB0ICogKG90aGVyLmIgLSBhYiksIGFhICsgdCAqIChvdGhlci5hIC0gYWEpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlcyBhIHJhbmRvbSBjb2xvci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBnYW1tYU9mZnNldCAtIFRoZSBnYW1tYSBvZmZzZXQuIFZhbHVlcyBiZXR3ZWVuIDAgYW5kIDEgaW5jcmVhc2UgdGhlIGF2ZXJhZ2UgYnJpZ2h0bmVzcyBvZiB0aGUgZ2VuZXJhdGVkIGNvbG9yLiBWYWx1ZXMgYmV0d2VlbiAwIGFuZCAtMSBkYXJrZW4gdGhlIGdlbmVyYXRlZCBjb2xvciB2YWx1ZXMuCiAgICAgICAgICogQHBhcmFtIHJhbmRvbUFscGhhIC0gRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBhbHBoYSBjaGFubmVsIGlzIHJhbmRvbS4gSWYgbm90LCB0aGUgYWxwaGEgdmFsdWVzIHdpbGwgYmUgMS4wLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgbmV3IHJhbmRvbSBjb2xvci4KICAgICAgICAgKi8KICAgICAgICBzdGF0aWMgcmFuZG9tKGdhbW1hT2Zmc2V0ID0gMC4wLCByYW5kb21BbHBoYSA9IGZhbHNlKSB7CiAgICAgICAgICAgIGlmIChnYW1tYU9mZnNldCA+IDAuMCkgewogICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBDb2xvcihnYW1tYU9mZnNldCArIE1hdGgucmFuZG9tKCkgKiAoMS4wIC0gZ2FtbWFPZmZzZXQpLCBnYW1tYU9mZnNldCArIE1hdGgucmFuZG9tKCkgKiAoMS4wIC0gZ2FtbWFPZmZzZXQpLCBnYW1tYU9mZnNldCArIE1hdGgucmFuZG9tKCkgKiAoMS4wIC0gZ2FtbWFPZmZzZXQpLCByYW5kb21BbHBoYSA/IGdhbW1hT2Zmc2V0ICsgTWF0aC5yYW5kb20oKSAqICgxLjAgLSBnYW1tYU9mZnNldCkgOiAxLjApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChnYW1tYU9mZnNldCA8IDAuMCkgewogICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBDb2xvcihNYXRoLnJhbmRvbSgpICogKDEuMCArIGdhbW1hT2Zmc2V0KSwgTWF0aC5yYW5kb20oKSAqICgxLjAgKyBnYW1tYU9mZnNldCksIE1hdGgucmFuZG9tKCkgKiAoMS4wICsgZ2FtbWFPZmZzZXQpLCByYW5kb21BbHBoYSA/IE1hdGgucmFuZG9tKCkgKiAoMS4wICsgZ2FtbWFPZmZzZXQpIDogMS4wKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbmV3IENvbG9yKE1hdGgucmFuZG9tKCksIE1hdGgucmFuZG9tKCksIE1hdGgucmFuZG9tKCksIHJhbmRvbUFscGhhID8gTWF0aC5yYW5kb20oKSA6IDEuMCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENsb25lcyB0aGlzIGNvbG9yIGFuZCByZXR1cm5zIGEgbmV3IGNvbG9yLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgY29sb3IuCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgQ29sb3IodGhpcy5yLCB0aGlzLmcsIHRoaXMuYiwgdGhpcy5hKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgdHlwZSBhcyBhbiBhcnJheS4gT2Z0ZW4gdXNlZCB0byBwYXNzIHR5cGVzIHRvIHRoZSBHUFUuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhcyBhbiBhcnJheS4KICAgICAgICAgKi8KICAgICAgICBhc0FycmF5KCkgewogICAgICAgICAgICByZXR1cm4gW3RoaXMuciwgdGhpcy5nLCB0aGlzLmIsIHRoaXMuYV07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHRlciBmcm9tIGFuIFJHQiBhcnJheS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSB2YWxzIC0gVGhlIHZhbHMgcGFyYW0uCiAgICAgICAgICovCiAgICAgICAgZnJvbUFycmF5KHZhbHMpIHsKICAgICAgICAgICAgdGhpcy5yID0gdmFsc1swXSAvIDI1NTsKICAgICAgICAgICAgdGhpcy5nID0gdmFsc1sxXSAvIDI1NTsKICAgICAgICAgICAgdGhpcy5iID0gdmFsc1syXSAvIDI1NTsKICAgICAgICAgICAgdGhpcy5hID0gdmFscy5sZW5ndGggPT0gNCA/IHZhbHNbM10gLyAyNTUgOiAxLjA7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQZXJzaXN0ZW5jZQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSB0b0pTT04gbWV0aG9kIGVuY29kZXMgdGhpcyB0eXBlIGFzIGEganNvbiBvYmplY3QgZm9yIHBlcnNpc3RlbmNlLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSBqc29uIG9iamVjdC4KICAgICAgICAgKi8KICAgICAgICB0b0pTT04oKSB7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICByOiB0aGlzLnIsCiAgICAgICAgICAgICAgICBnOiB0aGlzLmcsCiAgICAgICAgICAgICAgICBiOiB0aGlzLmIsCiAgICAgICAgICAgICAgICBhOiB0aGlzLmEsCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBmcm9tSlNPTiBtZXRob2QgZGVjb2RlcyBhIGpzb24gb2JqZWN0IGZvciB0aGlzIHR5cGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaiAtIFRoZSBqc29uIG9iamVjdC4KICAgICAgICAgKi8KICAgICAgICBmcm9tSlNPTihqKSB7CiAgICAgICAgICAgIHRoaXMuciA9IGoucjsKICAgICAgICAgICAgdGhpcy5nID0gai5nOwogICAgICAgICAgICB0aGlzLmIgPSBqLmI7CiAgICAgICAgICAgIHRoaXMuYSA9IGouYTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogTG9hZHMgdGhlIHN0YXRlIG9mIHRoZSB2YWx1ZSBmcm9tIGEgYmluYXJ5IHJlYWRlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSByZWFkZXIgLSBUaGUgcmVhZGVyIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyKSB7CiAgICAgICAgICAgIHRoaXMuciA9IHJlYWRlci5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICB0aGlzLmcgPSByZWFkZXIubG9hZEZsb2F0MzIoKTsKICAgICAgICAgICAgdGhpcy5iID0gcmVhZGVyLmxvYWRGbG9hdDMyKCk7CiAgICAgICAgICAgIHRoaXMuYSA9IHJlYWRlci5sb2FkRmxvYXQzMigpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBDU1MgcmdiYSBzdHJpbmcuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICB0b0NTU1N0cmluZygpIHsKICAgICAgICAgICAgcmV0dXJuICgncmdiYSgnICsKICAgICAgICAgICAgICAgIE1hdGgucm91bmQodGhpcy5yICogMjU1KSArCiAgICAgICAgICAgICAgICAnLCAnICsKICAgICAgICAgICAgICAgIE1hdGgucm91bmQodGhpcy5nICogMjU1KSArCiAgICAgICAgICAgICAgICAnLCAnICsKICAgICAgICAgICAgICAgIE1hdGgucm91bmQodGhpcy5iICogMjU1KSArCiAgICAgICAgICAgICAgICAnLCAnICsKICAgICAgICAgICAgICAgIHRoaXMuYSArCiAgICAgICAgICAgICAgICAnKScpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIFZlYzMgdG8gYSBzdHJpbmcgaW4gSlNPTiBmb3JtYXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICB0b1N0cmluZygpIHsKICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5ldy1jYXAKICAgICAgICAgICAgcmV0dXJuIFN0cmluZ0Z1bmN0aW9ucy5zdHJpbmdpZnlKU09OV2l0aEZpeGVkUHJlY2lzaW9uKHRoaXMudG9KU09OKCkpOwogICAgICAgIH0KICAgIH0KCiAgICB2YXIgRXVsZXJBbmdsZXNBeGlzT3JkZXI7CiAgICAoZnVuY3Rpb24gKEV1bGVyQW5nbGVzQXhpc09yZGVyKSB7CiAgICAgICAgRXVsZXJBbmdsZXNBeGlzT3JkZXJbRXVsZXJBbmdsZXNBeGlzT3JkZXJbIlhZWiJdID0gMF0gPSAiWFlaIjsKICAgICAgICBFdWxlckFuZ2xlc0F4aXNPcmRlcltFdWxlckFuZ2xlc0F4aXNPcmRlclsiWVpYIl0gPSAxXSA9ICJZWlgiOwogICAgICAgIEV1bGVyQW5nbGVzQXhpc09yZGVyW0V1bGVyQW5nbGVzQXhpc09yZGVyWyJaWFkiXSA9IDJdID0gIlpYWSI7CiAgICAgICAgRXVsZXJBbmdsZXNBeGlzT3JkZXJbRXVsZXJBbmdsZXNBeGlzT3JkZXJbIlhaWSJdID0gM10gPSAiWFpZIjsKICAgICAgICBFdWxlckFuZ2xlc0F4aXNPcmRlcltFdWxlckFuZ2xlc0F4aXNPcmRlclsiWllYIl0gPSA0XSA9ICJaWVgiOwogICAgICAgIEV1bGVyQW5nbGVzQXhpc09yZGVyW0V1bGVyQW5nbGVzQXhpc09yZGVyWyJZWFoiXSA9IDVdID0gIllYWiI7CiAgICB9KShFdWxlckFuZ2xlc0F4aXNPcmRlciB8fCAoRXVsZXJBbmdsZXNBeGlzT3JkZXIgPSB7fSkpOwogICAgLyoqCiAgICAgKiBDbGFzcyByZXByZXNlbnRpbmcgZXVsZXIgYW5nbGVzLiBFdWxlciBhbmdsZXMgZGVzY3JpYmUgcm90YXRpbmcgYW4gb2JqZWN0CiAgICAgKiBhcm91bmQgaXRzIHZhcmlvdXMgYXhpcyBpbiBhIHNwZWNpZmllZCBheGlzIG9yZGVyLgogICAgICoKICAgICAqLwogICAgY2xhc3MgRXVsZXJBbmdsZXMgewogICAgICAgIHg7CiAgICAgICAgeTsKICAgICAgICB6OwogICAgICAgIG9yZGVyOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIGV1bGVyIGFuZ2xlLiBSZWNlaXZlcyB0aGUgeHl6IHZhbHVlcyBpbiByYWRpYW5zIGFuZCB0aGUgb3JkZXIgdGhhdCB0aGUgcm90YXRpb25zIGFyZSBhcHBsaWVkLgogICAgICAgICAqCiAgICAgICAgICogT3JkZXIgcGFyYW1ldGVyIHZhbHVlczogYFhZWjogMGAsIGBZWlg6IDFgLCBgWlhZOiAyYCwgYFhaWTogM2AsIGBaWVg6IDRgLCBgWVhaOiA1YAogICAgICAgICAqCiAgICAgICAgICogSXQgY291bGQgYmUgZWl0aGVyIHRoZSBgc3RyaW5nYCBvciB0aGUgYG51bWJlcmAgdmFsdWUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0geCAtIFRoZSBhbmdsZSBvZiB0aGUgeCBheGlzIGluIHJhZGlhbnMuIERlZmF1bHQgaXMgMC4KICAgICAgICAgKiBAcGFyYW0geSAtIFRoZSBhbmdsZSBvZiB0aGUgeSBheGlzIGluIHJhZGlhbnMuIERlZmF1bHQgaXMgMC4KICAgICAgICAgKiBAcGFyYW0geiAtIFRoZSBhbmdsZSBvZiB0aGUgeiBheGlzIGluIHJhZGlhbnMuIERlZmF1bHQgaXMgMC4KICAgICAgICAgKiBAcGFyYW0gb3JkZXIgLSBUaGUgb3JkZXIgaW4gd2hpY2ggdGhlIHJvdGF0aW9ucyBhcmUgYXBwbGllZC4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3Rvcih4ID0gMCwgeSA9IDAsIHogPSAwLCBvcmRlciA9IDApIHsKICAgICAgICAgICAgdGhpcy54ID0geDsKICAgICAgICAgICAgdGhpcy55ID0geTsKICAgICAgICAgICAgdGhpcy56ID0gejsKICAgICAgICAgICAgaWYgKHR5cGVvZiBvcmRlciA9PT0gJ251bWJlcicgJiYgIWlzTmFOKG9yZGVyKSkKICAgICAgICAgICAgICAgIHRoaXMub3JkZXIgPSBvcmRlcjsKICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBzd2l0Y2ggKG9yZGVyKSB7CiAgICAgICAgICAgICAgICAgICAgY2FzZSAnWFlaJzoKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vcmRlciA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIGNhc2UgJ1laWCc6CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3JkZXIgPSAxOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICBjYXNlICdaWFknOgogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9yZGVyID0gMjsKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgY2FzZSAnWFpZJzoKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vcmRlciA9IDM7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIGNhc2UgJ1pZWCc6CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3JkZXIgPSA0OwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICBjYXNlICdZWFonOgogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9yZGVyID0gNTsKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIEV1bGVyIEFuZ2xlcyBPcmRlcjonICsgb3JkZXIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIEV1bGVyQW5nbGVzCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0geCAtIFRoZSB4IGF4aXMgcm90YXRpb24gaW4gcmFkaWFucy4KICAgICAgICAgKiBAcGFyYW0geSAtIFRoZSB5IGF4aXMgcm90YXRpb24gaW4gcmFkaWFucy4KICAgICAgICAgKiBAcGFyYW0geiAtIFRoZSB6IGF4aXMgcm90YXRpb24gaW4gcmFkaWFucy4KICAgICAgICAgKi8KICAgICAgICBzZXQoeCwgeSwgeikgewogICAgICAgICAgICB0aGlzLnggPSB4OwogICAgICAgICAgICB0aGlzLnkgPSB5OwogICAgICAgICAgICB0aGlzLnogPSB6OwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQZXJzaXN0ZW5jZQogICAgICAgIC8qKgogICAgICAgICAqIENvbnZlcnRzIHRoaXMgVmVjMyB0byBhIHN0cmluZyBpbiBKU09OIGZvcm1hdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHRvU3RyaW5nKCkgewogICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbmV3LWNhcAogICAgICAgICAgICByZXR1cm4gU3RyaW5nRnVuY3Rpb25zLnN0cmluZ2lmeUpTT05XaXRoRml4ZWRQcmVjaXNpb24odGhpcy50b0pTT04oKSk7CiAgICAgICAgfQogICAgICAgIHRvSlNPTigpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIHg6IHRoaXMueCwKICAgICAgICAgICAgICAgIHk6IHRoaXMueSwKICAgICAgICAgICAgICAgIHo6IHRoaXMueiwKICAgICAgICAgICAgICAgIG9yZGVyOiB0aGlzLm9yZGVyLAogICAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICBmcm9tSlNPTihqc29uKSB7CiAgICAgICAgICAgIHRoaXMueCA9IGpzb24ueDsKICAgICAgICAgICAgdGhpcy55ID0ganNvbi55OwogICAgICAgICAgICB0aGlzLnogPSBqc29uLno7CiAgICAgICAgICAgIHRoaXMub3JkZXIgPSBqc29uLm9yZGVyOwogICAgICAgIH0KICAgIH0KCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBuZXctY2FwICovCiAgICAvKioKICAgICAqIEEgY2xhc3MgcmVwcmVzZW50aW5nIGEgM3gzIG1hdHJpeC4KICAgICAqIFRoaXMgbWF0cml4IGNsYXNzIGlzIGJhc2VkIG9uIEdMTSwgYW5kIGlzIGNvbHVtbiBtYWpvci4KICAgICAqCiAgICAgKi8KICAgIGNsYXNzIE1hdDMgewogICAgICAgIG0wMCA9IDE7CiAgICAgICAgbTAxID0gMDsKICAgICAgICBtMDIgPSAwOwogICAgICAgIG0xMCA9IDA7CiAgICAgICAgbTExID0gMTsKICAgICAgICBtMTIgPSAwOwogICAgICAgIG0yMCA9IDA7CiAgICAgICAgbTIxID0gMDsKICAgICAgICBtMjIgPSAxOwogICAgICAgIC8qKgogICAgICAgICAqIEluaXRpYWxpemVzIHRoZSBNYXQzIGNsYXNzIHdpdGggZ2l2ZW4gZGF0YS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBtMDAgLSBSb3cgMCwgY29sdW1uIDAuCiAgICAgICAgICogQHBhcmFtIG0wMSAtIFJvdyAwLCBjb2x1bW4gMS4KICAgICAgICAgKiBAcGFyYW0gbTAyIC0gUm93IDAsIGNvbHVtbiAyLgogICAgICAgICAqIEBwYXJhbSBtMTAgLSBSb3cgMSwgY29sdW1uIDAuCiAgICAgICAgICogQHBhcmFtIG0xMSAtIFJvdyAxLCBjb2x1bW4gMS4KICAgICAgICAgKiBAcGFyYW0gbTEyIC0gUm93IDEsIGNvbHVtbiAyLgogICAgICAgICAqIEBwYXJhbSBtMjAgLSBSb3cgMiwgY29sdW1uIDAuCiAgICAgICAgICogQHBhcmFtIG0yMSAtIFJvdyAyLCBjb2x1bW4gMS4KICAgICAgICAgKiBAcGFyYW0gbTIyIC0gUm93IDIsIGNvbHVtbiAyLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKG0wMCA9IDEsIG0wMSA9IDAsIG0wMiA9IDAsIG0xMCA9IDAsIG0xMSA9IDEsIG0xMiA9IDAsIG0yMCA9IDAsIG0yMSA9IDAsIG0yMiA9IDEpIHsKICAgICAgICAgICAgaWYgKG0wMCBpbnN0YW5jZW9mIFZlYzMgJiYgbTAxIGluc3RhbmNlb2YgVmVjMyAmJiBtMDIgaW5zdGFuY2VvZiBWZWMzKSB7CiAgICAgICAgICAgICAgICB0aGlzLnNldChtMDAueCwgbTAwLnksIG0wMC56LCBtMDEueCwgbTAxLnksIG0wMS56LCBtMDIueCwgbTAyLnksIG0wMi56KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHRoaXMuc2V0KG0wMCwgbTAxLCBtMDIsIG0xMCwgbTExLCBtMTIsIG0yMCwgbTIxLCBtMjIpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHRlciBmb3IgdGhlIGB4YCBheGlzLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGB4YCBheGlzIGFzIGEgVmVjMy4KICAgICAgICAgKi8KICAgICAgICBnZXQgeEF4aXMoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyh0aGlzLm0wMCwgdGhpcy5tMDEsIHRoaXMubTAyKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0dGVyIGZvciB0aGUgYHhgIGF4aXMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gdmVjMyAtIFRoZSB2ZWMzIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldCB4QXhpcyh2ZWMzKSB7CiAgICAgICAgICAgIHRoaXMueEF4aXMuc2V0KHZlYzMueCwgdmVjMy55LCB2ZWMzLnopOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBHZXR0ZXIgZm9yIHRoZSBgeWAgYXhpcy4KICAgICAgICAgKiAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBgeWAgYXhpcyBhcyBhIFZlYzMuCiAgICAgICAgICovCiAgICAgICAgZ2V0IHlBeGlzKCkgewogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzModGhpcy5tMTAsIHRoaXMubTExLCB0aGlzLm0xMik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHRlciBmb3IgdGhlIGB5YCBheGlzLgogICAgICAgICAqIEBwYXJhbSB2ZWMzIC0gVGhlIHZlYzMgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0IHlBeGlzKHZlYzMpIHsKICAgICAgICAgICAgdGhpcy55QXhpcy5zZXQodmVjMy54LCB2ZWMzLnksIHZlYzMueik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHRlciBmb3IgdGhlIGB6YCBheGlzLgogICAgICAgICAqICogQHJldHVybiAtIFJldHVybnMgdGhlIGB6YCBheGlzIGFzIGEgVmVjMy4KICAgICAgICAgKi8KICAgICAgICBnZXQgekF4aXMoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyh0aGlzLm0yMCwgdGhpcy5tMjEsIHRoaXMubTIyKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0dGVyIGZvciB0aGUgYHpgIGF4aXMuCiAgICAgICAgICogQHBhcmFtIHZlYzMgLSBUaGUgdmVjMyB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXQgekF4aXModmVjMykgewogICAgICAgICAgICB0aGlzLnpBeGlzLnNldCh2ZWMzLngsIHZlYzMueSwgdmVjMy56KTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBTZXR0ZXJzCiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB0aGUgc3RhdGUgb2YgdGhlIE1hdDMgY2xhc3MKICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBtMDAgLSBSb3cgMCwgY29sdW1uIDAuCiAgICAgICAgICogQHBhcmFtIG0wMSAtIFJvdyAwLCBjb2x1bW4gMS4KICAgICAgICAgKiBAcGFyYW0gbTAyIC0gUm93IDAsIGNvbHVtbiAyLgogICAgICAgICAqIEBwYXJhbSBtMTAgLSBSb3cgMSwgY29sdW1uIDAuCiAgICAgICAgICogQHBhcmFtIG0xMSAtIFJvdyAxLCBjb2x1bW4gMS4KICAgICAgICAgKiBAcGFyYW0gbTEyIC0gUm93IDEsIGNvbHVtbiAyLgogICAgICAgICAqIEBwYXJhbSBtMjAgLSBSb3cgMiwgY29sdW1uIDAuCiAgICAgICAgICogQHBhcmFtIG0yMSAtIFJvdyAyLCBjb2x1bW4gMS4KICAgICAgICAgKiBAcGFyYW0gbTIyIC0gUm93IDIsIGNvbHVtbiAyLgogICAgICAgICAqLwogICAgICAgIHNldChtMDAgPSAxLCBtMDEgPSAwLCBtMDIgPSAwLCBtMTAgPSAwLCBtMTEgPSAxLCBtMTIgPSAwLCBtMjAgPSAwLCBtMjEgPSAwLCBtMjIgPSAxKSB7CiAgICAgICAgICAgIHRoaXMubTAwID0gbTAwOwogICAgICAgICAgICB0aGlzLm0wMSA9IG0wMTsKICAgICAgICAgICAgdGhpcy5tMDIgPSBtMDI7CiAgICAgICAgICAgIHRoaXMubTEwID0gbTEwOwogICAgICAgICAgICB0aGlzLm0xMSA9IG0xMTsKICAgICAgICAgICAgdGhpcy5tMTIgPSBtMTI7CiAgICAgICAgICAgIHRoaXMubTIwID0gbTIwOwogICAgICAgICAgICB0aGlzLm0yMSA9IG0yMTsKICAgICAgICAgICAgdGhpcy5tMjIgPSBtMjI7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgc3RhdGUgb2YgdGhlIE1hdDMgd2l0aCB0aGUgaWRlbnRpdHkgIE1hdHJpeAogICAgICAgICAqLwogICAgICAgIHNldElkZW50aXR5KCkgewogICAgICAgICAgICB0aGlzLnNldCgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHN0YXRlIG9mIHRoZSBNYXQzIGZyb20gYW5vdGhlciBNYXQzCiAgICAgICAgICoKICAgICAgICAgKiBOb3RlOiB3b3JrcyB3aXRoIGVpdGhlciBNYXQzIG9yIE1hdDQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbWF0IC0gVGhlIG1hdCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRGcm9tTWF0KG1hdCkgewogICAgICAgICAgICB0aGlzLm0wMCA9IG1hdC5tMDA7CiAgICAgICAgICAgIHRoaXMubTAxID0gbWF0Lm0wMTsKICAgICAgICAgICAgdGhpcy5tMDIgPSBtYXQubTAyOwogICAgICAgICAgICB0aGlzLm0xMCA9IG1hdC5tMTA7CiAgICAgICAgICAgIHRoaXMubTExID0gbWF0Lm0xMTsKICAgICAgICAgICAgdGhpcy5tMTIgPSBtYXQubTEyOwogICAgICAgICAgICB0aGlzLm0yMCA9IG1hdC5tMjA7CiAgICAgICAgICAgIHRoaXMubTIxID0gbWF0Lm0yMTsKICAgICAgICAgICAgdGhpcy5tMjIgPSBtYXQubTIyOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTY2FsZXMgYW5kIGNhbGN1bGF0ZXMgdGhlIGNyb3NzIHByb2R1Y3Qgb2YgdGhlIGBWZWMzYCBhbmQgc2V0cyB0aGUgcmVzdWx0IGluIHRoZSBNYXQzCiAgICAgICAgICogTm90ZTogdGhlIHJlc3VsdGluZyBtYXRyaXggK1ogYXhpcyBpcyBhbGlnbmVkIHdpdGggdGhlIHByb3ZpZGVkIGRpcmVjdGlvbiB2YWx1ZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBkaXIgLSBUaGUgZGlyIHZhbHVlLgogICAgICAgICAqIEBwYXJhbSB1cCAtIFRoZSB1cCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRGcm9tRGlyZWN0aW9uQW5kVXB2ZWN0b3IoZGlyLCB1cCkgewogICAgICAgICAgICBjb25zdCB6QXhpcyA9IGRpcjsKICAgICAgICAgICAgY29uc3QgekxlbiA9IHpBeGlzLmxlbmd0aCgpOwogICAgICAgICAgICBpZiAoekxlbiA8IE51bWJlci5FUFNJTE9OKSB7CiAgICAgICAgICAgICAgICB0aGlzLnNldElkZW50aXR5KCk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgekF4aXMuc2NhbGVJblBsYWNlKDEgLyB6TGVuKTsKICAgICAgICAgICAgY29uc3QgeEF4aXMgPSB1cC5jcm9zcyh6QXhpcyk7CiAgICAgICAgICAgIGNvbnN0IHhMZW4gPSB4QXhpcy5sZW5ndGgoKTsKICAgICAgICAgICAgaWYgKHhMZW4gPiBOdW1iZXIuRVBTSUxPTikKICAgICAgICAgICAgICAgIHhBeGlzLnNjYWxlSW5QbGFjZSgxIC8geExlbik7CiAgICAgICAgICAgIGNvbnN0IHlBeGlzID0gekF4aXMuY3Jvc3MoeEF4aXMpOwogICAgICAgICAgICBjb25zdCB5TGVuID0geUF4aXMubGVuZ3RoKCk7CiAgICAgICAgICAgIGlmICh5TGVuID4gTnVtYmVyLkVQU0lMT04pCiAgICAgICAgICAgICAgICB5QXhpcy5zY2FsZUluUGxhY2UoMSAvIHlMZW4pOwogICAgICAgICAgICB0aGlzLnNldCh4QXhpcy54LCB4QXhpcy55LCB4QXhpcy56LCB5QXhpcy54LCB5QXhpcy55LCB5QXhpcy56LCB6QXhpcy54LCB6QXhpcy55LCB6QXhpcy56KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogSW52ZXJ0cyBhIE1hdDMgYW5kIHJldHVybnMgdGhlIHJlc3VsdCBhcyBhIG5ldyBpbnN0YW5jZS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IE1hdDMuCiAgICAgICAgICovCiAgICAgICAgaW52ZXJzZSgpIHsKICAgICAgICAgICAgY29uc3QgYTAwID0gdGhpcy5tMDA7CiAgICAgICAgICAgIGNvbnN0IGEwMSA9IHRoaXMubTAxOwogICAgICAgICAgICBjb25zdCBhMDIgPSB0aGlzLm0wMjsKICAgICAgICAgICAgY29uc3QgYTEwID0gdGhpcy5tMTA7CiAgICAgICAgICAgIGNvbnN0IGExMSA9IHRoaXMubTExOwogICAgICAgICAgICBjb25zdCBhMTIgPSB0aGlzLm0xMjsKICAgICAgICAgICAgY29uc3QgYTIwID0gdGhpcy5tMjA7CiAgICAgICAgICAgIGNvbnN0IGEyMSA9IHRoaXMubTIxOwogICAgICAgICAgICBjb25zdCBhMjIgPSB0aGlzLm0yMjsKICAgICAgICAgICAgY29uc3QgYjAxID0gYTIyICogYTExIC0gYTEyICogYTIxOwogICAgICAgICAgICBjb25zdCBiMTEgPSAtYTIyICogYTEwICsgYTEyICogYTIwOwogICAgICAgICAgICBjb25zdCBiMjEgPSBhMjEgKiBhMTAgLSBhMTEgKiBhMjA7CiAgICAgICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnQKICAgICAgICAgICAgbGV0IGRldCA9IGEwMCAqIGIwMSArIGEwMSAqIGIxMSArIGEwMiAqIGIyMTsKICAgICAgICAgICAgaWYgKCFkZXQpIHsKICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignVW5hYmxlIHRvIGludmVydCBNYXQzJyk7CiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IE1hdDMoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBkZXQgPSAxLjAgLyBkZXQ7CiAgICAgICAgICAgIHJldHVybiBuZXcgTWF0MyhiMDEgKiBkZXQsICgtYTIyICogYTAxICsgYTAyICogYTIxKSAqIGRldCwgKGExMiAqIGEwMSAtIGEwMiAqIGExMSkgKiBkZXQsIGIxMSAqIGRldCwgKGEyMiAqIGEwMCAtIGEwMiAqIGEyMCkgKiBkZXQsICgtYTEyICogYTAwICsgYTAyICogYTEwKSAqIGRldCwgYjIxICogZGV0LCAoLWEyMSAqIGEwMCArIGEwMSAqIGEyMCkgKiBkZXQsIChhMTEgKiBhMDAgLSBhMDEgKiBhMTApICogZGV0KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogSW52ZXJ0cyBhIE1hdDMgaW4gcGxhY2UgbW9kaWZ5aW5nIGl0cyB2YWx1ZXMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBpbnZlcnRJblBsYWNlKCkgewogICAgICAgICAgICBjb25zdCBhMDAgPSB0aGlzLm0wMDsKICAgICAgICAgICAgY29uc3QgYTAxID0gdGhpcy5tMDE7CiAgICAgICAgICAgIGNvbnN0IGEwMiA9IHRoaXMubTAyOwogICAgICAgICAgICBjb25zdCBhMTAgPSB0aGlzLm0xMDsKICAgICAgICAgICAgY29uc3QgYTExID0gdGhpcy5tMTE7CiAgICAgICAgICAgIGNvbnN0IGExMiA9IHRoaXMubTEyOwogICAgICAgICAgICBjb25zdCBhMjAgPSB0aGlzLm0yMDsKICAgICAgICAgICAgY29uc3QgYTIxID0gdGhpcy5tMjE7CiAgICAgICAgICAgIGNvbnN0IGEyMiA9IHRoaXMubTIyOwogICAgICAgICAgICBjb25zdCBiMDEgPSBhMjIgKiBhMTEgLSBhMTIgKiBhMjE7CiAgICAgICAgICAgIGNvbnN0IGIxMSA9IC1hMjIgKiBhMTAgKyBhMTIgKiBhMjA7CiAgICAgICAgICAgIGNvbnN0IGIyMSA9IGEyMSAqIGExMCAtIGExMSAqIGEyMDsKICAgICAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBkZXRlcm1pbmFudAogICAgICAgICAgICBsZXQgZGV0ID0gYTAwICogYjAxICsgYTAxICogYjExICsgYTAyICogYjIxOwogICAgICAgICAgICBpZiAoIWRldCkgewogICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdVbmFibGUgdG8gaW52ZXJ0IE1hdDMnKTsKICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBkZXQgPSAxLjAgLyBkZXQ7CiAgICAgICAgICAgIHRoaXMuc2V0KGIwMSAqIGRldCwgKC1hMjIgKiBhMDEgKyBhMDIgKiBhMjEpICogZGV0LCAoYTEyICogYTAxIC0gYTAyICogYTExKSAqIGRldCwgYjExICogZGV0LCAoYTIyICogYTAwIC0gYTAyICogYTIwKSAqIGRldCwgKC1hMTIgKiBhMDAgKyBhMDIgKiBhMTApICogZGV0LCBiMjEgKiBkZXQsICgtYTIxICogYTAwICsgYTAxICogYTIwKSAqIGRldCwgKGExMSAqIGEwMCAtIGEwMSAqIGExMCkgKiBkZXQpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVHJhbnNwb3NlcyAoZXhjaGFuZ2VzIGNvbHVtbnMgd2l0aCByb3dzKSB0aGlzIG1hdHJpeAogICAgICAgICAqIGFuZCByZXR1cm5zIHRoZSByZXN1bHQgYXMgYSBuZXcgaW5zdGFuY2UuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJuIGEgbmV3IHRyYW5zcG9zZWQgTWF0My4KICAgICAgICAgKi8KICAgICAgICB0cmFuc3Bvc2UoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgTWF0Myh0aGlzLm0wMCwgdGhpcy5tMTAsIHRoaXMubTIwLCB0aGlzLm0wMSwgdGhpcy5tMTEsIHRoaXMubTIxLCB0aGlzLm0wMiwgdGhpcy5tMTIsIHRoaXMubTIyKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVHJhbnNwb3NlcyAoZXhjaGFuZ2VzIGNvbHVtbnMgd2l0aCByb3dzKSB0aGlzIG1hdHJpeCBtb2RpZnlpbmcgaXRzIHZhbHVlcy4KICAgICAgICAgKi8KICAgICAgICB0cmFuc3Bvc2VJblBsYWNlKCkgewogICAgICAgICAgICAvLyBJZiB3ZSBhcmUgdHJhbnNwb3Npbmcgb3Vyc2VsdmVzIHdlIGNhbiBza2lwIGEgZmV3IHN0ZXBzIGJ1dCBoYXZlIHRvIGNhY2hlIHNvbWUgdmFsdWVzCiAgICAgICAgICAgIGNvbnN0IGEwMSA9IHRoaXMubTAxOwogICAgICAgICAgICBjb25zdCBhMDIgPSB0aGlzLm0wMjsKICAgICAgICAgICAgY29uc3QgYTEyID0gdGhpcy5tMTI7CiAgICAgICAgICAgIHRoaXMubTAxID0gdGhpcy5tMTA7CiAgICAgICAgICAgIHRoaXMubTAyID0gdGhpcy5tMjA7CiAgICAgICAgICAgIHRoaXMubTEwID0gYTAxOwogICAgICAgICAgICB0aGlzLm0xMiA9IHRoaXMubTIxOwogICAgICAgICAgICB0aGlzLm0yMCA9IGEwMjsKICAgICAgICAgICAgdGhpcy5tMjEgPSBhMTI7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRyYW5zZm9ybXMgdGhlIFZlYzMgd2l0aCBhIE1hdDMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gdmVjMyAtIFRoZSB2ZWMzIHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm4gdGhlIHJlc3VsdCBhcyBhIG5ldyBWZWMzLgogICAgICAgICAqLwogICAgICAgIHRyYW5zZm9ybVZlYzModmVjMykgewogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzModGhpcy5tMDAgKiB2ZWMzLnggKyB0aGlzLm0wMSAqIHZlYzMueSArIHRoaXMubTAyICogdmVjMy56LCB0aGlzLm0xMCAqIHZlYzMueCArIHRoaXMubTExICogdmVjMy55ICsgdGhpcy5tMTIgKiB2ZWMzLnosIHRoaXMubTIwICogdmVjMy54ICsgdGhpcy5tMjEgKiB2ZWMzLnkgKyB0aGlzLm0yMiAqIHZlYzMueik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENsb25lcyB0aGlzIE1hdDMgcmV0dXJuaW5nIGEgbmV3IGluc3RhbmNlLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgTWF0My4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBNYXQzKHRoaXMubTAwLCB0aGlzLm0wMSwgdGhpcy5tMDIsIHRoaXMubTEwLCB0aGlzLm0xMSwgdGhpcy5tMTIsIHRoaXMubTIwLCB0aGlzLm0yMSwgdGhpcy5tMjIpOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQZXJzaXN0ZW5jZQogICAgICAgIC8qKgogICAgICAgICAqIExvYWRzIHRoZSBzdGF0ZSBvZiB0aGUgdmFsdWUgZnJvbSBhIGJpbmFyeSByZWFkZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICByZWFkQmluYXJ5KHJlYWRlcikgewogICAgICAgICAgICBjb25zdCBkYXRhID0gcmVhZGVyLmxvYWRGbG9hdDMyQXJyYXkoOSk7CiAgICAgICAgICAgIHRoaXMuZnJvbUFycmF5KGRhdGEpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdG9KU09OIG1ldGhvZCBlbmNvZGVzIHRoaXMgdHlwZSBhcyBhIGpzb24gb2JqZWN0IGZvciBwZXJzaXN0ZW5jZS4KICAgICAgICAgKi8KICAgICAgICB0b0pTT04oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmFzQXJyYXkoKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGZyb21KU09OIG1ldGhvZCBkZWNvZGVzIGEganNvbiBvYmplY3QgZm9yIHRoaXMgdHlwZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBqc29uIC0gVGhlIGpzb24gcGFyYW0uCiAgICAgICAgICovCiAgICAgICAgZnJvbUpTT04oanNvbikgewogICAgICAgICAgICB0aGlzLmZyb21BcnJheShqc29uKTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gRGVidWdnaW5nCiAgICAgICAgLyoqCiAgICAgICAgICogQ29udmVydHMgdGhpcyBWZWMzIHRvIGEgc3RyaW5nIGluIEpTT04gZm9ybWF0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgdG9TdHJpbmcoKSB7CiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuZXctY2FwCiAgICAgICAgICAgIHJldHVybiBTdHJpbmdGdW5jdGlvbnMuc3RyaW5naWZ5SlNPTldpdGhGaXhlZFByZWNpc2lvbih0aGlzLnRvSlNPTigpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBjdXJyZW50IE1hdGggdHlwZSBkYXRhIGFzIGFycmF5LiBPZnRlbiB1c2VkIHRvIHBhc3MgdHlwZXMgdG8gdGhlIEdQVS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSByZXN1bHQgYXMgYW4gYXJyYXkuCiAgICAgICAgICovCiAgICAgICAgYXNBcnJheSgpIHsKICAgICAgICAgICAgcmV0dXJuIFt0aGlzLm0wMCwgdGhpcy5tMDEsIHRoaXMubTAyLCB0aGlzLm0xMCwgdGhpcy5tMTEsIHRoaXMubTEyLCB0aGlzLm0yMCwgdGhpcy5tMjEsIHRoaXMubTIyXTsKICAgICAgICB9CiAgICAgICAgZnJvbUFycmF5KGFycmF5KSB7CiAgICAgICAgICAgIHRoaXMubTAwID0gYXJyYXlbMF07CiAgICAgICAgICAgIHRoaXMubTAxID0gYXJyYXlbMV07CiAgICAgICAgICAgIHRoaXMubTAyID0gYXJyYXlbMl07CiAgICAgICAgICAgIHRoaXMubTEwID0gYXJyYXlbM107CiAgICAgICAgICAgIHRoaXMubTExID0gYXJyYXlbNF07CiAgICAgICAgICAgIHRoaXMubTEyID0gYXJyYXlbNV07CiAgICAgICAgICAgIHRoaXMubTIwID0gYXJyYXlbNl07CiAgICAgICAgICAgIHRoaXMubTIxID0gYXJyYXlbN107CiAgICAgICAgICAgIHRoaXMubTIyID0gYXJyYXlbOF07CiAgICAgICAgfQogICAgfQoKICAgIC8qKgogICAgICogQSBjbGFzcyByZXByZXNlbnRpbmcgYSA0eDQgbWF0cml4LgogICAgICogVGhpcyBtYXRyaXggY2xhc3MgaXMgYmFzZWQgb24gR0xNLCBhbmQgaXMgY29sdW1uIG1ham9yLgogICAgICoKICAgICAqLwogICAgY2xhc3MgTWF0NCB7CiAgICAgICAgbTAwOwogICAgICAgIG0wMTsKICAgICAgICBtMDI7CiAgICAgICAgbTAzOwogICAgICAgIG0xMDsKICAgICAgICBtMTE7CiAgICAgICAgbTEyOwogICAgICAgIG0xMzsKICAgICAgICBtMjA7CiAgICAgICAgbTIxOwogICAgICAgIG0yMjsKICAgICAgICBtMjM7CiAgICAgICAgbTMwOwogICAgICAgIG0zMTsKICAgICAgICBtMzI7CiAgICAgICAgbTMzOwogICAgICAgIGNvbnN0cnVjdG9yKG0wMCA9IDEsIG0wMSA9IDAsIG0wMiA9IDAsIG0wMyA9IDAsIG0xMCA9IDAsIG0xMSA9IDEsIG0xMiA9IDAsIG0xMyA9IDAsIG0yMCA9IDAsIG0yMSA9IDAsIG0yMiA9IDEsIG0yMyA9IDAsIG0zMCA9IDAsIG0zMSA9IDAsIG0zMiA9IDAsIG0zMyA9IDEpIHsKICAgICAgICAgICAgdGhpcy5tMDAgPSBtMDA7CiAgICAgICAgICAgIHRoaXMubTAxID0gbTAxOwogICAgICAgICAgICB0aGlzLm0wMiA9IG0wMjsKICAgICAgICAgICAgdGhpcy5tMDMgPSBtMDM7CiAgICAgICAgICAgIHRoaXMubTEwID0gbTEwOwogICAgICAgICAgICB0aGlzLm0xMSA9IG0xMTsKICAgICAgICAgICAgdGhpcy5tMTIgPSBtMTI7CiAgICAgICAgICAgIHRoaXMubTEzID0gbTEzOwogICAgICAgICAgICB0aGlzLm0yMCA9IG0yMDsKICAgICAgICAgICAgdGhpcy5tMjEgPSBtMjE7CiAgICAgICAgICAgIHRoaXMubTIyID0gbTIyOwogICAgICAgICAgICB0aGlzLm0yMyA9IG0yMzsKICAgICAgICAgICAgdGhpcy5tMzAgPSBtMzA7CiAgICAgICAgICAgIHRoaXMubTMxID0gbTMxOwogICAgICAgICAgICB0aGlzLm0zMiA9IG0zMjsKICAgICAgICAgICAgdGhpcy5tMzMgPSBtMzM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHRlciBmb3IgdGhlIGB4YCBheGlzLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGB4YCBheGlzIGFzIGEgVmVjMy4KICAgICAgICAgKi8KICAgICAgICBnZXQgeEF4aXMoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyh0aGlzLm0wMCwgdGhpcy5tMDEsIHRoaXMubTAyKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0dGVyIGZvciB0aGUgYHhgIGF4aXMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gdmVjMyAtIFRoZSB2ZWMzIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldCB4QXhpcyh2ZWMzKSB7CiAgICAgICAgICAgIHRoaXMueEF4aXMuc2V0KHZlYzMueCwgdmVjMy55LCB2ZWMzLnopOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBHZXR0ZXIgZm9yIHRoZSBgeWAgYXhpcy4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBgeWAgYXhpcyBhcyBhIFZlYzMuCiAgICAgICAgICovCiAgICAgICAgZ2V0IHlBeGlzKCkgewogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzModGhpcy5tMTAsIHRoaXMubTExLCB0aGlzLm0xMik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHRlciBmb3IgdGhlIGB5YCBheGlzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHZlYzMgLSBUaGUgdmVjMyB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXQgeUF4aXModmVjMykgewogICAgICAgICAgICB0aGlzLnlBeGlzLnNldCh2ZWMzLngsIHZlYzMueSwgdmVjMy56KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0dGVyIGZvciB0aGUgYHpgIGF4aXMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgYHpgIGF4aXMgYXMgYSBWZWMzLgogICAgICAgICAqLwogICAgICAgIGdldCB6QXhpcygpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMzKHRoaXMubTIwLCB0aGlzLm0yMSwgdGhpcy5tMjIpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXR0ZXIgZm9yIHRoZSBgemAgYXhpcy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSB2ZWMzIC0gVGhlIHZlYzMgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0IHpBeGlzKHZlYzMpIHsKICAgICAgICAgICAgdGhpcy56QXhpcy5zZXQodmVjMy54LCB2ZWMzLnksIHZlYzMueik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHRlciBmb3IgdGhlIHRyYW5zbGF0aW9uIG9mIHRoZSBtYXRyaXguIEFzc3VtZXMgdGhlIHRyYW5zbGF0aW9uIHZhbHVlcyBhcmUgMTIsIDEzLCAmIDE0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIHRyYW5zbGF0aW9uLgogICAgICAgICAqLwogICAgICAgIGdldCB0cmFuc2xhdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMzKHRoaXMubTMwLCB0aGlzLm0zMSwgdGhpcy5tMzIpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXR0ZXIgZm9yIHRoZSB0cmFuc2xhdGlvbiBvZiB0aGUgbWF0cml4LiBBc3N1bWVzIHRoZSB0cmFuc2xhdGlvbiB2YWx1ZXMgYXJlIDEyLCAxMywgJiAxNC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSB2ZWMzIC0gVGhlIHRyYW5zbGF0aW9uLgogICAgICAgICAqLwogICAgICAgIHNldCB0cmFuc2xhdGlvbih2ZWMzKSB7CiAgICAgICAgICAgIHRoaXMubTMwID0gdmVjMy54OwogICAgICAgICAgICB0aGlzLm0zMSA9IHZlYzMueTsKICAgICAgICAgICAgdGhpcy5tMzIgPSB2ZWMzLno7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gU2V0dGVycwogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIHN0YXRlIG9mIHRoZSBNYXQ0IGNsYXNzCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbTAwIC0gUm93IDAsIGNvbHVtbiAwLgogICAgICAgICAqIEBwYXJhbSBtMDEgLSBSb3cgMCwgY29sdW1uIDEuCiAgICAgICAgICogQHBhcmFtIG0wMiAtIFJvdyAwLCBjb2x1bW4gMi4KICAgICAgICAgKiBAcGFyYW0gbTAzIC0gUm93IDAsIGNvbHVtbiAzLgogICAgICAgICAqIEBwYXJhbSBtMTAgLSBSb3cgMSwgY29sdW1uIDAuCiAgICAgICAgICogQHBhcmFtIG0xMSAtIFJvdyAxLCBjb2x1bW4gMS4KICAgICAgICAgKiBAcGFyYW0gbTEyIC0gUm93IDEsIGNvbHVtbiAyLgogICAgICAgICAqIEBwYXJhbSBtMTMgLSBSb3cgMSwgY29sdW1uIDMuCiAgICAgICAgICogQHBhcmFtIG0yMCAtIFJvdyAyLCBjb2x1bW4gMC4KICAgICAgICAgKiBAcGFyYW0gbTIxIC0gUm93IDIsIGNvbHVtbiAxLgogICAgICAgICAqIEBwYXJhbSBtMjIgLSBSb3cgMiwgY29sdW1uIDIuCiAgICAgICAgICogQHBhcmFtIG0yMyAtIFJvdyAyLCBjb2x1bW4gMy4KICAgICAgICAgKiBAcGFyYW0gbTMwIC0gUm93IDMsIGNvbHVtbiAwLgogICAgICAgICAqIEBwYXJhbSBtMzEgLSBSb3cgMywgY29sdW1uIDEuCiAgICAgICAgICogQHBhcmFtIG0zMiAtIFJvdyAzLCBjb2x1bW4gMi4KICAgICAgICAgKiBAcGFyYW0gbTMzIC0gUm93IDMsIGNvbHVtbiAzLgogICAgICAgICAqLwogICAgICAgIHNldChtMDAgPSAxLCBtMDEgPSAwLCBtMDIgPSAwLCBtMDMgPSAwLCBtMTAgPSAwLCBtMTEgPSAxLCBtMTIgPSAwLCBtMTMgPSAwLCBtMjAgPSAwLCBtMjEgPSAwLCBtMjIgPSAxLCBtMjMgPSAwLCBtMzAgPSAwLCBtMzEgPSAwLCBtMzIgPSAwLCBtMzMgPSAxKSB7CiAgICAgICAgICAgIHRoaXMubTAwID0gbTAwOwogICAgICAgICAgICB0aGlzLm0wMSA9IG0wMTsKICAgICAgICAgICAgdGhpcy5tMDIgPSBtMDI7CiAgICAgICAgICAgIHRoaXMubTAzID0gbTAzOwogICAgICAgICAgICB0aGlzLm0xMCA9IG0xMDsKICAgICAgICAgICAgdGhpcy5tMTEgPSBtMTE7CiAgICAgICAgICAgIHRoaXMubTEyID0gbTEyOwogICAgICAgICAgICB0aGlzLm0xMyA9IG0xMzsKICAgICAgICAgICAgdGhpcy5tMjAgPSBtMjA7CiAgICAgICAgICAgIHRoaXMubTIxID0gbTIxOwogICAgICAgICAgICB0aGlzLm0yMiA9IG0yMjsKICAgICAgICAgICAgdGhpcy5tMjMgPSBtMjM7CiAgICAgICAgICAgIHRoaXMubTMwID0gbTMwOwogICAgICAgICAgICB0aGlzLm0zMSA9IG0zMTsKICAgICAgICAgICAgdGhpcy5tMzIgPSBtMzI7CiAgICAgICAgICAgIHRoaXMubTMzID0gbTMzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHN0YXRlIG9mIHRoZSBNYXQ0IHdpdGggdGhlIGlkZW50aXR5ICBNYXRyaXgKICAgICAgICAgKi8KICAgICAgICBzZXRJZGVudGl0eSgpIHsKICAgICAgICAgICAgdGhpcy5zZXQoKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyBzdGF0ZSBvZiB0aGUgTWF0NCBmcm9tIGFub3RoZXIgTWF0NAogICAgICAgICAqCiAgICAgICAgICogTm90ZTogd29ya3Mgd2l0aCBlaXRoZXIgTWF0MyBvciBNYXQ0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG1hdDQgLSBUaGUgbWF0NCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRGcm9tTWF0NChtYXQ0KSB7CiAgICAgICAgICAgIHRoaXMubTAwID0gbWF0NC5tMDA7CiAgICAgICAgICAgIHRoaXMubTAxID0gbWF0NC5tMDE7CiAgICAgICAgICAgIHRoaXMubTAyID0gbWF0NC5tMDI7CiAgICAgICAgICAgIHRoaXMubTAzID0gbWF0NC5tMDM7CiAgICAgICAgICAgIHRoaXMubTEwID0gbWF0NC5tMTA7CiAgICAgICAgICAgIHRoaXMubTExID0gbWF0NC5tMTE7CiAgICAgICAgICAgIHRoaXMubTEyID0gbWF0NC5tMTI7CiAgICAgICAgICAgIHRoaXMubTEzID0gbWF0NC5tMTM7CiAgICAgICAgICAgIHRoaXMubTIwID0gbWF0NC5tMjA7CiAgICAgICAgICAgIHRoaXMubTIxID0gbWF0NC5tMjE7CiAgICAgICAgICAgIHRoaXMubTIyID0gbWF0NC5tMjI7CiAgICAgICAgICAgIHRoaXMubTIzID0gbWF0NC5tMjM7CiAgICAgICAgICAgIHRoaXMubTMwID0gbWF0NC5tMzA7CiAgICAgICAgICAgIHRoaXMubTMxID0gbWF0NC5tMzE7CiAgICAgICAgICAgIHRoaXMubTMyID0gbWF0NC5tMzI7CiAgICAgICAgICAgIHRoaXMubTMzID0gbWF0NC5tMzM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENvbnZlcnRzIGEgTWF0NCB0byBhIE1hdDMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBNYXQzLgogICAgICAgICAqLwogICAgICAgIHRvTWF0MygpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBNYXQzKHRoaXMubTAwLCB0aGlzLm0wMSwgdGhpcy5tMDIsIHRoaXMubTEwLCB0aGlzLm0xMSwgdGhpcy5tMTIsIHRoaXMubTIwLCB0aGlzLm0yMSwgdGhpcy5tMjIpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUcmFuc3Bvc2VzIChleGNoYW5nZXMgY29sdW1ucyB3aXRoIHJvd3MpIHRoaXMgbWF0cml4LgogICAgICAgICAqLwogICAgICAgIHRyYW5zcG9zZUluUGxhY2UoKSB7CiAgICAgICAgICAgIC8vIElmIHdlIGFyZSB0cmFuc3Bvc2luZyBvdXJzZWx2ZXMgd2UgY2FuIHNraXAgYSBmZXcgc3RlcHMgYnV0IGhhdmUgdG8gY2FjaGUgc29tZSB2YWx1ZXMKICAgICAgICAgICAgY29uc3QgYTAxID0gdGhpcy5tMDE7CiAgICAgICAgICAgIGNvbnN0IGEwMiA9IHRoaXMubTAyOwogICAgICAgICAgICBjb25zdCBhMDMgPSB0aGlzLm0wMzsKICAgICAgICAgICAgY29uc3QgYTEyID0gdGhpcy5tMTI7CiAgICAgICAgICAgIGNvbnN0IGExMyA9IHRoaXMubTEzOwogICAgICAgICAgICBjb25zdCBhMjMgPSB0aGlzLm0yMzsKICAgICAgICAgICAgdGhpcy5tMDEgPSB0aGlzLm0xMDsKICAgICAgICAgICAgdGhpcy5tMDIgPSB0aGlzLm0yMDsKICAgICAgICAgICAgdGhpcy5tMDMgPSB0aGlzLm0zMDsKICAgICAgICAgICAgdGhpcy5tMTAgPSBhMDE7CiAgICAgICAgICAgIHRoaXMubTEyID0gdGhpcy5tMjE7CiAgICAgICAgICAgIHRoaXMubTEzID0gdGhpcy5tMzE7CiAgICAgICAgICAgIHRoaXMubTIwID0gYTAyOwogICAgICAgICAgICB0aGlzLm0yMSA9IGExMjsKICAgICAgICAgICAgdGhpcy5tMjMgPSB0aGlzLm0zMjsKICAgICAgICAgICAgdGhpcy5tMzAgPSBhMDM7CiAgICAgICAgICAgIHRoaXMubTMxID0gYTEzOwogICAgICAgICAgICB0aGlzLm0zMiA9IGEyMzsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVHJhbnNwb3NlcyAoZXhjaGFuZ2VzIGNvbHVtbnMgd2l0aCByb3dzKSB0aGlzIG1hdHJpeAogICAgICAgICAqIGFuZCByZXR1cm5zIHRoZSByZXN1bHQgYXMgYSBuZXcgaW5zdGFuY2UuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJuIGEgbmV3IHRyYW5zcG9zZWQgTWF0NC4KICAgICAgICAgKi8KICAgICAgICB0cmFuc3Bvc2UoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgTWF0NCh0aGlzLm0wMCwgdGhpcy5tMTAsIHRoaXMubTIwLCB0aGlzLm0zMCwgdGhpcy5tMDEsIHRoaXMubTExLCB0aGlzLm0yMSwgdGhpcy5tMzEsIHRoaXMubTAyLCB0aGlzLm0xMiwgdGhpcy5tMjIsIHRoaXMubTMyLCB0aGlzLm0wMywgdGhpcy5tMTMsIHRoaXMubTIzLCB0aGlzLm0zMyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEludmVydHMgYSBNYXQ0IGFuZCByZXR1cm5zIHRoZSByZXN1bHQgYXMgYSBuZXcgaW5zdGFuY2UuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBNYXQ0LgogICAgICAgICAqLwogICAgICAgIGludmVyc2UoKSB7CiAgICAgICAgICAgIGNvbnN0IGEwMCA9IHRoaXMubTAwOwogICAgICAgICAgICBjb25zdCBhMDEgPSB0aGlzLm0wMTsKICAgICAgICAgICAgY29uc3QgYTAyID0gdGhpcy5tMDI7CiAgICAgICAgICAgIGNvbnN0IGEwMyA9IHRoaXMubTAzOwogICAgICAgICAgICBjb25zdCBhMTAgPSB0aGlzLm0xMDsKICAgICAgICAgICAgY29uc3QgYTExID0gdGhpcy5tMTE7CiAgICAgICAgICAgIGNvbnN0IGExMiA9IHRoaXMubTEyOwogICAgICAgICAgICBjb25zdCBhMTMgPSB0aGlzLm0xMzsKICAgICAgICAgICAgY29uc3QgYTIwID0gdGhpcy5tMjA7CiAgICAgICAgICAgIGNvbnN0IGEyMSA9IHRoaXMubTIxOwogICAgICAgICAgICBjb25zdCBhMjIgPSB0aGlzLm0yMjsKICAgICAgICAgICAgY29uc3QgYTIzID0gdGhpcy5tMjM7CiAgICAgICAgICAgIGNvbnN0IGEzMCA9IHRoaXMubTMwOwogICAgICAgICAgICBjb25zdCBhMzEgPSB0aGlzLm0zMTsKICAgICAgICAgICAgY29uc3QgYTMyID0gdGhpcy5tMzI7CiAgICAgICAgICAgIGNvbnN0IGEzMyA9IHRoaXMubTMzOwogICAgICAgICAgICBjb25zdCBiMDAgPSBhMDAgKiBhMTEgLSBhMDEgKiBhMTA7CiAgICAgICAgICAgIGNvbnN0IGIwMSA9IGEwMCAqIGExMiAtIGEwMiAqIGExMDsKICAgICAgICAgICAgY29uc3QgYjAyID0gYTAwICogYTEzIC0gYTAzICogYTEwOwogICAgICAgICAgICBjb25zdCBiMDMgPSBhMDEgKiBhMTIgLSBhMDIgKiBhMTE7CiAgICAgICAgICAgIGNvbnN0IGIwNCA9IGEwMSAqIGExMyAtIGEwMyAqIGExMTsKICAgICAgICAgICAgY29uc3QgYjA1ID0gYTAyICogYTEzIC0gYTAzICogYTEyOwogICAgICAgICAgICBjb25zdCBiMDYgPSBhMjAgKiBhMzEgLSBhMjEgKiBhMzA7CiAgICAgICAgICAgIGNvbnN0IGIwNyA9IGEyMCAqIGEzMiAtIGEyMiAqIGEzMDsKICAgICAgICAgICAgY29uc3QgYjA4ID0gYTIwICogYTMzIC0gYTIzICogYTMwOwogICAgICAgICAgICBjb25zdCBiMDkgPSBhMjEgKiBhMzIgLSBhMjIgKiBhMzE7CiAgICAgICAgICAgIGNvbnN0IGIxMCA9IGEyMSAqIGEzMyAtIGEyMyAqIGEzMTsKICAgICAgICAgICAgY29uc3QgYjExID0gYTIyICogYTMzIC0gYTIzICogYTMyOwogICAgICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50CiAgICAgICAgICAgIGxldCBkZXQgPSBiMDAgKiBiMTEgLSBiMDEgKiBiMTAgKyBiMDIgKiBiMDkgKyBiMDMgKiBiMDggLSBiMDQgKiBiMDcgKyBiMDUgKiBiMDY7CiAgICAgICAgICAgIGlmICghZGV0KSB7CiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1VuYWJsZSB0byBpbnZlcnQgTWF0NCcpOwogICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZGV0ID0gMS4wIC8gZGV0OwogICAgICAgICAgICByZXR1cm4gbmV3IE1hdDQoKGExMSAqIGIxMSAtIGExMiAqIGIxMCArIGExMyAqIGIwOSkgKiBkZXQsIChhMDIgKiBiMTAgLSBhMDEgKiBiMTEgLSBhMDMgKiBiMDkpICogZGV0LCAoYTMxICogYjA1IC0gYTMyICogYjA0ICsgYTMzICogYjAzKSAqIGRldCwgKGEyMiAqIGIwNCAtIGEyMSAqIGIwNSAtIGEyMyAqIGIwMykgKiBkZXQsIChhMTIgKiBiMDggLSBhMTAgKiBiMTEgLSBhMTMgKiBiMDcpICogZGV0LCAoYTAwICogYjExIC0gYTAyICogYjA4ICsgYTAzICogYjA3KSAqIGRldCwgKGEzMiAqIGIwMiAtIGEzMCAqIGIwNSAtIGEzMyAqIGIwMSkgKiBkZXQsIChhMjAgKiBiMDUgLSBhMjIgKiBiMDIgKyBhMjMgKiBiMDEpICogZGV0LCAoYTEwICogYjEwIC0gYTExICogYjA4ICsgYTEzICogYjA2KSAqIGRldCwgKGEwMSAqIGIwOCAtIGEwMCAqIGIxMCAtIGEwMyAqIGIwNikgKiBkZXQsIChhMzAgKiBiMDQgLSBhMzEgKiBiMDIgKyBhMzMgKiBiMDApICogZGV0LCAoYTIxICogYjAyIC0gYTIwICogYjA0IC0gYTIzICogYjAwKSAqIGRldCwgKGExMSAqIGIwNyAtIGExMCAqIGIwOSAtIGExMiAqIGIwNikgKiBkZXQsIChhMDAgKiBiMDkgLSBhMDEgKiBiMDcgKyBhMDIgKiBiMDYpICogZGV0LCAoYTMxICogYjAxIC0gYTMwICogYjAzIC0gYTMyICogYjAwKSAqIGRldCwgKGEyMCAqIGIwMyAtIGEyMSAqIGIwMSArIGEyMiAqIGIwMCkgKiBkZXQpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBJbnZlcnRzIGEgTWF0NC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGludmVydEluUGxhY2UoKSB7CiAgICAgICAgICAgIGNvbnN0IGEwMCA9IHRoaXMubTAwOwogICAgICAgICAgICBjb25zdCBhMDEgPSB0aGlzLm0wMTsKICAgICAgICAgICAgY29uc3QgYTAyID0gdGhpcy5tMDI7CiAgICAgICAgICAgIGNvbnN0IGEwMyA9IHRoaXMubTAzOwogICAgICAgICAgICBjb25zdCBhMTAgPSB0aGlzLm0xMDsKICAgICAgICAgICAgY29uc3QgYTExID0gdGhpcy5tMTE7CiAgICAgICAgICAgIGNvbnN0IGExMiA9IHRoaXMubTEyOwogICAgICAgICAgICBjb25zdCBhMTMgPSB0aGlzLm0xMzsKICAgICAgICAgICAgY29uc3QgYTIwID0gdGhpcy5tMjA7CiAgICAgICAgICAgIGNvbnN0IGEyMSA9IHRoaXMubTIxOwogICAgICAgICAgICBjb25zdCBhMjIgPSB0aGlzLm0yMjsKICAgICAgICAgICAgY29uc3QgYTIzID0gdGhpcy5tMjM7CiAgICAgICAgICAgIGNvbnN0IGEzMCA9IHRoaXMubTMwOwogICAgICAgICAgICBjb25zdCBhMzEgPSB0aGlzLm0zMTsKICAgICAgICAgICAgY29uc3QgYTMyID0gdGhpcy5tMzI7CiAgICAgICAgICAgIGNvbnN0IGEzMyA9IHRoaXMubTMzOwogICAgICAgICAgICBjb25zdCBiMDAgPSBhMDAgKiBhMTEgLSBhMDEgKiBhMTA7CiAgICAgICAgICAgIGNvbnN0IGIwMSA9IGEwMCAqIGExMiAtIGEwMiAqIGExMDsKICAgICAgICAgICAgY29uc3QgYjAyID0gYTAwICogYTEzIC0gYTAzICogYTEwOwogICAgICAgICAgICBjb25zdCBiMDMgPSBhMDEgKiBhMTIgLSBhMDIgKiBhMTE7CiAgICAgICAgICAgIGNvbnN0IGIwNCA9IGEwMSAqIGExMyAtIGEwMyAqIGExMTsKICAgICAgICAgICAgY29uc3QgYjA1ID0gYTAyICogYTEzIC0gYTAzICogYTEyOwogICAgICAgICAgICBjb25zdCBiMDYgPSBhMjAgKiBhMzEgLSBhMjEgKiBhMzA7CiAgICAgICAgICAgIGNvbnN0IGIwNyA9IGEyMCAqIGEzMiAtIGEyMiAqIGEzMDsKICAgICAgICAgICAgY29uc3QgYjA4ID0gYTIwICogYTMzIC0gYTIzICogYTMwOwogICAgICAgICAgICBjb25zdCBiMDkgPSBhMjEgKiBhMzIgLSBhMjIgKiBhMzE7CiAgICAgICAgICAgIGNvbnN0IGIxMCA9IGEyMSAqIGEzMyAtIGEyMyAqIGEzMTsKICAgICAgICAgICAgY29uc3QgYjExID0gYTIyICogYTMzIC0gYTIzICogYTMyOwogICAgICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50CiAgICAgICAgICAgIGxldCBkZXQgPSBiMDAgKiBiMTEgLSBiMDEgKiBiMTAgKyBiMDIgKiBiMDkgKyBiMDMgKiBiMDggLSBiMDQgKiBiMDcgKyBiMDUgKiBiMDY7CiAgICAgICAgICAgIGlmICghZGV0KSB7CiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1VuYWJsZSB0byBpbnZlcnQgTWF0NCcpOwogICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRldCA9IDEuMCAvIGRldDsKICAgICAgICAgICAgdGhpcy5zZXQoKGExMSAqIGIxMSAtIGExMiAqIGIxMCArIGExMyAqIGIwOSkgKiBkZXQsIChhMDIgKiBiMTAgLSBhMDEgKiBiMTEgLSBhMDMgKiBiMDkpICogZGV0LCAoYTMxICogYjA1IC0gYTMyICogYjA0ICsgYTMzICogYjAzKSAqIGRldCwgKGEyMiAqIGIwNCAtIGEyMSAqIGIwNSAtIGEyMyAqIGIwMykgKiBkZXQsIChhMTIgKiBiMDggLSBhMTAgKiBiMTEgLSBhMTMgKiBiMDcpICogZGV0LCAoYTAwICogYjExIC0gYTAyICogYjA4ICsgYTAzICogYjA3KSAqIGRldCwgKGEzMiAqIGIwMiAtIGEzMCAqIGIwNSAtIGEzMyAqIGIwMSkgKiBkZXQsIChhMjAgKiBiMDUgLSBhMjIgKiBiMDIgKyBhMjMgKiBiMDEpICogZGV0LCAoYTEwICogYjEwIC0gYTExICogYjA4ICsgYTEzICogYjA2KSAqIGRldCwgKGEwMSAqIGIwOCAtIGEwMCAqIGIxMCAtIGEwMyAqIGIwNikgKiBkZXQsIChhMzAgKiBiMDQgLSBhMzEgKiBiMDIgKyBhMzMgKiBiMDApICogZGV0LCAoYTIxICogYjAyIC0gYTIwICogYjA0IC0gYTIzICogYjAwKSAqIGRldCwgKGExMSAqIGIwNyAtIGExMCAqIGIwOSAtIGExMiAqIGIwNikgKiBkZXQsIChhMDAgKiBiMDkgLSBhMDEgKiBiMDcgKyBhMDIgKiBiMDYpICogZGV0LCAoYTMxICogYjAxIC0gYTMwICogYjAzIC0gYTMyICogYjAwKSAqIGRldCwgKGEyMCAqIGIwMyAtIGEyMSAqIGIwMSArIGEyMiAqIGIwMCkgKiBkZXQpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB0aGlzIG1hdHJpeCBhcyB0aGUgaW52ZXJzZSBvZiB0aGUgZ2l2ZW4gTWF0NC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBtYXQ0IC0gVGhlIG1hdDQgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIEluIGNhc2UgdGhlIGBkZXRlcm1pbmFudGAgY2FuJ3QgYmUgY2FsY3VsYXRlZCwgYSBgbnVsbGAgd2lsbCBiZSByZXR1cm5lZCwgb3RoZXJ3aXNlLCBub3RoaW5nIGlzIHJldHVybmVkCiAgICAgICAgICovCiAgICAgICAgc2V0SW52ZXJzZShtYXQ0KSB7CiAgICAgICAgICAgIGNvbnN0IGEwMCA9IG1hdDQubTAwOwogICAgICAgICAgICBjb25zdCBhMDEgPSBtYXQ0Lm0wMTsKICAgICAgICAgICAgY29uc3QgYTAyID0gbWF0NC5tMDI7CiAgICAgICAgICAgIGNvbnN0IGEwMyA9IG1hdDQubTAzOwogICAgICAgICAgICBjb25zdCBhMTAgPSBtYXQ0Lm0xMDsKICAgICAgICAgICAgY29uc3QgYTExID0gbWF0NC5tMTE7CiAgICAgICAgICAgIGNvbnN0IGExMiA9IG1hdDQubTEyOwogICAgICAgICAgICBjb25zdCBhMTMgPSBtYXQ0Lm0xMzsKICAgICAgICAgICAgY29uc3QgYTIwID0gbWF0NC5tMjA7CiAgICAgICAgICAgIGNvbnN0IGEyMSA9IG1hdDQubTIxOwogICAgICAgICAgICBjb25zdCBhMjIgPSBtYXQ0Lm0yMjsKICAgICAgICAgICAgY29uc3QgYTIzID0gbWF0NC5tMjM7CiAgICAgICAgICAgIGNvbnN0IGEzMCA9IG1hdDQubTMwOwogICAgICAgICAgICBjb25zdCBhMzEgPSBtYXQ0Lm0zMTsKICAgICAgICAgICAgY29uc3QgYTMyID0gbWF0NC5tMzI7CiAgICAgICAgICAgIGNvbnN0IGEzMyA9IG1hdDQubTMzOwogICAgICAgICAgICBjb25zdCBiMDAgPSBhMDAgKiBhMTEgLSBhMDEgKiBhMTA7CiAgICAgICAgICAgIGNvbnN0IGIwMSA9IGEwMCAqIGExMiAtIGEwMiAqIGExMDsKICAgICAgICAgICAgY29uc3QgYjAyID0gYTAwICogYTEzIC0gYTAzICogYTEwOwogICAgICAgICAgICBjb25zdCBiMDMgPSBhMDEgKiBhMTIgLSBhMDIgKiBhMTE7CiAgICAgICAgICAgIGNvbnN0IGIwNCA9IGEwMSAqIGExMyAtIGEwMyAqIGExMTsKICAgICAgICAgICAgY29uc3QgYjA1ID0gYTAyICogYTEzIC0gYTAzICogYTEyOwogICAgICAgICAgICBjb25zdCBiMDYgPSBhMjAgKiBhMzEgLSBhMjEgKiBhMzA7CiAgICAgICAgICAgIGNvbnN0IGIwNyA9IGEyMCAqIGEzMiAtIGEyMiAqIGEzMDsKICAgICAgICAgICAgY29uc3QgYjA4ID0gYTIwICogYTMzIC0gYTIzICogYTMwOwogICAgICAgICAgICBjb25zdCBiMDkgPSBhMjEgKiBhMzIgLSBhMjIgKiBhMzE7CiAgICAgICAgICAgIGNvbnN0IGIxMCA9IGEyMSAqIGEzMyAtIGEyMyAqIGEzMTsKICAgICAgICAgICAgY29uc3QgYjExID0gYTIyICogYTMzIC0gYTIzICogYTMyOwogICAgICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50CiAgICAgICAgICAgIGxldCBkZXQgPSBiMDAgKiBiMTEgLSBiMDEgKiBiMTAgKyBiMDIgKiBiMDkgKyBiMDMgKiBiMDggLSBiMDQgKiBiMDcgKyBiMDUgKiBiMDY7CiAgICAgICAgICAgIGlmICghZGV0KSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBpbnZlcnQgTWF0NCcpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRldCA9IDEuMCAvIGRldDsKICAgICAgICAgICAgdGhpcy5zZXQoKGExMSAqIGIxMSAtIGExMiAqIGIxMCArIGExMyAqIGIwOSkgKiBkZXQsIChhMDIgKiBiMTAgLSBhMDEgKiBiMTEgLSBhMDMgKiBiMDkpICogZGV0LCAoYTMxICogYjA1IC0gYTMyICogYjA0ICsgYTMzICogYjAzKSAqIGRldCwgKGEyMiAqIGIwNCAtIGEyMSAqIGIwNSAtIGEyMyAqIGIwMykgKiBkZXQsIChhMTIgKiBiMDggLSBhMTAgKiBiMTEgLSBhMTMgKiBiMDcpICogZGV0LCAoYTAwICogYjExIC0gYTAyICogYjA4ICsgYTAzICogYjA3KSAqIGRldCwgKGEzMiAqIGIwMiAtIGEzMCAqIGIwNSAtIGEzMyAqIGIwMSkgKiBkZXQsIChhMjAgKiBiMDUgLSBhMjIgKiBiMDIgKyBhMjMgKiBiMDEpICogZGV0LCAoYTEwICogYjEwIC0gYTExICogYjA4ICsgYTEzICogYjA2KSAqIGRldCwgKGEwMSAqIGIwOCAtIGEwMCAqIGIxMCAtIGEwMyAqIGIwNikgKiBkZXQsIChhMzAgKiBiMDQgLSBhMzEgKiBiMDIgKyBhMzMgKiBiMDApICogZGV0LCAoYTIxICogYjAyIC0gYTIwICogYjA0IC0gYTIzICogYjAwKSAqIGRldCwgKGExMSAqIGIwNyAtIGExMCAqIGIwOSAtIGExMiAqIGIwNikgKiBkZXQsIChhMDAgKiBiMDkgLSBhMDEgKiBiMDcgKyBhMDIgKiBiMDYpICogZGV0LCAoYTMxICogYjAxIC0gYTMwICogYjAzIC0gYTMyICogYjAwKSAqIGRldCwgKGEyMCAqIGIwMyAtIGEyMSAqIGIwMSArIGEyMiAqIGIwMCkgKiBkZXQpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBNdWx0aXBsaWVzIHR3byBNYXQ0cyBhbmQgcmV0dXJucyB0aGUgcmVzdWx0IGFzIGEgbmV3IGluc3RhbmNlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIE1hdDQgdG8gbXVsdGlwbHkgd2l0aC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBNYXQ0LgogICAgICAgICAqLwogICAgICAgIG11bHRpcGx5KG90aGVyKSB7CiAgICAgICAgICAgIGNvbnN0IGEwMCA9IHRoaXMubTAwOwogICAgICAgICAgICBjb25zdCBhMDEgPSB0aGlzLm0wMTsKICAgICAgICAgICAgY29uc3QgYTAyID0gdGhpcy5tMDI7CiAgICAgICAgICAgIGNvbnN0IGEwMyA9IHRoaXMubTAzOwogICAgICAgICAgICBjb25zdCBhMTAgPSB0aGlzLm0xMDsKICAgICAgICAgICAgY29uc3QgYTExID0gdGhpcy5tMTE7CiAgICAgICAgICAgIGNvbnN0IGExMiA9IHRoaXMubTEyOwogICAgICAgICAgICBjb25zdCBhMTMgPSB0aGlzLm0xMzsKICAgICAgICAgICAgY29uc3QgYTIwID0gdGhpcy5tMjA7CiAgICAgICAgICAgIGNvbnN0IGEyMSA9IHRoaXMubTIxOwogICAgICAgICAgICBjb25zdCBhMjIgPSB0aGlzLm0yMjsKICAgICAgICAgICAgY29uc3QgYTIzID0gdGhpcy5tMjM7CiAgICAgICAgICAgIGNvbnN0IGEzMCA9IHRoaXMubTMwOwogICAgICAgICAgICBjb25zdCBhMzEgPSB0aGlzLm0zMTsKICAgICAgICAgICAgY29uc3QgYTMyID0gdGhpcy5tMzI7CiAgICAgICAgICAgIGNvbnN0IGEzMyA9IHRoaXMubTMzOwogICAgICAgICAgICAvLyBDYWNoZSBvbmx5IHRoZSBjdXJyZW50IGxpbmUgb2YgdGhlIHNlY29uZCBtYXRyaXgKICAgICAgICAgICAgY29uc3QgYiA9IG90aGVyLmFzQXJyYXkoKTsKICAgICAgICAgICAgbGV0IGIwID0gYlswXTsKICAgICAgICAgICAgbGV0IGIxID0gYlsxXTsKICAgICAgICAgICAgbGV0IGIyID0gYlsyXTsKICAgICAgICAgICAgbGV0IGIzID0gYlszXTsKICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IE1hdDQoKTsKICAgICAgICAgICAgcmVzdWx0Lm0wMCA9IGIwICogYTAwICsgYjEgKiBhMTAgKyBiMiAqIGEyMCArIGIzICogYTMwOwogICAgICAgICAgICByZXN1bHQubTAxID0gYjAgKiBhMDEgKyBiMSAqIGExMSArIGIyICogYTIxICsgYjMgKiBhMzE7CiAgICAgICAgICAgIHJlc3VsdC5tMDIgPSBiMCAqIGEwMiArIGIxICogYTEyICsgYjIgKiBhMjIgKyBiMyAqIGEzMjsKICAgICAgICAgICAgcmVzdWx0Lm0wMyA9IGIwICogYTAzICsgYjEgKiBhMTMgKyBiMiAqIGEyMyArIGIzICogYTMzOwogICAgICAgICAgICBiMCA9IGJbNF07CiAgICAgICAgICAgIGIxID0gYls1XTsKICAgICAgICAgICAgYjIgPSBiWzZdOwogICAgICAgICAgICBiMyA9IGJbN107CiAgICAgICAgICAgIHJlc3VsdC5tMTAgPSBiMCAqIGEwMCArIGIxICogYTEwICsgYjIgKiBhMjAgKyBiMyAqIGEzMDsKICAgICAgICAgICAgcmVzdWx0Lm0xMSA9IGIwICogYTAxICsgYjEgKiBhMTEgKyBiMiAqIGEyMSArIGIzICogYTMxOwogICAgICAgICAgICByZXN1bHQubTEyID0gYjAgKiBhMDIgKyBiMSAqIGExMiArIGIyICogYTIyICsgYjMgKiBhMzI7CiAgICAgICAgICAgIHJlc3VsdC5tMTMgPSBiMCAqIGEwMyArIGIxICogYTEzICsgYjIgKiBhMjMgKyBiMyAqIGEzMzsKICAgICAgICAgICAgYjAgPSBiWzhdOwogICAgICAgICAgICBiMSA9IGJbOV07CiAgICAgICAgICAgIGIyID0gYlsxMF07CiAgICAgICAgICAgIGIzID0gYlsxMV07CiAgICAgICAgICAgIHJlc3VsdC5tMjAgPSBiMCAqIGEwMCArIGIxICogYTEwICsgYjIgKiBhMjAgKyBiMyAqIGEzMDsKICAgICAgICAgICAgcmVzdWx0Lm0yMSA9IGIwICogYTAxICsgYjEgKiBhMTEgKyBiMiAqIGEyMSArIGIzICogYTMxOwogICAgICAgICAgICByZXN1bHQubTIyID0gYjAgKiBhMDIgKyBiMSAqIGExMiArIGIyICogYTIyICsgYjMgKiBhMzI7CiAgICAgICAgICAgIHJlc3VsdC5tMjMgPSBiMCAqIGEwMyArIGIxICogYTEzICsgYjIgKiBhMjMgKyBiMyAqIGEzMzsKICAgICAgICAgICAgYjAgPSBiWzEyXTsKICAgICAgICAgICAgYjEgPSBiWzEzXTsKICAgICAgICAgICAgYjIgPSBiWzE0XTsKICAgICAgICAgICAgYjMgPSBiWzE1XTsKICAgICAgICAgICAgcmVzdWx0Lm0zMCA9IGIwICogYTAwICsgYjEgKiBhMTAgKyBiMiAqIGEyMCArIGIzICogYTMwOwogICAgICAgICAgICByZXN1bHQubTMxID0gYjAgKiBhMDEgKyBiMSAqIGExMSArIGIyICogYTIxICsgYjMgKiBhMzE7CiAgICAgICAgICAgIHJlc3VsdC5tMzIgPSBiMCAqIGEwMiArIGIxICogYTEyICsgYjIgKiBhMjIgKyBiMyAqIGEzMjsKICAgICAgICAgICAgcmVzdWx0Lm0zMyA9IGIwICogYTAzICsgYjEgKiBhMTMgKyBiMiAqIGEyMyArIGIzICogYTMzOwogICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBNdWx0aXBsaWVzIHR3byBNYXQ0cyBpbiBwbGFjZSBleHBsaWNpdGx5IG5vdCB1c2luZyBTSU1ELgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIE1hdDQgdG8gbXVsdGlwbHkgd2l0aC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBNYXQ0LgogICAgICAgICAqLwogICAgICAgIG11bHRpcGx5SW5QbGFjZShvdGhlcikgewogICAgICAgICAgICBjb25zdCBhID0gdGhpcy5hc0FycmF5KCk7CiAgICAgICAgICAgIGNvbnN0IGEwMCA9IGFbMF07CiAgICAgICAgICAgIGNvbnN0IGEwMSA9IGFbMV07CiAgICAgICAgICAgIGNvbnN0IGEwMiA9IGFbMl07CiAgICAgICAgICAgIGNvbnN0IGEwMyA9IGFbM107CiAgICAgICAgICAgIGNvbnN0IGExMCA9IGFbNF07CiAgICAgICAgICAgIGNvbnN0IGExMSA9IGFbNV07CiAgICAgICAgICAgIGNvbnN0IGExMiA9IGFbNl07CiAgICAgICAgICAgIGNvbnN0IGExMyA9IGFbN107CiAgICAgICAgICAgIGNvbnN0IGEyMCA9IGFbOF07CiAgICAgICAgICAgIGNvbnN0IGEyMSA9IGFbOV07CiAgICAgICAgICAgIGNvbnN0IGEyMiA9IGFbMTBdOwogICAgICAgICAgICBjb25zdCBhMjMgPSBhWzExXTsKICAgICAgICAgICAgY29uc3QgYTMwID0gYVsxMl07CiAgICAgICAgICAgIGNvbnN0IGEzMSA9IGFbMTNdOwogICAgICAgICAgICBjb25zdCBhMzIgPSBhWzE0XTsKICAgICAgICAgICAgY29uc3QgYTMzID0gYVsxNV07CiAgICAgICAgICAgIC8vIENhY2hlIG9ubHkgdGhlIGN1cnJlbnQgbGluZSBvZiB0aGUgc2Vjb25kIG1hdHJpeAogICAgICAgICAgICBjb25zdCBiID0gb3RoZXIuYXNBcnJheSgpOwogICAgICAgICAgICBsZXQgYjAgPSBiWzBdOwogICAgICAgICAgICBsZXQgYjEgPSBiWzFdOwogICAgICAgICAgICBsZXQgYjIgPSBiWzJdOwogICAgICAgICAgICBsZXQgYjMgPSBiWzNdOwogICAgICAgICAgICB0aGlzLm0wMCA9IGIwICogYTAwICsgYjEgKiBhMTAgKyBiMiAqIGEyMCArIGIzICogYTMwOwogICAgICAgICAgICB0aGlzLm0wMSA9IGIwICogYTAxICsgYjEgKiBhMTEgKyBiMiAqIGEyMSArIGIzICogYTMxOwogICAgICAgICAgICB0aGlzLm0wMiA9IGIwICogYTAyICsgYjEgKiBhMTIgKyBiMiAqIGEyMiArIGIzICogYTMyOwogICAgICAgICAgICB0aGlzLm0wMyA9IGIwICogYTAzICsgYjEgKiBhMTMgKyBiMiAqIGEyMyArIGIzICogYTMzOwogICAgICAgICAgICBiMCA9IGJbNF07CiAgICAgICAgICAgIGIxID0gYls1XTsKICAgICAgICAgICAgYjIgPSBiWzZdOwogICAgICAgICAgICBiMyA9IGJbN107CiAgICAgICAgICAgIHRoaXMubTEwID0gYjAgKiBhMDAgKyBiMSAqIGExMCArIGIyICogYTIwICsgYjMgKiBhMzA7CiAgICAgICAgICAgIHRoaXMubTExID0gYjAgKiBhMDEgKyBiMSAqIGExMSArIGIyICogYTIxICsgYjMgKiBhMzE7CiAgICAgICAgICAgIHRoaXMubTEyID0gYjAgKiBhMDIgKyBiMSAqIGExMiArIGIyICogYTIyICsgYjMgKiBhMzI7CiAgICAgICAgICAgIHRoaXMubTEzID0gYjAgKiBhMDMgKyBiMSAqIGExMyArIGIyICogYTIzICsgYjMgKiBhMzM7CiAgICAgICAgICAgIGIwID0gYls4XTsKICAgICAgICAgICAgYjEgPSBiWzldOwogICAgICAgICAgICBiMiA9IGJbMTBdOwogICAgICAgICAgICBiMyA9IGJbMTFdOwogICAgICAgICAgICB0aGlzLm0yMCA9IGIwICogYTAwICsgYjEgKiBhMTAgKyBiMiAqIGEyMCArIGIzICogYTMwOwogICAgICAgICAgICB0aGlzLm0yMSA9IGIwICogYTAxICsgYjEgKiBhMTEgKyBiMiAqIGEyMSArIGIzICogYTMxOwogICAgICAgICAgICB0aGlzLm0yMiA9IGIwICogYTAyICsgYjEgKiBhMTIgKyBiMiAqIGEyMiArIGIzICogYTMyOwogICAgICAgICAgICB0aGlzLm0yMyA9IGIwICogYTAzICsgYjEgKiBhMTMgKyBiMiAqIGEyMyArIGIzICogYTMzOwogICAgICAgICAgICBiMCA9IGJbMTJdOwogICAgICAgICAgICBiMSA9IGJbMTNdOwogICAgICAgICAgICBiMiA9IGJbMTRdOwogICAgICAgICAgICBiMyA9IGJbMTVdOwogICAgICAgICAgICB0aGlzLm0zMCA9IGIwICogYTAwICsgYjEgKiBhMTAgKyBiMiAqIGEyMCArIGIzICogYTMwOwogICAgICAgICAgICB0aGlzLm0zMSA9IGIwICogYTAxICsgYjEgKiBhMTEgKyBiMiAqIGEyMSArIGIzICogYTMxOwogICAgICAgICAgICB0aGlzLm0zMiA9IGIwICogYTAyICsgYjEgKiBhMTIgKyBiMiAqIGEyMiArIGIzICogYTMyOwogICAgICAgICAgICB0aGlzLm0zMyA9IGIwICogYTAzICsgYjEgKiBhMTMgKyBiMiAqIGEyMyArIGIzICogYTMzOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUG9zdCBtdWx0aXBsaWVzIHR3byBNYXQ0cyBpbiBwbGFjZSBleHBsaWNpdGx5IG5vdCB1c2luZyBTSU1ELgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIE1hdDQgdG8gbXVsdGlwbHkgd2l0aC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgcmVzdWx0IGFzIGEgbmV3IE1hdDQuCiAgICAgICAgICovCiAgICAgICAgcG9zdE11bHRpcGx5SW5QbGFjZShvdGhlcikgewogICAgICAgICAgICBjb25zdCBhID0gb3RoZXIuYXNBcnJheSgpOwogICAgICAgICAgICBjb25zdCBhMDAgPSBhWzBdOwogICAgICAgICAgICBjb25zdCBhMDEgPSBhWzFdOwogICAgICAgICAgICBjb25zdCBhMDIgPSBhWzJdOwogICAgICAgICAgICBjb25zdCBhMDMgPSBhWzNdOwogICAgICAgICAgICBjb25zdCBhMTAgPSBhWzRdOwogICAgICAgICAgICBjb25zdCBhMTEgPSBhWzVdOwogICAgICAgICAgICBjb25zdCBhMTIgPSBhWzZdOwogICAgICAgICAgICBjb25zdCBhMTMgPSBhWzddOwogICAgICAgICAgICBjb25zdCBhMjAgPSBhWzhdOwogICAgICAgICAgICBjb25zdCBhMjEgPSBhWzldOwogICAgICAgICAgICBjb25zdCBhMjIgPSBhWzEwXTsKICAgICAgICAgICAgY29uc3QgYTIzID0gYVsxMV07CiAgICAgICAgICAgIGNvbnN0IGEzMCA9IGFbMTJdOwogICAgICAgICAgICBjb25zdCBhMzEgPSBhWzEzXTsKICAgICAgICAgICAgY29uc3QgYTMyID0gYVsxNF07CiAgICAgICAgICAgIGNvbnN0IGEzMyA9IGFbMTVdOwogICAgICAgICAgICAvLyBDYWNoZSBvbmx5IHRoZSBjdXJyZW50IGxpbmUgb2YgdGhlIHNlY29uZCBtYXRyaXgKICAgICAgICAgICAgY29uc3QgYiA9IHRoaXMuYXNBcnJheSgpOwogICAgICAgICAgICBsZXQgYjAgPSBiWzBdOwogICAgICAgICAgICBsZXQgYjEgPSBiWzFdOwogICAgICAgICAgICBsZXQgYjIgPSBiWzJdOwogICAgICAgICAgICBsZXQgYjMgPSBiWzNdOwogICAgICAgICAgICB0aGlzLm0wMCA9IGIwICogYTAwICsgYjEgKiBhMTAgKyBiMiAqIGEyMCArIGIzICogYTMwOwogICAgICAgICAgICB0aGlzLm0wMSA9IGIwICogYTAxICsgYjEgKiBhMTEgKyBiMiAqIGEyMSArIGIzICogYTMxOwogICAgICAgICAgICB0aGlzLm0wMiA9IGIwICogYTAyICsgYjEgKiBhMTIgKyBiMiAqIGEyMiArIGIzICogYTMyOwogICAgICAgICAgICB0aGlzLm0wMyA9IGIwICogYTAzICsgYjEgKiBhMTMgKyBiMiAqIGEyMyArIGIzICogYTMzOwogICAgICAgICAgICBiMCA9IGJbNF07CiAgICAgICAgICAgIGIxID0gYls1XTsKICAgICAgICAgICAgYjIgPSBiWzZdOwogICAgICAgICAgICBiMyA9IGJbN107CiAgICAgICAgICAgIHRoaXMubTEwID0gYjAgKiBhMDAgKyBiMSAqIGExMCArIGIyICogYTIwICsgYjMgKiBhMzA7CiAgICAgICAgICAgIHRoaXMubTExID0gYjAgKiBhMDEgKyBiMSAqIGExMSArIGIyICogYTIxICsgYjMgKiBhMzE7CiAgICAgICAgICAgIHRoaXMubTEyID0gYjAgKiBhMDIgKyBiMSAqIGExMiArIGIyICogYTIyICsgYjMgKiBhMzI7CiAgICAgICAgICAgIHRoaXMubTEzID0gYjAgKiBhMDMgKyBiMSAqIGExMyArIGIyICogYTIzICsgYjMgKiBhMzM7CiAgICAgICAgICAgIGIwID0gYls4XTsKICAgICAgICAgICAgYjEgPSBiWzldOwogICAgICAgICAgICBiMiA9IGJbMTBdOwogICAgICAgICAgICBiMyA9IGJbMTFdOwogICAgICAgICAgICB0aGlzLm0yMCA9IGIwICogYTAwICsgYjEgKiBhMTAgKyBiMiAqIGEyMCArIGIzICogYTMwOwogICAgICAgICAgICB0aGlzLm0yMSA9IGIwICogYTAxICsgYjEgKiBhMTEgKyBiMiAqIGEyMSArIGIzICogYTMxOwogICAgICAgICAgICB0aGlzLm0yMiA9IGIwICogYTAyICsgYjEgKiBhMTIgKyBiMiAqIGEyMiArIGIzICogYTMyOwogICAgICAgICAgICB0aGlzLm0yMyA9IGIwICogYTAzICsgYjEgKiBhMTMgKyBiMiAqIGEyMyArIGIzICogYTMzOwogICAgICAgICAgICBiMCA9IGJbMTJdOwogICAgICAgICAgICBiMSA9IGJbMTNdOwogICAgICAgICAgICBiMiA9IGJbMTRdOwogICAgICAgICAgICBiMyA9IGJbMTVdOwogICAgICAgICAgICB0aGlzLm0zMCA9IGIwICogYTAwICsgYjEgKiBhMTAgKyBiMiAqIGEyMCArIGIzICogYTMwOwogICAgICAgICAgICB0aGlzLm0zMSA9IGIwICogYTAxICsgYjEgKiBhMTEgKyBiMiAqIGEyMSArIGIzICogYTMxOwogICAgICAgICAgICB0aGlzLm0zMiA9IGIwICogYTAyICsgYjEgKiBhMTIgKyBiMiAqIGEyMiArIGIzICogYTMyOwogICAgICAgICAgICB0aGlzLm0zMyA9IGIwICogYTAzICsgYjEgKiBhMTMgKyBiMiAqIGEyMyArIGIzICogYTMzOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVHJhbnNsYXRlIGEgTWF0NCBieSB0aGUgZ2l2ZW4gdmVjdG9yIG5vdCB1c2luZyBTSU1ELgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHYzIC0gVGhlIGdpdmVuIHZlY3RvciB0byB0cmFuc2xhdGUgYWxvbmcuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgdHJhbnNsYXRlSW5QbGFjZSh2MykgewogICAgICAgICAgICBjb25zdCBhID0gdGhpcy5hc0FycmF5KCk7CiAgICAgICAgICAgIGNvbnN0IHggPSB2My54OwogICAgICAgICAgICBjb25zdCB5ID0gdjMueTsKICAgICAgICAgICAgY29uc3QgeiA9IHYzLno7CiAgICAgICAgICAgIGFbMTJdID0gYVswXSAqIHggKyBhWzRdICogeSArIGFbOF0gKiB6ICsgYVsxMl07CiAgICAgICAgICAgIGFbMTNdID0gYVsxXSAqIHggKyBhWzVdICogeSArIGFbOV0gKiB6ICsgYVsxM107CiAgICAgICAgICAgIGFbMTRdID0gYVsyXSAqIHggKyBhWzZdICogeSArIGFbMTBdICogeiArIGFbMTRdOwogICAgICAgICAgICBhWzE1XSA9IGFbM10gKiB4ICsgYVs3XSAqIHkgKyBhWzExXSAqIHogKyBhWzE1XTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdlbmVyYXRlcyBhIGxvb2stYXQgbWF0cml4IHdpdGggdGhlIGdpdmVuIHBvc2l0aW9uLCBmb2NhbCBwb2ludCwgYW5kIHVwIGF4aXMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcG9zIC0gUG9zaXRpb24gb2YgdGhlIHZpZXdlci4KICAgICAgICAgKiBAcGFyYW0gdGFyZ2V0IC0gUG9pbnQgdGhlIHZpZXdlciBpcyBsb29raW5nIGF0LgogICAgICAgICAqIEBwYXJhbSB1cCAtIFZlYzMgcG9pbnRpbmcgdXAuCiAgICAgICAgICovCiAgICAgICAgc2V0TG9va0F0KHBvcywgdGFyZ2V0LCB1cCkgewogICAgICAgICAgICBjb25zdCB6QXhpcyA9IHBvcy5zdWJ0cmFjdCh0YXJnZXQpOwogICAgICAgICAgICBjb25zdCB6TGVuID0gekF4aXMubGVuZ3RoKCk7CiAgICAgICAgICAgIGlmICh6TGVuIDwgTnVtYmVyLkVQU0lMT04pIHsKICAgICAgICAgICAgICAgIHRoaXMuc2V0SWRlbnRpdHkoKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICB6QXhpcy5zY2FsZUluUGxhY2UoMS4wIC8gekxlbik7CiAgICAgICAgICAgIGNvbnN0IHhBeGlzID0gdXAuY3Jvc3MoekF4aXMpOwogICAgICAgICAgICBjb25zdCB4TGVuID0geEF4aXMubGVuZ3RoKCk7CiAgICAgICAgICAgIGlmICh4TGVuID4gTnVtYmVyLkVQU0lMT04pCiAgICAgICAgICAgICAgICB4QXhpcy5zY2FsZUluUGxhY2UoMS4wIC8geExlbik7CiAgICAgICAgICAgIGNvbnN0IHlBeGlzID0gekF4aXMuY3Jvc3MoeEF4aXMpOwogICAgICAgICAgICBjb25zdCB5TGVuID0geUF4aXMubGVuZ3RoKCk7CiAgICAgICAgICAgIGlmICh5TGVuID4gTnVtYmVyLkVQU0lMT04pCiAgICAgICAgICAgICAgICB5QXhpcy5zY2FsZUluUGxhY2UoMS4wIC8geUxlbik7CiAgICAgICAgICAgIC8qIGVzbGludC1kaXNhYmxlIHByZXR0aWVyL3ByZXR0aWVyKi8KICAgICAgICAgICAgdGhpcy5zZXQoeEF4aXMueCwgeEF4aXMueSwgeEF4aXMueiwgMCwgeUF4aXMueCwgeUF4aXMueSwgeUF4aXMueiwgMCwgekF4aXMueCwgekF4aXMueSwgekF4aXMueiwgMCwgcG9zLngsIHBvcy55LCBwb3MueiwgMSk7CiAgICAgICAgICAgIC8qIGVzbGludC1lbmFibGUgcHJldHRpZXIvcHJldHRpZXIqLwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGEgbWF0cml4IGZyb20gYSBnaXZlbiBhbmdsZSBhcm91bmQgYSBnaXZlbiBheGlzLgogICAgICAgICAqIFRoaXMgaXMgZXF1aXZhbGVudCB0byAoYnV0IG11Y2ggZmFzdGVyIHRoYW4pOgogICAgICAgICAqCiAgICAgICAgICogICAgIG1hdDQuaWRlbnRpdHkoZGVzdCk7CiAgICAgICAgICogICAgIG1hdDQucm90YXRlKGRlc3QsIGRlc3QsIHJhZCwgYXhpcyk7CiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gYXhpcyAtIFRoZSBheGlzIHRvIHJvdGF0ZSBhcm91bmQuCiAgICAgICAgICogQHBhcmFtIHJhZCAtIFRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRSb3RhdGlvbihheGlzLCByYWQpIHsKICAgICAgICAgICAgY29uc3QgbGVuID0gYXhpcy5sZW5ndGgoKTsKICAgICAgICAgICAgaWYgKE1hdGguYWJzKGxlbikgPCBOdW1iZXIuRVBTSUxPTikgewogICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgeCA9IGF4aXMueCAvIGxlbjsKICAgICAgICAgICAgY29uc3QgeSA9IGF4aXMueSAvIGxlbjsKICAgICAgICAgICAgY29uc3QgeiA9IGF4aXMueiAvIGxlbjsKICAgICAgICAgICAgY29uc3QgcyA9IE1hdGguc2luKHJhZCk7CiAgICAgICAgICAgIGNvbnN0IGMgPSBNYXRoLmNvcyhyYWQpOwogICAgICAgICAgICBjb25zdCB0ID0gMSAtIGM7CiAgICAgICAgICAgIC8vIFBlcmZvcm0gcm90YXRpb24tc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uCiAgICAgICAgICAgIGNvbnN0IGEgPSB0aGlzLmFzQXJyYXkoKTsKICAgICAgICAgICAgYVswXSA9IHggKiB4ICogdCArIGM7CiAgICAgICAgICAgIGFbMV0gPSB5ICogeCAqIHQgKyB6ICogczsKICAgICAgICAgICAgYVsyXSA9IHogKiB4ICogdCAtIHkgKiBzOwogICAgICAgICAgICBhWzNdID0gMDsKICAgICAgICAgICAgYVs0XSA9IHggKiB5ICogdCAtIHogKiBzOwogICAgICAgICAgICBhWzVdID0geSAqIHkgKiB0ICsgYzsKICAgICAgICAgICAgYVs2XSA9IHogKiB5ICogdCArIHggKiBzOwogICAgICAgICAgICBhWzddID0gMDsKICAgICAgICAgICAgYVs4XSA9IHggKiB6ICogdCArIHkgKiBzOwogICAgICAgICAgICBhWzldID0geSAqIHogKiB0IC0geCAqIHM7CiAgICAgICAgICAgIGFbMTBdID0geiAqIHogKiB0ICsgYzsKICAgICAgICAgICAgYVsxMV0gPSAwOwogICAgICAgICAgICBhWzEyXSA9IDA7CiAgICAgICAgICAgIGFbMTNdID0gMDsKICAgICAgICAgICAgYVsxNF0gPSAwOwogICAgICAgICAgICBhWzE1XSA9IDE7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGEgbWF0cml4IGZyb20gdGhlIGdpdmVuIGFuZ2xlIGFyb3VuZCB0aGUgWCBheGlzLgogICAgICAgICAqIFRoaXMgaXMgZXF1aXZhbGVudCB0byAoYnV0IG11Y2ggZmFzdGVyIHRoYW4pOgogICAgICAgICAqCiAgICAgICAgICogICAgIG1hdDQuaWRlbnRpdHkoZGVzdCk7CiAgICAgICAgICogICAgIG1hdDQucm90YXRlWChkZXN0LCBkZXN0LCByYWQpOwogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHJhZCAtIFRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRYUm90YXRpb24ocmFkKSB7CiAgICAgICAgICAgIGNvbnN0IHMgPSBNYXRoLnNpbihyYWQpOwogICAgICAgICAgICBjb25zdCBjID0gTWF0aC5jb3MocmFkKTsKICAgICAgICAgICAgLy8gUGVyZm9ybSBheGlzLXNwZWNpZmljIG1hdHJpeCBtdWx0aXBsaWNhdGlvbgogICAgICAgICAgICBjb25zdCBhID0gdGhpcy5hc0FycmF5KCk7CiAgICAgICAgICAgIC8qIGVzbGludC1kaXNhYmxlIHByZXR0aWVyL3ByZXR0aWVyKi8KICAgICAgICAgICAgYVswXSA9IDE7CiAgICAgICAgICAgIGFbMV0gPSAwOwogICAgICAgICAgICBhWzJdID0gMDsKICAgICAgICAgICAgYVszXSA9IDA7CiAgICAgICAgICAgIGFbNF0gPSAwOwogICAgICAgICAgICBhWzVdID0gYzsKICAgICAgICAgICAgYVs2XSA9IHM7CiAgICAgICAgICAgIGFbN10gPSAwOwogICAgICAgICAgICBhWzhdID0gMDsKICAgICAgICAgICAgYVs5XSA9IC1zOwogICAgICAgICAgICBhWzEwXSA9IGM7CiAgICAgICAgICAgIGFbMTFdID0gMDsKICAgICAgICAgICAgYVsxMl0gPSAwOwogICAgICAgICAgICBhWzEzXSA9IDA7CiAgICAgICAgICAgIGFbMTRdID0gMDsKICAgICAgICAgICAgYVsxNV0gPSAxOwogICAgICAgICAgICAvKiBlc2xpbnQtZW5hYmxlIHByZXR0aWVyL3ByZXR0aWVyKi8KICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYSBtYXRyaXggZnJvbSB0aGUgZ2l2ZW4gYW5nbGUgYXJvdW5kIHRoZSBZIGF4aXMuCiAgICAgICAgICogVGhpcyBpcyBlcXVpdmFsZW50IHRvIChidXQgbXVjaCBmYXN0ZXIgdGhhbik6CiAgICAgICAgICoKICAgICAgICAgKiAgICAgbWF0NC5pZGVudGl0eShkZXN0KTsKICAgICAgICAgKiAgICAgbWF0NC5yb3RhdGVZKGRlc3QsIGRlc3QsIHJhZCk7CiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmFkIC0gVGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5LgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldFlSb3RhdGlvbihyYWQpIHsKICAgICAgICAgICAgY29uc3QgcyA9IE1hdGguc2luKHJhZCk7CiAgICAgICAgICAgIGNvbnN0IGMgPSBNYXRoLmNvcyhyYWQpOwogICAgICAgICAgICAvLyBQZXJmb3JtIGF4aXMtc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uCiAgICAgICAgICAgIGNvbnN0IGEgPSB0aGlzLmFzQXJyYXkoKTsKICAgICAgICAgICAgLyogZXNsaW50LWRpc2FibGUgcHJldHRpZXIvcHJldHRpZXIqLwogICAgICAgICAgICBhWzBdID0gYzsKICAgICAgICAgICAgYVsxXSA9IDA7CiAgICAgICAgICAgIGFbMl0gPSAtczsKICAgICAgICAgICAgYVszXSA9IDA7CiAgICAgICAgICAgIGFbNF0gPSAwOwogICAgICAgICAgICBhWzVdID0gMTsKICAgICAgICAgICAgYVs2XSA9IDA7CiAgICAgICAgICAgIGFbN10gPSAwOwogICAgICAgICAgICBhWzhdID0gczsKICAgICAgICAgICAgYVs5XSA9IDA7CiAgICAgICAgICAgIGFbMTBdID0gYzsKICAgICAgICAgICAgYVsxMV0gPSAwOwogICAgICAgICAgICBhWzEyXSA9IDA7CiAgICAgICAgICAgIGFbMTNdID0gMDsKICAgICAgICAgICAgYVsxNF0gPSAwOwogICAgICAgICAgICBhWzE1XSA9IDE7CiAgICAgICAgICAgIC8qIGVzbGludC1lbmFibGUgcHJldHRpZXIvcHJldHRpZXIqLwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlcyBhIG1hdHJpeCBmcm9tIHRoZSBnaXZlbiBhbmdsZSBhcm91bmQgdGhlIFogYXhpcy4KICAgICAgICAgKiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gKGJ1dCBtdWNoIGZhc3RlciB0aGFuKToKICAgICAgICAgKgogICAgICAgICAqICAgICBtYXQ0LmlkZW50aXR5KGRlc3QpOwogICAgICAgICAqICAgICBtYXQ0LnJvdGF0ZVooZGVzdCwgZGVzdCwgcmFkKTsKICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSByYWQgLSBUaGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnkuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0WlJvdGF0aW9uKHJhZCkgewogICAgICAgICAgICBjb25zdCBzID0gTWF0aC5zaW4ocmFkKTsKICAgICAgICAgICAgY29uc3QgYyA9IE1hdGguY29zKHJhZCk7CiAgICAgICAgICAgIC8vIFBlcmZvcm0gYXhpcy1zcGVjaWZpYyBtYXRyaXggbXVsdGlwbGljYXRpb24KICAgICAgICAgICAgY29uc3QgYSA9IHRoaXMuYXNBcnJheSgpOwogICAgICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBwcmV0dGllci9wcmV0dGllciovCiAgICAgICAgICAgIGFbMF0gPSBjOwogICAgICAgICAgICBhWzFdID0gczsKICAgICAgICAgICAgYVsyXSA9IDA7CiAgICAgICAgICAgIGFbM10gPSAwOwogICAgICAgICAgICBhWzRdID0gLXM7CiAgICAgICAgICAgIGFbNV0gPSBjOwogICAgICAgICAgICBhWzZdID0gMDsKICAgICAgICAgICAgYVs3XSA9IDA7CiAgICAgICAgICAgIGFbOF0gPSAwOwogICAgICAgICAgICBhWzldID0gMDsKICAgICAgICAgICAgYVsxMF0gPSAxOwogICAgICAgICAgICBhWzExXSA9IDA7CiAgICAgICAgICAgIGFbMTJdID0gMDsKICAgICAgICAgICAgYVsxM10gPSAwOwogICAgICAgICAgICBhWzE0XSA9IDA7CiAgICAgICAgICAgIGFbMTVdID0gMTsKICAgICAgICAgICAgLyogZXNsaW50LWVuYWJsZSBwcmV0dGllci9wcmV0dGllciovCiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUcmFuc2Zvcm1zIHRoZSBWZWM0IHdpdGggYSBNYXQ0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHZlYyAtIFRoZSB2ZWMgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybiB0aGUgcmVzdWx0IGFzIGEgbmV3IFZlYzQuCiAgICAgICAgICovCiAgICAgICAgdHJhbnNmb3JtVmVjNCh2ZWMpIHsKICAgICAgICAgICAgY29uc3QgYSA9IHRoaXMuYXNBcnJheSgpOwogICAgICAgICAgICBjb25zdCB4ID0gdmVjLng7CiAgICAgICAgICAgIGNvbnN0IHkgPSB2ZWMueTsKICAgICAgICAgICAgY29uc3QgeiA9IHZlYy56OwogICAgICAgICAgICBjb25zdCB3ID0gdmVjLnc7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjNChhWzBdICogeCArIGFbNF0gKiB5ICsgYVs4XSAqIHogKyBhWzEyXSAqIHcsIGFbMV0gKiB4ICsgYVs1XSAqIHkgKyBhWzldICogeiArIGFbMTNdICogdywgYVsyXSAqIHggKyBhWzZdICogeSArIGFbMTBdICogeiArIGFbMTRdICogdywgYVszXSAqIHggKyBhWzddICogeSArIGFbMTFdICogeiArIGFbMTVdICogdyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRyYW5zZm9ybXMgdGhlIFZlYzMgd2l0aCBhIE1hdDQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gdmVjIC0gVGhlIHZlYyB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJuIHRoZSByZXN1bHQgYXMgYSBuZXcgVmVjMy4KICAgICAgICAgKi8KICAgICAgICB0cmFuc2Zvcm1WZWMzKHZlYykgewogICAgICAgICAgICBjb25zdCBhID0gdGhpcy5hc0FycmF5KCk7CiAgICAgICAgICAgIGNvbnN0IHggPSB2ZWMueDsKICAgICAgICAgICAgY29uc3QgeSA9IHZlYy55OwogICAgICAgICAgICBjb25zdCB6ID0gdmVjLno7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyhhWzBdICogeCArIGFbNF0gKiB5ICsgYVs4XSAqIHogKyBhWzEyXSwgYVsxXSAqIHggKyBhWzVdICogeSArIGFbOV0gKiB6ICsgYVsxM10sIGFbMl0gKiB4ICsgYVs2XSAqIHkgKyBhWzEwXSAqIHogKyBhWzE0XSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJvdGF0ZXMgYSBnaXZlbiBgVmVjM2AgYW5kIHRoZSByZXN1bHQgaXMgcmV0dXJuZWQgYXMgYSBuZXcgYFZlYzNgLCBhcHBseWluZyBvbmx5IHRoZSB0b3AgbGVmdCBjb21wb25lbnRzIG9mIHRoZSBtYXRyaXgsIHNvIG5vdCBhcHBseWluZyBhbnkgdHJhbnNsYXRpb24uCiAgICAgICAgICogQHBhcmFtIHZlYyAtIFRoZSB2ZWMgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybiB0aGUgcmVzdWx0IGFzIGEgbmV3IFZlYzMuCiAgICAgICAgICovCiAgICAgICAgcm90YXRlVmVjMyh2ZWMpIHsKICAgICAgICAgICAgY29uc3QgYSA9IHRoaXMuYXNBcnJheSgpOwogICAgICAgICAgICBjb25zdCB4ID0gdmVjLng7CiAgICAgICAgICAgIGNvbnN0IHkgPSB2ZWMueTsKICAgICAgICAgICAgY29uc3QgeiA9IHZlYy56OwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzMoYVswXSAqIHggKyBhWzRdICogeSArIGFbOF0gKiB6LCBhWzFdICogeCArIGFbNV0gKiB5ICsgYVs5XSAqIHosIGFbMl0gKiB4ICsgYVs2XSAqIHkgKyBhWzEwXSAqIHopOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXQgdGhlIHBlcnNwZWN0aXZlIGZyb20gYSBNYXQ0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGZvdlkgLSBUaGUgZm92WSB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gYXNwZWN0IC0gVGhlIGFzcGVjdCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gbmVhciAtIFRoZSBuZWFyIHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBmYXIgLSBUaGUgZmFyIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldFBlcnNwZWN0aXZlTWF0cml4KGZvdnksIGFzcGVjdCwgbmVhciwgZmFyKSB7CiAgICAgICAgICAgIGNvbnN0IGYgPSBNYXRoLnRhbihNYXRoLlBJICogMC41IC0gMC41ICogZm92eSk7CiAgICAgICAgICAgIGNvbnN0IHJhbmdlSW52ID0gMS4wIC8gKG5lYXIgLSBmYXIpOwogICAgICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBwcmV0dGllci9wcmV0dGllciovCiAgICAgICAgICAgIHRoaXMuc2V0KGYgLyBhc3BlY3QsIDAsIDAsIDAsIDAsIGYsIDAsIDAsIDAsIDAsIChuZWFyICsgZmFyKSAqIHJhbmdlSW52LCAtMSwgMCwgMCwgbmVhciAqIGZhciAqIHJhbmdlSW52ICogMiwgMCk7CiAgICAgICAgICAgIC8qIGVzbGludC1lbmFibGUgcHJldHRpZXIvcHJldHRpZXIqLwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDYWxjdWxhdGVzIHRoZSBvcnRob2dyYXBoaWMgbWF0cml4IGFuZCBzZXRzIHRoZSBzdGF0ZSBvZiB0aGUgTWF0NCBjbGFzcwogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGxlZnQgLSBUaGUgbGVmdCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gcmlnaHQgLSBUaGUgcmlnaHQgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGJvdHRvbSAtIFRoZSBib3R0b20gdmFsdWUuCiAgICAgICAgICogQHBhcmFtIHRvcCAtIFRoZSB0b3AgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIG5lYXIgLSBUaGUgbmVhciB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gZmFyIC0gVGhlIGZhciB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRPcnRob2dyYXBoaWNNYXRyaXgobGVmdCwgcmlnaHQsIGJvdHRvbSwgdG9wLCBuZWFyLCBmYXIpIHsKICAgICAgICAgICAgY29uc3QgbHIgPSAxIC8gKGxlZnQgLSByaWdodCk7CiAgICAgICAgICAgIGNvbnN0IGJ0ID0gMSAvIChib3R0b20gLSB0b3ApOwogICAgICAgICAgICBjb25zdCBuZiA9IDEgLyAobmVhciAtIGZhcik7CiAgICAgICAgICAgIC8qIGVzbGludC1kaXNhYmxlIHByZXR0aWVyL3ByZXR0aWVyKi8KICAgICAgICAgICAgdGhpcy5zZXQoLTIgKiBsciwgMCwgMCwgMCwgMCwgLTIgKiBidCwgMCwgMCwgMCwgMCwgMiAqIG5mLCAwLCAobGVmdCArIHJpZ2h0KSAqIGxyLCAodG9wICsgYm90dG9tKSAqIGJ0LCAoZmFyICsgbmVhcikgKiBuZiwgMSk7CiAgICAgICAgICAgIC8qIGVzbGludC1lbmFibGUgcHJldHRpZXIvcHJldHRpZXIqLwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXQgdGhlIE1hdHJpeCB0byBiZSBhIHNjYWxlIG1hdHJpeC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSB4IC0gVGhlIHggdmFsdWUuCiAgICAgICAgICogQHBhcmFtIHkgLSBUaGUgeSB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0geiAtIFRoZSB6IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldFNjYWxlKHgsIHksIHopIHsKICAgICAgICAgICAgLyogZXNsaW50LWRpc2FibGUgcHJldHRpZXIvcHJldHRpZXIqLwogICAgICAgICAgICBpZiAoeCBpbnN0YW5jZW9mIFZlYzMpIHsKICAgICAgICAgICAgICAgIHRoaXMuc2V0KHgueCwgMCwgMCwgMCwgMCwgeC55LCAwLCAwLCAwLCAwLCB4LnosIDAsIDAsIDAsIDAsIDEpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdGhpcy5zZXQoeCwgMCwgMCwgMCwgMCwgeSwgMCwgMCwgMCwgMCwgeiwgMCwgMCwgMCwgMCwgMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLyogZXNsaW50LWVuYWJsZSBwcmV0dGllci9wcmV0dGllciovCiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRyYW5zZm9ybXMgYSAzeDQgbWF0cml4IGludG8gYSA0eDQgbWF0cml4IGFuZCBzZXQgdGhlIHJlc3VsdCB0byB0aGUgTWF0aDQgc3RhdGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbTN4NCAtIFRoZSBtM3g0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldEZyb21NYXQzeDRBcnJheShtM3g0KSB7CiAgICAgICAgICAgIC8qIGVzbGludC1kaXNhYmxlIHByZXR0aWVyL3ByZXR0aWVyKi8KICAgICAgICAgICAgdGhpcy5zZXQobTN4NFswXSwgbTN4NFsxXSwgbTN4NFsyXSwgMCwgbTN4NFszXSwgbTN4NFs0XSwgbTN4NFs1XSwgMCwgbTN4NFs2XSwgbTN4NFs3XSwgbTN4NFs4XSwgMCwgbTN4NFs5XSwgbTN4NFsxMF0sIG0zeDRbMTFdLCAxKTsKICAgICAgICAgICAgLyogZXNsaW50LWVuYWJsZSBwcmV0dGllci9wcmV0dGllciovCiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENsb25lcyB0aGlzIE1hdDQgcmV0dXJuaW5nIGEgbmV3IGluc3RhbmNlLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgTWF0NC4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBNYXQ0KHRoaXMubTAwLCB0aGlzLm0wMSwgdGhpcy5tMDIsIHRoaXMubTAzLCB0aGlzLm0xMCwgdGhpcy5tMTEsIHRoaXMubTEyLCB0aGlzLm0xMywgdGhpcy5tMjAsIHRoaXMubTIxLCB0aGlzLm0yMiwgdGhpcy5tMjMsIHRoaXMubTMwLCB0aGlzLm0zMSwgdGhpcy5tMzIsIHRoaXMubTMzKTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIFZlYzMgdG8gYSBzdHJpbmcgaW4gSlNPTiBmb3JtYXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICB0b1N0cmluZygpIHsKICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5ldy1jYXAKICAgICAgICAgICAgcmV0dXJuIFN0cmluZ0Z1bmN0aW9ucy5zdHJpbmdpZnlKU09OV2l0aEZpeGVkUHJlY2lzaW9uKHRoaXMudG9KU09OKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdG9KU09OIG1ldGhvZCBlbmNvZGVzIHRoaXMgdHlwZSBhcyBhIGpzb24gb2JqZWN0IGZvciBwZXJzaXN0ZW5jZS4KICAgICAgICAgKgogICAgICAgICAqLwogICAgICAgIHRvSlNPTigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuYXNBcnJheSgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIGRlY29kZXMgYSBqc29uIG9iamVjdCBmb3IgdGhpcyB0eXBlLgogICAgICAgICAqCiAgICAgICAgICovCiAgICAgICAgZnJvbUpTT04oanNvbikgewogICAgICAgICAgICB0aGlzLmZyb21BcnJheShqc29uKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogTG9hZHMgdGhlIHN0YXRlIG9mIHRoZSB2YWx1ZSBmcm9tIGEgYmluYXJ5IHJlYWRlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSByZWFkZXIgLSBUaGUgcmVhZGVyIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyKSB7CiAgICAgICAgICAgIHRoaXMuZnJvbUFycmF5KHJlYWRlci5sb2FkRmxvYXQzMkFycmF5KDE2KSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgY3VycmVudCBNYXRoIHR5cGUgZGF0YSBhcyBhcnJheS4gT2Z0ZW4gdXNlZCB0byBwYXNzIHR5cGVzIHRvIHRoZSBHUFUuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgcmVzdWx0IGFzIGFuIGFycmF5LgogICAgICAgICAqLwogICAgICAgIGFzQXJyYXkoKSB7CiAgICAgICAgICAgIHJldHVybiBbCiAgICAgICAgICAgICAgICB0aGlzLm0wMCwKICAgICAgICAgICAgICAgIHRoaXMubTAxLAogICAgICAgICAgICAgICAgdGhpcy5tMDIsCiAgICAgICAgICAgICAgICB0aGlzLm0wMywKICAgICAgICAgICAgICAgIHRoaXMubTEwLAogICAgICAgICAgICAgICAgdGhpcy5tMTEsCiAgICAgICAgICAgICAgICB0aGlzLm0xMiwKICAgICAgICAgICAgICAgIHRoaXMubTEzLAogICAgICAgICAgICAgICAgdGhpcy5tMjAsCiAgICAgICAgICAgICAgICB0aGlzLm0yMSwKICAgICAgICAgICAgICAgIHRoaXMubTIyLAogICAgICAgICAgICAgICAgdGhpcy5tMjMsCiAgICAgICAgICAgICAgICB0aGlzLm0zMCwKICAgICAgICAgICAgICAgIHRoaXMubTMxLAogICAgICAgICAgICAgICAgdGhpcy5tMzIsCiAgICAgICAgICAgICAgICB0aGlzLm0zMywKICAgICAgICAgICAgXTsKICAgICAgICB9CiAgICAgICAgZnJvbUFycmF5KGFycmF5KSB7CiAgICAgICAgICAgIHRoaXMubTAwID0gYXJyYXlbMF07CiAgICAgICAgICAgIHRoaXMubTAxID0gYXJyYXlbMV07CiAgICAgICAgICAgIHRoaXMubTAyID0gYXJyYXlbMl07CiAgICAgICAgICAgIHRoaXMubTAzID0gYXJyYXlbM107CiAgICAgICAgICAgIHRoaXMubTEwID0gYXJyYXlbNF07CiAgICAgICAgICAgIHRoaXMubTExID0gYXJyYXlbNV07CiAgICAgICAgICAgIHRoaXMubTEyID0gYXJyYXlbNl07CiAgICAgICAgICAgIHRoaXMubTEzID0gYXJyYXlbN107CiAgICAgICAgICAgIHRoaXMubTIwID0gYXJyYXlbOF07CiAgICAgICAgICAgIHRoaXMubTIxID0gYXJyYXlbOV07CiAgICAgICAgICAgIHRoaXMubTIyID0gYXJyYXlbMTBdOwogICAgICAgICAgICB0aGlzLm0yMyA9IGFycmF5WzExXTsKICAgICAgICAgICAgdGhpcy5tMzAgPSBhcnJheVsxMl07CiAgICAgICAgICAgIHRoaXMubTMxID0gYXJyYXlbMTNdOwogICAgICAgICAgICB0aGlzLm0zMiA9IGFycmF5WzE0XTsKICAgICAgICAgICAgdGhpcy5tMzMgPSBhcnJheVsxNV07CiAgICAgICAgfQogICAgfQoKICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLXVudXNlZC12YXJzICovCiAgICAvKioKICAgICAqIENsYXNzIHJlcHJlc2VudGluZyBhIHF1YXRlcm5pb24uIFF1YXRlcm5pb25zIGFyZSB1c2VkIHRvIHJlcHJlc2VudCAzIGRpbWVuc2lvbmFsIHJvdGF0aW9ucy4KICAgICAqCiAgICAgKiBXaGlsZSBRdWF0ZXJuaW9ucyBhcmUgZGlmZmljdWx0IHRvIHVuZGVyc3RhbmQgdGhleSBoYXZlIGltcG9ydGFudCBtYXRoZW1hdGljYWwgcHJvcGVydGllcyB0aGF0IG1ha2UgdGhlbSB2ZXJ5IHVzZWZ1bCBpbiAzZCBlbmdpbmVzLgogICAgICogVGhleSBjYW4gYmUgZGlyZWN0bHkgbXVsdGlwbGllZCB0b2dldGhlciBpbiB0aGUgc2FtZSB3YXMgYXMgbWF0cmljZXMuCiAgICAgKiBUaGV5IGNhbiBiZSBpbnRlcnBvbGF0ZWQgZnJvbSBvbmUgdmFsdWUgdG8gYW5vdGhlciB3aGlsZSBtYWludGFpbmluZyBjb25zdGFudCBhbmd1bGFyIHZlbG9jaXR5LgogICAgICogVGhleSBjYW4gYmUgY29udmVydGVkIHRvIG90aGVyIG1vcmUgZWFzaWx5IHVuZGVyc3Rvb2QgcmVwcmVzZW50YXRpb25zIHN1Y2ggYXMgRXVsZXJBbmdsZXMgb3IgTWF0cmljZXMuCiAgICAgKgoKICAgICAqLwogICAgY2xhc3MgUXVhdCB7CiAgICAgICAgeDsKICAgICAgICB5OwogICAgICAgIHo7CiAgICAgICAgdzsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGEgcXVhdGVybmlvbi4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3Rvcih4ID0gMCwgeSA9IDAsIHogPSAwLCB3ID0gMSkgewogICAgICAgICAgICB0aGlzLnggPSB4OwogICAgICAgICAgICB0aGlzLnkgPSB5OwogICAgICAgICAgICB0aGlzLnogPSB6OwogICAgICAgICAgICB0aGlzLncgPSB3OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXR0ZXIgZnJvbSBzY2FsYXIgY29tcG9uZW50cy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSB4IC0gVGhlIHggYXhpcyByb3RhdGlvbi4KICAgICAgICAgKiBAcGFyYW0geSAgLSBUaGUgeSBheGlzIHJvdGF0aW9uLgogICAgICAgICAqIEBwYXJhbSB6ICAtIFRoZSB6IGF4aXMgcm90YXRpb24uCiAgICAgICAgICogQHBhcmFtIHcgIC0gVGhlIHcgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0KHgsIHksIHosIHcpIHsKICAgICAgICAgICAgdGhpcy54ID0geDsKICAgICAgICAgICAgdGhpcy55ID0geTsKICAgICAgICAgICAgdGhpcy56ID0gejsKICAgICAgICAgICAgdGhpcy53ID0gdzsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0dGVyIGZyb20gYW5vdGhlciB2ZWN0b3IuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgdmVjdG9yIHRvIHNldCBmcm9tLgogICAgICAgICAqLwogICAgICAgIHNldEZyb21PdGhlcihvdGhlcikgewogICAgICAgICAgICB0aGlzLnggPSBvdGhlci54OwogICAgICAgICAgICB0aGlzLnkgPSBvdGhlci55OwogICAgICAgICAgICB0aGlzLnogPSBvdGhlci56OwogICAgICAgICAgICB0aGlzLncgPSBvdGhlci53OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXQgdGhpcyBRdWF0IGZyb20gYSBldWxlciByb3RhdGlvbi4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBldWxlckFuZ2xlcyAtIFRoZSBldWxlciBhbmdsZXMgcm90YXRpb24uCiAgICAgICAgICovCiAgICAgICAgc2V0RnJvbUV1bGVyQW5nbGVzKGV1bGVyQW5nbGVzKSB7CiAgICAgICAgICAgIGNvbnN0IG9yZGVyZWQgPSBuZXcgVmVjMygpOwogICAgICAgICAgICBzd2l0Y2ggKGV1bGVyQW5nbGVzLm9yZGVyKSB7CiAgICAgICAgICAgICAgICBjYXNlIEV1bGVyQW5nbGVzQXhpc09yZGVyLlhZWjoKICAgICAgICAgICAgICAgICAgICBvcmRlcmVkLnNldChldWxlckFuZ2xlcy54LCAtZXVsZXJBbmdsZXMueSwgZXVsZXJBbmdsZXMueik7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIEV1bGVyQW5nbGVzQXhpc09yZGVyLllaWDoKICAgICAgICAgICAgICAgICAgICBvcmRlcmVkLnNldChldWxlckFuZ2xlcy55LCAtZXVsZXJBbmdsZXMueiwgZXVsZXJBbmdsZXMueCk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIEV1bGVyQW5nbGVzQXhpc09yZGVyLlpYWToKICAgICAgICAgICAgICAgICAgICBvcmRlcmVkLnNldChldWxlckFuZ2xlcy56LCAtZXVsZXJBbmdsZXMueCwgZXVsZXJBbmdsZXMueSk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIEV1bGVyQW5nbGVzQXhpc09yZGVyLlhaWToKICAgICAgICAgICAgICAgICAgICBvcmRlcmVkLnNldChldWxlckFuZ2xlcy54LCBldWxlckFuZ2xlcy56LCBldWxlckFuZ2xlcy55KTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgRXVsZXJBbmdsZXNBeGlzT3JkZXIuWllYOgogICAgICAgICAgICAgICAgICAgIG9yZGVyZWQuc2V0KGV1bGVyQW5nbGVzLnosIGV1bGVyQW5nbGVzLnksIGV1bGVyQW5nbGVzLngpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSBFdWxlckFuZ2xlc0F4aXNPcmRlci5ZWFo6CiAgICAgICAgICAgICAgICAgICAgb3JkZXJlZC5zZXQoZXVsZXJBbmdsZXMueSwgZXVsZXJBbmdsZXMueCwgZXVsZXJBbmdsZXMueik7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBFdWxlckFuZ2xlcyBvcmRlcjogJHtldWxlckFuZ2xlcy5vcmRlcn1gKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCB0aSA9IG9yZGVyZWQueCAqIDAuNTsKICAgICAgICAgICAgY29uc3QgdGogPSBvcmRlcmVkLnkgKiAwLjU7CiAgICAgICAgICAgIGNvbnN0IHRrID0gb3JkZXJlZC56ICogMC41OwogICAgICAgICAgICBjb25zdCBjaSA9IE1hdGguY29zKHRpKTsKICAgICAgICAgICAgY29uc3QgY2ogPSBNYXRoLmNvcyh0aik7CiAgICAgICAgICAgIGNvbnN0IGNrID0gTWF0aC5jb3ModGspOwogICAgICAgICAgICBjb25zdCBzaSA9IE1hdGguc2luKHRpKTsKICAgICAgICAgICAgY29uc3Qgc2ogPSBNYXRoLnNpbih0aik7CiAgICAgICAgICAgIGNvbnN0IHNrID0gTWF0aC5zaW4odGspOwogICAgICAgICAgICBjb25zdCBjYyA9IGNpICogY2s7CiAgICAgICAgICAgIGNvbnN0IGNzID0gY2kgKiBzazsKICAgICAgICAgICAgY29uc3Qgc2MgPSBzaSAqIGNrOwogICAgICAgICAgICBjb25zdCBzcyA9IHNpICogc2s7CiAgICAgICAgICAgIGNvbnN0IGFpID0gY2ogKiBzYyAtIHNqICogY3M7CiAgICAgICAgICAgIGNvbnN0IGFqID0gY2ogKiBzcyArIHNqICogY2M7CiAgICAgICAgICAgIGNvbnN0IGFrID0gY2ogKiBjcyAtIHNqICogc2M7CiAgICAgICAgICAgIHRoaXMudyA9IGNqICogY2MgKyBzaiAqIHNzOwogICAgICAgICAgICBzd2l0Y2ggKGV1bGVyQW5nbGVzLm9yZGVyKSB7CiAgICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICAgICAgLy8gJyBYWVonCiAgICAgICAgICAgICAgICAgICAgdGhpcy54ID0gYWk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy55ID0gLWFqOwogICAgICAgICAgICAgICAgICAgIHRoaXMueiA9IGFrOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgICAgIC8vICdZWlgnCiAgICAgICAgICAgICAgICAgICAgdGhpcy54ID0gYWs7CiAgICAgICAgICAgICAgICAgICAgdGhpcy55ID0gYWk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy56ID0gLWFqOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgICAgIC8vICdaWFknCiAgICAgICAgICAgICAgICAgICAgdGhpcy54ID0gLWFqOwogICAgICAgICAgICAgICAgICAgIHRoaXMueSA9IGFrOwogICAgICAgICAgICAgICAgICAgIHRoaXMueiA9IGFpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICAgICAgICAgIC8vICdYWlknCiAgICAgICAgICAgICAgICAgICAgdGhpcy54ID0gYWk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy55ID0gYWs7CiAgICAgICAgICAgICAgICAgICAgdGhpcy56ID0gYWo7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDQ6CiAgICAgICAgICAgICAgICAgICAgLy8gJ1pZWCcKICAgICAgICAgICAgICAgICAgICB0aGlzLnggPSBhazsKICAgICAgICAgICAgICAgICAgICB0aGlzLnkgPSBhajsKICAgICAgICAgICAgICAgICAgICB0aGlzLnogPSBhaTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgNToKICAgICAgICAgICAgICAgICAgICAvLyAnWVhaJwogICAgICAgICAgICAgICAgICAgIHRoaXMueCA9IGFqOwogICAgICAgICAgICAgICAgICAgIHRoaXMueSA9IGFpOwogICAgICAgICAgICAgICAgICAgIHRoaXMueiA9IGFrOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgRXVsZXJBbmdsZXMgb3JkZXI6ICR7ZXVsZXJBbmdsZXMub3JkZXJ9YCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ29udmVydHMgUXVhdCB0byBhbiBFdWxlckFuZ2xlcwogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHJvdGF0aW9uT3JkZXIgLSBUaGUgb3JkZXIgaW4gd2hpY2ggdGhlIHJvdGF0aW9ucyBhcmUgYXBwbGllZC4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICB0b0V1bGVyQW5nbGVzKHJvdGF0aW9uT3JkZXIpIHsKICAgICAgICAgICAgY29uc3Qgb3JkZXJlZCA9IG5ldyBWZWMzKCk7CiAgICAgICAgICAgIHN3aXRjaCAocm90YXRpb25PcmRlcikgewogICAgICAgICAgICAgICAgY2FzZSBFdWxlckFuZ2xlc0F4aXNPcmRlci5YWVo6CiAgICAgICAgICAgICAgICBjYXNlICdYWVonOgogICAgICAgICAgICAgICAgICAgIG9yZGVyZWQuc2V0KHRoaXMueiwgdGhpcy54LCB0aGlzLnkpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSBFdWxlckFuZ2xlc0F4aXNPcmRlci5ZWlg6CiAgICAgICAgICAgICAgICBjYXNlICdZWlgnOgogICAgICAgICAgICAgICAgICAgIG9yZGVyZWQuc2V0KHRoaXMueCwgdGhpcy55LCB0aGlzLnopOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSBFdWxlckFuZ2xlc0F4aXNPcmRlci5aWFk6CiAgICAgICAgICAgICAgICBjYXNlICdaWFknOgogICAgICAgICAgICAgICAgICAgIG9yZGVyZWQuc2V0KHRoaXMueSwgdGhpcy56LCB0aGlzLngpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSBFdWxlckFuZ2xlc0F4aXNPcmRlci5YWlk6CiAgICAgICAgICAgICAgICBjYXNlICdYWlknOgogICAgICAgICAgICAgICAgICAgIG9yZGVyZWQuc2V0KHRoaXMueSwgLXRoaXMueCwgdGhpcy56KTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgRXVsZXJBbmdsZXNBeGlzT3JkZXIuWllYOgogICAgICAgICAgICAgICAgY2FzZSAnWllYJzoKICAgICAgICAgICAgICAgICAgICBvcmRlcmVkLnNldCh0aGlzLngsIC10aGlzLnosIHRoaXMueSk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIEV1bGVyQW5nbGVzQXhpc09yZGVyLllYWjoKICAgICAgICAgICAgICAgIGNhc2UgJ1lYWic6CiAgICAgICAgICAgICAgICAgICAgb3JkZXJlZC5zZXQodGhpcy56LCAtdGhpcy55LCB0aGlzLngpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcm90YXRpb24gb3JkZXI6JyArIHJvdGF0aW9uT3JkZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGV1bGVyID0gbmV3IFZlYzMoKTsKICAgICAgICAgICAgY29uc3QgdGVzdCA9IG9yZGVyZWQueCAqIG9yZGVyZWQueSArIG9yZGVyZWQueiAqIHRoaXMudzsKICAgICAgICAgICAgaWYgKHRlc3QgPiAwLjQ5OTk5KSB7CiAgICAgICAgICAgICAgICAvLyBzaW5ndWxhcml0eSBhdCBub3J0aCBwb2xlCiAgICAgICAgICAgICAgICBldWxlci55ID0gMi4wICogTWF0aC5hdGFuMihvcmRlcmVkLngsIHRoaXMudyk7CiAgICAgICAgICAgICAgICBldWxlci56ID0gTWF0aC5QSSAqIDAuNTsKICAgICAgICAgICAgICAgIGV1bGVyLnggPSAwLjA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAodGVzdCA8IC0wLjQ5OTk5KSB7CiAgICAgICAgICAgICAgICAvLyBzaW5ndWxhcml0eSBhdCBzb3V0aCBwb2xlCiAgICAgICAgICAgICAgICBldWxlci55ID0gLTIuMCAqIE1hdGguYXRhbjIob3JkZXJlZC54LCB0aGlzLncpOwogICAgICAgICAgICAgICAgZXVsZXIueiA9IE1hdGguUEkgKiAtMC41OwogICAgICAgICAgICAgICAgZXVsZXIueCA9IDAuMDsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIGNvbnN0IHNxeCA9IG9yZGVyZWQueCAqIG9yZGVyZWQueDsKICAgICAgICAgICAgICAgIGNvbnN0IHNxeSA9IG9yZGVyZWQueSAqIG9yZGVyZWQueTsKICAgICAgICAgICAgICAgIGNvbnN0IHNxeiA9IG9yZGVyZWQueiAqIG9yZGVyZWQuejsKICAgICAgICAgICAgICAgIGV1bGVyLnkgPSBNYXRoLmF0YW4yKDIuMCAqIG9yZGVyZWQueSAqIHRoaXMudyAtIDIuMCAqIG9yZGVyZWQueCAqIG9yZGVyZWQueiwgMS4wIC0gMi4wICogc3F5IC0gMi4wICogc3F6KTsKICAgICAgICAgICAgICAgIGV1bGVyLnogPSBNYXRoLmFzaW4oMi4wICogdGVzdCk7CiAgICAgICAgICAgICAgICBldWxlci54ID0gTWF0aC5hdGFuMigyLjAgKiBvcmRlcmVkLnggKiB0aGlzLncgLSAyLjAgKiBvcmRlcmVkLnkgKiBvcmRlcmVkLnosIDEuMCAtIDIuMCAqIHNxeCAtIDIuMCAqIHNxeik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3dpdGNoIChyb3RhdGlvbk9yZGVyKSB7CiAgICAgICAgICAgICAgICBjYXNlIEV1bGVyQW5nbGVzQXhpc09yZGVyLlhZWjoKICAgICAgICAgICAgICAgIGNhc2UgJ1hZWic6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdWxlckFuZ2xlcyhldWxlci55LCBldWxlci56LCBldWxlci54LCByb3RhdGlvbk9yZGVyKTsKICAgICAgICAgICAgICAgIGNhc2UgRXVsZXJBbmdsZXNBeGlzT3JkZXIuWVpYOgogICAgICAgICAgICAgICAgY2FzZSAnWVpYJzoKICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV1bGVyQW5nbGVzKGV1bGVyLngsIGV1bGVyLnksIGV1bGVyLnosIHJvdGF0aW9uT3JkZXIpOwogICAgICAgICAgICAgICAgY2FzZSBFdWxlckFuZ2xlc0F4aXNPcmRlci5aWFk6CiAgICAgICAgICAgICAgICBjYXNlICdaWFknOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXVsZXJBbmdsZXMoZXVsZXIueiwgZXVsZXIueCwgZXVsZXIueSwgcm90YXRpb25PcmRlcik7CiAgICAgICAgICAgICAgICBjYXNlIEV1bGVyQW5nbGVzQXhpc09yZGVyLlhaWToKICAgICAgICAgICAgICAgIGNhc2UgJ1haWSc6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdWxlckFuZ2xlcygtZXVsZXIueSwgZXVsZXIueCwgZXVsZXIueiwgcm90YXRpb25PcmRlcik7CiAgICAgICAgICAgICAgICBjYXNlIEV1bGVyQW5nbGVzQXhpc09yZGVyLlpZWDoKICAgICAgICAgICAgICAgIGNhc2UgJ1pZWCc6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdWxlckFuZ2xlcyhldWxlci54LCBldWxlci56LCAtZXVsZXIueSwgcm90YXRpb25PcmRlcik7CiAgICAgICAgICAgICAgICBjYXNlIEV1bGVyQW5nbGVzQXhpc09yZGVyLllYWjoKICAgICAgICAgICAgICAgIGNhc2UgJ1lYWic6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdWxlckFuZ2xlcyhldWxlci56LCAtZXVsZXIueSwgZXVsZXIueCwgcm90YXRpb25PcmRlcik7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0IHRoaXMgUXVhdCB0byBhIHJvdGF0aW9uIGRlZmluZWQgYnkgYW4gYXhpcyBhbmQgYW4gYW5nbGUgKGluIHJhZGlhbnMpLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGF4aXMgLSBUaGUgYXhpcyBhcm91bmQgd2hpY2ggdG8gcm90YXRlLgogICAgICAgICAqIEBwYXJhbSBhbmdsZSAtIFRoZSBhbmdsZSB0byByb3RhdGUKICAgICAgICAgKi8KICAgICAgICBzZXRGcm9tQXhpc0FuZEFuZ2xlKGF4aXMsIGFuZ2xlKSB7CiAgICAgICAgICAgIGNvbnN0IGhhbGZBbmdsZSA9IGFuZ2xlIC8gMi4wOwogICAgICAgICAgICBjb25zdCB2ZWMgPSBheGlzLm5vcm1hbGl6ZSgpLnNjYWxlKE1hdGguc2luKGhhbGZBbmdsZSkpOwogICAgICAgICAgICB0aGlzLnNldCh2ZWMueCwgdmVjLnksIHZlYy56LCBNYXRoLmNvcyhoYWxmQW5nbGUpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB0aGUgc3RhdGUgb2YgdGhlIFF1YXQgdG8gbG9vayBpbiBhIHBhcnRpY3VsYXIgZGlyZWN0aW9uIGFsb25nIHRoZSB6IGF4aXMuCiAgICAgICAgICogPiBUaGUgY2FtZXJhIGxvb2tzIGRvd24gdGhlIG5lZ2F0aXZlIHogYXhpcywgc28gdG8gc2V0IGEgcm90YXRpb24gdmFsdWUKICAgICAgICAgKiA+IGZvciB0aGUgY2FtZXJhLCByZW1lbWJlciB0byBuZWdhdGUgdGhlIGRpcmVjdGlvbiB2ZWN0b3IuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gZGlyIC0gVGhlIGRpcmVjdGlvbiB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gdXAgLSBUaGUgdXAgdmVjdG9yLgogICAgICAgICAqLwogICAgICAgIHNldEZyb21EaXJlY3Rpb25BbmRVcHZlY3RvcihkaXIsIHVwKSB7CiAgICAgICAgICAgIGNvbnN0IG1hdDMgPSBuZXcgTWF0MygpOwogICAgICAgICAgICBtYXQzLnNldEZyb21EaXJlY3Rpb25BbmRVcHZlY3RvcihkaXIsIHVwKTsKICAgICAgICAgICAgdGhpcy5zZXRGcm9tTWF0MyhtYXQzKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB0aGUgc3RhdGUgb2YgdGhlIGBRdWF0YCBmcm9tIHR3byBgVmVjM2AuIFRoZSBxdWF0ZXJuaW9uIHdvdWxkIHRoZW4gcmVwcmVzZW50IHRoZSByb3RhdGlvbiBmcm9tIHYwIHRvIHYxIGluIDNkIHNwYWNlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHYwIC0gVGhlIHYwIHVuaXQgdmVjdG9yLgogICAgICAgICAqIEBwYXJhbSB2MSAtIFRoZSB2MSB1bml0IHZlY3Rvci4KICAgICAgICAgKi8KICAgICAgICBzZXRGcm9tMlZlY3RvcnModjAsIHYxKSB7CiAgICAgICAgICAgIGNvbnN0IGMgPSB2MC5jcm9zcyh2MSk7CiAgICAgICAgICAgIGNvbnN0IGQgPSB2MC5kb3QodjEpOwogICAgICAgICAgICBjb25zdCBzID0gTWF0aC5zcXJ0KCgxICsgZCkgKiAyKTsKICAgICAgICAgICAgLy8gdGhpcy5zZXQoIHMvMiwgYy54IC8gcywgYy55IC8gcywgYy56IC8gcyApOwogICAgICAgICAgICB0aGlzLnNldChjLnggLyBzLCBjLnkgLyBzLCBjLnogLyBzLCBzIC8gMik7CiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplSW5QbGFjZSgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXQgdGhlIFF1YXQgZnJvbSBhIE1hdDMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbWF0MyAtIFRoZSBtYXQzIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldEZyb21NYXQzKG1hdDMpIHsKICAgICAgICAgICAgLy8gQWxnb3JpdGhtIGluIEtlbiBTaG9lbWFrZSdzIGFydGljbGUgaW4gMTk4NyBTSUdHUkFQSCBjb3Vyc2Ugbm90ZXMKICAgICAgICAgICAgLy8gYXJ0aWNsZSAiUXVhdGVybmlvbiBDYWxjdWx1cyBhbmQgRmFzdCBBbmltYXRpb24iLgogICAgICAgICAgICBjb25zdCBkYXRhID0gbWF0My5hc0FycmF5KCk7CiAgICAgICAgICAgIGNvbnN0IGZUcmFjZSA9IGRhdGFbMF0gKyBkYXRhWzRdICsgZGF0YVs4XTsKICAgICAgICAgICAgbGV0IGZSb290OwogICAgICAgICAgICBpZiAoZlRyYWNlID4gMC4wKSB7CiAgICAgICAgICAgICAgICAvLyB8d3wgPiAxLzIsIG1heSBhcyB3ZWxsIGNob29zZSB3ID4gMS8yCiAgICAgICAgICAgICAgICBmUm9vdCA9IE1hdGguc3FydChmVHJhY2UgKyAxKTsgLy8gMncKICAgICAgICAgICAgICAgIHRoaXMudyA9IDAuNSAqIGZSb290OwogICAgICAgICAgICAgICAgZlJvb3QgPSAwLjUgLyBmUm9vdDsgLy8gMS8oNHcpCiAgICAgICAgICAgICAgICB0aGlzLnggPSAoZGF0YVs1XSAtIGRhdGFbN10pICogZlJvb3Q7CiAgICAgICAgICAgICAgICB0aGlzLnkgPSAoZGF0YVs2XSAtIGRhdGFbMl0pICogZlJvb3Q7CiAgICAgICAgICAgICAgICB0aGlzLnogPSAoZGF0YVsxXSAtIGRhdGFbM10pICogZlJvb3Q7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAvLyB8d3wgPD0gMS8yCiAgICAgICAgICAgICAgICBsZXQgaSA9IDA7CiAgICAgICAgICAgICAgICBpZiAoZGF0YVs0XSA+IGRhdGFbMF0pCiAgICAgICAgICAgICAgICAgICAgaSA9IDE7CiAgICAgICAgICAgICAgICBpZiAoZGF0YVs4XSA+IGRhdGFbaSAqIDMgKyBpXSkKICAgICAgICAgICAgICAgICAgICBpID0gMjsKICAgICAgICAgICAgICAgIGNvbnN0IGogPSAoaSArIDEpICUgMzsKICAgICAgICAgICAgICAgIGNvbnN0IGsgPSAoaSArIDIpICUgMzsKICAgICAgICAgICAgICAgIGZSb290ID0gTWF0aC5zcXJ0KGRhdGFbaSAqIDMgKyBpXSAtIGRhdGFbaiAqIDMgKyBqXSAtIGRhdGFbayAqIDMgKyBrXSArIDEuMCk7CiAgICAgICAgICAgICAgICBjb25zdCBhcnJheSA9IFswLCAwLCAwLCAwXTsKICAgICAgICAgICAgICAgIGFycmF5W2ldID0gMC41ICogZlJvb3Q7CiAgICAgICAgICAgICAgICBmUm9vdCA9IDAuNSAvIGZSb290OwogICAgICAgICAgICAgICAgYXJyYXlbM10gPSAoZGF0YVtqICogMyArIGtdIC0gZGF0YVtrICogMyArIGpdKSAqIGZSb290OwogICAgICAgICAgICAgICAgYXJyYXlbal0gPSAoZGF0YVtqICogMyArIGldICsgZGF0YVtpICogMyArIGpdKSAqIGZSb290OwogICAgICAgICAgICAgICAgYXJyYXlba10gPSAoZGF0YVtrICogMyArIGldICsgZGF0YVtpICogMyArIGtdKSAqIGZSb290OwogICAgICAgICAgICAgICAgdGhpcy5mcm9tQXJyYXkoYXJyYXkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplSW5QbGFjZSgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXQgdGhlIFF1YXQgZnJvbSBhIE1hdDQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbWF0NCAtIFRoZSBtYXQ0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldEZyb21NYXQ0KG1hdDQpIHsKICAgICAgICAgICAgLy8gQWxnb3JpdGhtIGluIEtlbiBTaG9lbWFrZSdzIGFydGljbGUgaW4gMTk4NyBTSUdHUkFQSCBjb3Vyc2Ugbm90ZXMKICAgICAgICAgICAgLy8gYXJ0aWNsZSAiUXVhdGVybmlvbiBDYWxjdWx1cyBhbmQgRmFzdCBBbmltYXRpb24iLgogICAgICAgICAgICBjb25zdCBkYXRhID0gbWF0NC5hc0FycmF5KCk7CiAgICAgICAgICAgIGNvbnN0IGZUcmFjZSA9IGRhdGFbMF0gKyBkYXRhWzVdICsgZGF0YVsxMF07CiAgICAgICAgICAgIGxldCBmUm9vdDsKICAgICAgICAgICAgaWYgKGZUcmFjZSA+IDAuMCkgewogICAgICAgICAgICAgICAgLy8gfHd8ID4gMS8yLCBtYXkgYXMgd2VsbCBjaG9vc2UgdyA+IDEvMgogICAgICAgICAgICAgICAgZlJvb3QgPSBNYXRoLnNxcnQoZlRyYWNlICsgMSk7IC8vIDJ3CiAgICAgICAgICAgICAgICB0aGlzLncgPSAwLjUgKiBmUm9vdDsKICAgICAgICAgICAgICAgIGZSb290ID0gMC41IC8gZlJvb3Q7IC8vIDEvKDR3KQogICAgICAgICAgICAgICAgdGhpcy54ID0gKGRhdGFbNl0gLSBkYXRhWzldKSAqIGZSb290OwogICAgICAgICAgICAgICAgdGhpcy55ID0gKGRhdGFbOF0gLSBkYXRhWzJdKSAqIGZSb290OwogICAgICAgICAgICAgICAgdGhpcy56ID0gKGRhdGFbMV0gLSBkYXRhWzRdKSAqIGZSb290OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgLy8gfHd8IDw9IDEvMgogICAgICAgICAgICAgICAgbGV0IGkgPSAwOwogICAgICAgICAgICAgICAgaWYgKGRhdGFbNV0gPiBkYXRhWzBdKQogICAgICAgICAgICAgICAgICAgIGkgPSAxOwogICAgICAgICAgICAgICAgaWYgKGRhdGFbMTBdID4gZGF0YVtpICogNCArIGldKQogICAgICAgICAgICAgICAgICAgIGkgPSAyOwogICAgICAgICAgICAgICAgY29uc3QgaiA9IChpICsgMSkgJSAzOwogICAgICAgICAgICAgICAgY29uc3QgayA9IChpICsgMikgJSAzOwogICAgICAgICAgICAgICAgZlJvb3QgPSBNYXRoLnNxcnQoZGF0YVtpICogNCArIGldIC0gZGF0YVtqICogNCArIGpdIC0gZGF0YVtrICogNCArIGtdICsgMS4wKTsKICAgICAgICAgICAgICAgIGNvbnN0IGFycmF5ID0gWzAsIDAsIDAsIDBdOwogICAgICAgICAgICAgICAgYXJyYXlbaV0gPSAwLjUgKiBmUm9vdDsKICAgICAgICAgICAgICAgIGZSb290ID0gMC41IC8gZlJvb3Q7CiAgICAgICAgICAgICAgICBhcnJheVszXSA9IChkYXRhW2ogKiA0ICsga10gLSBkYXRhW2sgKiA0ICsgal0pICogZlJvb3Q7CiAgICAgICAgICAgICAgICBhcnJheVtqXSA9IChkYXRhW2ogKiA0ICsgaV0gKyBkYXRhW2kgKiA0ICsgal0pICogZlJvb3Q7CiAgICAgICAgICAgICAgICBhcnJheVtrXSA9IChkYXRhW2sgKiA0ICsgaV0gKyBkYXRhW2kgKiA0ICsga10pICogZlJvb3Q7CiAgICAgICAgICAgICAgICB0aGlzLmZyb21BcnJheShhcnJheSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVJblBsYWNlKCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENoZWNrcyBpZiB0aGUgYW5nbGUgb2YgdGhlIFF1YXQgaXMgbGVzcyB0aGF0IGAgTnVtYmVyLkVQU0lMT05gCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0cnVlIG9yIGZhbHNlLgogICAgICAgICAqLwogICAgICAgIGlzSWRlbnRpdHkoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEFuZ2xlKCkgPCBOdW1iZXIuRVBTSUxPTjsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJuIHRoZSBhbmdsZSBvZiB0aGUgUXVhdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldEFuZ2xlKCkgewogICAgICAgICAgICByZXR1cm4gTWF0aC5hY29zKHRoaXMudykgKiAyLjA7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENoZWNrcyBpZiB0aGlzIFF1YXQgY29udGFpbnMgdGhlIHNhbWUgdmFsdWVzIGFzIHRoZSBvdGhlciBRdWF0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFF1YXQgdG8gY29tcGFyZSB3aXRoLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGB0cnVlYCBpZiBhcmUgdGhlIHNhbWUgVmVjdG9yLCBvdGhlcndpc2UsIGBmYWxzZWAuCiAgICAgICAgICovCiAgICAgICAgaXNFcXVhbChvdGhlcikgewogICAgICAgICAgICByZXR1cm4gdGhpcy54ID09IG90aGVyLnggJiYgdGhpcy55ID09IG90aGVyLnkgJiYgdGhpcy56ID09IG90aGVyLnogJiYgdGhpcy53ID09IG90aGVyLnc7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIFF1YXQgaXMgTk9UIGV4YWN0bHkgdGhlIHNhbWUgb3RoZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgUXVhdCB0byBjb21wYXJlIHdpdGguCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdHJ1ZSBvciBmYWxzZS4KICAgICAgICAgKi8KICAgICAgICBub3RFcXVhbHMob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMueCAhPSBvdGhlci54ICYmIHRoaXMueSAhPSBvdGhlci55ICYmIHRoaXMueiAhPSBvdGhlci56ICYmIHRoaXMudyAhPSBvdGhlci53OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBRdWF0IGlzIGFwcHJveGltYXRlbHkgdGhlIHNhbWUgYXMgb3RoZXIKICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBRdWF0IHRvIGNvbXBhcmUgd2l0aC4KICAgICAgICAgKiBAcGFyYW0gcHJlY2lzaW9uIC0gVGhlIHByZWNpc2lvbiB0byB3aGljaCB0aGUgdmFsdWVzIG11c3QgbWF0Y2guCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdHJ1ZSBvciBmYWxzZS4KICAgICAgICAgKi8KICAgICAgICBhcHByb3hFcXVhbChvdGhlciwgcHJlY2lzaW9uID0gTnVtYmVyLkVQU0lMT04pIHsKICAgICAgICAgICAgcmV0dXJuIChNYXRoLmFicyh0aGlzLnggLSBvdGhlci54KSA8IHByZWNpc2lvbiAmJgogICAgICAgICAgICAgICAgTWF0aC5hYnModGhpcy55IC0gb3RoZXIueSkgPCBwcmVjaXNpb24gJiYKICAgICAgICAgICAgICAgIE1hdGguYWJzKHRoaXMueiAtIG90aGVyLnopIDwgcHJlY2lzaW9uICYmCiAgICAgICAgICAgICAgICBNYXRoLmFicyh0aGlzLncgLSBvdGhlci53KSA8IHByZWNpc2lvbik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEFkZHMgb3RoZXIgdG8gdGhpcyBRdWF0IGFuZCByZXR1cm4gdGhlIHJlc3VsdCBhcyBhIG5ldyBRdWF0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFF1YXQgdG8gYWRkLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFF1YXQuCiAgICAgICAgICovCiAgICAgICAgYWRkKG90aGVyKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgUXVhdCh0aGlzLnggKyBvdGhlci54LCB0aGlzLnkgKyBvdGhlci55LCB0aGlzLnogKyBvdGhlci56LCB0aGlzLncgKyBvdGhlci53KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQWRkcyBvdGhlciB0byB0aGlzIFF1YXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgUXVhdCB0byBhZGQuCiAgICAgICAgICovCiAgICAgICAgYWRkSW5QbGFjZShvdGhlcikgewogICAgICAgICAgICB0aGlzLnggKz0gb3RoZXIueDsKICAgICAgICAgICAgdGhpcy55ICs9IG90aGVyLnk7CiAgICAgICAgICAgIHRoaXMueiArPSBvdGhlci56OwogICAgICAgICAgICB0aGlzLncgKz0gb3RoZXIudzsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU3VidHJhY3RzIG90aGVyIGZyb20gdGhpcyBRdWF0IGFuZCByZXR1cm5zIHRoZSByZXN1bHQgYXMgYSBuZXcgUXVhdC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBRdWF0IHRvIHN1YnRyYWN0LgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFF1YXQuCiAgICAgICAgICovCiAgICAgICAgc3VidHJhY3Qob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBRdWF0KHRoaXMueCAtIG90aGVyLngsIHRoaXMueSAtIG90aGVyLnksIHRoaXMueiAtIG90aGVyLnosIHRoaXMudyAtIG90aGVyLncpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTY2FsZXMgdGhpcyBRdWF0IGJ5IHNjYWxhciBhbmQgcmV0dXJucyB0aGUgcmVzdWx0IGFzIGEgbmV3IFF1YXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc2NhbGFyIC0gVGhlIHNjYWxhciB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBWZWMzLgogICAgICAgICAqLwogICAgICAgIHNjYWxlKHNjYWxhcikgewogICAgICAgICAgICByZXR1cm4gbmV3IFF1YXQodGhpcy54ICogc2NhbGFyLCB0aGlzLnkgKiBzY2FsYXIsIHRoaXMueiAqIHNjYWxhciwgdGhpcy53ICogc2NhbGFyKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2NhbGVzIHRoaXMgUXVhdCBieSBzY2FsYXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc2NhbGFyIC0gVGhlIHNjYWxhciB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzY2FsZUluUGxhY2Uoc2NhbGFyKSB7CiAgICAgICAgICAgIHRoaXMueCAqPSBzY2FsYXI7CiAgICAgICAgICAgIHRoaXMueSAqPSBzY2FsYXI7CiAgICAgICAgICAgIHRoaXMueiAqPSBzY2FsYXI7CiAgICAgICAgICAgIHRoaXMudyAqPSBzY2FsYXI7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiB0aGlzIFF1YXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgbGVuZ3RoLgogICAgICAgICAqLwogICAgICAgIGxlbmd0aCgpIHsKICAgICAgICAgICAgY29uc3QgeCA9IHRoaXMueDsKICAgICAgICAgICAgY29uc3QgeSA9IHRoaXMueTsKICAgICAgICAgICAgY29uc3QgeiA9IHRoaXMuejsKICAgICAgICAgICAgY29uc3QgdyA9IHRoaXMudzsKICAgICAgICAgICAgcmV0dXJuIE1hdGguc3FydCh4ICogeCArIHkgKiB5ICsgeiAqIHogKyB3ICogdyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgbGVuZ3RoIG9mIHRoaXMgUXVhdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBsZW5ndGguCiAgICAgICAgICovCiAgICAgICAgbGVuZ3RoU3F1YXJlZCgpIHsKICAgICAgICAgICAgY29uc3QgeCA9IHRoaXMueDsKICAgICAgICAgICAgY29uc3QgeSA9IHRoaXMueTsKICAgICAgICAgICAgY29uc3QgeiA9IHRoaXMuejsKICAgICAgICAgICAgY29uc3QgdyA9IHRoaXMudzsKICAgICAgICAgICAgcmV0dXJuIHggKiB4ICsgeSAqIHkgKyB6ICogeiArIHcgKiB3OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBOb3JtYWxpemVzIHRoZSBRdWF0IGFuZCByZXR1cm5zIGl0IGFzIGEgbmV3IFF1YXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgUXVhdCBub3JtYWxpemVkLgogICAgICAgICAqLwogICAgICAgIG5vcm1hbGl6ZSgpIHsKICAgICAgICAgICAgY29uc3QgeCA9IHRoaXMueDsKICAgICAgICAgICAgY29uc3QgeSA9IHRoaXMueTsKICAgICAgICAgICAgY29uc3QgeiA9IHRoaXMuejsKICAgICAgICAgICAgY29uc3QgdyA9IHRoaXMudzsKICAgICAgICAgICAgbGV0IGxlbiA9IHggKiB4ICsgeSAqIHkgKyB6ICogeiArIHcgKiB3OwogICAgICAgICAgICBpZiAobGVuIDwgTnVtYmVyLkVQU0lMT04pIHsKICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUXVhdCgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIFRPRE86IGV2YWx1YXRlIHVzZSBvZiBnbG1faW52c3FydCBoZXJlPwogICAgICAgICAgICBsZW4gPSAxIC8gTWF0aC5zcXJ0KGxlbik7CiAgICAgICAgICAgIHJldHVybiBuZXcgUXVhdCh4ICogbGVuLCB5ICogbGVuLCB6ICogbGVuLCB3ICogbGVuKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogTm9ybWFsaXplcyB0aGUgUXVhdCwgbW9kaWZ5aW5nIGl0cyB2YWx1ZXMgaW4gcGxhY2UuCiAgICAgICAgICovCiAgICAgICAgbm9ybWFsaXplSW5QbGFjZSgpIHsKICAgICAgICAgICAgY29uc3QgeCA9IHRoaXMueDsKICAgICAgICAgICAgY29uc3QgeSA9IHRoaXMueTsKICAgICAgICAgICAgY29uc3QgeiA9IHRoaXMuejsKICAgICAgICAgICAgY29uc3QgdyA9IHRoaXMudzsKICAgICAgICAgICAgbGV0IGxlbiA9IHggKiB4ICsgeSAqIHkgKyB6ICogeiArIHcgKiB3OwogICAgICAgICAgICBpZiAobGVuIDwgTnVtYmVyLkVQU0lMT04pIHsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZW4gPSAxIC8gTWF0aC5zcXJ0KGxlbik7CiAgICAgICAgICAgIHRoaXMuc2V0KHggKiBsZW4sIHkgKiBsZW4sIHogKiBsZW4sIHcgKiBsZW4pOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDYWxjdWxhdGVzIHRoZSBkb3QgcHJvZHVjdCBvZiB0aGlzIHF1YXQgYWdhaW5zdCBhbm90aGVyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFF1YXQgdG8gY29tcGFyZSB3aXRoLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBkb3QgcHJvZHVjdC4KICAgICAgICAgKi8KICAgICAgICBkb3Qob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMueCAqIG90aGVyLnggKyB0aGlzLnkgKiBvdGhlci55ICsgdGhpcy56ICogb3RoZXIueiArIHRoaXMudyAqIG90aGVyLnc7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIGNyb3NzIHByb2R1Y3Qgb2YgdHdvIFF1YXRzIGFuZCByZXR1cm5zIHRoZSByZXN1bHQgYXMgYSBuZXcgUXVhdC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBRdWF0IHRvIGNhbGN1bGF0ZSB3aXRoLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBjcm9zcyBwcm9kdWN0IGFzIGEgbmV3IFF1YXQuCiAgICAgICAgICovCiAgICAgICAgY3Jvc3Mob3RoZXIpIHsKICAgICAgICAgICAgY29uc3QgYXggPSB0aGlzLng7CiAgICAgICAgICAgIGNvbnN0IGF5ID0gdGhpcy55OwogICAgICAgICAgICBjb25zdCBheiA9IHRoaXMuejsKICAgICAgICAgICAgY29uc3QgYXQgPSB0aGlzLnc7CiAgICAgICAgICAgIGNvbnN0IGJ4ID0gb3RoZXIueDsKICAgICAgICAgICAgY29uc3QgYnkgPSBvdGhlci55OwogICAgICAgICAgICBjb25zdCBieiA9IG90aGVyLno7CiAgICAgICAgICAgIGNvbnN0IGJ0ID0gb3RoZXIudzsKICAgICAgICAgICAgcmV0dXJuIG5ldyBRdWF0KGF5ICogYnogLSBheiAqIGJ5LCBheiAqIGJ0IC0gYXQgKiBieiwgYXQgKiBieCAtIGF4ICogYnQsIGF4ICogYnkgLSBheSAqIGJ4KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgcm90YXRpb25hbCBjb25qdWdhdGUgb2YgdGhpcyBRdWF0LgogICAgICAgICAqIENvbmp1Z2F0aW9uIHJlcHJlc2VudHMgdGhlIHNhbWUgcm90YXRpb24gb2YgdGhlIFF1YXQgYnV0CiAgICAgICAgICogaW4gdGhlIG9wcG9zaXRlIGRpcmVjdGlvbiBhcm91bmQgdGhlIHJvdGF0aW9uYWwgYXhpcy4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSB0aGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGNvbmp1Z2F0ZSgpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBRdWF0KC10aGlzLngsIC10aGlzLnksIC10aGlzLnosIHRoaXMudyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybiB0aGUgaW52ZXJzZSBvZiB0aGUgYFF1YXRgCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBRdWF0LgogICAgICAgICAqLwogICAgICAgIGludmVyc2UoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbmp1Z2F0ZSgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBBbGlnbnMgdGhpcyBxdWF0ZXJuaW9uIHdpdGggYW5vdGhlciBvbmUgZW5zdXJpbmcgdGhhdCB0aGUgZGVsdGEgYmV0d2VlbgogICAgICAgICAqIHRoZSBRdWF0IHZhbHVlcyBpcyB0aGUgc2hvcnRlc3QgcGF0aCBvdmVyIHRoZSBoeXBlci1zcGhlcmUuCiAgICAgICAgICoKICAgICAgICAgKiAgQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFF1YXQgdG8gZGl2aWRlIGJ5LgogICAgICAgICAqLwogICAgICAgIGFsaWduV2l0aChvdGhlcikgewogICAgICAgICAgICBpZiAodGhpcy5kb3Qob3RoZXIpIDwgMC4wKSB7CiAgICAgICAgICAgICAgICB0aGlzLnNldCgtdGhpcy54LCAtdGhpcy55LCAtdGhpcy56LCAtdGhpcy53KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBNdWx0aXBsaWVzIHR3byB0aGlzIHF1YXQgYnkgYW5vdGhlciByZXR1cm5pbmcgdGhlIHJlc3VsdCBhcyBhIG5ldyBRdWF0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFF1YXQgdG8gbXVsdGlwbHkuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgUXVhdC4KICAgICAgICAgKi8KICAgICAgICBtdWx0aXBseShvdGhlcikgewogICAgICAgICAgICBjb25zdCBheCA9IHRoaXMueDsKICAgICAgICAgICAgY29uc3QgYXkgPSB0aGlzLnk7CiAgICAgICAgICAgIGNvbnN0IGF6ID0gdGhpcy56OwogICAgICAgICAgICBjb25zdCBhdyA9IHRoaXMudzsKICAgICAgICAgICAgY29uc3QgYnggPSBvdGhlci54OwogICAgICAgICAgICBjb25zdCBieSA9IG90aGVyLnk7CiAgICAgICAgICAgIGNvbnN0IGJ6ID0gb3RoZXIuejsKICAgICAgICAgICAgY29uc3QgYncgPSBvdGhlci53OwogICAgICAgICAgICByZXR1cm4gbmV3IFF1YXQoYXggKiBidyArIGF3ICogYnggKyBheSAqIGJ6IC0gYXogKiBieSwgYXkgKiBidyArIGF3ICogYnkgKyBheiAqIGJ4IC0gYXggKiBieiwgYXogKiBidyArIGF3ICogYnogKyBheCAqIGJ5IC0gYXkgKiBieCwgYXcgKiBidyAtIGF4ICogYnggLSBheSAqIGJ5IC0gYXogKiBieik7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIE11bHRpcGxpZXMgdGhpcyBxdWF0IGJ5IGFub3RoZXIsIG1vZGlmeWluZyBpdHMgdmFsdWVzIGluIHBsYWNlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFF1YXQgdG8gbXVsdGlwbHkuCiAgICAgICAgICovCiAgICAgICAgbXVsdGlwbHlJblBsYWNlKG90aGVyKSB7CiAgICAgICAgICAgIGNvbnN0IGF4ID0gdGhpcy54OwogICAgICAgICAgICBjb25zdCBheSA9IHRoaXMueTsKICAgICAgICAgICAgY29uc3QgYXogPSB0aGlzLno7CiAgICAgICAgICAgIGNvbnN0IGF3ID0gdGhpcy53OwogICAgICAgICAgICBjb25zdCBieCA9IG90aGVyLng7CiAgICAgICAgICAgIGNvbnN0IGJ5ID0gb3RoZXIueTsKICAgICAgICAgICAgY29uc3QgYnogPSBvdGhlci56OwogICAgICAgICAgICBjb25zdCBidyA9IG90aGVyLnc7CiAgICAgICAgICAgIHRoaXMuc2V0KGF4ICogYncgKyBhdyAqIGJ4ICsgYXkgKiBieiAtIGF6ICogYnksIGF5ICogYncgKyBhdyAqIGJ5ICsgYXogKiBieCAtIGF4ICogYnosIGF6ICogYncgKyBhdyAqIGJ6ICsgYXggKiBieSAtIGF5ICogYngsIGF3ICogYncgLSBheCAqIGJ4IC0gYXkgKiBieSAtIGF6ICogYnopOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSb3RhdGVzIGEgdmVjdG9yIGJ5IHRoaXMgcXVhdGVybmlvbi4KICAgICAgICAgKiBEb24ndCBmb3JnZXQgdG8gbm9ybWFsaXplIHRoZSBxdWF0ZXJuaW9uIHVubGVzcwogICAgICAgICAqIHlvdSB3YW50IGF4aWFsIHRyYW5zbGF0aW9uIGFzIHdlbGwgYXMgcm90YXRpb24uCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gdmVjMyAtIFRoZSB2ZWMzIHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzMuCiAgICAgICAgICovCiAgICAgICAgcm90YXRlVmVjMyh2ZWMzKSB7CiAgICAgICAgICAgIGNvbnN0IHZxID0gbmV3IFF1YXQodmVjMy54LCB2ZWMzLnksIHZlYzMueiwgMC4wKTsKICAgICAgICAgICAgY29uc3QgcHEgPSB0aGlzLm11bHRpcGx5KHZxKS5tdWx0aXBseSh0aGlzLmNvbmp1Z2F0ZSgpKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMzKHBxLngsIHBxLnksIHBxLnopOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHRoaXMgcXVhdGVybmlvbiB0byBhIHJvdGF0aW9uIGJ5IHRoZSBnaXZlbiBhbmdsZSBhYm91dCB0aGUgWCBheGlzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHJhZCAtIEFuZ2xlIChpbiByYWRpYW5zKSB0byByb3RhdGUuCiAgICAgICAgICovCiAgICAgICAgcm90YXRlWChyYWQpIHsKICAgICAgICAgICAgcmFkICo9IDAuNTsKICAgICAgICAgICAgY29uc3QgYXggPSB0aGlzLng7CiAgICAgICAgICAgIGNvbnN0IGF5ID0gdGhpcy55OwogICAgICAgICAgICBjb25zdCBheiA9IHRoaXMuejsKICAgICAgICAgICAgY29uc3QgYXcgPSB0aGlzLnc7CiAgICAgICAgICAgIGNvbnN0IGJ4ID0gTWF0aC5zaW4ocmFkKTsKICAgICAgICAgICAgY29uc3QgYncgPSBNYXRoLmNvcyhyYWQpOwogICAgICAgICAgICB0aGlzLnggPSBheCAqIGJ3ICsgYXcgKiBieDsKICAgICAgICAgICAgdGhpcy55ID0gYXkgKiBidyArIGF6ICogYng7CiAgICAgICAgICAgIHRoaXMueiA9IGF6ICogYncgLSBheSAqIGJ4OwogICAgICAgICAgICB0aGlzLncgPSBhdyAqIGJ3IC0gYXggKiBieDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB0aGlzIHF1YXRlcm5pb24gdG8gYSByb3RhdGlvbiBieSB0aGUgZ2l2ZW4gYW5nbGUgYWJvdXQgdGhlIFkgYXhpcy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSByYWQgLSBBbmdsZSAoaW4gcmFkaWFucykgdG8gcm90YXRlLgogICAgICAgICAqLwogICAgICAgIHJvdGF0ZVkocmFkKSB7CiAgICAgICAgICAgIHJhZCAqPSAwLjU7CiAgICAgICAgICAgIGNvbnN0IGF4ID0gdGhpcy54OwogICAgICAgICAgICBjb25zdCBheSA9IHRoaXMueTsKICAgICAgICAgICAgY29uc3QgYXogPSB0aGlzLno7CiAgICAgICAgICAgIGNvbnN0IGF3ID0gdGhpcy53OwogICAgICAgICAgICBjb25zdCBieSA9IE1hdGguc2luKHJhZCk7CiAgICAgICAgICAgIGNvbnN0IGJ3ID0gTWF0aC5jb3MocmFkKTsKICAgICAgICAgICAgdGhpcy54ID0gYXggKiBidyAtIGF6ICogYnk7CiAgICAgICAgICAgIHRoaXMueSA9IGF5ICogYncgKyBhdyAqIGJ5OwogICAgICAgICAgICB0aGlzLnogPSBheiAqIGJ3ICsgYXggKiBieTsKICAgICAgICAgICAgdGhpcy53ID0gYXcgKiBidyAtIGF5ICogYnk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhpcyBxdWF0ZXJuaW9uIHRvIGEgcm90YXRpb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBaIGF4aXMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmFkIC0gQW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZS4KICAgICAgICAgKi8KICAgICAgICByb3RhdGVaKHJhZCkgewogICAgICAgICAgICByYWQgKj0gMC41OwogICAgICAgICAgICBjb25zdCBheCA9IHRoaXMueDsKICAgICAgICAgICAgY29uc3QgYXkgPSB0aGlzLnk7CiAgICAgICAgICAgIGNvbnN0IGF6ID0gdGhpcy56OwogICAgICAgICAgICBjb25zdCBhdyA9IHRoaXMudzsKICAgICAgICAgICAgY29uc3QgYnogPSBNYXRoLnNpbihyYWQpOwogICAgICAgICAgICBjb25zdCBidyA9IE1hdGguY29zKHJhZCk7CiAgICAgICAgICAgIHRoaXMueCA9IGF4ICogYncgKyBheSAqIGJ6OwogICAgICAgICAgICB0aGlzLnkgPSBheSAqIGJ3IC0gYXggKiBiejsKICAgICAgICAgICAgdGhpcy56ID0gYXogKiBidyArIGF3ICogYno7CiAgICAgICAgICAgIHRoaXMudyA9IGF3ICogYncgLSBheiAqIGJ6OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIFF1YXQgdG8gYSBNYXQzIChhIDN4MyBtYXRyaXgpLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRSZXR1cm5zIGEgbmV3IE1hdDMuCiAgICAgICAgICovCiAgICAgICAgdG9NYXQzKCkgewogICAgICAgICAgICBjb25zdCB4ID0gdGhpcy54OwogICAgICAgICAgICBjb25zdCB5ID0gdGhpcy55OwogICAgICAgICAgICBjb25zdCB6ID0gdGhpcy56OwogICAgICAgICAgICBjb25zdCB3ID0gdGhpcy53OwogICAgICAgICAgICBjb25zdCB4MiA9IHggKyB4OwogICAgICAgICAgICBjb25zdCB5MiA9IHkgKyB5OwogICAgICAgICAgICBjb25zdCB6MiA9IHogKyB6OwogICAgICAgICAgICBjb25zdCB4eCA9IHggKiB4MjsKICAgICAgICAgICAgY29uc3QgeXggPSB5ICogeDI7CiAgICAgICAgICAgIGNvbnN0IHl5ID0geSAqIHkyOwogICAgICAgICAgICBjb25zdCB6eCA9IHogKiB4MjsKICAgICAgICAgICAgY29uc3QgenkgPSB6ICogeTI7CiAgICAgICAgICAgIGNvbnN0IHp6ID0geiAqIHoyOwogICAgICAgICAgICBjb25zdCB3eCA9IHcgKiB4MjsKICAgICAgICAgICAgY29uc3Qgd3kgPSB3ICogeTI7CiAgICAgICAgICAgIGNvbnN0IHd6ID0gdyAqIHoyOwogICAgICAgICAgICBjb25zdCBtYXQzID0gbmV3IE1hdDMoKTsKICAgICAgICAgICAgbWF0My5tMDAgPSAxIC0geXkgLSB6ejsKICAgICAgICAgICAgbWF0My5tMTAgPSB5eCAtIHd6OwogICAgICAgICAgICBtYXQzLm0yMCA9IHp4ICsgd3k7CiAgICAgICAgICAgIG1hdDMubTAxID0geXggKyB3ejsKICAgICAgICAgICAgbWF0My5tMTEgPSAxIC0geHggLSB6ejsKICAgICAgICAgICAgbWF0My5tMjEgPSB6eSAtIHd4OwogICAgICAgICAgICBtYXQzLm0wMiA9IHp4IC0gd3k7CiAgICAgICAgICAgIG1hdDMubTEyID0genkgKyB3eDsKICAgICAgICAgICAgbWF0My5tMjIgPSAxIC0geHggLSB5eTsKICAgICAgICAgICAgcmV0dXJuIG1hdDM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZXMgYSBWZWMzIHZhbHVlIGFsaWduZWQgd2l0aCB0aGUgWCBheGlzIG9mIHRoaXMgcXVhdGVybmlvbi4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmVzdWx0aW5nIFZlYzMgdmFsdWUKICAgICAgICAgKi8KICAgICAgICBnZXRYYXhpcygpIHsKICAgICAgICAgICAgY29uc3QgeHkgPSB0aGlzLnggKiB0aGlzLnk7CiAgICAgICAgICAgIGNvbnN0IHh6ID0gdGhpcy54ICogdGhpcy56OwogICAgICAgICAgICBjb25zdCB5eSA9IHRoaXMueSAqIHRoaXMueTsKICAgICAgICAgICAgY29uc3QgeXcgPSB0aGlzLnkgKiB0aGlzLnc7CiAgICAgICAgICAgIGNvbnN0IHp6ID0gdGhpcy56ICogdGhpcy56OwogICAgICAgICAgICBjb25zdCB6dyA9IHRoaXMueiAqIHRoaXMudzsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMzKDEuMCAtIDIuMCAqICh6eiArIHl5KSwgMi4wICogKHh5ICsgencpLCAyLjAgKiAoeHogLSB5dykpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDYWxjdWxhdGVzIGEgVmVjMyB2YWx1ZSBhbGlnbmVkIHdpdGggdGhlIFkgYXhpcyBvZiB0aGlzIHF1YXRlcm5pb24uCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJlc3VsdGluZyBWZWMzIHZhbHVlCiAgICAgICAgICovCiAgICAgICAgZ2V0WWF4aXMoKSB7CiAgICAgICAgICAgIGNvbnN0IHh4ID0gdGhpcy54ICogdGhpcy54OwogICAgICAgICAgICBjb25zdCB4eSA9IHRoaXMueCAqIHRoaXMueTsKICAgICAgICAgICAgY29uc3QgeHcgPSB0aGlzLnggKiB0aGlzLnc7CiAgICAgICAgICAgIGNvbnN0IHl6ID0gdGhpcy55ICogdGhpcy56OwogICAgICAgICAgICBjb25zdCB6eiA9IHRoaXMueiAqIHRoaXMuejsKICAgICAgICAgICAgY29uc3QgencgPSB0aGlzLnogKiB0aGlzLnc7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMygyLjAgKiAoeHkgLSB6dyksIDEuMCAtIDIuMCAqICh6eiArIHh4KSwgMi4wICogKHl6ICsgeHcpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsY3VsYXRlcyBhIFZlYzMgdmFsdWUgYWxpZ25lZCB3aXRoIHRoZSBaIGF4aXMgb2YgdGhpcyBxdWF0ZXJuaW9uLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXN1bHRpbmcgVmVjMyB2YWx1ZQogICAgICAgICAqLwogICAgICAgIGdldFpheGlzKCkgewogICAgICAgICAgICBjb25zdCB4eCA9IHRoaXMueCAqIHRoaXMueDsKICAgICAgICAgICAgY29uc3QgeHogPSB0aGlzLnggKiB0aGlzLno7CiAgICAgICAgICAgIGNvbnN0IHh3ID0gdGhpcy54ICogdGhpcy53OwogICAgICAgICAgICBjb25zdCB5eSA9IHRoaXMueSAqIHRoaXMueTsKICAgICAgICAgICAgY29uc3QgeXogPSB0aGlzLnkgKiB0aGlzLno7CiAgICAgICAgICAgIGNvbnN0IHl3ID0gdGhpcy55ICogdGhpcy53OwogICAgICAgICAgICAvLyBjb25zdCB0ZW1wID0gbmV3IFZlYzMoKQogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzMoMi4wICogKHl3ICsgeHopLCAyLjAgKiAoeXogLSB4dyksIDEuMCAtIDIuMCAqICh5eSArIHh4KSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJlZmxlY3RzIHRoaXMgcXVhdGVybmlvbiBhY2NvcmRpbmcgdG8gdGhlIGF4aXMgcHJvdmlkZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gYXhpc0luZGV4IC0gQW4gaW50ZWdlciB3aXRoIHZhbHVlIG9mIDAgZm9yIHRoZSBYIGF4aXMsIDEgZm9yIHRoZSBZIGF4aXMsIGFuZCAyIGZvciB0aGUgWiBheGlzLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFF1YXQuCiAgICAgICAgICovCiAgICAgICAgbWlycm9yKGF4aXNJbmRleCkgewogICAgICAgICAgICBzd2l0Y2ggKGF4aXNJbmRleCkgewogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUXVhdCh0aGlzLnosIHRoaXMudywgdGhpcy54LCB0aGlzLnkpOwogICAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUXVhdCgtdGhpcy53LCB0aGlzLnosIHRoaXMueSwgLXRoaXMueCk7CiAgICAgICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBRdWF0KHRoaXMueCwgdGhpcy55LCB0aGlzLnosIC10aGlzLncpOwogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFF1YXQodGhpcy56LCB0aGlzLncsIHRoaXMueCwgdGhpcy55KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIFF1YXQgdG8gYSBNYXQ0IChhIDR4NCBtYXRyaXgpLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgTWF0NC4KICAgICAgICAgKi8KICAgICAgICB0b01hdDQoKSB7CiAgICAgICAgICAgIGNvbnN0IHggPSB0aGlzLng7CiAgICAgICAgICAgIGNvbnN0IHkgPSB0aGlzLnk7CiAgICAgICAgICAgIGNvbnN0IHogPSB0aGlzLno7CiAgICAgICAgICAgIGNvbnN0IHcgPSB0aGlzLnc7CiAgICAgICAgICAgIGNvbnN0IHgyID0geCArIHg7CiAgICAgICAgICAgIGNvbnN0IHkyID0geSArIHk7CiAgICAgICAgICAgIGNvbnN0IHoyID0geiArIHo7CiAgICAgICAgICAgIGNvbnN0IHh4ID0geCAqIHgyOwogICAgICAgICAgICBjb25zdCB5eCA9IHkgKiB4MjsKICAgICAgICAgICAgY29uc3QgeXkgPSB5ICogeTI7CiAgICAgICAgICAgIGNvbnN0IHp4ID0geiAqIHgyOwogICAgICAgICAgICBjb25zdCB6eSA9IHogKiB5MjsKICAgICAgICAgICAgY29uc3QgenogPSB6ICogejI7CiAgICAgICAgICAgIGNvbnN0IHd4ID0gdyAqIHgyOwogICAgICAgICAgICBjb25zdCB3eSA9IHcgKiB5MjsKICAgICAgICAgICAgY29uc3Qgd3ogPSB3ICogejI7CiAgICAgICAgICAgIC8vIFNldCB0aGUgY29sdW1ucwogICAgICAgICAgICBjb25zdCBtYXQ0ID0gbmV3IE1hdDQoKTsKICAgICAgICAgICAgbWF0NC5tMDAgPSAxIC0geXkgLSB6ejsKICAgICAgICAgICAgbWF0NC5tMTAgPSB5eCAtIHd6OwogICAgICAgICAgICBtYXQ0Lm0yMCA9IHp4ICsgd3k7CiAgICAgICAgICAgIG1hdDQubTAxID0geXggKyB3ejsKICAgICAgICAgICAgbWF0NC5tMTEgPSAxIC0geHggLSB6ejsKICAgICAgICAgICAgbWF0NC5tMjEgPSB6eSAtIHd4OwogICAgICAgICAgICBtYXQ0Lm0wMiA9IHp4IC0gd3k7CiAgICAgICAgICAgIG1hdDQubTEyID0genkgKyB3eDsKICAgICAgICAgICAgbWF0NC5tMjIgPSAxIC0geHggLSB5eTsKICAgICAgICAgICAgcmV0dXJuIG1hdDQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFBlcmZvcm1zIGEgbGluZWFyIGludGVycG9sYXRpb24gb2YgdGhpcyBRdWF0IHRvd2FyZHMgYW5vdGhlciBRdWF0LCByZXR1cm5pbmcgdGhlIHJlc3VsdCBhcyBhIG5ldyBRdWF0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyICAtIFRoZSBvdGhlciBRdWF0IHRvIGludGVycG9sYXRlIHRvd2FyZHMuCiAgICAgICAgICogQHBhcmFtIHQgLSBJbnRlcnBvbGF0aW9uIHJhdGlvLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFF1YXQuCiAgICAgICAgICovCiAgICAgICAgbGVycChvdGhlciwgdCkgewogICAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgUXVhdCh0aGlzLnggKyB0ICogKG90aGVyLnggLSB0aGlzLngpLCB0aGlzLnkgKyB0ICogKG90aGVyLnkgLSB0aGlzLnkpLCB0aGlzLnogKyB0ICogKG90aGVyLnogLSB0aGlzLnopLCB0aGlzLncgKyB0ICogKG90aGVyLncgLSB0aGlzLncpKTsKICAgICAgICAgICAgcmVzdWx0Lm5vcm1hbGl6ZUluUGxhY2UoKTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUGVyZm9ybXMgYSBzcGhlcmljYWwgbGluZWFyIGludGVycG9sYXRpb24gb2YgdGhpcyBRdWF0IHRvd2FyZHMgYW5vdGhlciBRdWF0LCByZXR1cm5pbmcgdGhlIHJlc3VsdCBhcyBhIG5ldyBRdWF0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG90aGVyIC0gVGhlIG90aGVyIFF1YXQgdG8gaW50ZXJwb2xhdGUgdG93YXJkcy4KICAgICAgICAgKiBAcGFyYW0gdCAtIEludGVycG9sYXRpb24gYW1vdW50IGJldHdlZW4gdGhlIHR3byBpbnB1dHMuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgUXVhdC4KICAgICAgICAgKi8KICAgICAgICBzbGVycChvdGhlciwgbGFtYmRhKSB7CiAgICAgICAgICAgIC8vLyBodHRwczovL3d3dy5nZW9tZXRyaWN0b29scy5jb20vRG9jdW1lbnRhdGlvbi9GYXN0QW5kQWNjdXJhdGVTbGVycC5wZGYKICAgICAgICAgICAgY29uc3QgZG90UHJvZHVjdCA9IHRoaXMuZG90KG90aGVyKTsKICAgICAgICAgICAgaWYgKGRvdFByb2R1Y3QgPiAwLjk5OSkKICAgICAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgICAvLyBhbGdvcml0aG0gYWRhcHRlZCBmcm9tIFNob2VtYWtlJ3MgcGFwZXIKICAgICAgICAgICAgLy8gbGFtYmRhIGlzIGluICgwLCDPgC8yXQogICAgICAgICAgICBjb25zdCB0aGV0YSA9IE1hdGguYWNvcyhkb3RQcm9kdWN0KTsKICAgICAgICAgICAgY29uc3Qgc3QgPSBNYXRoLnNpbih0aGV0YSk7CiAgICAgICAgICAgIGNvbnN0IHN1dCA9IE1hdGguc2luKGxhbWJkYSAqIHRoZXRhKTsKICAgICAgICAgICAgY29uc3Qgc291dCA9IE1hdGguc2luKCgxIC0gbGFtYmRhKSAqIHRoZXRhKTsKICAgICAgICAgICAgY29uc3QgY29lZmYxID0gc291dCAvIHN0OwogICAgICAgICAgICBjb25zdCBjb2VmZjIgPSBzdXQgLyBzdDsKICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFF1YXQoY29lZmYxICogdGhpcy54ICsgY29lZmYyICogb3RoZXIueCwgY29lZmYxICogdGhpcy55ICsgY29lZmYyICogb3RoZXIueSwgY29lZmYxICogdGhpcy56ICsgY29lZmYyICogb3RoZXIueiwgY29lZmYxICogdGhpcy53ICsgY29lZmYyICogb3RoZXIudyk7CiAgICAgICAgICAgIHJlc3VsdC5ub3JtYWxpemVJblBsYWNlKCk7CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENsb25lcyB0aGlzIFF1YXQgYW5kIHJldHVybnMgYSBuZXcgUXVhdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFF1YXQuCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgUXVhdCh0aGlzLngsIHRoaXMueSwgdGhpcy56LCB0aGlzLncpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSB0eXBlIGFzIGFuIGFycmF5LiBPZnRlbiB1c2VkIHRvIHBhc3MgdHlwZXMgdG8gdGhlIEdQVS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGFzIGFuIGFycmF5LgogICAgICAgICAqLwogICAgICAgIGFzQXJyYXkoKSB7CiAgICAgICAgICAgIHJldHVybiBbdGhpcy54LCB0aGlzLnksIHRoaXMueiwgdGhpcy53XTsKICAgICAgICB9CiAgICAgICAgZnJvbUFycmF5KGFycmF5KSB7CiAgICAgICAgICAgIHRoaXMueCA9IGFycmF5WzBdOwogICAgICAgICAgICB0aGlzLnkgPSBhcnJheVsxXTsKICAgICAgICAgICAgdGhpcy56ID0gYXJyYXlbMl07CiAgICAgICAgICAgIHRoaXMudyA9IGFycmF5WzNdOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQZXJzaXN0ZW5jZQogICAgICAgIC8qKgogICAgICAgICAqIENvbnZlcnRzIHRoaXMgVmVjMyB0byBhIHN0cmluZyBpbiBKU09OIGZvcm1hdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHRvU3RyaW5nKCkgewogICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbmV3LWNhcAogICAgICAgICAgICByZXR1cm4gU3RyaW5nRnVuY3Rpb25zLnN0cmluZ2lmeUpTT05XaXRoRml4ZWRQcmVjaXNpb24odGhpcy50b0pTT04oKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSB0b0pTT04gbWV0aG9kIGVuY29kZXMgdGhpcyB0eXBlIGFzIGEganNvbiBvYmplY3QgZm9yIHBlcnNpc3RlbmNlLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSBqc29uIG9iamVjdC4KICAgICAgICAgKi8KICAgICAgICB0b0pTT04oKSB7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICB4OiB0aGlzLngsCiAgICAgICAgICAgICAgICB5OiB0aGlzLnksCiAgICAgICAgICAgICAgICB6OiB0aGlzLnosCiAgICAgICAgICAgICAgICB3OiB0aGlzLncsCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBmcm9tSlNPTiBtZXRob2QgZGVjb2RlcyBhIGpzb24gb2JqZWN0IGZvciB0aGlzIHR5cGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaiAtIFRoZSBqc29uIG9iamVjdC4KICAgICAgICAgKi8KICAgICAgICBmcm9tSlNPTihqKSB7CiAgICAgICAgICAgIHRoaXMueCA9IGoueDsKICAgICAgICAgICAgdGhpcy55ID0gai55OwogICAgICAgICAgICB0aGlzLnogPSBqLno7CiAgICAgICAgICAgIHRoaXMudyA9IGoudzsKICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVJblBsYWNlKCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIExvYWRzIHRoZSBzdGF0ZSBvZiB0aGUgdmFsdWUgZnJvbSBhIGJpbmFyeSByZWFkZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICByZWFkQmluYXJ5KHJlYWRlcikgewogICAgICAgICAgICB0aGlzLnggPSByZWFkZXIubG9hZEZsb2F0MzIoKTsKICAgICAgICAgICAgdGhpcy55ID0gcmVhZGVyLmxvYWRGbG9hdDMyKCk7CiAgICAgICAgICAgIHRoaXMueiA9IHJlYWRlci5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICB0aGlzLncgPSByZWFkZXIubG9hZEZsb2F0MzIoKTsKICAgICAgICB9CiAgICB9CgogICAgLyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi8KICAgIC8qKgogICAgICogQ2xhc3MgcmVwcmVzZW50aW5nIGFuIFhmbyB0cmFuc2Zvcm0sIHdoaWNoIGlzIGEgdHJhbnNmb3JtYXRpb24gZGVjb21wb3NlZCBpbnRvIDMgY29tcG9uZW50IHZhbHVlcy4gVHJhbnNsYXRpb24sIE9yaWVudGF0aW9uLCBhbmQgU2NhbGluZy4KICAgICAqLwogICAgY2xhc3MgWGZvIHsKICAgICAgICB0cjsKICAgICAgICBvcmk7CiAgICAgICAgc2M7CiAgICAgICAgLyoqCiAgICAgICAgICogSW5pdGlhbGl6ZXMgdGhlIFhmbyBvYmplY3QuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gdHIgLSBUaGUgdHJhbnNsYXRpb24gdmFsdWUuCiAgICAgICAgICogQHBhcmFtIG9yaSAtIFRoZSBvcmllbnRhdGlvbiB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gc2MgLSBUaGUgc2NhbGluZyB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3Rvcih0ciA9IG5ldyBWZWMzKCksIG9yaSA9IG5ldyBRdWF0KCksIHNjID0gbmV3IFZlYzMoMSwgMSwgMSkpIHsKICAgICAgICAgICAgdGhpcy50ciA9IHRyOwogICAgICAgICAgICB0aGlzLm9yaSA9IG9yaTsKICAgICAgICAgICAgdGhpcy5zYyA9IHNjOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHRoZSBzdGF0ZSBvZiB0aGUgWGZvIG9iamVjdC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSB0ciAtIFRoZSB0cmFuc2xhdGlvbiB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gb3JpIC0gVGhlIG9yaWVudGF0aW9uIHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBzYyAtIFRoZSBzY2FsaW5nIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldCh0ciwgb3JpLCBzYykgewogICAgICAgICAgICB0aGlzLnRyID0gdHI7CiAgICAgICAgICAgIHRoaXMub3JpID0gb3JpOwogICAgICAgICAgICBpZiAoc2MgaW5zdGFuY2VvZiBWZWMzKQogICAgICAgICAgICAgICAgdGhpcy5zYyA9IHNjOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHRoZSBzdGF0ZSBvZiB0aGUgWGZvIG9iamVjdCB1c2luZyBhbm90aGVyIFhmbyBvYmplY3QuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3RoZXIgLSBUaGUgb3RoZXIgWGZvIHRvIHNldCBmcm9tLgogICAgICAgICAqLwogICAgICAgIHNldEZyb21PdGhlcihvdGhlcikgewogICAgICAgICAgICB0aGlzLnRyID0gb3RoZXIudHI7CiAgICAgICAgICAgIHRoaXMub3JpID0gb3RoZXIub3JpOwogICAgICAgICAgICB0aGlzLnNjID0gb3RoZXIuc2M7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFZlcmlmaWVzIHRoYXQgdGhlIFhmbyBvYmplY3QgaXMgYW4gYGlkZW50aXR5YCwgY2hlY2tpbmcgdGhhdCB0aGUgdHJhbnNsYXRpb24sIG9yaWVudGF0aW9uIGFuZCBzY2FsaW5nIGF0dHJpYnV0ZXMgYXJlIGluIHRoZWlyIGluaXRpYWwgc3RhdGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBpc0lkZW50aXR5KCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy50ci5pc051bGwoKSAmJiB0aGlzLm9yaS5pc0lkZW50aXR5KCkgJiYgdGhpcy5zYy5pczExMSgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDaGVja3MgaWYgdGhpcyBWZWMzIGNvbnRhaW5zIHRoZSBzYW1lIHZhbHVlcyBhcyB0aGUgb3RoZXIgVmVjMy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWMzIHRvIGNvbXBhcmUgd2l0aC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBgdHJ1ZWAgaWYgYXJlIHRoZSBzYW1lIFZlY3Rvciwgb3RoZXJ3aXNlLCBgZmFsc2VgLgogICAgICAgICAqLwogICAgICAgIGlzRXF1YWwob3RoZXIpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMudHIuaXNFcXVhbChvdGhlci50cikgJiYgdGhpcy5vcmkuaXNFcXVhbChvdGhlci5vcmkpICYmIHRoaXMuc2MuaXNFcXVhbChvdGhlci5zYyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIFZlYzIgaXMgYXBwcm94aW1hdGVseSB0aGUgc2FtZSBhcyBvdGhlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBWZWMzIHRvIGNvbXBhcmUgd2l0aC4KICAgICAgICAgKiBAcGFyYW0gcHJlY2lzaW9uIC0gVGhlIHByZWNpc2lvbiB0byB3aGljaCB0aGUgdmFsdWVzIG11c3QgbWF0Y2guCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdHJ1ZSBvciBmYWxzZS4KICAgICAgICAgKi8KICAgICAgICBhcHByb3hFcXVhbChvdGhlciwgcHJlY2lzaW9uID0gTnVtYmVyLkVQU0lMT04pIHsKICAgICAgICAgICAgcmV0dXJuICgob3RoZXIudHIgPyB0aGlzLnRyLmFwcHJveEVxdWFsKG90aGVyLnRyLCBwcmVjaXNpb24pIDogdHJ1ZSkgJiYKICAgICAgICAgICAgICAgIChvdGhlci5vcmkgPyB0aGlzLm9yaS5hcHByb3hFcXVhbChvdGhlci5vcmksIHByZWNpc2lvbikgOiB0cnVlKSAmJgogICAgICAgICAgICAgICAgKG90aGVyLnNjID8gdGhpcy5zYy5hcHByb3hFcXVhbChvdGhlci5zYywgcHJlY2lzaW9uKSA6IHRydWUpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHNldExvb2tBdCBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIHBvcyAtIFRoZSBwb3NpdGlvbiB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gdGFyZ2V0IC0gVGhlIHRhcmdldCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gdXAgLSBUaGUgdXAgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0TG9va0F0KHBvcywgdGFyZ2V0LCB1cCkgewogICAgICAgICAgICAvLyBOb3RlOiBXZSBsb29rIGFsb25nIHRoZSAteiBheGlzLiBOZWdhdGUgdGhlIGRpcmVjdGlvbi4KICAgICAgICAgICAgY29uc3QgZGlyID0gcG9zLnN1YnRyYWN0KHRhcmdldCk7CiAgICAgICAgICAgIGNvbnN0IGRpckxlbiA9IGRpci5sZW5ndGgoKTsKICAgICAgICAgICAgaWYgKGRpckxlbiA8IE51bWJlci5FUFNJTE9OKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZGlyJyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5vcmkuc2V0RnJvbURpcmVjdGlvbkFuZFVwdmVjdG9yKGRpciwgdXApOwogICAgICAgICAgICB0aGlzLnRyID0gcG9zOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBNdWx0aXBsaWVzIHR3byBYZm8gdHJhbnNmb3Jtcy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSB4Zm8gLSBUaGUgeGZvIHRvIG11bHRpcGx5IHdpdGguCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYW4gWGZvLgogICAgICAgICAqLwogICAgICAgIG11bHRpcGx5KHhmbykgewogICAgICAgICAgICBsZXQgdGhpc19zYyA9IHRoaXMuc2M7CiAgICAgICAgICAgIC8vIGNoZWNrIGZvciBub24tdW5pZm9ybSBzY2FsZS4KICAgICAgICAgICAgaWYgKE1hdGguYWJzKHRoaXMuc2MueSAtIHRoaXMuc2MueCkgPiAwLjAwMSB8fAogICAgICAgICAgICAgICAgTWF0aC5hYnModGhpcy5zYy56IC0gdGhpcy5zYy54KSA+IDAuMDAxIHx8CiAgICAgICAgICAgICAgICBNYXRoLmFicyh0aGlzLnNjLnogLSB0aGlzLnNjLnkpID4gMC4wMDEpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHRoaXNfbWF0NCA9IHRoaXMudG9NYXQ0KCk7CiAgICAgICAgICAgICAgICBjb25zdCBvdGhlcl9tYXQ0ID0geGZvLm9yaS50b01hdDQoKTsKICAgICAgICAgICAgICAgIGNvbnN0IHJlc000ID0gdGhpc19tYXQ0Lm11bHRpcGx5KG90aGVyX21hdDQpOwogICAgICAgICAgICAgICAgdGhpc19zYyA9IG5ldyBWZWMzKHJlc000LnhBeGlzLmxlbmd0aCgpLCByZXNNNC55QXhpcy5sZW5ndGgoKSwgcmVzTTQuekF4aXMubGVuZ3RoKCkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBYZm8odGhpcy50ci5hZGQodGhpcy5vcmkucm90YXRlVmVjMyh0aGlzLnNjLm11bHRpcGx5KHhmby50cikpKSwgdGhpcy5vcmkubXVsdGlwbHkoeGZvLm9yaSksIHRoaXNfc2MubXVsdGlwbHkoeGZvLnNjKSk7CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIGludmVyc2Ugb2YgdGhlIFhmbyBvYmplY3QsIGJ1dCByZXR1cm5zLiB0aGUgcmVzdWx0IGFzIGEgbmV3IFhmby4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFhmby4KICAgICAgICAgKi8KICAgICAgICBpbnZlcnNlKCkgewogICAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgWGZvKCk7CiAgICAgICAgICAgIHJlc3VsdC5vcmkgPSB0aGlzLm9yaS5pbnZlcnNlKCk7CiAgICAgICAgICAgIC8vIGNoZWNrIGZvciBub24tdW5pZm9ybSBzY2FsZS4KICAgICAgICAgICAgaWYgKE1hdGguYWJzKHRoaXMuc2MueSAtIHRoaXMuc2MueCkgPiAwLjAwMSB8fAogICAgICAgICAgICAgICAgTWF0aC5hYnModGhpcy5zYy56IC0gdGhpcy5zYy54KSA+IDAuMDAxIHx8CiAgICAgICAgICAgICAgICBNYXRoLmFicyh0aGlzLnNjLnogLSB0aGlzLnNjLnkpID4gMC4wMDEpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHRoaXNfbWF0NCA9IHRoaXMudG9NYXQ0KCkuaW52ZXJzZSgpOwogICAgICAgICAgICAgICAgcmVzdWx0LnNjID0gbmV3IFZlYzModGhpc19tYXQ0LnhBeGlzLmxlbmd0aCgpLCB0aGlzX21hdDQueUF4aXMubGVuZ3RoKCksIHRoaXNfbWF0NC56QXhpcy5sZW5ndGgoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICByZXN1bHQuc2MgPSB0aGlzLnNjLmludmVyc2UoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXN1bHQudHIgPSByZXN1bHQub3JpLnJvdGF0ZVZlYzModGhpcy50ci5uZWdhdGUoKS5tdWx0aXBseShyZXN1bHQuc2MpKTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVHJhbnNmb3JtcyBYZm8gb2JqZWN0IHVzaW5nIGEgYFZlYzNgIG9iamVjdC4gRmlyc3Qgc2NhbGluZyBpdCwgdGhlbiByb3RhdGluZyBhbmQgZmluYWxseSBhZGRpbmcgdGhlIHJlc3VsdCB0byBjdXJyZW50IHRyYW5zbGF0aW9uIG9iamVjdC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSB2ZWMzIC0gVGhlIHZlYzMgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgdHJhbnNmb3JtVmVjMyh2ZWMzKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnRyLmFkZCh0aGlzLm9yaS5yb3RhdGVWZWMzKHRoaXMuc2MubXVsdGlwbHkodmVjMykpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHRoaXMgWGZvIGFuZCBvdGhlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvdGhlciAtIFRoZSBvdGhlciBYZm8gdG8gaW50ZXJwb2xhdGUgdG93YXJkcy4KICAgICAgICAgKiBAcGFyYW0gdCAtIEludGVycG9sYXRpb24gcmF0aW8uCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgWGZvLgogICAgICAgICAqLwogICAgICAgIGxlcnAob3RoZXIsIHQpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBYZm8odGhpcy50ci5sZXJwKG90aGVyLnRyLCB0KSwgdGhpcy5vcmkuc2xlcnAob3RoZXIub3JpLCB0KSwgdGhpcy5zYy5sZXJwKG90aGVyLnNjLCB0KSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENvbnZlcnRzIHRoaXMgWGZvIHRvIGEgTWF0NCAoYSA0eDQgbWF0cml4KS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IE1hdDQuCiAgICAgICAgICovCiAgICAgICAgdG9NYXQ0KCkgewogICAgICAgICAgICBjb25zdCBzY2wgPSBuZXcgTWF0NCh0aGlzLnNjLngsIDAsIDAsIDAsIDAsIHRoaXMuc2MueSwgMCwgMCwgMCwgMCwgdGhpcy5zYy56LCAwLCAwLCAwLCAwLCAxLjApOwogICAgICAgICAgICBjb25zdCByb3QgPSB0aGlzLm9yaS50b01hdDQoKTsKICAgICAgICAgICAgY29uc3QgdHJuID0gbmV3IE1hdDQoKTsKICAgICAgICAgICAgdHJuLnRyYW5zbGF0aW9uID0gdGhpcy50cjsKICAgICAgICAgICAgcmV0dXJuIHRybi5tdWx0aXBseShyb3QpLm11bHRpcGx5KHNjbCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIHN0YXRlIG9mIHRoZSBYZm8gb2JqZWN0IHVzaW5nIE1hdDQuCiAgICAgICAgICogQHBhcmFtIG1hdDQgLSBUaGUgbWF0NCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRGcm9tTWF0NChtYXQ0KSB7CiAgICAgICAgICAgIHRoaXMudHIgPSBtYXQ0LnRyYW5zbGF0aW9uOwogICAgICAgICAgICB0aGlzLm9yaS5zZXRGcm9tTWF0NChtYXQ0KTsKICAgICAgICAgICAgdGhpcy5zYy5zZXQobWF0NC54QXhpcy5sZW5ndGgoKSwgbWF0NC55QXhpcy5sZW5ndGgoKSwgbWF0NC56QXhpcy5sZW5ndGgoKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENsb25lcyB0aGlzIFhmbyBhbmQgcmV0dXJucyBhIG5ldyBYZm8uCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBYZm8uCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgWGZvKHRoaXMudHIuY2xvbmUoKSwgdGhpcy5vcmkuY2xvbmUoKSwgdGhpcy5zYy5jbG9uZSgpKTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdG9KU09OIG1ldGhvZCBlbmNvZGVzIHRoaXMgdHlwZSBhcyBhIGpzb24gb2JqZWN0IGZvciBwZXJzaXN0ZW5jZS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUganNvbiBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgdG9KU09OKCkgewogICAgICAgICAgICBjb25zdCBqID0gewogICAgICAgICAgICAgICAgdHI6IHRoaXMudHIudG9KU09OKCksCiAgICAgICAgICAgICAgICBvcmk6IHRoaXMub3JpLnRvSlNPTigpLAogICAgICAgICAgICAgICAgc2M6IHRoaXMuc2MudG9KU09OKCksCiAgICAgICAgICAgIH07CiAgICAgICAgICAgIHJldHVybiBqOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIGRlY29kZXMgYSBqc29uIG9iamVjdCBmb3IgdGhpcyB0eXBlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGogLSBUaGUganNvbiBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgZnJvbUpTT04oaikgewogICAgICAgICAgICB0aGlzLnRyLmZyb21KU09OKGoudHIpOwogICAgICAgICAgICB0aGlzLm9yaS5mcm9tSlNPTihqLm9yaSk7CiAgICAgICAgICAgIGlmIChqLnNjKSB7CiAgICAgICAgICAgICAgICB0aGlzLnNjLmZyb21KU09OKGouc2MpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIExvYWRzIHRoZSBzdGF0ZSBvZiB0aGUgdmFsdWUgZnJvbSBhIGJpbmFyeSByZWFkZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICByZWFkQmluYXJ5KHJlYWRlcikgewogICAgICAgICAgICB0aGlzLnRyLnJlYWRCaW5hcnkocmVhZGVyKTsKICAgICAgICAgICAgdGhpcy5vcmkucmVhZEJpbmFyeShyZWFkZXIpOwogICAgICAgICAgICB0aGlzLnNjLnJlYWRCaW5hcnkocmVhZGVyKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGZyb21KU09OIG1ldGhvZCBkZWNvZGVzIGEganNvbiBvYmplY3QgZm9yIHRoaXMgdHlwZS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHRvU3RyaW5nKCkgewogICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbmV3LWNhcAogICAgICAgICAgICByZXR1cm4gU3RyaW5nRnVuY3Rpb25zLnN0cmluZ2lmeUpTT05XaXRoRml4ZWRQcmVjaXNpb24odGhpcy50b0pTT04oKSk7CiAgICAgICAgfQogICAgfQoKICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIGJveCBpbiAyRCBzcGFjZS4gTmVlZGluZyB0d28gVmVjMiB2ZWN0b3JzIGRlc2NyaWJpbmcgdGhlIGNvcm5lcnMKICAgICAqLwogICAgY2xhc3MgQm94MiB7CiAgICAgICAgcDA7CiAgICAgICAgcDE7CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlcyBhIEJveDIgb2JqZWN0IHVzaW5nIFZlYzJzLgogICAgICAgICAqIEluIGNhc2UgdGhlIHBhcmFtZXRlcnMgYXJlIG5vdCBwYXNzZWQgYnksIHRoZWlyIHZhbHVlcyBhcmUgcHJlLWRlZmluZWQ6CiAgICAgICAgICoKICAgICAgICAgKiBwMCBpcyBhIFZlYzIgd2l0aCB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvTnVtYmVyL1BPU0lUSVZFX0lORklOSVRZfGBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFlgfQogICAgICAgICAqCiAgICAgICAgICogcDEgaXMgYSBWZWMyIHdpdGgge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL051bWJlci9ORUdBVElWRV9JTkZJTklUWXxgTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZYH0KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBwMCAtIEEgcG9pbnQgcmVwcmVzZW50aW5nIHRoZSBjb3JuZXJzIG9mIGEgMkQgYm94LgogICAgICAgICAqIEBwYXJhbSBwMSAtIEEgcG9pbnQgcmVwcmVzZW50aW5nIHRoZSBjb3JuZXJzIG9mIGEgMkQgYm94LgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKHAwLCBwMSkgewogICAgICAgICAgICBpZiAocDAgaW5zdGFuY2VvZiBWZWMyKSB7CiAgICAgICAgICAgICAgICB0aGlzLnAwID0gcDA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB0aGlzLnAwID0gbmV3IFZlYzIoTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLCBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChwMSBpbnN0YW5jZW9mIFZlYzIpIHsKICAgICAgICAgICAgICAgIHRoaXMucDEgPSBwMTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHRoaXMucDEgPSBuZXcgVmVjMihOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFksIE51bWJlci5ORUdBVElWRV9JTkZJTklUWSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyBib3RoIFZlYzIgcG9pbnRzCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcDAgLSBBIHBvaW50IHJlcHJlc2VudGluZyB0aGUgY29ybmVycyBvZiBhIDJEIGJveC4KICAgICAgICAgKiBAcGFyYW0gcDEgLSBBIHBvaW50IHJlcHJlc2VudGluZyB0aGUgY29ybmVycyBvZiBhIDJEIGJveC4KICAgICAgICAgKi8KICAgICAgICBzZXQocDAsIHAxKSB7CiAgICAgICAgICAgIHRoaXMucDAgPSBwMDsKICAgICAgICAgICAgdGhpcy5wMSA9IHAxOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXNldHMgdGhlIGJveDIgYmFjayB0byBhbiB1bmluaXRpYWxpemVkIHN0YXRlLgogICAgICAgICAqCiAgICAgICAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvTnVtYmVyL1BPU0lUSVZFX0lORklOSVRZfGBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFlgfQogICAgICAgICAqIGFuZCB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvTnVtYmVyL05FR0FUSVZFX0lORklOSVRZfGBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFlgfQogICAgICAgICAqLwogICAgICAgIHJlc2V0KCkgewogICAgICAgICAgICB0aGlzLnAwLnggPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7CiAgICAgICAgICAgIHRoaXMucDEueCA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTsKICAgICAgICAgICAgdGhpcy5wMC55ID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgICAgICAgICB0aGlzLnAxLnkgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYHRydWVgIGlmIHRoZSBib3ggaGFzIGJlZW4gZXhwYW5kZWQgdG8gY29udGFpbiBhIHBvaW50LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgaXNWYWxpZCgpIHsKICAgICAgICAgICAgcmV0dXJuICh0aGlzLnAwLnggIT0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZICYmCiAgICAgICAgICAgICAgICB0aGlzLnAxLnggIT0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZICYmCiAgICAgICAgICAgICAgICB0aGlzLnAwLnkgIT0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZICYmCiAgICAgICAgICAgICAgICB0aGlzLnAxLnkgIT0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogRXhwYW5kcyB0aGUgQm94MiB0byBjb250YWluIHRoZSBuZXcgcG9pbnQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcG9pbnQgLSBBIHBvaW50IHJlcHJlc2VudHMgdGhlIGNvcm5lcnMgb2YgYSAyRCBib3guCiAgICAgICAgICovCiAgICAgICAgYWRkUG9pbnQocG9pbnQpIHsKICAgICAgICAgICAgaWYgKHRoaXMucDAueCA9PSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkgfHwgcG9pbnQueCA8IHRoaXMucDAueCkKICAgICAgICAgICAgICAgIHRoaXMucDAueCA9IHBvaW50Lng7CiAgICAgICAgICAgIGlmICh0aGlzLnAwLnkgPT0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZIHx8IHBvaW50LnkgPCB0aGlzLnAwLnkpCiAgICAgICAgICAgICAgICB0aGlzLnAwLnkgPSBwb2ludC55OwogICAgICAgICAgICBpZiAodGhpcy5wMS55ID09IE51bWJlci5ORUdBVElWRV9JTkZJTklUWSB8fCBwb2ludC54ID4gdGhpcy5wMS54KQogICAgICAgICAgICAgICAgdGhpcy5wMS54ID0gcG9pbnQueDsKICAgICAgICAgICAgaWYgKHRoaXMucDEueSA9PSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFkgfHwgcG9pbnQueSA+IHRoaXMucDEueSkKICAgICAgICAgICAgICAgIHRoaXMucDEueSA9IHBvaW50Lnk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIGxlbmd0aCBvZiB0aGUgZGlhZ29uYWwgb2YgdGhlIGJveC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBkaXN0YW5jZS4KICAgICAgICAgKi8KICAgICAgICBzaXplKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5wMS5kaXN0YW5jZVRvKHRoaXMucDApOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBzaXplIG9mIGEgQm94MiAtIHRoZSBzYW1lIGFzIHNpemUoKS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgVmVjMi4KICAgICAgICAgKi8KICAgICAgICBkaWFnb25hbCgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMucDEuc3VidHJhY3QodGhpcy5wMCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIGNlbnRlciBwb2ludCBvZiBhIEJveDIuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIFZlYzIuCiAgICAgICAgICovCiAgICAgICAgY2VudGVyKCkgewogICAgICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLnAxLnN1YnRyYWN0KHRoaXMucDApOwogICAgICAgICAgICByZXN1bHQuc2NhbGVJblBsYWNlKDAuNSk7CiAgICAgICAgICAgIHJlc3VsdC5hZGRJblBsYWNlKHRoaXMucDApOwogICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDbG9uZXMgdGhpcyBWZWMyIGFuZCByZXR1cm5zIGEgbmV3IFZlYzIuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBWZWMyLgogICAgICAgICAqLwogICAgICAgIGNsb25lKCkgewogICAgICAgICAgICByZXR1cm4gbmV3IEJveDIodGhpcy5wMC5jbG9uZSgpLCB0aGlzLnAxLmNsb25lKCkpOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBFbmNvZGVzIGBCb3gyYCBDbGFzcyBhcyBhIEpTT04gb2JqZWN0IGZvciBwZXJzaXN0ZW5jZS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUganNvbiBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgdG9KU09OKCkgewogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgcDA6IHRoaXMucDAudG9KU09OKCksCiAgICAgICAgICAgICAgICBwMTogdGhpcy5wMS50b0pTT04oKSwKICAgICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogRGVjb2RlcyBhIEpTT04gb2JqZWN0IHRvIHNldCB0aGUgc3RhdGUgb2YgdGhpcyBjbGFzcy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBqIC0gVGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIGZyb21KU09OKGopIHsKICAgICAgICAgICAgLy8gV2UgbmVlZCB0byB2ZXJpZnkgdGhhdCBwMCBhbmQgcDEgYXhlcyBhcmUgbnVtZXJpYywgc28gaW4gY2FzZSB0aGV5IGFyZSBub3QsIHdlIHJlc3RvcmUgdGhlbSB0byB0aGVpciBkZWZhdWx0IHZhbHVlcy4KICAgICAgICAgICAgLy8gVGhpcywgYmVjYXVzZSAnSW5maW5pdHknIGFuZCAnLUluZmluaXR5JyBhcmUgc3RyaW5naWZpZWQgYXMgJ251bGwnLgogICAgICAgICAgICBjb25zdCBwMCA9IHsKICAgICAgICAgICAgICAgIHg6IE1hdGhGdW5jdGlvbnMuaXNOdW1lcmljKGoucDAueCkgPyBqLnAwLnggOiBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksCiAgICAgICAgICAgICAgICB5OiBNYXRoRnVuY3Rpb25zLmlzTnVtZXJpYyhqLnAwLnkpID8gai5wMC55IDogTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLAogICAgICAgICAgICB9OwogICAgICAgICAgICBjb25zdCBwMSA9IHsKICAgICAgICAgICAgICAgIHg6IE1hdGhGdW5jdGlvbnMuaXNOdW1lcmljKGoucDEueCkgPyBqLnAxLnggOiBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFksCiAgICAgICAgICAgICAgICB5OiBNYXRoRnVuY3Rpb25zLmlzTnVtZXJpYyhqLnAxLnkpID8gai5wMS55IDogTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZLAogICAgICAgICAgICB9OwogICAgICAgICAgICB0aGlzLnAwLmZyb21KU09OKHAwKTsKICAgICAgICAgICAgdGhpcy5wMS5mcm9tSlNPTihwMSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGxzIGB0b0pTT05gIG1ldGhvZCBhbmQgc3RyaW5naWZpZXMgaXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICB0b1N0cmluZygpIHsKICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5ldy1jYXAKICAgICAgICAgICAgcmV0dXJuIFN0cmluZ0Z1bmN0aW9ucy5zdHJpbmdpZnlKU09OV2l0aEZpeGVkUHJlY2lzaW9uKHRoaXMudG9KU09OKCkpOwogICAgICAgIH0KICAgIH0KCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBuZXctY2FwICovCiAgICAvKioKICAgICAqIENsYXNzIHJlcHJlc2VudGluZyBhIG1hdGhlbWF0aWNhbCBzcGhlcmUsIGFzIG9wcG9zZWQgdG8gdGhlIFNwaGVyZSBjbGFzcyBkZXJpdmVkIGZyb20gUHJvY2VkdXJhbE1lc2guCiAgICAgKgogICAgICovCiAgICBjbGFzcyBTcGhlcmVUeXBlIHsKICAgICAgICBwb3M7CiAgICAgICAgcmFkaXVzOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIHNwaGVyZS4KICAgICAgICAgKiBAcGFyYW0gcG9zIC0gVGhlIHBvc2l0aW9uIG9mIHRoZSBzcGhlcmUuCiAgICAgICAgICogQHBhcmFtIHJhZGl1cyAtIFRoZSByYWRpdXMgb2YgdGhlIHNwaGVyZS4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3Rvcihwb3MgPSBuZXcgVmVjMygpLCByYWRpdXMgPSAwKSB7CiAgICAgICAgICAgIGlmIChwb3MgaW5zdGFuY2VvZiBWZWMzKSB7CiAgICAgICAgICAgICAgICB0aGlzLnBvcyA9IHBvczsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHRoaXMucG9zID0gbmV3IFZlYzMoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnJhZGl1cyA9IHJhZGl1czsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2xvbmVzIHRoaXMgc3BoZXJlIGFuZCByZXR1cm5zIGEgbmV3IHNwaGVyZS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IHNwaGVyZS4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBTcGhlcmVUeXBlKHRoaXMucG9zLmNsb25lKCksIHRoaXMucmFkaXVzKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2hlY2tzIGlmIHRoaXMgc3BoZXJlIGludGVyc2VjdHMgYSBib3guCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gYm94IC0gVGhlIGJveCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBpbnRlcnNlY3RzQm94KGJveCkgewogICAgICAgICAgICByZXR1cm4gYm94LmludGVyc2VjdHNTcGhlcmUodGhpcyk7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIFBlcnNpc3RlbmNlCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHRvSlNPTiBtZXRob2QgZW5jb2RlcyB0aGlzIHR5cGUgYXMgYSBqc29uIG9iamVjdCBmb3IgcGVyc2lzdGVuY2UuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIHRvSlNPTigpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIHBvczogdGhpcy5wb3MudG9KU09OKCksCiAgICAgICAgICAgICAgICByYWRpdXM6IHRoaXMucmFkaXVzLAogICAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDYWxscyBgdG9KU09OYCBtZXRob2QgYW5kIHN0cmluZ2lmaWVzIGl0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgdG9TdHJpbmcoKSB7CiAgICAgICAgICAgIHJldHVybiBTdHJpbmdGdW5jdGlvbnMuc3RyaW5naWZ5SlNPTldpdGhGaXhlZFByZWNpc2lvbih0aGlzLnRvSlNPTigpKTsKICAgICAgICB9CiAgICB9CgogICAgLyoqCiAgICAgKiBDbGFzcyByZXByZXNlbnRpbmcgYSBib3ggaW4gM0Qgc3BhY2UuCiAgICAgKiBSZXByZXNlbnRzIGEgYm94IGluIDNEIHNwYWNlIGRlZmluZWQgYnkgdHdvIFZlYzMgdmFsdWVzIHdoaWNoIGRlZmluZSBvcHBvc2luZyBjb3JuZXJzIG9mIHRoZSBib3guCiAgICAgKi8KICAgIGNsYXNzIEJveDMgewogICAgICAgIHAwOwogICAgICAgIHAxOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYSBCb3gzIG9iamVjdCB1c2luZyBWZWMzcy4KICAgICAgICAgKiBJbiBjYXNlIHRoZSBwYXJhbWV0ZXJzIGFyZSBub3QgcGFzc2VkIGJ5LCB0aGVpciB2YWx1ZXMgYXJlIHByZS1kZWZpbmVkOgogICAgICAgICAqCiAgICAgICAgICogcDAgaXMgYSBWZWMyIHdpdGgge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL051bWJlci9QT1NJVElWRV9JTkZJTklUWXxgTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZYH0KICAgICAgICAgKgogICAgICAgICAqIHAxIGlzIGEgVmVjMiB3aXRoIHtAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9OdW1iZXIvTkVHQVRJVkVfSU5GSU5JVFl8YE51bWJlci5ORUdBVElWRV9JTkZJTklUWWB9CiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcDAgLSBBIHBvaW50IHJlcHJlc2VudGluZyB0aGUgY29ybmVycyBvZiBhIDNEIGJveC4KICAgICAgICAgKiBAcGFyYW0gcDEgLSBBIHBvaW50IHJlcHJlc2VudGluZyB0aGUgY29ybmVycyBvZiBhIDNEIGJveC4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3RvcihwMCA9IG5ldyBWZWMzKE51bWJlci5QT1NJVElWRV9JTkZJTklUWSwgTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLCBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkpLCBwMSA9IG5ldyBWZWMzKE51bWJlci5ORUdBVElWRV9JTkZJTklUWSwgTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZLCBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFkpKSB7CiAgICAgICAgICAgIHRoaXMucDAgPSBwMDsKICAgICAgICAgICAgdGhpcy5wMSA9IHAxOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBHZXR0ZXIgZm9yIHRoZSBsb3dlciAoeCwgeSwgeikgYm91bmRhcnkgb2YgdGhlIGJveC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBtaW5pbXVtIFZlYzMuCiAgICAgICAgICovCiAgICAgICAgZ2V0IG1pbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMucDA7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHRlciBmb3IgdGhlIHVwcGVyICh4LCB5LCB6KSBib3VuZGFyeSBvZiB0aGUgYm94LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIG1heGltdW0gVmVjMy4KICAgICAgICAgKi8KICAgICAgICBnZXQgbWF4KCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5wMTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyBib3RoIFZlYzMgcG9pbnRzCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcDAgLSBBIHBvaW50IHJlcHJlc2VudGluZyB0aGUgY29ybmVycyBvZiBhIDNEIGJveC4KICAgICAgICAgKiBAcGFyYW0gcDEgLSBBIHBvaW50IHJlcHJlc2VudGluZyB0aGUgY29ybmVycyBvZiBhIDNEIGJveC4KICAgICAgICAgKi8KICAgICAgICBzZXQocDAsIHAxKSB7CiAgICAgICAgICAgIHRoaXMucDAgPSBwMDsKICAgICAgICAgICAgdGhpcy5wMSA9IHAxOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXNldHMgdGhlIGJveDMgYmFjayB0byBhbiB1bmluaXRpYWxpemVkIHN0YXRlLgogICAgICAgICAqLwogICAgICAgIHJlc2V0KCkgewogICAgICAgICAgICB0aGlzLnAwLnggPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7CiAgICAgICAgICAgIHRoaXMucDAueSA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTsKICAgICAgICAgICAgdGhpcy5wMC56ID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgICAgICAgICB0aGlzLnAxLnggPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7CiAgICAgICAgICAgIHRoaXMucDEueSA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTsKICAgICAgICAgICAgdGhpcy5wMS56ID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYm94IGhhcyBiZWVuIGV4cGFuZGVkIHRvIGNvbnRhaW4gYSBwb2ludC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGlzVmFsaWQoKSB7CiAgICAgICAgICAgIHJldHVybiAodGhpcy5wMC54ICE9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWSAmJgogICAgICAgICAgICAgICAgdGhpcy5wMS54ICE9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWSAmJgogICAgICAgICAgICAgICAgdGhpcy5wMC55ICE9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWSAmJgogICAgICAgICAgICAgICAgdGhpcy5wMS55ICE9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWSAmJgogICAgICAgICAgICAgICAgdGhpcy5wMC56ICE9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWSAmJgogICAgICAgICAgICAgICAgdGhpcy5wMS56ICE9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEV4cGFuZHMgdGhlIEJveDMgdG8gY29udGFpbiB0aGUgbmV3IHBvaW50LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHBvaW50IC0gQSBwb2ludCByZXByZXNlbnRzIHRoZSBjb3JuZXJzIG9mIGEgM0QgYm94LgogICAgICAgICAqLwogICAgICAgIGFkZFBvaW50KHBvaW50KSB7CiAgICAgICAgICAgIGlmIChwb2ludC54ICE9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWSAmJiBwb2ludC54ICE9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWSkgewogICAgICAgICAgICAgICAgaWYgKHBvaW50LnggPCB0aGlzLnAwLngpCiAgICAgICAgICAgICAgICAgICAgdGhpcy5wMC54ID0gcG9pbnQueDsKICAgICAgICAgICAgICAgIGlmIChwb2ludC54ID4gdGhpcy5wMS54KQogICAgICAgICAgICAgICAgICAgIHRoaXMucDEueCA9IHBvaW50Lng7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHBvaW50LnkgIT0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZICYmIHBvaW50LnkgIT0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZKSB7CiAgICAgICAgICAgICAgICBpZiAocG9pbnQueSA8IHRoaXMucDAueSkKICAgICAgICAgICAgICAgICAgICB0aGlzLnAwLnkgPSBwb2ludC55OwogICAgICAgICAgICAgICAgaWYgKHBvaW50LnkgPiB0aGlzLnAxLnkpCiAgICAgICAgICAgICAgICAgICAgdGhpcy5wMS55ID0gcG9pbnQueTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocG9pbnQueiAhPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkgJiYgcG9pbnQueiAhPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFkpIHsKICAgICAgICAgICAgICAgIGlmIChwb2ludC56IDwgdGhpcy5wMC56KQogICAgICAgICAgICAgICAgICAgIHRoaXMucDAueiA9IHBvaW50Lno7CiAgICAgICAgICAgICAgICBpZiAocG9pbnQueiA+IHRoaXMucDEueikKICAgICAgICAgICAgICAgICAgICB0aGlzLnAxLnogPSBwb2ludC56OwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEFkZHMgYEJveDNgIHRvIHRoaXMgYEJveDNgLCBvZiB0aGUgWGZvIGluc3RhbmNlIGlzIHBhc3NlZCBpbiB0aGUgcGFyYW1ldGVycwogICAgICAgICAqIGl0IHByb2NlZWRzIHRvIGFwcGx5IHRoZSB0cmFuc2Zvcm0gZm9yIHRoZSBWZWMzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGJveDMgLSBBIDNEIGJveC4KICAgICAgICAgKiBAcGFyYW0geGZvIC0gQSAzRCB0cmFuc2Zvcm0uCiAgICAgICAgICovCiAgICAgICAgYWRkQm94Myhib3gzLCB0cmFuc2Zvcm0pIHsKICAgICAgICAgICAgaWYgKHRyYW5zZm9ybSkgewogICAgICAgICAgICAgICAgLy8gVHJhbnNmb3JtIGVhY2ggY29ybmVyIG9mIHRoZSBCb3gzIGludG8gdGhlIG5ldyBjb29yZGluYXRlIHN5c3RlbS4KICAgICAgICAgICAgICAgIHRoaXMuYWRkUG9pbnQodHJhbnNmb3JtLnRyYW5zZm9ybVZlYzMoYm94My5wMCkpOwogICAgICAgICAgICAgICAgdGhpcy5hZGRQb2ludCh0cmFuc2Zvcm0udHJhbnNmb3JtVmVjMyhuZXcgVmVjMyhib3gzLnAwLngsIGJveDMucDAueSwgYm94My5wMS56KSkpOwogICAgICAgICAgICAgICAgdGhpcy5hZGRQb2ludCh0cmFuc2Zvcm0udHJhbnNmb3JtVmVjMyhuZXcgVmVjMyhib3gzLnAwLngsIGJveDMucDEueSwgYm94My5wMC56KSkpOwogICAgICAgICAgICAgICAgdGhpcy5hZGRQb2ludCh0cmFuc2Zvcm0udHJhbnNmb3JtVmVjMyhuZXcgVmVjMyhib3gzLnAxLngsIGJveDMucDAueSwgYm94My5wMC56KSkpOwogICAgICAgICAgICAgICAgdGhpcy5hZGRQb2ludCh0cmFuc2Zvcm0udHJhbnNmb3JtVmVjMyhuZXcgVmVjMyhib3gzLnAwLngsIGJveDMucDEueSwgYm94My5wMS56KSkpOwogICAgICAgICAgICAgICAgdGhpcy5hZGRQb2ludCh0cmFuc2Zvcm0udHJhbnNmb3JtVmVjMyhuZXcgVmVjMyhib3gzLnAxLngsIGJveDMucDAueSwgYm94My5wMS56KSkpOwogICAgICAgICAgICAgICAgdGhpcy5hZGRQb2ludCh0cmFuc2Zvcm0udHJhbnNmb3JtVmVjMyhuZXcgVmVjMyhib3gzLnAxLngsIGJveDMucDEueSwgYm94My5wMC56KSkpOwogICAgICAgICAgICAgICAgdGhpcy5hZGRQb2ludCh0cmFuc2Zvcm0udHJhbnNmb3JtVmVjMyhib3gzLnAxKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB0aGlzLmFkZFBvaW50KGJveDMucDApOwogICAgICAgICAgICAgICAgdGhpcy5hZGRQb2ludChib3gzLnAxKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBsZW5ndGggb2YgdGhlIGRpYWdvbmFsIG9mIHRoZSBib3guCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgZGlzdGFuY2UuCiAgICAgICAgICovCiAgICAgICAgc2l6ZSgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMucDEuZGlzdGFuY2VUbyh0aGlzLnAwKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgZGlhZ29uYWwgdmVjdG9yIG9mIHRoZSBCPWJveCBmcm9tIHAwIHRvIHAxLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBCb3gzLgogICAgICAgICAqLwogICAgICAgIGRpYWdvbmFsKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5wMS5zdWJ0cmFjdCh0aGlzLnAwKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgY2VudGVyIHBvaW50IG9mIGEgQm94My4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgVmVjMy4KICAgICAgICAgKi8KICAgICAgICBjZW50ZXIoKSB7CiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMucDEuc3VidHJhY3QodGhpcy5wMCk7CiAgICAgICAgICAgIHJlc3VsdC5zY2FsZUluUGxhY2UoMC41KTsKICAgICAgICAgICAgcmVzdWx0LmFkZEluUGxhY2UodGhpcy5wMCk7CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENvbnZlcnRzIHRoaXMgQm94MyB0byBhIE1hdDQgKGEgNHg0IG1hdHJpeCkuIFRoZSByZXR1cm5lZCBtYXQ0IHdvdWxkIHRyYW5zZm9ybSBhIHVuaXQgY3ViZSBpbnRvIHRoZSBzaGFwZSBvZiB0aGUgQm91bmRpbmcgYm94LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgTWF0NC4KICAgICAgICAgKi8KICAgICAgICB0b01hdDQoKSB7CiAgICAgICAgICAgIGNvbnN0IHNjeCA9IHRoaXMucDEueCAtIHRoaXMucDAueDsKICAgICAgICAgICAgY29uc3Qgc2N5ID0gdGhpcy5wMS55IC0gdGhpcy5wMC55OwogICAgICAgICAgICBjb25zdCBzY3ogPSB0aGlzLnAxLnogLSB0aGlzLnAwLno7CiAgICAgICAgICAgIHJldHVybiBuZXcgTWF0NChzY3gsIDAsIDAsIDAsIDAsIHNjeSwgMCwgMCwgMCwgMCwgc2N6LCAwLCB0aGlzLnAwLngsIHRoaXMucDAueSwgdGhpcy5wMC56LCAxLjApOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDYWxjdWxhdGVzIGFuZCByZXR1cm5zIHRoZSBib3VuZGluZyBTcGhlcmUgb2YgdGhlIEJveDMKICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldEJvdW5kaW5nU3BoZXJlKCkgewogICAgICAgICAgICByZXR1cm4gbmV3IFNwaGVyZVR5cGUodGhpcy5jZW50ZXIoKSwgdGhpcy5kaWFnb25hbCgpLmxlbmd0aCgpICogMC41KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogRGV0ZXJtaW5lcyBpZiB0aGlzIEJveDMgaW50ZXJzZWN0cyBhIGdpdmVuIGJveCB2YWx1ZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBib3ggLSBUaGUgYm94IHRvIGNoZWNrIGZvciBpbnRlcnNlY3Rpb24gYWdhaW5zdC4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0cnVlIGlmIHRoZSBzaGFwZXMgaW50ZXJzZWN0LgogICAgICAgICAqLwogICAgICAgIGludGVyc2VjdHNCb3goYm94KSB7CiAgICAgICAgICAgIC8vIFVzaW5nIDYgc3BsaXR0aW5nIHBsYW5lcyB0byBydWxlIG91dCBpbnRlcnNlY3Rpb25zLgogICAgICAgICAgICByZXR1cm4gYm94Lm1heC54IDwgdGhpcy5taW4ueCB8fAogICAgICAgICAgICAgICAgYm94Lm1pbi54ID4gdGhpcy5tYXgueCB8fAogICAgICAgICAgICAgICAgYm94Lm1heC55IDwgdGhpcy5taW4ueSB8fAogICAgICAgICAgICAgICAgYm94Lm1pbi55ID4gdGhpcy5tYXgueSB8fAogICAgICAgICAgICAgICAgYm94Lm1heC56IDwgdGhpcy5taW4ueiB8fAogICAgICAgICAgICAgICAgYm94Lm1pbi56ID4gdGhpcy5tYXguegogICAgICAgICAgICAgICAgPyBmYWxzZQogICAgICAgICAgICAgICAgOiB0cnVlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBEZXRlcm1pbmVzIGlmIHRoaXMgQm94MyBpbnRlcnNlY3RzIGEgc3BoZXJlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHNwaGVyZSAtIFRoZSBzcGhlcmUgdG8gY2hlY2sgZm9yIGludGVyc2VjdGlvbiBhZ2FpbnN0LgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRydWUgaWYgdGhlIHNoYXBlcyBpbnRlcnNlY3QuCiAgICAgICAgICovCiAgICAgICAgaW50ZXJzZWN0c1NwaGVyZShzcGhlcmUpIHsKICAgICAgICAgICAgbGV0IGNsb3Nlc3RQb2ludCA9IG5ldyBWZWMzKCk7CiAgICAgICAgICAgIC8vIEZpbmQgdGhlIHBvaW50IG9uIHRoZSBBQUJCIGNsb3Nlc3QgdG8gdGhlIHNwaGVyZSBjZW50ZXIuCiAgICAgICAgICAgIC8vIHRoaXMuY2xhbXBQb2ludCggc3BoZXJlLmNlbnRlciwgY2xvc2VzdFBvaW50ICk7CiAgICAgICAgICAgIC8vIElmIHRoYXQgcG9pbnQgaXMgaW5zaWRlIHRoZSBzcGhlcmUsIHRoZSBBQUJCIGFuZCBzcGhlcmUgaW50ZXJzZWN0LgogICAgICAgICAgICByZXR1cm4gY2xvc2VzdFBvaW50LmRpc3RhbmNlVG8oc3BoZXJlLnBvcykgPD0gc3BoZXJlLnJhZGl1cyAqIHNwaGVyZS5yYWRpdXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIERldGVybWluZXMgaWYgdGhpcyBCb3gzIGludGVyc2VjdHMgYSBwbGFuZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBwbGFuZSAtIFRoZSBwbGFuZSB0byBjaGVjayBmb3IgaW50ZXJzZWN0aW9uIGFnYWluc3QuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgaW50ZXJzZWN0c1BsYW5lKHBsYW5lKSB7CiAgICAgICAgICAgIC8vIFdlIGNvbXB1dGUgdGhlIG1pbmltdW0gYW5kIG1heGltdW0gZG90IHByb2R1Y3QgdmFsdWVzLiBJZiB0aG9zZSB2YWx1ZXMKICAgICAgICAgICAgLy8gYXJlIG9uIHRoZSBzYW1lIHNpZGUgKGJhY2sgb3IgZnJvbnQpIG9mIHRoZSBwbGFuZSwgdGhlbiB0aGVyZSBpcyBubyBpbnRlcnNlY3Rpb24uCiAgICAgICAgICAgIGxldCBtaW47CiAgICAgICAgICAgIGxldCBtYXg7CiAgICAgICAgICAgIGlmIChwbGFuZS5ub3JtYWwueCA+IDApIHsKICAgICAgICAgICAgICAgIG1pbiA9IHBsYW5lLm5vcm1hbC54ICogdGhpcy5taW4ueDsKICAgICAgICAgICAgICAgIG1heCA9IHBsYW5lLm5vcm1hbC54ICogdGhpcy5tYXgueDsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIG1pbiA9IHBsYW5lLm5vcm1hbC54ICogdGhpcy5tYXgueDsKICAgICAgICAgICAgICAgIG1heCA9IHBsYW5lLm5vcm1hbC54ICogdGhpcy5taW4ueDsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocGxhbmUubm9ybWFsLnkgPiAwKSB7CiAgICAgICAgICAgICAgICBtaW4gKz0gcGxhbmUubm9ybWFsLnkgKiB0aGlzLm1pbi55OwogICAgICAgICAgICAgICAgbWF4ICs9IHBsYW5lLm5vcm1hbC55ICogdGhpcy5tYXgueTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIG1pbiArPSBwbGFuZS5ub3JtYWwueSAqIHRoaXMubWF4Lnk7CiAgICAgICAgICAgICAgICBtYXggKz0gcGxhbmUubm9ybWFsLnkgKiB0aGlzLm1pbi55OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChwbGFuZS5ub3JtYWwueiA+IDApIHsKICAgICAgICAgICAgICAgIG1pbiArPSBwbGFuZS5ub3JtYWwueiAqIHRoaXMubWluLno7CiAgICAgICAgICAgICAgICBtYXggKz0gcGxhbmUubm9ybWFsLnogKiB0aGlzLm1heC56OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgbWluICs9IHBsYW5lLm5vcm1hbC56ICogdGhpcy5tYXguejsKICAgICAgICAgICAgICAgIG1heCArPSBwbGFuZS5ub3JtYWwueiAqIHRoaXMubWluLno7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIG1pbiA8PSAtcGxhbmUudyAmJiBtYXggPj0gLXBsYW5lLnc7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENsb25lcyB0aGlzIEJveDMgYW5kIHJldHVybnMgYSBuZXcgQm94My4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBCb3gzLgogICAgICAgICAqLwogICAgICAgIGNsb25lKCkgewogICAgICAgICAgICByZXR1cm4gbmV3IEJveDModGhpcy5wMC5jbG9uZSgpLCB0aGlzLnAxLmNsb25lKCkpOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBFbmNvZGVzIGBCb3gzYCBDbGFzcyBhcyBhIEpTT04gb2JqZWN0IGZvciBwZXJzaXN0ZW5jZS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUganNvbiBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgdG9KU09OKCkgewogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgcDA6IHRoaXMucDAudG9KU09OKCksCiAgICAgICAgICAgICAgICBwMTogdGhpcy5wMS50b0pTT04oKSwKICAgICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogRGVjb2RlcyBhIEpTT04gb2JqZWN0IHRvIHNldCB0aGUgc3RhdGUgb2YgdGhpcyBjbGFzcy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBqIC0gVGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIGZyb21KU09OKGopIHsKICAgICAgICAgICAgLy8gV2UgbmVlZCB0byB2ZXJpZnkgdGhhdCBwMCBhbmQgcDEgYXhlcyBhcmUgbnVtZXJpYywgc28gaW4gY2FzZSB0aGV5IGFyZSBub3QsIHdlIHJlc3RvcmUgdGhlbSB0byB0aGVpciBkZWZhdWx0IHZhbHVlcy4KICAgICAgICAgICAgLy8gVGhpcywgYmVjYXVzZSAnSW5maW5pdHknIGFuZCAnLUluZmluaXR5JyBhcmUgc3RyaW5naWZpZWQgYXMgJ251bGwnLgogICAgICAgICAgICBjb25zdCBwMCA9IHsKICAgICAgICAgICAgICAgIHg6IE1hdGhGdW5jdGlvbnMuaXNOdW1lcmljKGoucDAueCkgPyBqLnAwLnggOiBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksCiAgICAgICAgICAgICAgICB5OiBNYXRoRnVuY3Rpb25zLmlzTnVtZXJpYyhqLnAwLnkpID8gai5wMC55IDogTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLAogICAgICAgICAgICAgICAgejogTWF0aEZ1bmN0aW9ucy5pc051bWVyaWMoai5wMC56KSA/IGoucDAueiA6IE51bWJlci5QT1NJVElWRV9JTkZJTklUWSwKICAgICAgICAgICAgfTsKICAgICAgICAgICAgY29uc3QgcDEgPSB7CiAgICAgICAgICAgICAgICB4OiBNYXRoRnVuY3Rpb25zLmlzTnVtZXJpYyhqLnAxLngpID8gai5wMS54IDogTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZLAogICAgICAgICAgICAgICAgeTogTWF0aEZ1bmN0aW9ucy5pc051bWVyaWMoai5wMS55KSA/IGoucDEueSA6IE51bWJlci5ORUdBVElWRV9JTkZJTklUWSwKICAgICAgICAgICAgICAgIHo6IE1hdGhGdW5jdGlvbnMuaXNOdW1lcmljKGoucDEueikgPyBqLnAxLnogOiBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFksCiAgICAgICAgICAgIH07CiAgICAgICAgICAgIHRoaXMucDAuZnJvbUpTT04ocDApOwogICAgICAgICAgICB0aGlzLnAxLmZyb21KU09OKHAxKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsbHMgYHRvSlNPTmAgbWV0aG9kIGFuZCBzdHJpbmdpZmllcyBpdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHRvU3RyaW5nKCkgewogICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbmV3LWNhcAogICAgICAgICAgICByZXR1cm4gU3RyaW5nRnVuY3Rpb25zLnN0cmluZ2lmeUpTT05XaXRoRml4ZWRQcmVjaXNpb24odGhpcy50b0pTT04oKSk7CiAgICAgICAgfQogICAgfQoKICAgIGxldCBudW1CYXNlSXRlbXMgPSAwOwogICAgLyoqCiAgICAgKiBCYXNlIGNsYXNzIGZvciBJdGVtcyBpbiB0aGUgc2NlbmUuIEl0IGNhbiBiZSBwYXJhbWV0ZXJpemVkIGFuZCBjYW4gZW1pdCBldmVudHMuCiAgICAgKgogICAgICogKipFdmVudHMqKgogICAgICogKiAqKm5hbWVDaGFuZ2VkOioqIEVtaXR0ZWQgZXZlcnkgdGltZSB0aGUgSXRlbSdzIG5hbWUgaXMgY2hhbmdlLiBtb3N0bHkgaW4gYHNldE5hbWVgIG1ldGhvZC4KICAgICAqICogKipzZWxlY3RlZENoYW5nZWQ6KiogRW1pdHRlZCBgc2VsZWN0ZWRgIHN0YXR1cyBjaGFuZ2VzLCBtb3N0bHkgaW4gYHNldFNlbGVjdGVkYCBtZXRob2QuCiAgICAgKgogICAgICogQGV4dGVuZHMge0V2ZW50RW1pdHRlcn0KICAgICAqLwogICAgY2xhc3MgQmFzZUl0ZW0gZXh0ZW5kcyBFdmVudEVtaXR0ZXIgewogICAgICAgICNuYW1lOwogICAgICAgICNvd25lckl0ZW0gPSB1bmRlZmluZWQ7CiAgICAgICAgc2VsZWN0ZWQgPSBmYWxzZTsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgYSBiYXNlIGl0ZW0gYnkgZGVmaW5pbmcgaXRzIG5hbWUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBiYXNlIGl0ZW0uCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IobmFtZSA9ICcnKSB7CiAgICAgICAgICAgIHN1cGVyKCk7CiAgICAgICAgICAgIHRoaXMuI25hbWUgPSBuYW1lOwogICAgICAgICAgICBudW1CYXNlSXRlbXMrKzsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIFN0YXRpYyBNZXRob2RzCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGdldE51bUJhc2VJdGVtcyBtZXRob2QgcmV0dXJucyB0aGUgdG90YWwgbnVtYmVyIG9mIGJhc2UgaXRlbXMgY3JlYXRlZC4KICAgICAgICAgKiBUaGlzIG1ldGhvZCBpcyB1c2VkIGluIGRlYnVnZ2luZyBtZW1vcnkgY29uc3VtcHRpb24uCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgdG90YWwgbnVtYmVyIG9mIGJhc2UgaXRlbXMgY3JlYXRlZC4KICAgICAgICAgKi8KICAgICAgICBzdGF0aWMgZ2V0TnVtQmFzZUl0ZW1zKCkgewogICAgICAgICAgICByZXR1cm4gbnVtQmFzZUl0ZW1zOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gTmFtZSBhbmQgUGF0aAogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIG5hbWUgb2YgdGhlIGJhc2UgaXRlbS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBiYXNlIGl0ZW0gbmFtZS4KICAgICAgICAgKi8KICAgICAgICBnZXQgbmFtZSgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuI25hbWU7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIG5hbWUgb2YgdGhlIGJhc2UgaXRlbShVcGRhdGVzIHBhdGgpLgogICAgICAgICAqCiAgICAgICAgICogQGVtaXRzIGBuYW1lQ2hhbmdlZGAgd2l0aCBgbmV3TmFtZWAgYW5kIGBvbGROYW1lYCBkYXRhLgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIGJhc2UgaXRlbSBuYW1lLgogICAgICAgICAqLwogICAgICAgIHNldCBuYW1lKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICh0aGlzLiNuYW1lICE9IHZhbHVlKSB7CiAgICAgICAgICAgICAgICBjb25zdCBvbGROYW1lID0gdGhpcy4jbmFtZTsKICAgICAgICAgICAgICAgIHRoaXMuI25hbWUgPSB2YWx1ZTsKICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0gbmV3IE5hbWVDaGFuZ2VkRXZlbnQob2xkTmFtZSwgdmFsdWUpOwogICAgICAgICAgICAgICAgdGhpcy5lbWl0KCduYW1lQ2hhbmdlZCcsIGV2ZW50KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHBhdGggb2YgdGhlIGl0ZW0gaW4gdGhlIHRyZWUgYXMgYW4gYXJyYXkgb2YgbmFtZXMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhbiBhcnJheS4KICAgICAgICAgKi8KICAgICAgICBnZXQgcGF0aCgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UGF0aCgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHBhdGggb2YgdGhlIGl0ZW0gaW4gdGhlIHRyZWUgYXMgYW4gYXJyYXkgb2YgbmFtZXMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhbiBhcnJheS4KICAgICAgICAgKi8KICAgICAgICBnZXQgb3duZXJJdGVtKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy4jb3duZXJJdGVtOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBuYW1lIG9mIHRoZSBiYXNlIGl0ZW0uCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgYmFzZSBpdGVtIG5hbWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0TmFtZSgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuI25hbWU7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIG5hbWUgb2YgdGhlIGJhc2UgaXRlbShVcGRhdGVzIHBhdGgpLgogICAgICAgICAqCiAgICAgICAgICogQGVtaXRzIGBuYW1lQ2hhbmdlZGAgd2l0aCBgbmV3TmFtZWAgYW5kIGBvbGROYW1lYCBkYXRhLgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIGJhc2UgaXRlbSBuYW1lLgogICAgICAgICAqLwogICAgICAgIHNldE5hbWUobmFtZSkgewogICAgICAgICAgICB0aGlzLm5hbWUgPSBuYW1lOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHBhdGggb2YgdGhlIGl0ZW0gaW4gdGhlIHRyZWUgYXMgYW4gYXJyYXkgb2YgbmFtZXMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhbiBhcnJheS4KICAgICAgICAgKi8KICAgICAgICBnZXRQYXRoKCkgewogICAgICAgICAgICBpZiAodGhpcy4jb3duZXJJdGVtID09IHVuZGVmaW5lZCkKICAgICAgICAgICAgICAgIHJldHVybiBbdGhpcy4jbmFtZV07CiAgICAgICAgICAgIHJldHVybiBbLi4udGhpcy4jb3duZXJJdGVtLmdldFBhdGgoKSwgdGhpcy4jbmFtZV07CiAgICAgICAgfQogICAgICAgIC8vIFBhdGggVHJhdmVyc2FsCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHJlc29sdmVQYXRoIG1ldGhvZCB0cmF2ZXJzZXMgdGhlIHN1YnRyZWUgZnJvbSB0aGlzIGl0ZW0gZG93bgogICAgICAgICAqIG1hdGNoaW5nIGVhY2ggbmFtZSBpbiB0aGUgcGF0aCB3aXRoIGEgY2hpbGQgdW50aWwgaXQgcmVhY2hlcyB0aGUKICAgICAgICAgKiBlbmQgb2YgdGhlIHBhdGguCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcGF0aCAtIFRoZSBwYXRoIHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICByZXNvbHZlUGF0aChwYXRoLCBpbmRleCA9IDApIHsKICAgICAgICAgICAgaWYgKGluZGV4ID09IDApIHsKICAgICAgICAgICAgICAgIGlmIChwYXRoWzBdID09ICcuJyB8fCBwYXRoWzBdID09IHRoaXMuI25hbWUpCiAgICAgICAgICAgICAgICAgICAgaW5kZXgrKzsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocGF0aFtpbmRleF0gPT0gJy4uJykgewogICAgICAgICAgICAgICAgaWYgKHRoaXMuI293bmVySXRlbSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiNvd25lckl0ZW0ucmVzb2x2ZVBhdGgocGF0aCwgaW5kZXggKyAxKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIHRocm93IEVycm9yKCd0aGlzLiNvd25lckl0ZW0gaXMgdW5kZWZpbmVkJyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGluZGV4ID09IHBhdGgubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gT3duZXIgSXRlbQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBnZXRPd25lciBtZXRob2QgcmV0dXJucyB0aGUgY3VycmVudCBvd25lciBvZiB0aGUgaXRlbS4KICAgICAgICAgKiBUaGUgaXRlbSBpcyBhIGNoaWxkIG9mIHRoZSBjdXJyZW50IG93bmVyLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGN1cnJlbnQgb3duZXIuCiAgICAgICAgICovCiAgICAgICAgZ2V0T3duZXIoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLiNvd25lckl0ZW07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBzZXRPd25lciBtZXRob2QgYXNzaWducyBhIG5ldyBvd25lciB0byB0aGUgaXRlbS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvd25lckl0ZW0gLSBUaGUgbmV3IG93bmVyIGl0ZW0uCiAgICAgICAgICovCiAgICAgICAgc2V0T3duZXIob3duZXJJdGVtKSB7CiAgICAgICAgICAgIHRoaXMuI293bmVySXRlbSA9IG93bmVySXRlbTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIFNlbGVjdGlvbgogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBpc1NlbGVjdGVkIG1ldGhvZC4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBpc1NlbGVjdGVkKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5zZWxlY3RlZDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2hhbmdlcyB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgc2VsZWN0aW9uIG9mIHRoaXMgaXRlbS4KICAgICAgICAgKgogICAgICAgICAqIEBlbWl0cyBgc2VsZWN0ZWRDaGFuZ2VkYCB3aXRoIHNlbGVjdGVkIHN0YXRlCiAgICAgICAgICogQHBhcmFtIHNlbCAtIEJvb2xlYW4gaW5kaWNhdGluZyB0aGUgbmV3IHNlbGVjdGlvbiBzdGF0ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRTZWxlY3RlZChzZWwpIHsKICAgICAgICAgICAgdGhpcy5zZWxlY3RlZCA9IHNlbDsKICAgICAgICAgICAgbGV0IGV2ZW50ID0gbmV3IFNlbGVjdGVkRXZlbnQodGhpcy5zZWxlY3RlZCk7CiAgICAgICAgICAgIHRoaXMuZW1pdCgnc2VsZWN0ZWRDaGFuZ2VkJywgZXZlbnQpOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBFbmNvZGVzIHRoZSBjdXJyZW50IG9iamVjdCBhcyBhIGpzb24gb2JqZWN0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUganNvbiBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgdG9KU09OKGNvbnRleHQpIHsKICAgICAgICAgICAgY29uc3QganNvbiA9IHsKICAgICAgICAgICAgICAgIHR5cGU6IHRoaXMuZ2V0Q2xhc3NOYW1lKCksCiAgICAgICAgICAgICAgICBuYW1lOiB0aGlzLiNuYW1lLAogICAgICAgICAgICB9OwogICAgICAgICAgICByZXR1cm4ganNvbjsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogRGVjb2RlcyBhIGpzb24gb2JqZWN0IGZvciB0aGlzIHR5cGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0ganNvbiAtIFRoZSBqc29uIG9iamVjdCB0aGlzIGl0ZW0gbXVzdCBkZWNvZGUuCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBmcm9tSlNPTihqc29uLCBjb250ZXh0KSB7CiAgICAgICAgICAgIGlmIChqc29uLm5hbWUpCiAgICAgICAgICAgICAgICB0aGlzLiNuYW1lID0ganNvbi5uYW1lOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHN0YXRlIG9mIGN1cnJlbnQgSXRlbShJbmNsdWRpbmcgcGFyYW1ldGVycykgdXNpbmcgYSBiaW5hcnkgcmVhZGVyIG9iamVjdC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSByZWFkZXIgLSBUaGUgcmVhZGVyIHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgcmVhZEJpbmFyeShyZWFkZXIsIGNvbnRleHQpIHsKICAgICAgICAgICAgLy8gcmVhZCB0aGUgdHlwZSwgYnV0IGRvbid0IHVzZSBpdC4gVGhpcyBsaW5lIG11c3Qgbm90IGJlIHJlbW92ZWQuCiAgICAgICAgICAgIC8vIGFzIHRoZSBiaW5hcnkgcG9pbnRlciBpcyBpbmNyZW1lbnRlZC4KICAgICAgICAgICAgLypjb25zdCB0eXBlID0gKi8gcmVhZGVyLmxvYWRTdHIoKTsKICAgICAgICAgICAgdGhpcy5zZXROYW1lKHJlYWRlci5sb2FkU3RyKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDb252ZXJ0cyBvYmplY3QncyBKU09OIHZhbHVlIGFuZCBjb252ZXJ0cyBpdCB0byBhIHN0cmluZy4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dAogICAgICAgICAqIEByZXR1cm4gLSBTdHJpbmcgb2Ygb2JqZWN0J3MgcGFyYW1ldGVyIGxpc3Qgc3RhdGUuCiAgICAgICAgICovCiAgICAgICAgdG9TdHJpbmcoY29udGV4dCkgewogICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcy50b0pTT04oKSwgbnVsbCwgMik7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBDbG9uZSBhbmQgRGVzdHJveQogICAgICAgIC8qKgogICAgICAgICAqIENsb25lcyB0aGlzIGJhc2UgaXRlbSBhbmQgcmV0dXJucyBhIG5ldyBiYXNlIGl0ZW0uCiAgICAgICAgICoKICAgICAgICAgKiAqKk5vdGU6KiogRWFjaCBjbGFzcyBzaG91bGQgaW1wbGVtZW50IGNsb25lIHRvIGJlIGNsb25hYmxlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoY29udGV4dCkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy5jb25zdHJ1Y3Rvci5uYW1lICsgJyBkb2VzIG5vdCBpbXBsZW1lbnQgaXRzIGNsb25lIG1ldGhvZCcpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBXaGVuIGEgQmFzZUl0ZW0gaXMgY2xvbmVkLCBpbml0aWFsbHkgdGhlIGNvbnN0cnVjdG9yIGlzCiAgICAgICAgICogY2FsbGVkIHRvIGdlbmVyYXRlIGEgbmV3IGluc3RhbmNlLiBUaGlzIGluc3RhbmNlIHRoZW4gY29waWVzCiAgICAgICAgICogaXRzIHZhbHVlcyBmcm9tIHRoZSBzb3VyY2UgdXNpbmcgdGhpcyBtZXRob2QuCiAgICAgICAgICogVGhpcyBtZXRob2QgY29waWVzIGFueSByZWxldmFudCBkYXRhIGZyb20gdGhlIHNvdXJjZSBvYmplY3QgdG8KICAgICAgICAgKiBlbnN1cmUgdGhhdCBpdCByZXByZXNlbnRzIGEgdmFsaWQgY2xvbmUuCiAgICAgICAgICogRGVyaXZlZCBjbGFzc2VzIG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIGNvcHkgYW55IHJlbGV2YW50CiAgICAgICAgICogZGF0YSBmcm9tIHRoZSBzb3VyY2Ugb2JqZWN0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHNyYyAtIFRoZSBCYXNlSXRlbSB0byBjb3B5IGZyb20uCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZQogICAgICAgICAqLwogICAgICAgIGNvcHlGcm9tKHNyYywgY29udGV4dCkgewogICAgICAgICAgICB0aGlzLnNldE5hbWUoc3JjLmdldE5hbWUoKSk7CiAgICAgICAgfQogICAgfQoKICAgIC8qKgogICAgICogQ2xhc3MgdGhhdCBhbGxvd3Mgb3RoZXIgY2xhc3NlcyB0byBiZSBwYXJhbWV0ZXJpemVkIGJ5IGBQYXJhbWV0ZXJgIHR5cGUgb2Ygb2JqZWN0cy4KICAgICAqIE5vdCBvbmx5IGhvc3RpbmcgcGFyYW1ldGVycywgYnV0IHRoZWlyIGV2ZW50cy4KICAgICAqCiAgICAgKiBAZXh0ZW5kcyB7QmFzZUl0ZW19CiAgICAgKi8KICAgIGNsYXNzIFBhcmFtZXRlck93bmVyIGV4dGVuZHMgQmFzZUl0ZW0gewogICAgICAgIHBhcmFtRXZlbnRMaXN0ZW5lcklEcyA9IHt9OwogICAgICAgIHBhcmFtTWFwcGluZyA9IHt9OwogICAgICAgIHBhcmFtcyA9IFtdOwogICAgICAgIGRlcHJlY2F0ZWRQYXJhbU1hcHBpbmcgPSB7fTsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIFBhcmFtZXRlck93bmVyIGJ5IGluaXRpYWxpemluZyBwYXJhbWV0ZXIgaG9zdGluZyBtYXBwaW5ncyBhbmQgZXZlbnRzLgogICAgICAgICAqCiAgICAgICAgICogRXZlcnkgT2JqZWN0IGhhcyBhIHVuaXF1ZSBpZGVudGlmaWVyIHdoaWNoIGlzIGJhc2VkIG9uIGEgY291bnRlciB0aGF0IGlzIGluY3JlbWVudGVkLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKG5hbWUpIHsKICAgICAgICAgICAgc3VwZXIobmFtZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIG51bWJlciBvZiBwYXJhbWV0ZXJzIGN1cnJlbnQgb2JqZWN0IGhhcy4KICAgICAgICAgKi8KICAgICAgICBnZXROdW1QYXJhbWV0ZXJzKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJhbXMubGVuZ3RoOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgcGFyYW1ldGVycyBjdXJyZW50IG9iamVjdCBoYXMuCiAgICAgICAgICovCiAgICAgICAgZ2V0IG51bVBhcmFtZXRlcnMoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmFtcy5sZW5ndGg7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYWxsIHRoZSBwYXJhbWV0ZXJzIG9mIHRoZSBvYmplY3QuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUGFyYW1ldGVyIExpc3QKICAgICAgICAgKi8KICAgICAgICBnZXRQYXJhbWV0ZXJzKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJhbXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIGluZGV4IG9mIGEgcGFyYW1ldGVyIGluIHBhcmFtZXRlciBsaXN0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHBhcmFtTmFtZSAtIE5hbWUgb2YgdGhlIHBhcmFtZXRlci4KICAgICAgICAgKiBAcmV0dXJuIC0gUG9zaXRpb24gaW4gdGhlIGFycmF5CiAgICAgICAgICovCiAgICAgICAgZ2V0UGFyYW1ldGVySW5kZXgocGFyYW1OYW1lKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmFtTWFwcGluZ1twYXJhbU5hbWVdOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIGBQYXJhbWV0ZXJgIG9iamVjdCBpbiBhIGdpdmVuIGluZGV4CiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBQb3NpdGlvbiBvZiB0aGUgcGFyYW1ldGVyIGluIHRoZSBhcnJheQogICAgICAgICAqIEByZXR1cm4gLSBQYXJhbWV0ZXIgb2JqZWN0IHZhbHVlCiAgICAgICAgICovCiAgICAgICAgZ2V0UGFyYW1ldGVyQnlJbmRleChpbmRleCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJhbXNbaW5kZXhdOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBWYWxpZGF0ZXMgaWYgdGhlIHNwZWNpZmllZCBwYXJhbWV0ZXIgZXhpc3RzIGluIHRoZSBvYmplY3QuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcGFyYW1OYW1lIC0gVGhlIHBhcmFtZXRlciBuYW1lLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGhhc1BhcmFtZXRlcihwYXJhbU5hbWUpIHsKICAgICAgICAgICAgcmV0dXJuIHBhcmFtTmFtZSBpbiB0aGlzLnBhcmFtTWFwcGluZzsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQWRkIGEgbWFwcGluZyBmcm9tIG9uZSBuYW1lIHRvIGEgbmV3IHBhcmFtZXRlci4KICAgICAgICAgKiBUaGlzIGlzIHVzZWQgdG8gaGFuZGxlIG1pZ3JhdGluZyBwYXJhbWV0ZXJzIHRvIG5ldyBuYW1lcy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBrZXkgLSBUaGUgcGFyYW1ldGVyIG5hbWUuCiAgICAgICAgICogQHBhcmFtIHBhcmFtTmFtZSAtIFRoZSBwYXJhbWV0ZXIgbmFtZS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBhZGRQYXJhbWV0ZXJEZXByZWNhdGlvbk1hcHBpbmcoa2V5LCBwYXJhbU5hbWUpIHsKICAgICAgICAgICAgdGhpcy5kZXByZWNhdGVkUGFyYW1NYXBwaW5nW2tleV0gPSBwYXJhbU5hbWU7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYFBhcmFtZXRlcmAgb2JqZWN0IHVzaW5nIHRoZSBnaXZlbiBuYW1lCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcGFyYW1OYW1lIC0gVGhlIHBhcmFtZXRlciBuYW1lLgogICAgICAgICAqIEByZXR1cm4gLSBQYXJhbWV0ZXIgb2JqZWN0IHZhbHVlCiAgICAgICAgICovCiAgICAgICAgZ2V0UGFyYW1ldGVyKHBhcmFtTmFtZSkgewogICAgICAgICAgICBsZXQgaW5kZXggPSB0aGlzLnBhcmFtTWFwcGluZ1twYXJhbU5hbWVdOwogICAgICAgICAgICBpZiAoaW5kZXggPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICBjb25zdCBuZXdQYXJhbU5hbWUgPSB0aGlzLmRlcHJlY2F0ZWRQYXJhbU1hcHBpbmdbcGFyYW1OYW1lXTsKICAgICAgICAgICAgICAgIGlmICghbmV3UGFyYW1OYW1lKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogU2hvdWxkIHRoaXMgbWV0aG9kIG5vdCByZXR1cm4gbnVsbD8KICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgICAgICAvLyB0aHJvdyBFcnJvcihgTm8gUGFyYW1ldGVyIHdpdGggdGhhdCBuYW1lIGV4aXN0czogJHtwYXJhbU5hbWV9IGApCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYFBhcmFtZXRlciBuYW1lICR7cGFyYW1OYW1lfSBpcyBub3cgZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSAke25ld1BhcmFtTmFtZX0gaW5zdGVhZC5gKTsKICAgICAgICAgICAgICAgICAgICBpbmRleCA9IHRoaXMucGFyYW1NYXBwaW5nW25ld1BhcmFtTmFtZV07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyYW1zW2luZGV4XTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhpcyBtZXRob2QgY2FuIGJlIG92ZXJyaWRkZW4gaW4gZGVyaXZlZCBjbGFzc2VzCiAgICAgICAgICogdG8gcGVyZm9ybSBnZW5lcmFsIHVwZGF0ZXMgKHNlZSBHTFBhc3Mgb3IgQmFzZUl0ZW0pLgogICAgICAgICAqIEBwYXJhbSBldmVudCAtIFRoZSBldmVudCBvYmplY3QgZW1pdHRlZCBieSB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICovCiAgICAgICAgcGFyYW1ldGVyVmFsdWVDaGFuZ2VkKGV2ZW50KSB7CiAgICAgICAgICAgIHRoaXMuZW1pdCgncGFyYW1ldGVyVmFsdWVDaGFuZ2VkJywgZXZlbnQpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBBZGRzIGBQYXJhbWV0ZXJgIG9iamVjdCB0byB0aGUgb3duZXIncyBwYXJhbWV0ZXIgbGlzdC4KICAgICAgICAgKgogICAgICAgICAqIEBlbWl0cyBgcGFyYW1ldGVyQWRkZWRgIHdpdGggdGhlIG5hbWUgb2YgdGhlIHBhcmFtLgogICAgICAgICAqIEBwYXJhbSBwYXJhbSAtIFRoZSBwYXJhbWV0ZXIgdG8gYWRkLgogICAgICAgICAqIEByZXR1cm4gLSBXaXRoIGBvd25lcmAgYW5kIGB2YWx1ZUNoYW5nZWRgIGV2ZW50IHNldC4KICAgICAgICAgKi8KICAgICAgICBhZGRQYXJhbWV0ZXIocGFyYW0pIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5zZXJ0UGFyYW1ldGVyKHBhcmFtLCB0aGlzLnBhcmFtcy5sZW5ndGgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBBZGRzIGBQYXJhbWV0ZXJgIG9iamVjdCB0byB0aGUgb3duZXIncyBwYXJhbWV0ZXIgbGlzdCB1c2luZyB0aGUgaW5kZXguCiAgICAgICAgICogSXQgcmVwbGFjZXMgdGhlIGV2ZW50IGluIHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICoKICAgICAgICAgKgogICAgICAgICAqIEBlbWl0cyBgcGFyYW1ldGVyQWRkZWRgIHdpdGggdGhlIG5hbWUgb2YgdGhlIHBhcmFtLgogICAgICAgICAqIEBwYXJhbSBwYXJhbSAtIFRoZSBwYXJhbWV0ZXIgdG8gaW5zZXJ0LgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gV2l0aCBgb3duZXJgIGFuZCBgdmFsdWVDaGFuZ2VkYCBldmVudCBzZXQuCiAgICAgICAgICovCiAgICAgICAgaW5zZXJ0UGFyYW1ldGVyKHBhcmFtLCBpbmRleCkgewogICAgICAgICAgICBjb25zdCBuYW1lID0gcGFyYW0uZ2V0TmFtZSgpOwogICAgICAgICAgICBpZiAodGhpcy5wYXJhbU1hcHBpbmdbbmFtZV0gIT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1JlcGxhY2luZyBQYXJhbWV0ZXI6JyArIG5hbWUpOwogICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVQYXJhbWV0ZXIobmFtZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcGFyYW0uc2V0T3duZXIodGhpcyk7CiAgICAgICAgICAgIHRoaXMucGFyYW1FdmVudExpc3RlbmVySURzW25hbWVdID0gcGFyYW0ub24oJ3ZhbHVlQ2hhbmdlZCcsIChldmVudCkgPT4gewogICAgICAgICAgICAgICAgLy8gTm90ZTogc3ByZWFkIG9wZXJhdG9ycyBjYXVzZSBlcnJvcnMgb24gaU9TIDExLgogICAgICAgICAgICAgICAgY29uc3QgbmV3RXZlbnQgPSB7IHBhcmFtIH07CiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBldmVudCkKICAgICAgICAgICAgICAgICAgICBuZXdFdmVudFtrZXldID0gZXZlbnRba2V5XTsKICAgICAgICAgICAgICAgIHRoaXMucGFyYW1ldGVyVmFsdWVDaGFuZ2VkKG5ld0V2ZW50KTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHRoaXMucGFyYW1zLnNwbGljZShpbmRleCwgMCwgcGFyYW0pOwogICAgICAgICAgICBmb3IgKGxldCBpID0gaW5kZXg7IGkgPCB0aGlzLnBhcmFtcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgdGhpcy5wYXJhbU1hcHBpbmdbdGhpcy5wYXJhbXNbaV0uZ2V0TmFtZSgpXSA9IGk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgZXZlbnQgPSBuZXcgUGFyYW1ldGVyQWRkZWRFdmVudChuYW1lKTsKICAgICAgICAgICAgdGhpcy5lbWl0KCdwYXJhbWV0ZXJBZGRlZCcsIGV2ZW50KTsKICAgICAgICAgICAgcmV0dXJuIHBhcmFtOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZW1vdmVzIGBQYXJhbWV0ZXJgIGZyb20gb3duZXIsIGJ5IHVzaW5nIHBhcmFtZXRlcidzIG5hbWUuCiAgICAgICAgICogQGVtaXRzIGBwYXJhbWV0ZXJSZW1vdmVkYCB3aXRoIHRoZSBuYW1lIG9mIHRoZSBwYXJhbS4KICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBwYXJhbWV0ZXIgbmFtZS4KICAgICAgICAgKi8KICAgICAgICByZW1vdmVQYXJhbWV0ZXIobmFtZSkgewogICAgICAgICAgICBpZiAodGhpcy5wYXJhbU1hcHBpbmdbbmFtZV0gPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byByZW1vdmUgUGFyYW1ldGVyOicgKyBuYW1lKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMucGFyYW1NYXBwaW5nW25hbWVdOwogICAgICAgICAgICBjb25zdCBwYXJhbSA9IHRoaXMucGFyYW1zW3RoaXMucGFyYW1NYXBwaW5nW25hbWVdXTsKICAgICAgICAgICAgcGFyYW0ub2ZmKCd2YWx1ZUNoYW5nZWQnLCB0aGlzLnBhcmFtRXZlbnRMaXN0ZW5lcklEc1tuYW1lXSk7CiAgICAgICAgICAgIHRoaXMucGFyYW1zLnNwbGljZShpbmRleCwgMSk7CiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnBhcmFtTWFwcGluZ1tuYW1lXTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IGluZGV4OyBpIDwgdGhpcy5wYXJhbXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMucGFyYW1NYXBwaW5nW3RoaXMucGFyYW1zW2ldLmdldE5hbWUoKV0gPSBpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0gbmV3IFBhcmFtZXRlclJlbW92ZWRFdmVudChuYW1lKTsKICAgICAgICAgICAgdGhpcy5lbWl0KCdwYXJhbWV0ZXJSZW1vdmVkJywgZXZlbnQpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXBsYWNlcyBvbGQgYFBhcmFtZXRlcmAgYnkgcGFzc2luZyBhIG5ldyBvbmUgd2l0aCB0aGUgc2FtZSBuYW1lLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHBhcmFtIC0gVGhlIHBhcmFtZXRlciB0byByZXBsYWNlLgogICAgICAgICAqIEByZXR1cm4gLSBgUGFyYW1ldGVyYCB3aXRoIGB2YWx1ZUNoYW5nZWRgIGV2ZW50IHNldC4KICAgICAgICAgKi8KICAgICAgICByZXBsYWNlUGFyYW1ldGVyKHBhcmFtKSB7CiAgICAgICAgICAgIGNvbnN0IG5hbWUgPSBwYXJhbS5nZXROYW1lKCk7CiAgICAgICAgICAgIGlmICh0aGlzLnBhcmFtTWFwcGluZ1tuYW1lXSA9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIHJlcGxhY2UgUGFyYW1ldGVyOicgKyBuYW1lKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMucGFyYW1NYXBwaW5nW25hbWVdOwogICAgICAgICAgICB0aGlzLnJlbW92ZVBhcmFtZXRlcihuYW1lKTsKICAgICAgICAgICAgdGhpcy5pbnNlcnRQYXJhbWV0ZXIocGFyYW0sIGluZGV4KTsKICAgICAgICAgICAgcmV0dXJuIHBhcmFtOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgcmVzb2x2ZVBhdGggbWV0aG9kIHRyYXZlcnNlcyB0aGUgc3VidHJlZSBmcm9tIHRoaXMgaXRlbSBkb3duCiAgICAgICAgICogbWF0Y2hpbmcgZWFjaCBuYW1lIGluIHRoZSBwYXRoIHdpdGggYSBjaGlsZCB1bnRpbCBpdCByZWFjaGVzIHRoZQogICAgICAgICAqIGVuZCBvZiB0aGUgcGF0aC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBwYXRoIC0gVGhlIHBhdGggdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gVGhlIGluZGV4IHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlc29sdmVQYXRoKHBhdGgsIGluZGV4ID0gMCkgewogICAgICAgICAgICBpZiAoaW5kZXggPT0gMCkgewogICAgICAgICAgICAgICAgaWYgKHBhdGhbMF0gPT0gJy4nIHx8IHBhdGhbMF0gPT0gdGhpcy5uYW1lKQogICAgICAgICAgICAgICAgICAgIGluZGV4Kys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHBhdGhbaW5kZXhdID09ICcuLicpIHsKICAgICAgICAgICAgICAgIGlmICh0aGlzLm93bmVySXRlbSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm93bmVySXRlbS5yZXNvbHZlUGF0aChwYXRoLCBpbmRleCArIDEpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgRXJyb3IoJ3RoaXMub3duZXJJdGVtIGlzIHVuZGVmaW5lZCcpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChpbmRleCA9PSBwYXRoLmxlbmd0aCkgewogICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gTWF5YmUgdGhlIG5hbWUgaXMgYSBwYXJhbWV0ZXIgbmFtZS4KICAgICAgICAgICAgY29uc3QgcGFyYW0gPSB0aGlzLmdldFBhcmFtZXRlcihwYXRoW2luZGV4XSk7CiAgICAgICAgICAgIGlmIChwYXJhbSkgewogICAgICAgICAgICAgICAgaWYgKGluZGV4IDwgcGF0aC5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGFyYW0ucmVzb2x2ZVBhdGgocGF0aCwgaW5kZXggKyAxKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJldHVybiBwYXJhbTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byByZXNvbHZlIHBhdGggOiBbJHtwYXRoLnRvU3RyaW5nKCl9XSBhZnRlcjogJHt0aGlzLmdldE5hbWUoKX0gXG5ObyBjaGlsZCBvciBwYXJhbWV0ZXIgY2FsbGVkIDogIiR7cGF0aFtpbmRleF19ImApOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdG9KU09OIG1ldGhvZCBlbmNvZGVzIHRoaXMgdHlwZSBhcyBhIGpzb24gb2JqZWN0IGZvciBwZXJzaXN0ZW5jZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIGNvbnN0IGpzb24gPSBzdXBlci50b0pTT04oY29udGV4dCk7CiAgICAgICAgICAgIGNvbnN0IHBhcmFtc0pTT04gPSB7fTsKICAgICAgICAgICAgbGV0IHNhdmVkUGFyYW1zID0gMDsKICAgICAgICAgICAgZm9yIChjb25zdCBwYXJhbSBvZiB0aGlzLnBhcmFtcykgewogICAgICAgICAgICAgICAgaWYgKHBhcmFtLmlzRHJpdmVuQnlPcGVyYXRvcigpKQogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgY29uc3QgcGFyYW1KU09OID0gcGFyYW0udG9KU09OKGNvbnRleHQpOwogICAgICAgICAgICAgICAgaWYgKHBhcmFtSlNPTikgewogICAgICAgICAgICAgICAgICAgIHBhcmFtc0pTT05bcGFyYW0uZ2V0TmFtZSgpXSA9IHBhcmFtSlNPTjsKICAgICAgICAgICAgICAgICAgICBzYXZlZFBhcmFtcysrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChzYXZlZFBhcmFtcyA+IDApCiAgICAgICAgICAgICAgICBqc29uLnBhcmFtcyA9IHBhcmFtc0pTT047CiAgICAgICAgICAgIHJldHVybiBqc29uOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIGRlY29kZXMgYSBqc29uIG9iamVjdCBmb3IgdGhpcyB0eXBlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGpzb24gLSBUaGUganNvbiBvYmplY3QgdGhpcyBpdGVtIG11c3QgZGVjb2RlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZnJvbUpTT04oanNvbiwgY29udGV4dCkgewogICAgICAgICAgICBzdXBlci5mcm9tSlNPTihqc29uLCBjb250ZXh0KTsKICAgICAgICAgICAgaWYgKGpzb24ucGFyYW1zKSB7CiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBqc29uLnBhcmFtcykgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHBqID0ganNvbi5wYXJhbXNba2V5XTsKICAgICAgICAgICAgICAgICAgICBpZiAocGoucGFyYW1QYXRoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQ/LnJlc29sdmVQYXRoKHBqLnBhcmFtUGF0aCwgKHBhcmFtKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlcGxhY2VQYXJhbWV0ZXIocGFyYW0pOwogICAgICAgICAgICAgICAgICAgICAgICB9LCAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1VuYWJsZSB0byByZXNvbHZlIHNoYXJlZCBwYXJhbWV0ZXI6JyArIHBqLnBhcmFtUGF0aCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHBhcmFtID0gdGhpcy5nZXRQYXJhbWV0ZXIoa2V5KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJhbSAmJiBwai50eXBlICYmIHBqLm5hbWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtID0gUmVnaXN0cnkuY29uc3RydWN0Q2xhc3MocGoudHlwZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcmFtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignVW5hYmxlIHRvIGNvbnN0cnVjdCBwcm9wOicgKyBwai5uYW1lICsgJyBvZiB0eXBlOicgKyBwai50eXBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtLnNldE5hbWUocGoubmFtZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZFBhcmFtZXRlcihwYXJhbSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmFtKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW0uZnJvbUpTT04ocGosIGNvbnRleHQpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBVc2VzIHBhc3NlZCBpbiBCaW5SZWFkZXIgb2JqZWN0KGNvbnRhaW5pbmcgYW4gSW50MzIgYXJyYXkgd2l0aCBhbGwgdGhlIHBhcmFtZXRlcnMpIHRvIHJlY29uc3RydWN0IGFsbCBwYXJhbWV0ZXJzIHN0YXRlLgogICAgICAgICAqCiAgICAgICAgICogSW4gZWFjaCBpdGVyYXRpb24gb2YgdGhlIGFycmF5LCBwcm9wVHlwZSBhbmQgcHJvcE5hbWUgYXJlIGV4dHJhY3RlZCBhbmQKICAgICAgICAgKiB1c2VkIHRvIGJ1aWxkIHRoZSByaWdodCBgUGFyYW1ldGVyYCBjbGFzcy4gVGhlbiBhbGwgb2YgdGhlbSBhcmUgYWRkZWQgdG8gdGhlIG9iamVjdC4KICAgICAgICAgKgogICAgICAgICAqIEBlbWl0cyBgcGFyYW1ldGVyQWRkZWRgIHdpdGggdGhlIG5hbWUgb2YgdGhlIHBhcmFtLgogICAgICAgICAqIEBwYXJhbSByZWFkZXIgLSBUaGUgcmVhZGVyIHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgcmVhZEJpbmFyeShyZWFkZXIsIGNvbnRleHQpIHsKICAgICAgICAgICAgc3VwZXIucmVhZEJpbmFyeShyZWFkZXIsIGNvbnRleHQpOwogICAgICAgICAgICB0aGlzLnJlYWRCaW5hcnlQYXJhbXMocmVhZGVyLCBjb250ZXh0KTsKICAgICAgICB9CiAgICAgICAgcmVhZEJpbmFyeVBhcmFtcyhyZWFkZXIsIGNvbnRleHQpIHsKICAgICAgICAgICAgaWYgKGNvbnRleHQ/LnZlcnNpb25zWyd6ZWEtZW5naW5lJ10uY29tcGFyZShbMCwgMCwgM10pID49IDApIHsKICAgICAgICAgICAgICAgIGNvbnN0IG51bVByb3BzID0gcmVhZGVyLmxvYWRVSW50MzIoKTsKICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtUHJvcHM7IGkrKykgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHByb3BUeXBlID0gcmVhZGVyLmxvYWRTdHIoKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBwcm9wTmFtZSA9IHJlYWRlci5sb2FkU3RyKCk7CiAgICAgICAgICAgICAgICAgICAgbGV0IHBhcmFtID0gdGhpcy5nZXRQYXJhbWV0ZXIocHJvcE5hbWUpOwogICAgICAgICAgICAgICAgICAgIGlmICghcGFyYW0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW0gPSBSZWdpc3RyeS5jb25zdHJ1Y3RDbGFzcyhwcm9wVHlwZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghcGFyYW0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1VuYWJsZSB0byBjb25zdHJ1Y3QgcHJvcDonICsgcHJvcE5hbWUgKyAnIG9mIHR5cGU6JyArIHByb3BUeXBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtLnNldE5hbWUocHJvcE5hbWUpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZFBhcmFtZXRlcihwYXJhbSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHBhcmFtLnJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gQ2xvbmUgYW5kIERlc3Ryb3kKICAgICAgICAvKioKICAgICAgICAgKiBDbG9uZXMgdGhpcyBiYXNlIGl0ZW0gYW5kIHJldHVybnMgYSBuZXcgYmFzZSBpdGVtLgogICAgICAgICAqCiAgICAgICAgICogKipOb3RlOioqIEVhY2ggY2xhc3Mgc2hvdWxkIGltcGxlbWVudCBjbG9uZSB0byBiZSBjbG9uYWJsZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGNsb25lKGNvbnRleHQpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHRoaXMuY29uc3RydWN0b3IubmFtZSArICcgZG9lcyBub3QgaW1wbGVtZW50IGl0cyBjbG9uZSBtZXRob2QnKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ29waWVzIFBhcmFtZXRlcnMgZnJvbSBhbm90aGVyIGBQYXJhbWV0ZXJPd25lcmAgdG8gY3VycmVudCBvYmplY3QuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc3JjIC0gVGhlIFBhcmFtZXRlck93bmVyIGNvcHkgZnJvbS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlCiAgICAgICAgICovCiAgICAgICAgY29weUZyb20oc3JjLCBjb250ZXh0KSB7CiAgICAgICAgICAgIGlmICghKHNyYyBpbnN0YW5jZW9mIFBhcmFtZXRlck93bmVyKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5ub3QgY29weSBmcm9tIHNyYycpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN1cGVyLmNvcHlGcm9tKHNyYywgY29udGV4dCk7CiAgICAgICAgICAgIC8vIE5vdGU6IExvb3Agb3ZlciB0aGUgcGFyYW1ldGVycyBpbiByZXZlcnNlIG9yZGVyLAogICAgICAgICAgICAvLyB0aGlzIGlzIGJlY2F1c2Ugb2Z0ZW4sIHBhcmFtZXRlciBkZXBlbmRlbmNpZXMKICAgICAgICAgICAgLy8gYXJlIGJvdHRvbSB0byB0b3AgKGJvdHRvbSBwYXJhbXMgZGVwZW5kZW50IG9uIGhpZ2hlciBwYXJhbXMpLgogICAgICAgICAgICAvLyBUaGlzIG1lYW5zIHRoYXQgYXMgYSBwYXJhbWV0ZXIgaXMgc2V0IHdpdGggYSBuZXcgdmFsdWUKICAgICAgICAgICAgLy8gaXQgd2lsbCBkaXJ0eSB0aGUgcGFyYW1zIGJlbG93IGl0LgogICAgICAgICAgICBsZXQgaSA9IHNyYy5nZXROdW1QYXJhbWV0ZXJzKCk7CiAgICAgICAgICAgIHdoaWxlIChpLS0pIHsKICAgICAgICAgICAgICAgIGNvbnN0IHNyY1BhcmFtID0gc3JjLmdldFBhcmFtZXRlckJ5SW5kZXgoaSk7CiAgICAgICAgICAgICAgICBjb25zdCBwYXJhbSA9IHRoaXMuZ2V0UGFyYW1ldGVyKHNyY1BhcmFtLmdldE5hbWUoKSk7CiAgICAgICAgICAgICAgICBpZiAocGFyYW0pIHsKICAgICAgICAgICAgICAgICAgICAvLyBOb3RlOiB3ZSBhcmUgbm90IGNsb25pbmcgdGhlIHZhbHVlcy4KICAgICAgICAgICAgICAgICAgICBwYXJhbS5jb3B5RnJvbShzcmNQYXJhbSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZFBhcmFtZXRlcihzcmNQYXJhbS5jbG9uZSgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55ICovCiAgICBmdW5jdGlvbiBhcHByb3hFcXVhbChhLCBiKSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGlmIChNYXRoLmFicyhiW2ldIC0gYVtpXSkgPiAwLjAwMSkKICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBjb25zdCByZXNpemVBcnJheSA9IChpbkFycmF5LCBuZXdTaXplKSA9PiB7CiAgICAgICAgaWYgKGluQXJyYXkgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7CiAgICAgICAgICAgIGNvbnN0IG5ld0FycmF5ID0gbmV3IFVpbnQ4QXJyYXkobmV3U2l6ZSk7CiAgICAgICAgICAgIG5ld0FycmF5LnNldChpbkFycmF5KTsKICAgICAgICAgICAgcmV0dXJuIG5ld0FycmF5OwogICAgICAgIH0KICAgICAgICBlbHNlIGlmIChpbkFycmF5IGluc3RhbmNlb2YgSW50OEFycmF5KSB7CiAgICAgICAgICAgIGNvbnN0IG5ld0FycmF5ID0gbmV3IEludDhBcnJheShuZXdTaXplKTsKICAgICAgICAgICAgbmV3QXJyYXkuc2V0KGluQXJyYXkpOwogICAgICAgICAgICByZXR1cm4gbmV3QXJyYXk7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKGluQXJyYXkgaW5zdGFuY2VvZiBVaW50MTZBcnJheSkgewogICAgICAgICAgICBjb25zdCBuZXdBcnJheSA9IG5ldyBVaW50MTZBcnJheShuZXdTaXplKTsKICAgICAgICAgICAgbmV3QXJyYXkuc2V0KGluQXJyYXkpOwogICAgICAgICAgICByZXR1cm4gbmV3QXJyYXk7CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICBjb25zdCBuZXdBcnJheSA9IG5ldyBGbG9hdDMyQXJyYXkobmV3U2l6ZSk7CiAgICAgICAgICAgIG5ld0FycmF5LnNldChpbkFycmF5KTsKICAgICAgICAgICAgcmV0dXJuIG5ld0FycmF5OwogICAgICAgIH0KICAgIH07CiAgICBjbGFzcyBBdHRyaWJ1dGUgZXh0ZW5kcyBCYXNlQ2xhc3MgewogICAgICAgIGRhdGFUeXBlTmFtZTsKICAgICAgICBzdHJpZGU7CiAgICAgICAgaW5pdFZhbHVlID0gTnVtYmVyLk5hTjsKICAgICAgICBub3JtYWxpemVkOwogICAgICAgIGRhdGE7CiAgICAgICAgbWVzaDsKICAgICAgICBzcGxpdFZhbHVlcyA9IFtdOwogICAgICAgIHNwbGl0cyA9IHt9OwogICAgICAgIGNvbnN0cnVjdG9yKGRhdGFUeXBlTmFtZSwgc3RyaWRlLCBpbml0VmFsdWUgPSBOdW1iZXIuTmFOKSB7CiAgICAgICAgICAgIHN1cGVyKCk7CiAgICAgICAgICAgIHRoaXMuZGF0YVR5cGVOYW1lID0gZGF0YVR5cGVOYW1lOwogICAgICAgICAgICB0aGlzLnN0cmlkZSA9IHN0cmlkZTsKICAgICAgICAgICAgdGhpcy5pbml0VmFsdWUgPSBpbml0VmFsdWU7CiAgICAgICAgICAgIHRoaXMuaW5pdCgpOwogICAgICAgIH0KICAgICAgICBpbml0KCkgewogICAgICAgICAgICB0aGlzLmRhdGEgPSBuZXcgRmxvYXQzMkFycmF5KDApOwogICAgICAgICAgICB0aGlzLmluaXRSYW5nZSgwKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB0aGUgTWVzaCByZWZlcmVuY2UgdG8gdGhlIFZlcnRleEF0dHJpYnV0ZS4gVGhpcyBpcyBuZWVkZWQgZm9yIGF0dHJpYnV0ZXMKICAgICAgICAgKiBhc3NpZ25lZCB0byBtZXNoZXMsIGFuZCBpcyB1c2VkIHRvIGNhbGN1bGF0ZSBmYWNlIHZlcnRleCBpbmRpY2VzLgogICAgICAgICAqID4gTm90ZTogdGhlIG1lc2ggYXV0b21hdGljYWxseSBjYWxscyB0aGlzIG1ldGhvZCB3aGVuIGEgdmVydGV4IGF0dHJpYnV0ZSBpcyBhc3NpZ25lZC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBtZXNoIC0gVGhlIG1lc2ggb2JqZWN0CiAgICAgICAgICovCiAgICAgICAgc2V0TWVzaChtZXNoKSB7CiAgICAgICAgICAgIHRoaXMubWVzaCA9IG1lc2g7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIGJhY2tpbmcgYXJyYXkgZm9yIHRoaXMgYXR0cmlidXRlCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBhc0FycmF5KCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBuYW1lIG9mIHRoZSBtYXRoIHR5cGUgdGhpcyBhdHRyaWJ1dGUgc3RvcmVzLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0RGF0YVR5cGVOYW1lKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhVHlwZU5hbWU7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIGNvdW50IG9mIGF0dHJpYnV0ZSB2YWx1ZXMgaW4gdGhlIGRhdGEuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRDb3VudCgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0YS5sZW5ndGggLyB0aGlzLnN0cmlkZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgY291bnQgb2YgYXR0cmlidXRlIHZhbHVlcyBpbiB0aGUgZGF0YS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldCBjb3VudCgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0YS5sZW5ndGggLyB0aGlzLnN0cmlkZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB0aGUgY291bnQgb2YgYXR0cmlidXRlIHZhbHVlcyBpbiB0aGUgZGF0YS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBzaXplIC0gVGhlIHNpemUgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0Q291bnQoY291bnQpIHsKICAgICAgICAgICAgY29uc3QgcHJldkxlbmd0aCA9IHRoaXMuZGF0YS5sZW5ndGg7CiAgICAgICAgICAgIGNvbnN0IG5ld0xlbmd0aCA9IGNvdW50ICogdGhpcy5zdHJpZGU7CiAgICAgICAgICAgIGlmIChuZXdMZW5ndGggPiBwcmV2TGVuZ3RoKSB7CiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSByZXNpemVBcnJheSh0aGlzLmRhdGEsIG5ld0xlbmd0aCk7CiAgICAgICAgICAgICAgICB0aGlzLmluaXRSYW5nZShwcmV2TGVuZ3RoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIGlmIChuZXdMZW5ndGggPCBwcmV2TGVuZ3RoKSB7CiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSB0aGlzLmRhdGEuc2xpY2UoMCwgbmV3TGVuZ3RoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIDsKICAgICAgICAgICAgdGhpcy5zcGxpdHMgPSB7fTsKICAgICAgICAgICAgdGhpcy5zcGxpdFZhbHVlcyA9IFtdOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBGaWxscyB1cCBkYXRhIHZhbHVlcyB3aXRoIGRlZmF1bHQgb25lcyBzdGFydGluZyBmcm9tIHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc3RhcnQgLSBUaGUgc3RhcnQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgaW5pdFJhbmdlKHN0YXJ0KSB7CiAgICAgICAgICAgIC8vIEluaXRpYWxpemUgdGhlIHZhbHVlcyB0byBpbnZhbGlkIHZhbHVlcy4KICAgICAgICAgICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgdGhpcy5kYXRhLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICB0aGlzLmRhdGFbaV0gPSB0aGlzLmluaXRWYWx1ZTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpc0luaXRpYWxpemVkKGEpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBpZiAoYVtpXSAhPSB0aGlzLmluaXRWYWx1ZSkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIG51bWJlciBvZiBlbGVtZW50cyBzdG9yZWQgaW4gZWFjaCBgVGAuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXQgbnVtRWxlbWVudHMoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0cmlkZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBkYXRhIHZhbHVlIG9mIHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0RmxvYXQzMlZhbHVlKGluZGV4KSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFbaW5kZXhdOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIGRhdGEgdmFsdWUgaW4gdGhlIHNwZWNpZmllZCBpbmRleC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgcGFyYW0uCiAgICAgICAgICovCiAgICAgICAgc2V0RmxvYXQzMlZhbHVlKGluZGV4LCB2YWx1ZSkgewogICAgICAgICAgICB0aGlzLmRhdGFbaW5kZXhdID0gdmFsdWU7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgZGF0YSB2YWx1ZXMgaW4gdGhlIHNwZWNpZmllZCBpbmRleC4KICAgICAgICAgKi8KICAgICAgICBnZXRWYWx1ZXMoaW5kZXgpIHsKICAgICAgICAgICAgaWYgKGluZGV4ID49IHRoaXMuZGF0YS5sZW5ndGggLyB0aGlzLnN0cmlkZSkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB2ZXJ0ZXggaW5kZXg6JyArIGluZGV4ICsgJy4gTnVtIFZlcnRpY2VzOicgKyB0aGlzLmRhdGEubGVuZ3RoIC8gdGhpcy5zdHJpZGUpOwogICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBpbmRleCAqIHRoaXMuc3RyaWRlOwogICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhLnN1YmFycmF5KG9mZnNldCwgb2Zmc2V0ICsgdGhpcy5zdHJpZGUpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIGRhdGEgdmFsdWVzIGluIHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICovCiAgICAgICAgc2V0VmFsdWVzKGluZGV4LCB2YWx1ZXMpIHsKICAgICAgICAgICAgaWYgKGluZGV4ID49IHRoaXMuZGF0YS5sZW5ndGggLyB0aGlzLnN0cmlkZSkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB2ZXJ0ZXggaW5kZXg6JyArIGluZGV4ICsgJy4gTnVtIFZlcnRpY2VzOicgKyB0aGlzLmRhdGEubGVuZ3RoIC8gdGhpcy5zdHJpZGUpOwogICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBpbmRleCAqIHRoaXMuc3RyaWRlOwogICAgICAgICAgICB0aGlzLmRhdGEuc2V0KHZhbHVlcywgb2Zmc2V0KTsKICAgICAgICB9CiAgICAgICAgbWVyZ2Uob3RoZXIsIHhmbyA9IG5ldyBYZm8oKSkgewogICAgICAgICAgICBjb25zdCBwcmV2TnVtVmFsdWVzID0gdGhpcy5kYXRhLmxlbmd0aDsKICAgICAgICAgICAgY29uc3QgYWRkZWRWYWx1ZXMgPSBvdGhlci5kYXRhLmxlbmd0aDsKICAgICAgICAgICAgY29uc3QgbmV3TGVuZ3RoID0gcHJldk51bVZhbHVlcyArIGFkZGVkVmFsdWVzOwogICAgICAgICAgICBjb25zdCBkYXRhID0gbmV3IEZsb2F0MzJBcnJheShuZXdMZW5ndGgpOwogICAgICAgICAgICBkYXRhLnNldCh0aGlzLmRhdGEsIDApOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFkZGVkVmFsdWVzOyBpKyspIHsKICAgICAgICAgICAgICAgIGRhdGFbcHJldk51bVZhbHVlcyArIGldID0gb3RoZXIuZGF0YVtpXTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLmRhdGEgPSBkYXRhOwogICAgICAgICAgICB0aGlzLnNwbGl0VmFsdWVzID0gWy4uLnRoaXMuc3BsaXRWYWx1ZXMsIC4uLm90aGVyLnNwbGl0VmFsdWVzXTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBGYWNlIFZlcnRleCBWYWx1ZXMKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZ2V0U3BsaXRzIG1ldGhvZC4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRTcGxpdHMoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnNwbGl0czsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgdmFsdWUgb2YgYSBjb3JuZXIgdmVydGV4IG9mIGEgZmFjZS4KICAgICAgICAgKiBAcGFyYW0gZmFjZSAtIFRoZSBmYWNlIGluZGV4LgogICAgICAgICAqIEBwYXJhbSBmYWNlVmVydGV4IC0gVGhlIGluZGV4IG9mIHZlcnRleCB3aXRoaW4gdGhlIGZhY2UuIFswLi4uIG51bSBmYWNlIHZlcnRpY2VzXQogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldEZhY2VWZXJ0ZXhWYWx1ZV9hcnJheShmYWNlLCBmYWNlVmVydGV4KSB7CiAgICAgICAgICAgIGNvbnN0IHZlcnRleCA9IHRoaXMubWVzaC5nZXRGYWNlVmVydGV4SW5kZXgoZmFjZSwgZmFjZVZlcnRleCk7CiAgICAgICAgICAgIGlmICh2ZXJ0ZXggaW4gdGhpcy5zcGxpdHMgJiYgZmFjZSBpbiB0aGlzLnNwbGl0c1t2ZXJ0ZXhdKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zcGxpdFZhbHVlc1t0aGlzLnNwbGl0c1t2ZXJ0ZXhdW2ZhY2VdXTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhLnN1YmFycmF5KHZlcnRleCAqIHRoaXMuc3RyaWRlLCAodmVydGV4ICsgMSkgKiB0aGlzLnN0cmlkZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIHZhbHVlIG9mIGEgY29ybmVyIHZlcnRleCBvZiBhIGZhY2UuCiAgICAgICAgICogQHBhcmFtIGZhY2UgLSBUaGUgZmFjZSBpbmRleC4KICAgICAgICAgKiBAcGFyYW0gZmFjZVZlcnRleCAtIFRoZSBpbmRleCBvZiB2ZXJ0ZXggd2l0aGluIHRoZSBmYWNlLiBbMC4uLiBudW0gZmFjZSB2ZXJ0aWNlc10KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0RmFjZVZlcnRleFZhbHVlX2FycmF5KGZhY2UsIGZhY2VWZXJ0ZXgsIHZhbHVlKSB7CiAgICAgICAgICAgIGNvbnN0IHZlcnRleCA9IHRoaXMubWVzaC5nZXRGYWNlVmVydGV4SW5kZXgoZmFjZSwgZmFjZVZlcnRleCk7CiAgICAgICAgICAgIHRoaXMuc2V0RmFjZVZlcnRleFZhbHVlX0J5VmVydGV4SW5kZXgoZmFjZSwgdmVydGV4LCB2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBzZXRGYWNlVmVydGV4VmFsdWVfQnlWZXJ0ZXhJbmRleCBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIGZhY2UgLSBUaGUgZmFjZSBpbmRleC4KICAgICAgICAgKiBAcGFyYW0gdmVydGV4IC0gVGhlIHZlcnRleCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0RmFjZVZlcnRleFZhbHVlX0J5VmVydGV4SW5kZXgoZmFjZSwgdmVydGV4LCB2YWx1ZSkgewogICAgICAgICAgICBjb25zdCBjdXJyVmFsdWUgPSB0aGlzLmRhdGEuc3ViYXJyYXkodmVydGV4ICogdGhpcy5zdHJpZGUsICh2ZXJ0ZXggKyAxKSAqIHRoaXMuc3RyaWRlKTsKICAgICAgICAgICAgaWYgKCF0aGlzLmlzSW5pdGlhbGl6ZWQoY3VyclZhbHVlKSkgewogICAgICAgICAgICAgICAgLy8gdGhlIHZhbHVlIGlzIHVuaW5pdGlhbGl6ZWQuIEluaXRpYWxpemUgaXQuCiAgICAgICAgICAgICAgICBjdXJyVmFsdWUuc2V0KHZhbHVlKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIGlmIChhcHByb3hFcXVhbChjdXJyVmFsdWUsIHZhbHVlKSkgOwogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIC8vIFRoZSBuZXcgdmFsdWUgaXMgZGlmZmVyZW50IGZyb20gdGhlIGV4aXN0aW5nIHZhbHVlCiAgICAgICAgICAgICAgICBpZiAodmVydGV4IGluIHRoaXMuc3BsaXRzKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gTm93IGNoZWNrIGlmIGFueSBleGlzdGluZyBzcGxpdHMgZm9yIHRoaXMgdmVydGV4IG1hdGNoIHRoZSB2YWx1ZSBiZWluZyBzZXQuCiAgICAgICAgICAgICAgICAgICAgLy8gaS5lLiBmb3IgZmFjZXMgYXJvdW5kIGEgdmVydGV4LCB0aGVyZSB3aWxsIG9mdGVuIGJlIGEgc2VhbSBhbG9uZyAyIGVkZ2VzCiAgICAgICAgICAgICAgICAgICAgLy8gd2hlcmUgdGhlIHZhbHVlcyBkaWZmZXIuIE9uIGVhY2ggc2lkZSBvZiB0aGUgc2VhbSwgYWxsIGZhY2VzIGNhbiB1c2UgdGhlIHNhbWUKICAgICAgICAgICAgICAgICAgICAvLyB2YWx1ZS4gV2Ugc2hvdWxkIHNlZSB0aGVuIG9ubHkgb25lIHNwbGl0IHZhbHVlIGZvciB0aGUgdmVydGV4LgogICAgICAgICAgICAgICAgICAgIGNvbnN0IHZlcnRleFNwbGl0SWRzID0gdGhpcy5zcGxpdHNbdmVydGV4XTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpZCBpbiB2ZXJ0ZXhTcGxpdElkcykgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzcGxpdElkID0gdmVydGV4U3BsaXRJZHNbZmlkXTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFwcHJveEVxdWFsKHRoaXMuc3BsaXRWYWx1ZXNbc3BsaXRJZF0sIHZhbHVlKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmUtdXNlIHRoaXMgc3BsaXQgdmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcnRleFNwbGl0SWRzW2ZhY2VdID0gc3BsaXRJZDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIHNwbGl0IGFscmVhZHkgZXhpc3RzIGZvciB0aGlzIGZhY2UsIHJlLXVzZSBpdC4KICAgICAgICAgICAgICAgICAgICBpZiAoZmFjZSBpbiB0aGlzLnNwbGl0c1t2ZXJ0ZXhdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3BsaXRWYWx1ZXNbdGhpcy5zcGxpdHNbdmVydGV4XVtmYWNlXV0gPSB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIHRoaXMuc3BsaXRzW3ZlcnRleF0gPSB7fTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRoaXMuc3BsaXRzW3ZlcnRleF1bZmFjZV0gPSB0aGlzLnNwbGl0VmFsdWVzLmxlbmd0aDsKICAgICAgICAgICAgICAgIHRoaXMuc3BsaXRWYWx1ZXMucHVzaCh2YWx1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHNldFNwbGl0VmVydGV4VmFsdWUgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSB2ZXJ0ZXggLSBUaGUgdmVydGV4IHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBmYWNlIC0gVGhlIGZhY2UgaW5kZXguCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldFNwbGl0VmVydGV4VmFsdWVfYXJyYXkodmVydGV4LCBmYWNlLCB2YWx1ZSkgewogICAgICAgICAgICBpZiAoISh2ZXJ0ZXggaW4gdGhpcy5zcGxpdHMpKQogICAgICAgICAgICAgICAgdGhpcy5zcGxpdHNbdmVydGV4XSA9IHt9OwogICAgICAgICAgICBpZiAoZmFjZSBpbiB0aGlzLnNwbGl0c1t2ZXJ0ZXhdKSB7CiAgICAgICAgICAgICAgICBjb25zdCBjdXJyVmFsdWUgPSB0aGlzLnNwbGl0VmFsdWVzW3RoaXMuc3BsaXRzW3ZlcnRleF1bZmFjZV1dOwogICAgICAgICAgICAgICAgaWYgKGFwcHJveEVxdWFsKGN1cnJWYWx1ZSwgdmFsdWUpKQogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignRmFjZSBWZXJ0ZXggQWxyZWFkeSBTcGxpdCB3aXRoIGRpZmZlcmVudCB2YWx1ZScpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuc3BsaXRzW3ZlcnRleF1bZmFjZV0gPSB0aGlzLnNwbGl0VmFsdWVzLmxlbmd0aDsKICAgICAgICAgICAgdGhpcy5zcGxpdFZhbHVlcy5wdXNoKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHNldFNwbGl0VmVydGV4VmFsdWVzIG1ldGhvZC4KICAgICAgICAgKiBAcGFyYW0gdmVydGV4IC0gVGhlIHZlcnRleCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gZmFjZUdyb3VwIC0gVGhlIGZhY2VHcm91cCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0U3BsaXRWZXJ0ZXhWYWx1ZXModmVydGV4LCBmYWNlR3JvdXAsIHZhbHVlcykgewogICAgICAgICAgICBpZiAoISh2ZXJ0ZXggaW4gdGhpcy5zcGxpdHMpKQogICAgICAgICAgICAgICAgdGhpcy5zcGxpdHNbdmVydGV4XSA9IHt9OwogICAgICAgICAgICBjb25zdCBzcGxpdEluZGV4ID0gdGhpcy5zcGxpdFZhbHVlcy5sZW5ndGg7CiAgICAgICAgICAgIHRoaXMuc3BsaXRWYWx1ZXMucHVzaCh2YWx1ZXMpOwogICAgICAgICAgICBmb3IgKGNvbnN0IGZhY2Ugb2YgZmFjZUdyb3VwKSB7CiAgICAgICAgICAgICAgICAvLyBpZiAoZmFjZSBpbiB0aGlzLnNwbGl0c1t2ZXJ0ZXhdKSB7CiAgICAgICAgICAgICAgICAvLyAgICAgbGV0IGN1cnJWYWx1ZSA9IHRoaXMuc3BsaXRWYWx1ZXNbdGhpcy5zcGxpdHNbdmVydGV4XVtmYWNlXV07CiAgICAgICAgICAgICAgICAvLyAgICAgaWYgKGN1cnJWYWx1ZS5hcHByb3hFcXVhbCh2YWx1ZSkpCiAgICAgICAgICAgICAgICAvLyAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIC8vICAgICBjb25zb2xlLndhcm4oIkZhY2UgVmVydGV4IEFscmVhZHkgU3BsaXQgd2l0aCBkaWZmZXJlbnQgdmFsdWUiKTsKICAgICAgICAgICAgICAgIC8vIH0KICAgICAgICAgICAgICAgIHRoaXMuc3BsaXRzW3ZlcnRleF1bZmFjZV0gPSBzcGxpdEluZGV4OwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBnZW5lcmF0ZVNwbGl0VmFsdWVzIG1ldGhvZC4KICAgICAgICAgKiBAcGFyYW0gc3BsaXRJbmRpY2VzIC0gVGhlIHNwbGl0SW5kaWNlcyB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gc3BsaXRDb3VudCAtIFRoZSBzcGxpdENvdW50IHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdlbmVyYXRlU3BsaXRWYWx1ZXMoc3BsaXRJbmRpY2VzLCBzcGxpdENvdW50KSB7CiAgICAgICAgICAgIGlmIChzcGxpdENvdW50ID09IDApCiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhOwogICAgICAgICAgICBjb25zdCBudW1VblNwbGl0VmFsdWVzID0gdGhpcy5nZXRDb3VudCgpOwogICAgICAgICAgICBjb25zdCBkYXRhID0gcmVzaXplQXJyYXkodGhpcy5kYXRhLCAobnVtVW5TcGxpdFZhbHVlcyArIHNwbGl0Q291bnQpICogdGhpcy5zdHJpZGUpOwogICAgICAgICAgICAvLyBOb3cgZHVwbGljYXRlIHRoZSBzcGxpdCB2YWx1ZXMgdG8gZ2VuZXJhdGUgYW4gYXR0cmlidXRlcyBhcnJheQogICAgICAgICAgICAvLyB1c2luZyB0aGUgc2hhcmVkIHNwbGl0cyBhY3Jvc3MgYWxsIGF0dHJpYnV0ZXMuCiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBndWFyZC1mb3ItaW4KICAgICAgICAgICAgZm9yIChjb25zdCB2ZXJ0ZXggaW4gc3BsaXRJbmRpY2VzKSB7CiAgICAgICAgICAgICAgICBjb25zdCBmYWNlcyA9IHNwbGl0SW5kaWNlc1t2ZXJ0ZXhdOwogICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGd1YXJkLWZvci1pbgogICAgICAgICAgICAgICAgZm9yIChjb25zdCBmYWNlIGluIGZhY2VzKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGd0ID0gbnVtVW5TcGxpdFZhbHVlcyArIGZhY2VzW2ZhY2VdOwogICAgICAgICAgICAgICAgICAgIGlmICh2ZXJ0ZXggaW4gdGhpcy5zcGxpdHMgJiYgZmFjZSBpbiB0aGlzLnNwbGl0c1t2ZXJ0ZXhdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgYXR0cmlidXRlIGhhcyBhIHNwbGl0IHZhbHVlIGluIGl0cyBhcnJheS4KICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2UgbXVzdCB1c2UgdGhhdCB2YWx1ZS4uLgogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzcmMgPSB0aGlzLnNwbGl0c1t2ZXJ0ZXhdW2ZhY2VdOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzcmNBcnJheSA9IHRoaXMuc3BsaXRWYWx1ZXNbc3JjXTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzcmNBcnJheS5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVt0Z3QgKiB0aGlzLnN0cmlkZSArIGldID0gc3JjQXJyYXlbaV07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIENvcHkgZWFjaCBzY2FsYXIgdmFsdWUgdG8gdGhlIG5ldyBwbGFjZSBpbiB0aGUgYXJyYXkuCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNyYyA9IHBhcnNlSW50KHZlcnRleCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGUgPSAwOyBlIDwgdGhpcy5zdHJpZGU7IGUrKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVt0Z3QgKiB0aGlzLnN0cmlkZSArIGVdID0gdGhpcy5kYXRhW3NyYyAqIHRoaXMuc3RyaWRlICsgZV07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGRhdGE7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQZXJzaXN0ZW5jZQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSB0b0pTT04gbWV0aG9kIGVuY29kZXMgdGhpcyB0eXBlIGFzIGEganNvbiBvYmplY3QgZm9yIHBlcnNpc3RlbmNlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUganNvbiBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgdG9KU09OKGNvbnRleHQpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIGRhdGE6IEFycmF5LmZyb20odGhpcy5kYXRhKSwKICAgICAgICAgICAgICAgIGRhdGFUeXBlOiB0aGlzLmRhdGFUeXBlTmFtZSwKICAgICAgICAgICAgICAgIGxlbmd0aDogdGhpcy5kYXRhLmxlbmd0aCAvIHRoaXMuc3RyaWRlLAogICAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIGRlY29kZXMgYSBqc29uIG9iamVjdCBmb3IgdGhpcyB0eXBlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGogLSBUaGUganNvbiBvYmplY3QgdGhpcyBpdGVtIG11c3QgZGVjb2RlLgogICAgICAgICAqLwogICAgICAgIGZyb21KU09OKGopIHsKICAgICAgICAgICAgY29uc3QgZGF0YSA9IGouZGF0YTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICB0aGlzLmRhdGFbaV0gPSBkYXRhW2ldOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBsb2FkU3BsaXRWYWx1ZXMgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSByZWFkZXIgLSBUaGUgcmVhZGVyIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGxvYWRTcGxpdFZhbHVlcyhyZWFkZXIpIHsKICAgICAgICAgICAgY29uc3Qgc3BsaXRJbmRpY2VzID0gcmVhZGVyLmxvYWRVSW50MzJBcnJheSgpOwogICAgICAgICAgICBpZiAoc3BsaXRJbmRpY2VzLmxlbmd0aCA9PSAwKQogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICBsZXQgb2Zmc2V0ID0gMDsKICAgICAgICAgICAgbGV0IG51bVNwbGl0VmFsdWVzID0gMDsKICAgICAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHZlcnRleElkID0gc3BsaXRJbmRpY2VzW29mZnNldCsrXTsKICAgICAgICAgICAgICAgIGNvbnN0IG51bVNwbGl0cyA9IHNwbGl0SW5kaWNlc1tvZmZzZXQrK107CiAgICAgICAgICAgICAgICBjb25zdCBzcGxpdHMgPSB7fTsKICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtU3BsaXRzOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBmYWNlSWQgPSBzcGxpdEluZGljZXNbb2Zmc2V0KytdOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHNwbGl0SWQgPSBzcGxpdEluZGljZXNbb2Zmc2V0KytdOwogICAgICAgICAgICAgICAgICAgIHNwbGl0c1tmYWNlSWRdID0gc3BsaXRJZDsKICAgICAgICAgICAgICAgICAgICBpZiAoc3BsaXRJZCA+PSBudW1TcGxpdFZhbHVlcykKICAgICAgICAgICAgICAgICAgICAgICAgbnVtU3BsaXRWYWx1ZXMgPSBzcGxpdElkICsgMTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRoaXMuc3BsaXRzW3ZlcnRleElkXSA9IHNwbGl0czsKICAgICAgICAgICAgICAgIGlmIChvZmZzZXQgPj0gc3BsaXRJbmRpY2VzLmxlbmd0aCkKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBkaW0gPSB0aGlzLnN0cmlkZTsKICAgICAgICAgICAgY29uc3Qgc3BsaXRWYWx1ZXMgPSByZWFkZXIubG9hZEZsb2F0MzJBcnJheShudW1TcGxpdFZhbHVlcyAqIGRpbSk7CiAgICAgICAgICAgIHRoaXMuc3BsaXRWYWx1ZXMgPSBbXTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1TcGxpdFZhbHVlczsgaSsrKSB7CiAgICAgICAgICAgICAgICBjb25zdCB2YWwgPSBzcGxpdFZhbHVlcy5zbGljZShpICogZGltLCBpICogZGltICsgZGltKTsKICAgICAgICAgICAgICAgIHRoaXMuc3BsaXRWYWx1ZXMucHVzaCh2YWwpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgb2JqZWN0J3Mgc3RhdGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICB0b1N0cmluZygpIHsKICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoaXMudG9KU09OKCksIG51bGwsIDIpOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gTWVtb3J5CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB2ZXJ0ZXggYXR0cmlidXRlcyBidWZmZXJzIGFuZCBpdHMgY291bnQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZW5CdWZmZXIoKSB7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICB2YWx1ZXM6IHRoaXMuZGF0YSwKICAgICAgICAgICAgICAgIGNvdW50OiB0aGlzLmdldENvdW50KCksCiAgICAgICAgICAgICAgICBkaW1lbnNpb246IHRoaXMuc3RyaWRlLAogICAgICAgICAgICAgICAgZGF0YVR5cGU6IHRoaXMuZGF0YVR5cGVOYW1lLAogICAgICAgICAgICAgICAgbm9ybWFsaXplZDogdGhpcy5ub3JtYWxpemVkLAogICAgICAgICAgICB9OwogICAgICAgIH0KICAgIH0KCiAgICAvKioKICAgICAqIENsYXNzIHJlcHJlc2VudGluZyBhbiBhdHRyaWJ1dGUuCiAgICAgKi8KICAgIGNsYXNzIFZlYzJBdHRyaWJ1dGUgZXh0ZW5kcyBBdHRyaWJ1dGUgewogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIFZlYzJBdHRyaWJ1dGUuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IoZGF0YVR5cGVOYW1lID0gJ1ZlYzInKSB7CiAgICAgICAgICAgIHN1cGVyKGRhdGFUeXBlTmFtZSwgMik7CiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplZCA9IGZhbHNlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBWZWMyIGZyb20gdGhlIHNwZWNpZmllZCBpbmRleC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIFZlYzIgLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldFZhbHVlKGluZGV4KSB7CiAgICAgICAgICAgIGlmIChpbmRleCA+PSB0aGlzLmRhdGEubGVuZ3RoIC8gdGhpcy5zdHJpZGUpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdmVydGV4IGluZGV4OicgKyBpbmRleCArICcuIE51bSBWZXJ0aWNlczonICsgdGhpcy5kYXRhLmxlbmd0aCAvIDMpOwogICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBpbmRleCAqIHRoaXMuc3RyaWRlOwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzIodGhpcy5kYXRhW29mZnNldF0sIHRoaXMuZGF0YVtvZmZzZXQgKyAxXSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgVmVjMiBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gVGhlIGluZGV4IHZhbHVlLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSBwYXJhbS4KICAgICAgICAgKi8KICAgICAgICBzZXRWYWx1ZShpbmRleCwgdmFsdWUpIHsKICAgICAgICAgICAgaWYgKGluZGV4ID49IHRoaXMuZGF0YS5sZW5ndGggLyB0aGlzLnN0cmlkZSkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB2ZXJ0ZXggaW5kZXg6JyArIGluZGV4ICsgJy4gTnVtIFZlcnRpY2VzOicgKyB0aGlzLmRhdGEubGVuZ3RoIC8gMyk7CiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IGluZGV4ICogdGhpcy5zdHJpZGU7CiAgICAgICAgICAgIHRoaXMuZGF0YS5zZXQodmFsdWUuYXNBcnJheSgpLCBvZmZzZXQpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSB2YWx1ZSBvZiBhIGNvcm5lciB2ZXJ0ZXggb2YgYSBmYWNlLgogICAgICAgICAqID4gTm90ZTogJ1JlZicgbWVhbnMgdGhhdCB0aGUgdmFsdWUgY29udGFpbnMgYSByZWZlcmVuY2UgdG8gdGhlIGRhdGEgaW4gdGhlIGF0dHJpYnV0ZS4KICAgICAgICAgKiA+IFRoZSBjb21wb25lbnRzIG9mIHRoZSB2YWx1ZSBjYW4gYmUgY2hhbmdlZCBjYXVzaW5nIHRoZSBhdHRyaWJ1dGVzIGRhdGEgaXMgY2hhbmdlZC4KICAgICAgICAgKiA+IE5vIG5lZWQgdG8gY2FsbCAnc2V0RmFjZVZlcnRleFZhbHVlJy4KICAgICAgICAgKiBAcGFyYW0gZmFjZSAtIFRoZSBmYWNlIGluZGV4LgogICAgICAgICAqIEBwYXJhbSBmYWNlVmVydGV4IC0gVGhlIGluZGV4IG9mIHZlcnRleCB3aXRoaW4gdGhlIGZhY2UuIFswLi4uIG51bSBmYWNlIHZlcnRpY2VzXQogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldEZhY2VWZXJ0ZXhWYWx1ZShmYWNlLCBmYWNlVmVydGV4KSB7CiAgICAgICAgICAgIGNvbnN0IGFycmF5ID0gdGhpcy5nZXRGYWNlVmVydGV4VmFsdWVfYXJyYXkoZmFjZSwgZmFjZVZlcnRleCk7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMihhcnJheVswXSwgYXJyYXlbMV0pOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHRoZSB2YWx1ZSBvZiBhIGNvcm5lciB2ZXJ0ZXggb2YgYSBmYWNlLgogICAgICAgICAqIEBwYXJhbSBmYWNlIC0gVGhlIGZhY2UgaW5kZXguCiAgICAgICAgICogQHBhcmFtIGZhY2VWZXJ0ZXggLSBUaGUgaW5kZXggb2YgdmVydGV4IHdpdGhpbiB0aGUgZmFjZS4gWzAuLi4gbnVtIGZhY2UgdmVydGljZXNdCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldEZhY2VWZXJ0ZXhWYWx1ZShmYWNlLCBmYWNlVmVydGV4LCB2YWx1ZSkgewogICAgICAgICAgICB0aGlzLnNldEZhY2VWZXJ0ZXhWYWx1ZV9hcnJheShmYWNlLCBmYWNlVmVydGV4LCBGbG9hdDMyQXJyYXkuZnJvbSh2YWx1ZS5hc0FycmF5KCkpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHNldFNwbGl0VmVydGV4VmFsdWUgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSB2ZXJ0ZXggLSBUaGUgdmVydGV4IHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBmYWNlIC0gVGhlIGZhY2UgaW5kZXguCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldFNwbGl0VmVydGV4VmFsdWUodmVydGV4LCBmYWNlLCB2YWx1ZSkgewogICAgICAgICAgICB0aGlzLnNldFNwbGl0VmVydGV4VmFsdWVfYXJyYXkodmVydGV4LCBmYWNlLCBGbG9hdDMyQXJyYXkuZnJvbSh2YWx1ZS5hc0FycmF5KCkpKTsKICAgICAgICB9CiAgICAgICAgbWVyZ2Uob3RoZXIsIHhmbyA9IG5ldyBYZm8oKSkgewogICAgICAgICAgICBjb25zdCBwcmV2TnVtVmFsdWVzID0gdGhpcy5nZXRDb3VudCgpOwogICAgICAgICAgICBjb25zdCBhZGRlZFZhbHVlcyA9IG90aGVyLmdldENvdW50KCk7CiAgICAgICAgICAgIHRoaXMuc2V0Q291bnQocHJldk51bVZhbHVlcyArIGFkZGVkVmFsdWVzKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhZGRlZFZhbHVlczsgaSsrKSB7CiAgICAgICAgICAgICAgICB0aGlzLnNldFZhbHVlKHByZXZOdW1WYWx1ZXMgKyBpLCBvdGhlci5nZXRWYWx1ZShpKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5zcGxpdFZhbHVlcyA9IFsuLi50aGlzLnNwbGl0VmFsdWVzLCAuLi5vdGhlci5zcGxpdFZhbHVlc107CiAgICAgICAgfQogICAgfQogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ1ZlYzJBdHRyaWJ1dGUnLCBWZWMyQXR0cmlidXRlKTsKCiAgICBjb25zdCBtYXBJbiQyID0gKHZhbHVlKSA9PiB7CiAgICAgICAgcmV0dXJuIE1hdGhGdW5jdGlvbnMuZW5jb2RlMTZCaXRGbG9hdCh2YWx1ZSk7CiAgICB9OwogICAgY29uc3QgbWFwT3V0JDIgPSAodmFsdWUpID0+IHsKICAgICAgICByZXR1cm4gTWF0aEZ1bmN0aW9ucy5kZWNvZGUxNkJpdEZsb2F0KHZhbHVlKTsKICAgIH07CiAgICAvKioKICAgICAqIENsYXNzIHJlcHJlc2VudGluZyBhbiBhdHRyaWJ1dGUuCiAgICAgKi8KICAgIGNsYXNzIFZlYzJmMTZBdHRyaWJ1dGUgZXh0ZW5kcyBWZWMyQXR0cmlidXRlIHsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgYSBWZWMzZjhBdHRyaWJ1dGUuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgICAgIHN1cGVyKCdWZWMyZjE2Jyk7CiAgICAgICAgfQogICAgICAgIGluaXQoKSB7CiAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5ldyBVaW50MTZBcnJheSgwKTsKICAgICAgICAgICAgdGhpcy5pbml0UmFuZ2UoMCk7CiAgICAgICAgfQogICAgICAgIGluaXRSYW5nZShzdGFydCkgewogICAgICAgICAgICAvLyBJbml0aWFsaXplIHRoZSB2YWx1ZXMgdG8gaW52YWxpZCB2YWx1ZXMuCiAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdGFydDsgaSA8IHRoaXMuZGF0YS5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgdGhpcy5kYXRhW2ldID0gbWFwSW4kMihOdW1iZXIuTmFOKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpc0luaXRpYWxpemVkKGEpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBpZiAoTnVtYmVyLmlzRmluaXRlKG1hcE91dCQyKGFbaV0pKSkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYSBjb3B5IG9mIHRoZSBWZWMyIHZhbHVlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdmFsdWUuCiAgICAgICAgICogQHJldHVybiBWZWMyIC0gVGhlIHZhbHVlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICovCiAgICAgICAgZ2V0VmFsdWUoaW5kZXgpIHsKICAgICAgICAgICAgaWYgKGluZGV4ID49IHRoaXMuZGF0YS5sZW5ndGggLyB0aGlzLnN0cmlkZSkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB2ZXJ0ZXggaW5kZXg6JyArIGluZGV4ICsgJy4gTnVtIFZlcnRpY2VzOicgKyB0aGlzLmRhdGEubGVuZ3RoIC8gMyk7CiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IGluZGV4ICogdGhpcy5zdHJpZGU7CiAgICAgICAgICAgIGNvbnN0IHZhbHVlRGF0YSA9IHRoaXMuZGF0YS5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIHRoaXMuc3RyaWRlKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMyKG1hcE91dCQyKHZhbHVlRGF0YVswXSksIG1hcE91dCQyKHZhbHVlRGF0YVsxXSkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIFZlYzIgYXQgdGhlIHNwZWNpZmllZCBpbmRleC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgcGFyYW0uCiAgICAgICAgICovCiAgICAgICAgc2V0VmFsdWUoaW5kZXgsIHZhbHVlKSB7CiAgICAgICAgICAgIGlmIChpbmRleCA+PSB0aGlzLmRhdGEubGVuZ3RoIC8gdGhpcy5zdHJpZGUpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdmVydGV4IGluZGV4OicgKyBpbmRleCArICcuIE51bSBWZXJ0aWNlczonICsgdGhpcy5kYXRhLmxlbmd0aCAvIDMpOwogICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBpbmRleCAqIHRoaXMuc3RyaWRlOwogICAgICAgICAgICBjb25zdCB2YWx1ZURhdGEgPSB0aGlzLmRhdGEuc3ViYXJyYXkob2Zmc2V0LCBvZmZzZXQgKyB0aGlzLnN0cmlkZSk7CiAgICAgICAgICAgIHZhbHVlRGF0YVswXSA9IG1hcEluJDIodmFsdWUueCk7CiAgICAgICAgICAgIHZhbHVlRGF0YVsxXSA9IG1hcEluJDIodmFsdWUueSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIHZhbHVlIG9mIGEgY29ybmVyIHZlcnRleCBvZiBhIGZhY2UuCiAgICAgICAgICogPiBOb3RlOiAnUmVmJyBtZWFucyB0aGF0IHRoZSB2YWx1ZSBjb250YWlucyBhIHJlZmVyZW5jZSB0byB0aGUgZGF0YSBpbiB0aGUgYXR0cmlidXRlLgogICAgICAgICAqID4gVGhlIGNvbXBvbmVudHMgb2YgdGhlIHZhbHVlIGNhbiBiZSBjaGFuZ2VkIGNhdXNpbmcgdGhlIGF0dHJpYnV0ZXMgZGF0YSBpcyBjaGFuZ2VkLgogICAgICAgICAqID4gTm8gbmVlZCB0byBjYWxsICdzZXRGYWNlVmVydGV4VmFsdWUnLgogICAgICAgICAqIEBwYXJhbSBmYWNlIC0gVGhlIGZhY2UgaW5kZXguCiAgICAgICAgICogQHBhcmFtIGZhY2VWZXJ0ZXggLSBUaGUgaW5kZXggb2YgdmVydGV4IHdpdGhpbiB0aGUgZmFjZS4gWzAuLi4gbnVtIGZhY2UgdmVydGljZXNdCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0RmFjZVZlcnRleFZhbHVlKGZhY2UsIGZhY2VWZXJ0ZXgpIHsKICAgICAgICAgICAgY29uc3QgYXJyYXkgPSB0aGlzLmdldEZhY2VWZXJ0ZXhWYWx1ZV9hcnJheShmYWNlLCBmYWNlVmVydGV4KTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMyKG1hcE91dCQyKGFycmF5WzBdKSwgbWFwT3V0JDIoYXJyYXlbMV0pKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB0aGUgdmFsdWUgb2YgYSBjb3JuZXIgdmVydGV4IG9mIGEgZmFjZS4KICAgICAgICAgKiBAcGFyYW0gZmFjZSAtIFRoZSBmYWNlIGluZGV4LgogICAgICAgICAqIEBwYXJhbSBmYWNlVmVydGV4IC0gVGhlIGluZGV4IG9mIHZlcnRleCB3aXRoaW4gdGhlIGZhY2UuIFswLi4uIG51bSBmYWNlIHZlcnRpY2VzXQogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRGYWNlVmVydGV4VmFsdWUoZmFjZSwgZmFjZVZlcnRleCwgdmFsdWUpIHsKICAgICAgICAgICAgY29uc3QgdmFsdWVEYXRhID0gbmV3IFVpbnQxNkFycmF5KDIpOwogICAgICAgICAgICB2YWx1ZURhdGFbMF0gPSBtYXBJbiQyKHZhbHVlLngpOwogICAgICAgICAgICB2YWx1ZURhdGFbMV0gPSBtYXBJbiQyKHZhbHVlLnkpOwogICAgICAgICAgICB0aGlzLnNldEZhY2VWZXJ0ZXhWYWx1ZV9hcnJheShmYWNlLCBmYWNlVmVydGV4LCB2YWx1ZURhdGEpOwogICAgICAgIH0KICAgIH0KCiAgICBjbGFzcyBWZWMzUmVmIHsKICAgICAgICBkYXRhOwogICAgICAgIGNvbnN0cnVjdG9yKGRhdGEpIHsKICAgICAgICAgICAgdGhpcy5kYXRhID0gZGF0YTsKICAgICAgICB9CiAgICAgICAgZ2V0IHgoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFbMF07CiAgICAgICAgfQogICAgICAgIHNldCB4KHZhbHVlKSB7CiAgICAgICAgICAgIHRoaXMuZGF0YVswXSA9IHZhbHVlOwogICAgICAgIH0KICAgICAgICBnZXQgeSgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0YVsxXTsKICAgICAgICB9CiAgICAgICAgc2V0IHkodmFsdWUpIHsKICAgICAgICAgICAgdGhpcy5kYXRhWzFdID0gdmFsdWU7CiAgICAgICAgfQogICAgICAgIGdldCB6KCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhWzJdOwogICAgICAgIH0KICAgICAgICBzZXQgeih2YWx1ZSkgewogICAgICAgICAgICB0aGlzLmRhdGFbMl0gPSB2YWx1ZTsKICAgICAgICB9CiAgICAgICAgc2V0KHgsIHksIHopIHsKICAgICAgICAgICAgdGhpcy5kYXRhWzBdID0geDsKICAgICAgICAgICAgdGhpcy5kYXRhWzFdID0geTsKICAgICAgICAgICAgdGhpcy5kYXRhWzJdID0gejsKICAgICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIENsYXNzIHJlcHJlc2VudGluZyBhbiBhdHRyaWJ1dGUuCiAgICAgKi8KICAgIGNsYXNzIFZlYzNBdHRyaWJ1dGUgZXh0ZW5kcyBBdHRyaWJ1dGUgewogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIFZlYzNBdHRyaWJ1dGUuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IoZGF0YVR5cGVOYW1lID0gJ1ZlYzMnKSB7CiAgICAgICAgICAgIHN1cGVyKGRhdGFUeXBlTmFtZSwgMyk7CiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplZCA9IGZhbHNlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIGEgY29weSBvZiB0aGUgVmVjMyB2YWx1ZSBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gVGhlIGluZGV4IHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gVmVjMyAtIFRoZSB2YWx1ZSBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LgogICAgICAgICAqLwogICAgICAgIGdldFZhbHVlKGluZGV4KSB7CiAgICAgICAgICAgIGlmIChpbmRleCA+PSB0aGlzLmRhdGEubGVuZ3RoIC8gdGhpcy5zdHJpZGUpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdmVydGV4IGluZGV4OicgKyBpbmRleCArICcuIE51bSBWZXJ0aWNlczonICsgdGhpcy5kYXRhLmxlbmd0aCAvIDMpOwogICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBpbmRleCAqIHRoaXMuc3RyaWRlOwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzModGhpcy5kYXRhW29mZnNldCArIDBdLCB0aGlzLmRhdGFbb2Zmc2V0ICsgMV0sIHRoaXMuZGF0YVtvZmZzZXQgKyAyXSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYSBjb3B5IG9mIHRoZSBWZWMzIHZhbHVlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICoKICAgICAgICAgKiBAZGVwcmVjYXRlZCAtIFRoaXMgbWV0aG9kIHdpbGwgc29vbiBiZSByZW1vdmVkLgogICAgICAgICAqIEByZXR1cm4gVmVjMyAtIFRoZSB2YWx1ZSBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LgogICAgICAgICAqLwogICAgICAgIGdldFZhbHVlUmVmKGluZGV4KSB7CiAgICAgICAgICAgIGlmIChpbmRleCA+PSB0aGlzLmRhdGEubGVuZ3RoIC8gdGhpcy5zdHJpZGUpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdmVydGV4IGluZGV4OicgKyBpbmRleCArICcuIE51bSBWZXJ0aWNlczonICsgdGhpcy5kYXRhLmxlbmd0aCAvIDMpOwogICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBpbmRleCAqIHRoaXMuc3RyaWRlOwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzNSZWYodGhpcy5kYXRhLnN1YmFycmF5KG9mZnNldCwgb2Zmc2V0ICsgMykpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIFZlYzMgYXQgdGhlIHNwZWNpZmllZCBpbmRleC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgcGFyYW0uCiAgICAgICAgICovCiAgICAgICAgc2V0VmFsdWUoaW5kZXgsIHZhbHVlKSB7CiAgICAgICAgICAgIHRoaXMuc2V0VmFsdWVzKGluZGV4LCB2YWx1ZS5hc0FycmF5KCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSB2YWx1ZSBvZiBhIGNvcm5lciB2ZXJ0ZXggb2YgYSBmYWNlLgogICAgICAgICAqID4gTm90ZTogJ1JlZicgbWVhbnMgdGhhdCB0aGUgdmFsdWUgY29udGFpbnMgYSByZWZlcmVuY2UgdG8gdGhlIGRhdGEgaW4gdGhlIGF0dHJpYnV0ZS4KICAgICAgICAgKiA+IFRoZSBjb21wb25lbnRzIG9mIHRoZSB2YWx1ZSBjYW4gYmUgY2hhbmdlZCBjYXVzaW5nIHRoZSBhdHRyaWJ1dGVzIGRhdGEgaXMgY2hhbmdlZC4KICAgICAgICAgKiA+IE5vIG5lZWQgdG8gY2FsbCAnc2V0RmFjZVZlcnRleFZhbHVlJy4KICAgICAgICAgKiBAcGFyYW0gZmFjZSAtIFRoZSBmYWNlIGluZGV4LgogICAgICAgICAqIEBwYXJhbSBmYWNlVmVydGV4IC0gVGhlIGluZGV4IG9mIHZlcnRleCB3aXRoaW4gdGhlIGZhY2UuIFswLi4uIG51bSBmYWNlIHZlcnRpY2VzXQogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldEZhY2VWZXJ0ZXhWYWx1ZShmYWNlLCBmYWNlVmVydGV4KSB7CiAgICAgICAgICAgIGNvbnN0IGFycmF5ID0gdGhpcy5nZXRGYWNlVmVydGV4VmFsdWVfYXJyYXkoZmFjZSwgZmFjZVZlcnRleCk7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyhhcnJheVswXSwgYXJyYXlbMV0sIGFycmF5WzJdKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB0aGUgdmFsdWUgb2YgYSBjb3JuZXIgdmVydGV4IG9mIGEgZmFjZS4KICAgICAgICAgKiBAcGFyYW0gZmFjZSAtIFRoZSBmYWNlIGluZGV4LgogICAgICAgICAqIEBwYXJhbSBmYWNlVmVydGV4IC0gVGhlIGluZGV4IG9mIHZlcnRleCB3aXRoaW4gdGhlIGZhY2UuIFswLi4uIG51bSBmYWNlIHZlcnRpY2VzXQogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRGYWNlVmVydGV4VmFsdWUoZmFjZSwgZmFjZVZlcnRleCwgdmFsdWUpIHsKICAgICAgICAgICAgdGhpcy5zZXRGYWNlVmVydGV4VmFsdWVfYXJyYXkoZmFjZSwgZmFjZVZlcnRleCwgRmxvYXQzMkFycmF5LmZyb20odmFsdWUuYXNBcnJheSgpKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBzZXRTcGxpdFZlcnRleFZhbHVlIG1ldGhvZC4KICAgICAgICAgKiBAcGFyYW0gdmVydGV4IC0gVGhlIHZlcnRleCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gZmFjZSAtIFRoZSBmYWNlIGluZGV4LgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRTcGxpdFZlcnRleFZhbHVlKHZlcnRleCwgZmFjZSwgdmFsdWUpIHsKICAgICAgICAgICAgdGhpcy5zZXRTcGxpdFZlcnRleFZhbHVlX2FycmF5KHZlcnRleCwgZmFjZSwgRmxvYXQzMkFycmF5LmZyb20odmFsdWUuYXNBcnJheSgpKSk7CiAgICAgICAgfQogICAgICAgIG1lcmdlKG90aGVyLCB4Zm8gPSBuZXcgWGZvKCkpIHsKICAgICAgICAgICAgY29uc3QgcHJldk51bVZhbHVlcyA9IHRoaXMuZ2V0Q291bnQoKTsKICAgICAgICAgICAgY29uc3QgYWRkZWRWYWx1ZXMgPSBvdGhlci5nZXRDb3VudCgpOwogICAgICAgICAgICAvLyBXZSBjYWNoZWQgdGhlc2UgdmFsdWVzIGJlZm9yZSBjYWxsaW5nICdzZXRDb3VudCcuCiAgICAgICAgICAgIC8vIE1heWJlICdzZXRDb3VudCcgc2hvdWxuZCd0IGNsZWFyIHRoZSBzcGxpdHMuIEl0IHNlZW1zIGhlYXZ5LCBidXQgSSBkb24ndCB3YW50IHRvIGNoYW5nZSBhbnl0aGluZy4KICAgICAgICAgICAgLy8gV2Ugc2hvdWxkIGp1c3QgcmUtd3JpdGUgdGhlIHN5c3RlbSB3aXRob3V0IHNwbGl0cyBhbnl3YXkuCiAgICAgICAgICAgIC8vIGNvbnN0IHNwbGl0VmFsdWVzID0gWy4uLnRoaXMuc3BsaXRWYWx1ZXMsIC4uLm90aGVyLnNwbGl0VmFsdWVzXQogICAgICAgICAgICAvLyBjb25zdCBzcGxpdHMgPSBbLi4udGhpcy5zcGxpdHMsIC4uLm90aGVyLnNwbGl0c10KICAgICAgICAgICAgdGhpcy5zZXRDb3VudChwcmV2TnVtVmFsdWVzICsgYWRkZWRWYWx1ZXMpOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFkZGVkVmFsdWVzOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMuc2V0VmFsdWUocHJldk51bVZhbHVlcyArIGksIHhmby50cmFuc2Zvcm1WZWMzKG90aGVyLmdldFZhbHVlKGkpKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gdGhpcy5zcGxpdFZhbHVlcyA9IFsuLi50aGlzLnNwbGl0VmFsdWVzLCAuLi5vdGhlci5zcGxpdFZhbHVlc10KICAgICAgICB9CiAgICB9CiAgICBSZWdpc3RyeS5yZWdpc3RlcignVmVjM0F0dHJpYnV0ZScsIFZlYzNBdHRyaWJ1dGUpOwoKICAgIGNsYXNzIFZlYzNmOFJlZiB7CiAgICAgICAgZGF0YTsKICAgICAgICBjb25zdHJ1Y3RvcihkYXRhKSB7CiAgICAgICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7CiAgICAgICAgfQogICAgICAgIGdldCB4KCkgewogICAgICAgICAgICByZXR1cm4gTWF0aEZ1bmN0aW9ucy5kZWNvZGUxNkJpdEZsb2F0KHRoaXMuZGF0YVswXSk7CiAgICAgICAgfQogICAgICAgIHNldCB4KHZhbHVlKSB7CiAgICAgICAgICAgIHRoaXMuZGF0YVswXSA9IE1hdGhGdW5jdGlvbnMuZW5jb2RlMTZCaXRGbG9hdCh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGdldCB5KCkgewogICAgICAgICAgICByZXR1cm4gTWF0aEZ1bmN0aW9ucy5kZWNvZGUxNkJpdEZsb2F0KHRoaXMuZGF0YVsxXSk7CiAgICAgICAgfQogICAgICAgIHNldCB5KHZhbHVlKSB7CiAgICAgICAgICAgIHRoaXMuZGF0YVsxXSA9IE1hdGhGdW5jdGlvbnMuZW5jb2RlMTZCaXRGbG9hdCh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGdldCB6KCkgewogICAgICAgICAgICByZXR1cm4gTWF0aEZ1bmN0aW9ucy5kZWNvZGUxNkJpdEZsb2F0KHRoaXMuZGF0YVsyXSk7CiAgICAgICAgfQogICAgICAgIHNldCB6KHZhbHVlKSB7CiAgICAgICAgICAgIHRoaXMuZGF0YVsyXSA9IE1hdGhGdW5jdGlvbnMuZW5jb2RlMTZCaXRGbG9hdCh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHNldCh4LCB5LCB6KSB7CiAgICAgICAgICAgIHRoaXMuZGF0YVswXSA9IE1hdGhGdW5jdGlvbnMuZW5jb2RlMTZCaXRGbG9hdCh4KTsKICAgICAgICAgICAgdGhpcy5kYXRhWzFdID0gTWF0aEZ1bmN0aW9ucy5lbmNvZGUxNkJpdEZsb2F0KHkpOwogICAgICAgICAgICB0aGlzLmRhdGFbMl0gPSBNYXRoRnVuY3Rpb25zLmVuY29kZTE2Qml0RmxvYXQoeik7CiAgICAgICAgfQogICAgfQogICAgY29uc3QgbWFwSW4kMSA9ICh2YWx1ZSwgdmFsdWVSYW5nZSkgPT4gewogICAgICAgIHJldHVybiBNYXRoRnVuY3Rpb25zLnJlbWFwKHZhbHVlLCB2YWx1ZVJhbmdlWzBdLCB2YWx1ZVJhbmdlWzFdLCAtMTI3LCAxMjcpOwogICAgfTsKICAgIGNvbnN0IG1hcE91dCQxID0gKHZhbHVlLCB2YWx1ZVJhbmdlKSA9PiB7CiAgICAgICAgcmV0dXJuIE1hdGhGdW5jdGlvbnMucmVtYXAodmFsdWUsIC0xMjcsIDEyNywgdmFsdWVSYW5nZVswXSwgdmFsdWVSYW5nZVsxXSk7CiAgICB9OwogICAgLyoqCiAgICAgKiBDbGFzcyByZXByZXNlbnRpbmcgYW4gYXR0cmlidXRlLgogICAgICovCiAgICBjbGFzcyBWZWMzZjhBdHRyaWJ1dGUgZXh0ZW5kcyBWZWMzQXR0cmlidXRlIHsKICAgICAgICB2YWx1ZVJhbmdlOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIFZlYzNmOEF0dHJpYnV0ZS4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3Rvcih2YWx1ZVJhbmdlID0gWy0xLCAxXSkgewogICAgICAgICAgICBzdXBlcignVmVjM2Y4Jyk7CiAgICAgICAgICAgIHRoaXMudmFsdWVSYW5nZSA9IHZhbHVlUmFuZ2U7CiAgICAgICAgfQogICAgICAgIGluaXQoKSB7CiAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5ldyBJbnQ4QXJyYXkoMCk7CiAgICAgICAgICAgIHRoaXMuaW5pdFJhbmdlKDApOwogICAgICAgIH0KICAgICAgICBpbml0UmFuZ2Uoc3RhcnQpIHsKICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgdmFsdWVzIHRvIGludmFsaWQgdmFsdWVzLgogICAgICAgICAgICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCB0aGlzLmRhdGEubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMuZGF0YVtpXSA9IG1hcEluJDEoTnVtYmVyLk5hTiwgdGhpcy52YWx1ZVJhbmdlKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpc0luaXRpYWxpemVkKGEpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBpZiAoTnVtYmVyLmlzRmluaXRlKG1hcE91dCQxKGFbaV0sIHRoaXMudmFsdWVSYW5nZSkpKQogICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBhIGNvcHkgb2YgdGhlIFZlYzMgdmFsdWUgYXQgdGhlIHNwZWNpZmllZCBpbmRleC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIFZlYzMgLSBUaGUgdmFsdWUgYXQgdGhlIHNwZWNpZmllZCBpbmRleC4KICAgICAgICAgKi8KICAgICAgICBnZXRWYWx1ZShpbmRleCkgewogICAgICAgICAgICBpZiAoaW5kZXggPj0gdGhpcy5kYXRhLmxlbmd0aCAvIHRoaXMuc3RyaWRlKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHZlcnRleCBpbmRleDonICsgaW5kZXggKyAnLiBOdW0gVmVydGljZXM6JyArIHRoaXMuZGF0YS5sZW5ndGggLyAzKTsKICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gaW5kZXggKiB0aGlzLnN0cmlkZTsKICAgICAgICAgICAgY29uc3QgdmFsdWVEYXRhID0gdGhpcy5kYXRhLnN1YmFycmF5KG9mZnNldCwgb2Zmc2V0ICsgdGhpcy5zdHJpZGUpOwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzMobWFwT3V0JDEodmFsdWVEYXRhWzBdLCB0aGlzLnZhbHVlUmFuZ2UpLCBtYXBPdXQkMSh2YWx1ZURhdGFbMV0sIHRoaXMudmFsdWVSYW5nZSksIG1hcE91dCQxKHZhbHVlRGF0YVsyXSwgdGhpcy52YWx1ZVJhbmdlKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYSBjb3B5IG9mIHRoZSBWZWMzIHZhbHVlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICoKICAgICAgICAgKiBAZGVwcmVjYXRlZCAtIFRoaXMgbWV0aG9kIHdpbGwgc29vbiBiZSByZW1vdmVkLgogICAgICAgICAqIEByZXR1cm4gVmVjMyAtIFRoZSB2YWx1ZSBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LgogICAgICAgICAqLwogICAgICAgIGdldFZhbHVlUmVmKGluZGV4KSB7CiAgICAgICAgICAgIGlmIChpbmRleCA+PSB0aGlzLmRhdGEubGVuZ3RoIC8gdGhpcy5zdHJpZGUpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdmVydGV4IGluZGV4OicgKyBpbmRleCArICcuIE51bSBWZXJ0aWNlczonICsgdGhpcy5kYXRhLmxlbmd0aCAvIDMpOwogICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBpbmRleCAqIHRoaXMuc3RyaWRlOwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzNmOFJlZih0aGlzLmRhdGEuc3ViYXJyYXkob2Zmc2V0LCBvZmZzZXQgKyAzKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgVmVjMyBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gVGhlIGluZGV4IHZhbHVlLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSBwYXJhbS4KICAgICAgICAgKi8KICAgICAgICBzZXRWYWx1ZShpbmRleCwgdmFsdWUpIHsKICAgICAgICAgICAgaWYgKGluZGV4ID49IHRoaXMuZGF0YS5sZW5ndGggLyB0aGlzLnN0cmlkZSkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB2ZXJ0ZXggaW5kZXg6JyArIGluZGV4ICsgJy4gTnVtIFZlcnRpY2VzOicgKyB0aGlzLmRhdGEubGVuZ3RoIC8gMyk7CiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IGluZGV4ICogdGhpcy5zdHJpZGU7CiAgICAgICAgICAgIGNvbnN0IHZhbHVlRGF0YSA9IHRoaXMuZGF0YS5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIHRoaXMuc3RyaWRlKTsKICAgICAgICAgICAgdmFsdWVEYXRhWzBdID0gbWFwSW4kMSh2YWx1ZS54LCB0aGlzLnZhbHVlUmFuZ2UpOwogICAgICAgICAgICB2YWx1ZURhdGFbMV0gPSBtYXBJbiQxKHZhbHVlLnksIHRoaXMudmFsdWVSYW5nZSk7CiAgICAgICAgICAgIHZhbHVlRGF0YVsyXSA9IG1hcEluJDEodmFsdWUueiwgdGhpcy52YWx1ZVJhbmdlKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgdmFsdWUgb2YgYSBjb3JuZXIgdmVydGV4IG9mIGEgZmFjZS4KICAgICAgICAgKiA+IE5vdGU6ICdSZWYnIG1lYW5zIHRoYXQgdGhlIHZhbHVlIGNvbnRhaW5zIGEgcmVmZXJlbmNlIHRvIHRoZSBkYXRhIGluIHRoZSBhdHRyaWJ1dGUuCiAgICAgICAgICogPiBUaGUgY29tcG9uZW50cyBvZiB0aGUgdmFsdWUgY2FuIGJlIGNoYW5nZWQgY2F1c2luZyB0aGUgYXR0cmlidXRlcyBkYXRhIGlzIGNoYW5nZWQuCiAgICAgICAgICogPiBObyBuZWVkIHRvIGNhbGwgJ3NldEZhY2VWZXJ0ZXhWYWx1ZScuCiAgICAgICAgICogQHBhcmFtIGZhY2UgLSBUaGUgZmFjZSBpbmRleC4KICAgICAgICAgKiBAcGFyYW0gZmFjZVZlcnRleCAtIFRoZSBpbmRleCBvZiB2ZXJ0ZXggd2l0aGluIHRoZSBmYWNlLiBbMC4uLiBudW0gZmFjZSB2ZXJ0aWNlc10KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRGYWNlVmVydGV4VmFsdWUoZmFjZSwgZmFjZVZlcnRleCkgewogICAgICAgICAgICBjb25zdCBhcnJheSA9IHRoaXMuZ2V0RmFjZVZlcnRleFZhbHVlX2FycmF5KGZhY2UsIGZhY2VWZXJ0ZXgpOwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzMobWFwT3V0JDEoYXJyYXlbMF0sIHRoaXMudmFsdWVSYW5nZSksIG1hcE91dCQxKGFycmF5WzFdLCB0aGlzLnZhbHVlUmFuZ2UpLCBtYXBPdXQkMShhcnJheVsyXSwgdGhpcy52YWx1ZVJhbmdlKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIHZhbHVlIG9mIGEgY29ybmVyIHZlcnRleCBvZiBhIGZhY2UuCiAgICAgICAgICogQHBhcmFtIGZhY2UgLSBUaGUgZmFjZSBpbmRleC4KICAgICAgICAgKiBAcGFyYW0gZmFjZVZlcnRleCAtIFRoZSBpbmRleCBvZiB2ZXJ0ZXggd2l0aGluIHRoZSBmYWNlLiBbMC4uLiBudW0gZmFjZSB2ZXJ0aWNlc10KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0RmFjZVZlcnRleFZhbHVlKGZhY2UsIGZhY2VWZXJ0ZXgsIHZhbHVlKSB7CiAgICAgICAgICAgIGNvbnN0IHZhbHVlRGF0YSA9IG5ldyBJbnQ4QXJyYXkoMyk7CiAgICAgICAgICAgIHZhbHVlRGF0YVswXSA9IG1hcEluJDEodmFsdWUueCwgdGhpcy52YWx1ZVJhbmdlKTsKICAgICAgICAgICAgdmFsdWVEYXRhWzFdID0gbWFwSW4kMSh2YWx1ZS55LCB0aGlzLnZhbHVlUmFuZ2UpOwogICAgICAgICAgICB2YWx1ZURhdGFbMl0gPSBtYXBJbiQxKHZhbHVlLnosIHRoaXMudmFsdWVSYW5nZSk7CiAgICAgICAgICAgIHRoaXMuc2V0RmFjZVZlcnRleFZhbHVlX2FycmF5KGZhY2UsIGZhY2VWZXJ0ZXgsIHZhbHVlRGF0YSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBzZXRTcGxpdFZlcnRleFZhbHVlcyBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIHZlcnRleCAtIFRoZSB2ZXJ0ZXggdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGZhY2VHcm91cCAtIFRoZSBmYWNlR3JvdXAgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldFNwbGl0VmVydGV4VmFsdWVzKHZlcnRleCwgZmFjZUdyb3VwLCB2YWx1ZXMpIHsKICAgICAgICAgICAgc3VwZXIuc2V0U3BsaXRWZXJ0ZXhWYWx1ZXModmVydGV4LCBmYWNlR3JvdXAsIHZhbHVlcy5tYXAoKHYpID0+IG1hcEluJDEodiwgdGhpcy52YWx1ZVJhbmdlKSwgdGhpcy52YWx1ZVJhbmdlKSk7CiAgICAgICAgfQogICAgfQoKICAgIGNvbnN0IG1hcEluID0gKHZhbHVlKSA9PiB7CiAgICAgICAgcmV0dXJuIE1hdGhGdW5jdGlvbnMuZW5jb2RlMTZCaXRGbG9hdCh2YWx1ZSk7CiAgICB9OwogICAgY29uc3QgbWFwT3V0ID0gKHZhbHVlKSA9PiB7CiAgICAgICAgcmV0dXJuIE1hdGhGdW5jdGlvbnMuZGVjb2RlMTZCaXRGbG9hdCh2YWx1ZSk7CiAgICB9OwogICAgY2xhc3MgVmVjM2YxNlJlZiB7CiAgICAgICAgZGF0YTsKICAgICAgICBjb25zdHJ1Y3RvcihkYXRhKSB7CiAgICAgICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7CiAgICAgICAgfQogICAgICAgIGdldCB4KCkgewogICAgICAgICAgICByZXR1cm4gbWFwT3V0KHRoaXMuZGF0YVswXSk7CiAgICAgICAgfQogICAgICAgIHNldCB4KHZhbHVlKSB7CiAgICAgICAgICAgIHRoaXMuZGF0YVswXSA9IG1hcEluKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgZ2V0IHkoKSB7CiAgICAgICAgICAgIHJldHVybiBtYXBPdXQodGhpcy5kYXRhWzFdKTsKICAgICAgICB9CiAgICAgICAgc2V0IHkodmFsdWUpIHsKICAgICAgICAgICAgdGhpcy5kYXRhWzFdID0gbWFwSW4odmFsdWUpOwogICAgICAgIH0KICAgICAgICBnZXQgeigpIHsKICAgICAgICAgICAgcmV0dXJuIG1hcE91dCh0aGlzLmRhdGFbMl0pOwogICAgICAgIH0KICAgICAgICBzZXQgeih2YWx1ZSkgewogICAgICAgICAgICB0aGlzLmRhdGFbMl0gPSBtYXBJbih2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHNldCh4LCB5LCB6KSB7CiAgICAgICAgICAgIHRoaXMuZGF0YVswXSA9IG1hcEluKHgpOwogICAgICAgICAgICB0aGlzLmRhdGFbMV0gPSBtYXBJbih5KTsKICAgICAgICAgICAgdGhpcy5kYXRhWzJdID0gbWFwSW4oeik7CiAgICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiBDbGFzcyByZXByZXNlbnRpbmcgYW4gYXR0cmlidXRlLgogICAgICovCiAgICBjbGFzcyBWZWMzZjE2QXR0cmlidXRlIGV4dGVuZHMgVmVjM0F0dHJpYnV0ZSB7CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlIGEgVmVjM2Y4QXR0cmlidXRlLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgICAgICBzdXBlcignVmVjM2YxNicpOwogICAgICAgIH0KICAgICAgICBpbml0KCkgewogICAgICAgICAgICB0aGlzLmRhdGEgPSBuZXcgVWludDE2QXJyYXkoMCk7CiAgICAgICAgICAgIHRoaXMuaW5pdFJhbmdlKDApOwogICAgICAgIH0KICAgICAgICBpbml0UmFuZ2Uoc3RhcnQpIHsKICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgdmFsdWVzIHRvIGludmFsaWQgdmFsdWVzLgogICAgICAgICAgICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCB0aGlzLmRhdGEubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMuZGF0YVtpXSA9IG1hcEluKE51bWJlci5OYU4pOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlzSW5pdGlhbGl6ZWQoYSkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGEubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIGlmIChOdW1iZXIuaXNGaW5pdGUobWFwT3V0KGFbaV0pKSkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYSBjb3B5IG9mIHRoZSBWZWMzIHZhbHVlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdmFsdWUuCiAgICAgICAgICogQHJldHVybiBWZWMzIC0gVGhlIHZhbHVlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICovCiAgICAgICAgZ2V0VmFsdWUoaW5kZXgpIHsKICAgICAgICAgICAgaWYgKGluZGV4ID49IHRoaXMuZGF0YS5sZW5ndGggLyB0aGlzLnN0cmlkZSkKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB2ZXJ0ZXggaW5kZXg6JyArIGluZGV4ICsgJy4gTnVtIFZlcnRpY2VzOicgKyB0aGlzLmRhdGEubGVuZ3RoIC8gMyk7CiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IGluZGV4ICogdGhpcy5zdHJpZGU7CiAgICAgICAgICAgIGNvbnN0IHZhbHVlRGF0YSA9IHRoaXMuZGF0YS5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIHRoaXMuc3RyaWRlKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMzKG1hcE91dCh2YWx1ZURhdGFbMF0pLCBtYXBPdXQodmFsdWVEYXRhWzFdKSwgbWFwT3V0KHZhbHVlRGF0YVsyXSkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIGEgY29weSBvZiB0aGUgVmVjMyB2YWx1ZSBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LgogICAgICAgICAqCiAgICAgICAgICogQGRlcHJlY2F0ZWQgLSBUaGlzIG1ldGhvZCB3aWxsIHNvb24gYmUgcmVtb3ZlZC4KICAgICAgICAgKiBAcmV0dXJuIFZlYzMgLSBUaGUgdmFsdWUgYXQgdGhlIHNwZWNpZmllZCBpbmRleC4KICAgICAgICAgKi8KICAgICAgICBnZXRWYWx1ZVJlZihpbmRleCkgewogICAgICAgICAgICBpZiAoaW5kZXggPj0gdGhpcy5kYXRhLmxlbmd0aCAvIHRoaXMuc3RyaWRlKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHZlcnRleCBpbmRleDonICsgaW5kZXggKyAnLiBOdW0gVmVydGljZXM6JyArIHRoaXMuZGF0YS5sZW5ndGggLyAzKTsKICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gaW5kZXggKiB0aGlzLnN0cmlkZTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMzZjE2UmVmKHRoaXMuZGF0YS5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIDMpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyBWZWMzIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdmFsdWUuCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHBhcmFtLgogICAgICAgICAqLwogICAgICAgIHNldFZhbHVlKGluZGV4LCB2YWx1ZSkgewogICAgICAgICAgICBpZiAoaW5kZXggPj0gdGhpcy5kYXRhLmxlbmd0aCAvIHRoaXMuc3RyaWRlKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHZlcnRleCBpbmRleDonICsgaW5kZXggKyAnLiBOdW0gVmVydGljZXM6JyArIHRoaXMuZGF0YS5sZW5ndGggLyAzKTsKICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gaW5kZXggKiB0aGlzLnN0cmlkZTsKICAgICAgICAgICAgY29uc3QgdmFsdWVEYXRhID0gdGhpcy5kYXRhLnN1YmFycmF5KG9mZnNldCwgb2Zmc2V0ICsgdGhpcy5zdHJpZGUpOwogICAgICAgICAgICB2YWx1ZURhdGFbMF0gPSBtYXBJbih2YWx1ZS54KTsKICAgICAgICAgICAgdmFsdWVEYXRhWzFdID0gbWFwSW4odmFsdWUueSk7CiAgICAgICAgICAgIHZhbHVlRGF0YVsyXSA9IG1hcEluKHZhbHVlLnopOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSB2YWx1ZSBvZiBhIGNvcm5lciB2ZXJ0ZXggb2YgYSBmYWNlLgogICAgICAgICAqID4gTm90ZTogJ1JlZicgbWVhbnMgdGhhdCB0aGUgdmFsdWUgY29udGFpbnMgYSByZWZlcmVuY2UgdG8gdGhlIGRhdGEgaW4gdGhlIGF0dHJpYnV0ZS4KICAgICAgICAgKiA+IFRoZSBjb21wb25lbnRzIG9mIHRoZSB2YWx1ZSBjYW4gYmUgY2hhbmdlZCBjYXVzaW5nIHRoZSBhdHRyaWJ1dGVzIGRhdGEgaXMgY2hhbmdlZC4KICAgICAgICAgKiA+IE5vIG5lZWQgdG8gY2FsbCAnc2V0RmFjZVZlcnRleFZhbHVlJy4KICAgICAgICAgKiBAcGFyYW0gZmFjZSAtIFRoZSBmYWNlIGluZGV4LgogICAgICAgICAqIEBwYXJhbSBmYWNlVmVydGV4IC0gVGhlIGluZGV4IG9mIHZlcnRleCB3aXRoaW4gdGhlIGZhY2UuIFswLi4uIG51bSBmYWNlIHZlcnRpY2VzXQogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldEZhY2VWZXJ0ZXhWYWx1ZShmYWNlLCBmYWNlVmVydGV4KSB7CiAgICAgICAgICAgIGNvbnN0IGFycmF5ID0gdGhpcy5nZXRGYWNlVmVydGV4VmFsdWVfYXJyYXkoZmFjZSwgZmFjZVZlcnRleCk7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyhtYXBPdXQoYXJyYXlbMF0pLCBtYXBPdXQoYXJyYXlbMV0pLCBtYXBPdXQoYXJyYXlbMl0pKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB0aGUgdmFsdWUgb2YgYSBjb3JuZXIgdmVydGV4IG9mIGEgZmFjZS4KICAgICAgICAgKiBAcGFyYW0gZmFjZSAtIFRoZSBmYWNlIGluZGV4LgogICAgICAgICAqIEBwYXJhbSBmYWNlVmVydGV4IC0gVGhlIGluZGV4IG9mIHZlcnRleCB3aXRoaW4gdGhlIGZhY2UuIFswLi4uIG51bSBmYWNlIHZlcnRpY2VzXQogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRGYWNlVmVydGV4VmFsdWUoZmFjZSwgZmFjZVZlcnRleCwgdmFsdWUpIHsKICAgICAgICAgICAgY29uc3QgdmFsdWVEYXRhID0gbmV3IFVpbnQxNkFycmF5KDMpOwogICAgICAgICAgICB2YWx1ZURhdGFbMF0gPSBtYXBJbih2YWx1ZS54KTsKICAgICAgICAgICAgdmFsdWVEYXRhWzFdID0gbWFwSW4odmFsdWUueSk7CiAgICAgICAgICAgIHZhbHVlRGF0YVsyXSA9IG1hcEluKHZhbHVlLnopOwogICAgICAgICAgICB0aGlzLnNldEZhY2VWZXJ0ZXhWYWx1ZV9hcnJheShmYWNlLCBmYWNlVmVydGV4LCB2YWx1ZURhdGEpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgc2V0U3BsaXRWZXJ0ZXhWYWx1ZXMgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSB2ZXJ0ZXggLSBUaGUgdmVydGV4IHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBmYWNlR3JvdXAgLSBUaGUgZmFjZUdyb3VwIHZhbHVlLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRTcGxpdFZlcnRleFZhbHVlcyh2ZXJ0ZXgsIGZhY2VHcm91cCwgdmFsdWVzKSB7CiAgICAgICAgICAgIHN1cGVyLnNldFNwbGl0VmVydGV4VmFsdWVzKHZlcnRleCwgZmFjZUdyb3VwLCB2YWx1ZXMubWFwKCh2KSA9PiBtYXBJbih2KSkpOwogICAgICAgIH0KICAgIH0KCiAgICAvKioKICAgICAqIENsYXNzIHJlcHJlc2VudGluZyBhbiBhdHRyaWJ1dGUuCiAgICAgKi8KICAgIGNsYXNzIENvbG9yQXR0cmlidXRlIGV4dGVuZHMgQXR0cmlidXRlIHsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgYSBDb2xvckF0dHJpYnV0ZS4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICAgICAgc3VwZXIoJ0NvbG9yJywgNCk7CiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplZCA9IGZhbHNlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIGEgY29weSBvZiB0aGUgQ29sb3IgdmFsdWUgYXQgdGhlIHNwZWNpZmllZCBpbmRleC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIENvbG9yIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRWYWx1ZShpbmRleCkgewogICAgICAgICAgICBpZiAoaW5kZXggPj0gdGhpcy5kYXRhLmxlbmd0aCAvIHRoaXMuc3RyaWRlKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHZlcnRleCBpbmRleDonICsgaW5kZXggKyAnLiBOdW0gVmVydGljZXM6JyArIHRoaXMuZGF0YS5sZW5ndGggLyAzKTsKICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gaW5kZXggKiB0aGlzLnN0cmlkZTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBDb2xvcih0aGlzLmRhdGFbb2Zmc2V0ICsgMF0sIHRoaXMuZGF0YVtvZmZzZXQgKyAxXSwgdGhpcy5kYXRhW29mZnNldCArIDJdLCB0aGlzLmRhdGFbb2Zmc2V0ICsgM10pOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIENvbG9yIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdmFsdWUuCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHBhcmFtLgogICAgICAgICAqLwogICAgICAgIHNldFZhbHVlKGluZGV4LCB2YWx1ZSkgewogICAgICAgICAgICB0aGlzLnNldFZhbHVlcyhpbmRleCwgdmFsdWUuYXNBcnJheSgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgdmFsdWUgb2YgYSBjb3JuZXIgdmVydGV4IG9mIGEgZmFjZS4KICAgICAgICAgKiA+IE5vdGU6ICdSZWYnIG1lYW5zIHRoYXQgdGhlIHZhbHVlIGNvbnRhaW5zIGEgcmVmZXJlbmNlIHRvIHRoZSBkYXRhIGluIHRoZSBhdHRyaWJ1dGUuCiAgICAgICAgICogPiBUaGUgY29tcG9uZW50cyBvZiB0aGUgdmFsdWUgY2FuIGJlIGNoYW5nZWQgY2F1c2luZyB0aGUgYXR0cmlidXRlcyBkYXRhIGlzIGNoYW5nZWQuCiAgICAgICAgICogPiBObyBuZWVkIHRvIGNhbGwgJ3NldEZhY2VWZXJ0ZXhWYWx1ZScuCiAgICAgICAgICogQHBhcmFtIGZhY2UgLSBUaGUgZmFjZSBpbmRleC4KICAgICAgICAgKiBAcGFyYW0gZmFjZVZlcnRleCAtIFRoZSBpbmRleCBvZiB2ZXJ0ZXggd2l0aGluIHRoZSBmYWNlLiBbMC4uLiBudW0gZmFjZSB2ZXJ0aWNlc10KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRGYWNlVmVydGV4VmFsdWUoZmFjZSwgZmFjZVZlcnRleCkgewogICAgICAgICAgICBjb25zdCBhcnJheSA9IHRoaXMuZ2V0RmFjZVZlcnRleFZhbHVlX2FycmF5KGZhY2UsIGZhY2VWZXJ0ZXgpOwogICAgICAgICAgICByZXR1cm4gbmV3IENvbG9yKGFycmF5WzBdLCBhcnJheVsxXSwgYXJyYXlbMl0sIGFycmF5WzNdKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB0aGUgdmFsdWUgb2YgYSBjb3JuZXIgdmVydGV4IG9mIGEgZmFjZS4KICAgICAgICAgKiBAcGFyYW0gZmFjZSAtIFRoZSBmYWNlIGluZGV4LgogICAgICAgICAqIEBwYXJhbSBmYWNlVmVydGV4IC0gVGhlIGluZGV4IG9mIHZlcnRleCB3aXRoaW4gdGhlIGZhY2UuIFswLi4uIG51bSBmYWNlIHZlcnRpY2VzXQogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRGYWNlVmVydGV4VmFsdWUoZmFjZSwgZmFjZVZlcnRleCwgdmFsdWUpIHsKICAgICAgICAgICAgdGhpcy5zZXRGYWNlVmVydGV4VmFsdWVfYXJyYXkoZmFjZSwgZmFjZVZlcnRleCwgRmxvYXQzMkFycmF5LmZyb20odmFsdWUuYXNBcnJheSgpKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBzZXRTcGxpdFZlcnRleFZhbHVlIG1ldGhvZC4KICAgICAgICAgKiBAcGFyYW0gdmVydGV4IC0gVGhlIHZlcnRleCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gZmFjZSAtIFRoZSBmYWNlIGluZGV4LgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRTcGxpdFZlcnRleFZhbHVlKHZlcnRleCwgZmFjZSwgdmFsdWUpIHsKICAgICAgICAgICAgdGhpcy5zZXRTcGxpdFZlcnRleFZhbHVlX2FycmF5KHZlcnRleCwgZmFjZSwgRmxvYXQzMkFycmF5LmZyb20odmFsdWUuYXNBcnJheSgpKSk7CiAgICAgICAgfQogICAgICAgIG1lcmdlKG90aGVyLCB4Zm8gPSBuZXcgWGZvKCkpIHsKICAgICAgICAgICAgY29uc3QgcHJldk51bVZhbHVlcyA9IHRoaXMuZ2V0Q291bnQoKTsKICAgICAgICAgICAgY29uc3QgYWRkZWRWYWx1ZXMgPSBvdGhlci5nZXRDb3VudCgpOwogICAgICAgICAgICB0aGlzLnNldENvdW50KHByZXZOdW1WYWx1ZXMgKyBhZGRlZFZhbHVlcyk7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWRkZWRWYWx1ZXM7IGkrKykgewogICAgICAgICAgICAgICAgdGhpcy5zZXRWYWx1ZShwcmV2TnVtVmFsdWVzICsgaSwgb3RoZXIuZ2V0VmFsdWUoaSkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuc3BsaXRWYWx1ZXMgPSBbLi4udGhpcy5zcGxpdFZhbHVlcywgLi4ub3RoZXIuc3BsaXRWYWx1ZXNdOwogICAgICAgIH0KICAgIH0KICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdDb2xvckF0dHJpYnV0ZScsIENvbG9yQXR0cmlidXRlKTsKCiAgICB2YXIgT3BlcmF0b3JPdXRwdXRNb2RlOwogICAgKGZ1bmN0aW9uIChPcGVyYXRvck91dHB1dE1vZGUpIHsKICAgICAgICBPcGVyYXRvck91dHB1dE1vZGVbT3BlcmF0b3JPdXRwdXRNb2RlWyJPUF9XUklURSJdID0gMF0gPSAiT1BfV1JJVEUiOwogICAgICAgIE9wZXJhdG9yT3V0cHV0TW9kZVtPcGVyYXRvck91dHB1dE1vZGVbIk9QX1JFQURfV1JJVEUiXSA9IDFdID0gIk9QX1JFQURfV1JJVEUiOwogICAgfSkoT3BlcmF0b3JPdXRwdXRNb2RlIHx8IChPcGVyYXRvck91dHB1dE1vZGUgPSB7fSkpOwoKICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIHJlYWN0aXZlIHR5cGUgb2YgYXR0cmlidXRlIHRoYXQgY2FuIGJlIG93bmVkIGJ5IGEgYFBhcmFtZXRlck93bmVyYCBjbGFzcy4KICAgICAqCiAgICAgKiAqKkV2ZW50cyoqCiAgICAgKiAqICoqbmFtZUNoYW5nZWQ6KiogVHJpZ2dlcmVkIHdoZW4gdGhlIG5hbWUgb2YgdGhlIHBhcmFtZXRlciBjaGFuZ2VzLgogICAgICogKiAqKnZhbHVlQ2hhbmdlZDoqKiBUcmlnZ2VyZWQgd2hlbiB0aGUgdmFsdWUgb2YgdGhlIHBhcmFtZXRlciBjaGFuZ2VzLgogICAgICovCiAgICBjbGFzcyBQYXJhbWV0ZXIgZXh0ZW5kcyBCYXNlSXRlbSB7CiAgICAgICAgI3ZhbHVlOwogICAgICAgIGRpcnR5ID0gZmFsc2U7CiAgICAgICAgYm91bmRJbnB1dHMgPSBbXTsKICAgICAgICBib3VuZE91dHB1dHMgPSBbXTsKICAgICAgICBjbGVhbmluZyA9IGZhbHNlOwogICAgICAgIGRpcnR5T3BJbmRleCA9IDA7CiAgICAgICAgZmlyc3RPUF9XUklURSA9IDA7CiAgICAgICAgZGF0YVR5cGU7CiAgICAgICAgLyoqCiAgICAgICAgICogV2hlbiBpbml0aWFsaXppbmcgYSBuZXcgcGFyYW1ldGVyLCB0aGUgcGFzc2VkIGluIHZhbHVlIGNvdWxkIGJlIGFueXRoaW5nLgogICAgICAgICAqIElmIGl0IGlzIGEgbmV3IHR5cGUgb2YgdmFsdWUsIGp1c3QgZW5zdXJlIHlvdSByZWdpc3RlciBpdCBpbiB0aGUgYFJlZ2lzdHJ5YC4KICAgICAgICAgKgogICAgICAgICAqIEhvdyB0byB1c2UgaXQ6CiAgICAgICAgICoKICAgICAgICAgKiBgYGBqYXZhc2NyaXB0CiAgICAgICAgICogIC8vIENyZWF0aW5nIGEgcGFyYW1ldGVyIG9iamVjdAogICAgICAgICAqICBjb25zdCBwYXJhbSA9IG5ldyBQYXJhbWV0ZXIoJ1RpdGxlJywgJ0F3ZXNvbWUgUGFyYW1ldGVyIFZhbHVlJywgJ1N0cmluZycpCiAgICAgICAgICoKICAgICAgICAgKiAgIC8vIENhcHR1cmluZyBldmVudHMKICAgICAgICAgKiAgcGFyYW0ub24oJ3ZhbHVlQ2hhbmdlZCcsICguLi5wYXJhbXMpID0+IGNvbnNvbGUubG9nKCdWYWx1ZSBjaGFuZ2VkIScpKQogICAgICAgICAqCiAgICAgICAgICogIC8vIENoYW5naW5nIHBhcmFtZXRlcidzIHZhbHVlIHdpbGwgY2F1c2UgYHZhbHVlQ2hhbmdlZGAgZXZlbnQgdG8gdHJpZ2dlci4KICAgICAgICAgKiAgcGFyYW0uc2V0VmFsdWUoJ0EgTmV3IEF3ZXNvbWUgUGFyYW1ldGVyIFZhbHVlJykKICAgICAgICAgKiAgLy8gQXMgcmVzdWx0IHRoZSBjb25zb2xlIGxvZyBjb2RlIHdpbGwgZXhlY3V0ZTogVmFsdWUgQ2hhbmdlZCEKICAgICAgICAgKiBgYGAKICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHBhcmFtZXRlci4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci4KICAgICAgICAgKiBAcGFyYW0gZGF0YVR5cGUgLSBUaGUgZGF0YSB0eXBlIG9mIHRoZSBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IobmFtZSA9ICcnLCB2YWx1ZSwgZGF0YVR5cGUpIHsKICAgICAgICAgICAgc3VwZXIobmFtZSk7CiAgICAgICAgICAgIHRoaXMuI3ZhbHVlID0gdmFsdWU7CiAgICAgICAgICAgIHRoaXMuZGF0YVR5cGUgPSBkYXRhVHlwZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBwYXJhbWV0ZXIncyBkYXRhIHR5cGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXREYXRhVHlwZSgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0YVR5cGU7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIE9wZXJhdG9yIGJpbmRpbmdzCiAgICAgICAgLyoqCiAgICAgICAgICogV2hlbiBhbiBPcGVyYXRvciBpcyByZWFkaW5nIGZyb20gYSBwYXJhbWV0ZXIsIGl0IG11c3QgYmUgZGlydGllZCB3aGVuIHRoZSBwYXJhbWV0ZXIgdmFsdWUKICAgICAgICAgKiBjaGFuZ2VzLiBUaGUgUGFyYW1ldGVyIG1haW50YWlucyBhIGxpc3Qgb2YgYm91bmQgaW5wdXRzIGFuZCB3aWxsIHByb3BhZ2F0ZSBkaXJ0eSB0bwogICAgICAgICAqIHRoZW0gZXhwbGljaXRseS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBvcGVyYXRvcklucHV0IC0gVGhlIG91dHB1dCB0aGF0IHdlIGFyZSB1bmJpbmRpbmcgZnJvbSB0aGUgUGFyYW1ldGVyCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gVGhlIGluZGV4KG9wdGlvbmFsKSB0aGF0IHRoZSBvdXRwdXQgaXMgYmVpbmcgYm91bmQgYXQuCiAgICAgICAgICogQHJldHVybiAtIFRoZSBpbmRleCBvZiB0aGUgYm91bmQgb3V0cHV0LgogICAgICAgICAqLwogICAgICAgIGJpbmRPcGVyYXRvcklucHV0KG9wZXJhdG9ySW5wdXQpIHsKICAgICAgICAgICAgdGhpcy5ib3VuZElucHV0cy5wdXNoKG9wZXJhdG9ySW5wdXQpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBXaGVuIGFuIG9wZXJhdG9yIGlzIGJlaW5nIHJlbW92ZWQgZnJvbSByZWFkaW5nIGZyb20gYSBQYXJhbWV0ZXIsIHRoZSBJbnB1dCBpcyByZW1vdmVkCiAgICAgICAgICogVGhpcyBtZWFucyB0aGUgb3BlcmF0b3Igd2lsbCBubyBsb25nZXIgcmVjZWl2ZSB1cGRhdGVzIHdoZW4gdGhlIG9wZXJhdG9yIGNoYW5nZXMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gb3BlcmF0b3JJbnB1dCAtIFRoZSBvdXRwdXQgdGhhdCB3ZSBhcmUgdW5iaW5kaW5nIGZyb20gdGhlIFBhcmFtZXRlcgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHVuYmluZE9wZXJhdG9ySW5wdXQob3BlcmF0b3JJbnB1dCkgewogICAgICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMuYm91bmRJbnB1dHMuaW5kZXhPZihvcGVyYXRvcklucHV0KTsKICAgICAgICAgICAgdGhpcy5ib3VuZElucHV0cy5zcGxpY2UoaW5kZXgsIDEpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBXaGVuIGFuIE9wZXJhdG9yIHdyaXRlcyB0byBhIHBhcmFtZXRlciwgaXQgYmluZHMgaXRzIG91dHB1dHMgdG8gdGhlIHBhcmFtZXRlciBhdCBhIGdpdmVuCiAgICAgICAgICogaW5kZXguIFRoZW4gd2hlbiB0aGUgb3BlcmF0b3IgaXMgZGlydGllZCBieSBvbmUgb2YgaXRzIGlucHV0cywgaXQgZXhwbGljaXRseSBkaXJ0aWVzCiAgICAgICAgICogdGhlIG91dHB1dCBwYXJhbWV0ZXJzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG9wZXJhdG9yT3V0cHV0IC0gVGhlIG91dHB1dCB0aGF0IHdlIGFyZSB1bmJpbmRpbmcgZnJvbSB0aGUgUGFyYW1ldGVyCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gVGhlIGluZGV4KG9wdGlvbmFsKSB0aGF0IHRoZSBvdXRwdXQgaXMgYmVpbmcgYm91bmQgYXQuCiAgICAgICAgICogQHJldHVybiAtIFRoZSBpbmRleCBvZiB0aGUgYm91bmQgb3V0cHV0LgogICAgICAgICAqLwogICAgICAgIGJpbmRPcGVyYXRvck91dHB1dChvcGVyYXRvck91dHB1dCwgaW5kZXggPSAtMSkgewogICAgICAgICAgICBpZiAoaW5kZXggPT0gLTEpCiAgICAgICAgICAgICAgICBpbmRleCA9IHRoaXMuYm91bmRPdXRwdXRzLmxlbmd0aDsKICAgICAgICAgICAgdGhpcy5ib3VuZE91dHB1dHMuc3BsaWNlKGluZGV4LCAwLCBvcGVyYXRvck91dHB1dCk7CiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgcmVtYWluaW5nIGJpbmRpbmcgaW5kaWNlcwogICAgICAgICAgICBmb3IgKGxldCBpID0gaW5kZXg7IGkgPCB0aGlzLmJvdW5kT3V0cHV0cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgdGhpcy5ib3VuZE91dHB1dHNbaV0uc2V0UGFyYW1CaW5kSW5kZXgoaSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gSWYgd2Ugd2VyZW4ndCBhbHJlYWR5IGRpcnR5LCBtYWtlIHN1cmUgdG8gZW1pdCBhICd2YWx1ZUNoYW5nZWQnIGFueXdheS4KICAgICAgICAgICAgdGhpcy5fX2ZpbmRGaXJzdE9QX1dSSVRFKCk7CiAgICAgICAgICAgIC8vIFRoaXMgZW5zdXJlcyB0aGF0IHRoZSBvcGVyYXRvciBzdGFjayBpcyBjb25zaWRlcmVkICdjbGVhbicKICAgICAgICAgICAgLy8gYW5kIHRoZW4gd2UgY2FsbCBzZXQgZGlydHkgdG8gZm9yY2UgaXQgdG8gYmVjb21lIGRpcnR5IGZyb20gdGhlIGluc2VydGlvbiBwb2ludCBkb3duLgogICAgICAgICAgICAvLyBXaXRob3V0IHRoaXMgbGluZSwgdGhlIG9wZXJhdG9yIGlzIGNvbnNpZGVyZWQgYWxyZWFkeSAnZGlydHknLCBhbmQgc28gd29uJ3QgcHJvcGFnYXRlLgogICAgICAgICAgICB0aGlzLmRpcnR5T3BJbmRleCA9IHRoaXMuYm91bmRPdXRwdXRzLmxlbmd0aDsKICAgICAgICAgICAgdGhpcy5zZXREaXJ0eShpbmRleCk7CiAgICAgICAgICAgIHJldHVybiBpbmRleDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogV2hlbiBhbiBvcGVyYXRvciBpcyB1bmJpbmRpbmcgZnJvbSBhIHBhcmFtZXRlciwgaXQgcmVtb3ZlcyBpdHMgc2VsZiBmcm9tIHRoZSBsaXN0IG1haW50YWluZWQKICAgICAgICAgKiBieSB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG9wZXJhdG9yT3V0cHV0IC0gVGhlIG91dHB1dCB0aGF0IHdlIGFyZSB1bmJpbmRpbmcgZnJvbSB0aGUgUGFyYW1ldGVyCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgdW5iaW5kT3BlcmF0b3JPdXRwdXQob3BlcmF0b3JPdXRwdXQpIHsKICAgICAgICAgICAgY29uc3QgaW5kZXggPSBvcGVyYXRvck91dHB1dC5nZXRQYXJhbUJpbmRJbmRleCgpOwogICAgICAgICAgICB0aGlzLmJvdW5kT3V0cHV0cy5zcGxpY2UoaW5kZXgsIDEpOwogICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHJlbWFpbmluZyBiaW5kaW5nIGluZGljZXMKICAgICAgICAgICAgZm9yIChsZXQgaSA9IGluZGV4OyBpIDwgdGhpcy5ib3VuZE91dHB1dHMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMuYm91bmRPdXRwdXRzW2ldLnNldFBhcmFtQmluZEluZGV4KGkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuX19maW5kRmlyc3RPUF9XUklURSgpOwogICAgICAgICAgICB0aGlzLmRpcnR5T3BJbmRleCA9IHRoaXMuYm91bmRPdXRwdXRzLmxlbmd0aDsKICAgICAgICAgICAgdGhpcy5zZXREaXJ0eShNYXRoLm1heCgwLCBpbmRleCAtIDEpKTsKICAgICAgICAgICAgcmV0dXJuIGluZGV4OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBGaW5kIHRoZSBmaXJzdCBvcGVyYXRvciBpbiBvdXIgc3RhY2sgd2hpY2ggd3JpdGVzIHVzaW5nIGFuIE9QX1dSSVRFIGNvbm5lY3Rpb24uCiAgICAgICAgICogQWxsIG9wZXJhdG9ycyBiZWZvcmUgdGhpcyBvcCBjYW4gYmUgaWdub3JlZCBkdXJpbmcgZGlydHkgcHJvcGFnYXRpb24uCiAgICAgICAgICogQHByaXZhdGUKICAgICAgICAgKi8KICAgICAgICBfX2ZpbmRGaXJzdE9QX1dSSVRFKCkgewogICAgICAgICAgICB0aGlzLmZpcnN0T1BfV1JJVEUgPSB0aGlzLmJvdW5kT3V0cHV0cy5sZW5ndGg7CiAgICAgICAgICAgIGlmICh0aGlzLmJvdW5kT3V0cHV0cy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgICBmb3IgKHRoaXMuZmlyc3RPUF9XUklURS0tOyB0aGlzLmZpcnN0T1BfV1JJVEUgPiAwOyB0aGlzLmZpcnN0T1BfV1JJVEUtLSkgewogICAgICAgICAgICAgICAgICAgIC8vIEZpbmQgdGhlIGZpcnN0IE9QX1dSSVRFIGJpbmRpbmcuIChOb3RlOiB3ZSBjb3VsZCBjYWNoZSB0aGlzKQogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmJvdW5kT3V0cHV0c1t0aGlzLmZpcnN0T1BfV1JJVEVdLmdldE1vZGUoKSA9PSBPcGVyYXRvck91dHB1dE1vZGUuT1BfV1JJVEUpCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlzRHJpdmVuQnlPcGVyYXRvcigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmlyc3RPUF9XUklURSA9PSAwICYmIHRoaXMuYm91bmRPdXRwdXRzLmxlbmd0aCA+IDA7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIERpcnRpZXMgdGhpcyBQYXJhbWV0ZXIgc28gc3Vic2VxdWVudCBjYWxscyB0byBgZ2V0VmFsdWVgIHdpbGwgY2F1c2UgYW4gZXZhbHVhdGlvbiBvZiBpdHMgYm91bmQgb3BlcmF0b3JzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gSW5kZXggb2YgdGhlIG9wZXJhdG9yCiAgICAgICAgICogQHJldHVybiAtIGB0cnVlYCBpZiB0aGUgUGFyYW1ldGVyIHdhcyBtYWRlIGRpcnR5LCBlbHNlIGBmYWxzZWAgaWYgaXQgd2FzIGFscmVhZHkgZGlydHkuCiAgICAgICAgICovCiAgICAgICAgc2V0RGlydHkoaW5kZXgpIHsKICAgICAgICAgICAgLy8gRGV0ZXJtaW5lIHRoZSBmaXJzdCBvcGVyYXRvciBpbiB0aGUgc3RhY2sgdGhhdCBtdXN0IGV2YWx1YXRlIHRvIGNsZWFuIHRoZSBwYXJhbWV0ZXIuCiAgICAgICAgICAgIC8vIE5vdGU6IGlmIGEgUkVBRF9XUklURSBvcCBpcyBiZWNvbWluZyBkaXJ0eSwgdGhlbiB3ZSBkaXJ0eSBiYWNrIHVwIHRvIHRoYXQgb3AuCiAgICAgICAgICAgIGlmIChpbmRleCA8IHRoaXMuZGlydHlPcEluZGV4KSB7CiAgICAgICAgICAgICAgICAvLyBJZiB3ZSBtdXN0IGRpcnR5IGFsbCBvcGVyYXRvcnMgaW4gdGhlIHN0YWNrIGZyb20gdGhlIGxhc3QgT1BfV1JJVEUgdG8gdGhlIGVuZC4KICAgICAgICAgICAgICAgIC8vIE5vdGU6IElmIGEgc2V0RGlydHkgY2FsbCBjb21lcyBmcm9tIGFuIG9wIHRoYXQgcHJlY2VkZXMgYW4gT1BfV1JJVEUgb3BlcmF0b3IsIHdlCiAgICAgICAgICAgICAgICAvLyBjYW4gc2FmZWx5IGRpc2NhcmQgaXQsIGFzIGl0cyBvdXRwdXQgd2lsbCBoYXZlIG5vIGVmZmVjdCBvbiB0aGUgdmFsdWUgb2YgdGhpcyBwYXJhbWV0ZXIuCiAgICAgICAgICAgICAgICBsZXQgbmV3RGlydHlJbmRleCA9IHRoaXMuZmlyc3RPUF9XUklURTsKICAgICAgICAgICAgICAgIGlmIChuZXdEaXJ0eUluZGV4IDw9IGluZGV4KSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXJ0eU9wSW5kZXggPSBuZXdEaXJ0eUluZGV4OwogICAgICAgICAgICAgICAgICAgIGZvciAobmV3RGlydHlJbmRleCsrOyBuZXdEaXJ0eUluZGV4IDwgdGhpcy5ib3VuZE91dHB1dHMubGVuZ3RoOyBuZXdEaXJ0eUluZGV4KyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGlydHkgYWxsIHRoZSBvdGhlciBib3VuZCBvcHMgZnJvbSB0aGUgT1BfV1JJVEUgdG8gdGhlIHRvcCBvZiB0aGUgc3RhY2suCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuZXdEaXJ0eUluZGV4ICE9IGluZGV4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHdpbGwgY2F1c2UgdGhlIG90aGVyIG91dHB1dHMgb2YgdGhlIG9wZXJhdG9yIHRvIGJlY29tZSBkaXJ0eS4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYm91bmRPdXRwdXRzW25ld0RpcnR5SW5kZXhdLmdldE9wZXJhdG9yKCkuc2V0RGlydHkoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuYm91bmRJbnB1dHMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5ib3VuZElucHV0c1tpXS5zZXREaXJ0eSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXQoJ3ZhbHVlQ2hhbmdlZCcpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0cnVlIGlmIHRoaXMgcGFyYW1ldGVyIGlzIGN1cnJlbnRseSBkaXJ0eSBhbmQgd2lsbCBldmFsdWF0ZSBpdHMgYm91bmQKICAgICAgICAgKiBvcGVyYXRvcnMgaWYgaXRzIHZhbHVlIGlzIHJlcXVlc3RlZCBieSBhIGNhbGwgdG8gZ2V0VmFsdWUuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIGJvb2xlYW4uCiAgICAgICAgICovCiAgICAgICAgaXNEaXJ0eSgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGlydHlPcEluZGV4IDwgdGhpcy5ib3VuZE91dHB1dHMubGVuZ3RoOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgZmlyc3QgJ2RpcnR5JyBiaW5kaW5nIGluIHRoZSBzdGFjay4gVGhpcyB3aWxsIGJlIHRoZSBpbmRleCBvZiB0aGUKICAgICAgICAgKiBmaXJzdCBvcGVyYXRvciB0aGF0IHdpbGwgZXZhbHVhdGUgd2hlbiB0aGUgcGFyYW1ldGVyIG5lZWRzIHRvIGJlIGNsZWFuZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIGluZGV4IG9mIHRoZSBkaXJ0eSBiaW5kaW5nIGluIHRoZSBiaW5kaW5nIHN0YWNrLgogICAgICAgICAqLwogICAgICAgIGdldERpcnR5QmluZGluZ0luZGV4KCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5kaXJ0eU9wSW5kZXg7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBzZXRDbGVhbkZyb21PcCBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGNvbXB1dGVkIHZhbHVlIHRvIGJlIHN0b3JlZCBpbiB0aGUgUGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCBvZiB0aGUgYm91bmQgT3BlcmF0b3JPdXRwdXQuCiAgICAgICAgICovCiAgICAgICAgc2V0Q2xlYW5Gcm9tT3AodmFsdWUsIGluZGV4KSB7CiAgICAgICAgICAgIGlmIChpbmRleCAhPSB0aGlzLmRpcnR5T3BJbmRleCkgewogICAgICAgICAgICAgICAgaWYgKGluZGV4IDwgdGhpcy5kaXJ0eU9wSW5kZXgpIHsKICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGNhbiBoYXBwZW4gd2hlbiBhbiBvcGVyYXRvciBpbiB0aGUgZm9sbG93aW5nIGNhc2UuCiAgICAgICAgICAgICAgICAgICAgLy8gUGFyYW1BIFtPcEMsIE9wQiwgT3BBXQogICAgICAgICAgICAgICAgICAgIC8vIFBhcmFtQiBbT3BDLCBPcEFdCiAgICAgICAgICAgICAgICAgICAgLy8gV2hlbiBPcEIgZGlydGllcyBQYXJhbUEsIGFuZCBpcyBldmFsdWF0ZWQsIFBhcmFtQiBpcyBjb25zaWRlcmVkIGNsZWFuIGJlY2F1c2UgT3BBIHdhcyBuZXZlciBkaXJ0aWVkCiAgICAgICAgICAgICAgICAgICAgLy8gV2Ugc2VlIHRoaXMgbWVzc2FnZSB3aGVuIHBhcmFtZXRlcnMgYXJlIGV2YWx1YXRlZCBhcyBzb29uIGFzIGEgY2hhbmdlIGlzIGRldGVjdGVkIGluc3RlYWQgb2YKICAgICAgICAgICAgICAgICAgICAvLyBpbiBiYXRjaGVzLiBOb3cgdGhhdCBhbGwgcmVuZGVyaW5nIGNvZGUgaXMgcHVsbGluZyBkYXRhIG9ubHkgZHVyaW5nIHRoZSByZW5kZXIgY3ljbGUsIHdlIGFyYQogICAgICAgICAgICAgICAgICAgIC8vIG5vdCBzZWVpbmcgaXQgYW55bW9yZS4gSG93ZXZlciwgbWF5YmUgd2l0aCBhIFVJIG9wZW4sIGl0IHdpbGwgc3RhcnQgZW1pdHRpbmcgdGhpcyB3YXJuaW5nLgogICAgICAgICAgICAgICAgICAgIC8vIE5vdGU6IHRoaXMgd291bGQgYmUgY2F1c2VkLCBpZiBhIFBhcmFtZXRlciBpcyBhbHJlYWR5IGNsZWFuZWQgYnkgYW4gT3BlcmF0b3IsIGFuZCB5ZXQgdGhlIE9wZXJhdG9yCiAgICAgICAgICAgICAgICAgICAgLy8gaXMgcmUtZXZhbHVhdGluZy4gSSBhbSBub3Qgc3VyZSBob3cgdGhpcyBjYW4gb2NjdXIuCiAgICAgICAgICAgICAgICAgICAgLy8gY29uc3Qgb3AgPSBvcGVyYXRvck91dHB1dC5nZXRPcGVyYXRvcigpCiAgICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coCiAgICAgICAgICAgICAgICAgICAgLy8gICBgT3BlcmF0b3I6OiAkewogICAgICAgICAgICAgICAgICAgIC8vICAgICBvcC5jb25zdHJ1Y3Rvci5uYW1lCiAgICAgICAgICAgICAgICAgICAgLy8gICB9IHdpdGggbmFtZTogJHtvcC5uYW1lfSBpcyBiZWluZyBjbGVhbmVkIGltbWVkaWF0ZWx5LCBpbnN0ZWFkIG9mIGxhemlseS5gCiAgICAgICAgICAgICAgICAgICAgLy8gKQogICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBQYXJhbWV0ZXIgaXMgY2xlYW5lZCB3aGVuIGl0IHdhcyBhbHJlYWR5IGNsZWFuIHRvIHRoYXQgcG9pbnQgaW4gdGhlIHN0YWNrOmAsIHRoaXMuZ2V0UGF0aCgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuYm91bmRPdXRwdXRzW2luZGV4XS5nZXRNb2RlKCkgIT0gT3BlcmF0b3JPdXRwdXRNb2RlLk9QX1dSSVRFKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gQSBwYXJhbWV0ZXIgY2FuIGJlY29tZSBkaXJ0eSAoc28gX19kaXJ0eU9wSW5kZXggPT0gMCksIGFuZCB0aGVuIGFub3RoZXIgb3BlcmF0b3IgYm91bmQgb24gdG9wLgogICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBuZXh0IG9wIGlzIGEgV1JJVEUgb3AsIHRoZW4gd2UgY2FuIGZhc3QgZm9yd2FyZCB0aGUgZGlydHkgaW5kZXguCiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGhpc0NsYXNzTmFtZSA9IHRoaXMuZ2V0Q2xhc3NOYW1lKCk7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3AgPSB0aGlzLmJvdW5kT3V0cHV0c1tpbmRleF0uZ2V0T3BlcmF0b3IoKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBvcENsYXNzTmFtZSA9IG9wLmNvbnN0cnVjdG9yLm5hbWU7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBQYXJhbWV0ZXI6ICR7dGhpc0NsYXNzTmFtZX0gd2l0aCBuYW1lOiAke3RoaXMuZ2V0TmFtZSgpfSBpcyBub3QgY2xlYW5pbmcgYWxsIG91dHB1dHMgZHVyaW5nIGV2YWx1YXRpb24gb2Ygb3A6ICR7b3BDbGFzc05hbWV9IHdpdGggbmFtZTogJHtvcC5uYW1lfWApOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuI3ZhbHVlID0gdmFsdWU7CiAgICAgICAgICAgIC8vIEFzIGVhY2ggb3BlcmF0b3Igd3JpdGVzIGl0cyB2YWx1ZSwgdGhlIGRpcnR5IHZhbHVlIGlzIGluY3JlbWVudGVkCiAgICAgICAgICAgIHRoaXMuZGlydHlPcEluZGV4ID0gaW5kZXggKyAxOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBEdXJpbmcgb3BlcmF0b3IgZXZhbHVhdGlvbiwgb3BlcmF0b3JzIGNhbiB1c2UgdGhpcyBtZXRob2QgdG8gcmV0cmlldmUgdGhlIGV4aXN0aW5nCiAgICAgICAgICogdmFsdWUgb2Ygb25lIG9mIHRoZWlyIG91dHB1dHMuCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gVGhlIGluZGV4IG9mIHRoZSBib3VuZCBPcGVyYXRvck91dHB1dCB0byBldmFsdWF0ZSB1cCB0by4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRWYWx1ZUZyb21PcChpbmRleCkgewogICAgICAgICAgICAvLyBOb3RlOiBkdXJpbmcgZXZhbHVhdGlvbiBvZiBhbiBPcGVyYXRvciB0aGF0IHdyaXRlcyB0byBtdWx0aXBsZSBvdXRwdXRzLAogICAgICAgICAgICAvLyBpdCBjYW4gd3JpdGUgdG8gYW4gb3V0cHV0IHdpdGggYW4gSU8gc2V0dGluZywgd2hpY2ggbWVhbnMgaXQgcmV0cmlldmVzCiAgICAgICAgICAgIC8vIHRoZSBwcmV2aW91cyB2YWx1ZSB3aGlsZSBjYWxjdWxhdGluZyB0aGUgbmV4dC4KICAgICAgICAgICAgaWYgKHRoaXMuZGlydHlPcEluZGV4IDwgaW5kZXgpIHsKICAgICAgICAgICAgICAgIHRoaXMuX2NsZWFuKGluZGV4KTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhpcy4jdmFsdWU7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENsZWFucyB0aGUgcGFyYW1ldGVyIHVwIHRwIHRoZSBpbmRleCBvZiB0aGUgc3BlY2lmaWVkIGluZGV4IG9mIHRoZSBib3VuZCBPcGVyYXRvck91dHB1dAogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gVGhlIGluZGV4IG9mIHRoZSBib3VuZCBPcGVyYXRvck91dHB1dCB0byBldmFsdWF0ZSB1cCB0by4KICAgICAgICAgKi8KICAgICAgICBfY2xlYW4oaW5kZXgpIHsKICAgICAgICAgICAgaWYgKHRoaXMuY2xlYW5pbmcpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ3ljbGUgZGV0ZWN0ZWQgd2hlbiBjbGVhbmluZzogJHt0aGlzLmdldFBhdGgoKX0uIE9wZXJhdG9ycyBuZWVkIHRvIGJlIHJlYm91bmQgdG8gZml4IGVycm9yc2ApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuY2xlYW5pbmcgPSB0cnVlOwogICAgICAgICAgICB3aGlsZSAodGhpcy5kaXJ0eU9wSW5kZXggPCBpbmRleCkgewogICAgICAgICAgICAgICAgY29uc3QgdG1wID0gdGhpcy5kaXJ0eU9wSW5kZXg7CiAgICAgICAgICAgICAgICBjb25zdCBvcGVyYXRvck91dHB1dCA9IHRoaXMuYm91bmRPdXRwdXRzW3RoaXMuZGlydHlPcEluZGV4XTsKICAgICAgICAgICAgICAgIC8vIFRoZSBvcCBjYW4gZ2V0IHRoZSBjdXJyZW50IHZhbHVlIGFuZCBtb2RpZnkgaXQgaW4gcGxhY2UKICAgICAgICAgICAgICAgIC8vIGFuZCBzZXQgdGhlIG91dHB1dCB0byBjbGVhbi4KICAgICAgICAgICAgICAgIG9wZXJhdG9yT3V0cHV0LmdldE9wZXJhdG9yKCkuZXZhbHVhdGUoKTsKICAgICAgICAgICAgICAgIGlmICh0bXAgPT0gdGhpcy5kaXJ0eU9wSW5kZXgpIHsKICAgICAgICAgICAgICAgICAgICAvLyBEdXJpbmcgaW5pdGlhbCBjb25maWd1cmF0aW9uIG9mIGFuIG9wZXJhdG9yLCBjbGVhbmluZyBvdXRwdXRzIG1pZ2h0IGJlIGRpc2FibGVkLgogICAgICAgICAgICAgICAgICAgIGNvbnN0IG9wID0gdGhpcy5ib3VuZE91dHB1dHNbdGhpcy5kaXJ0eU9wSW5kZXhdLmdldE9wZXJhdG9yKCk7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3BDbGFzc05hbWUgPSBvcC5jb25zdHJ1Y3Rvci5uYW1lOwogICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgT3BlcmF0b3I6ICR7b3BDbGFzc05hbWV9IHdpdGggbmFtZTogJHtvcC5uYW1lfSBpcyBub3QgY2xlYW5pbmcgaXRzIG91dHB1dHMgZHVyaW5nIGV2YWx1YXRpb25gKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmRpcnR5T3BJbmRleCsrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuY2xlYW5pbmcgPSBmYWxzZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBwYXJhbWV0ZXIncyB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRWYWx1ZSgpIHsKICAgICAgICAgICAgaWYgKHRoaXMuZGlydHlPcEluZGV4IDwgdGhpcy5ib3VuZE91dHB1dHMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9jbGVhbih0aGlzLmJvdW5kT3V0cHV0cy5sZW5ndGgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0aGlzLiN2YWx1ZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHBhcmFtLgogICAgICAgICAqLwogICAgICAgIHNldFZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdGhyb3ctbGl0ZXJhbAogICAgICAgICAgICAgICAgdGhyb3cgJ3VuZGVmaW5lZCB3YXMgcGFzc2VkIGludG8gdGhlIHNldCB2YWx1ZSBmb3IgcGFyYW06JyArIHRoaXMuZ2V0TmFtZSgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh0aGlzLmJvdW5kT3V0cHV0cy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gdGhpcy5ib3VuZE91dHB1dHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBvcGVyYXRvck91dHB1dCA9IHRoaXMuYm91bmRPdXRwdXRzW2ldOwogICAgICAgICAgICAgICAgICAgIHZhbHVlID0gb3BlcmF0b3JPdXRwdXQuYmFja1Byb3BhZ2F0ZVZhbHVlKHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICBpZiAob3BlcmF0b3JPdXRwdXQuZ2V0TW9kZSgpID09IDAgLyogT1BfV1JJVEUgKi8pCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnb2JqZWN0JykgewogICAgICAgICAgICAgICAgLy8gTm90ZTogZXF1YWxpdHkgdGVzdHMgb24gYW55dGhpbmcgYnV0IHNpbXBsZSB2YWx1ZXMgaXMgZ29pbmcgdG8gYmUgc3VwZXIgZXhwZW5zaXZlLgogICAgICAgICAgICAgICAgaWYgKHRoaXMuI3ZhbHVlID09IHZhbHVlKQogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLiN2YWx1ZSA9IHZhbHVlOwogICAgICAgICAgICAvLyBOb3RlOiBvbmx5IHVzZXJzIGNhbGwgJ3NldFZhbHVlJy4gT3BlcmF0b3JzIGNhbGwgJ3NldENsZWFuRnJvbU9wJwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuYm91bmRJbnB1dHMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIHRoaXMuYm91bmRJbnB1dHNbaV0ucGFyYW1WYWx1ZUNoYW5nZWQoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLmVtaXQoJ3ZhbHVlQ2hhbmdlZCcpOwogICAgICAgIH0KICAgICAgICBnZXQgdmFsdWUoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldFZhbHVlKCk7CiAgICAgICAgfQogICAgICAgIHNldCB2YWx1ZSh2YWx1ZSkgewogICAgICAgICAgICB0aGlzLnNldFZhbHVlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIFBlcnNpc3RlbmNlCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGxvYWRWYWx1ZSBpcyB1c2VkIHRvIGNoYW5nZSB0aGUgdmFsdWUgb2YgYSBwYXJhbWV0ZXIsIHdpdGhvdXQgdHJpZ2dlcmluZyBhCiAgICAgICAgICogdmFsdWVDaGFuZ2VzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgbG9hZFZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIHRoaXMuI3ZhbHVlID0gdmFsdWU7CiAgICAgICAgfQogICAgICAgIGNvcHlGcm9tKHNyYywgY29udGV4dCkgewogICAgICAgICAgICB0aGlzLmxvYWRWYWx1ZShzcmMudmFsdWUpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgcmVhZEJpbmFyeSBtZXRob2QuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIGNvbnNvbGUud2FybihgVE9ETzogUGFyYW1ldGVyOiAke3RoaXMuY29uc3RydWN0b3IubmFtZX0gd2l0aCBuYW1lOiAke3RoaXMubmFtZX0gZG9lcyBub3QgaW1wbGVtZW50IHJlYWRCaW5hcnlgKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgcGFyYW1ldGVyJ3MgcGF0aCBhcyBhbiBhcnJheSBvZiBzdHJpbmdzLgogICAgICAgICAqIEluY2x1ZGVzIG93bmVyJ3MgcGF0aCBpbiBjYXNlIGl0IGlzIG93bmVkIGJ5IGEgYFBhcmFtZXRlck93bmVyYC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldFBhdGgoKSB7CiAgICAgICAgICAgIGlmICh0aGlzLm93bmVySXRlbSBpbnN0YW5jZW9mIEJhc2VJdGVtKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gWy4uLnRoaXMub3duZXJJdGVtLmdldFBhdGgoKSwgdGhpcy5uYW1lXTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHJldHVybiBbdGhpcy5uYW1lXTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXNvbHZlUGF0aChwYXRoLCBpbmRleCA9IDApIHsKICAgICAgICAgICAgaWYgKGluZGV4ID09IDApIHsKICAgICAgICAgICAgICAgIGlmIChwYXRoWzBdID09ICcuJyB8fCBwYXRoWzBdID09IHRoaXMubmFtZSkKICAgICAgICAgICAgICAgICAgICBpbmRleCsrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChwYXRoW2luZGV4XSA9PSAnLi4nKSB7CiAgICAgICAgICAgICAgICBpZiAodGhpcy5vd25lckl0ZW0pIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5vd25lckl0ZW0ucmVzb2x2ZVBhdGgocGF0aCwgaW5kZXggKyAxKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIHRocm93IEVycm9yKCd0aGlzLm93bmVySXRlbSBpcyB1bmRlZmluZWQnKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoaW5kZXggPT0gcGF0aC5sZW5ndGgpIHsKICAgICAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChwYXRoW2luZGV4XSA9PSAndmFsdWUnKSB7CiAgICAgICAgICAgICAgICAvLyBUaGUgcGF0aCB0byB0aGUgcGFyYW1ldGVyLCBhc3N1bWVzIHRoYXQgdGhlIG5leHQgaXRlbSB3aWxsIGJlIGEgc3ViLXBhcmFtCiAgICAgICAgICAgICAgICAvLyBvZiB0aGUgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci4KICAgICAgICAgICAgICAgIGlmICh0aGlzLiN2YWx1ZSBpbnN0YW5jZW9mIEJhc2VJdGVtKQogICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiN2YWx1ZS5yZXNvbHZlUGF0aChwYXRoLCBpbmRleCArIDEpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBwYXRoOicgKyBwYXRoICsgJ1snICsgaW5kZXggKyAnXS4gUGF0aCBkb2VzIG5vdCByZXNvbHZlIHRvIGEgQmFzZUl0ZW0nKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHJlYWRCaW5hcnkgbWV0aG9kLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHJlYWRlciAtIFRoZSByZWFkZXIgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBkZXN0cm95KCkgewogICAgICAgICAgICBjb25zb2xlLndhcm4oJ25vdGhpbmcgZGVzdHJveWVkLiBUaGlzIG1ldGhvZCB3YXMgbm90IG92ZXJ3cml0dGVuIGluIHN1YmNsYXNzJyk7CiAgICAgICAgfQogICAgfQoKICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIHNwZWNpZmljIHR5cGUgb2YgcGFyYW1ldGVyLCB0aGF0IG9ubHkgc3RvcmVzIG51bWVyaWMgdmFsdWVzLgogICAgICoKICAgICAqIGBgYGphdmFzY3JpcHQKICAgICAqIGNvbnN0IG51bWJlclBhcmFtID0gbmV3IE51bWJlclBhcmFtZXRlcignTXlOdW1iZXInLCAxNSkKICAgICAqIC8vJ215UGFyYW1ldGVyT3duZXJJdGVtJyBpcyBhbiBpbnN0YW5jZSBvZiBhICdQYXJhbWV0ZXJPd25lcicgY2xhc3MuCiAgICAgKiAvLyBSZW1lbWJlciB0aGF0IG9ubHkgJ1BhcmFtZXRlck93bmVyJyBhbmQgY2xhc3NlcyB0aGF0IGV4dGVuZCBmcm9tIGl0IGNhbiBob3N0ICdQYXJhbWV0ZXInIG9iamVjdHMuCiAgICAgKiBteVBhcmFtZXRlck93bmVySXRlbS5hZGRQYXJhbWV0ZXIobnVtYmVyUGFyYW0pCiAgICAgKiBgYGAKICAgICAqCiAgICAgKiBAZXh0ZW5kcyBQYXJhbWV0ZXIKICAgICAqLwogICAgY2xhc3MgTnVtYmVyUGFyYW1ldGVyIGV4dGVuZHMgUGFyYW1ldGVyIHsKICAgICAgICByYW5nZTsgLy8gVE9ETzogc2hvdWxkIGNyZWF0ZSB0eXBlIHdpdGggdHdvIGZpZWxkcyBmb3IgcmFuZ2UuIE11c3QgY2hhbmdlIGhvdyByYW5nZSBpcyB1c2VkLgogICAgICAgIHN0ZXA7CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlIGEgbnVtYmVyIHBhcmFtZXRlci4KICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBudW1iZXIgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSByYW5nZSAtIEFuIGFycmF5IHdpdGggdHdvIG51bWJlcnMuIElmIGRlZmluZWQsIHRoZSBwYXJhbWV0ZXIgdmFsdWUgd2lsbCBiZSBjbGFtcGVkLgogICAgICAgICAqIEBwYXJhbSBzdGVwIC0gVGhlIHN0ZXAgdmFsdWUuIElmIGRlZmluZWQsIHRoZSBwYXJhbWV0ZXIgdmFsdWUgd2lsbCBiZSByb3VuZGVkIHRvIHRoZSBuZWFyZXN0IGludGVnZXIuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IobmFtZSA9ICcnLCB2YWx1ZSA9IDAsIHJhbmdlLCBzdGVwKSB7CiAgICAgICAgICAgIHN1cGVyKG5hbWUsIHZhbHVlLCAnTnVtYmVyJyk7CiAgICAgICAgICAgIHRoaXMucmFuZ2UgPSByYW5nZTsKICAgICAgICAgICAgdGhpcy5zdGVwID0gc3RlcDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgcmFuZ2UgdG8gd2hpY2ggdGhlIHBhcmFtZXRlciBpcyByZXN0cmFpbmVkLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0UmFuZ2UoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnJhbmdlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHRoZSByYW5nZSB0byB3aGljaCB0aGUgcGFyYW1ldGVyIGlzIHJlc3RyYWluZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmFuZ2UgLSBUaGUgcmFuZ2UgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0UmFuZ2UocmFuZ2UpIHsKICAgICAgICAgICAgdGhpcy5yYW5nZSA9IHJhbmdlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBzdGVwIG51bWJlciwgd2hpY2ggaXMgdGhlIG9uZSB1c2VkIGZvciByb3VuZGluZy4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldFN0ZXAoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0ZXA7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgc3RlcCB2YWx1ZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBzdGVwIC0gVGhlIHN0ZXAgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0U3RlcChzdGVwKSB7CiAgICAgICAgICAgIHRoaXMuc3RlcCA9IHN0ZXA7CiAgICAgICAgfQogICAgICAgIHNldFZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT0gJ251bWJlcicpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdmFsdWUgcHJvdmlkZWQgaXMgbm90IGEgbnVtYmVyLiBDaGVjayB0aGUgc291cmNlIG9mIHRoaXMgdmFsdWVgKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdXBlci5zZXRWYWx1ZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQZXJzaXN0ZW5jZQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSB0b0pTT04gbWV0aG9kIGVuY29kZXMgdGhpcyB0eXBlIGFzIGEganNvbiBvYmplY3QgZm9yIHBlcnNpc3RlbmNlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUganNvbiBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgdG9KU09OKGNvbnRleHQpIHsKICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogdGhpcy5nZXRDbGFzc05hbWUoKSwgbmFtZTogdGhpcy5uYW1lLCB2YWx1ZTogdGhpcy52YWx1ZSB9OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIGRlY29kZXMgYSBqc29uIG9iamVjdCBmb3IgdGhpcyB0eXBlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGogLSBUaGUganNvbiBvYmplY3QgdGhpcyBpdGVtIG11c3QgZGVjb2RlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZnJvbUpTT04oaiwgY29udGV4dCkgewogICAgICAgICAgICB0aGlzLnZhbHVlID0gai52YWx1ZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogRXh0cmFjdHMgYSBudW1iZXIgdmFsdWUgZnJvbSBhIGJ1ZmZlciwgdXBkYXRpbmcgY3VycmVudCBwYXJhbWV0ZXIgc3RhdGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHRoaXMudmFsdWUgPSByZWFkZXIubG9hZEZsb2F0MzIoKTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIENsb25lCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGNsb25lIG1ldGhvZCBjb25zdHJ1Y3RzIGEgbmV3IG51bWJlciBwYXJhbWV0ZXIsIGNvcGllcyBpdHMgdmFsdWVzCiAgICAgICAgICogZnJvbSB0aGlzIHBhcmFtZXRlciBhbmQgcmV0dXJucyBpdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IG51bWJlciBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgTnVtYmVyUGFyYW1ldGVyKHRoaXMubmFtZSwgdGhpcy52YWx1ZSwgdGhpcy5yYW5nZSwgdGhpcy5zdGVwKTsKICAgICAgICB9CiAgICB9CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVxdWlyZS1qc2RvYwogICAgY2xhc3MgRmxvYXQzMlBhcmFtZXRlciBleHRlbmRzIE51bWJlclBhcmFtZXRlciB7CiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHJlcXVpcmUtanNkb2MKICAgICAgICByZWFkQmluYXJ5KHJlYWRlciwgY29udGV4dCkgewogICAgICAgICAgICB0aGlzLnZhbHVlID0gcmVhZGVyLmxvYWRGbG9hdDMyKCk7CiAgICAgICAgfQogICAgfQogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHJlcXVpcmUtanNkb2MKICAgIGNsYXNzIFNJbnQzMlBhcmFtZXRlciBleHRlbmRzIE51bWJlclBhcmFtZXRlciB7CiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHJlcXVpcmUtanNkb2MKICAgICAgICByZWFkQmluYXJ5KHJlYWRlciwgY29udGV4dCkgewogICAgICAgICAgICB0aGlzLnZhbHVlID0gcmVhZGVyLmxvYWRTSW50MzIoKTsKICAgICAgICB9CiAgICB9CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVxdWlyZS1qc2RvYwogICAgY2xhc3MgVUludDMyUGFyYW1ldGVyIGV4dGVuZHMgTnVtYmVyUGFyYW1ldGVyIHsKICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVxdWlyZS1qc2RvYwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHRoaXMudmFsdWUgPSByZWFkZXIubG9hZFVJbnQzMigpOwogICAgICAgIH0KICAgIH0KICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSByZXF1aXJlLWpzZG9jCiAgICBjbGFzcyBBbmdsZVBhcmFtZXRlciBleHRlbmRzIEZsb2F0MzJQYXJhbWV0ZXIgewogICAgfQogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ051bWJlclBhcmFtZXRlcicsIE51bWJlclBhcmFtZXRlcik7CiAgICBSZWdpc3RyeS5yZWdpc3RlcignUHJvcGVydHlfU0ludDMyJywgU0ludDMyUGFyYW1ldGVyKTsKICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdQcm9wZXJ0eV9VSW50MzInLCBVSW50MzJQYXJhbWV0ZXIpOwogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ1Byb3BlcnR5X0Zsb2F0MzInLCBGbG9hdDMyUGFyYW1ldGVyKTsKICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdBbmdsZVBhcmFtZXRlcicsIEFuZ2xlUGFyYW1ldGVyKTsKCiAgICAvKioKICAgICAqIFJlcHJlc2VudHMgYSBzcGVjaWZpYyB0eXBlIG9mIHBhcmFtZXRlciwgdGhhdCBzdG9yZXMgbXVsdGlwbGUgY2hvaWNlKGFycmF5KSB2YWx1ZXMuCiAgICAgKgogICAgICogaS5lLjoKICAgICAqIGBgYGphdmFzY3JpcHQKICAgICAqIGNvbnN0IG11bHRpQ2hvaWNlUGFyYW1ldGVyID0gIG5ldyBNdWx0aUNob2ljZVBhcmFtZXRlcignSW5pdGlhbFhmb01vZGUnLCBHUk9VUF9JTklUSUFMX1hGT19NT0RFUy5hdmVyYWdlLCBbCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbWFudWFsJywKICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdmaXJzdCcsCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnYXZlcmFnZScsCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZ2xvYmFsJywKICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdKQogICAgICogLy8nbXlQYXJhbWV0ZXJPd25lckl0ZW0nIGlzIGFuIGluc3RhbmNlIG9mIGEgJ1BhcmFtZXRlck93bmVyJyBjbGFzcy4KICAgICAqIC8vIFJlbWVtYmVyIHRoYXQgb25seSAnUGFyYW1ldGVyT3duZXInIGFuZCBjbGFzc2VzIHRoYXQgZXh0ZW5kIGZyb20gaXQgY2FuIGhvc3QgJ1BhcmFtZXRlcicgb2JqZWN0cy4KICAgICAqIG15UGFyYW1ldGVyT3duZXJJdGVtLmFkZFBhcmFtZXRlcihtdWx0aUNob2ljZVBhcmFtZXRlcikKICAgICAqIGBgYAogICAgICogQGV4dGVuZHMgTnVtYmVyUGFyYW1ldGVyCiAgICAgKi8KICAgIGNsYXNzIE11bHRpQ2hvaWNlUGFyYW1ldGVyIGV4dGVuZHMgTnVtYmVyUGFyYW1ldGVyIHsKICAgICAgICBjaG9pY2VzOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIG11bHRpIGNob2ljZSBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbXVsdGkgY2hvaWNlIHBhcmFtZXRlci4KICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGNob2ljZXMgLSBUaGUgY2hvaWNlcyB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3RvcihuYW1lLCBpbmRleCwgY2hvaWNlcyA9IFtdKSB7CiAgICAgICAgICAgIHN1cGVyKG5hbWUsIGluZGV4LCBbMCwgY2hvaWNlcy5sZW5ndGhdLCAxKTsKICAgICAgICAgICAgdGhpcy5jaG9pY2VzID0gY2hvaWNlczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBjaG9pY2VzIGFycmF5LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0Q2hvaWNlcygpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hvaWNlczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyBwYXJhbWV0ZXIgaW5kZXggdmFsdWUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgcGFyYW0uCiAgICAgICAgICovCiAgICAgICAgc2V0VmFsdWUodmFsdWUpIHsKICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHsKICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5jaG9pY2VzLmluZGV4T2YodmFsdWUpOwogICAgICAgICAgICAgICAgaWYgKGluZGV4ID09PSAtMSkgewogICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEludmFsaWQgdmFsdWUgZm9yIE11bHRpQ2hvaWNlUGFyYW1ldGVyOiAke3ZhbHVlfS4gY2hvaWNlcyBhcmU6ICR7dGhpcy5jaG9pY2VzfS5gKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIHN1cGVyLnNldFZhbHVlKGluZGV4KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHN1cGVyLnNldFZhbHVlKHZhbHVlKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBNdWx0aUNob2ljZVBhcmFtZXRlcih0aGlzLm5hbWUsIHRoaXMudmFsdWUsIHRoaXMuY2hvaWNlcyk7CiAgICAgICAgfQogICAgfQogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ011bHRpQ2hvaWNlUGFyYW1ldGVyJywgTXVsdGlDaG9pY2VQYXJhbWV0ZXIpOwoKICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFycyAqLwogICAgLyoqCiAgICAgKiBSZXByZXNlbnRzIGEgc3BlY2lmaWMgdHlwZSBvZiBwYXJhbWV0ZXIsIHRoYXQgb25seSBzdG9yZXMgYGJvb2xlYW5gIHZhbHVlcy4KICAgICAqCiAgICAgKiBpLmUuOgogICAgICogYGBgamF2YXNjcmlwdAogICAgICogY29uc3QgYm9vbGVhblBhcmFtID0gbmV3IEJvb2xlYW5QYXJhbWV0ZXIoJ015Qm9vbGVhbicsIHRydWUpCiAgICAgKiAvLydteVBhcmFtZXRlck93bmVySXRlbScgaXMgYW4gaW5zdGFuY2Ugb2YgYSAnUGFyYW1ldGVyT3duZXInIGNsYXNzLgogICAgICogLy8gUmVtZW1iZXIgdGhhdCBvbmx5ICdQYXJhbWV0ZXJPd25lcicgYW5kIGNsYXNzZXMgdGhhdCBleHRlbmQgZnJvbSBpdCBjYW4gaG9zdCAnUGFyYW1ldGVyJyBvYmplY3RzLgogICAgICogbXlQYXJhbWV0ZXJPd25lckl0ZW0uYWRkUGFyYW1ldGVyKGJvb2xlYW5QYXJhbSkKICAgICAqIGBgYAogICAgICogQGV4dGVuZHMgUGFyYW1ldGVyCiAgICAgKi8KICAgIGNsYXNzIEJvb2xlYW5QYXJhbWV0ZXIgZXh0ZW5kcyBQYXJhbWV0ZXIgewogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYSBuZXcgcGFyYW1ldGVyIHdpdGggYEJvb2xlYW5gIGRhdGEgdHlwZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGJvb2xlYW4gcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKG5hbWUgPSAnJywgdmFsdWUpIHsKICAgICAgICAgICAgc3VwZXIobmFtZSwgdmFsdWUgIT0gdW5kZWZpbmVkID8gdmFsdWUgOiBmYWxzZSwgJ0Jvb2xlYW4nKTsKICAgICAgICB9CiAgICAgICAgc2V0VmFsdWUodmFsdWUpIHsKICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPSAnYm9vbGVhbicpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdmFsdWUgcHJvdmlkZWQgaXMgbm90IGEgYm9vbGVhbi4gQ2hlY2sgdGhlIHNvdXJjZSBvZiB0aGlzIHZhbHVlYCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3VwZXIuc2V0VmFsdWUodmFsdWUpOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBMb2FkcyB0aGUgYm9vbGVhbiB2YWx1ZXMgZnJvbSB0aGUgYmluYXJ5IGJ1ZmZlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSByZWFkZXIgLSBUaGUgcmVhZGVyIHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgcmVhZEJpbmFyeShyZWFkZXIsIGNvbnRleHQpIHsKICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHJlYWRlci5sb2FkVUludDgoKSAhPSAwOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdG9KU09OIG1ldGhvZCBzZXJpYWxpemVzIHRoaXMgaW5zdGFuY2UgYXMgYSBKU09OLgogICAgICAgICAqIEl0IGNhbiBiZSB1c2VkIGZvciBwZXJzaXN0ZW5jZSwgZGF0YSB0cmFuc2ZlciwgZXRjLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUganNvbiBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgdG9KU09OKGNvbnRleHQpIHsKICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogdGhpcy5nZXRDbGFzc05hbWUoKSwgbmFtZTogdGhpcy5uYW1lLCB2YWx1ZTogdGhpcy52YWx1ZSB9OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIHRha2VzIGEgSlNPTiBhbmQgZGVzZXJpYWxpemVzIGludG8gYW4gaW5zdGFuY2Ugb2YgdGhpcyB0eXBlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGogLSBUaGUganNvbiBvYmplY3QgdGhpcyBpdGVtIG11c3QgZGVjb2RlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZnJvbUpTT04oaiwgY29udGV4dCkgewogICAgICAgICAgICB0aGlzLnZhbHVlID0gai52YWx1ZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGNsb25lIG1ldGhvZCBjb25zdHJ1Y3RzIGEgbmV3IHBhcmFtZXRlciwgY29waWVzIGl0cyB2YWx1ZXMKICAgICAgICAgKiBmcm9tIHRoaXMgcGFyYW1ldGVyIGFuZCByZXR1cm5zIGl0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgY2xvbmVkIHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBCb29sZWFuUGFyYW1ldGVyKHRoaXMubmFtZSwgdGhpcy52YWx1ZSk7CiAgICAgICAgfQogICAgfQogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ0Jvb2xlYW5QYXJhbWV0ZXInLCBCb29sZWFuUGFyYW1ldGVyKTsKICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdQcm9wZXJ0eV9Cb29sZWFuJywgQm9vbGVhblBhcmFtZXRlcik7CgogICAgLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqLwogICAgLyoqCiAgICAgKiBSZXByZXNlbnRzIGEgc3BlY2lmaWMgdHlwZSBvZiBwYXJhbWV0ZXIsIHRoYXQgb25seSBzdG9yZXMgVmVjMih0d28tZGltZW5zaW9uYWwgY29vcmRpbmF0ZSkgdmFsdWVzLgogICAgICoKICAgICAqIGkuZS46CiAgICAgKiBgYGBqYXZhc2NyaXB0CiAgICAgKiBjb25zdCB2ZWMyUGFyYW0gPSBuZXcgVmVjMlBhcmFtZXRlcignTXlWZWMyJywgbmV3IFZlYzIoMS4yLCAzLjQpKQogICAgICogLy8nbXlQYXJhbWV0ZXJPd25lckl0ZW0nIGlzIGFuIGluc3RhbmNlIG9mIGEgJ1BhcmFtZXRlck93bmVyJyBjbGFzcy4KICAgICAqIC8vIFJlbWVtYmVyIHRoYXQgb25seSAnUGFyYW1ldGVyT3duZXInIGFuZCBjbGFzc2VzIHRoYXQgZXh0ZW5kIGZyb20gaXQgY2FuIGhvc3QgJ1BhcmFtZXRlcicgb2JqZWN0cy4KICAgICAqIG15UGFyYW1ldGVyT3duZXJJdGVtLmFkZFBhcmFtZXRlcih2ZWMyUGFyYW0pCiAgICAgKiBgYGAKICAgICAqCiAgICAgKiAqKkV2ZW50cyoqCiAgICAgKiAqICoqcmFuZ2VDaGFuZ2VkOioqIFRyaWdnZXJlZCB3aGVuIHJhZ2UgYXJyYXkgY2hhbmdlcy4KICAgICAqCiAgICAgKiBAZXh0ZW5kcyBQYXJhbWV0ZXIKICAgICAqLwogICAgY2xhc3MgVmVjMlBhcmFtZXRlciBleHRlbmRzIFBhcmFtZXRlciB7CiAgICAgICAgcmFuZ2U7CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlIGEgVmVjMiBwYXJhbWV0ZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBWZWMyIHBhcmFtZXRlci4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci4KICAgICAgICAgKiBAcGFyYW0gcmFuZ2UgLSBUaGUgcmFuZ2UgdmFsdWUgaXMgYW4gYXJyYXkgb2YgdHdvIGBWZWMyYCBvYmplY3RzLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKG5hbWUgPSAnJywgdmFsdWUsIHJhbmdlKSB7CiAgICAgICAgICAgIHN1cGVyKG5hbWUsIHZhbHVlID8gdmFsdWUgOiBuZXcgVmVjMigpLCAnVmVjMicpOwogICAgICAgICAgICB0aGlzLnJhbmdlID0gcmFuZ2U7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIHJhbmdlIG9mIHZhbHVlcyBpbiB3aGljaCBjdXJyZW50IHBhcmFtZXRlciBjYW4gYmUuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRSYW5nZSgpIHsKICAgICAgICAgICAgLy8gUmFuZ2Ugc2hvdWxkIGJlIGFuIGFycmF5IG9mIDIgdmVjMnMuIFttaW4oeCx5KSwgbWF4KHgseSldCiAgICAgICAgICAgIHJldHVybiB0aGlzLnJhbmdlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgX19zZXRSYW5nZSBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIHJhbmdlIC0gVGhlIHJhbmdlIHZhbHVlLgogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICovCiAgICAgICAgc2V0UmFuZ2UocmFuZ2UpIHsKICAgICAgICAgICAgLy8gU2hvdWxkIGJlIGFuIGFycmF5IFswLCAyMF0KICAgICAgICAgICAgdGhpcy5yYW5nZSA9IHJhbmdlOwogICAgICAgICAgICB0aGlzLmVtaXQoJ3JhbmdlQ2hhbmdlZCcsIHsgcmFuZ2UgfSk7CiAgICAgICAgfQogICAgICAgIHNldFZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgVmVjMikpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdmFsdWUgcHJvdmlkZWQgaXMgbm90IGFuIGluc3RhbmNlIG9mIGEgJ1ZlYzInIGNsYXNzLiBDaGVjayB0aGUgc291cmNlIG9mIHRoaXMgdmFsdWVgKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdXBlci5zZXRWYWx1ZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEV4dHJhY3RzIGEgbnVtYmVyIHZhbHVlIGZyb20gYSBidWZmZXIsIHVwZGF0aW5nIGN1cnJlbnQgcGFyYW1ldGVyIHN0YXRlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHJlYWRlciAtIFRoZSByZWFkZXIgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICByZWFkQmluYXJ5KHJlYWRlciwgY29udGV4dCkgewogICAgICAgICAgICB0aGlzLnZhbHVlPy5yZWFkQmluYXJ5KHJlYWRlcik7CiAgICAgICAgfQogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLmdldENsYXNzTmFtZSgpLAogICAgICAgICAgICAgICAgbmFtZTogdGhpcy5uYW1lLAogICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMudmFsdWU/LnRvSlNPTigpLAogICAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICBmcm9tSlNPTihqLCBjb250ZXh0KSB7CiAgICAgICAgICAgIGNvbnN0IHZlYzIgPSBuZXcgVmVjMigpOwogICAgICAgICAgICB2ZWMyLmZyb21KU09OKGoudmFsdWUpOwogICAgICAgICAgICB0aGlzLnZhbHVlID0gdmVjMjsKICAgICAgICAgICAgaWYgKGoubmFtZSkKICAgICAgICAgICAgICAgIHRoaXMubmFtZSA9IGoubmFtZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGNsb25lIG1ldGhvZCBjb25zdHJ1Y3RzIGEgbmV3IFZlYzIgcGFyYW1ldGVyLCBjb3BpZXMgaXRzIHZhbHVlcwogICAgICAgICAqIGZyb20gdGhpcyBwYXJhbWV0ZXIgYW5kIHJldHVybnMgaXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBWZWMyIHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgY29uc3QgY2xvbmVkUGFyYW0gPSBuZXcgVmVjMlBhcmFtZXRlcih0aGlzLm5hbWUsIHRoaXMudmFsdWU/LmNsb25lKCkpOwogICAgICAgICAgICBpZiAodGhpcy5yYW5nZSkKICAgICAgICAgICAgICAgIGNsb25lZFBhcmFtLnNldFJhbmdlKHRoaXMucmFuZ2UpOwogICAgICAgICAgICByZXR1cm4gY2xvbmVkUGFyYW07CiAgICAgICAgfQogICAgfQogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ1ZlYzJQYXJhbWV0ZXInLCBWZWMyUGFyYW1ldGVyKTsKICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdQcm9wZXJ0eV9WZWMyXzMyZicsIFZlYzJQYXJhbWV0ZXIpOwoKICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi8KICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIHNwZWNpZmljIHR5cGUgb2YgcGFyYW1ldGVyLCB0aGF0IG9ubHkgc3RvcmVzIFZlYzModGhyZWUtZGltZW5zaW9uYWwgY29vcmRpbmF0ZSkgdmFsdWVzLgogICAgICoKICAgICAqIGkuZS46CiAgICAgKiBgYGBqYXZhc2NyaXB0CiAgICAgKiBjb25zdCB2ZWMzUGFyYW0gPSBuZXcgVmVjM1BhcmFtZXRlcignTXlWZWMzJywgbmV3IFZlYzMoMS4yLCAzLjQsIDEpKQogICAgICogLy8nbXlQYXJhbWV0ZXJPd25lckl0ZW0nIGlzIGFuIGluc3RhbmNlIG9mIGEgJ1BhcmFtZXRlck93bmVyJyBjbGFzcy4KICAgICAqIC8vIFJlbWVtYmVyIHRoYXQgb25seSAnUGFyYW1ldGVyT3duZXInIGFuZCBjbGFzc2VzIHRoYXQgZXh0ZW5kIGZyb20gaXQgY2FuIGhvc3QgJ1BhcmFtZXRlcicgb2JqZWN0cy4KICAgICAqIG15UGFyYW1ldGVyT3duZXJJdGVtLmFkZFBhcmFtZXRlcih2ZWMzUGFyYW0pCiAgICAgKiBgYGAKICAgICAqIEBleHRlbmRzIFBhcmFtZXRlcgogICAgICovCiAgICBjbGFzcyBWZWMzUGFyYW1ldGVyIGV4dGVuZHMgUGFyYW1ldGVyIHsKICAgICAgICByYW5nZTsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgYSBWZWMzIHBhcmFtZXRlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIFZlYzMgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSByYW5nZSAtIFRoZSByYW5nZSB2YWx1ZSBpcyBhbiBhcnJheSBvZiB0d28gYFZlYzNgIG9iamVjdHMuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IobmFtZSA9ICcnLCB2YWx1ZSwgcmFuZ2UpIHsKICAgICAgICAgICAgc3VwZXIobmFtZSwgdmFsdWUgPyB2YWx1ZSA6IG5ldyBWZWMzKCksICdWZWMzJyk7CiAgICAgICAgICAgIHRoaXMucmFuZ2UgPSByYW5nZTsKICAgICAgICB9CiAgICAgICAgc2V0VmFsdWUodmFsdWUpIHsKICAgICAgICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBWZWMzKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB2YWx1ZSBwcm92aWRlZCBpcyBub3QgYW4gaW5zdGFuY2Ugb2YgYSAnVmVjMicgY2xhc3MuIENoZWNrIHRoZSBzb3VyY2Ugb2YgdGhpcyB2YWx1ZWApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN1cGVyLnNldFZhbHVlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIFBlcnNpc3RlbmNlCiAgICAgICAgLyoqCiAgICAgICAgICogRXh0cmFjdHMgYSBudW1iZXIgdmFsdWUgZnJvbSBhIGJ1ZmZlciwgdXBkYXRpbmcgY3VycmVudCBwYXJhbWV0ZXIgc3RhdGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHRoaXMudmFsdWU/LnJlYWRCaW5hcnkocmVhZGVyKTsKICAgICAgICB9CiAgICAgICAgdG9KU09OKGNvbnRleHQpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIHR5cGU6IHRoaXMuZ2V0Q2xhc3NOYW1lKCksCiAgICAgICAgICAgICAgICBuYW1lOiB0aGlzLm5hbWUsCiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy52YWx1ZT8udG9KU09OKCksCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIGZyb21KU09OKGosIGNvbnRleHQpIHsKICAgICAgICAgICAgY29uc3QgdmVjNCA9IG5ldyBWZWMzKCk7CiAgICAgICAgICAgIHZlYzQuZnJvbUpTT04oai52YWx1ZSk7CiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2ZWM0OwogICAgICAgICAgICBpZiAoai5uYW1lKQogICAgICAgICAgICAgICAgdGhpcy5uYW1lID0gai5uYW1lOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgY2xvbmUgbWV0aG9kIGNvbnN0cnVjdHMgYSBuZXcgVmVjMyBwYXJhbWV0ZXIsIGNvcGllcyBpdHMgdmFsdWVzCiAgICAgICAgICogZnJvbSB0aGlzIHBhcmFtZXRlciBhbmQgcmV0dXJucyBpdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFZlYzMgcGFyYW1ldGVyLgogICAgICAgICAqLwogICAgICAgIGNsb25lKCkgewogICAgICAgICAgICBjb25zdCBjbG9uZWRQYXJhbSA9IG5ldyBWZWMzUGFyYW1ldGVyKHRoaXMubmFtZSwgdGhpcy52YWx1ZT8uY2xvbmUoKSk7CiAgICAgICAgICAgIHJldHVybiBjbG9uZWRQYXJhbTsKICAgICAgICB9CiAgICB9CiAgICBSZWdpc3RyeS5yZWdpc3RlcignVmVjM1BhcmFtZXRlcicsIFZlYzNQYXJhbWV0ZXIpOwogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ1Byb3BlcnR5X1ZlYzNfMzJmJywgVmVjM1BhcmFtZXRlcik7CgogICAgLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqLwogICAgLyoqCiAgICAgKiBSZXByZXNlbnRzIGEgc3BlY2lmaWMgdHlwZSBvZiBwYXJhbWV0ZXIsIHRoYXQgb25seSBzdG9yZXMgVmVjNChmb3VyLWRpbWVuc2lvbmFsIGNvb3JkaW5hdGUpIHZhbHVlcy4KICAgICAqCiAgICAgKiBpLmUuOgogICAgICogYGBgamF2YXNjcmlwdAogICAgICogY29uc3QgdmVjNFBhcmFtID0gbmV3IFZlYzRQYXJhbWV0ZXIoJ015VmVjNCcsIG5ldyBWZWM0KDEuMiwgMy40LCAxLCA0LjIpKQogICAgICogLy8nbXlQYXJhbWV0ZXJPd25lckl0ZW0nIGlzIGFuIGluc3RhbmNlIG9mIGEgJ1BhcmFtZXRlck93bmVyJyBjbGFzcy4KICAgICAqIC8vIFJlbWVtYmVyIHRoYXQgb25seSAnUGFyYW1ldGVyT3duZXInIGFuZCBjbGFzc2VzIHRoYXQgZXh0ZW5kIGZyb20gaXQgY2FuIGhvc3QgJ1BhcmFtZXRlcicgb2JqZWN0cy4KICAgICAqIG15UGFyYW1ldGVyT3duZXJJdGVtLmFkZFBhcmFtZXRlcih2ZWM0UGFyYW0pCiAgICAgKiBgYGAKICAgICAqCiAgICAgKiBAZXh0ZW5kcyBQYXJhbWV0ZXIKICAgICAqLwogICAgY2xhc3MgVmVjNFBhcmFtZXRlciBleHRlbmRzIFBhcmFtZXRlciB7CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlIGEgVmVjNCBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgVmVjNCBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIG9mIHRoZSBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IobmFtZSA9ICcnLCB2YWx1ZSkgewogICAgICAgICAgICBzdXBlcihuYW1lLCB2YWx1ZSA/IHZhbHVlIDogbmV3IFZlYzQoKSwgJ1ZlYzQnKTsKICAgICAgICB9CiAgICAgICAgc2V0VmFsdWUodmFsdWUpIHsKICAgICAgICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBWZWM0KSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB2YWx1ZSBwcm92aWRlZCBpcyBub3QgYW4gaW5zdGFuY2Ugb2YgYSAnVmVjNCcgY2xhc3MuIENoZWNrIHRoZSBzb3VyY2Ugb2YgdGhpcyB2YWx1ZWApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN1cGVyLnNldFZhbHVlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIFBlcnNpc3RlbmNlCiAgICAgICAgLyoqCiAgICAgICAgICogRXh0cmFjdHMgYSBudW1iZXIgdmFsdWUgZnJvbSBhIGJ1ZmZlciwgdXBkYXRpbmcgY3VycmVudCBwYXJhbWV0ZXIgc3RhdGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHRoaXMudmFsdWU/LnJlYWRCaW5hcnkocmVhZGVyKTsKICAgICAgICB9CiAgICAgICAgdG9KU09OKGNvbnRleHQpIHsKICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogdGhpcy5nZXRDbGFzc05hbWUoKSwgbmFtZTogdGhpcy5uYW1lLCB2YWx1ZTogdGhpcy52YWx1ZT8udG9KU09OKCkgfTsKICAgICAgICB9CiAgICAgICAgZnJvbUpTT04oaiwgY29udGV4dCkgewogICAgICAgICAgICBjb25zdCB2ZWM0ID0gbmV3IFZlYzQoKTsKICAgICAgICAgICAgdmVjNC5mcm9tSlNPTihqLnZhbHVlKTsKICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZlYzQ7CiAgICAgICAgICAgIGlmIChqLm5hbWUpCiAgICAgICAgICAgICAgICB0aGlzLm5hbWUgPSBqLm5hbWU7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBDbG9uZQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBjbG9uZSBtZXRob2QgY29uc3RydWN0cyBhIG5ldyBWZWM0IHBhcmFtZXRlciwgY29waWVzIGl0cyB2YWx1ZXMKICAgICAgICAgKiBmcm9tIHRoaXMgcGFyYW1ldGVyIGFuZCByZXR1cm5zIGl0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgVmVjNCBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgIGNvbnN0IGNsb25lZFBhcmFtID0gbmV3IFZlYzRQYXJhbWV0ZXIodGhpcy5uYW1lLCB0aGlzLnZhbHVlPy5jbG9uZSgpKTsKICAgICAgICAgICAgcmV0dXJuIGNsb25lZFBhcmFtOwogICAgICAgIH0KICAgIH0KICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdWZWM0UGFyYW1ldGVyJywgVmVjNFBhcmFtZXRlcik7CiAgICBSZWdpc3RyeS5yZWdpc3RlcignUHJvcGVydHlfVmVjNF8zMmYnLCBWZWM0UGFyYW1ldGVyKTsKCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMgKi8KICAgIC8qKgogICAgICogQGV4dGVuZHMgUGFyYW1ldGVyCiAgICAgKi8KICAgIGNsYXNzIEJveDJQYXJhbWV0ZXIgZXh0ZW5kcyBQYXJhbWV0ZXIgewogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIEJveDIgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIEJveDIgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKG5hbWUgPSAnJywgdmFsdWUpIHsKICAgICAgICAgICAgc3VwZXIobmFtZSwgdmFsdWUgPyB2YWx1ZSA6IG5ldyBCb3gyKCksICdCb3gyJyk7CiAgICAgICAgfQogICAgICAgIHNldFZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgQm94MikpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdmFsdWUgcHJvdmlkZWQgaXMgbm90IGFuIGluc3RhbmNlIG9mIGEgJ0JveDInIGNsYXNzLiBDaGVjayB0aGUgc291cmNlIG9mIHRoaXMgdmFsdWVgKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdXBlci5zZXRWYWx1ZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEV4dHJhY3RzIGEgbnVtYmVyIHZhbHVlIGZyb20gYSBidWZmZXIsIHVwZGF0aW5nIGN1cnJlbnQgcGFyYW1ldGVyIHN0YXRlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHJlYWRlciAtIFRoZSByZWFkZXIgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICByZWFkQmluYXJ5KHJlYWRlciwgY29udGV4dCkgewogICAgICAgICAgICB0aGlzLnZhbHVlLnAwLnJlYWRCaW5hcnkocmVhZGVyKTsKICAgICAgICAgICAgdGhpcy52YWx1ZS5wMS5yZWFkQmluYXJ5KHJlYWRlcik7CiAgICAgICAgfQogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLmdldENsYXNzTmFtZSgpLAogICAgICAgICAgICAgICAgbmFtZTogdGhpcy5uYW1lLAogICAgICAgICAgICAgICAgdmFsdWU6IHsKICAgICAgICAgICAgICAgICAgICBwMDogdGhpcy52YWx1ZS5wMC50b0pTT04oKSwKICAgICAgICAgICAgICAgICAgICBwMTogdGhpcy52YWx1ZS5wMS50b0pTT04oKSwKICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIGZyb21KU09OKGosIGNvbnRleHQpIHsKICAgICAgICAgICAgdGhpcy52YWx1ZS5wMC5mcm9tSlNPTihqLnAwKTsKICAgICAgICAgICAgdGhpcy52YWx1ZS5wMS5mcm9tSlNPTihqLnAxKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGNsb25lIG1ldGhvZCBjb25zdHJ1Y3RzIGEgbmV3IEJveDIgcGFyYW1ldGVyLAogICAgICAgICAqIGNvcGllcyBpdHMgdmFsdWVzIGZyb20gdGhpcyBwYXJhbWV0ZXIgYW5kIHJldHVybnMgaXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBjbG9uZWQgQm94MiBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgIGNvbnN0IGNsb25lZFBhcmFtID0gbmV3IEJveDJQYXJhbWV0ZXIodGhpcy5uYW1lLCB0aGlzLnZhbHVlPy5jbG9uZSgpKTsKICAgICAgICAgICAgcmV0dXJuIGNsb25lZFBhcmFtOwogICAgICAgIH0KICAgIH0KICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdCb3gyUGFyYW1ldGVyJywgQm94MlBhcmFtZXRlcik7CiAgICBSZWdpc3RyeS5yZWdpc3RlcignUHJvcGVydHlfQm94Ml8zMmYnLCBCb3gyUGFyYW1ldGVyKTsKCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMgKi8KICAgIC8qKgogICAgICogQGV4dGVuZHMgUGFyYW1ldGVyCiAgICAgKi8KICAgIGNsYXNzIEJveDNQYXJhbWV0ZXIgZXh0ZW5kcyBQYXJhbWV0ZXIgewogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIEJveDMgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIEJveDMgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKG5hbWUgPSAnJywgdmFsdWUpIHsKICAgICAgICAgICAgc3VwZXIobmFtZSwgdmFsdWUgPyB2YWx1ZSA6IG5ldyBCb3gzKCksICdCb3gzJyk7CiAgICAgICAgfQogICAgICAgIHNldFZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgQm94MykpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdmFsdWUgcHJvdmlkZWQgaXMgbm90IGFuIGluc3RhbmNlIG9mIGEgJ0JveDMnIGNsYXNzLiBDaGVjayB0aGUgc291cmNlIG9mIHRoaXMgdmFsdWVgKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdXBlci5zZXRWYWx1ZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEV4dHJhY3RzIGEgbnVtYmVyIHZhbHVlIGZyb20gYSBidWZmZXIsIHVwZGF0aW5nIGN1cnJlbnQgcGFyYW1ldGVyIHN0YXRlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHJlYWRlciAtIFRoZSByZWFkZXIgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICByZWFkQmluYXJ5KHJlYWRlciwgY29udGV4dCkgewogICAgICAgICAgICB0aGlzLnZhbHVlLnAwLnJlYWRCaW5hcnkocmVhZGVyKTsKICAgICAgICAgICAgdGhpcy52YWx1ZS5wMS5yZWFkQmluYXJ5KHJlYWRlcik7CiAgICAgICAgfQogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLmdldENsYXNzTmFtZSgpLAogICAgICAgICAgICAgICAgbmFtZTogdGhpcy5uYW1lLAogICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMudmFsdWUudG9KU09OKCksCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIGZyb21KU09OKGosIGNvbnRleHQpIHsKICAgICAgICAgICAgaWYgKGoudmFsdWUpIHsKICAgICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmUKICAgICAgICAgICAgICAgIHRoaXMudmFsdWUuZnJvbUpTT04oai52YWx1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGNsb25lIG1ldGhvZCBjb25zdHJ1Y3RzIGEgbmV3IEJveDMgcGFyYW1ldGVyLAogICAgICAgICAqIGNvcGllcyBpdHMgdmFsdWVzIGZyb20gdGhpcyBwYXJhbWV0ZXIgYW5kIHJldHVybnMgaXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBjbG9uZWQgQm94MyBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgIGNvbnN0IGNsb25lZFBhcmFtID0gbmV3IEJveDNQYXJhbWV0ZXIodGhpcy5uYW1lLCB0aGlzLnZhbHVlPy5jbG9uZSgpKTsKICAgICAgICAgICAgcmV0dXJuIGNsb25lZFBhcmFtOwogICAgICAgIH0KICAgIH0KICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdCb3gzUGFyYW1ldGVyJywgQm94M1BhcmFtZXRlcik7CiAgICBSZWdpc3RyeS5yZWdpc3RlcignUHJvcGVydHlfQm94M18zMmYnLCBCb3gzUGFyYW1ldGVyKTsKCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55ICovCiAgICAvKioKICAgICAqIFJlcHJlc2VudHMgYSBzcGVjaWZpYyB0eXBlIG9mIHBhcmFtZXRlciwgdGhhdCBvbmx5IHN0b3JlcyBgQ29sb3JgIHZhbHVlcy4KICAgICAqCiAgICAgKiBpLmUuOgogICAgICogYGBgamF2YXNjcmlwdAogICAgICogY29uc3QgY29sb3JQYXJhbSA9IG5ldyBDb2xvclBhcmFtZXRlcignTXlDb2xvcicsIG5ldyBDb2xvcigwLCAyNTQsIDIpKQogICAgICogLy8nbXlQYXJhbWV0ZXJPd25lckl0ZW0nIGlzIGFuIGluc3RhbmNlIG9mIGEgJ1BhcmFtZXRlck93bmVyJyBjbGFzcy4KICAgICAqIC8vIFJlbWVtYmVyIHRoYXQgb25seSAnUGFyYW1ldGVyT3duZXInIGFuZCBjbGFzc2VzIHRoYXQgZXh0ZW5kIGZyb20gaXQgY2FuIGhvc3QgJ1BhcmFtZXRlcicgb2JqZWN0cy4KICAgICAqIG15UGFyYW1ldGVyT3duZXJJdGVtLmFkZFBhcmFtZXRlcihjb2xvclBhcmFtKQogICAgICogYGBgCiAgICAgKgogICAgICogQGV4dGVuZHMgUGFyYW1ldGVyCiAgICAgKi8KICAgIGNsYXNzIENvbG9yUGFyYW1ldGVyIGV4dGVuZHMgUGFyYW1ldGVyIHsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgYSBjb2xvciBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgY29sb3IgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKG5hbWUgPSAnJywgdmFsdWUpIHsKICAgICAgICAgICAgc3VwZXIobmFtZSwgdmFsdWUgPyB2YWx1ZSA6IG5ldyBDb2xvcigpLCAnQ29sb3InKTsKICAgICAgICB9CiAgICAgICAgc2V0VmFsdWUodmFsdWUpIHsKICAgICAgICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBDb2xvcikpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdmFsdWUgcHJvdmlkZWQgaXMgbm90IGFuIGluc3RhbmNlIG9mIGEgJ0NvbG9yJyBjbGFzcy4gQ2hlY2sgdGhlIHNvdXJjZSBvZiB0aGlzIHZhbHVlYCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3VwZXIuc2V0VmFsdWUodmFsdWUpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBFeHRyYWN0cyBgQ29sb3JgIHZhbHVlcyBmcm9tIGEgYnVmZmVyLCB1cGRhdGluZyBjdXJyZW50IHBhcmFtZXRlciBzdGF0ZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSByZWFkZXIgLSBUaGUgcmVhZGVyIHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgcmVhZEJpbmFyeShyZWFkZXIsIGNvbnRleHQpIHsKICAgICAgICAgICAgY29uc3QgdmFsdWUgPSByZWFkZXIubG9hZFJHQkFGbG9hdDMyQ29sb3IoKTsKICAgICAgICAgICAgLy8gSWYgdGhlIHZhbHVlIGlzIGluIGxpbmVhciBzcGFjZSwgdGhlbiB3ZSBzaG91bGQgY29udmVydCBpdCB0byBnYW1tYSBzcGFjZS4KICAgICAgICAgICAgLy8gTm90ZTogISEgdGhpcyBzaG91bGQgYWx3YXlzIGJlIGRvbmUgaW4gcHJlcHJvY2Vzc2luZy4uLgogICAgICAgICAgICB2YWx1ZS5hcHBseUdhbW1hKDIuMik7CiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICAgICAgICB9CiAgICAgICAgdG9KU09OKGNvbnRleHQpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIHR5cGU6IHRoaXMuZ2V0Q2xhc3NOYW1lKCksCiAgICAgICAgICAgICAgICBuYW1lOiB0aGlzLm5hbWUsCiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy52YWx1ZT8udG9KU09OKCksCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIGZyb21KU09OKGosIGNvbnRleHQpIHsKICAgICAgICAgICAgLy8gaWYgKGoudmFsdWUudHlwZSkgdGhpcy52YWx1ZSA9IFJlZ2lzdHJ5LmNvbnN0cnVjdENsYXNzKCdDb2xvcicpIGFzIENvbG9yIC8vIFRPRE86IGNvbW1lbnRlZCBvdXQgUmVnaXN0cnkuY29uc3RydWN0Q2xhc3MKICAgICAgICAgICAgdGhpcy52YWx1ZT8uZnJvbUpTT04oai52YWx1ZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBjbG9uZSBtZXRob2QgY29uc3RydWN0cyBhIG5ldyBjb2xvciBwYXJhbWV0ZXIsCiAgICAgICAgICogY29waWVzIGl0cyB2YWx1ZXMgZnJvbSB0aGlzIHBhcmFtZXRlciBhbmQgcmV0dXJucyBpdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IGNsb25lZCBjb2xvciBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgIGNvbnN0IGNsb25lZFBhcmFtID0gbmV3IENvbG9yUGFyYW1ldGVyKHRoaXMubmFtZSwgdGhpcy52YWx1ZT8uY2xvbmUoKSk7CiAgICAgICAgICAgIHJldHVybiBjbG9uZWRQYXJhbTsKICAgICAgICB9CiAgICB9CiAgICBSZWdpc3RyeS5yZWdpc3RlcignQ29sb3JQYXJhbWV0ZXInLCBDb2xvclBhcmFtZXRlcik7CiAgICBSZWdpc3RyeS5yZWdpc3RlcignUHJvcGVydHlfQ29sb3JfMzJmJywgQ29sb3JQYXJhbWV0ZXIpOwoKICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi8KICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIHNwZWNpZmljIHR5cGUgb2YgcGFyYW1ldGVyLCB0aGF0IG9ubHkgc3RvcmVzIFZlYzMoZm91ci1kaW1lbnNpb25hbCBjb29yZGluYXRlKSB2YWx1ZXMuCiAgICAgKgogICAgICogaS5lLjoKICAgICAqIGBgYGphdmFzY3JpcHQKICAgICAqIGNvbnN0IHF1YXRQYXJhbSA9IG5ldyBRdWF0UGFyYW1ldGVyKCdNeVF1YXQnLCBuZXcgUXVhdCgxLjIsIDMuNCwgMSwgNC4yKSkKICAgICAqIC8vJ215UGFyYW1ldGVyT3duZXJJdGVtJyBpcyBhbiBpbnN0YW5jZSBvZiBhICdQYXJhbWV0ZXJPd25lcicgY2xhc3MuCiAgICAgKiAvLyBSZW1lbWJlciB0aGF0IG9ubHkgJ1BhcmFtZXRlck93bmVyJyBhbmQgY2xhc3NlcyB0aGF0IGV4dGVuZCBmcm9tIGl0IGNhbiBob3N0ICdQYXJhbWV0ZXInIG9iamVjdHMuCiAgICAgKiBteVBhcmFtZXRlck93bmVySXRlbS5hZGRQYXJhbWV0ZXIocXVhdFBhcmFtKQogICAgICogYGBgCiAgICAgKgogICAgICogQGV4dGVuZHMgUGFyYW1ldGVyCiAgICAgKi8KICAgIGNsYXNzIFF1YXRQYXJhbWV0ZXIgZXh0ZW5kcyBQYXJhbWV0ZXIgewogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIFF1YXQgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIFF1YXQgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKG5hbWUgPSAnJywgdmFsdWUpIHsKICAgICAgICAgICAgc3VwZXIobmFtZSwgdmFsdWUgPyB2YWx1ZSA6IG5ldyBRdWF0KCksICdRdWF0Jyk7CiAgICAgICAgfQogICAgICAgIHNldFZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgUXVhdCkpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdmFsdWUgcHJvdmlkZWQgaXMgbm90IGFuIGluc3RhbmNlIG9mIGEgJ1F1YXQnIGNsYXNzLiBDaGVjayB0aGUgc291cmNlIG9mIHRoaXMgdmFsdWVgKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdXBlci5zZXRWYWx1ZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQZXJzaXN0ZW5jZQogICAgICAgIC8qKgogICAgICAgICAqIEV4dHJhY3RzIGEgbnVtYmVyIHZhbHVlIGZyb20gYSBidWZmZXIsIHVwZGF0aW5nIGN1cnJlbnQgcGFyYW1ldGVyIHN0YXRlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHJlYWRlciAtIFRoZSByZWFkZXIgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICByZWFkQmluYXJ5KHJlYWRlciwgY29udGV4dCkgewogICAgICAgICAgICB0aGlzLnZhbHVlPy5yZWFkQmluYXJ5KHJlYWRlcik7CiAgICAgICAgfQogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLmdldENsYXNzTmFtZSgpLAogICAgICAgICAgICAgICAgbmFtZTogdGhpcy5uYW1lLAogICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMudmFsdWU/LnRvSlNPTigpLAogICAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICBmcm9tSlNPTihqLCBjb250ZXh0KSB7CiAgICAgICAgICAgIGNvbnN0IHF1YXQgPSBuZXcgUXVhdCgpOwogICAgICAgICAgICBxdWF0LmZyb21KU09OKGoudmFsdWUpOwogICAgICAgICAgICB0aGlzLnZhbHVlID0gcXVhdDsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIENsb25lCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGNsb25lIG1ldGhvZCBjb25zdHJ1Y3RzIGEgbmV3IFF1YXQgcGFyYW1ldGVyLCBjb3BpZXMgaXRzIHZhbHVlcwogICAgICAgICAqIGZyb20gdGhpcyBwYXJhbWV0ZXIgYW5kIHJldHVybnMgaXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBRdWF0IHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgY29uc3QgY2xvbmVkUGFyYW0gPSBuZXcgUXVhdFBhcmFtZXRlcih0aGlzLm5hbWUsIHRoaXMudmFsdWU/LmNsb25lKCkpOwogICAgICAgICAgICByZXR1cm4gY2xvbmVkUGFyYW07CiAgICAgICAgfQogICAgfQogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ1F1YXRQYXJhbWV0ZXInLCBRdWF0UGFyYW1ldGVyKTsKICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdQcm9wZXJ0eV9RdWF0XzMyZicsIFF1YXRQYXJhbWV0ZXIpOwoKICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFycyAqLwogICAgLyoqCiAgICAgKiBSZXByZXNlbnRzIGEgc3BlY2lmaWMgdHlwZSBvZiBwYXJhbWV0ZXIsIHRoYXQgb25seSBzdG9yZXMgTWF0MygzeDMgbWF0cml4KSB2YWx1ZXMuCiAgICAgKgogICAgICogaS5lLjoKICAgICAqIGBgYGphdmFzY3JpcHQKICAgICAqIGNvbnN0IG1hdDNQYXJhbSA9IG5ldyBNYTNQYXJhbWV0ZXIoJ015TWF0MycsIG5ldyBNYXQzKC4uLmFyZ3MpKQogICAgICogLy8nbXlQYXJhbWV0ZXJPd25lckl0ZW0nIGlzIGFuIGluc3RhbmNlIG9mIGEgJ1BhcmFtZXRlck93bmVyJyBjbGFzcy4KICAgICAqIC8vIFJlbWVtYmVyIHRoYXQgb25seSAnUGFyYW1ldGVyT3duZXInIGFuZCBjbGFzc2VzIHRoYXQgZXh0ZW5kIGZyb20gaXQgY2FuIGhvc3QgJ1BhcmFtZXRlcicgb2JqZWN0cy4KICAgICAqIG15UGFyYW1ldGVyT3duZXJJdGVtLmFkZFBhcmFtZXRlcihtYXQzUGFyYW0pCiAgICAgKiBgYGAKICAgICAqCiAgICAgKiBAZXh0ZW5kcyBQYXJhbWV0ZXIKICAgICAqLwogICAgY2xhc3MgTWF0M1BhcmFtZXRlciBleHRlbmRzIFBhcmFtZXRlciB7CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlIGEgTWF0MyBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgTWF0MyBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIG9mIHRoZSBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IobmFtZSA9ICcnLCB2YWx1ZSkgewogICAgICAgICAgICBzdXBlcihuYW1lLCB2YWx1ZSA/IHZhbHVlIDogbmV3IE1hdDMoKSwgJ01hdDMnKTsKICAgICAgICB9CiAgICAgICAgc2V0VmFsdWUodmFsdWUpIHsKICAgICAgICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBNYXQzKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB2YWx1ZSBwcm92aWRlZCBpcyBub3QgYW4gaW5zdGFuY2Ugb2YgYSAnTWF0MycgY2xhc3MuIENoZWNrIHRoZSBzb3VyY2Ugb2YgdGhpcyB2YWx1ZWApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN1cGVyLnNldFZhbHVlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogRXh0cmFjdHMgYSBudW1iZXIgdmFsdWUgZnJvbSBhIGJ1ZmZlciwgdXBkYXRpbmcgY3VycmVudCBwYXJhbWV0ZXIgc3RhdGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHRoaXMudmFsdWU/LnJlYWRCaW5hcnkocmVhZGVyKTsKICAgICAgICB9CiAgICAgICAgdG9KU09OKGNvbnRleHQpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIHR5cGU6IHRoaXMuZ2V0Q2xhc3NOYW1lKCksCiAgICAgICAgICAgICAgICBuYW1lOiB0aGlzLm5hbWUsCiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy52YWx1ZT8udG9KU09OKCksCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIGZyb21KU09OKGosIGNvbnRleHQpIHsKICAgICAgICAgICAgY29uc3QgbWF0MyA9IG5ldyBNYXQzKCk7CiAgICAgICAgICAgIG1hdDMuZnJvbUpTT04oai52YWx1ZSk7CiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBtYXQzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgY2xvbmUgbWV0aG9kIGNvbnN0cnVjdHMgYSBuZXcgTWF0MyBwYXJhbWV0ZXIsCiAgICAgICAgICogY29waWVzIGl0cyB2YWx1ZXMgZnJvbSB0aGlzIHBhcmFtZXRlciBhbmQgcmV0dXJucyBpdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IGNsb25lZCBNYXQzIHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgY29uc3QgY2xvbmVkUGFyYW0gPSBuZXcgTWF0M1BhcmFtZXRlcih0aGlzLm5hbWUsIHRoaXMudmFsdWU/LmNsb25lKCkpOwogICAgICAgICAgICByZXR1cm4gY2xvbmVkUGFyYW07CiAgICAgICAgfQogICAgfQogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ01hdDNQYXJhbWV0ZXInLCBNYXQzUGFyYW1ldGVyKTsKICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdQcm9wZXJ0eV9NYXQzXzMyZicsIE1hdDNQYXJhbWV0ZXIpOwoKICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi8KICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIHNwZWNpZmljIHR5cGUgb2YgcGFyYW1ldGVyLCB0aGF0IG9ubHkgc3RvcmVzIE1hdDQoNHg0IG1hdHJpeCkgdmFsdWVzLgogICAgICoKICAgICAqIGkuZS46CiAgICAgKiBgYGBqYXZhc2NyaXB0CiAgICAgKiBjb25zdCBtYXQ0UGFyYW0gPSBuZXcgTWEzUGFyYW1ldGVyKCdNeU1hdDQnLCBuZXcgTWF0NCguLi5hcmdzKSkKICAgICAqIC8vJ215UGFyYW1ldGVyT3duZXJJdGVtJyBpcyBhbiBpbnN0YW5jZSBvZiBhICdQYXJhbWV0ZXJPd25lcicgY2xhc3MuCiAgICAgKiAvLyBSZW1lbWJlciB0aGF0IG9ubHkgJ1BhcmFtZXRlck93bmVyJyBhbmQgY2xhc3NlcyB0aGF0IGV4dGVuZCBmcm9tIGl0IGNhbiBob3N0ICdQYXJhbWV0ZXInIG9iamVjdHMuCiAgICAgKiBteVBhcmFtZXRlck93bmVySXRlbS5hZGRQYXJhbWV0ZXIobWF0NFBhcmFtKQogICAgICogYGBgCiAgICAgKgogICAgICogQGV4dGVuZHMgUGFyYW1ldGVyCiAgICAgKi8KICAgIGNsYXNzIE1hdDRQYXJhbWV0ZXIgZXh0ZW5kcyBQYXJhbWV0ZXIgewogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIE1hdDQgcGFyYW1ldGVyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgTWF0NCBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIG9mIHRoZSBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IobmFtZSA9ICcnLCB2YWx1ZSkgewogICAgICAgICAgICBzdXBlcihuYW1lLCB2YWx1ZSA/IHZhbHVlIDogbmV3IE1hdDQoKSwgJ01hdDQnKTsKICAgICAgICB9CiAgICAgICAgc2V0VmFsdWUodmFsdWUpIHsKICAgICAgICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBNYXQ0KSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB2YWx1ZSBwcm92aWRlZCBpcyBub3QgYW4gaW5zdGFuY2Ugb2YgYSAnTWF0NCcgY2xhc3MuIENoZWNrIHRoZSBzb3VyY2Ugb2YgdGhpcyB2YWx1ZWApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN1cGVyLnNldFZhbHVlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogRXh0cmFjdHMgYSBudW1iZXIgdmFsdWUgZnJvbSBhIGJ1ZmZlciwgdXBkYXRpbmcgY3VycmVudCBwYXJhbWV0ZXIgc3RhdGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHRoaXMudmFsdWU/LnJlYWRCaW5hcnkocmVhZGVyKTsKICAgICAgICB9CiAgICAgICAgdG9KU09OKGNvbnRleHQpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIHR5cGU6IHRoaXMuZ2V0Q2xhc3NOYW1lKCksCiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy52YWx1ZT8udG9KU09OKCksCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIGZyb21KU09OKGosIGNvbnRleHQpIHsKICAgICAgICAgICAgY29uc3QgbWF0NCA9IG5ldyBNYXQ0KCk7CiAgICAgICAgICAgIG1hdDQuZnJvbUpTT04oai52YWx1ZSk7CiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBtYXQ0OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgY2xvbmUgbWV0aG9kIGNvbnN0cnVjdHMgYSBuZXcgTWF0NCBwYXJhbWV0ZXIsCiAgICAgICAgICogY29waWVzIGl0cyB2YWx1ZXMgZnJvbSB0aGlzIHBhcmFtZXRlciBhbmQgcmV0dXJucyBpdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IGNsb25lZCBNYXQ0IHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgY29uc3QgY2xvbmVkUGFyYW0gPSBuZXcgTWF0NFBhcmFtZXRlcih0aGlzLm5hbWUsIHRoaXMudmFsdWU/LmNsb25lKCkpOwogICAgICAgICAgICByZXR1cm4gY2xvbmVkUGFyYW07CiAgICAgICAgfQogICAgfQogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ01hdDRQYXJhbWV0ZXInLCBNYXQ0UGFyYW1ldGVyKTsKICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdQcm9wZXJ0eV9NYXQ0XzMyZicsIE1hdDRQYXJhbWV0ZXIpOwoKICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi8KICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIHNwZWNpZmljIHR5cGUgb2YgcGFyYW1ldGVyLCB0aGF0IG9ubHkgc3RvcmVzIGBYZm9gIHRyYW5zZm9ybSB2YWx1ZXMuCiAgICAgKgogICAgICogYGBgamF2YXNjcmlwdAogICAgICogY29uc3QgeGZvUGFyYW0gPSBuZXcgWGZvUGFyYW1ldGVyKCdNeVhmbycsIG5ldyBYZm8obmV3IFZlYzMoMS4yLCAzLjQsIDEpKSkKICAgICAqIC8vJ215UGFyYW1ldGVyT3duZXJJdGVtJyBpcyBhbiBpbnN0YW5jZSBvZiBhICdQYXJhbWV0ZXJPd25lcicgY2xhc3MuCiAgICAgKiAvLyBSZW1lbWJlciB0aGF0IG9ubHkgJ1BhcmFtZXRlck93bmVyJyBhbmQgY2xhc3NlcyB0aGF0IGV4dGVuZCBmcm9tIGl0IGNhbiBob3N0ICdQYXJhbWV0ZXInIG9iamVjdHMuCiAgICAgKiBteVBhcmFtZXRlck93bmVySXRlbS5hZGRQYXJhbWV0ZXIoeGZvUGFyYW0pCiAgICAgKiBgYGAKICAgICAqCiAgICAgKiBAZXh0ZW5kcyBQYXJhbWV0ZXIKICAgICAqLwogICAgY2xhc3MgWGZvUGFyYW1ldGVyIGV4dGVuZHMgUGFyYW1ldGVyIHsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgYSBYZm8gcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIFhmbyBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIG9mIHRoZSBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IobmFtZSA9ICcnLCB2YWx1ZSkgewogICAgICAgICAgICBzdXBlcihuYW1lLCB2YWx1ZSA/IHZhbHVlIDogbmV3IFhmbygpLCAnWGZvJyk7CiAgICAgICAgfQogICAgICAgIHNldFZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgWGZvKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB2YWx1ZSBwcm92aWRlZCBpcyBub3QgYW4gaW5zdGFuY2Ugb2YgYSAnWGZvJyBjbGFzcy4gQ2hlY2sgdGhlIHNvdXJjZSBvZiB0aGlzIHZhbHVlYCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3VwZXIuc2V0VmFsdWUodmFsdWUpOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBFeHRyYWN0cyBhIG51bWJlciB2YWx1ZSBmcm9tIGEgYnVmZmVyLCB1cGRhdGluZyBjdXJyZW50IHBhcmFtZXRlciBzdGF0ZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSByZWFkZXIgLSBUaGUgcmVhZGVyIHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgcmVhZEJpbmFyeShyZWFkZXIsIGNvbnRleHQpIHsKICAgICAgICAgICAgdGhpcy52YWx1ZS5yZWFkQmluYXJ5KHJlYWRlcik7CiAgICAgICAgfQogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6IHRoaXMuZ2V0Q2xhc3NOYW1lKCksIG5hbWU6IHRoaXMubmFtZSwgdmFsdWU6IHRoaXMudmFsdWUudG9KU09OKCkgfTsKICAgICAgICB9CiAgICAgICAgZnJvbUpTT04oaiwgY29udGV4dCkgewogICAgICAgICAgICBjb25zdCB4Zm8gPSBuZXcgWGZvKCk7CiAgICAgICAgICAgIHhmby5mcm9tSlNPTihqLnZhbHVlKTsKICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHhmbzsKICAgICAgICAgICAgaWYgKGoubmFtZSkKICAgICAgICAgICAgICAgIHRoaXMubmFtZSA9IGoubmFtZTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIENsb25lCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGNsb25lIG1ldGhvZCBjb25zdHJ1Y3RzIGEgbmV3IFhmbyBwYXJhbWV0ZXIsIGNvcGllcyBpdHMgdmFsdWVzCiAgICAgICAgICogZnJvbSB0aGlzIHBhcmFtZXRlciBhbmQgcmV0dXJucyBpdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IFhmbyBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgIGNvbnN0IGNsb25lZFBhcmFtID0gbmV3IFhmb1BhcmFtZXRlcih0aGlzLm5hbWUsIHRoaXMudmFsdWUuY2xvbmUoKSk7CiAgICAgICAgICAgIHJldHVybiBjbG9uZWRQYXJhbTsKICAgICAgICB9CiAgICB9CiAgICBSZWdpc3RyeS5yZWdpc3RlcignWGZvUGFyYW1ldGVyJywgWGZvUGFyYW1ldGVyKTsKICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdQcm9wZXJ0eV9YZm9fMzJmJywgWGZvUGFyYW1ldGVyKTsKCiAgICAvKioKICAgICAqIFJlcHJlc2VudHMgYSAyRCBpbWFnZSBpdGVtLCBjb250YWluaW5nIHdpZHRoIGFuZCBoZWlnaHQuCiAgICAgKgogICAgICogKipFdmVudHMqKgogICAgICogKiAqKnVwZGF0ZWQ6KiogVHJpZ2dlcmVkIHdoZW4gdGhlIHZhbHVlIG9mIGFueSBvZiB0aGUgcGFyYW1ldGVycyBsaXN0ZWQgYWJvdmUgY2hhbmdlcy4KICAgICAqCiAgICAgKiBAZXh0ZW5kcyBQYXJhbWV0ZXJPd25lcgogICAgICovCiAgICBjbGFzcyBCYXNlSW1hZ2UgZXh0ZW5kcyBQYXJhbWV0ZXJPd25lciB7CiAgICAgICAgd2lkdGggPSAwOwogICAgICAgIGhlaWdodCA9IDA7CiAgICAgICAgZm9ybWF0ID0gJ1JHQic7CiAgICAgICAgdHlwZSA9ICdVTlNJR05FRF9CWVRFJzsKICAgICAgICBsb2FkZWQgPSBmYWxzZTsKICAgICAgICBtaXBNYXBwZWQgPSB0cnVlOwogICAgICAgIHdyYXBTID0gJ1JFUEVBVCc7CiAgICAgICAgd3JhcFQgPSAnUkVQRUFUJzsKICAgICAgICBtaW5GaWx0ZXIgPSAnTElORUFSJzsKICAgICAgICBtYWdGaWx0ZXIgPSAnTElORUFSJzsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIEJhc2VJbWFnZS4KICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIG5hbWUgb2YgdGhlIGl0ZW0KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3RvcihuYW1lID0gJ0ltYWdlJykgewogICAgICAgICAgICBzdXBlcihuYW1lKTsKICAgICAgICAgICAgdGhpcy5vbigncGFyYW1ldGVyVmFsdWVDaGFuZ2VkJywgKCkgPT4gewogICAgICAgICAgICAgICAgdGhpcy5lbWl0KCd1cGRhdGVkJyk7CiAgICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRydWUgaWYgbG9hZGVkLgogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBib29sZWFuLgogICAgICAgICAqLwogICAgICAgIGlzTG9hZGVkKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5sb2FkZWQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYWxsIHBhcmFtZXRlcnMgYW5kIGNsYXNzIHN0YXRlIHZhbHVlcy4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldFBhcmFtcygpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIHR5cGU6IHRoaXMudHlwZSwKICAgICAgICAgICAgICAgIGZvcm1hdDogdGhpcy5mb3JtYXQsCiAgICAgICAgICAgICAgICB3aWR0aDogdGhpcy53aWR0aCwKICAgICAgICAgICAgICAgIGhlaWdodDogdGhpcy5oZWlnaHQsCiAgICAgICAgICAgICAgICB3cmFwUzogdGhpcy53cmFwUywKICAgICAgICAgICAgICAgIHdyYXBUOiB0aGlzLndyYXBULAogICAgICAgICAgICAgICAgbWluRmlsdGVyOiB0aGlzLm1pbkZpbHRlciwKICAgICAgICAgICAgICAgIG1hZ0ZpbHRlcjogdGhpcy5tYWdGaWx0ZXIsCiAgICAgICAgICAgICAgICBtaXBNYXBwZWQ6IHRoaXMubWlwTWFwcGVkLAogICAgICAgICAgICB9OwogICAgICAgIH0KICAgIH0KCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMgKi8KICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIHNwZWNpZmljIHR5cGUgb2YgcGFyYW1ldGVyLCB0aGF0IG9ubHkgc3RvcmVzIGBCYXNlSW1hZ2VgIHZhbHVlcy4KICAgICAqCiAgICAgKiBpLmUuOgogICAgICogYGBgamF2YXNjcmlwdAogICAgICogLy8gU2luY2UgYExhYmVsYCBpcyBhIGBCYXNlSW1hZ2VgIGltcGxlbWVudGF0aW9uLCBpdCBoZWxwcyB1cyB3aXRoIHRoZSBleGFtcGxlLgogICAgICogY29uc3QgbGFiZWwgPSBuZXcgTGFiZWwoJ015IGF3ZXNvbWUgbGFiZWwnLCAnTGFiZWxQYWNrJykKICAgICAqIGNvbnN0IGltYWdlUGFyYW0gPSBuZXcgSW1hZ2VQYXJhbWV0ZXIoJ015SW1hZ2UnLCBsYWJlbCkKICAgICAqIC8vJ215UGFyYW1ldGVyT3duZXJJdGVtJyBpcyBhbiBpbnN0YW5jZSBvZiBhICdQYXJhbWV0ZXJPd25lcicgY2xhc3MuCiAgICAgKiAvLyBSZW1lbWJlciB0aGF0IG9ubHkgJ1BhcmFtZXRlck93bmVyJyBhbmQgY2xhc3NlcyB0aGF0IGV4dGVuZCBmcm9tIGl0IGNhbiBob3N0ICdQYXJhbWV0ZXInIG9iamVjdHMuCiAgICAgKiBteVBhcmFtZXRlck93bmVySXRlbS5hZGRQYXJhbWV0ZXIoaW1hZ2VQYXJhbSkKICAgICAqIGBgYAogICAgICoKICAgICAqIEBleHRlbmRzIFBhcmFtZXRlcgogICAgICovCiAgICBjbGFzcyBJbWFnZVBhcmFtZXRlciBleHRlbmRzIFBhcmFtZXRlciB7CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlIGFuIGltYWdlIHBhcmFtZXRlci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGltYWdlIHBhcmFtZXRlci4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3RvcihuYW1lID0gJycsIHZhbHVlKSB7CiAgICAgICAgICAgIHN1cGVyKG5hbWUsIHZhbHVlLCAnQmFzZUltYWdlJyk7CiAgICAgICAgfQogICAgICAgIHNldFZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgQmFzZUltYWdlKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB2YWx1ZSBwcm92aWRlZCBpcyBub3QgYW4gaW5zdGFuY2Ugb2YgJ0Jhc2VJbWFnZScgY2xhc3MuIENoZWNrIHRoZSBzb3VyY2Ugb2YgdGhpcyB2YWx1ZWApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN1cGVyLnNldFZhbHVlKHZhbHVlKTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIFBlcnNpc3RlbmNlCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHRvSlNPTiBtZXRob2QgZW5jb2RlcyB0aGlzIHR5cGUgYXMgYSBqc29uIG9iamVjdCBmb3IgcGVyc2lzdGVuY2UuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBqc29uIG9iamVjdC4KICAgICAgICAgKi8KICAgICAgICB0b0pTT04oY29udGV4dCkgewogICAgICAgICAgICBjb25zdCBqID0gewogICAgICAgICAgICAgICAgdHlwZTogdGhpcy5nZXRDbGFzc05hbWUoKSwKICAgICAgICAgICAgICAgIG5hbWU6IHRoaXMubmFtZSwKICAgICAgICAgICAgfTsKICAgICAgICAgICAgaWYgKHRoaXMudmFsdWUpIHsKICAgICAgICAgICAgICAgIGouaW1hZ2VUeXBlID0gdGhpcy52YWx1ZS5nZXRDbGFzc05hbWUoKTsKICAgICAgICAgICAgICAgIGoudmFsdWUgPSB0aGlzLnZhbHVlLnRvSlNPTigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBqOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIGRlY29kZXMgYSBqc29uIG9iamVjdCBmb3IgdGhpcyB0eXBlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGogLSBUaGUganNvbiBvYmplY3QgdGhpcyBpdGVtIG11c3QgZGVjb2RlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIGZyb21KU09OKGosIGNvbnRleHQpIHsKICAgICAgICAgICAgaWYgKGouaW1hZ2VUeXBlKSB7CiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gUmVnaXN0cnkuY29uc3RydWN0Q2xhc3Moai5pbWFnZVR5cGUpOwogICAgICAgICAgICAgICAgaWYgKGoudmFsdWUpCiAgICAgICAgICAgICAgICAgICAgdGhpcy52YWx1ZT8uZnJvbUpTT04oai52YWx1ZSwgY29udGV4dCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIENsb25lCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGNsb25lIG1ldGhvZCBjb25zdHJ1Y3RzIGEgbmV3IGltYWdlIHBhcmFtZXRlciwKICAgICAgICAgKiBjb3BpZXMgaXRzIHZhbHVlcyBmcm9tIHRoaXMgcGFyYW1ldGVyIGFuZCByZXR1cm5zIGl0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgY2xvbmVkIGltYWdlIHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgY29uc3QgY2xvbmVkUGFyYW0gPSBuZXcgSW1hZ2VQYXJhbWV0ZXIodGhpcy5uYW1lLCB0aGlzLnZhbHVlKTsKICAgICAgICAgICAgcmV0dXJuIGNsb25lZFBhcmFtOwogICAgICAgIH0KICAgIH0KICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdJbWFnZVBhcmFtZXRlcicsIEltYWdlUGFyYW1ldGVyKTsKCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMgKi8KICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIHNwZWNpZmljIHR5cGUgb2YgcGFyYW1ldGVyLCB0aGF0IG9ubHkgc3RvcmVzIE1hdDQoNHg0IG1hdHJpeCkgdmFsdWVzLgogICAgICoKICAgICAqIGkuZS46CiAgICAgKiBgYGBqYXZhc2NyaXB0CiAgICAgKiBjb25zdCBzdHJpbmdQYXJhbSA9IG5ldyBTdHJpbmdQYXJhbWV0ZXIoJ015U3RyaW5nJywgJ0EgU3RyaW5nIHZhbHVlIGdvZXMgaGVyZScpCiAgICAgKiAvLydteVBhcmFtZXRlck93bmVySXRlbScgaXMgYW4gaW5zdGFuY2Ugb2YgYSAnUGFyYW1ldGVyT3duZXInIGNsYXNzLgogICAgICogLy8gUmVtZW1iZXIgdGhhdCBvbmx5ICdQYXJhbWV0ZXJPd25lcicgYW5kIGNsYXNzZXMgdGhhdCBleHRlbmQgZnJvbSBpdCBjYW4gaG9zdCAnUGFyYW1ldGVyJyBvYmplY3RzLgogICAgICogbXlQYXJhbWV0ZXJPd25lckl0ZW0uYWRkUGFyYW1ldGVyKHN0cmluZ1BhcmFtKQogICAgICogYGBgCiAgICAgKgogICAgICogQGV4dGVuZHMgUGFyYW1ldGVyCiAgICAgKi8KICAgIGNsYXNzIFN0cmluZ1BhcmFtZXRlciBleHRlbmRzIFBhcmFtZXRlciB7CiAgICAgICAgbXVsdGlMaW5lOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIHN0cmluZyBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWF0ZXJpYWwgY29sb3IgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKG5hbWUgPSAnJywgdmFsdWUgPSAnJykgewogICAgICAgICAgICBzdXBlcihuYW1lLCB2YWx1ZSwgJ1N0cmluZycpOwogICAgICAgICAgICB0aGlzLm11bHRpTGluZSA9IGZhbHNlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIGZsYWcgdGhhdCBpbmRpY2F0ZXMgaWYgdGhlIHN0cmluZyBjb250YWlucyBuZXcgbGluZSBmZWVkcy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBtdWx0aUxpbmUgLSBUaGUgbXVsdGlMaW5lIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldE11bHRpTGluZShtdWx0aUxpbmUpIHsKICAgICAgICAgICAgdGhpcy5tdWx0aUxpbmUgPSBtdWx0aUxpbmU7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgbXVsdGktbGluZSBmbGFnIHZhbHVlLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0TXVsdGlMaW5lKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5tdWx0aUxpbmU7CiAgICAgICAgfQogICAgICAgIHNldFZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT0gJ3N0cmluZycpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdmFsdWUgcHJvdmlkZWQgaXMgbm90IGEgc3RyaW5nLiBDaGVjayB0aGUgc291cmNlIG9mIHRoaXMgdmFsdWVgKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdXBlci5zZXRWYWx1ZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEV4dHJhY3RzIHRoZSBzdHJpbmcgdmFsdWUgZnJvbSBhIGJ1ZmZlciwgdXBkYXRpbmcgY3VycmVudCBwYXJhbWV0ZXIgc3RhdGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHRoaXMudmFsdWUgPSByZWFkZXIubG9hZFN0cigpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdG9KU09OIG1ldGhvZCBzZXJpYWxpemVzIHRoaXMgaW5zdGFuY2UgYXMgYSBKU09OLgogICAgICAgICAqIEl0IGNhbiBiZSB1c2VkIGZvciBwZXJzaXN0ZW5jZSwgZGF0YSB0cmFuc2ZlciwgZXRjLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUganNvbiBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgdG9KU09OKGNvbnRleHQpIHsKICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogdGhpcy5nZXRDbGFzc05hbWUoKSwgbmFtZTogdGhpcy5uYW1lLCB2YWx1ZTogdGhpcy52YWx1ZSB9OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIHRha2VzIGEgSlNPTiBhbmQgZGVzZXJpYWxpemVzIGludG8gYW4gaW5zdGFuY2Ugb2YgdGhpcyB0eXBlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGogLSBUaGUganNvbiBvYmplY3QgdGhpcyBpdGVtIG11c3QgZGVjb2RlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZnJvbUpTT04oaiwgY29udGV4dCkgewogICAgICAgICAgICBjb25zdCBuZXdWYWx1ZSA9IGoudmFsdWUgPz8gJyc7CiAgICAgICAgICAgIGlmICh0aGlzLnZhbHVlICE9IG5ld1ZhbHVlKSB7CiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gbmV3VmFsdWU7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGNsb25lIG1ldGhvZCBjb25zdHJ1Y3RzIGEgbmV3IHN0cmluZyBwYXJhbWV0ZXIsIGNvcGllcyBpdHMgdmFsdWVzCiAgICAgICAgICogZnJvbSB0aGlzIHBhcmFtZXRlciBhbmQgcmV0dXJucyBpdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgbmV3IHN0cmluZyBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgU3RyaW5nUGFyYW1ldGVyKHRoaXMubmFtZSwgdGhpcy52YWx1ZSk7CiAgICAgICAgfQogICAgfQogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ1N0cmluZ1BhcmFtZXRlcicsIFN0cmluZ1BhcmFtZXRlcik7CiAgICBSZWdpc3RyeS5yZWdpc3RlcignUHJvcGVydHlfU3RyaW5nJywgU3RyaW5nUGFyYW1ldGVyKTsKCiAgICAvKioKICAgICAqIEEgcGFyYW1ldGVyIGZvciBzdG9yaW5nIGFuIGFycmF5IG9mIHN0cmluZyB2YWx1ZXMuCiAgICAgKgogICAgICogQGV4dGVuZHMgUGFyYW1ldGVyCiAgICAgKi8KICAgIGNsYXNzIFN0cmluZ0xpc3RQYXJhbWV0ZXIgZXh0ZW5kcyBQYXJhbWV0ZXIgewogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIHN0cmluZyBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWF0ZXJpYWwgY29sb3IgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKG5hbWUgPSAnJywgdmFsdWUgPSBbXSkgewogICAgICAgICAgICBzdXBlcihuYW1lLCB2YWx1ZSwgJ1N0cmluZ1tdJyk7CiAgICAgICAgfQogICAgICAgIHNldFZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdmFsdWUgcHJvdmlkZWQgaXMgbm90IGFuIGFycmF5LiBDaGVjayB0aGUgc291cmNlIG9mIHRoaXMgdmFsdWVgKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdXBlci5zZXRWYWx1ZSh2YWx1ZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEV4dHJhY3RzIHRoZSBzdHJpbmcgdmFsdWUgZnJvbSBhIGJ1ZmZlciwgdXBkYXRpbmcgY3VycmVudCBwYXJhbWV0ZXIgc3RhdGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0ge0JpblJlYWRlcn0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0ge29iamVjdH0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHRoaXMudmFsdWUgPSByZWFkZXIubG9hZFN0ckFycmF5KCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSB0b0pTT04gbWV0aG9kIHNlcmlhbGl6ZXMgdGhpcyBpbnN0YW5jZSBhcyBhIEpTT04uCiAgICAgICAgICogSXQgY2FuIGJlIHVzZWQgZm9yIHBlcnNpc3RlbmNlLCBkYXRhIHRyYW5zZmVyLCBldGMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIHVua25vd24+fSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICogQHJldHVybiB7UmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IHVuZGVmaW5lZD59IC0gUmV0dXJucyB0aGUganNvbiBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgdG9KU09OKGNvbnRleHQpIHsKICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogdGhpcy5nZXRDbGFzc05hbWUoKSwgbmFtZTogdGhpcy5uYW1lLCB2YWx1ZTogdGhpcy52YWx1ZSB9OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIHRha2VzIGEgSlNPTiBhbmQgZGVzZXJpYWxpemVzIGludG8gYW4gaW5zdGFuY2Ugb2YgdGhpcyB0eXBlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgdW5kZWZpbmVkPn0gaiAtIFRoZSBqc29uIG9iamVjdCB0aGlzIGl0ZW0gbXVzdCBkZWNvZGUuCiAgICAgICAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGZyb21KU09OKGosIGNvbnRleHQpIHsKICAgICAgICAgICAgdGhpcy52YWx1ZSA9IGoudmFsdWU7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBjbG9uZSBtZXRob2QgY29uc3RydWN0cyBhIG5ldyBzdHJpbmcgcGFyYW1ldGVyLCBjb3BpZXMgaXRzIHZhbHVlcwogICAgICAgICAqIGZyb20gdGhpcyBwYXJhbWV0ZXIgYW5kIHJldHVybnMgaXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIHtTdHJpbmdMaXN0UGFyYW1ldGVyfSAtIFJldHVybnMgYSBuZXcgc3RyaW5nIHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgY29uc3QgY2xvbmVkUGFyYW0gPSBuZXcgU3RyaW5nTGlzdFBhcmFtZXRlcih0aGlzLm5hbWUsIHRoaXMudmFsdWUpOwogICAgICAgICAgICByZXR1cm4gY2xvbmVkUGFyYW07CiAgICAgICAgfQogICAgfQogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ1N0cmluZ0xpc3RQYXJhbWV0ZXInLCBTdHJpbmdMaXN0UGFyYW1ldGVyKTsKICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdQcm9wZXJ0eV9TdHJpbmdMaXN0JywgU3RyaW5nTGlzdFBhcmFtZXRlcik7CgogICAgLyoqCiAgICAgKiBBIHBhcmFtZXRlciBmb3Igc3RvcmluZyBhbiBhcnJheSBvZiBzdHJpbmcgdmFsdWVzLgogICAgICoKICAgICAqIEBleHRlbmRzIFBhcmFtZXRlcgogICAgICovCiAgICBjbGFzcyBGbG9hdDMyQXJyYXlQYXJhbWV0ZXIgZXh0ZW5kcyBQYXJhbWV0ZXIgewogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIHN0cmluZyBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWF0ZXJpYWwgY29sb3IgcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKG5hbWUgPSAnJywgdmFsdWUgPSBuZXcgRmxvYXQzMkFycmF5KCkpIHsKICAgICAgICAgICAgc3VwZXIobmFtZSwgdmFsdWUsICdGbG9hdFtdJyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEV4dHJhY3RzIHRoZSBzdHJpbmcgdmFsdWUgZnJvbSBhIGJ1ZmZlciwgdXBkYXRpbmcgY3VycmVudCBwYXJhbWV0ZXIgc3RhdGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0ge0JpblJlYWRlcn0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0ge29iamVjdH0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHRoaXMudmFsdWUgPSByZWFkZXIubG9hZEZsb2F0MzJBcnJheSgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdG9KU09OIG1ldGhvZCBzZXJpYWxpemVzIHRoaXMgaW5zdGFuY2UgYXMgYSBKU09OLgogICAgICAgICAqIEl0IGNhbiBiZSB1c2VkIGZvciBwZXJzaXN0ZW5jZSwgZGF0YSB0cmFuc2ZlciwgZXRjLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqIEByZXR1cm4ge1JlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCB1bmRlZmluZWQ+fSAtIFJldHVybnMgdGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6IHRoaXMuZ2V0Q2xhc3NOYW1lKCksIG5hbWU6IHRoaXMubmFtZSwgdmFsdWU6IHRoaXMudmFsdWUgfTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGZyb21KU09OIG1ldGhvZCB0YWtlcyBhIEpTT04gYW5kIGRlc2VyaWFsaXplcyBpbnRvIGFuIGluc3RhbmNlIG9mIHRoaXMgdHlwZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IHVuZGVmaW5lZD59IGogLSBUaGUganNvbiBvYmplY3QgdGhpcyBpdGVtIG11c3QgZGVjb2RlLgogICAgICAgICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59IGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBmcm9tSlNPTihqLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBqLnZhbHVlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgY2xvbmUgbWV0aG9kIGNvbnN0cnVjdHMgYSBuZXcgc3RyaW5nIHBhcmFtZXRlciwgY29waWVzIGl0cyB2YWx1ZXMKICAgICAgICAgKiBmcm9tIHRoaXMgcGFyYW1ldGVyIGFuZCByZXR1cm5zIGl0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiB7RmxvYXQzMkFycmF5UGFyYW1ldGVyfSAtIFJldHVybnMgYSBuZXcgc3RyaW5nIHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgY29uc3QgY2xvbmVkUGFyYW0gPSBuZXcgRmxvYXQzMkFycmF5UGFyYW1ldGVyKHRoaXMubmFtZSwgdGhpcy52YWx1ZSk7CiAgICAgICAgICAgIHJldHVybiBjbG9uZWRQYXJhbTsKICAgICAgICB9CiAgICB9CiAgICBSZWdpc3RyeS5yZWdpc3RlcignRmxvYXQzMkFycmF5UGFyYW1ldGVyJywgRmxvYXQzMkFycmF5UGFyYW1ldGVyKTsKICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdQcm9wZXJ0eV9GbG9hdDMyQXJyYXknLCBGbG9hdDMyQXJyYXlQYXJhbWV0ZXIpOwoKICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFycyAqLwogICAgLyoqCiAgICAgKiBBIFBhcmFtZXRlciBmb3Igc3RvcmluZyBsaXN0KGFycmF5KSB2YWx1ZXMuCiAgICAgKgogICAgICogaS5lLjoKICAgICAqIGBgYGphdmFzY3JpcHQKICAgICAqIGNvbnN0IGxpc3RQYXJhbSA9IG5ldyBMaXN0UGFyYW1ldGVyKCdNeUxpc3QnLCBHZWFyUGFyYW1ldGVyKQogICAgICogLy8nbXlQYXJhbWV0ZXJPd25lckl0ZW0nIGlzIGFuIGluc3RhbmNlIG9mIGEgJ1BhcmFtZXRlck93bmVyJyBjbGFzcy4KICAgICAqIC8vIFJlbWVtYmVyIHRoYXQgb25seSAnUGFyYW1ldGVyT3duZXInIGFuZCBjbGFzc2VzIHRoYXQgZXh0ZW5kIGZyb20gaXQgY2FuIGhvc3QgJ1BhcmFtZXRlcicgb2JqZWN0cy4KICAgICAqIG15UGFyYW1ldGVyT3duZXJJdGVtLmFkZFBhcmFtZXRlcihsaXN0UGFyYW0pCiAgICAgKiBgYGAKICAgICAqCiAgICAgKiAqKkV2ZW50cyoqCiAgICAgKiAqICoqdmFsdWVDaGFuZ2VkOioqIFRyaWdnZXJlZCB3aGVuIHNldHRpbmcgYSB2YWx1ZSBjaGFuZ2VzIGluIHRoZSBhcnJheShpbnNlcnQsIGFkZCwgcmVtb3ZlKS4KICAgICAqICogKiplbGVtZW50QWRkZWQ6KiogVHJpZ2dlcmVkIHdoZW4gYW4gZWxlbWVudCBpcyBhZGRlZCB0byB0aGUgYXJyYXkoYWRkLCBpbnNlcnQpLgogICAgICogKiAqKmVsZW1lbnRSZW1vdmVkOioqIFRyaWdnZXJlZCB3aGVuIGFuIGVsZW1lbnQgaXMgcmVtb3ZlZCBmcm9tIHRoZSBhcnJheQogICAgICoKICAgICAqIEBleHRlbmRzIFBhcmFtZXRlcgogICAgICovCiAgICBjbGFzcyBMaXN0UGFyYW1ldGVyIGV4dGVuZHMgUGFyYW1ldGVyIHsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgYSBsaXN0IHBhcmFtZXRlci4KICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBsaXN0IHBhcmFtZXRlci4KICAgICAgICAgKiBAcGFyYW0gZGF0YVR5cGUgLSBUaGUgZGF0YVR5cGUgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IobmFtZSA9ICcnLCBkYXRhVHlwZSkgewogICAgICAgICAgICBzdXBlcihuYW1lLCBbXSwgZGF0YVR5cGUpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZmlsdGVyIG1ldGhvZC4KICAgICAgICAgKiBAcGFyYW0gaXRlbSAtIFRoZSBpdGVtIHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqCiAgICAgICAgICogQHByaXZhdGUKICAgICAgICAgKi8KICAgICAgICBmaWx0ZXIoaXRlbSkgewogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgY291bnQgb2YgaXRlbXMgaW4gdGhlIGFycmF5LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0Q291bnQoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlPy5sZW5ndGggfHwgMDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB2YWx1ZSBmcm9tIHRoZSBhcnJheSBpbiB0aGUgc3BlY2lmaWVkIGluZGV4LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gVGhlIGluZGV4IHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldEVsZW1lbnQoaW5kZXgpIHsKICAgICAgICAgICAgaWYgKCF0aGlzLnZhbHVlKQogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgYSB2YWx1ZSBpbiB0aGUgc3BlY2lmaWVkIGFycmF5J3MgaW5kZXguCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdmFsdWUuCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldEVsZW1lbnQoaW5kZXgsIHZhbHVlKSB7CiAgICAgICAgICAgIGlmICghdGhpcy52YWx1ZSkKICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSBbXTsKICAgICAgICAgICAgdGhpcy52YWx1ZVtpbmRleF0gPSB2YWx1ZTsKICAgICAgICAgICAgdGhpcy5lbWl0KCd2YWx1ZUNoYW5nZWQnKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQWRkcyBhIG5ldyBlbGVtZW50IGF0IHRoZSBlbmQgb2YgdGhlIGFycmF5IHBpbGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gZWxlbSAtIFRoZSBlbGVtIHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGFkZEVsZW1lbnQoZWxlbSkgewogICAgICAgICAgICBpZiAoKCFlbGVtICYmIGVsZW0gIT0gMCkgfHwgIXRoaXMuZmlsdGVyKGVsZW0pKQogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICBpZiAoIXRoaXMudmFsdWUpCiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gW107CiAgICAgICAgICAgIHRoaXMudmFsdWUucHVzaChlbGVtKTsKICAgICAgICAgICAgdGhpcy5lbWl0KCdlbGVtZW50QWRkZWQnLCB7IGVsZW0sIGluZGV4OiB0aGlzLnZhbHVlLmxlbmd0aCAtIDEgfSk7CiAgICAgICAgICAgIHRoaXMuZW1pdCgndmFsdWVDaGFuZ2VkJyk7CiAgICAgICAgICAgIHJldHVybiBlbGVtOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZW1vdmVzIGFuIGFycmF5IGVsZW1lbnQgZnJvbSB0aGUgc3BlY2lmaWVkIGluZGV4CiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgcmVtb3ZlRWxlbWVudChpbmRleCkgewogICAgICAgICAgICBpZiAoIXRoaXMudmFsdWUpCiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gW107CiAgICAgICAgICAgIGNvbnN0IGVsZW0gPSB0aGlzLnZhbHVlW2luZGV4XTsKICAgICAgICAgICAgdGhpcy52YWx1ZS5zcGxpY2UoaW5kZXgsIDEpOwogICAgICAgICAgICB0aGlzLmVtaXQoJ2VsZW1lbnRSZW1vdmVkJywgeyBlbGVtLCBpbmRleCB9KTsKICAgICAgICAgICAgdGhpcy5lbWl0KCd2YWx1ZUNoYW5nZWQnKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogSW5zZXJ0cyBhIG5ldyBlbGVtZW50IGluIHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGVsZW0gLSBUaGUgZWxlbSB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBpbnNlcnRFbGVtZW50KGluZGV4LCBlbGVtKSB7CiAgICAgICAgICAgIGlmICghdGhpcy52YWx1ZSB8fCAhdGhpcy5maWx0ZXIoZWxlbSkpCiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIHRoaXMudmFsdWUuc3BsaWNlKGluZGV4LCAwLCBlbGVtKTsKICAgICAgICAgICAgdGhpcy5lbWl0KCdlbGVtZW50QWRkZWQnLCB7IGVsZW0sIGluZGV4IH0pOwogICAgICAgICAgICB0aGlzLmVtaXQoJ3ZhbHVlQ2hhbmdlZCcpOwogICAgICAgIH0KICAgICAgICBzZXRWYWx1ZSh2YWx1ZSkgewogICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkodmFsdWUpKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHZhbHVlIHByb3ZpZGVkIGlzIG5vdCBhbiBhcnJheS4gQ2hlY2sgdGhlIHNvdXJjZSBvZiB0aGlzIHZhbHVlYCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3VwZXIuc2V0VmFsdWUodmFsdWUpOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdG9KU09OIG1ldGhvZCBlbmNvZGVzIHRoaXMgdHlwZSBhcyBhIGpzb24gb2JqZWN0IGZvciBwZXJzaXN0ZW5jZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIGNvbnN0IGl0ZW1zID0gW107CiAgICAgICAgICAgIGlmICh0aGlzLnZhbHVlKSB7CiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHAgb2YgdGhpcy52YWx1ZSkgewogICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5kYXRhVHlwZSA9PT0gJ3N0cmluZycpCiAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1zLnB1c2gocCk7CiAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICBpdGVtcy5wdXNoKHAudG9KU09OKGNvbnRleHQpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgdHlwZTogdGhpcy5nZXRDbGFzc05hbWUoKSwKICAgICAgICAgICAgICAgIG5hbWU6IHRoaXMubmFtZSwKICAgICAgICAgICAgICAgIHZhbHVlOiBpdGVtcywKICAgICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGZyb21KU09OIG1ldGhvZCBkZWNvZGVzIGEganNvbiBvYmplY3QgZm9yIHRoaXMgdHlwZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBqIC0gVGhlIGpzb24gb2JqZWN0IHRoaXMgaXRlbSBtdXN0IGRlY29kZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGZyb21KU09OKGosIGNvbnRleHQpIHsKICAgICAgICAgICAgaWYgKGouaXRlbXMgPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0ludmFsaWQgUGFyYW1ldGVyIEpTT04nKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCB2YWx1ZSA9IFtdOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGouaXRlbXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIGxldCBlbGVtOwogICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmRhdGFUeXBlID09PSAnc3RyaW5nJykgewogICAgICAgICAgICAgICAgICAgIGVsZW0gPSBqLml0ZW1zW2ldOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmRhdGFUeXBlKQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyAnTm8gRGF0YVR5cGUnOwogICAgICAgICAgICAgICAgICAgIGVsZW0gPSBSZWdpc3RyeS5jb25zdHJ1Y3RDbGFzcyh0aGlzLmRhdGFUeXBlKTsKICAgICAgICAgICAgICAgICAgICBlbGVtLmZyb21KU09OKGouaXRlbXNbaV0sIGNvbnRleHQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFsdWUucHVzaChlbGVtKTsKICAgICAgICAgICAgICAgIHRoaXMuZW1pdCgnZWxlbWVudEFkZGVkJywgeyBlbGVtLCBpbmRleDogdGhpcy52YWx1ZS5sZW5ndGggLSAxIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIENsb25lIGFuZCBEZXN0cm95CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGNsb25lIG1ldGhvZCBjb25zdHJ1Y3RzIGEgbmV3IGxpc3QgcGFyYW1ldGVyLCBjb3BpZXMgaXRzIHZhbHVlcwogICAgICAgICAqIGZyb20gdGhpcyBwYXJhbWV0ZXIgYW5kIHJldHVybnMgaXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIG5ldyBsaXN0IHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgY29uc3QgY2xvbmVkVmFsdWUgPSB0aGlzLnZhbHVlID8gdGhpcy52YWx1ZS5zbGljZSgwKSA6IFtdOwogICAgICAgICAgICBpZiAoIXRoaXMuZGF0YVR5cGUpCiAgICAgICAgICAgICAgICB0aHJvdyAnVGhpcyBwYXJhbWV0ZXIgZG9lcyBub3QgaGF2ZSBhIERhdGFUeXBlJzsKICAgICAgICAgICAgY29uc3QgY2xvbmVkUGFyYW0gPSBuZXcgTGlzdFBhcmFtZXRlcih0aGlzLm5hbWUsIHRoaXMuZGF0YVR5cGUpOwogICAgICAgICAgICBjbG9uZWRQYXJhbS5zZXRWYWx1ZShjbG9uZWRWYWx1ZSk7CiAgICAgICAgICAgIHJldHVybiBjbG9uZWRQYXJhbTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGRlc3Ryb3kgaXMgY2FsbGVkIGJ5IHRoZSBzeXN0ZW0gdG8gY2F1c2UgZXhwbGljaXQgcmVzb3VyY2VzIGNsZWFudXAuCiAgICAgICAgICogVXNlcnMgc2hvdWxkIG5ldmVyIG5lZWQgdG8gY2FsbCB0aGlzIG1ldGhvZCBkaXJlY3RseS4KICAgICAgICAgKi8KICAgICAgICBkZXN0cm95KCkgewogICAgICAgICAgICBpZiAoIXRoaXMudmFsdWUpCiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52YWx1ZS5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgaWYgKHRoaXMudmFsdWVbaV0gaW5zdGFuY2VvZiBQYXJhbWV0ZXIpCiAgICAgICAgICAgICAgICAgICAgdGhpcy52YWx1ZVtpXS5kZXN0cm95KCk7CiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUVsZW1lbnQoaSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICBSZWdpc3RyeS5yZWdpc3RlcignTGlzdFBhcmFtZXRlcicsIExpc3RQYXJhbWV0ZXIpOwoKICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9leHBsaWNpdC1tb2R1bGUtYm91bmRhcnktdHlwZXMgKi8KICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIHNwZWNpZmljIHR5cGUgb2YgcGFyYW1ldGVyLCB0aGF0IHN0b3JlcyBtdWx0aXBsZSBwYXJhbWV0ZXJzIGluIG9iamVjdCBmb3JtYXQuCiAgICAgKgogICAgICogaS5lLjoKICAgICAqIGBgYGphdmFzY3JpcHQKICAgICAqIGNvbnN0IHN0cnVjdFBhcmFtID0gbmV3IFN0cnVjdFBhcmFtZXRlcignTXlTdHJ1Y3RQYXJhbScpCiAgICAgKiAvLydteVBhcmFtZXRlck93bmVySXRlbScgaXMgYW4gaW5zdGFuY2Ugb2YgYSAnUGFyYW1ldGVyT3duZXInIGNsYXNzLgogICAgICogLy8gUmVtZW1iZXIgdGhhdCBvbmx5ICdQYXJhbWV0ZXJPd25lcicgYW5kIGNsYXNzZXMgdGhhdCBleHRlbmQgZnJvbSBpdCBjYW4gaG9zdCAnUGFyYW1ldGVyJyBvYmplY3RzLgogICAgICogbXlQYXJhbWV0ZXJPd25lckl0ZW0uYWRkUGFyYW1ldGVyKHN0cnVjdFBhcmFtKQogICAgICogYGBgCiAgICAgKgogICAgICogKipFdmVudHMqKgogICAgICogKiAqKnZhbHVlQ2hhbmdlZDoqKiBUcmlnZ2VyZWQgd2hlbmV2ZXIgcGFyYW1ldGVyJ3MgdmFsdWUgY2hhbmdlcy4KICAgICAqCiAgICAgKiBAZXh0ZW5kcyBQYXJhbWV0ZXIKICAgICAqLwogICAgY2xhc3MgU3RydWN0UGFyYW1ldGVyIGV4dGVuZHMgUGFyYW1ldGVyIHsKICAgICAgICBtZW1iZXJzOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIHN0cnVjdCBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgc3RydWN0IHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICAgICAgICAgIHN1cGVyKG5hbWUsIHt9LCAnU3RydWN0Jyk7CiAgICAgICAgICAgIHRoaXMubWVtYmVycyA9IFtdOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgX2FkZE1lbWJlciBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIHBhcmFtZXRlciAtIFRoZSBwYXJhbWV0ZXIgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICogQHByaXZhdGUKICAgICAgICAgKi8KICAgICAgICBhZGRNZW1iZXIocGFyYW1ldGVyKSB7CiAgICAgICAgICAgIGlmICh0aGlzLnZhbHVlKQogICAgICAgICAgICAgICAgdGhpcy52YWx1ZVtwYXJhbWV0ZXIuZ2V0TmFtZSgpXSA9IHBhcmFtZXRlci52YWx1ZTsKICAgICAgICAgICAgcGFyYW1ldGVyLm9uKCd2YWx1ZUNoYW5nZWQnLCAoKSA9PiB7CiAgICAgICAgICAgICAgICBpZiAodGhpcy52YWx1ZSkKICAgICAgICAgICAgICAgICAgICB0aGlzLnZhbHVlW3BhcmFtZXRlci5nZXROYW1lKCldID0gcGFyYW1ldGVyLnZhbHVlOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgdGhpcy5tZW1iZXJzLnB1c2gocGFyYW1ldGVyKTsKICAgICAgICAgICAgdGhpcy5lbWl0KCd2YWx1ZUNoYW5nZWQnKTsKICAgICAgICAgICAgcmV0dXJuIHBhcmFtZXRlcjsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGdldFBhcmFtZXRlciBtZXRob2QuCiAgICAgICAgICoKICAgICAgICAgKiBAcHJpdmF0ZQogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIHBhcmFtZXRlciBuYW1lLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldFBhcmFtZXRlcihuYW1lKSB7CiAgICAgICAgICAgIGZvciAoY29uc3QgcCBvZiB0aGlzLm1lbWJlcnMpIHsKICAgICAgICAgICAgICAgIGlmIChwLmdldE5hbWUoKSA9PSBuYW1lKQogICAgICAgICAgICAgICAgICAgIHJldHVybiBwOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIExvb2tzIGZvciBhIG1lbWJlciBwYXJhbWV0ZXIgd2l0aCB0aGUgc3BlY2lmaWVkIG5hbWUgYW5kIHJldHVybnMgaXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBwYXJhbWV0ZXIgbmFtZS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRNZW1iZXIobmFtZSkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRQYXJhbWV0ZXIobmFtZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIG5hbWUgb2YgYWxsIHBhcmFtZXRlcnMgaW4gU3RydWN0UGFyYW1ldGVyLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0TWVtYmVyTmFtZXMoKSB7CiAgICAgICAgICAgIGNvbnN0IG5hbWVzID0gW107CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5tZW1iZXJzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBjb25zdCBtZW1iZXIgPSB0aGlzLm1lbWJlcnNbaV07CiAgICAgICAgICAgICAgICBpZiAobWVtYmVyICE9IG51bGwpCiAgICAgICAgICAgICAgICAgICAgbmFtZXNbaV0gPSBtZW1iZXIuZ2V0TmFtZSgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBuYW1lczsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIFBlcnNpc3RlbmNlCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHRvSlNPTiBtZXRob2QgZW5jb2RlcyB0aGlzIHR5cGUgYXMgYSBqc29uIG9iamVjdCBmb3IgcGVyc2lzdGVuY2UuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBqc29uIG9iamVjdC4KICAgICAgICAgKi8KICAgICAgICB0b0pTT04oY29udGV4dCkgewogICAgICAgICAgICBjb25zdCBtZW1iZXJzID0gW107CiAgICAgICAgICAgIGZvciAoY29uc3QgcCBvZiB0aGlzLm1lbWJlcnMpCiAgICAgICAgICAgICAgICBtZW1iZXJzLnB1c2gocC50b0pTT04oY29udGV4dCkpOwogICAgICAgICAgICByZXR1cm4geyB0eXBlOiB0aGlzLmdldENsYXNzTmFtZSgpLCBuYW1lOiB0aGlzLm5hbWUsIG1lbWJlcnMgfTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGZyb21KU09OIG1ldGhvZCBkZWNvZGVzIGEganNvbiBvYmplY3QgZm9yIHRoaXMgdHlwZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBqIC0gVGhlIGpzb24gb2JqZWN0IHRoaXMgaXRlbSBtdXN0IGRlY29kZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGZyb21KU09OKGosIGNvbnRleHQpIHsKICAgICAgICAgICAgaWYgKGoubWVtYmVycyA9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignSW52YWxpZCBQYXJhbWV0ZXIgSlNPTicpOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgai5tZW1iZXJzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBpZiAoai5tZW1iZXJzW2ldKSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZW1iZXJzW2ldLmZyb21KU09OKGoubWVtYmVyc1tpXSwgY29udGV4dCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5uYW1lID0gai5uYW1lOwogICAgICAgIH0KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgY29uc3QgY2xvbmVkUGFyYW0gPSBuZXcgU3RydWN0UGFyYW1ldGVyKHRoaXMubmFtZSk7CiAgICAgICAgICAgIHJldHVybiBjbG9uZWRQYXJhbTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIERlc3Ryb3kKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZGVzdHJveSBpcyBjYWxsZWQgYnkgdGhlIHN5c3RlbSB0byBjYXVzZSBleHBsaWNpdCByZXNvdXJjZXMgY2xlYW51cC4KICAgICAgICAgKiBVc2VycyBzaG91bGQgbmV2ZXIgbmVlZCB0byBjYWxsIHRoaXMgbWV0aG9kIGRpcmVjdGx5LgogICAgICAgICAqLwogICAgICAgIGRlc3Ryb3koKSB7CiAgICAgICAgICAgIGZvciAoY29uc3QgcCBvZiB0aGlzLm1lbWJlcnMpIHsKICAgICAgICAgICAgICAgIC8vIFRPRE86IG5vdCBzdXJlIGFib3V0IHRoaXMuIEkgYWRkZWQgYSBkby1ub3RoaW5nIGRlc3Ryb3kgbWV0aG9kIGluIFBhcmFtZXRlcjxUPiB0byBiZSBvdmVyd3JpdHRlbgogICAgICAgICAgICAgICAgLy8gc2luY2Ugb25seSBzb21lIHN1YmNsYXNzZXMgdXNlIGRlc3Ryb3kuCiAgICAgICAgICAgICAgICBwLmRlc3Ryb3koKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdTdHJ1Y3RQYXJhbWV0ZXInLCBTdHJ1Y3RQYXJhbWV0ZXIpOwoKICAgIC8qKiBDbGFzcyByZXByZXNlbnRpbmcgYW4gb3BlcmF0b3Igb3V0cHV0LgogICAgICogQGV4dGVuZHMgRXZlbnRFbWl0dGVyCiAgICAgKi8KICAgIGNsYXNzIE9wZXJhdG9yT3V0cHV0IHsKICAgICAgICBuYW1lOwogICAgICAgIG1vZGU7CiAgICAgICAgb3AgPSBudWxsOwogICAgICAgIHBhcmFtOwogICAgICAgIHBhcmFtQmluZEluZGV4OwogICAgICAgIGRldGFjaGVkOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhbiBvcGVyYXRvciBvdXRwdXQuCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gb3BlcmF0b3JPdXRwdXRNb2RlIC0gVGhlIG1vZGUgd2hpY2ggdGhlIE9wZXJhdG9yT3V0cHV0IHVzZXMgdG8gYmluZCB0byBpdHMgdGFyZ2V0IHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3RvcihuYW1lLCBvcGVyYXRvck91dHB1dE1vZGUgPSBPcGVyYXRvck91dHB1dE1vZGUuT1BfV1JJVEUpIHsKICAgICAgICAgICAgdGhpcy5uYW1lID0gbmFtZTsKICAgICAgICAgICAgdGhpcy5tb2RlID0gb3BlcmF0b3JPdXRwdXRNb2RlOwogICAgICAgICAgICB0aGlzLnBhcmFtID0gdW5kZWZpbmVkOwogICAgICAgICAgICB0aGlzLnBhcmFtQmluZEluZGV4ID0gLTE7CiAgICAgICAgICAgIHRoaXMuZGV0YWNoZWQgPSBmYWxzZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyBvcGVyYXRvciB0aGF0IG93bnMgdGhpcyBvdXRwdXQuIENhbGxlZCBieSB0aGUgb3BlcmF0b3Igd2hlbiBhZGRpbmcgb3V0cHV0cwogICAgICAgICAqIEBwYXJhbSBvcCAtIFRoZSBvcGVyYXRvciBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgc2V0T3BlcmF0b3Iob3ApIHsKICAgICAgICAgICAgdGhpcy5vcCA9IG9wOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIG9wZXJhdG9yIHRoYXQgb3ducyB0aGlzIG91dHB1dC4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIG9wZXJhdG9yIG9iamVjdC4KICAgICAgICAgKi8KICAgICAgICBnZXRPcGVyYXRvcigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMub3A7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgbW9kZSB0aGF0IHRoZSBvdXRwdXQgd3JpdGVzIHRvIGJlIHBhcmFtZXRlci4gTXVzdCBiZSBhIG51bWJlciBmcm9tIE9wZXJhdG9yT3V0cHV0TW9kZQogICAgICAgICAqIEByZXR1cm4gLSBUaGUgbW9kZSB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRNb2RlKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5tb2RlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBvdXRwdXQgaXMgY29ubmVjdGVkIHRvIGEgcGFyYW1ldGVyLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGlzQ29ubmVjdGVkKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJhbSAhPSB1bmRlZmluZWQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBnZXRQYXJhbSBtZXRob2QuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0UGFyYW0oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmFtOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHRoZSBQYXJhbWV0ZXIgZm9yIHRoaXMgb3V0cHV0IHRvIHdyaXRlIHRvLgogICAgICAgICAqIEBwYXJhbSBwYXJhbSAtIFRoZSBwYXJhbSB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdG8gYmluZCBhdCBpbiB0aGUgUGFyYW1ldGVyLgogICAgICAgICAqLwogICAgICAgIHNldFBhcmFtKHBhcmFtLCBpbmRleCA9IC0xKSB7CiAgICAgICAgICAgIGlmICh0aGlzLnBhcmFtKSB7CiAgICAgICAgICAgICAgICB0aGlzLnBhcmFtLnVuYmluZE9wZXJhdG9yT3V0cHV0KHRoaXMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMucGFyYW0gPSBwYXJhbTsKICAgICAgICAgICAgaWYgKHRoaXMucGFyYW0pIHsKICAgICAgICAgICAgICAgIHRoaXMucGFyYW1CaW5kSW5kZXggPSB0aGlzLnBhcmFtLmJpbmRPcGVyYXRvck91dHB1dCh0aGlzLCBpbmRleCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGJpbmRpbmcgb24gdGhlIHBhcmFtZXRlciBvZiB0aGlzIE9wZXJhdG9yT3V0cHV0CiAgICAgICAgICogdXAgdG8gZGF0ZS4KICAgICAgICAgKiBAcmV0dXJuIGluZGV4IC0gVGhlIGluZGV4IG9mIHRoZSBiaW5kaW5nIG9uIHRoZSBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgZ2V0UGFyYW1CaW5kSW5kZXgoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmFtQmluZEluZGV4OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBJZiBiaW5kaW5ncyBjaGFuZ2Ugb24gYSBQYXJhbWV0ZXIsIGl0IHdpbGwgY2FsbCB0aGlzIG1ldGhvZCB0byBlbnN1cmUgdGhlIG91dHB1dCBpbmRleCBpcwogICAgICAgICAqIHVwIHRvIGRhdGUuCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gVGhlIGluZGV4IG9mIHRoZSBiaW5kaW5nIG9uIHRoZSBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgc2V0UGFyYW1CaW5kSW5kZXgoaW5kZXgpIHsKICAgICAgICAgICAgdGhpcy5wYXJhbUJpbmRJbmRleCA9IGluZGV4OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBQcm9wYWdhdGVzIGRpcnR5IHRvIHRoZSBjb25uZWN0ZWQgcGFyYW1ldGVyLgogICAgICAgICAqLwogICAgICAgIHNldERpcnR5KCkgewogICAgICAgICAgICBpZiAodGhpcy5wYXJhbSkgewogICAgICAgICAgICAgICAgdGhpcy5wYXJhbS5zZXREaXJ0eSh0aGlzLnBhcmFtQmluZEluZGV4KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZ2V0VmFsdWUgbWV0aG9kLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldFZhbHVlKCkgewogICAgICAgICAgICBpZiAodGhpcy5wYXJhbSkgewogICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyYW0uZ2V0VmFsdWVGcm9tT3AodGhpcy5wYXJhbUJpbmRJbmRleCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHRzLW1pZ3JhdGUoMjU1NCkgRklYTUU6IEV4cGVjdGVkIDAtMSBhcmd1bWVudHMsIGJ1dCBnb3QgMi4KICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGNhbGwgZ2V0VmFsdWUgb24gT3BlcmF0b3JPdXRwdXQgdGhhdCBpcyBub3QgY29ubmVjdGVkOicsIHRoaXMubmFtZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogV2hlbiB0aGUgdmFsdWUgb24gYSBQYXJhbWV0ZXIgaXMgbW9kaWZpZWQgYnkgYSB1c2VyIGJ5IGNhbGxpbmcgJ3NldFZhbHVlLAogICAgICAgICAqIHRoZW4gaWYgYW55IG9wZXJhdG9ycyBhcmUgYm91bmQsIHRoZSB2YWx1ZSBvZiB0aGUgUGFyYW1ldGVyIGNhbm5vdCBiZSBtb2RpZmllZAogICAgICAgICAqIGRpcmVjdGx5IGFzIGl0IGlzIHRoZSByZXN1bHQgb2YgYSBjb21wdXRhdGlvbi4gSW5zdGVhZCwgdGhlIFBhcmFtZXRlciBjYWxscwogICAgICAgICAqICdiYWNrUHJvcGFnYXRlVmFsdWUnIG9uIHRoZSBPcGVyYXRvciB0byBjYXVzZSB0aGUgT3BlcmF0b3IgdG8gaGFuZGxlIHByb3BhZ2F0aW5nCiAgICAgICAgICogdGhlIHZhbHVlIHRvIG9uZSBvciBtb3JlIG9mIGl0cyBpbnB1dHMuCiAgICAgICAgICogdG8gaXRzIGlucHV0cy4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgcGFyYW0uCiAgICAgICAgICogQHJldHVybiAtIFRoZSBtb2RpZmllZCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBiYWNrUHJvcGFnYXRlVmFsdWUodmFsdWUpIHsKICAgICAgICAgICAgaWYgKHRoaXMub3ApIHsKICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5vcC5iYWNrUHJvcGFnYXRlVmFsdWUodmFsdWUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHNldENsZWFuIG1ldGhvZC4KICAgICAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgcGFyYW0uCiAgICAgICAgICovCiAgICAgICAgc2V0Q2xlYW4odmFsdWUpIHsKICAgICAgICAgICAgaWYgKHRoaXMucGFyYW0pIHsKICAgICAgICAgICAgICAgIHRoaXMucGFyYW0uc2V0Q2xlYW5Gcm9tT3AodmFsdWUsIHRoaXMucGFyYW1CaW5kSW5kZXgpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQZXJzaXN0ZW5jZQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSB0b0pTT04gbWV0aG9kIGVuY29kZXMgdGhpcyB0eXBlIGFzIGEganNvbiBvYmplY3QgZm9yIHBlcnNpc3RlbmNlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIGNvbnN0IHBhcmFtUGF0aCA9IHRoaXMucGFyYW0gPyB0aGlzLnBhcmFtLmdldFBhdGgoKSA6ICcnOwogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgbmFtZTogdGhpcy5uYW1lLAogICAgICAgICAgICAgICAgcGFyYW1QYXRoOiBjb250ZXh0ICYmIGNvbnRleHQubWFrZVJlbGF0aXZlID8gY29udGV4dC5tYWtlUmVsYXRpdmUocGFyYW1QYXRoKSA6IHBhcmFtUGF0aCwKICAgICAgICAgICAgICAgIHBhcmFtQmluZEluZGV4OiB0aGlzLnBhcmFtQmluZEluZGV4LAogICAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIGRlY29kZXMgYSBqc29uIG9iamVjdCBmb3IgdGhpcyB0eXBlLgogICAgICAgICAqIEBwYXJhbSBqIC0gVGhlIGpzb24gb2JqZWN0IHRoaXMgaXRlbSBtdXN0IGRlY29kZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGZyb21KU09OKGosIGNvbnRleHQpIHsKICAgICAgICAgICAgaWYgKGoucGFyYW1QYXRoKSB7CiAgICAgICAgICAgICAgICAvLyBOb3RlOiB0aGUgdHJlZSBzaG91bGQgaGF2ZSBmdWxseSBsb2FkZWQgYnkgdGhlIHRpbWUgd2UgYXJlIGxvYWRpbmcgb3BlcmF0b3JzCiAgICAgICAgICAgICAgICAvLyBldmVuIG5ldyBpdGVtcyBhbmQgZ3JvdXBzIHNob3VsZCBoYXZlIGJlZW4gY3JlYXRlZC4gT3BlcmF0b3JzIGFuZCBzdGF0ZSBtYWNoaW5lcwogICAgICAgICAgICAgICAgLy8gYXJlIGxvYWRlZCBsYXN0LgogICAgICAgICAgICAgICAgY29udGV4dD8ucmVzb2x2ZVBhdGgoai5wYXJhbVBhdGgsIChwYXJhbSkgPT4gewogICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGFyYW0ocGFyYW0sIGoucGFyYW1CaW5kSW5kZXgpOwogICAgICAgICAgICAgICAgfSwgKHJlYXNvbikgPT4gewogICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybigiT3BlcmF0b3JPdXRwdXQ6ICciICsgdGhpcy5uYW1lICsgIicuIFVuYWJsZSB0byBjb25uZWN0IHRvOiIgKyBqLnBhcmFtUGF0aCk7CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZGV0YWNoIG1ldGhvZCBpcyBjYWxsZWQgd2hlbiBhbiBvcGVyYXRvciBpcyBiZWluZyByZW1vdmVkIGZyb20gdGhlIHNjZW5lIHRyZWUuCiAgICAgICAgICogSXQgcmVtb3ZlcyBhbGwgY29ubmVjdGlvbnMgdG8gcGFyYW1ldGVycyBpbiB0aGUgc2NlbmUuCiAgICAgICAgICovCiAgICAgICAgZGV0YWNoKCkgewogICAgICAgICAgICAvLyBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuIHdlIHdhbnQgdG8gc3VzcGVuZCBhbiBvcGVyYXRvcgogICAgICAgICAgICAvLyBmcm9tIGZ1bmN0aW9uaW5nIGJlY2F1c2UgaXQgaXMgZGVsZXRlZCBhbmQgb24gdGhlIHVuZG8gc3RhY2suCiAgICAgICAgICAgIC8vIE9uY2Ugb3BlcmF0b3JzIGhhdmUgcGVyc2lzdGVudCBjb25uZWN0aW9ucywKICAgICAgICAgICAgLy8gd2Ugd2lsbCBzaW1wbHkgdW5pbnN0YWxsIHRoZSBvdXRwdXQgZnJvbSB0aGUgcGFyYW1ldGVyLgogICAgICAgICAgICB0aGlzLmRldGFjaGVkID0gdHJ1ZTsKICAgICAgICAgICAgdGhpcy5wYXJhbUJpbmRJbmRleCA9IHRoaXMucGFyYW0gPyB0aGlzLnBhcmFtLnVuYmluZE9wZXJhdG9yT3V0cHV0KHRoaXMpIDogLTE7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSByZWF0dGFjaCBtZXRob2QgY2FuIGJlIGNhbGxlZCB3aGVuIHJlLWluc3RhdGluZyBhbiBvcGVyYXRvciBpbiB0aGUgc2NlbmUuCiAgICAgICAgICovCiAgICAgICAgcmVhdHRhY2goKSB7CiAgICAgICAgICAgIHRoaXMuZGV0YWNoZWQgPSBmYWxzZTsKICAgICAgICAgICAgaWYgKHRoaXMucGFyYW0pIHsKICAgICAgICAgICAgICAgIHRoaXMucGFyYW1CaW5kSW5kZXggPSB0aGlzLnBhcmFtLmJpbmRPcGVyYXRvck91dHB1dCh0aGlzLCB0aGlzLnBhcmFtQmluZEluZGV4KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgcmViaW5kIHJlYmluZHMgdGhlIG91dHB1dHMgdG8gYmUgYXQgdGhlIHRvcCBvZiB0aGUgc3RhY2sgZm9yIGl0cyBwYXJhbWV0ZXIuCiAgICAgICAgICovCiAgICAgICAgcmViaW5kKCkgewogICAgICAgICAgICBpZiAodGhpcy5wYXJhbSkgewogICAgICAgICAgICAgICAgdGhpcy5wYXJhbS51bmJpbmRPcGVyYXRvck91dHB1dCh0aGlzKTsKICAgICAgICAgICAgICAgIHRoaXMucGFyYW1CaW5kSW5kZXggPSB0aGlzLnBhcmFtLmJpbmRPcGVyYXRvck91dHB1dCh0aGlzKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIGNsYXNzIFhmb09wZXJhdG9yT3V0cHV0IGV4dGVuZHMgT3BlcmF0b3JPdXRwdXQgewogICAgfQoKICAgIC8qKgogICAgICogQ2xhc3MgcmVwcmVzZW50aW5nIGFuIG9wZXJhdG9yLgogICAgICoKICAgICAqLwogICAgY2xhc3MgT3BlcmF0b3IgewogICAgICAgIG5hbWU7CiAgICAgICAgaW5wdXRzOwogICAgICAgIG91dHB1dHM7CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlIGFuIG9wZXJhdG9yLgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IobmFtZSA9ICcnKSB7CiAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICAgICAgICAgIHRoaXMuaW5wdXRzID0gbmV3IE1hcCgpOwogICAgICAgICAgICB0aGlzLm91dHB1dHMgPSBuZXcgTWFwKCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoaXMgbWV0aG9kIHNldHMgdGhlIHN0YXRlIG9mIHRoZSBvcGVyYXRvciB0byBkaXJ0eSB3aGljaCBwcm9wYWdhdGVzCiAgICAgICAgICogdG8gdGhlIG91dHB1dHMgb2YgdGhpcyBvcGVyYXRvciwgYW5kIHdoaWNoIG1heSB0aGVuIHByb3BhZ2F0ZSB0byBvdGhlcgogICAgICAgICAqIG9wZXJhdG9ycy4gV2hlbiB0aGUgc2NlbmUgaXMgY2xlYW5lZCwgd2hpY2ggdXN1YWxseSBpcyBjYXVzZWQgYnkgcmVuZGVyaW5nCiAgICAgICAgICogdGhlbiB0aGUgY2hhaW4gb2Ygb3BlcmF0b3JzIGFyZSBjbGVhbmVkIGJ5IHRyaWdnZXJpbmcgZXZhbHVhdGlvbi4KICAgICAgICAgKiBAcHJpdmF0ZQogICAgICAgICAqLwogICAgICAgIHNldERpcnR5KCkgewogICAgICAgICAgICB0aGlzLm91dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PiBvdXRwdXQuc2V0RGlydHkoKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBhZGRJbnB1dCBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIGlucHV0IC0gVGhlIG5hbWUgb2YgdGhlIGlucHV0LCBvciB0aGUgaW5wdXQgb2JqZWN0CiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgYWRkSW5wdXQoaW5wdXQpIHsKICAgICAgICAgICAgaW5wdXQuc2V0T3BlcmF0b3IodGhpcyk7CiAgICAgICAgICAgIHRoaXMuaW5wdXRzLnNldChpbnB1dC5uYW1lLCBpbnB1dCk7CiAgICAgICAgICAgIHRoaXMuc2V0RGlydHkoKTsKICAgICAgICAgICAgcmV0dXJuIGlucHV0OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgcmVtb3ZlSW5wdXQgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSBpbnB1dCAtIFRoZSBuYW1lIG9mIHRoZSBpbnB1dCwgb3IgdGhlIGlucHV0IG9iamVjdAogICAgICAgICAqLwogICAgICAgIHJlbW92ZUlucHV0KGlucHV0KSB7CiAgICAgICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT0gJ3N0cmluZycpCiAgICAgICAgICAgICAgICBpbnB1dCA9IHRoaXMuZ2V0SW5wdXQoaW5wdXQpOwogICAgICAgICAgICBpZiAoaW5wdXQuZ2V0UGFyYW0oKSkKICAgICAgICAgICAgICAgIGlucHV0LnNldFBhcmFtKHVuZGVmaW5lZCk7CiAgICAgICAgICAgIHRoaXMuaW5wdXRzLmRlbGV0ZShpbnB1dC5uYW1lKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0dGVyIGZvciB0aGUgbnVtYmVyIG9mIGlucHV0cyBpbiB0aGlzIG9wZXJhdG9yLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBudW1iZXIgb2YgaW5wdXRzLgogICAgICAgICAqLwogICAgICAgIGdldE51bUlucHV0cygpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5wdXRzLnNpemU7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBnZXRJbnB1dEJ5SW5kZXggbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRJbnB1dEJ5SW5kZXgoaW5kZXgpIHsKICAgICAgICAgICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5pbnB1dHMudmFsdWVzKCkpW2luZGV4XTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGdldElucHV0IG1ldGhvZC4KICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldElucHV0KG5hbWUpIHsKICAgICAgICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLmlucHV0cy5nZXQobmFtZSk7CiAgICAgICAgICAgIGlmICghaW5wdXQpCiAgICAgICAgICAgICAgICB0aHJvdyBgQ291bGRuJ3QgZmluZCBhbiBJbnB1dCB3aXRoIHRoZSBuYW1lIG9mICcke25hbWV9J2A7CiAgICAgICAgICAgIHJldHVybiBpbnB1dDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGFkZE91dHB1dCBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIG91dHB1dCAtIFRoZSBuYW1lIG9mIHRoZSBvdXRwdXQsIG9yIHRoZSBvdXRwdXQgb2JqZWN0CiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgYWRkT3V0cHV0KG91dHB1dCkgewogICAgICAgICAgICBvdXRwdXQuc2V0T3BlcmF0b3IodGhpcyk7CiAgICAgICAgICAgIC8vIGlmICh0aGlzLmdldE91dHB1dChvdXRwdXQubmFtZSkpIHRocm93IG5ldyBFcnJvcihgT3BlcmF0b3Igb3V0cHV0IGFscmVhZHkgZXhpc3RzICR7b3V0cHV0Lm5hbWV9YCkKICAgICAgICAgICAgdGhpcy5vdXRwdXRzLnNldChvdXRwdXQubmFtZSwgb3V0cHV0KTsKICAgICAgICAgICAgdGhpcy5zZXREaXJ0eSgpOwogICAgICAgICAgICByZXR1cm4gb3V0cHV0OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgcmVtb3ZlT3V0cHV0IG1ldGhvZC4KICAgICAgICAgKiBAcGFyYW0gb3V0cHV0IC0gVGhlIG5hbWUgb2YgdGhlIG91dHB1dCwgb3IgdGhlIG91dHB1dCBvYmplY3QKICAgICAgICAgKi8KICAgICAgICByZW1vdmVPdXRwdXQob3V0cHV0KSB7CiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3V0cHV0ID09ICdzdHJpbmcnKQogICAgICAgICAgICAgICAgb3V0cHV0ID0gdGhpcy5nZXRPdXRwdXQob3V0cHV0KTsKICAgICAgICAgICAgaWYgKCEob3V0cHV0IGluc3RhbmNlb2YgT3BlcmF0b3JPdXRwdXQpKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHJlbW92ZU91dHB1dCBvbmx5IGFjY2VwdHMgc3RyaW5nIG9yIE9wZXJhdG9ySW5wdXRgKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAob3V0cHV0LmdldFBhcmFtKCkpCiAgICAgICAgICAgICAgICBvdXRwdXQuc2V0UGFyYW0oKTsKICAgICAgICAgICAgdGhpcy5vdXRwdXRzLmRlbGV0ZShvdXRwdXQubmFtZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHRlciBmb3IgdGhlIG51bWJlciBvZiBvdXRwdXRzIGluIHRoaXMgb3BlcmF0b3IuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIG51bWJlciBvZiBvdXRwdXRzLgogICAgICAgICAqLwogICAgICAgIGdldE51bU91dHB1dHMoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLm91dHB1dHMuc2l6ZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGdldE91dHB1dEJ5SW5kZXggbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRPdXRwdXRCeUluZGV4KGluZGV4KSB7CiAgICAgICAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMub3V0cHV0cy52YWx1ZXMoKSlbaW5kZXhdOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZ2V0T3V0cHV0IG1ldGhvZC4KICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldE91dHB1dChuYW1lKSB7CiAgICAgICAgICAgIGNvbnN0IG91dHB1dCA9IHRoaXMub3V0cHV0cy5nZXQobmFtZSk7CiAgICAgICAgICAgIGlmICghb3V0cHV0KQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZG4ndCBmaW5kIGFuIE91dHB1dCB3aXRoIHRoZSBuYW1lIG9mICcke25hbWV9J2ApOwogICAgICAgICAgICByZXR1cm4gb3V0cHV0OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZXZhbHVhdGUgbWV0aG9kLgogICAgICAgICAqIENvbXB1dGVzIHRoZSB2YWx1ZXMgb2YgZWFjaCBvZiB0aGUgb3V0cHV0cyBiYXNlZCBvbiB0aGUgdmFsdWVzIG9mIHRoZSBpbnB1dHMKICAgICAgICAgKiBhbmQgdGhlIHZhbHVlcyBvZiBvdXRwdXRzIHdpdGggbW9kZSBPUF9SRUFEX1dSSVRFLgogICAgICAgICAqIFRoaXMgbWV0aG9kIG11c3QgYmUgaW1wbGVtZW50ZWQgYnkgYWxsIE9wZXJhdG9ycy4KICAgICAgICAgKi8KICAgICAgICBldmFsdWF0ZSgpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgeWV0IGltcGxlbWVudGVkJyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFdoZW4gdGhlIHZhbHVlIG9uIGEgUGFyYW1ldGVyIGlzIG1vZGlmaWVkIGJ5IGEgdXNlciBieSBjYWxsaW5nICdzZXRWYWx1ZSwKICAgICAgICAgKiB0aGVuIGlmIGFueSBvcGVyYXRvcnMgYXJlIGJvdW5kLCB0aGUgdmFsdWUgb2YgdGhlIFBhcmFtZXRlciBjYW5ub3QgYmUgbW9kaWZpZWQKICAgICAgICAgKiBkaXJlY3RseSBhcyBpdCBpcyB0aGUgcmVzdWx0IG9mIGEgY29tcHV0YXRpb24uIEluc3RlYWQsIHRoZSBQYXJhbWV0ZXIgY2FsbHMKICAgICAgICAgKiAnYmFja1Byb3BhZ2F0ZVZhbHVlJyBvbiB0aGUgT3BlcmF0b3IgdG8gY2F1c2UgdGhlIE9wZXJhdG9yIHRvIGhhbmRsZSBwcm9wYWdhdGluZwogICAgICAgICAqIHRoZSB2YWx1ZSB0byBvbmUgb3IgbW9yZSBvZiBpdHMgaW5wdXRzLgogICAgICAgICAqIHRvIGl0cyBpbnB1dHMuCiAgICAgICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHBhcmFtLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgbW9kaWZpZWQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgYmFja1Byb3BhZ2F0ZVZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIC8vIFRPRE86IEltcGxlbWVudCBtZSBmb3IgY3VzdG9tIG1hbmlwdWxhdGlvbnMuCiAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGRldGFjaCBtZXRob2QuCiAgICAgICAgICovCiAgICAgICAgZGV0YWNoKCkgewogICAgICAgICAgICB0aGlzLmlucHV0cy5mb3JFYWNoKChpbnB1dCkgPT4gaW5wdXQuZGV0YWNoKCkpOwogICAgICAgICAgICB0aGlzLm91dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PiBvdXRwdXQuZGV0YWNoKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgcmVhdHRhY2ggbWV0aG9kLgogICAgICAgICAqLwogICAgICAgIHJlYXR0YWNoKCkgewogICAgICAgICAgICB0aGlzLmlucHV0cy5mb3JFYWNoKChpbnB1dCkgPT4gaW5wdXQucmVhdHRhY2goKSk7CiAgICAgICAgICAgIHRoaXMub3V0cHV0cy5mb3JFYWNoKChvdXRwdXQpID0+IG91dHB1dC5yZWF0dGFjaCgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHJlYmluZCBtZXRob2QuCiAgICAgICAgICovCiAgICAgICAgcmViaW5kKCkgewogICAgICAgICAgICB0aGlzLm91dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PiBvdXRwdXQucmViaW5kKCkpOwogICAgICAgIH0KICAgIH0KCiAgICAvKiogQ2xhc3MgcmVwcmVzZW50aW5nIGFuIG9wZXJhdG9yIGlucHV0LgogICAgICogQGV4dGVuZHMgRXZlbnRFbWl0dGVyCiAgICAgKi8KICAgIGNsYXNzIE9wZXJhdG9ySW5wdXQgewogICAgICAgIG5hbWU7CiAgICAgICAgb3A7CiAgICAgICAgcGFyYW07CiAgICAgICAgZGV0YWNoZWQgPSBmYWxzZTsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgYW4gb3BlcmF0b3IgaW5wdXQuCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgb3BlcmF0b3IgdGhhdCBvd25zIHRoaXMgaW5wdXQuIENhbGxlZCBieSB0aGUgb3BlcmF0b3Igd2hlbiBhZGRpbmcgaW5wdXRzCiAgICAgICAgICogQHBhcmFtIG9wIC0gVGhlIG9wZXJhdG9yIG9iamVjdC4KICAgICAgICAgKi8KICAgICAgICBzZXRPcGVyYXRvcihvcCkgewogICAgICAgICAgICB0aGlzLm9wID0gb3A7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgb3BlcmF0b3IgdGhhdCBvd25zIHRoaXMgaW5wdXQuCiAgICAgICAgICogQHJldHVybiAtIFRoZSBvcGVyYXRvciBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgZ2V0T3BlcmF0b3IoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLm9wOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBpbnB1dCBpcyBjb25uZWN0ZWQgdG8gYSBwYXJhbWV0ZXIuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgaXNDb25uZWN0ZWQoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmFtICE9IG51bGw7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBnZXRQYXJhbSBtZXRob2QuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0UGFyYW0oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmFtOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBAcHJpdmF0ZQogICAgICAgICAqIFRoZSBoYW5kbGVyIGZ1bmN0aW9uIGZvciB3aGVuIHRoZSBpbnB1dCBwYXJhbXRlciBjaGFuZ2VzLgogICAgICAgICAqIEBwYXJhbSBldmVudCAtIFRoZSBldmVudCBvYmplY3QuCiAgICAgICAgICovCiAgICAgICAgcGFyYW1WYWx1ZUNoYW5nZWQoKSB7CiAgICAgICAgICAgIGlmICh0aGlzLm9wKQogICAgICAgICAgICAgICAgdGhpcy5vcC5zZXREaXJ0eSgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBBc3NpZ25zIHRoZSBQYXJhbXRlciB0byBiZSB1c2VkIHRvIHByb3ZpZGUgdGhlIGlucHV0IHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBwYXJhbSAtIFRoZSBwYXJhbSB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRQYXJhbShwYXJhbSkgewogICAgICAgICAgICBpZiAodGhpcy5wYXJhbSkgewogICAgICAgICAgICAgICAgdGhpcy5wYXJhbS51bmJpbmRPcGVyYXRvcklucHV0KHRoaXMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMucGFyYW0gPSBwYXJhbTsKICAgICAgICAgICAgaWYgKHRoaXMucGFyYW0pIHsKICAgICAgICAgICAgICAgIHRoaXMucGFyYW0uYmluZE9wZXJhdG9ySW5wdXQodGhpcyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gV2hlbiBhbiBpbnB1dCBwYXJhbSBpcyBhc3NpZ25lZCwgdGhlIG9wIHNob3VsZAogICAgICAgICAgICAvLyBwcm9wYWdhdGUgZGlydHkgdG8gaXRzIG91dHB1dHMuCiAgICAgICAgICAgIGlmICh0aGlzLm9wKQogICAgICAgICAgICAgICAgdGhpcy5vcC5zZXREaXJ0eSgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZ2V0VmFsdWUgbWV0aG9kLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldFZhbHVlKCkgewogICAgICAgICAgICBpZiAodGhpcy5wYXJhbSkKICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmFtLnZhbHVlOwogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBnZXRWYWx1ZScpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgc2V0VmFsdWUgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSBwYXJhbS4KICAgICAgICAgKi8KICAgICAgICBzZXRWYWx1ZSh2YWx1ZSkgewogICAgICAgICAgICBpZiAodGhpcy5wYXJhbSkgewogICAgICAgICAgICAgICAgdGhpcy5wYXJhbS5zZXRWYWx1ZSh2YWx1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUHJvcGFnYXRlcyBmcm9tIHRoZSB1cHN0cmVhbSBwYXJhbWV0ZXIgdG8gdGhlIGNvbm5lY3RlZCBvcGVyYXRvci4KICAgICAgICAgKi8KICAgICAgICBzZXREaXJ0eSgpIHsKICAgICAgICAgICAgaWYgKHRoaXMub3ApIHsKICAgICAgICAgICAgICAgIHRoaXMub3Auc2V0RGlydHkoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdG9KU09OIG1ldGhvZCBlbmNvZGVzIHRoaXMgdHlwZSBhcyBhIGpzb24gb2JqZWN0IGZvciBwZXJzaXN0ZW5jZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIGNvbnN0IGFic1BhdGggPSB0aGlzLnBhcmFtID8gdGhpcy5wYXJhbS5nZXRQYXRoKCkgOiBbXTsKICAgICAgICAgICAgY29uc3QgcGFyYW1QYXRoID0gKGNvbnRleHQgJiYgY29udGV4dC5tYWtlUmVsYXRpdmUgPyBjb250ZXh0Lm1ha2VSZWxhdGl2ZShhYnNQYXRoKSA6IGFic1BhdGgpOwogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgbmFtZTogdGhpcy5uYW1lLAogICAgICAgICAgICAgICAgcGFyYW1QYXRoOiBwYXJhbVBhdGgsCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBmcm9tSlNPTiBtZXRob2QgZGVjb2RlcyBhIGpzb24gb2JqZWN0IGZvciB0aGlzIHR5cGUuCiAgICAgICAgICogQHBhcmFtIGogLSBUaGUganNvbiBvYmplY3QgdGhpcyBpdGVtIG11c3QgZGVjb2RlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZnJvbUpTT04oaiwgY29udGV4dCkgewogICAgICAgICAgICBpZiAoai5wYXJhbVBhdGgpIHsKICAgICAgICAgICAgICAgIC8vIE5vdGU6IHRoZSB0cmVlIHNob3VsZCBoYXZlIGZ1bGx5IGxvYWRlZCBieSB0aGUgdGltZSB3ZSBhcmUgbG9hZGluZyBvcGVyYXRvcnMKICAgICAgICAgICAgICAgIC8vIGV2ZW4gbmV3IGl0ZW1zIGFuZCBncm91cHMgc2hvdWxkIGhhdmUgYmVlbiBjcmVhdGVkLiBPcGVyYXRvcnMgYW5kIHN0YXRlIG1hY2hpbmVzCiAgICAgICAgICAgICAgICAvLyBhcmUgbG9hZGVkIGxhc3QuCiAgICAgICAgICAgICAgICBjb250ZXh0Py5yZXNvbHZlUGF0aChqLnBhcmFtUGF0aCwgKHBhcmFtKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRQYXJhbShwYXJhbSk7CiAgICAgICAgICAgICAgICB9LCAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCJPcGVyYXRvcklucHV0OiAnIiArIHRoaXMubmFtZSArICInLiBVbmFibGUgdG8gY29ubmVjdCB0bzoiICsgai5wYXJhbVBhdGgpOwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGRldGFjaCBtZXRob2QgaXMgY2FsbGVkIHdoZW4gYW4gb3BlcmF0b3IgaXMgYmVpbmcgcmVtb3ZlZCBmcm9tIHRoZSBzY2VuZSB0cmVlLgogICAgICAgICAqIEl0IHJlbW92ZXMgYWxsIGNvbm5lY3Rpb25zIHRvIHBhcmFtZXRlcnMgaW4gdGhlIHNjZW5lLgogICAgICAgICAqLwogICAgICAgIGRldGFjaCgpIHsKICAgICAgICAgICAgLy8gVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2hlbiB3ZSB3YW50IHRvIHN1c3BlbmQgYW4gb3BlcmF0b3IKICAgICAgICAgICAgLy8gZnJvbSBmdW5jdGlvbmluZyBiZWNhdXNlIGl0IGlzIGRlbGV0ZWQgYW5kIG9uIHRoZSB1bmRvIHN0YWNrLgogICAgICAgICAgICAvLyBPbmNlIG9wZXJhdG9ycyBoYXZlIHBlcnNpc3RlbnQgY29ubmVjdGlvbnMsCiAgICAgICAgICAgIC8vIHdlIHdpbGwgc2ltcGx5IHVuaW5zdGFsbCB0aGUgb3V0cHV0IGZyb20gdGhlIHBhcmFtZXRlci4KICAgICAgICAgICAgaWYgKHRoaXMucGFyYW0pIHsKICAgICAgICAgICAgICAgIHRoaXMucGFyYW0udW5iaW5kT3BlcmF0b3JJbnB1dCh0aGlzKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgcmVhdHRhY2ggbWV0aG9kIGNhbiBiZSBjYWxsZWQgd2hlbiByZS1pbnN0YXRpbmcgYW4gb3BlcmF0b3IgaW4gdGhlIHNjZW5lLgogICAgICAgICAqLwogICAgICAgIHJlYXR0YWNoKCkgewogICAgICAgICAgICB0aGlzLmRldGFjaGVkID0gZmFsc2U7CiAgICAgICAgICAgIGlmICh0aGlzLnBhcmFtKSB7CiAgICAgICAgICAgICAgICB0aGlzLnBhcmFtLmJpbmRPcGVyYXRvcklucHV0KHRoaXMpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgY2xhc3MgWGZvT3BlcmF0b3JJbnB1dCBleHRlbmRzIE9wZXJhdG9ySW5wdXQgewogICAgfQoKICAgIC8qKiBUaGUgb3BlcmF0b3IgdGhlIGNhbGN1bGF0ZXMgdGhlIGdsb2JhbCBYZm8gb2YgYSBUcmVlSXRlbSBiYXNlZCBvbiBpdHMgcGFyZW50cyBHbG9iYWxYZm8gYW5kIGl0cyBvd24gTG9jYWxYZm8KICAgICAqIEBleHRlbmRzIE9wZXJhdG9yCiAgICAgKiBAcHJpdmF0ZQogICAgICovCiAgICBjbGFzcyBDYWxjR2xvYmFsWGZvT3BlcmF0b3IgZXh0ZW5kcyBPcGVyYXRvciB7CiAgICAgICAgcGFyZW50R2xvYmFsID0gbmV3IFhmb09wZXJhdG9ySW5wdXQoJ1BhcmVudEdsb2JhbCcpOwogICAgICAgIGxvY2FsWGZvID0gbmV3IFhmb09wZXJhdG9ySW5wdXQoJ0xvY2FsWGZvJyk7CiAgICAgICAgZ2xvYmFsWGZvID0gbmV3IFhmb09wZXJhdG9yT3V0cHV0KCdHbG9iYWxYZm8nKTsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgYSBDYWxjR2xvYmFsWGZvT3BlcmF0b3Igb3BlcmF0b3IuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gZ3JvdXBHbG9iYWxYZm9QYXJhbSAtIFRoZSBHbG9iYWxYZm8gcGFyYW0gZm91bmQgb24gdGhlIEdyb3VwLgogICAgICAgICAqIEBwYXJhbSBjdXR0aW5nUGxhbmVQYXJhbSAtIFRoZSBwYXJhbWV0ZXIgb24gdGhlIEdyb3VwIHdoaWNoIGRlZmluZXMgdGhlIGRpc3BsYWNlbWVudCB0byBhcHBseSB0byB0aGUgbWVtYmVycy4KICAgICAgICAgKi8KICAgICAgICAvLyBUT0RPOiBhZGRpbmcgbmV3IFhmb1AuLi4gdG8gbWFrZSBpbmhlcml0ZW5jZSB3b3JrCiAgICAgICAgY29uc3RydWN0b3IoZ2xvYmFsWGZvUGFyYW0sIGxvY2FsWGZvUGFyYW0pIHsKICAgICAgICAgICAgc3VwZXIoJ0NhbGNHbG9iYWxYZm9PcGVyYXRvcicpOwogICAgICAgICAgICB0aGlzLmxvY2FsWGZvLnNldFBhcmFtKGxvY2FsWGZvUGFyYW0pOwogICAgICAgICAgICB0aGlzLmdsb2JhbFhmby5zZXRQYXJhbShnbG9iYWxYZm9QYXJhbSk7CiAgICAgICAgICAgIHRoaXMuYWRkSW5wdXQodGhpcy5wYXJlbnRHbG9iYWwpOwogICAgICAgICAgICB0aGlzLmFkZElucHV0KHRoaXMubG9jYWxYZm8pOwogICAgICAgICAgICB0aGlzLmFkZE91dHB1dCh0aGlzLmdsb2JhbFhmbyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBiYWNrUHJvcGFnYXRlVmFsdWUgbWV0aG9kIGludmVydHMgdGhlIG1hdGhlbWF0aWNzIG9mIHRoZSAnZXZhbHVhdGUnCiAgICAgICAgICogbWV0aG9kIHNvIGl0IGNhbiBwcm9wYWdhdGUgdGhlIHZhbHVlIGJhY2t3YXJkcyB0byBpdHMgaW5wdXRzLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIHRoZSBuZXcgdmFsdWUgYmVpbmcgc2V0IG9uIHRoZSBvdXRwdXQgR2xvYmFsWGZvCiAgICAgICAgICovCiAgICAgICAgYmFja1Byb3BhZ2F0ZVZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICh0aGlzLnBhcmVudEdsb2JhbC5pc0Nvbm5lY3RlZCgpKSB7CiAgICAgICAgICAgICAgICBjb25zdCBwYXJlbnRHbG9iYWxYZm8gPSB0aGlzLnBhcmVudEdsb2JhbC5nZXRWYWx1ZSgpOwogICAgICAgICAgICAgICAgdGhpcy5sb2NhbFhmby5zZXRWYWx1ZShwYXJlbnRHbG9iYWxYZm8uaW52ZXJzZSgpLm11bHRpcGx5KHZhbHVlKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsWGZvLnNldFZhbHVlKHZhbHVlKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZXZhbHVhdGUgbWV0aG9kIGNhbGN1bGF0ZXMgYSBuZXcgZ2xvYmFsIFhmbyBiYXNlZCBvbiB0aGUgcGFyZW50cyBHbG9iYWwgWGZvLAogICAgICAgICAqIGFuZCB0aGUgbG9jYWwgWGZvIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGV2YWx1YXRlKCkgewogICAgICAgICAgICBjb25zdCBsb2NhbFhmbyA9IHRoaXMubG9jYWxYZm8uZ2V0VmFsdWUoKTsKICAgICAgICAgICAgaWYgKHRoaXMucGFyZW50R2xvYmFsLmlzQ29ubmVjdGVkKCkpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHBhcmVudEdsb2JhbFhmbyA9IHRoaXMucGFyZW50R2xvYmFsLmdldFZhbHVlKCk7CiAgICAgICAgICAgICAgICB0aGlzLmdsb2JhbFhmby5zZXRDbGVhbihwYXJlbnRHbG9iYWxYZm8ubXVsdGlwbHkobG9jYWxYZm8pKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHRoaXMuZ2xvYmFsWGZvLnNldENsZWFuKGxvY2FsWGZvKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICAvKioKICAgICAqIFJlcHJlc2VudHMgYSBzcGVjaWZpYyB0eXBlIG9mIHBhcmFtZXRlciwgdGhhdCBvbmx5IHN0b3JlcyBgQm94M2AgdmFsdWVzLgogICAgICoKICAgICAqIGkuZS46CiAgICAgKiBgYGBqYXZhc2NyaXB0CiAgICAgKiBjb25zdCBib3VuZGluZ0JveCA9IG5ldyBCb3VuZGluZ0JveFBhcmFtZXRlcignTXlCQm94JywgbmV3IFRyZWVJdGVtKCkpCiAgICAgKiAvLydteVBhcmFtZXRlck93bmVySXRlbScgaXMgYW4gaW5zdGFuY2Ugb2YgYSAnUGFyYW1ldGVyT3duZXInIGNsYXNzLgogICAgICogLy8gUmVtZW1iZXIgdGhhdCBvbmx5ICdQYXJhbWV0ZXJPd25lcicgYW5kIGNsYXNzZXMgdGhhdCBleHRlbmQgZnJvbSBpdCBjYW4gaG9zdCAnUGFyYW1ldGVyJyBvYmplY3RzLgogICAgICogbXlQYXJhbWV0ZXJPd25lckl0ZW0uYWRkUGFyYW1ldGVyKGJvdW5kaW5nQm94KQogICAgICogYGBgCiAgICAgKiBAZXh0ZW5kcyBQYXJhbWV0ZXIKICAgICAqLwogICAgY2xhc3MgQm91bmRpbmdCb3hQYXJhbWV0ZXIgZXh0ZW5kcyBCb3gzUGFyYW1ldGVyIHsKICAgICAgICAvLyBwcm90ZWN0ZWQgZGlydHk6IGJvb2xlYW4sIHZhbHVlLCBuYW1lCiAgICAgICAgdHJlZUl0ZW07CiAgICAgICAgZGlydHkgPSB0cnVlOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgQm91bmRpbmdCb3hQYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBOYW1lIG9mIHRoZSBwYXJhbWV0ZXIKICAgICAgICAgKiBAcGFyYW0gdHJlZUl0ZW0gLSBgVHJlZUl0ZW1gIHRoYXQgY29udGFpbnMgYEJveDNgIHJlcHJlc2VudGluZyB0aGUgQm91bmRpbmcgQm94CiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IobmFtZSA9ICcnLCB0cmVlSXRlbSkgewogICAgICAgICAgICBzdXBlcihuYW1lKTsKICAgICAgICAgICAgdGhpcy50cmVlSXRlbSA9IHRyZWVJdGVtOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBNYWtlcyBwYXJhbWV0ZXIgdmFsdWUgYmUgZGlydHksIHNvIHdoZW4gYGdldFZhbHVlYCBpcyBjYWxsZWQsCiAgICAgICAgICogYW4gZXZhbHVhdGlvbiBpcyB0aGVuIGV4ZWN1dGVkIHRvIHJlLWNhbGN1bGF0ZSB0aGUgQm91bmRpbmdCb3gKICAgICAgICAgKgogICAgICAgICAqIEBtZW1iZXJvZiBCb3VuZGluZ0JveFBhcmFtZXRlcgogICAgICAgICAqLwogICAgICAgIHNldERpcnR5KGluZGV4KSB7CiAgICAgICAgICAgIGlmICghdGhpcy5kaXJ0eSkgewogICAgICAgICAgICAgICAgdGhpcy5kaXJ0eSA9IHRydWU7CiAgICAgICAgICAgICAgICB0aGlzLmVtaXQoJ3ZhbHVlQ2hhbmdlZCcpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICBnZXRWYWx1ZSgpIHsKICAgICAgICAgICAgaWYgKHRoaXMuZGlydHkpIHsKICAgICAgICAgICAgICAgIC8vQHRzLWlnbm9yZQogICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHRoaXMudHJlZUl0ZW0uY2xlYW5Cb3VuZGluZ0JveCgpOwogICAgICAgICAgICAgICAgdGhpcy5kaXJ0eSA9IGZhbHNlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBzdXBlci5nZXRWYWx1ZSgpOwogICAgICAgIH0KICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgY29uc3QgYkJveDNDbG9uZSA9IG5ldyBCb3VuZGluZ0JveFBhcmFtZXRlcih0aGlzLm5hbWUsIHRoaXMudHJlZUl0ZW0pOwogICAgICAgICAgICBiQm94M0Nsb25lLnZhbHVlID0gdGhpcy52YWx1ZT8uY2xvbmUoKTsKICAgICAgICAgICAgcmV0dXJuIGJCb3gzQ2xvbmU7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFdlIGRvIG5vdCB3YW50IHRoaXMgcGFyYW1ldGVyIHNlcmlhbGl6ZWQuCiAgICAgICAgICovCiAgICAgICAgaXNEcml2ZW5CeU9wZXJhdG9yKCkgewogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIFBlcnNpc3RlbmNlCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGxvYWRWYWx1ZSBpcyB1c2VkIHRvIGNoYW5nZSB0aGUgdmFsdWUgb2YgYSBwYXJhbWV0ZXIsIHdpdGhvdXQgdHJpZ2dlcmluZyBhCiAgICAgICAgICogdmFsdWVDaGFuZ2VzLCBvciBzZXR0aW5nIHRoZSBVU0VSX0VESVRFRCBzdGF0ZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGxvYWRWYWx1ZSh2YWx1ZSkgewogICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWUuY2xvbmUoKTsKICAgICAgICB9CiAgICB9CiAgICBSZWdpc3RyeS5yZWdpc3RlcignQm91bmRpbmdCb3hQYXJhbWV0ZXInLCBCb3VuZGluZ0JveFBhcmFtZXRlcik7CgogICAgLyoqCiAgICAgKiBDbGFzcyByZXByZXNlbnRpbmcgYW4gSXRlbSBpbiB0aGUgc2NlbmUgdHJlZSB3aXRoIGhpZXJhcmNoeSBjYXBhYmlsaXRpZXMgKGhhcyBjaGlsZHJlbikuCiAgICAgKiBJdCBoYXMgdGhlIGNhcGFiaWxpdHkgdG8gYWRkIGFuZCByZW1vdmUgY2hpbGRyZW4uCiAgICAgKiAqKlBhcmFtZXRlcnMqKgogICAgICogKiAqKlZpc2libGUoYEJvb2xlYW5QYXJhbWV0ZXJgKToqKiBTaG93cy9IaWRlcyB0aGUgaXRlbS4KICAgICAqICogKipMb2NhbFhmbyhgWGZvUGFyYW1ldGVyYCk6KiogU3BlY2lmaWVzIHRoZSBvZmZzZXQgb2YgdGhpcyB0cmVlIGl0ZW0gZnJvbSBpdHMgcGFyZW50LgogICAgICogKiAqKkdsb2JhbFhmbyhgWGZvUGFyYW1ldGVyYCk6KiogUHJvdmlkZXMgdGhlIGNvbXB1dGVkIHdvcmxkIFhmbyBvZiB0aGlzIHRyZWUgaXRlbS4KICAgICAqICogKipCb3VuZGluZ0JveChgQm91bmRpbmdCb3hgKToqKiBQcm92aWRlcyB0aGUgYm91bmRpbmcgYm94IGZvciB0aGUgdHJlZSBpdGVtIGFuZCBhbGwgb2YgaXRzIGNoaWxkcmVuIGluIHRoZSAzZCBzY2VuZS4KICAgICAqCiAgICAgKiAqKkV2ZW50cyoqCiAgICAgKiAqICoqZ2xvYmFsWGZvQ2hhbmdlZDoqKiBFbWl0dGVkIHdoZW4gdGhlIHZhbHVlIG9mIEdsb2JhbFhmbyBwYXJhbWV0ZXIgY2hhbmdlcy4KICAgICAqICogKip2aXNpYmlsaXR5Q2hhbmdlZDoqKiBFbWl0dGVkIHdoZW4gdGhlIHZpc2liaWxpdHkgb24gdGhlIHRyZWUgaXRlbSBjaGFuZ2VzLgogICAgICogKiAqKmhpZ2hsaWdodENoYW5nZWQ6KiogRW1pdHRlZCB3aGVuIHRoZSBoaWdobGlnaHQgb24gdGhlIHRyZWUgaXRlbSBjaGFuZ2VzLgogICAgICogKiAqKmNoaWxkQWRkZWQ6KiogRW1pdHRlZCB3aGVuIGEgaXRlbSBpcyBhZGRlZCBhcyBhIGNoaWxkLgogICAgICogKiAqKmNoaWxkUmVtb3ZlZDoqKiBFbWl0dGVkIHdoZW4gYW4gaXRlbSBpcyByZW1vdmVkIGZyb20gdGhlIGNoaWxkIG5vZGVzLgogICAgICogKiAqKnBvaW50ZXJEb3duOioqIEVtaXR0ZWQgd2hlbiBhIHBvaW50ZXJEb3duIGV2ZW50IGhhcHBlbnMgaW4gYW4gaXRlbS4KICAgICAqICogKipwb2ludGVyVXA6KiogRW1pdHRlZCB3aGVuIGEgcG9pbnRlclVwIGV2ZW50IGhhcHBlbnMgaW4gYW4gaXRlbS4KICAgICAqICogKipwb2ludGVyTW92ZToqKiBFbWl0dGVkIHdoZW4gYSBwb2ludGVyTW92ZSBldmVudCBoYXBwZW5zIGluIGFuIGl0ZW0uCiAgICAgKiAqICoqcG9pbnRlckVudGVyOioqIEVtaXR0ZWQgd2hlbiBhIHBvaW50ZXJFbnRlciBldmVudCBoYXBwZW5zIGluIGFuIGl0ZW0uCiAgICAgKiAqICoqcG9pbnRlckNsaWNrOioqIEVtaXR0ZWQgd2hlbiBhIHBvaW50ZXIgaXMgY2xpY2tlZCBvbiBhbiBpdGVtLgogICAgICogKiAqKnBvaW50ZXJEb3VibGVDbGljazoqKiBFbWl0dGVkIHdoZW4gYSBwb2ludGVyIGlzIGRvdWJsZS1jbGlja2VkIG9uIGFuIGl0ZW0uCiAgICAgKiAqICoqcG9pbnRlckxvbmdQcmVzczoqKiBFbWl0dGVkIHdoZW4gYSBwb2ludGVyIGlzIGNsaWNrZWQgYW5kIGhlbGQgb24gYW4gaXRlbSBmb3IgYSBsb25nIHRpbWUuCiAgICAgKgogICAgICoKICAgICAqIEBleHRlbmRzIHtQYXJhbWV0ZXJPd25lcn0KICAgICAqLwogICAgY2xhc3MgVHJlZUl0ZW0gZXh0ZW5kcyBQYXJhbWV0ZXJPd25lciB7CiAgICAgICAgLy8gQ29udHJvbHMgaWYgdGhpcyBUcmVlSXRlbSBvciBpdHMgY2hpbGRyZW4gY29udHJpYnV0ZSB0byB0aGUgYm91bmRpbmcgYm94ZXMKICAgICAgICAvLyBpbiB0aGUgc2NlbmUuIElmIHNldCB0byBmYWxzZSwgQ2FtZXJhIGZyYW1pbmcgd2lsbCBpZ25vcmUgdGhpcyBpdGVtLAogICAgICAgIGRpc2FibGVCb3VuZGluZ0JveCA9IGZhbHNlOwogICAgICAgIF9fY2hpbGRJdGVtcyA9IFtdOwogICAgICAgIF9fY2hpbGRJdGVtc0V2ZW50SGFuZGxlcnMgPSBbXTsKICAgICAgICBjaGlsZEl0ZW1zTWFwcGluZyA9IHt9OwogICAgICAgIGNoaWxkSXRlbXNNYXBwaW5nQ29ycnVwdCA9IGZhbHNlOwogICAgICAgIC8qKgogICAgICAgICAqIEBtZW1iZXIgZ2xvYmFsWGZvUGFyYW0gLSBTdG9yZXMgdGhlIGdsb2JhbCBYZm8gZm9yIHRoaXMgdHJlZSBpdGVtLgogICAgICAgICAqIGdsb2JhbCB4Zm9zIGFyZSBjYWxjdWxhdGVkIGZyb20gdGhlIGxvY2FsWGZvIGFuZCBwYXJlbnRYZm8uCiAgICAgICAgICovCiAgICAgICAgZ2xvYmFsWGZvUGFyYW0gPSBuZXcgWGZvUGFyYW1ldGVyKCdHbG9iYWxYZm8nLCBuZXcgWGZvKCkpOwogICAgICAgIC8qKgogICAgICAgICAqIEBtZW1iZXIgbG9jYWxYZm9QYXJhbSAtIFN0b3JlcyB0aGUgbG9jYWwgWGZvIGZvciB0aGlzIHRyZWUgaXRlbS4KICAgICAgICAgKiBsb2NhbCBYZm9zIGFyZSB0aGUgb2Zmc2V0IGZyb20gdGhlIHBhcmVudCdzIGNvb3JkaW5hdGUgZnJhbWUuCiAgICAgICAgICovCiAgICAgICAgbG9jYWxYZm9QYXJhbSA9IG5ldyBYZm9QYXJhbWV0ZXIoJ0xvY2FsWGZvJywgbmV3IFhmbygpKTsKICAgICAgICAvKioKICAgICAgICAgKiBAbWVtYmVyIGJvdW5kaW5nQm94UGFyYW0gLSBTdG9yZXMgdGhlIGJvdW5kaW5nIGJveCBmb3IgdGhpcyB0cmVlIGl0ZW0KICAgICAgICAgKi8KICAgICAgICBib3VuZGluZ0JveFBhcmFtID0gbmV3IEJvdW5kaW5nQm94UGFyYW1ldGVyKCdCb3VuZGluZ0JveCcsIHRoaXMpOwogICAgICAgIC8qKgogICAgICAgICAqIEBtZW1iZXIgdmlzaWJsZVBhcmFtIC0gV2hldGhlciB0aGlzIHRyZWUgaXRlbSBpcyB2aXNpYmxlIG9yIG5vdC4KICAgICAgICAgKiBBbnkgZ2l2ZW4gdHJlZSBpdGVtIGlzIGFsc28gaXMgYWZmZWN0ZWQgYnkgcGFyZW50J3MgdmlzaWJpbGl0eS4KICAgICAgICAgKi8KICAgICAgICB2aXNpYmxlUGFyYW0gPSBuZXcgQm9vbGVhblBhcmFtZXRlcignVmlzaWJsZScsIHRydWUpOwogICAgICAgIC8qKgogICAgICAgICAqIEBtZW1iZXIgcGlja2FibGVQYXJhbSAtIFdoZXRoZXIgdGhpcyB0cmVlIGl0ZW0gaWMgcGlja2FibGUgaW4gdGhlIHZpZXdwb3J0IG9yIG5vdC4KICAgICAgICAgKiBBbnkgZ2l2ZW4gdHJlZSBpdGVtIGlzIGFsc28gaXMgYWZmZWN0ZWQgYnkgcGFyZW50J3MgcGljay1hYmxpbGl0eS4KICAgICAgICAgKi8KICAgICAgICBwaWNrYWJsZVBhcmFtID0gbmV3IEJvb2xlYW5QYXJhbWV0ZXIoJ1BpY2thYmxlJywgdHJ1ZSk7CiAgICAgICAgLyoqCiAgICAgICAgICogQG1lbWJlciBvcGFjaXR5UGFyYW0gLSBDb250cm9scywgaW4gY29tYmluYXRpb24gd2l0aCBNYXRlcmlhbCB0cmFuc3BhcmVuY3ksCiAgICAgICAgICogdGhlIG9wYWNpdHkgb2YgdGhpcyBpdGVtIGFuZCBpdHMgY2hpbGRyZW4uCiAgICAgICAgICovCiAgICAgICAgb3BhY2l0eVBhcmFtID0gbmV3IE51bWJlclBhcmFtZXRlcignT3BhY2l0eScsIDEsIFswLCAxXSk7CiAgICAgICAgaGlnaGxpZ2h0TWFwcGluZyA9IHt9OwogICAgICAgIGhpZ2hsaWdodHMgPSBbXTsKICAgICAgICAjdmlzaWJsZSA9IHRydWU7CiAgICAgICAgI3BpY2thYmxlID0gdHJ1ZTsKICAgICAgICB2aXNpYmxlQ291bnRlciA9IDE7IC8vIFZpc2libGUgYnkgRGVmYXVsdC4KICAgICAgICBwaWNrYWJsZUNvdW50ZXIgPSAxOyAvLyBQaWNrYWJsZSBieSBEZWZhdWx0LgogICAgICAgIG9wYWNpdHkgPSAxOyAvLyBPcGFxdWUgYnkgRGVmYXVsdC4KICAgICAgICBpbmhlcml0ZWRPcGFjaXR5VmFsdWVzID0gbmV3IE1hcCgpOwogICAgICAgIGdsb2JhbFhmb09wOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYSB0cmVlIGl0ZW0gd2l0aCB0aGUgc3BlY2lmaWVkIG5hbWUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0cmVlIGl0ZW0uIEl0J3MgdGhlIGlkZW50aWZpZXIgb2YgdGhlIHRyZWUgaXRlbS4KICAgICAgICAgKiBJdCdzIGFuIGlkZW50aWZpZXIgaW50ZW5kZWQgdG8gYmUgaHVtYW4gcmVhZGFibGUuCiAgICAgICAgICogSXQncyBpbmNsdWRlZCBpbiB0aGUgcGF0aCB0aGF0IHdlIHVzZSB0byBhY2Nlc3MgYSBwYXJ0aWN1bGFyIGl0ZW0uCiAgICAgICAgICogSXQncyB1c2VkIHRvIGRpc3BsYXkgaXQgaW4gdGhlIHRyZWUuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IobmFtZSkgewogICAgICAgICAgICBzdXBlcihuYW1lKTsKICAgICAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgICAgICAvLyBBZGQgcGFyYW1ldGVycy4KICAgICAgICAgICAgdGhpcy5hZGRQYXJhbWV0ZXIodGhpcy52aXNpYmxlUGFyYW0pOwogICAgICAgICAgICB0aGlzLmFkZFBhcmFtZXRlcih0aGlzLnBpY2thYmxlUGFyYW0pOwogICAgICAgICAgICB0aGlzLmFkZFBhcmFtZXRlcih0aGlzLm9wYWNpdHlQYXJhbSk7CiAgICAgICAgICAgIHRoaXMuYWRkUGFyYW1ldGVyKHRoaXMubG9jYWxYZm9QYXJhbSk7CiAgICAgICAgICAgIHRoaXMuYWRkUGFyYW1ldGVyKHRoaXMuZ2xvYmFsWGZvUGFyYW0pOwogICAgICAgICAgICB0aGlzLmFkZFBhcmFtZXRlcih0aGlzLmJvdW5kaW5nQm94UGFyYW0pOwogICAgICAgICAgICB0aGlzLmdsb2JhbFhmb09wID0gbmV3IENhbGNHbG9iYWxYZm9PcGVyYXRvcih0aGlzLmdsb2JhbFhmb1BhcmFtLCB0aGlzLmxvY2FsWGZvUGFyYW0pOwogICAgICAgICAgICB0aGlzLmdsb2JhbFhmb1BhcmFtLm9uKCd2YWx1ZUNoYW5nZWQnLCAoZXZlbnQpID0+IHsKICAgICAgICAgICAgICAgIHRoaXMuc2V0Qm91bmRpbmdCb3hEaXJ0eSgpOwogICAgICAgICAgICAgICAgLy8gTm90ZTogZGVwcmVjYXRlIHRoaXMgZXZlbnQuCiAgICAgICAgICAgICAgICB0aGlzLmVtaXQoJ2dsb2JhbFhmb0NoYW5nZWQnLCBldmVudCk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICB0aGlzLnZpc2libGVQYXJhbS5vbigndmFsdWVDaGFuZ2VkJywgKCkgPT4gewogICAgICAgICAgICAgICAgdGhpcy52aXNpYmxlQ291bnRlciArPSB0aGlzLnZpc2libGVQYXJhbS52YWx1ZSA/IDEgOiAtMTsKICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlVmlzaWJpbGl0eSgpOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgdGhpcy5waWNrYWJsZVBhcmFtLm9uKCd2YWx1ZUNoYW5nZWQnLCAoKSA9PiB7CiAgICAgICAgICAgICAgICB0aGlzLnBpY2thYmxlQ291bnRlciArPSB0aGlzLnBpY2thYmxlUGFyYW0udmFsdWUgPyAxIDogLTE7CiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVBpY2thYmxlKCk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICB0aGlzLm9wYWNpdHlQYXJhbS5vbigndmFsdWVDaGFuZ2VkJywgKCkgPT4gewogICAgICAgICAgICAgICAgdGhpcy51cGRhdGVPcGFjaXR5KCk7CiAgICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICBzZXRPd25lcihvd25lckl0ZW0pIHsKICAgICAgICAgICAgaWYgKG93bmVySXRlbSAmJiAhKG93bmVySXRlbSBpbnN0YW5jZW9mIFRyZWVJdGVtKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5ub3Qgc2V0T3duZXInKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodGhpcy5vd25lckl0ZW0pIHsKICAgICAgICAgICAgICAgIGlmICh0aGlzLm93bmVySXRlbSBpbnN0YW5jZW9mIFRyZWVJdGVtKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGVmZmVjdCBvZiB0aGUgaW52aXNpYmxlIG93bmVyIGlzIHJlbW92ZWQuCiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLm93bmVySXRlbS5pc1Zpc2libGUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52aXNpYmxlQ291bnRlcisrOwogICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5vd25lckl0ZW0uaXNQaWNrYWJsZSgpKQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBpY2thYmxlQ291bnRlcisrOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5vd25lckl0ZW0uZ2V0Q2hpbGRJbmRleCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggPj0gMCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vd25lckl0ZW0udW5iaW5kQ2hpbGQoaW5kZXgsIHRoaXMpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHN1cGVyLnNldE93bmVyKG93bmVySXRlbSk7CiAgICAgICAgICAgIGlmICh0aGlzLm93bmVySXRlbSkgewogICAgICAgICAgICAgICAgaWYgKHRoaXMub3duZXJJdGVtIGluc3RhbmNlb2YgVHJlZUl0ZW0pIHsKICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZWZmZWN0IG9mIHRoZSBpbnZpc2libGUgb3duZXIgaXMgYWRkZWQuCiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLm93bmVySXRlbS5pc1Zpc2libGUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52aXNpYmxlQ291bnRlci0tOwogICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5vd25lckl0ZW0uaXNQaWNrYWJsZSgpKQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBpY2thYmxlQ291bnRlci0tOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZ2xvYmFsWGZvT3AuZ2V0SW5wdXQoJ1BhcmVudEdsb2JhbCcpLnNldFBhcmFtKHRoaXMub3duZXJJdGVtLmdsb2JhbFhmb1BhcmFtKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHRoaXMuZ2xvYmFsWGZvT3AuZ2V0SW5wdXQoJ1BhcmVudEdsb2JhbCcpLnNldFBhcmFtKHVuZGVmaW5lZCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy51cGRhdGVWaXNpYmlsaXR5KCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIHBhcmVudCBvZiBjdXJyZW50IFRyZWVJdGVtLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIHBhcmVudCBpdGVtLgogICAgICAgICAqLwogICAgICAgIGdldFBhcmVudEl0ZW0oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldE93bmVyKCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIHBhcmVudCBvZiBjdXJyZW50IFRyZWVJdGVtLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHBhcmVudEl0ZW0gLSBUaGUgcGFyZW50IGl0ZW0uCiAgICAgICAgICovCiAgICAgICAgc2V0UGFyZW50SXRlbShwYXJlbnRJdGVtKSB7CiAgICAgICAgICAgIHRoaXMuc2V0T3duZXIocGFyZW50SXRlbSk7CiAgICAgICAgfQogICAgICAgIGdldCBwYXJlbnQoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldE93bmVyKCk7CiAgICAgICAgfQogICAgICAgIHNldCBwYXJlbnQodHJlZUl0ZW0pIHsKICAgICAgICAgICAgdGhpcy5zZXRPd25lcih0cmVlSXRlbSk7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBWaXNpYmlsaXR5CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB2aXNpYmxlIHBhcmFtZXRlciB2YWx1ZSBmb3IgY3VycmVudCBUcmVlSXRlbS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgdmlzaWJsZSBwYXJhbSB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBpc1Zpc2libGUoKSB7CiAgICAgICAgICAgIC8vIFNob3VsZCBuZXZlciBiZSBtb3JlIHRoYW4gMSwgYnV0IGNhbiBiZSBsZXNzIHRoYW4gMC4KICAgICAgICAgICAgcmV0dXJuIHRoaXMudmlzaWJsZUNvdW50ZXIgPiAwOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHZpc2libGUgcGFyYW1ldGVyIHZhbHVlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHZhbCAtIFRoZSB2YWwgcGFyYW0uCiAgICAgICAgICovCiAgICAgICAgc2V0VmlzaWJsZSh2aXNpYmxlKSB7CiAgICAgICAgICAgIHRoaXMudmlzaWJsZVBhcmFtLnZhbHVlID0gdmlzaWJsZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVXBkYXRlcyBjdXJyZW50IFRyZWVJdGVtIHZpc2libGUgc3RhdGUgYW5kIHByb3BhZ2F0ZXMgaXRzIHZhbHVlIHRvIGNoaWxkcmVuIGVsZW1lbnRzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHZhbCAtIFRoZSB2YWwgcGFyYW0uCiAgICAgICAgICovCiAgICAgICAgcHJvcGFnYXRlVmlzaWJpbGl0eSh2YWwpIHsKICAgICAgICAgICAgdGhpcy52aXNpYmxlQ291bnRlciArPSB2YWw7CiAgICAgICAgICAgIHRoaXMudXBkYXRlVmlzaWJpbGl0eSgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdXBkYXRlVmlzaWJpbGl0eSBtZXRob2QuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBib29sZWFuLgogICAgICAgICAqLwogICAgICAgIHVwZGF0ZVZpc2liaWxpdHkoKSB7CiAgICAgICAgICAgIGNvbnN0IHZpc2libGUgPSB0aGlzLnZpc2libGVDb3VudGVyID4gMDsKICAgICAgICAgICAgaWYgKHZpc2libGUgIT0gdGhpcy4jdmlzaWJsZSkgewogICAgICAgICAgICAgICAgdGhpcy4jdmlzaWJsZSA9IHZpc2libGU7CiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGNoaWxkSXRlbSBvZiB0aGlzLl9fY2hpbGRJdGVtcykgewogICAgICAgICAgICAgICAgICAgIGNoaWxkSXRlbS5wcm9wYWdhdGVWaXNpYmlsaXR5KHRoaXMuI3Zpc2libGUgPyAxIDogLTEpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhpcy5lbWl0KCd2aXNpYmlsaXR5Q2hhbmdlZCcsIG5ldyBTdGF0ZUNoYW5nZWRFdmVudCh2aXNpYmxlKSk7CiAgICAgICAgICAgICAgICAvLyBOb3RlOiB3ZSB1c2VkIHRvIGhhbmRsZSB0aGlzIGJ5IGxpc3RlbmluZyB0byBhICd2YWx1ZUNoYW5nZWQnIGV2ZW50IG9uIHRoZQogICAgICAgICAgICAgICAgLy8gcGFyYW1ldGVyLgogICAgICAgICAgICAgICAgaWYgKHRoaXMub3duZXJJdGVtIGluc3RhbmNlb2YgVHJlZUl0ZW0pIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLm93bmVySXRlbS5zZXRCb3VuZGluZ0JveERpcnR5KCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQaWNrYWJsZQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdmlzaWJsZSBwYXJhbWV0ZXIgdmFsdWUgZm9yIGN1cnJlbnQgVHJlZUl0ZW0uCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHZpc2libGUgcGFyYW0gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgaXNQaWNrYWJsZSgpIHsKICAgICAgICAgICAgLy8gU2hvdWxkIG5ldmVyIGJlIG1vcmUgdGhhbiAxLCBidXQgY2FuIGJlIGxlc3MgdGhhbiAwLgogICAgICAgICAgICByZXR1cm4gdGhpcy5waWNrYWJsZUNvdW50ZXIgPiAwOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBVcGRhdGVzIGN1cnJlbnQgVHJlZUl0ZW0gdmlzaWJsZSBzdGF0ZSBhbmQgcHJvcGFnYXRlcyBpdHMgdmFsdWUgdG8gY2hpbGRyZW4gZWxlbWVudHMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gdmFsIC0gVGhlIHZhbCBwYXJhbS4KICAgICAgICAgKi8KICAgICAgICBwcm9wYWdhdGVQaWNrYWJsZSh2YWwpIHsKICAgICAgICAgICAgdGhpcy5waWNrYWJsZUNvdW50ZXIgKz0gdmFsOwogICAgICAgICAgICB0aGlzLnVwZGF0ZVBpY2thYmxlKCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSB1cGRhdGVQaWNrYWJsZSBtZXRob2QuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBib29sZWFuLgogICAgICAgICAqLwogICAgICAgIHVwZGF0ZVBpY2thYmxlKCkgewogICAgICAgICAgICBjb25zdCBwaWNrYWJsZSA9IHRoaXMucGlja2FibGVDb3VudGVyID4gMDsKICAgICAgICAgICAgaWYgKHBpY2thYmxlICE9IHRoaXMuI3BpY2thYmxlKSB7CiAgICAgICAgICAgICAgICB0aGlzLiNwaWNrYWJsZSA9IHBpY2thYmxlOwogICAgICAgICAgICAgICAgZm9yIChjb25zdCBjaGlsZEl0ZW0gb2YgdGhpcy5fX2NoaWxkSXRlbXMpIHsKICAgICAgICAgICAgICAgICAgICBjaGlsZEl0ZW0ucHJvcGFnYXRlUGlja2FibGUodGhpcy4jcGlja2FibGUgPyAxIDogLTEpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhpcy5lbWl0KCdwaWNrYWJpbGl0eUNoYW5nZWQnLCBuZXcgU3RhdGVDaGFuZ2VkRXZlbnQocGlja2FibGUpKTsKICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIE9wYWNpdHkKICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHN0YXR1cyBvZiB0aGUgb3BhY2l0eSB2YWx1ZS4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRydWUgaWYgdGhlIG9wYWNpdHkgdmFsdWUgaXMgbGVzcyB0aGFuIDEuCiAgICAgICAgICovCiAgICAgICAgaXNPcGFxdWUoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLm9wYWNpdHkgPiAwLjk5OTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0IHRoZSB2YWx1ZSBvZiBvcGFjaXR5IGluaGVyaXRlZCBieSBhIGdpdmVuIHRyZWUgaXRlbS4KICAgICAgICAgKi8KICAgICAgICBzZXRJbmhlcml0ZWRPcGFjaXR5KHBhcmVudCwgdmFsdWUpIHsKICAgICAgICAgICAgdGhpcy5pbmhlcml0ZWRPcGFjaXR5VmFsdWVzLnNldChwYXJlbnQsIHZhbHVlKTsKICAgICAgICAgICAgdGhpcy51cGRhdGVPcGFjaXR5KCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIG5ldyBvcGFjaXR5IHZhbHVlIGJhc2VkIG9uIHRoZSBvcGFjaXR5UGFyYW0gdmFsdWUKICAgICAgICAgKiBhbmQgdGhlIGxvd2VzdCBvZiB0aGUgaW5oZXJpdGVkIG9wYWNpdHkgdmFsdWVzLgogICAgICAgICAqLwogICAgICAgIHVwZGF0ZU9wYWNpdHkoKSB7CiAgICAgICAgICAgIGxldCBpbmhlcml0ZWRPcGFjaXR5VmFsdWUgPSAxOwogICAgICAgICAgICB0aGlzLmluaGVyaXRlZE9wYWNpdHlWYWx1ZXMuZm9yRWFjaCgodmFsdWUpID0+IHsKICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA8IGluaGVyaXRlZE9wYWNpdHlWYWx1ZSkKICAgICAgICAgICAgICAgICAgICBpbmhlcml0ZWRPcGFjaXR5VmFsdWUgPSB2YWx1ZTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGNvbnN0IHdhc09wYXF1ZSA9IHRoaXMub3BhY2l0eSA+IDAuOTk5OwogICAgICAgICAgICB0aGlzLm9wYWNpdHkgPSB0aGlzLm9wYWNpdHlQYXJhbS52YWx1ZSAqIGluaGVyaXRlZE9wYWNpdHlWYWx1ZTsKICAgICAgICAgICAgLy8gZWxzZSB0aGlzLm9wYWNpdHkgPSB0aGlzLm9wYWNpdHlQYXJhbS52YWx1ZQogICAgICAgICAgICBmb3IgKGNvbnN0IGNoaWxkSXRlbSBvZiB0aGlzLl9fY2hpbGRJdGVtcykgewogICAgICAgICAgICAgICAgY2hpbGRJdGVtLnNldEluaGVyaXRlZE9wYWNpdHkodGhpcywgdGhpcy5vcGFjaXR5KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBpc09wYXF1ZSA9IHRoaXMub3BhY2l0eSA+IDAuOTk5OwogICAgICAgICAgICB0aGlzLmVtaXQoJ29wYWNpdHlDaGFuZ2VkJywgbmV3IE9wYWNpdHlTdGF0ZUNoYW5nZWRFdmVudChpc09wYXF1ZSwgd2FzT3BhcXVlICE9IGlzT3BhcXVlKSk7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBIaWdobGlnaHRzCiAgICAgICAgLyoqCiAgICAgICAgICogQWRkcyBhIGhpZ2hsaWdodCB0byB0aGUgdHJlZSBpdGVtLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdHJlZSBpdGVtLgogICAgICAgICAqIEBwYXJhbSBjb2xvciAtIFRoZSBjb2xvciBvZiB0aGUgaGlnaGxpZ2h0LgogICAgICAgICAqIEBwYXJhbSBwcm9wYWdhdGVUb0NoaWxkcmVuIC0gQSBib29sZWFuIGluZGljYXRpbmcgd2hldGhlciB0byBwcm9wYWdhdGUgdG8gY2hpbGRyZW4uCiAgICAgICAgICovCiAgICAgICAgYWRkSGlnaGxpZ2h0KG5hbWUsIGNvbG9yLCBwcm9wYWdhdGVUb0NoaWxkcmVuID0gdHJ1ZSkgewogICAgICAgICAgICAvLyBJZiB0aGUgaGlnaGxpZ2h0IHdhcyBhbHJlYWR5IGluIHRoZSBsaXN0LAogICAgICAgICAgICAvLyByZW1vdmUgaXQgYW5kIHB1dCBpdCBhdCB0aGUgdG9wLgogICAgICAgICAgICBpZiAobmFtZSBpbiB0aGlzLmhpZ2hsaWdodE1hcHBpbmcpIHsKICAgICAgICAgICAgICAgIGlmICh0aGlzLmhpZ2hsaWdodHNbdGhpcy5oaWdobGlnaHRzLmxlbmd0aCAtIDFdICE9IG5hbWUpIHsKICAgICAgICAgICAgICAgICAgICAvLyBUaGUgaGlnaGxpZ2h0IHdhcyBhbHJlYWR5IGluIHRoZSBsaXN0LCBidXQgbm90IGF0IHRoZSB0b3AuIE1vdmUgaXQgdG8gdGhlIHRvcC4KICAgICAgICAgICAgICAgICAgICBjb25zdCBpZCA9IHRoaXMuaGlnaGxpZ2h0cy5pbmRleE9mKG5hbWUpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuaGlnaGxpZ2h0cy5zcGxpY2UoaWQsIDEpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuaGlnaGxpZ2h0cy5wdXNoKG5hbWUpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdCgnaGlnaGxpZ2h0Q2hhbmdlZCcsIHsgbmFtZSwgY29sb3IgfSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGl0ZW0gaXMgYWxyZWFkeSBoaWdobGlnaHRlZCB3aXRoIHRoaXMgaGlnaGxpZ2h0CiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmhpZ2hsaWdodE1hcHBpbmdbbmFtZV0uaXNFcXVhbChjb2xvcikpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRNYXBwaW5nW25hbWVdID0gY29sb3I7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdCgnaGlnaGxpZ2h0Q2hhbmdlZCcsIHsgbmFtZSwgY29sb3IgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRzLnB1c2gobmFtZSk7CiAgICAgICAgICAgICAgICB0aGlzLmhpZ2hsaWdodE1hcHBpbmdbbmFtZV0gPSBjb2xvcjsKICAgICAgICAgICAgICAgIHRoaXMuZW1pdCgnaGlnaGxpZ2h0Q2hhbmdlZCcsIHsgbmFtZSwgY29sb3IgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHByb3BhZ2F0ZVRvQ2hpbGRyZW4pIHsKICAgICAgICAgICAgICAgIHRoaXMuX19jaGlsZEl0ZW1zLmZvckVhY2goKGNoaWxkSXRlbSkgPT4gewogICAgICAgICAgICAgICAgICAgIGNoaWxkSXRlbS5hZGRIaWdobGlnaHQobmFtZSwgY29sb3IsIHByb3BhZ2F0ZVRvQ2hpbGRyZW4pOwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmVtb3ZlcyBhIGhpZ2hsaWdodCB0byB0aGUgdHJlZSBpdGVtLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdHJlZSBpdGVtLgogICAgICAgICAqIEBwYXJhbSBwcm9wYWdhdGVUb0NoaWxkcmVuIC0gQSBib29sZWFuIGluZGljYXRpbmcgd2hldGhlciB0byBwcm9wYWdhdGUgdG8gY2hpbGRyZW4uCiAgICAgICAgICovCiAgICAgICAgcmVtb3ZlSGlnaGxpZ2h0KG5hbWUsIHByb3BhZ2F0ZVRvQ2hpbGRyZW4gPSB0cnVlKSB7CiAgICAgICAgICAgIGlmIChuYW1lIGluIHRoaXMuaGlnaGxpZ2h0TWFwcGluZykgewogICAgICAgICAgICAgICAgaWYgKHRoaXMuaGlnaGxpZ2h0c1t0aGlzLmhpZ2hsaWdodHMubGVuZ3RoIC0gMV0gPT0gbmFtZSkgewogICAgICAgICAgICAgICAgICAgIHRoaXMuaGlnaGxpZ2h0cy5wb3AoKTsKICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5oaWdobGlnaHRNYXBwaW5nW25hbWVdOwogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmhpZ2hsaWdodHMubGVuZ3RoID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXh0TmFtZSA9IHRoaXMuaGlnaGxpZ2h0c1t0aGlzLmhpZ2hsaWdodHMubGVuZ3RoIC0gMV07CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5leHRDb2xvciA9IHRoaXMuaGlnaGxpZ2h0TWFwcGluZ1tuZXh0TmFtZV07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdCgnaGlnaGxpZ2h0Q2hhbmdlZCcsIHsgbmFtZTogbmV4dE5hbWUsIGNvbG9yOiBuZXh0Q29sb3IgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgbGFzdCBoaWdobGlnaHQgd2FzIHJlbW92ZWQsIHNvIGVtaXQgYW4gZXZlbnQgc2F5aW5nIHdlIGFyZSBubyBsb25nZXIgaGlnaGxpZ2h0ZWQuCiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdCgnaGlnaGxpZ2h0Q2hhbmdlZCcpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIC8vIFRoZSByZW1vdmVkIGhpZ2hsaWdodCB3YXMgbm90IHRoZSBjdXJyZW50IGhpZ2hsaWdodCwgc28gbm8gY2hhbmdlIG5lZWRzIHRvIGJlIHNob3duLgogICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkID0gdGhpcy5oaWdobGlnaHRzLmluZGV4T2YobmFtZSk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRzLnNwbGljZShpZCwgMSk7CiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuaGlnaGxpZ2h0TWFwcGluZ1tuYW1lXTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChwcm9wYWdhdGVUb0NoaWxkcmVuKSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5fX2NoaWxkSXRlbXMuZm9yRWFjaCgoY2hpbGRJdGVtKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkSXRlbS5yZW1vdmVIaWdobGlnaHQobmFtZSwgcHJvcGFnYXRlVG9DaGlsZHJlbik7CiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgY29sb3Igb2YgdGhlIGN1cnJlbnQgaGlnaGxpZ2h0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSBjb2xvciB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRIaWdobGlnaHQoKSB7CiAgICAgICAgICAgIGlmICh0aGlzLmhpZ2hsaWdodHMubGVuZ3RoID09IDApIHsKICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0aGlzLmhpZ2hsaWdodE1hcHBpbmdbdGhpcy5oaWdobGlnaHRzW3RoaXMuaGlnaGxpZ2h0cy5sZW5ndGggLSAxXV07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIG5hbWUgb2YgdGhlIGN1cnJlbnQgaGlnaGxpZ2h0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSBjb2xvciB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRIaWdobGlnaHROYW1lKCkgewogICAgICAgICAgICBpZiAodGhpcy5oaWdobGlnaHRzLmxlbmd0aCA9PSAwKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhpcy5oaWdobGlnaHRzW3RoaXMuaGlnaGxpZ2h0cy5sZW5ndGggLSAxXTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBgdHJ1ZWAgaWYgdGhpcyBpdGVtcyBoYXMgYSBoaWdobGlnaHQgY29sb3IgYXNzaWduZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gYFRydWVgIGlmIHRoaXMgaXRlbSBpcyBoaWdobGlnaHRlZC4KICAgICAgICAgKi8KICAgICAgICBpc0hpZ2hsaWdodGVkKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5oaWdobGlnaHRzLmxlbmd0aCA+IDA7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBCb3VuZGluZyBCb3gKICAgICAgICBjbGVhbkJvdW5kaW5nQm94KCkgewogICAgICAgICAgICBjb25zdCBiYm94ID0gbmV3IEJveDMoKTsKICAgICAgICAgICAgdGhpcy5fX2NoaWxkSXRlbXMuZm9yRWFjaCgoY2hpbGRJdGVtKSA9PiB7CiAgICAgICAgICAgICAgICBpZiAoY2hpbGRJdGVtLmlzVmlzaWJsZSgpICYmIGNoaWxkSXRlbS5pc1BpY2thYmxlKCkpIHsKICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygiIC0gIiwgY2hpbGRJdGVtLmNvbnN0cnVjdG9yLm5hbWUsIGNoaWxkSXRlbS5nZXROYW1lKCksIGNoaWxkSXRlbS5nbG9iYWxYZm9QYXJhbS52YWx1ZS5zYy54LCBjaGlsZEl0ZW0uZ2V0Qm91bmRpbmdCb3goKS50b1N0cmluZygpKQogICAgICAgICAgICAgICAgICAgIGNvbnN0IGJveDMgPSBjaGlsZEl0ZW0uYm91bmRpbmdCb3hQYXJhbS52YWx1ZTsKICAgICAgICAgICAgICAgICAgICBpZiAoYm94MykKICAgICAgICAgICAgICAgICAgICAgICAgYmJveC5hZGRCb3gzKGJveDMpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgLy8gY29uc29sZS5sb2codGhpcy5nZXROYW1lKCksIGJib3gudG9TdHJpbmcoKSkKICAgICAgICAgICAgcmV0dXJuIGJib3g7CiAgICAgICAgfQogICAgICAgIHNldEJvdW5kaW5nQm94RGlydHkoKSB7CiAgICAgICAgICAgIGlmICh0aGlzLmJvdW5kaW5nQm94UGFyYW0pIHsKICAgICAgICAgICAgICAgIC8vIFdpbGwgY2F1c2UgYm91bmRpbmdDaGFuZ2VkIHRvIGVtaXQKICAgICAgICAgICAgICAgIHRoaXMuYm91bmRpbmdCb3hQYXJhbS5zZXREaXJ0eSgtMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gTm90ZTogd2UgdXNlZCB0byBoYW5kbGUgdGhpcyBieSBsaXN0ZW5pbmcgdG8gYSAndmFsdWVDaGFuZ2VkJyBldmVudCBvbiB0aGUKICAgICAgICAgICAgLy8gcGFyYW1ldGVyLgogICAgICAgICAgICBpZiAodGhpcy5vd25lckl0ZW0gaW5zdGFuY2VvZiBUcmVlSXRlbSkgewogICAgICAgICAgICAgICAgdGhpcy5vd25lckl0ZW0uc2V0Qm91bmRpbmdCb3hEaXJ0eSgpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBDaGlsZHJlbgogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgY2hpbGRyZW4gbGlzdCwgYnV0IGNoaWxkcmVuIGFyZSBub3QgcmVxdWlyZWQgdG8gaGF2ZSBoaWVyYXJjaHkgc3RydWN0dXJlKGBUcmVlSXRlbWApLgogICAgICAgICAqIE1lYW5pbmcgdGhhdCBpdCBjb3VsZCBiZSBhbm90aGVyIGtpbmQgb2YgaXRlbSB0aGFuIGBUcmVlSXRlbWAuCiAgICAgICAgICoKICAgICAgICAgKiBpLmUuICoqQmFzZUltYWdlKioKICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBMaXN0IG9mIGBUcmVlSXRlbWAgb3duZWQgYnkgY3VycmVudCBUcmVlSXRlbS4KICAgICAgICAgKi8KICAgICAgICBnZXRDaGlsZHJlbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX19jaGlsZEl0ZW1zOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgY2hpbGQgdHJlZSBpdGVtcy4KICAgICAgICAgKi8KICAgICAgICBnZXROdW1DaGlsZHJlbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX19jaGlsZEl0ZW1zLmxlbmd0aDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGNoaWxkIHRyZWUgaXRlbXMuCiAgICAgICAgICovCiAgICAgICAgZ2V0IG51bUNoaWxkcmVuKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fX2NoaWxkSXRlbXMubGVuZ3RoOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBBcHBseSBhbiBpbmRleCB0byB0aGUgbmFtZSBpZiBuYW1lIGV4aXN0cyB3aXRoaW4gdGhpcyBpdGVtJ3MgY2hpbGRyZW4uCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgdW5pcXVlIG5hbWUuCiAgICAgICAgICovCiAgICAgICAgZ2VuZXJhdGVVbmlxdWVOYW1lKG5hbWUpIHsKICAgICAgICAgICAgd2hpbGUgKHRoaXMuY2hpbGRJdGVtc01hcHBpbmdbbmFtZS50b0xvY2FsZUxvd2VyQ2FzZSgpXSAhPSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4UmVnZXhwID0gLyhcZCspJC9pOwogICAgICAgICAgICAgICAgY29uc3QgaW5kZXhNYXRjaGVzID0gbmFtZS5tYXRjaChpbmRleFJlZ2V4cCk7CiAgICAgICAgICAgICAgICBsZXQgbmV3SW5kZXggPSAxOwogICAgICAgICAgICAgICAgaWYgKGluZGV4TWF0Y2hlcykgewogICAgICAgICAgICAgICAgICAgIG5ld0luZGV4ID0gcGFyc2VJbnQoaW5kZXhNYXRjaGVzWzFdKSArIDE7CiAgICAgICAgICAgICAgICAgICAgbmFtZSA9IG5hbWUucmVwbGFjZShpbmRleFJlZ2V4cCwgJycpOyAvLyByZW1vdmUgb2xkIGluZGV4CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBuYW1lICs9IGAke25ld0luZGV4fWAucGFkU3RhcnQoMiwgJzAnKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbmFtZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVXBkYXRlcyB0aGUgaW50ZXJuYWwgYWNjZWxlcmF0aW9uIHN0cnVjdHVyZSB0aGF0IHNwZWVkcyB1cCBsb29raW5nIHVwIGNoaWxkcmVuIGJ5IG5hbWUuCiAgICAgICAgICogQHBhcmFtIHN0YXJ0IC0gVGhlIHN0YXJ0IHZhbHVlLgogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICovCiAgICAgICAgdXBkYXRlQ2hpbGROYW1lTWFwcGluZyhzdGFydCkgewogICAgICAgICAgICAvLyBJZiBhIGNoaWxkIGhhcyBiZWVuIGFkZGVkIG9yIHJlbW92ZWQgZnJvbSB0aGUKICAgICAgICAgICAgLy8gdHJlZSBpdGVtLCB3ZSBuZWVkIHRvIHVwZGF0ZSB0aGUgYWNjZWxlcmF0aW9uIHN0cnVjdHVyZS4KICAgICAgICAgICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgdGhpcy5fX2NoaWxkSXRlbXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIGNvbnN0IG5hbWUgPSB0aGlzLl9fY2hpbGRJdGVtc1tpXS5uYW1lLnRvTG9jYWxlTG93ZXJDYXNlKCk7CiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkSXRlbXNNYXBwaW5nW25hbWVdID0gaTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBXaGVuIGEgY2hpbGQncyBuYW1lIGNoYW5nZWQsIHdlIHVwZGF0ZSBvdXIgYWNjZWxlcmF0aW9uIHN0cnVjdHVyZS4KICAgICAgICAgKiBAcGFyYW0gZXZlbnQgLSBUaGUgc3RhcnQgdmFsdWUuCiAgICAgICAgICogQHByaXZhdGUKICAgICAgICAgKi8KICAgICAgICBjaGlsZE5hbWVDaGFuZ2VkKGV2ZW50KSB7CiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgYWNjZWxlcmF0aW9uIHN0cnVjdHVyZS4KICAgICAgICAgICAgaWYgKHRoaXMuY2hpbGRJdGVtc01hcHBpbmdDb3JydXB0KSB7CiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUNoaWxkTmFtZU1hcHBpbmcoMCk7CiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkSXRlbXNNYXBwaW5nQ29ycnVwdCA9IGZhbHNlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgY29uc3Qgb2xkTmFtZSA9IGV2ZW50Lm9sZE5hbWUudG9Mb2NhbGVMb3dlckNhc2UoKTsKICAgICAgICAgICAgICAgIGNvbnN0IG5ld05hbWUgPSBldmVudC5uZXdOYW1lLnRvTG9jYWxlTG93ZXJDYXNlKCk7CiAgICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMuY2hpbGRJdGVtc01hcHBpbmdbb2xkTmFtZV07CiAgICAgICAgICAgICAgICBpZiAodGhpcy5jaGlsZEl0ZW1zTWFwcGluZ1tuZXdOYW1lXSAhPSB1bmRlZmluZWQpCiAgICAgICAgICAgICAgICAgICAgdGhpcy5jaGlsZEl0ZW1zTWFwcGluZ0NvcnJ1cHQgPSB0cnVlOwogICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2hpbGRJdGVtc01hcHBpbmdbb2xkTmFtZV07CiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkSXRlbXNNYXBwaW5nW25ld05hbWVdID0gaW5kZXg7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogSW5zZXJ0cyBhIGNoaWxkLiBJdCBhY2NlcHRzIGFsbCBraW5kIG9mIGBUcmVlSXRlbWAsIG5vdCBvbmx5IGBUcmVlSXRlbWAuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gY2hpbGRJdGVtIC0gVGhlIGNoaWxkIFRyZWVJdGVtIHRvIGluc2VydC4KICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdG8gYWRkIHRoZSBjaGlsZCBpdGVtLgogICAgICAgICAqIEBwYXJhbSBtYWludGFpblhmbyAtIEJvb2xlYW4gdGhhdCBkZXRlcm1pbmVzIGlmIHRoZSBYZm8gdmFsdWUgaXMgbWFpbnRhaW5lZC4KICAgICAgICAgKiBAcGFyYW0gZml4Q29sbGlzaW9ucyAtIE1vZGlmeSB0aGUgbmFtZSBvZiB0aGUgaXRlbSB0byBhdm9pZCBuYW1lIGNvbGxpc2lvbnMuCiAgICAgICAgICogSWYgZmFsc2UsIGFuIGV4Y2VwdGlvbiB3bGwgYmUgdGhyb3duIGluc3RlYWQgaWYgYSBuYW1lIGNvbGxpc2lvbiBvY2N1cnMuCiAgICAgICAgICogQHJldHVybiAtIFRoZSBpbmRleCBvZiB0aGUgY2hpbGQgaXRlbSBpbiB0aGlzIGl0ZW1zIGNoaWxkcmVuIGFycmF5LgogICAgICAgICAqLwogICAgICAgIGluc2VydENoaWxkKGNoaWxkSXRlbSwgaW5kZXgsIG1haW50YWluWGZvID0gZmFsc2UsIGZpeENvbGxpc2lvbnMgPSB0cnVlKSB7CiAgICAgICAgICAgIGxldCBuYW1lID0gY2hpbGRJdGVtLm5hbWU7CiAgICAgICAgICAgIGxldCBuYW1lTGMgPSBuYW1lLnRvTG9jYWxlTG93ZXJDYXNlKCk7CiAgICAgICAgICAgIGlmIChuYW1lTGMgaW4gdGhpcy5jaGlsZEl0ZW1zTWFwcGluZykgewogICAgICAgICAgICAgICAgaWYgKGZpeENvbGxpc2lvbnMpIHsKICAgICAgICAgICAgICAgICAgICBuYW1lID0gdGhpcy5nZW5lcmF0ZVVuaXF1ZU5hbWUobmFtZSk7CiAgICAgICAgICAgICAgICAgICAgbmFtZUxjID0gbmFtZS50b0xvY2FsZUxvd2VyQ2FzZSgpOwogICAgICAgICAgICAgICAgICAgIGNoaWxkSXRlbS5zZXROYW1lKG5hbWUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJJdGVtICciICsgbmFtZSArICInIGlzIGFscmVhZHkgYSBjaGlsZCBvZiA6IiArIHRoaXMuZ2V0UGF0aCgpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoIShjaGlsZEl0ZW0gaW5zdGFuY2VvZiBUcmVlSXRlbSkpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignT2JqZWN0IGlzIGlzIG5vdCBhIHRyZWUgaXRlbSA6JyArIGNoaWxkSXRlbSk7IC8vIFRPRE86IG5lZWQgYmV0dGVyIG91dHB1dCBoZXJlKyBjaGlsZEl0ZW0uY29uc3RydWN0b3IubmFtZSkKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBsaXN0ZW5lcklEcyA9IHt9OwogICAgICAgICAgICBsaXN0ZW5lcklEc1snbmFtZUNoYW5nZWQnXSA9IGNoaWxkSXRlbS5vbignbmFtZUNoYW5nZWQnLCAoZXZlbnQpID0+IHsKICAgICAgICAgICAgICAgIHRoaXMuY2hpbGROYW1lQ2hhbmdlZChldmVudCk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBsZXQgcHJldkdsb2JhbDsKICAgICAgICAgICAgaWYgKG1haW50YWluWGZvKSB7CiAgICAgICAgICAgICAgICBwcmV2R2xvYmFsID0gY2hpbGRJdGVtLmdsb2JhbFhmb1BhcmFtLnZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuc2V0Qm91bmRpbmdCb3hEaXJ0eSgpOwogICAgICAgICAgICB0aGlzLmhpZ2hsaWdodHMuZm9yRWFjaCgobmFtZSkgPT4gewogICAgICAgICAgICAgICAgY2hpbGRJdGVtLmFkZEhpZ2hsaWdodChuYW1lLCB0aGlzLmhpZ2hsaWdodE1hcHBpbmdbbmFtZV0sIHRydWUpOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgY2hpbGRJdGVtLnNldEluaGVyaXRlZE9wYWNpdHkodGhpcywgdGhpcy5vcGFjaXR5KTsKICAgICAgICAgICAgdGhpcy5fX2NoaWxkSXRlbXMuc3BsaWNlKGluZGV4LCAwLCBjaGlsZEl0ZW0pOwogICAgICAgICAgICB0aGlzLl9fY2hpbGRJdGVtc0V2ZW50SGFuZGxlcnMuc3BsaWNlKGluZGV4LCAwLCBsaXN0ZW5lcklEcyk7CiAgICAgICAgICAgIC8vIElmIHdlIGhhdmUgbm9uLXVuaXF1ZSBuYW1lcywgd2UgbmVlZCB0byByZWdlbmVyYXRlIHRoaXMgbWFwcGluZy4KICAgICAgICAgICAgaWYgKHRoaXMuY2hpbGRJdGVtc01hcHBpbmdbbmFtZUxjXSkKICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRJdGVtc01hcHBpbmdDb3JydXB0ID0gdHJ1ZTsKICAgICAgICAgICAgdGhpcy5jaGlsZEl0ZW1zTWFwcGluZ1tuYW1lTGNdID0gaW5kZXg7CiAgICAgICAgICAgIHRoaXMudXBkYXRlQ2hpbGROYW1lTWFwcGluZyhpbmRleCArIDEpOwogICAgICAgICAgICBjaGlsZEl0ZW0uc2V0T3duZXIodGhpcyk7CiAgICAgICAgICAgIGlmIChtYWludGFpblhmbykgewogICAgICAgICAgICAgICAgLy8gTWFpbmFpbiB0aGUgcHJldmlvdXMgZ2xvYmFsIFhmby4KICAgICAgICAgICAgICAgIGNoaWxkSXRlbS5nbG9iYWxYZm9QYXJhbS52YWx1ZSA9IHByZXZHbG9iYWw7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5lbWl0KCdjaGlsZEFkZGVkJywgbmV3IENoaWxkQWRkZWRFdmVudChpbmRleCwgY2hpbGRJdGVtKSk7CiAgICAgICAgICAgIHJldHVybiBjaGlsZEl0ZW07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEFkZHMgYSBjaGlsZC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBjaGlsZEl0ZW0gLSBUaGUgY2hpbGQgVHJlZUl0ZW0gdG8gYWRkLgogICAgICAgICAqIEBwYXJhbSBtYWludGFpblhmbyAtIEJvb2xlYW4gdGhhdCBkZXRlcm1pbmVzIGlmCiAgICAgICAgICogdGhlIEdsb2JhbCBYZm8gdmFsdWUgaXMgbWFpbnRhaW5lZC4gSWYgdHJ1ZSwgd2hlbiBtb3ZpbmcKICAgICAgICAgKiBpdGVtcyBpbiB0aGUgaGllcmFyY2h5IGZyb20gb25lIHBhcmVudCB0byBhbm90aGVyLCB0aGUgbG9jYWwgWGZvCiAgICAgICAgICogb2YgdGhlIGl0ZW0gd2lsbCBiZSBtb2RpZmllZCB0byBtYWludGFpbiBhbmQgdGhlIEdsb2JhbCBYZm8uCiAgICAgICAgICogTm90ZTogdGhpcyBvcHRpb24gZGVmYXVsdHMgdG8gZmFsc2UgYmVjYXVzZSB3ZSBleHBlY3QgdGhhdCBpcyB0aGUKICAgICAgICAgKiBiZWhhdmlvciB1c2VycyB3b3VsZCBleHBlY3Qgd2hlbiBtYW5pcHVsYXRpbmcgdGhlIHRyZWUgaW4gY29kZS4KICAgICAgICAgKiBUbyBiZSBzYWZlIGFuZCB1bmFtYmlndW91cywgYWx3YXlzIHRyeSB0byBzcGVjaWZ5IHRoaXMgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGZpeENvbGxpc2lvbnMgLSBNb2RpZnkgdGhlIG5hbWUgb2YgdGhlIGl0ZW0gdG8gYXZvaWQKICAgICAgICAgKiBuYW1lIGNvbGxpc2lvbnMgd2l0aCBvdGhlciBjaGlsZHJlbiBvZiB0aGUgc2FtZSBwYXJlbnQuCiAgICAgICAgICogSWYgZmFsc2UsIGFuIGV4Y2VwdGlvbiB3bGwgYmUgdGhyb3duIGluc3RlYWQgaWYgYSBuYW1lIGNvbGxpc2lvbiBvY2N1cnMuCiAgICAgICAgICogQHJldHVybiBjaGlsZEl0ZW0gLSBUaGUgY2hpbGQgVHJlZUl0ZW0gdGhhdCB3YXMgYWRkZWQuCiAgICAgICAgICovCiAgICAgICAgYWRkQ2hpbGQoY2hpbGRJdGVtLCBtYWludGFpblhmbyA9IHRydWUsIGZpeENvbGxpc2lvbnMgPSB0cnVlKSB7CiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5fX2NoaWxkSXRlbXMubGVuZ3RoOwogICAgICAgICAgICB0aGlzLmluc2VydENoaWxkKGNoaWxkSXRlbSwgaW5kZXgsIG1haW50YWluWGZvLCBmaXhDb2xsaXNpb25zKTsKICAgICAgICAgICAgcmV0dXJuIGNoaWxkSXRlbTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBjaGlsZCBlbGVtZW50IGluIHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdG8gcmVtb3ZlIHRoZSBjaGlsZCBUcmVlSXRlbS4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJuIHRoZSBjaGlsZCBUcmVlSXRlbS4KICAgICAgICAgKi8KICAgICAgICBnZXRDaGlsZChpbmRleCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fX2NoaWxkSXRlbXNbaW5kZXhdOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIGNoaWxkIGVsZW1lbnQgd2l0aCB0aGUgc3BlY2lmaWVkIG5hbWUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm4gdGhlIGNoaWxkIFRyZWVJdGVtLgogICAgICAgICAqLwogICAgICAgIGdldENoaWxkQnlOYW1lKG5hbWUpIHsKICAgICAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLmNoaWxkSXRlbXNNYXBwaW5nW25hbWUudG9Mb2NhbGVMb3dlckNhc2UoKV07CiAgICAgICAgICAgIGlmIChpbmRleCAhPSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9fY2hpbGRJdGVtc1tpbmRleF07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgY2hpbGRyZW4gbmFtZXMgYXMgYW4gYXJyYXkgb2Ygc3RyaW5ncy4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBBbiBhcnJheSBvZiBuYW1lcyBmb3IgZWFjaCBjaGlsZC4KICAgICAgICAgKi8KICAgICAgICBnZXRDaGlsZE5hbWVzKCkgewogICAgICAgICAgICBjb25zdCBuYW1lcyA9IFtdOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX19jaGlsZEl0ZW1zLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBjb25zdCBjaGlsZEl0ZW0gPSB0aGlzLl9fY2hpbGRJdGVtc1tpXTsKICAgICAgICAgICAgICAgIGlmIChjaGlsZEl0ZW0gIT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICBuYW1lc1tpXSA9IGNoaWxkSXRlbS5nZXROYW1lKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIG5hbWVzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBVbkJpbmQgYW4gaXRlbSBmcm9tIHRoZSBncm91cC4gVGhpcyBtZXRob2QgaXMgY2FsbGVkCiAgICAgICAgICogYXV0b21hdGljYWxseSB3aGVuIGFuIGl0ZW0gaXMgcmVtb3ZlZCBmcm9tIHRoZSBncm91cC4KICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGNoaWxkSXRlbSAtIGl0ZW0gdG8gdW5iaW5kLgogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICovCiAgICAgICAgdW5iaW5kQ2hpbGQoaW5kZXgsIGNoaWxkSXRlbSkgewogICAgICAgICAgICBjb25zdCBsaXN0ZW5lcklEcyA9IHRoaXMuX19jaGlsZEl0ZW1zRXZlbnRIYW5kbGVyc1tpbmRleF07CiAgICAgICAgICAgIGNoaWxkSXRlbS5vZmYoJ25hbWVDaGFuZ2VkJywgbGlzdGVuZXJJRHNbJ25hbWVDaGFuZ2VkJ10pOwogICAgICAgICAgICB0aGlzLl9fY2hpbGRJdGVtcy5zcGxpY2UoaW5kZXgsIDEpOwogICAgICAgICAgICB0aGlzLl9fY2hpbGRJdGVtc0V2ZW50SGFuZGxlcnMuc3BsaWNlKGluZGV4LCAxKTsKICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2hpbGRJdGVtc01hcHBpbmdbY2hpbGRJdGVtLm5hbWUudG9Mb2NhbGVMb3dlckNhc2UoKV07CiAgICAgICAgICAgIHRoaXMudXBkYXRlQ2hpbGROYW1lTWFwcGluZyhpbmRleCk7CiAgICAgICAgICAgIHRoaXMuc2V0Qm91bmRpbmdCb3hEaXJ0eSgpOwogICAgICAgICAgICB0aGlzLmVtaXQoJ2NoaWxkUmVtb3ZlZCcsIHsgY2hpbGRJdGVtLCBpbmRleCB9KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmVtb3ZlcyBhIGNoaWxkIFRyZWVJdGVtIGJ5IHNwZWNpZnlpbmcgaXRzIGluZGV4LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gVGhlIGluZGV4IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlbW92ZUNoaWxkKGluZGV4KSB7CiAgICAgICAgICAgIGNvbnN0IGNoaWxkSXRlbSA9IHRoaXMuX19jaGlsZEl0ZW1zW2luZGV4XTsKICAgICAgICAgICAgaWYgKCFjaGlsZEl0ZW0pIHsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnVuYmluZENoaWxkKGluZGV4LCBjaGlsZEl0ZW0pOwogICAgICAgICAgICBjaGlsZEl0ZW0uc2V0T3duZXIodW5kZWZpbmVkKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmVtb3ZlcyBhIGNoaWxkIFRyZWVJdGVtIGJ5IHNwZWNpZnlpbmcgaXRzIG5hbWUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIHBhcmFtLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm4gdGhlIGNoaWxkIFRyZWVJdGVtLgogICAgICAgICAqLwogICAgICAgIHJlbW92ZUNoaWxkQnlOYW1lKG5hbWUpIHsKICAgICAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLmNoaWxkSXRlbXNNYXBwaW5nW25hbWUudG9Mb2NhbGVMb3dlckNhc2UoKV07CiAgICAgICAgICAgIGlmIChpbmRleCAhPSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJlbW92ZUNoaWxkKGluZGV4KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZW1vdmVzIHRoZSBwcm92aWRlZCBpdGVtIGZyb20gdGhpcyBUcmVlSXRlbSBpZiBpdCBpcyBvbmUgb2YgaXRzIGNoaWxkcmVuLgogICAgICAgICAqIEFuIGV4Y2VwdGlvbiBpcyB0aHJvd24gaWYgdGhlIGl0ZW0gaXMgbm90IGEgY2hpbGQgb2YgdGhpcyB0cmVlIGl0ZW0uCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gY2hpbGRJdGVtIC0gVGhlIGNoaWxkIFRyZWVJdGVtIHRvIHJlbW92ZS4KICAgICAgICAgKi8KICAgICAgICByZW1vdmVDaGlsZEJ5SGFuZGxlKGNoaWxkSXRlbSkgewogICAgICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMuX19jaGlsZEl0ZW1zLmluZGV4T2YoY2hpbGRJdGVtKTsKICAgICAgICAgICAgaWYgKGluZGV4ID09IC0xKQogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFcnJvciBpbiByZW1vdmVDaGlsZEJ5SGFuZGxlLiBDaGlsZCBub3QgZm91bmQ6JyArIGNoaWxkSXRlbS5nZXROYW1lKCkpOwogICAgICAgICAgICB0aGlzLnJlbW92ZUNoaWxkKGluZGV4KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmVtb3ZlcyBhbGwgY2hpbGRyZW4gSXRlbXMuCiAgICAgICAgICovCiAgICAgICAgcmVtb3ZlQWxsQ2hpbGRyZW4oKSB7CiAgICAgICAgICAgIGxldCBpbmRleCA9IHRoaXMuX19jaGlsZEl0ZW1zLmxlbmd0aDsKICAgICAgICAgICAgd2hpbGUgKGluZGV4LS0pIHsKICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlQ2hpbGQoaW5kZXgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuc2V0Qm91bmRpbmdCb3hEaXJ0eSgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIGluZGV4IHBvc2l0aW9uIG9mIHRoZSBzcGVjaWZpZWQgaXRlbS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBjaGlsZEl0ZW0gLSBUaGUgY2hpbGQgVHJlZUl0ZW0gdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIENoaWxkIGluZGV4IGluIGNoaWxkcmVuIGFycmF5LgogICAgICAgICAqLwogICAgICAgIGdldENoaWxkSW5kZXgoY2hpbGRJdGVtKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9fY2hpbGRJdGVtcy5pbmRleE9mKGNoaWxkSXRlbSk7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQYXRoIFRyYXZlcnNhbAogICAgICAgIC8vIE5vdGU6IFBhdGggcmVzb2x1dGlvbiBzdGFydHMgYXQgdGhlIHJvb3Qgb2YgdGhlCiAgICAgICAgLy8gdHJlZSB0aGUgcGF0aCB3YXMgZ2VuZXJhdGVkIGZyb20gKHNvIGluZGV4PTEsIGJlY2F1c2Ugd2UgZG9uJ3QgcmVzb2x2ZSByb290KS4KICAgICAgICAvLyBOb3RlOiBXaGVuIGEgcGF0aCBpcyBtYWRlIHJlbGF0aXZlIHRvIGFuIGl0ZW0gaW4gaXRzIHRyZWUsIHRoZSBwYXRoCiAgICAgICAgLy8gc3RhcnRzIHdpdGggdGhlIGNoaWxkIGVsZW1lbnRzLgogICAgICAgIC8qKgogICAgICAgICAqIFRoZSByZXNvbHZlUGF0aCBtZXRob2QgdHJhdmVyc2VzIHRoZSBzdWJ0cmVlIGZyb20gdGhpcyBpdGVtIGRvd24KICAgICAgICAgKiBtYXRjaGluZyBlYWNoIG5hbWUgaW4gdGhlIHBhdGggd2l0aCBhIGNoaWxkIHVudGlsIGl0IHJlYWNoZXMgdGhlCiAgICAgICAgICogZW5kIG9mIHRoZSBwYXRoLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHBhdGggLSBUaGUgcGF0aCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgaW5kZXggdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgcmVzb2x2ZVBhdGgocGF0aCwgaW5kZXggPSAwKSB7CiAgICAgICAgICAgIGlmIChpbmRleCA9PSAwKSB7CiAgICAgICAgICAgICAgICBpZiAocGF0aFswXSA9PSAnLicgfHwgcGF0aFswXSA9PSB0aGlzLm5hbWUpCiAgICAgICAgICAgICAgICAgICAgaW5kZXgrKzsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocGF0aFtpbmRleF0gPT0gJy4uJykgewogICAgICAgICAgICAgICAgaWYgKHRoaXMub3duZXJJdGVtKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMub3duZXJJdGVtLnJlc29sdmVQYXRoKHBhdGgsIGluZGV4ICsgMSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcigndGhpcy5vd25lckl0ZW0gaXMgdW5kZWZpbmVkJyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGluZGV4ID09IHBhdGgubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBjaGlsZE5hbWUgPSBwYXRoW2luZGV4XTsKICAgICAgICAgICAgY29uc3QgY2hpbGRJdGVtID0gdGhpcy5nZXRDaGlsZEJ5TmFtZShjaGlsZE5hbWUpOwogICAgICAgICAgICBpZiAoY2hpbGRJdGVtKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gY2hpbGRJdGVtLnJlc29sdmVQYXRoKHBhdGgsIGluZGV4ICsgMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHN1cGVyLnJlc29sdmVQYXRoKHBhdGgsIGluZGV4KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVHJhdmVyc2UgdGhlIHRyZWUgc3RydWN0dXJlIGZyb20gdGhpcyBwb2ludCBkb3duCiAgICAgICAgICogYW5kIGZpcmUgdGhlIGNhbGxiYWNrIGZvciBlYWNoIHZpc2l0ZWQgaXRlbS4KICAgICAgICAgKiBOb3RlOiBEZXB0aCBvbmx5IHVzZWQgYnkgc2VsZWN0aW9uIHNldHMgZm9yIG5vdy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBjYWxsYmFjayAtIFRoZSBjYWxsYmFjayB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gaW5jbHVkZVRoaXMgLSBGaXJlIHRoZSBjYWxsYmFjayBmb3IgdGhpcyBpdGVtLgogICAgICAgICAqLwogICAgICAgIHRyYXZlcnNlKGNhbGxiYWNrLCBpbmNsdWRlVGhpcyA9IHRydWUpIHsKICAgICAgICAgICAgY29uc3QgX19jID0gKHRyZWVJdGVtLCBkZXB0aCkgPT4gewogICAgICAgICAgICAgICAgY29uc3QgY2hpbGRyZW4gPSB0cmVlSXRlbS5nZXRDaGlsZHJlbigpOwogICAgICAgICAgICAgICAgZm9yIChjb25zdCBjaGlsZEl0ZW0gb2YgY2hpbGRyZW4pIHsKICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGRJdGVtKQogICAgICAgICAgICAgICAgICAgICAgICBfX3QoY2hpbGRJdGVtLCBkZXB0aCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIGNvbnN0IF9fdCA9ICh0cmVlSXRlbSwgZGVwdGgpID0+IHsKICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjayh0cmVlSXRlbSwgZGVwdGgpID09IGZhbHNlKQogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIF9fYyh0cmVlSXRlbSwgZGVwdGggKyAxKTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgaWYgKGluY2x1ZGVUaGlzKSB7CiAgICAgICAgICAgICAgICBfX3QodGhpcywgMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBfX2ModGhpcywgMCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBFdmVudHMKICAgICAgICAvKioKICAgICAgICAgKiBDYWxsZWQgYnkgdGhlIFZpZXdwb3J0IHdoZW4gZXZlbnRzIGFyZSByZWNlaXZlZCBieSB0aGUgY2FudmFzIGVsZW1lbnQuCiAgICAgICAgICogVGhlIGV2ZW50IGlzIHByb3BhZ2F0ZWQgdG8gYSBUcmVlSXRlbSBpZiBpdCBpcyB1bmRlciB0aGUgcG9pbnRlciBhdCB0aGUgdGltZS4KICAgICAgICAgKiBUaGUgWmVhUG9pbnRlckV2ZW50IGFic3RyYWN0cyB0aGUgTW91c2UsIHRvdWNoIGFuZCBvdXIgY3VzdG9tIFhSIGV2ZW50cy4KICAgICAgICAgKiBUaGlzIG1ldGhvZCBlbWl0cyB0aGUgWmVhUG9pbnRlckV2ZW50IHdpdGggdGhlIGtleSAncG9pbnRlckRvd24nLCBhbmQKICAgICAgICAgKiBwcm9wYWdhdGVzIGl0IHVwIHRvIHRoZSBUcmVlSXRlbSdzIG93bmVyLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGV2ZW50IC0gVGhlIGV2ZW50IHZhbHVlCiAgICAgICAgICovCiAgICAgICAgb25Qb2ludGVyRG93bihldmVudCkgewogICAgICAgICAgICB0aGlzLmVtaXQoJ3BvaW50ZXJEb3duJywgZXZlbnQpOwogICAgICAgICAgICBpZiAoZXZlbnQucHJvcGFnYXRpbmcgJiYgdGhpcy5vd25lckl0ZW0gaW5zdGFuY2VvZiBUcmVlSXRlbSkgewogICAgICAgICAgICAgICAgdGhpcy5vd25lckl0ZW0ub25Qb2ludGVyRG93bihldmVudCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsbGVkIGJ5IHRoZSBWaWV3cG9ydCB3aGVuIGV2ZW50cyBhcmUgcmVjZWl2ZWQgYnkgdGhlIGNhbnZhcyBlbGVtZW50LgogICAgICAgICAqIFRoZSBldmVudCBpcyBwcm9wYWdhdGVkIHRvIGEgVHJlZUl0ZW0gaWYgaXQgaXMgdW5kZXIgdGhlIHBvaW50ZXIgYXQgdGhlIHRpbWUuCiAgICAgICAgICogVGhlIFplYVBvaW50ZXJFdmVudCBhYnN0cmFjdHMgdGhlIE1vdXNlLCB0b3VjaCBhbmQgb3VyIGN1c3RvbSBYUiBldmVudHMuCiAgICAgICAgICogVGhpcyBtZXRob2QgZW1pdHMgdGhlIFplYVBvaW50ZXJFdmVudCB3aXRoIHRoZSBrZXkgJ3BvaW50ZXJEb3duJywgYW5kCiAgICAgICAgICogcHJvcGFnYXRlcyBpdCB1cCB0byB0aGUgVHJlZUl0ZW0ncyBvd25lci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBldmVudCAtIFRoZSBwb2ludGVyIGV2ZW50IHRoYXQgd2FzIGdlbmVyYXRlZCBmcm9tIHRoZSB1c2VyIGludGVyYWN0aW9uCiAgICAgICAgICovCiAgICAgICAgb25Qb2ludGVyVXAoZXZlbnQpIHsKICAgICAgICAgICAgdGhpcy5lbWl0KCdwb2ludGVyVXAnLCBldmVudCk7CiAgICAgICAgICAgIGlmIChldmVudC5wcm9wYWdhdGluZyAmJiB0aGlzLm93bmVySXRlbSBpbnN0YW5jZW9mIFRyZWVJdGVtKSB7CiAgICAgICAgICAgICAgICB0aGlzLm93bmVySXRlbS5vblBvaW50ZXJVcChldmVudCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsbGVkIGJ5IHRoZSBWaWV3cG9ydCB3aGVuIGV2ZW50cyBhcmUgcmVjZWl2ZWQgYnkgdGhlIGNhbnZhcyBlbGVtZW50LgogICAgICAgICAqIFRoZSBldmVudCBpcyBwcm9wYWdhdGVkIHRvIGEgVHJlZUl0ZW0gaWYgaXQgaXMgdW5kZXIgdGhlIHBvaW50ZXIgYXQgdGhlIHRpbWUuCiAgICAgICAgICogVGhlIFplYVBvaW50ZXJFdmVudCBhYnN0cmFjdHMgdGhlIE1vdXNlLCB0b3VjaCBhbmQgb3VyIGN1c3RvbSBYUiBldmVudHMuCiAgICAgICAgICogVGhpcyBtZXRob2QgZW1pdHMgdGhlIFplYVBvaW50ZXJFdmVudCB3aXRoIHRoZSBrZXkgJ3BvaW50ZXJNb3ZlJywgYW5kCiAgICAgICAgICogcHJvcGFnYXRlcyBpdCB1cCB0byB0aGUgVHJlZUl0ZW0ncyBvd25lci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBldmVudCAtIFRoZSBwb2ludGVyIGV2ZW50IHRoYXQgd2FzIGdlbmVyYXRlZCBmcm9tIHRoZSB1c2VyIGludGVyYWN0aW9uCiAgICAgICAgICovCiAgICAgICAgb25Qb2ludGVyTW92ZShldmVudCkgewogICAgICAgICAgICB0aGlzLmVtaXQoJ3BvaW50ZXJNb3ZlJywgZXZlbnQpOwogICAgICAgICAgICBpZiAoZXZlbnQucHJvcGFnYXRpbmcgJiYgdGhpcy5vd25lckl0ZW0gaW5zdGFuY2VvZiBUcmVlSXRlbSkgewogICAgICAgICAgICAgICAgdGhpcy5vd25lckl0ZW0ub25Qb2ludGVyTW92ZShldmVudCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsbGVkIGJ5IHRoZSBWaWV3cG9ydCB3aGVuIHRoZSBtb3VzZSBvciBvdGhlciBwb2ludGVyIGVudGVycyB0aGUgY2FudmFzIGVsZW1lbnQuCiAgICAgICAgICogVGhlIGV2ZW50IGlzIHByb3BhZ2F0ZWQgdG8gYSBUcmVlSXRlbSBpZiBpdCBpcyB1bmRlciB0aGUgcG9pbnRlciBhdCB0aGUgdGltZS4KICAgICAgICAgKiBUaGUgWmVhUG9pbnRlckV2ZW50IGFic3RyYWN0cyB0aGUgTW91c2UsIHRvdWNoIGFuZCBvdXIgY3VzdG9tIFhSIGV2ZW50cy4KICAgICAgICAgKiBUaGlzIG1ldGhvZCBlbWl0cyB0aGUgWmVhUG9pbnRlckV2ZW50IHdpdGggdGhlIGtleSAncG9pbnRlckVudGVyJywgYW5kCiAgICAgICAgICogcHJvcGFnYXRlcyBpdCB1cCB0byB0aGUgVHJlZUl0ZW0ncyBvd25lci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBldmVudCAtIFRoZSBwb2ludGVyIGV2ZW50IHRoYXQgd2FzIGdlbmVyYXRlZCBmcm9tIHRoZSB1c2VyIGludGVyYWN0aW9uCiAgICAgICAgICovCiAgICAgICAgb25Qb2ludGVyRW50ZXIoZXZlbnQpIHsKICAgICAgICAgICAgdGhpcy5lbWl0KCdwb2ludGVyRW50ZXInLCBldmVudCk7CiAgICAgICAgICAgIGlmIChldmVudC5wcm9wYWdhdGluZyAmJiB0aGlzLm93bmVySXRlbSBpbnN0YW5jZW9mIFRyZWVJdGVtKSB7CiAgICAgICAgICAgICAgICB0aGlzLm93bmVySXRlbS5vblBvaW50ZXJFbnRlcihldmVudCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsbGVkIGJ5IHRoZSBWaWV3cG9ydCB3aGVuIHRoZSBtb3VzZSBvciBvdGhlciBwb2ludGVyIGxlYXZlcyB0aGUgY2FudmFzIGVsZW1lbnQuCiAgICAgICAgICogVGhlIGV2ZW50IGlzIHByb3BhZ2F0ZWQgdG8gYSBUcmVlSXRlbSBpZiBpdCBpcyB1bmRlciB0aGUgcG9pbnRlciBhdCB0aGUgdGltZS4KICAgICAgICAgKiBUaGUgWmVhUG9pbnRlckV2ZW50IGFic3RyYWN0cyB0aGUgTW91c2UsIHRvdWNoIGFuZCBvdXIgY3VzdG9tIFhSIGV2ZW50cy4KICAgICAgICAgKiBUaGlzIG1ldGhvZCBlbWl0cyB0aGUgWmVhUG9pbnRlckV2ZW50IHdpdGggdGhlIGtleSAncG9pbnRlckxlYXZlJywgYW5kCiAgICAgICAgICogcHJvcGFnYXRlcyBpdCB1cCB0byB0aGUgVHJlZUl0ZW0ncyBvd25lci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBldmVudCAtIFRoZSBwb2ludGVyIGV2ZW50IHRoYXQgd2FzIGdlbmVyYXRlZCBmcm9tIHRoZSB1c2VyIGludGVyYWN0aW9uCiAgICAgICAgICovCiAgICAgICAgb25Qb2ludGVyTGVhdmUoZXZlbnQpIHsKICAgICAgICAgICAgdGhpcy5lbWl0KCdwb2ludGVyTGVhdmUnLCBldmVudCk7CiAgICAgICAgICAgIGlmIChldmVudC5wcm9wYWdhdGluZyAmJiB0aGlzLm93bmVySXRlbSBpbnN0YW5jZW9mIFRyZWVJdGVtKSB7CiAgICAgICAgICAgICAgICB0aGlzLm93bmVySXRlbS5vblBvaW50ZXJMZWF2ZShldmVudCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsbGVkIGJ5IHRoZSBWaWV3cG9ydCB3aGVuIHRoZSBtb3VzZSBvciBvdGhlciBwb2ludGVyIGlzIGNsaWNrZWQgb24gdGhpcyBpdGVtLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGV2ZW50IC0gVGhlIHBvaW50ZXIgZXZlbnQgdGhhdCB3YXMgZ2VuZXJhdGVkIGZyb20gdGhlIHVzZXIgaW50ZXJhY3Rpb24KICAgICAgICAgKi8KICAgICAgICBvblBvaW50ZXJDbGljayhldmVudCkgewogICAgICAgICAgICB0aGlzLmVtaXQoJ3BvaW50ZXJDbGljaycsIGV2ZW50KTsKICAgICAgICAgICAgaWYgKGV2ZW50LnByb3BhZ2F0aW5nICYmIHRoaXMub3duZXJJdGVtIGluc3RhbmNlb2YgVHJlZUl0ZW0pIHsKICAgICAgICAgICAgICAgIHRoaXMub3duZXJJdGVtLm9uUG9pbnRlckNsaWNrKGV2ZW50KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDYWxsZWQgYnkgdGhlIFZpZXdwb3J0IHdoZW4gdGhlIG1vdXNlIG9yIG90aGVyIHBvaW50ZXIgaXMgZG91YmxlLWNsaWNrZWQgb24gdGhpcyBpdGVtLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGV2ZW50IC0gVGhlIHBvaW50ZXIgZXZlbnQgdGhhdCB3YXMgZ2VuZXJhdGVkIGZyb20gdGhlIHVzZXIgaW50ZXJhY3Rpb24KICAgICAgICAgKi8KICAgICAgICBvblBvaW50ZXJEb3VibGVDbGljayhldmVudCkgewogICAgICAgICAgICB0aGlzLmVtaXQoJ3BvaW50ZXJEb3VibGVDbGljaycsIGV2ZW50KTsKICAgICAgICAgICAgaWYgKGV2ZW50LnByb3BhZ2F0aW5nICYmIHRoaXMub3duZXJJdGVtIGluc3RhbmNlb2YgVHJlZUl0ZW0pIHsKICAgICAgICAgICAgICAgIHRoaXMub3duZXJJdGVtLm9uUG9pbnRlckRvdWJsZUNsaWNrKGV2ZW50KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDYWxsZWQgYnkgdGhlIFZpZXdwb3J0IHdoZW4gdGhlIG1vdXNlIG9yIG90aGVyIHBvaW50ZXIgaXMgZG91YmxlLWNsaWNrZWQgb24gdGhpcyBpdGVtLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGV2ZW50IC0gVGhlIHBvaW50ZXIgZXZlbnQgdGhhdCB3YXMgZ2VuZXJhdGVkIGZyb20gdGhlIHVzZXIgaW50ZXJhY3Rpb24KICAgICAgICAgKi8KICAgICAgICBvblBvaW50ZXJMb25nUHJlc3MoZXZlbnQpIHsKICAgICAgICAgICAgdGhpcy5lbWl0KCdwb2ludGVyTG9uZ1ByZXNzJywgZXZlbnQpOwogICAgICAgICAgICBpZiAoZXZlbnQucHJvcGFnYXRpbmcgJiYgdGhpcy5vd25lckl0ZW0gaW5zdGFuY2VvZiBUcmVlSXRlbSkgewogICAgICAgICAgICAgICAgdGhpcy5vd25lckl0ZW0ub25Qb2ludGVyTG9uZ1ByZXNzKGV2ZW50KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDYWxsZWQgYnkgdGhlIFZpZXdwb3J0IHdoZW4gdGhlIG1vdXNlIHdoZWVsIGV2ZW50IGlzIHJlY2VpdmVkIGJ5IHRoZSBjYW52YXMgZWxlbWVudC4KICAgICAgICAgKiBFbWl0cyB0aGUgWmVhV2hlZWxFdmVudCB3aXRoIHRoZSBrZXkgJ21vdXNlV2hlZWwnLCBhbmQgUHJvcGFnYXRlcyBpcyB1cCB0byB0aGUgVHJlZUl0ZW0ncyBvd25lci4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBldmVudCAtIFRoZSB3aGVlbCBldmVudCB0aGF0IG9jY3Vycy4KICAgICAgICAgKi8KICAgICAgICBvbldoZWVsKGV2ZW50KSB7CiAgICAgICAgICAgIHRoaXMuZW1pdCgnbW91c2VXaGVlbCcsIGV2ZW50KTsKICAgICAgICAgICAgaWYgKGV2ZW50LnByb3BhZ2F0aW5nICYmIHRoaXMub3duZXJJdGVtIGluc3RhbmNlb2YgVHJlZUl0ZW0pIHsKICAgICAgICAgICAgICAgIHRoaXMub3duZXJJdGVtLm9uV2hlZWwoZXZlbnQpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENhbGxlZCBieSB0aGUgVmlld3BvcnQgd2hlbiB0aGUgdG91Y2ggY2FuY2VsIGV2ZW50IGlzIHJlY2VpdmVkIGJ5IHRoZSBjYW52YXMgZWxlbWVudC4KICAgICAgICAgKiBFbWl0cyB0aGUgWmVhVG91Y2hFdmVudCB3aXRoIHRoZSBrZXkgJ3RvdWNoQ2FuY2VsJywgYW5kIFByb3BhZ2F0ZXMgaXMgdXAgdG8gdGhlIFRyZWVJdGVtJ3Mgb3duZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gZXZlbnQgLSBUaGUgd2hlZWwgZXZlbnQgdGhhdCBvY2N1cnMuCiAgICAgICAgICovCiAgICAgICAgb25Ub3VjaENhbmNlbChldmVudCkgewogICAgICAgICAgICB0aGlzLmVtaXQoJ3RvdWNoQ2FuY2VsJywgZXZlbnQpOwogICAgICAgICAgICBpZiAoZXZlbnQucHJvcGFnYXRpbmcgJiYgdGhpcy5vd25lckl0ZW0gaW5zdGFuY2VvZiBUcmVlSXRlbSkgewogICAgICAgICAgICAgICAgdGhpcy5vd25lckl0ZW0ub25Ub3VjaENhbmNlbChldmVudCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIFBlcnNpc3RlbmNlCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHRvSlNPTiBtZXRob2Qgc2VyaWFsaXplcyB0aGlzIGluc3RhbmNlIGFzIGEgSlNPTi4KICAgICAgICAgKiBJdCBjYW4gYmUgdXNlZCBmb3IgcGVyc2lzdGVuY2UsIGRhdGEgdHJhbnNmZXIsIGV0Yy4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIGxldCBqID0gc3VwZXIudG9KU09OKGNvbnRleHQpOwogICAgICAgICAgICAvLyBTb21lIEl0ZW1zLCBzdWNoIGFzIHRoZSBTbGlkZXJTY2VuZVdpZGdldCBkbyBub3QgbmVlZCB0aGVpciBjaGlsZHJlbgogICAgICAgICAgICAvLyB0byBiZSBzYXZlZC4KICAgICAgICAgICAgY29uc3QgY2hpbGRJdGVtc0pTT04gPSB7fTsKICAgICAgICAgICAgZm9yIChjb25zdCBjaGlsZEl0ZW0gb2YgdGhpcy5fX2NoaWxkSXRlbXMpIHsKICAgICAgICAgICAgICAgIGlmIChjaGlsZEl0ZW0pIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGlsZEpTT04gPSBjaGlsZEl0ZW0udG9KU09OKGNvbnRleHQpOwogICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZEpTT04pCiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkSXRlbXNKU09OW2NoaWxkSXRlbS5nZXROYW1lKCldID0gY2hpbGRKU09OOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChPYmplY3Qua2V5cyhjaGlsZEl0ZW1zSlNPTikubGVuZ3RoID4gMCkgewogICAgICAgICAgICAgICAgaWYgKGopIHsKICAgICAgICAgICAgICAgICAgICBqLmNoaWxkcmVuID0gY2hpbGRJdGVtc0pTT047CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBqID0gewogICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiB0aGlzLm5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBjaGlsZEl0ZW1zSlNPTiwKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBqOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIHRha2VzIGEgSlNPTiBhbmQgZGVzZXJpYWxpemVzIGludG8gYW4gaW5zdGFuY2Ugb2YgdGhpcyB0eXBlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGogLSBUaGUganNvbiBvYmplY3QgdGhpcyBpdGVtIG11c3QgZGVjb2RlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZnJvbUpTT04oaiwgY29udGV4dCwgb25Eb25lKSB7CiAgICAgICAgICAgIHN1cGVyLmZyb21KU09OKGosIGNvbnRleHQpOwogICAgICAgICAgICAvLyBpZiAoJ2Jib3gnIGluIGopewogICAgICAgICAgICAvLyAgICAgbGV0IGJveCA9IG5ldyBCb3gzKCk7CiAgICAgICAgICAgIC8vICAgICBib3guZnJvbUpTT04oai5iYm94KTsKICAgICAgICAgICAgLy8gICAgIHRoaXMuYm91bmRpbmdCb3hQYXJhbS52YWx1ZSA9IGJveCkKICAgICAgICAgICAgLy8gfQogICAgICAgICAgICBpZiAoai5jaGlsZHJlbiAhPSBudWxsKSB7CiAgICAgICAgICAgICAgICBjb25zdCBjaGlsZHJlbkpzb24gPSBqLmNoaWxkcmVuOwogICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY2hpbGRyZW5Kc29uKSkgewogICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgY2hpbGRKc29uIG9mIGNoaWxkcmVuSnNvbikgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBOb3RlOiBEdXJpbmcgbG9hZGluZyBvZiBhc3NldCB0cmVlcywgd2UgaGF2ZSBhbgogICAgICAgICAgICAgICAgICAgICAgICAvLyBleGlzdGluZyB0cmVlIGdlbmVyYXRlZCBieSBsb2FkaW5nIGEgYmluIGRhdGEgZmlsZS4KICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNoaWxkSXRlbSA9IHRoaXMuZ2V0Q2hpbGRCeU5hbWUoY2hpbGRKc29uLm5hbWUpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGRJdGVtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZEl0ZW0uZnJvbUpTT04oY2hpbGRKc29uLCBjb250ZXh0KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZEpzb24udHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkSXRlbSA9IFJlZ2lzdHJ5LmNvbnN0cnVjdENsYXNzKGNoaWxkSnNvbi50eXBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGRJdGVtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vdGU6IHdlIHNob3VsZCBsb2FkIHRoZSBqc29uIGZpcnN0LCBhcyBpdAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtYXkgY29udGFpbiB0aGUgdW5pcXVlIG5hbWUgb2YgdGhlIGl0ZW0uCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkSXRlbS5mcm9tSlNPTihjaGlsZEpzb24sIGNvbnRleHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZENoaWxkKGNoaWxkSXRlbSwgZmFsc2UsIGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZ3VhcmQtZm9yLWluCiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBjaGlsZE5hbWUgaW4gY2hpbGRyZW5Kc29uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNoaWxkSnNvbiA9IGNoaWxkcmVuSnNvbltjaGlsZE5hbWVdOwogICAgICAgICAgICAgICAgICAgICAgICAvLyBOb3RlOiBEdXJpbmcgbG9hZGluZyBvZiBhc3NldCB0cmVlcywgd2UgaGF2ZSBhbgogICAgICAgICAgICAgICAgICAgICAgICAvLyBleGlzdGluZyB0cmVlIGdlbmVyYXRlZCBieSBsb2FkaW5nIGEgYmluIGRhdGEgZmlsZS4KICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNoaWxkSXRlbSA9IHRoaXMuZ2V0Q2hpbGRCeU5hbWUoY2hpbGROYW1lKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkSXRlbSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRJdGVtLmZyb21KU09OKGNoaWxkSnNvbiwgY29udGV4dCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY2hpbGRKc29uLnR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkSXRlbSA9IFJlZ2lzdHJ5LmNvbnN0cnVjdENsYXNzKGNoaWxkSnNvbi50eXBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZEl0ZW0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOb3RlOiB3ZSBhZGQgdGhlIGNoaWxkIG5vdyBiZWZvcmUgbG9hZGluZy4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIGJlY2F1c2UgY2VydGFpbiBpdGVtcy4gKGUuZy4gR3JvdXBzKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENhbGN1bGF0ZSB0aGVpciBnbG9iYWwgWGZvLCBhbmQgdXNlIGl0IHRvIG1vZGlmeQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSB0cmFuc2Zvcm0gb2YgdGhlaXIgbWVtYmVycy4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOb3RlOiBHcm91cHMgYmluZCB0byBpdGVtcyBpbiB0aGUgc2NlbmUgd2hpY2ggYXJlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWxyZWFkeSBhZGRlZCBhcyBjaGlsZHJlbiwgYW5kIHNvIGhhdmUgZ2xvYmFsIFhmb3MuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgcHJlZmVyIHRvIGFkZCBhIGNoaWxkIGFmdGVyIGl0cyBsb2FkZWQsIGJlY2F1c2Ugc29tZXRpbWVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW4gdGhlIHRyZWUgaXMgYXNzZXQgaXRlbXMsIHdobyB3aWxsIG9ubHkgdG9nZ2xlZCBhcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHVubG9hZGVkIG9uY2UgdGhleSBhcmUgbG9hZGVkKGVsc2UgdGhleSBhcmUgY29uc2lkZXJlZCBpbmxpbmUgYXNzZXRzLikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZEl0ZW0uZnJvbUpTT04oY2hpbGRKc29uLCBjb250ZXh0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZENoaWxkKGNoaWxkSXRlbSwgZmFsc2UsIGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gaWYgKGouY29tcG9uZW50cykgewogICAgICAgICAgICAvLyAgIGZvciAoY29uc3QgY2ogb2Ygai5jb21wb25lbnRzKSB7CiAgICAgICAgICAgIC8vICAgICBjb25zdCBjb21wb25lbnQgPSBSZWdpc3RyeS5jb25zdHJ1Y3RDbGFzcyhjai50eXBlID8gY2oudHlwZSA6IGNqLm5hbWUpCiAgICAgICAgICAgIC8vICAgICBpZiAoY29tcG9uZW50KSB7CiAgICAgICAgICAgIC8vICAgICAgIGNvbXBvbmVudC5mcm9tSlNPTihjaiwgY29udGV4dCkKICAgICAgICAgICAgLy8gICAgICAgdGhpcy5hZGRDb21wb25lbnQoY29tcG9uZW50KQogICAgICAgICAgICAvLyAgICAgfQogICAgICAgICAgICAvLyAgIH0KICAgICAgICAgICAgLy8gfQogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHN0YXRlIG9mIGN1cnJlbnQgSXRlbShJbmNsdWRpbmcgcGFyYW1ldGVycyAmIGNoaWxkcmVuKSB1c2luZyBhIGJpbmFyeSByZWFkZXIgb2JqZWN0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHJlYWRlciAtIFRoZSByZWFkZXIgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICByZWFkQmluYXJ5KHJlYWRlciwgY29udGV4dCkgewogICAgICAgICAgICBzdXBlci5yZWFkQmluYXJ5KHJlYWRlciwgY29udGV4dCk7CiAgICAgICAgICAgIGNvbnN0IGl0ZW1GbGFncyA9IHJlYWRlci5sb2FkVUludDgoKTsKICAgICAgICAgICAgY29uc3QgdmlzaWJpbGl0eUZsYWcgPSAxIDw8IDE7CiAgICAgICAgICAgIC8vIE5vdGU6IFhSZWYgbG9hZHMgYSB2aXNpYmxpdHkgc2V0dGluZyBmb3IgaXRzZWxmIHdoZW4gbG9hZGluZyBpbiB0aGUgcGFyZW50IGFzc2VtYmx5IHRyZWUsCiAgICAgICAgICAgIC8vIHRoZW4gaXQgbG9hZHMgdGhlIHpjYWQgZmlsZSB3aGljaCBjb250YWlucyBhIHZpc2liaWxpdHkgc2V0dGluZyBmb3IgdGhlIENBREFzc3NldC4gVGhpcwogICAgICAgICAgICAvLyB2aXNpYmlsaXR5IHNldHRpbmcgd291bGQgb3ZlcnJpZGUgdGhlIFhSZWYuIElkZWFsbHkgdGhlIHpjYWQgZmlsZSB3b3VsZCBub3Qgc3RvcmUgYSB2aXNpYmxpdHkKICAgICAgICAgICAgLy8gc2V0dGluZyBmb3IgdGhlIENBREFzc2V0LCBhcyB0aGF0IHNob3VsZCBiZSBzZXQgYnkgdGhlIGxvYWRpbmcgY29udGV4dC4KICAgICAgICAgICAgLy8gVmlzaWJsZSBpcyB0cnVlIGJ5IGRlZmF1bHQsIHNvIG9ubHkgc2V0IGl0IHRvIGZhbHNlLiBUaGlzIGlzIHRvIHdvcmsgYXJvdW5kIHRoZSBhYm92ZSBjb25mbGljdC4KICAgICAgICAgICAgaWYgKChpdGVtRmxhZ3MgJiB2aXNpYmlsaXR5RmxhZykgPT0gMCkKICAgICAgICAgICAgICAgIHRoaXMuc2V0VmlzaWJsZShmYWxzZSk7CiAgICAgICAgICAgIC8vIE5vdGU6IHRvIHNhdmUgc3BhY2UsIHNvbWUgdmFsdWVzIGFyZSBza2lwcGVkIGlmIHRoZXkgYXJlIGlkZW50aXR5IHZhbHVlcwogICAgICAgICAgICBjb25zdCBsb2NhbFhmb0ZsYWcgPSAxIDw8IDI7CiAgICAgICAgICAgIGNvbnN0IGxvY2FsWGZvSW5kZXBlbmRlbnRTY0ZsYWcgPSAxIDw8IDU7CiAgICAgICAgICAgIGlmIChpdGVtRmxhZ3MgJiBsb2NhbFhmb0ZsYWcpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHhmbyA9IG5ldyBYZm8oKTsKICAgICAgICAgICAgICAgIHhmby50ciA9IHJlYWRlci5sb2FkRmxvYXQzMlZlYzMoKTsKICAgICAgICAgICAgICAgIHhmby5vcmkgPSByZWFkZXIubG9hZEZsb2F0MzJRdWF0KCk7CiAgICAgICAgICAgICAgICBpZiAoaXRlbUZsYWdzICYgbG9jYWxYZm9JbmRlcGVuZGVudFNjRmxhZykgewogICAgICAgICAgICAgICAgICAgIHhmby5zYyA9IHJlYWRlci5sb2FkRmxvYXQzMlZlYzMoKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHNjID0gcmVhZGVyLmxvYWRGbG9hdDMyKCk7CiAgICAgICAgICAgICAgICAgICAgeGZvLnNjLnNldChzYywgc2MsIHNjKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRoaXMubG9jYWxYZm9QYXJhbS52YWx1ZSA9IHhmbzsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBiYm94RmxhZyA9IDEgPDwgMzsKICAgICAgICAgICAgaWYgKGl0ZW1GbGFncyAmIGJib3hGbGFnKSB7CiAgICAgICAgICAgICAgICB0aGlzLmJvdW5kaW5nQm94UGFyYW0ubG9hZFZhbHVlKG5ldyBCb3gzKHJlYWRlci5sb2FkRmxvYXQzMlZlYzMoKSwgcmVhZGVyLmxvYWRGbG9hdDMyVmVjMygpKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgbnVtQ2hpbGRyZW4gPSByZWFkZXIubG9hZFVJbnQzMigpOwogICAgICAgICAgICBpZiAobnVtQ2hpbGRyZW4gPiAwKSB7CiAgICAgICAgICAgICAgICBjb25zdCB0b2MgPSByZWFkZXIubG9hZFVJbnQzMkFycmF5KG51bUNoaWxkcmVuKTsKICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQ2hpbGRyZW47IGkrKykgewogICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRlci5zZWVrKHRvY1tpXSk7IC8vIFJlc2V0IHRoZSBwb2ludGVyIHRvIHRoZSBzdGFydCBvZiB0aGUgaXRlbSBkYXRhLgogICAgICAgICAgICAgICAgICAgICAgICBsZXQgY2hpbGRUeXBlID0gcmVhZGVyLmxvYWRTdHIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hpbGRJdGVtID0gUmVnaXN0cnkuY29uc3RydWN0Q2xhc3MoY2hpbGRUeXBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjaGlsZEl0ZW0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNoaWxkTmFtZSA9IHJlYWRlci5sb2FkU3RyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1VuYWJsZSB0byBjb25zdHJ1Y3QgY2hpbGQ6JyArIGNoaWxkTmFtZSArICcgb2YgdHlwZTonICsgY2hpbGRUeXBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRlci5zZWVrKHRvY1tpXSk7IC8vIFJlc2V0IHRoZSBwb2ludGVyIHRvIHRoZSBzdGFydCBvZiB0aGUgaXRlbSBkYXRhLgogICAgICAgICAgICAgICAgICAgICAgICBjaGlsZEl0ZW0ucmVhZEJpbmFyeShyZWFkZXIsIGNvbnRleHQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZENoaWxkKGNoaWxkSXRlbSwgZmFsc2UsIHRydWUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0Vycm9yIGxvYWRpbmcgdHJlZSBpdGVtOiAnLCBlKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIENsb25lIGFuZCBEZXN0cm95CiAgICAgICAgY2xvbmUoY29udGV4dCkgewogICAgICAgICAgICBjb25zdCBjbG9uZWQgPSBuZXcgVHJlZUl0ZW0oJycpOwogICAgICAgICAgICBjbG9uZWQuY29weUZyb20odGhpcywgY29udGV4dCk7CiAgICAgICAgICAgIHJldHVybiBjbG9uZWQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENvcGllcyBjdXJyZW50IFRyZWVJdGVtIHdpdGggYWxsIGl0cyBjaGlsZHJlbi4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBzcmMgLSBUaGUgdHJlZSBpdGVtIHRvIGNvcHkgZnJvbS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGNvcHlGcm9tKHNyYywgY29udGV4dCkgewogICAgICAgICAgICBpZiAoIShzcmMgaW5zdGFuY2VvZiBUcmVlSXRlbSkpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignY2Fubm90IGNvcHkgZnJvbSBzcmMnKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdXBlci5jb3B5RnJvbShzcmMsIGNvbnRleHQpOwogICAgICAgICAgICAvLyBOb3RlOiBjb25maWd1cmUgdmlzaWJsaXR5IGFuZCBvcGFjaXR5IGJlZm9yZSBhZGRpbmcgY2hpbGRyZW4uIFRoZXkgd2lsbAogICAgICAgICAgICAvLyBpbmhlcml0IHRoZXNlIHNldHRpbmdzIGFzIHRoZXkgYXJlIGFkZGVkLgogICAgICAgICAgICB0aGlzLnZpc2libGVDb3VudGVyID0gdGhpcy52aXNpYmxlUGFyYW0udmFsdWUgPyAxIDogMDsKICAgICAgICAgICAgdGhpcy51cGRhdGVWaXNpYmlsaXR5KCk7CiAgICAgICAgICAgIHRoaXMudXBkYXRlT3BhY2l0eSgpOwogICAgICAgICAgICAvLyBOb3RlOiBJZiBhIHRyZWUgaXRlbSBhbHJlYWR5IGhhZCBjaGlsZHJlbiwgd2UgbXVzdCBjbGVhciB0aGVtIGJlZm9yZSBhZGRpbmcgZnJvbSB0aGUgc3JjLgogICAgICAgICAgICAvLyBBbiBYUmVmIHN0b3JlZCBpbiBhbiBhc3NlbWJseSBtYXkgY29udGFpbiBhIGNhY2hlIG9mIGl0cyBzdWJ0cmVlLgogICAgICAgICAgICAvLyBJZiB0aGUgWFJlZiB1cmwgZG9lcyByZXNvbHZlIHRvIGEgZmlsZSwgd2UgbXVzdCBjbGVhciB0aGlzIGNhY2hlIGJlZm9yZSBsb2FkaW5nIHRoZSBhY3R1YWwgZGF0YS4KICAgICAgICAgICAgdGhpcy5yZW1vdmVBbGxDaGlsZHJlbigpOwogICAgICAgICAgICBzcmMuZ2V0Q2hpbGRyZW4oKS5mb3JFYWNoKChzcmNDaGlsZEl0ZW0pID0+IHsKICAgICAgICAgICAgICAgIGlmIChzcmNDaGlsZEl0ZW0pCiAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRDaGlsZChzcmNDaGlsZEl0ZW0uY2xvbmUoY29udGV4dCksIGZhbHNlLCBmYWxzZSk7CiAgICAgICAgICAgIH0pOwogICAgICAgIH0KICAgIH0KICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdUcmVlSXRlbScsIFRyZWVJdGVtKTsKCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55ICovCiAgICAvKioKICAgICAqIFJlcHJlc2VudHMgYSBzcGVjaWZpYyB0eXBlIG9mIHBhcmFtZXRlciwgdGhhdCBvbmx5IHN0b3JlcyBgVHJlZUl0ZW1gIHZhbHVlcy4KICAgICAqCiAgICAgKiBpLmUuOgogICAgICogYGBgamF2YXNjcmlwdAogICAgICogY29uc3QgdHJlZUl0ZW0gPSBuZXcgVHJlZUl0ZW0oJ3RyZWUxJykKICAgICAqIGNvbnN0IHRyZWVJdGVtUGFyYW0gPSBuZXcgVHJlZUl0ZW1QYXJhbWV0ZXIoJ015VHJlZUl0ZW0nLCB0cmVlSXRlbSkKICAgICAqIC8vJ215UGFyYW1ldGVyT3duZXJJdGVtJyBpcyBhbiBpbnN0YW5jZSBvZiBhICdQYXJhbWV0ZXJPd25lcicgY2xhc3MuCiAgICAgKiAvLyBSZW1lbWJlciB0aGF0IG9ubHkgJ1BhcmFtZXRlck93bmVyJyBhbmQgY2xhc3NlcyB0aGF0IGV4dGVuZCBmcm9tIGl0IGNhbiBob3N0ICdQYXJhbWV0ZXInIG9iamVjdHMuCiAgICAgKiBteVBhcmFtZXRlck93bmVySXRlbS5hZGRQYXJhbWV0ZXIodHJlZUl0ZW1QYXJhbSkKICAgICAqIGBgYAogICAgICoKICAgICAqICoqRXZlbnRzKioKICAgICAqICogKip0cmVlSXRlbUdsb2JhbFhmb0NoYW5nZWQ6KiogVHJpZ2dlcmVkIHdoZW4gY29tcHV0ZWQgd29ybGQgWGZvIG9mIHBhcmFtZXRlcidzIGBUcmVlSXRlbWAgY2hhbmdlcy4KICAgICAqICogKip2YWx1ZUNoYW5nZWQ6KiogVHJpZ2dlcmVkIHdoZW4gcGFyYW1ldGVyJ3MgdmFsdWUgY2hhbmdlcy4KICAgICAqCiAgICAgKiBAZXh0ZW5kcyBQYXJhbWV0ZXIKICAgICAqLwogICAgY2xhc3MgVHJlZUl0ZW1QYXJhbWV0ZXIgZXh0ZW5kcyBQYXJhbWV0ZXIgewogICAgICAgIGZpbHRlckZuOwogICAgICAgIGxpc3RlbmVySURzID0ge307CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlIGEgdHJlZSBpdGVtIHBhcmFtZXRlci4KICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0cmVlIGl0ZW0gcGFyYW1ldGVyLgogICAgICAgICAqIEBwYXJhbSBmaWx0ZXJGbiAtIFRoZSBmaWx0ZXJGbiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3RvcihuYW1lID0gJycsIGZpbHRlckZuKSB7CiAgICAgICAgICAgIHN1cGVyKG5hbWUsIG51bGwsICdUcmVlSXRlbScpOwogICAgICAgICAgICB0aGlzLmZpbHRlckZuID0gZmlsdGVyRm47CiAgICAgICAgfQogICAgICAgIGVtaXRUcmVlSXRlbUdsb2JhbFhmb0NoYW5nZWQoZXZlbnQpIHsKICAgICAgICAgICAgdGhpcy5lbWl0KCd0cmVlSXRlbUdsb2JhbFhmb0NoYW5nZWQnLCBldmVudCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBzZXRGaWx0ZXJGbiBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIGZpbHRlckZuIC0gVGhlIGZpbHRlckZuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldEZpbHRlckZuKGZpbHRlckZuKSB7CiAgICAgICAgICAgIHRoaXMuZmlsdGVyRm4gPSBmaWx0ZXJGbjsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGdldEZpbHRlckZuIG1ldGhvZC4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRGaWx0ZXJGbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmlsdGVyRm47CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgcGFyYW1ldGVyJ3MgYFRyZWVJdGVtYCB2YWx1ZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB0cmVlSXRlbSB2YWx1ZQogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldFZhbHVlKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgVHJlZUl0ZW0pKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHZhbHVlIHByb3ZpZGVkIGlzIG5vdCBhbiBpbnN0YW5jZSBvZiBhICdUcmVlSXRlbScgY2xhc3MuIENoZWNrIHRoZSBzb3VyY2Ugb2YgdGhpcyB2YWx1ZWApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIDAgPT0gbm9ybWFsIHNldC4gMSA9IGNoYW5nZWQgdmlhIGNsZWFuZXIgZm4sIDI9Y2hhbmdlIGJ5IGxvYWRpbmcvY2xvbmluZyBjb2RlLgogICAgICAgICAgICBpZiAodGhpcy5maWx0ZXJGbiAmJiAhdGhpcy5maWx0ZXJGbih2YWx1ZSkpCiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIGlmICh0aGlzLnZhbHVlICE9PSB2YWx1ZSkgewogICAgICAgICAgICAgICAgaWYgKHRoaXMudmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLnZhbHVlLm9mZignZ2xvYmFsWGZvQ2hhbmdlZCcsIHRoaXMubGlzdGVuZXJJRHNbJ2dsb2JhbFhmb0NoYW5nZWQnXSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdXBlci5zZXRWYWx1ZSh2YWx1ZSk7CiAgICAgICAgICAgICAgICBpZiAodGhpcy52YWx1ZSkgewogICAgICAgICAgICAgICAgICAgIHRoaXMubGlzdGVuZXJJRHNbJ2dsb2JhbFhmb0NoYW5nZWQnXSA9IHRoaXMudmFsdWUub24oJ2dsb2JhbFhmb0NoYW5nZWQnLCAoZXZlbnQpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0VHJlZUl0ZW1HbG9iYWxYZm9DaGFuZ2VkKGV2ZW50KTsKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdG9KU09OIG1ldGhvZCBlbmNvZGVzIHRoaXMgdHlwZSBhcyBhIGpzb24gb2JqZWN0IGZvciBwZXJzaXN0ZW5jZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLmdldENsYXNzTmFtZSgpLAogICAgICAgICAgICAgICAgbmFtZTogdGhpcy5uYW1lLAogICAgICAgICAgICAgICAgdmFsdWU6IGNvbnRleHQubWFrZVJlbGF0aXZlKHRoaXMudmFsdWU/LmdldFBhdGgoKSksCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBmcm9tSlNPTiBtZXRob2QgZGVjb2RlcyBhIGpzb24gb2JqZWN0IGZvciB0aGlzIHR5cGUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gaiAtIFRoZSBqc29uIG9iamVjdCB0aGlzIGl0ZW0gbXVzdCBkZWNvZGUuCiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBmcm9tSlNPTihqLCBjb250ZXh0KSB7CiAgICAgICAgICAgIGlmIChqLnZhbHVlID09IG51bGwpIHsKICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignSW52YWxpZCBQYXJhbWV0ZXIgSlNPTicpOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnRleHQucmVzb2x2ZVBhdGgoai52YWx1ZSwgKHRyZWVJdGVtKSA9PiB7CiAgICAgICAgICAgICAgICB0aGlzLnNldFZhbHVlKHRyZWVJdGVtKTsKICAgICAgICAgICAgfSwgKCkgPT4gewogICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdVbmFibGUgdG8gcmVzb2x2ZSB0cmVlIGl0ZW0gcGFyYW1ldGVyIHZhbHVlOicgKyBqLnBhcmFtUGF0aCk7CiAgICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gQ2xvbmUgYW5kIERlc3Ryb3kKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgY2xvbmUgbWV0aG9kIGNvbnN0cnVjdHMgYSBuZXcgdHJlZSBpdGVtIHBhcmFtZXRlciwgY29waWVzIGl0cyB2YWx1ZXMKICAgICAgICAgKiBmcm9tIHRoaXMgcGFyYW1ldGVyIGFuZCByZXR1cm5zIGl0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgdHJlZSBpdGVtIHBhcmFtZXRlci4KICAgICAgICAgKi8KICAgICAgICBjbG9uZShjb250ZXh0KSB7CiAgICAgICAgICAgIGNvbnN0IGNsb25lZFBhcmFtID0gbmV3IFRyZWVJdGVtUGFyYW1ldGVyKHRoaXMubmFtZSwgdGhpcy5maWx0ZXJGbik7CiAgICAgICAgICAgIGlmICh0aGlzLnZhbHVlKQogICAgICAgICAgICAgICAgY2xvbmVkUGFyYW0uc2V0VmFsdWUodGhpcy52YWx1ZS5jbG9uZShjb250ZXh0KSk7CiAgICAgICAgICAgIHJldHVybiBjbG9uZWRQYXJhbTsKICAgICAgICB9CiAgICB9CiAgICBSZWdpc3RyeS5yZWdpc3RlcignVHJlZUl0ZW1QYXJhbWV0ZXInLCBUcmVlSXRlbVBhcmFtZXRlcik7CgogICAgLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqLwogICAgY2xhc3MgSXRlbUV2ZW50IGV4dGVuZHMgQmFzZUV2ZW50IHsKICAgICAgICBpdGVtOwogICAgICAgIGluZGV4OwogICAgICAgIGNvbnN0cnVjdG9yKGl0ZW0sIGluZGV4KSB7CiAgICAgICAgICAgIHN1cGVyKCk7CiAgICAgICAgICAgIHRoaXMuaW5kZXggPSBpbmRleDsKICAgICAgICAgICAgdGhpcy5pdGVtID0gaXRlbTsKICAgICAgICB9CiAgICB9CiAgICAvKiogQ2xhc3MgcmVwcmVzZW50aW5nIGFuIGl0ZW0gc2V0IHBhcmFtZXRlci4KICAgICAqIEBleHRlbmRzIFBhcmFtZXRlcgogICAgICogQHByaXZhdGUKICAgICAqLwogICAgY2xhc3MgSXRlbVNldFBhcmFtZXRlciBleHRlbmRzIFBhcmFtZXRlciB7CiAgICAgICAgZmlsdGVyRm47CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlIGFuIGl0ZW0gc2V0IHBhcmFtZXRlci4KICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBpdGVtIHNldCBwYXJhbWV0ZXIuCiAgICAgICAgICogQHBhcmFtIGZpbHRlckZuIC0gVGhlIGZpbHRlckZuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKG5hbWUgPSAnJywgZmlsdGVyRm4pIHsKICAgICAgICAgICAgc3VwZXIobmFtZSwgbmV3IFNldCgpLCAnVHJlZUl0ZW0nKTsKICAgICAgICAgICAgdGhpcy5maWx0ZXJGbiA9IGZpbHRlckZuOyAvLyBOb3RlOiB0aGUgZmlsdGVyIEZuIGluZGljYXRlcyB0aGF0IHVzZXJzIHdpbGwgZWRpdCB0aGUgc2V0LgogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgc2V0RmlsdGVyRm4gbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSBmaWx0ZXJGbiAtIFRoZSBmaWx0ZXJGbiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRGaWx0ZXJGbihmaWx0ZXJGbikgewogICAgICAgICAgICB0aGlzLmZpbHRlckZuID0gZmlsdGVyRm47CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBnZXRGaWx0ZXJGbiBtZXRob2QuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0RmlsdGVyRm4oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbHRlckZuOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZ2V0SXRlbSBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIGluZGV4IC0gVGhlIGluZGV4IHBhcmFtLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldEl0ZW0oaW5kZXgpIHsKICAgICAgICAgICAgLy8gaWYgKCF0aGlzLl9faXRlbXMpIHJldHVybiB1bmRlZmluZWQKICAgICAgICAgICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy52YWx1ZSlbaW5kZXhdOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgYWRkSXRlbSBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIGl0ZW0gLSBUaGUgaXRlbSB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gZW1pdFZhbHVlQ2hhbmdlZCAtIFRoZSBlbWl0IHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGFkZEl0ZW0oaXRlbSwgZW1pdFZhbHVlQ2hhbmdlZCA9IHRydWUpIHsKICAgICAgICAgICAgaWYgKHRoaXMuZmlsdGVyRm4gJiYgIXRoaXMuZmlsdGVyRm4oaXRlbSkpIHsKICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignSXRlbVNldCBfX2ZpbHRlckZuIHJlamVjdGluZyBpdGVtOicsIGl0ZW0uZ2V0UGF0aCgpKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoIXRoaXMudmFsdWUuaGFzKGl0ZW0pKSB7CiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlLmFkZChpdGVtKTsKICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gQXJyYXkuZnJvbSh0aGlzLnZhbHVlKS5pbmRleE9mKGl0ZW0pOwogICAgICAgICAgICAgICAgdGhpcy5lbWl0KCdpdGVtQWRkZWQnLCBuZXcgSXRlbUV2ZW50KGl0ZW0sIGluZGV4KSk7CiAgICAgICAgICAgICAgICBpZiAoZW1pdFZhbHVlQ2hhbmdlZCkKICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXQoJ3ZhbHVlQ2hhbmdlZCcpOwogICAgICAgICAgICAgICAgcmV0dXJuIGluZGV4OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgcmV0dXJuIC0xOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEFkZHMgaXRlbXMgdG8gdGhlIHBhcmFtZXRlciB2YWx1ZQogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGl0ZW1zIC0gbGlzdCBvZiBpdGVtcyB0byBhZGQgdG8gdGhlIHBhcmFtZXRlcgogICAgICAgICAqIEBwYXJhbSBlbWl0VmFsdWVDaGFuZ2VkCiAgICAgICAgICogQG1lbWJlcm9mIEl0ZW1TZXRQYXJhbWV0ZXIKICAgICAgICAgKi8KICAgICAgICBhZGRJdGVtcyhpdGVtcywgZW1pdFZhbHVlQ2hhbmdlZCA9IHRydWUpIHsKICAgICAgICAgICAgaXRlbXMuZm9yRWFjaCgoaXRlbSkgPT4gdGhpcy5hZGRJdGVtKGl0ZW0sIGZhbHNlKSk7CiAgICAgICAgICAgIGlmIChlbWl0VmFsdWVDaGFuZ2VkKQogICAgICAgICAgICAgICAgdGhpcy5lbWl0KCd2YWx1ZUNoYW5nZWQnKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHJlbW92ZUl0ZW0gbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gZW1pdFZhbHVlQ2hhbmdlZCAtIFRoZSBlbWl0IHBhcmFtLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlbW92ZUl0ZW0oaW5kZXgsIGVtaXRWYWx1ZUNoYW5nZWQgPSB0cnVlKSB7CiAgICAgICAgICAgIGNvbnN0IGl0ZW0gPSBBcnJheS5mcm9tKHRoaXMudmFsdWUpW2luZGV4XTsKICAgICAgICAgICAgdGhpcy52YWx1ZS5kZWxldGUoaXRlbSk7CiAgICAgICAgICAgIHRoaXMuZW1pdCgnaXRlbVJlbW92ZWQnLCBuZXcgSXRlbUV2ZW50KGl0ZW0sIGluZGV4KSk7CiAgICAgICAgICAgIGlmIChlbWl0VmFsdWVDaGFuZ2VkKQogICAgICAgICAgICAgICAgdGhpcy5lbWl0KCd2YWx1ZUNoYW5nZWQnKTsKICAgICAgICAgICAgcmV0dXJuIGl0ZW07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBzZXRJdGVtcyBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIGl0ZW1zIC0gVGhlIGl0ZW0gcGFyYW0uCiAgICAgICAgICogQHBhcmFtIGVtaXQgLSBUaGUgZW1pdCBwYXJhbS4KICAgICAgICAgKi8KICAgICAgICBzZXRJdGVtcyhpdGVtcywgZW1pdCA9IHRydWUpIHsKICAgICAgICAgICAgY29uc3QgdmFsdWVzID0gQXJyYXkuZnJvbSh0aGlzLnZhbHVlKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IHZhbHVlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgICAgICAgICAgICAgY29uc3QgaXRlbSA9IHZhbHVlc1tpXTsKICAgICAgICAgICAgICAgIGlmICghaXRlbXMuaGFzKGl0ZW0pKSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVJdGVtKGksIGZhbHNlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHsKICAgICAgICAgICAgICAgIGlmICghdGhpcy52YWx1ZS5oYXMoaXRlbSkpIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZEl0ZW0oaXRlbSwgZmFsc2UpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChlbWl0KQogICAgICAgICAgICAgICAgdGhpcy5lbWl0KCd2YWx1ZUNoYW5nZWQnKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGNsZWFySXRlbXMgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSBlbWl0IC0gVGhlIGVtaXQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgY2xlYXJJdGVtcyhlbWl0VmFsdWVDaGFuZ2VkID0gdHJ1ZSkgewogICAgICAgICAgICB0aGlzLnZhbHVlLmNsZWFyKCk7CiAgICAgICAgICAgIGlmIChlbWl0VmFsdWVDaGFuZ2VkKQogICAgICAgICAgICAgICAgdGhpcy5lbWl0KCd2YWx1ZUNoYW5nZWQnKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGdldE51bUl0ZW1zIG1ldGhvZC4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXROdW1JdGVtcygpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWUuc2l6ZTsgLy8gbWlnaHQgYmUgZmFzdGVyCiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQZXJzaXN0ZW5jZQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSB0b0pTT04gbWV0aG9kIGVuY29kZXMgdGhpcyB0eXBlIGFzIGEganNvbiBvYmplY3QgZm9yIHBlcnNpc3RlbmNlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgdG9KU09OKGNvbnRleHQpIHsKICAgICAgICAgICAgaWYgKCF0aGlzLnZhbHVlKQogICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IG5ldyBTZXQoKTsKICAgICAgICAgICAgY29uc3QgcGF0aHMgPSBbXTsKICAgICAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHRoaXMudmFsdWUpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHBhdGggPSBpdGVtLmdldFBhdGgoKTsKICAgICAgICAgICAgICAgIHBhdGhzLnB1c2goY29udGV4dCAmJiBjb250ZXh0Lm1ha2VSZWxhdGl2ZSA/IGNvbnRleHQubWFrZVJlbGF0aXZlKHBhdGgpIDogcGF0aCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIHR5cGU6IHRoaXMuZ2V0Q2xhc3NOYW1lKCksCiAgICAgICAgICAgICAgICBuYW1lOiB0aGlzLm5hbWUsCiAgICAgICAgICAgICAgICB2YWx1ZTogcGF0aHMsCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBmcm9tSlNPTiBtZXRob2QgZGVjb2RlcyBhIGpzb24gb2JqZWN0IGZvciB0aGlzIHR5cGUuCiAgICAgICAgICogQHBhcmFtIGogLSBUaGUganNvbiBvYmplY3QgdGhpcyBpdGVtIG11c3QgZGVjb2RlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZnJvbUpTT04oaiwgY29udGV4dCkgewogICAgICAgICAgICBpZiAoIWNvbnRleHQgfHwgIWNvbnRleHQucmVzb2x2ZVBhdGgpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGxvYWQgSlNPTiBvbiBhIEl0ZW1TZXRQYXJhbWV0ZXIgd2l0aG91dCBhIGxvYWQgY29udGV4dCcpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IHBhdGhzID0gai52YWx1ZTsKICAgICAgICAgICAgcGF0aHMuZm9yRWFjaCgocGF0aCkgPT4gewogICAgICAgICAgICAgICAgY29udGV4dC5yZXNvbHZlUGF0aChwYXRoLCAodHJlZUl0ZW0pID0+IHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZEl0ZW0odHJlZUl0ZW0sIGZhbHNlKTsKICAgICAgICAgICAgICAgIH0sICgpID0+IHsKICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oIkJhc2VHcm91cDogJyIgKyB0aGlzLmdldE5hbWUoKSArICInLiBVbmFibGUgdG8gbG9hZCBpdGVtOiIgKyBwYXRoKTsKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIENsb25lCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGNsb25lIG1ldGhvZCBjb25zdHJ1Y3RzIGEgaXRlbSBzZXQgbmV3IHBhcmFtZXRlciwgY29waWVzIGl0cyB2YWx1ZXMKICAgICAgICAgKiBmcm9tIHRoaXMgcGFyYW1ldGVyIGFuZCByZXR1cm5zIGl0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBuZXcgaXRlbSBzZXQgcGFyYW1ldGVyLgogICAgICAgICAqLwogICAgICAgIGNsb25lKCkgewogICAgICAgICAgICBjb25zdCBjbG9uZWRQYXJhbSA9IG5ldyBJdGVtU2V0UGFyYW1ldGVyKHRoaXMubmFtZSwgdGhpcy5maWx0ZXJGbik7CiAgICAgICAgICAgIHJldHVybiBjbG9uZWRQYXJhbTsKICAgICAgICB9CiAgICB9CiAgICBSZWdpc3RyeS5yZWdpc3RlcignSXRlbVNldFBhcmFtZXRlcicsIEl0ZW1TZXRQYXJhbWV0ZXIpOwoKICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi8KICAgIGNvbnN0IHBhcnNlOEJpdFBvc2l0aW9uc0FycmF5ID0gKHJhbmdlLCBvZmZzZXQsIHNjbFZlYywgcG9zaXRpb25zX3F1YW50aXplZCwgcG9zaXRpb25zQXR0cikgPT4gewogICAgICAgIGZvciAobGV0IGkgPSByYW5nZVswXTsgaSA8IHJhbmdlWzFdOyBpKyspIHsKICAgICAgICAgICAgY29uc3QgcG9zID0gbmV3IFZlYzMocG9zaXRpb25zX3F1YW50aXplZFtpICogMyArIDBdIC8gMjU1LjAsIHBvc2l0aW9uc19xdWFudGl6ZWRbaSAqIDMgKyAxXSAvIDI1NS4wLCBwb3NpdGlvbnNfcXVhbnRpemVkW2kgKiAzICsgMl0gLyAyNTUuMCk7CiAgICAgICAgICAgIHBvcy5tdWx0aXBseUluUGxhY2Uoc2NsVmVjKTsKICAgICAgICAgICAgcG9zLmFkZEluUGxhY2Uob2Zmc2V0KTsKICAgICAgICAgICAgcG9zaXRpb25zQXR0ci5zZXRWYWx1ZShpLCBwb3MpOwogICAgICAgIH0KICAgIH07CiAgICBjb25zdCBwYXJzZTE2Qml0UG9zaXRpb25zQXJyYXkgPSAocmFuZ2UsIG9mZnNldCwgc2NsVmVjLCBwb3NpdGlvbnNfcXVhbnRpemVkLCBwb3NpdGlvbnNBdHRyKSA9PiB7CiAgICAgICAgZm9yIChsZXQgaSA9IHJhbmdlWzBdOyBpIDwgcmFuZ2VbMV07IGkrKykgewogICAgICAgICAgICBjb25zdCBwb3MgPSBuZXcgVmVjMyhwb3NpdGlvbnNfcXVhbnRpemVkW2kgKiAzICsgMF0gLyA2NTUzNS4wLCBwb3NpdGlvbnNfcXVhbnRpemVkW2kgKiAzICsgMV0gLyA2NTUzNS4wLCBwb3NpdGlvbnNfcXVhbnRpemVkW2kgKiAzICsgMl0gLyA2NTUzNS4wKTsKICAgICAgICAgICAgcG9zLm11bHRpcGx5SW5QbGFjZShzY2xWZWMpOwogICAgICAgICAgICBwb3MuYWRkSW5QbGFjZShvZmZzZXQpOwogICAgICAgICAgICBwb3NpdGlvbnNBdHRyLnNldFZhbHVlKGksIHBvcyk7CiAgICAgICAgfQogICAgfTsKICAgIGNvbnN0IHBhcnNlOEJpdE5vcm1hbHNBcnJheSA9IChyYW5nZSwgb2Zmc2V0LCBzY2xWZWMsIG5vcm1hbHNfcXVhbnRpemVkLCBub3JtYWxzQXR0cikgPT4gewogICAgICAgIGlmIChzY2xWZWMuaXNOdWxsKCkpCiAgICAgICAgICAgIHNjbFZlYy5zZXQoMSwgMSwgMSk7CiAgICAgICAgZm9yIChsZXQgaSA9IHJhbmdlWzBdOyBpIDwgcmFuZ2VbMV07IGkrKykgewogICAgICAgICAgICBjb25zdCBub3JtYWwgPSBuZXcgVmVjMyhub3JtYWxzX3F1YW50aXplZFtpICogMyArIDBdIC8gMjU1LjAsIG5vcm1hbHNfcXVhbnRpemVkW2kgKiAzICsgMV0gLyAyNTUuMCwgbm9ybWFsc19xdWFudGl6ZWRbaSAqIDMgKyAyXSAvIDI1NS4wKTsKICAgICAgICAgICAgbm9ybWFsLm11bHRpcGx5SW5QbGFjZShzY2xWZWMpOwogICAgICAgICAgICBub3JtYWwuYWRkSW5QbGFjZShvZmZzZXQpOwogICAgICAgICAgICBub3JtYWwubm9ybWFsaXplSW5QbGFjZSgpOwogICAgICAgICAgICBub3JtYWxzQXR0ci5zZXRWYWx1ZShpLCBub3JtYWwpOwogICAgICAgIH0KICAgIH07CiAgICBjb25zdCBwYXJzZThCaXRUZXh0dXJlQ29vcmRzQXJyYXkgPSAocmFuZ2UsIG9mZnNldCwgc2NsVmVjLCB0ZXhDb29yZHNfcXVhbnRpemVkLCB0ZXhDb29yZHNBdHRyKSA9PiB7CiAgICAgICAgLy8gaWYgKHNjbFZlYy5pc051bGwoKSkKICAgICAgICAvLyAgICAgc2NsVmVjLnNldCgxLCAxLCAxKTsKICAgICAgICBmb3IgKGxldCBpID0gcmFuZ2VbMF07IGkgPCByYW5nZVsxXTsgaSsrKSB7CiAgICAgICAgICAgIGNvbnN0IHRleHR1cmVDb29yZCA9IG5ldyBWZWMyKHRleENvb3Jkc19xdWFudGl6ZWRbaSAqIDIgKyAwXSAvIDI1NS4wLCB0ZXhDb29yZHNfcXVhbnRpemVkW2kgKiAyICsgMV0gLyAyNTUuMCk7CiAgICAgICAgICAgIHRleHR1cmVDb29yZC5tdWx0aXBseUluUGxhY2Uoc2NsVmVjKTsKICAgICAgICAgICAgdGV4dHVyZUNvb3JkLmFkZEluUGxhY2Uob2Zmc2V0KTsKICAgICAgICAgICAgdGV4Q29vcmRzQXR0ci5zZXRWYWx1ZShpLCB0ZXh0dXJlQ29vcmQpOwogICAgICAgIH0KICAgIH07CiAgICBjb25zdCBwYXJzZTE2Qml0VGV4dHVyZUNvb3Jkc0FycmF5ID0gKHJhbmdlLCBvZmZzZXQsIHNjbFZlYywgdGV4Q29vcmRzX3F1YW50aXplZCwgdGV4Q29vcmRzQXR0cikgPT4gewogICAgICAgIC8vIGlmIChzY2xWZWMuaXNOdWxsKCkpCiAgICAgICAgLy8gICAgIHNjbFZlYy5zZXQoMSwgMSwgMSk7CiAgICAgICAgZm9yIChsZXQgaSA9IHJhbmdlWzBdOyBpIDwgcmFuZ2VbMV07IGkrKykgewogICAgICAgICAgICBjb25zdCB0ZXh0dXJlQ29vcmQgPSBuZXcgVmVjMih0ZXhDb29yZHNfcXVhbnRpemVkW2kgKiAyICsgMF0gLyA2NTUzNS4wLCB0ZXhDb29yZHNfcXVhbnRpemVkW2kgKiAyICsgMV0gLyA2NTUzNS4wKTsKICAgICAgICAgICAgdGV4dHVyZUNvb3JkLm11bHRpcGx5SW5QbGFjZShzY2xWZWMpOwogICAgICAgICAgICB0ZXh0dXJlQ29vcmQuYWRkSW5QbGFjZShvZmZzZXQpOwogICAgICAgICAgICB0ZXhDb29yZHNBdHRyLnNldFZhbHVlKGksIHRleHR1cmVDb29yZCk7CiAgICAgICAgfQogICAgfTsKICAgIC8qKgogICAgICogUmVwcmVzZW50cyBhIGJhc2UgY2xhc3MgZm9yIDNEIGdlb21ldHJ5IGl0ZW1zLgogICAgICoKICAgICAqICoqRXZlbnRzKioKICAgICAqICogKipib3VuZGluZ0JveENoYW5nZWQ6KiogVHJpZ2dlcmVkIHdoZW4gdGhlIGJvdW5kaW5nIGJveCBjaGFuZ2VzLgogICAgICogKiAqKmdlb21EYXRhQ2hhbmdlZDoqKiBFbWl0dGVkIHdoZW4gdGhlIGdlb21ldHJ5IGF0dHJpYnV0ZXMgaGF2ZSBjaGFuZ2VkLiBUaGUgdG9wb2xvZ3kgZGlkIG5vdCBjaGFuZ2UuIFRoZSBSZW5kZXJlciB3aWxsIHVwbG9hZCB0aGUgbmV3IGF0dHJpYnV0ZXMgdG8gdGhlIEdQVS4KICAgICAqICogKipnZW9tRGF0YVRvcG9sb2d5Q2hhbmdlZDoqKiBFbWl0dGVkIHdoZW4gdGhlIGdlb21ldHJ5IGF0dHJpYnV0ZXMgYW5kIHRvcG9sb2d5IGhhdmUgY2hhbmdlZC4gIFRoZSBSZW5kZXJlciB3aWxsIHVwbG9hZCB0aGUgbmV3IGF0dHJpYnV0ZXMgYW5kIHRvcG9sb2d5IHRvIHRoZSBHUFUuCiAgICAgKgogICAgICogQGV4dGVuZHMgUGFyYW1ldGVyT3duZXIKICAgICAqLwogICAgY2xhc3MgQmFzZUdlb20gZXh0ZW5kcyBQYXJhbWV0ZXJPd25lciB7CiAgICAgICAgYm91bmRpbmdCb3ggPSBuZXcgQm94MygpOwogICAgICAgIGJvdW5kaW5nQm94RGlydHkgPSB0cnVlOwogICAgICAgIF9fbWV0YURhdGEgPSBuZXcgTWFwKCk7CiAgICAgICAgI251bVZlcnRpY2VzID0gMDsKICAgICAgICBfX3ZlcnRleEF0dHJpYnV0ZXMgPSBuZXcgTWFwKCk7CiAgICAgICAgZGVidWdDb2xvciA9IG5ldyBDb2xvcigxLCAwLCAwLCAxKTsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgYSBiYXNlIGdlb20uCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgICAgIHN1cGVyKCk7CiAgICAgICAgICAgIHRoaXMuYWRkVmVydGV4QXR0cmlidXRlKCdwb3NpdGlvbnMnLCBuZXcgVmVjM2YxNkF0dHJpYnV0ZSgpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgY3VycmVudCBwYXRoIG9mIHRoZSBpdGVtIGluIHRoZSB0cmVlIGFzIGFuIGFycmF5IG9mIG5hbWVzLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYW4gYXJyYXkuCiAgICAgICAgICovCiAgICAgICAgZ2V0UGF0aCgpIHsKICAgICAgICAgICAgaWYgKHRoaXMub3duZXJJdGVtID09IHVuZGVmaW5lZCkKICAgICAgICAgICAgICAgIHJldHVybiBbdGhpcy5uYW1lXTsKICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5vd25lckl0ZW0gaW5zdGFuY2VvZiBQYXJhbWV0ZXIpIHsKICAgICAgICAgICAgICAgIHJldHVybiBbLi4udGhpcy5vd25lckl0ZW0uZ2V0UGF0aCgpLCAndmFsdWUnXTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHJldHVybiBbLi4udGhpcy5vd25lckl0ZW0uZ2V0UGF0aCgpLCB0aGlzLm5hbWVdOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBjbGVhciBtZXRob2QuCiAgICAgICAgICovCiAgICAgICAgY2xlYXIoKSB7CiAgICAgICAgICAgIHRoaXMuc2V0TnVtVmVydGljZXMoMCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEFkZHMgYSBuZXcgdmVydGV4IGF0dHJpYnV0ZSB0byB0aGUgZ2VvbWV0cnkuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB2ZXJ0ZXggYXR0cmlidXRlLgogICAgICAgICAqIEBwYXJhbSBkYXRhVHlwZSAtIFRoZSBkYXRhVHlwZSB2YWx1ZS4gLy8gVE9ETzogaXMgYW55IG9rIHZzLiBBdHRyVmFsdWUgfCBudW1iZXIuIFVuc3VyZSBhYm91dCBob3cgZGF0YVR5cGUgaXMgdXNlZAogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGFuIGF0dHJpYnV0ZS4KICAgICAgICAgKi8KICAgICAgICBhZGRWZXJ0ZXhBdHRyaWJ1dGUobmFtZSwgYXR0cikgewogICAgICAgICAgICBhdHRyLnNldENvdW50KHRoaXMuI251bVZlcnRpY2VzKTsKICAgICAgICAgICAgdGhpcy5fX3ZlcnRleEF0dHJpYnV0ZXMuc2V0KG5hbWUsIGF0dHIpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDaGVja3MgaWYgdGhlIHRoZSBnZW9tZXRyeSBoYXMgYW4gYXR0cmlidXRlIHdpdGggdGhlIHNwZWNpZmllZCBuYW1lLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdmVydGV4IGF0dHJpYnV0ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBoYXNWZXJ0ZXhBdHRyaWJ1dGUobmFtZSkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fX3ZlcnRleEF0dHJpYnV0ZXMuaGFzKG5hbWUpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHZlcnRleCBhdHRyaWJ1dGUgd2l0aCB0aGUgc3BlY2lmaWVkIG5hbWUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB2ZXJ0ZXggYXR0cmlidXRlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldFZlcnRleEF0dHJpYnV0ZShuYW1lKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9fdmVydGV4QXR0cmlidXRlcy5nZXQobmFtZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYWxsIHZlcnRleCBhdHRyaWJ1dGVzIGluIGFuIG9iamVjdCB3aXRoIHRoZWlyIG5hbWVzLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0VmVydGV4QXR0cmlidXRlcygpIHsKICAgICAgICAgICAgY29uc3QgdmVydGV4QXR0cmlidXRlcyA9IHt9OwogICAgICAgICAgICBmb3IgKGNvbnN0IFtrZXksIGF0dHJdIG9mIHRoaXMuX192ZXJ0ZXhBdHRyaWJ1dGVzLmVudHJpZXMoKSkKICAgICAgICAgICAgICAgIHZlcnRleEF0dHJpYnV0ZXNba2V5XSA9IGF0dHI7CiAgICAgICAgICAgIHJldHVybiB2ZXJ0ZXhBdHRyaWJ1dGVzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zICdwb3NpdGlvbnMnIHZlcnRleCBhdHRyaWJ1dGUuCiAgICAgICAgICovCiAgICAgICAgZ2V0IHBvc2l0aW9ucygpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX192ZXJ0ZXhBdHRyaWJ1dGVzLmdldCgncG9zaXRpb25zJyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIG51bWJlciBvZiB2ZXJ0ZXggYXR0cmlidXRlcy4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIG51bVZlcnRpY2VzKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy4jbnVtVmVydGljZXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIG51bWJlciBvZiB2ZXJ0ZXggYXR0cmlidXRlcy4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldE51bVZlcnRpY2VzKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy4jbnVtVmVydGljZXM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIG51bWJlciBvZiB2ZXJ0aWNlcyB0aGUgZ2VvbWV0cnkgaGFzLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGNvdW50IC0gVGhlIGNvdW50IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldE51bVZlcnRpY2VzKGNvdW50KSB7CiAgICAgICAgICAgIHRoaXMuI251bVZlcnRpY2VzID0gY291bnQ7CiAgICAgICAgICAgIC8vIFJlc2l6ZXMgZWFjaCBvZiB0aGUgdmVydGV4IGF0dHJpYnV0ZXMgdG8gbWF0Y2ggdGhlIG5ldyBjb3VudC4KICAgICAgICAgICAgdGhpcy5fX3ZlcnRleEF0dHJpYnV0ZXMuZm9yRWFjaCgoYXR0cikgPT4gYXR0ci5zZXRDb3VudCh0aGlzLiNudW1WZXJ0aWNlcykpOwogICAgICAgICAgICB0aGlzLnNldEJvdW5kaW5nQm94RGlydHkoKTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIEJvdW5kaW5nQm94CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgYm91bmRpbmcgYm94IGZvciBnZW9tZXRyeS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRCb3VuZGluZ0JveCgpIHsKICAgICAgICAgICAgaWYgKHRoaXMuYm91bmRpbmdCb3hEaXJ0eSkKICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlQm91bmRpbmdCb3goKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuYm91bmRpbmdCb3g7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBzZXRCb3VuZGluZ0JveERpcnR5IG1ldGhvZC4KICAgICAgICAgKi8KICAgICAgICBzZXRCb3VuZGluZ0JveERpcnR5KCkgewogICAgICAgICAgICB0aGlzLmJvdW5kaW5nQm94RGlydHkgPSB0cnVlOwogICAgICAgICAgICB0aGlzLmVtaXQoJ2JvdW5kaW5nQm94Q2hhbmdlZCcpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdXBkYXRlQm91bmRpbmdCb3ggbWV0aG9kLgogICAgICAgICAqLwogICAgICAgIHVwZGF0ZUJvdW5kaW5nQm94KCkgewogICAgICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSB0aGlzLnBvc2l0aW9uczsKICAgICAgICAgICAgY29uc3QgYmJveCA9IG5ldyBCb3gzKCk7CiAgICAgICAgICAgIGlmIChwb3NpdGlvbnMpIHsKICAgICAgICAgICAgICAgIGNvbnN0IG51bVZlcnRzID0gcG9zaXRpb25zLmdldENvdW50KCk7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bVZlcnRzOyBpKyspCiAgICAgICAgICAgICAgICAgICAgYmJveC5hZGRQb2ludChwb3NpdGlvbnMuZ2V0VmFsdWUoaSkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuYm91bmRpbmdCb3ggPSBiYm94OwogICAgICAgICAgICB0aGlzLmJvdW5kaW5nQm94RGlydHkgPSBmYWxzZTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogTWVyZ2VzIGEgc2VwYXJhdGUgZ2VvbWV0cnkgaW50byB0aGlzIG9uZS4gU2ltaWxhciB0byBhICd1bmlvbicgYm9vbGVhbiBvcGVyYXRpb24uCiAgICAgICAgICogQHBhcmFtIG90aGVyIHRoZSBvdGhlciBnZW9tIHRoYXQgd2lsbCBiZSBtZXJnZWQgaW50byB0aGlzIG9uZQogICAgICAgICAqIEBwYXJhbSB4Zm8gdGhlIHRyYW5zZm9ybWF0aW9uIHRvIGJlIGFwcGxpZWQgdG8gdGhlIG90aGVyIGdlb20gYXMgaXQgaXMgbWVyZ2VkIGluLgogICAgICAgICAqLwogICAgICAgIG1lcmdlKG90aGVyLCB4Zm8gPSBuZXcgWGZvKCkpIHsKICAgICAgICAgICAgY29uc3QgcHJldk51bVZlcnRzID0gdGhpcy5nZXROdW1WZXJ0aWNlcygpOwogICAgICAgICAgICBjb25zdCBhZGRlZFZlcnRzID0gb3RoZXIuZ2V0TnVtVmVydGljZXMoKTsKICAgICAgICAgICAgZm9yIChjb25zdCBbYXR0ck5hbWUsIGF0dHJdIG9mIHRoaXMuX192ZXJ0ZXhBdHRyaWJ1dGVzKSB7CiAgICAgICAgICAgICAgICBjb25zdCBvdGhlckF0dHIgPSBvdGhlci5nZXRWZXJ0ZXhBdHRyaWJ1dGUoYXR0ck5hbWUpOwogICAgICAgICAgICAgICAgaWYgKG90aGVyQXR0cikgewogICAgICAgICAgICAgICAgICAgIGlmIChhdHRyTmFtZSA9PSAncG9zaXRpb25zJykKICAgICAgICAgICAgICAgICAgICAgICAgYXR0ci5tZXJnZShvdGhlckF0dHIsIHhmbyk7CiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoYXR0ck5hbWUgPT0gJ25vcm1hbHMnKQogICAgICAgICAgICAgICAgICAgICAgICBhdHRyLm1lcmdlKG90aGVyQXR0ciwgbmV3IFhmbyhuZXcgVmVjMygpLCB4Zm8ub3JpKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gTm90ZTogYWxsIHRoZSBhdHRyaWJ1dGVzIGhhdmUgYWxyZWFkeSBiZWVuIHJlc2l6ZWQsIHNvCiAgICAgICAgICAgIC8vIHRoaXMgaXMganVzdCBhIGZpbmFsIGNoZWNrLgogICAgICAgICAgICB0aGlzLnNldE51bVZlcnRpY2VzKHByZXZOdW1WZXJ0cyArIGFkZGVkVmVydHMpOwogICAgICAgICAgICB0aGlzLnVwZGF0ZUJvdW5kaW5nQm94KCk7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBNZW1vcnkKICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHZlcnRleCBhdHRyaWJ1dGVzIGJ1ZmZlcnMgYW5kIGl0cyBjb3VudC4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZW5CdWZmZXJzKG9wdHMpIHsKICAgICAgICAgICAgY29uc3QgYXR0ckJ1ZmZlcnMgPSB7fTsKICAgICAgICAgICAgZm9yIChjb25zdCBbYXR0ck5hbWUsIGF0dHJdIG9mIHRoaXMuX192ZXJ0ZXhBdHRyaWJ1dGVzKSB7CiAgICAgICAgICAgICAgICBhdHRyQnVmZmVyc1thdHRyTmFtZV0gPSBhdHRyLmdlbkJ1ZmZlcigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICBudW1WZXJ0aWNlczogdGhpcy5udW1WZXJ0aWNlcygpLAogICAgICAgICAgICAgICAgYXR0ckJ1ZmZlcnMsCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIE9uY2UgdGhlIGJ1ZmZlcnMgaGF2ZSBiZWVuIHVwbG9hZGVkIHRvIHRoZSBHUFUsIHdlIGFyZSBmcmVlIHRvIHJlbGVhc2UgdGhlbS4KICAgICAgICAgKiBUaGUgR0xHZW9tTGlicmFyeSBtYXkgY2FsbCB0aGlzIGZ1bmN0aW9uIHRvIGxldCB0aGUgZ2VvbWV0cnkga25vdyBpdCBjYW4gcmVsZWFzZSBhbnkgaGFuZGxlcy4KICAgICAgICAgKi8KICAgICAgICBmcmVlQnVmZmVycygpIHsgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQZXJzaXN0ZW5jZQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgc3RhdGUgb2YgY3VycmVudCBHZW9tZXRyeShJbmNsdWRpbmcgVmVydGljZXMgYW5kIEJvdW5kaW5nIEJveCkgdXNpbmcgYSBiaW5hcnkgcmVhZGVyIG9iamVjdC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSByZWFkZXIgLSBUaGUgcmVhZGVyIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGxvYWRCYXNlR2VvbUJpbmFyeShyZWFkZXIsIGNvbnRleHQpIHsKICAgICAgICAgICAgdGhpcy5uYW1lID0gcmVhZGVyLmxvYWRTdHIoKTsKICAgICAgICAgICAgY29uc3QgZmxhZ3MgPSByZWFkZXIubG9hZFVJbnQ4KCk7CiAgICAgICAgICAgIHRoaXMuZGVidWdDb2xvciA9IHJlYWRlci5sb2FkUkdCRmxvYXQzMkNvbG9yKCk7CiAgICAgICAgICAgIGNvbnN0IG51bVZlcnRzID0gcmVhZGVyLmxvYWRVSW50MzIoKTsKICAgICAgICAgICAgdGhpcy5ib3VuZGluZ0JveC5zZXQocmVhZGVyLmxvYWRGbG9hdDMyVmVjMygpLCByZWFkZXIubG9hZEZsb2F0MzJWZWMzKCkpOwogICAgICAgICAgICBsZXQgbm9ybWFsc0F0dHI7CiAgICAgICAgICAgIGxldCB0ZXhDb29yZHNBdHRyOwogICAgICAgICAgICBpZiAoZmxhZ3MgJiAoMSA8PCAxKSkgewogICAgICAgICAgICAgICAgbm9ybWFsc0F0dHIgPSB0aGlzLmdldFZlcnRleEF0dHJpYnV0ZSgnbm9ybWFscycpOwogICAgICAgICAgICAgICAgaWYgKCFub3JtYWxzQXR0cikgewogICAgICAgICAgICAgICAgICAgIG5vcm1hbHNBdHRyID0gbmV3IFZlYzNmOEF0dHJpYnV0ZSgpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkVmVydGV4QXR0cmlidXRlKCdub3JtYWxzJywgbm9ybWFsc0F0dHIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChmbGFncyAmICgxIDw8IDIpKSB7CiAgICAgICAgICAgICAgICB0ZXhDb29yZHNBdHRyID0gdGhpcy5nZXRWZXJ0ZXhBdHRyaWJ1dGUoJ3RleENvb3JkcycpOwogICAgICAgICAgICAgICAgaWYgKCF0ZXhDb29yZHNBdHRyKSB7CiAgICAgICAgICAgICAgICAgICAgdGV4Q29vcmRzQXR0ciA9IG5ldyBWZWMyZjE2QXR0cmlidXRlKCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRWZXJ0ZXhBdHRyaWJ1dGUoJ3RleENvb3JkcycsIHRleENvb3Jkc0F0dHIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IG51bUNsdXN0ZXJzID0gcmVhZGVyLmxvYWRVSW50MzIoKTsKICAgICAgICAgICAgaWYgKG51bUNsdXN0ZXJzID09IDApIHsKICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uc0F0dHIgPSB0aGlzLnBvc2l0aW9uczsKICAgICAgICAgICAgICAgIC8vIEZyb20gMy4xMi4wLCB2ZXJ0ZXggZGF0YSBpcyBhIG1peCBvZiAxNmJpdCBhbmQgOCBiaXQgcXVhbml0aXphdGlvbgogICAgICAgICAgICAgICAgLy8gd2l0aG91dCBhbnkgay1tZWFucyBjbHVzdGVyaW5nLgogICAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZQogICAgICAgICAgICAgICAgcG9zaXRpb25zQXR0ci5kYXRhID0gcmVhZGVyLmxvYWRVSW50MTZBcnJheShudW1WZXJ0cyAqIDMpOwogICAgICAgICAgICAgICAgaWYgKG5vcm1hbHNBdHRyKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZQogICAgICAgICAgICAgICAgICAgIG5vcm1hbHNBdHRyLmRhdGEgPSByZWFkZXIubG9hZEludDhBcnJheShudW1WZXJ0cyAqIDMpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHRleENvb3Jkc0F0dHIpIHsKICAgICAgICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlCiAgICAgICAgICAgICAgICAgICAgdGV4Q29vcmRzQXR0ci5kYXRhID0gcmVhZGVyLmxvYWRVSW50MTZBcnJheShudW1WZXJ0cyAqIDIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy8gVGhpcyBzaG91bGQgYmUgYSBuby1vcCBpbiBlYWNoIG9mIHRoZSBhdHRyaWJ1dGVzIGFzIHRoZXkgYWxyZWFkeSBoYXZlCiAgICAgICAgICAgICAgICAvLyBhcnJheXMgb2YgdGhlIGFwcHJvcHJpYXRlIHNpemUuLgogICAgICAgICAgICAgICAgdGhpcy5zZXROdW1WZXJ0aWNlcyhudW1WZXJ0cyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAobnVtQ2x1c3RlcnMgPT0gMSkgewogICAgICAgICAgICAgICAgLy8gT2xkZXIgemNhZCBmaWxlcyBzdG9yZSAzMiBiaXQgZmxvYXRzLiBUaGUgcmVuZGVyZXIgbWF5IGNvbnZlcnQgdGhlc2UgdG8gMTZiaXQuCiAgICAgICAgICAgICAgICB0aGlzLmFkZFZlcnRleEF0dHJpYnV0ZSgncG9zaXRpb25zJywgbmV3IFZlYzNBdHRyaWJ1dGUoKSk7CiAgICAgICAgICAgICAgICB0aGlzLnNldE51bVZlcnRpY2VzKG51bVZlcnRzKTsKICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uc0F0dHIgPSB0aGlzLnBvc2l0aW9uczsKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBib3gzID0gdGhpcy5ib3VuZGluZ0JveDsKICAgICAgICAgICAgICAgICAgICAvLyBGcm9tIDMuOS4xLCB2ZXJ0ZXggZGF0YSBpcyBhIG1peCBvZiAxNmJpdCBhbmQgOCBiaXQgcXVhbml0aXphdGlvbgogICAgICAgICAgICAgICAgICAgIGlmIChjb250ZXh0LnZlcnNpb25zWyd6ZWEtZW5naW5lJ10uY29tcGFyZShbMywgOSwgMV0pID49IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9zaXRpb25zX3F1YW50aXplZCA9IHJlYWRlci5sb2FkVUludDE2QXJyYXkobnVtVmVydHMgKiAzLCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlMTZCaXRQb3NpdGlvbnNBcnJheShbMCwgbnVtVmVydHNdLCBib3gzLnAwLCBib3gzLmRpYWdvbmFsKCksIHBvc2l0aW9uc19xdWFudGl6ZWQsIHBvc2l0aW9uc0F0dHIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9zaXRpb25zX3F1YW50aXplZCA9IHJlYWRlci5sb2FkVUludDhBcnJheShudW1WZXJ0cyAqIDMsIGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgcGFyc2U4Qml0UG9zaXRpb25zQXJyYXkoWzAsIG51bVZlcnRzXSwgYm94My5wMCwgYm94My5kaWFnb25hbCgpLCBwb3NpdGlvbnNfcXVhbnRpemVkLCBwb3NpdGlvbnNBdHRyKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAobm9ybWFsc0F0dHIpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBib3gzID0gbmV3IEJveDMocmVhZGVyLmxvYWRGbG9hdDMyVmVjMygpLCByZWFkZXIubG9hZEZsb2F0MzJWZWMzKCkpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IG5vcm1hbHNfcXVhbnRpemVkID0gcmVhZGVyLmxvYWRVSW50OEFycmF5KG51bVZlcnRzICogMywgZmFsc2UpOwogICAgICAgICAgICAgICAgICAgIHBhcnNlOEJpdE5vcm1hbHNBcnJheShbMCwgbnVtVmVydHNdLCBib3gzLnAwLCBib3gzLmRpYWdvbmFsKCksIG5vcm1hbHNfcXVhbnRpemVkLCBub3JtYWxzQXR0cik7CiAgICAgICAgICAgICAgICAgICAgbm9ybWFsc0F0dHIubG9hZFNwbGl0VmFsdWVzKHJlYWRlcik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAodGV4Q29vcmRzQXR0cikgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IGJveDIgPSBuZXcgQm94MihyZWFkZXIubG9hZEZsb2F0MzJWZWMyKCksIHJlYWRlci5sb2FkRmxvYXQzMlZlYzIoKSk7CiAgICAgICAgICAgICAgICAgICAgLy8gRnJvbSAzLjkuMSwgdmVydGV4IGRhdGEgaXMgYSBtaXggb2YgMTZiaXQgYW5kIDggYml0IHF1YW5pdGl6YXRpb24KICAgICAgICAgICAgICAgICAgICBpZiAoY29udGV4dC52ZXJzaW9uc1snemVhLWVuZ2luZSddLmNvbXBhcmUoWzMsIDksIDFdKSA+PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRleENvb3Jkc19xdWFudGl6ZWQgPSByZWFkZXIubG9hZFVJbnQxNkFycmF5KG51bVZlcnRzICogMiwgZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICBwYXJzZTE2Qml0VGV4dHVyZUNvb3Jkc0FycmF5KFswLCBudW1WZXJ0c10sIGJveDIucDAsIGJveDIuZGlhZ29uYWwoKSwgdGV4Q29vcmRzX3F1YW50aXplZCwgdGV4Q29vcmRzQXR0cik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXhDb29yZHNfcXVhbnRpemVkID0gcmVhZGVyLmxvYWRVSW50OEFycmF5KG51bVZlcnRzICogMiwgZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICBwYXJzZThCaXRUZXh0dXJlQ29vcmRzQXJyYXkoWzAsIG51bVZlcnRzXSwgYm94Mi5wMCwgYm94Mi5kaWFnb25hbCgpLCB0ZXhDb29yZHNfcXVhbnRpemVkLCB0ZXhDb29yZHNBdHRyKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdGV4Q29vcmRzQXR0ci5sb2FkU3BsaXRWYWx1ZXMocmVhZGVyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIC8vIE9sZGVyIHpjYWQgZmlsZXMgc3RvcmUgMzIgYml0IGZsb2F0cy4gVGhlIHJlbmRlcmVyIG1heSBjb252ZXJ0IHRoZXNlIHRvIDE2Yml0LgogICAgICAgICAgICAgICAgdGhpcy5hZGRWZXJ0ZXhBdHRyaWJ1dGUoJ3Bvc2l0aW9ucycsIG5ldyBWZWMzQXR0cmlidXRlKCkpOwogICAgICAgICAgICAgICAgdGhpcy5zZXROdW1WZXJ0aWNlcyhudW1WZXJ0cyk7CiAgICAgICAgICAgICAgICBjb25zdCBwb3NpdGlvbnNBdHRyID0gdGhpcy5wb3NpdGlvbnM7CiAgICAgICAgICAgICAgICBjb25zdCBjbHVzdGVycyA9IFtdOwogICAgICAgICAgICAgICAgbGV0IG9mZnNldCA9IDA7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUNsdXN0ZXJzOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjb3VudCA9IHJlYWRlci5sb2FkVUludDMyKCk7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2x1c3RlckRhdGEgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlOiBbb2Zmc2V0LCBvZmZzZXQgKyBjb3VudF0sCiAgICAgICAgICAgICAgICAgICAgICAgIGJib3g6IG5ldyBCb3gzKHJlYWRlci5sb2FkRmxvYXQzMlZlYzMoKSwgcmVhZGVyLmxvYWRGbG9hdDMyVmVjMygpKSwKICAgICAgICAgICAgICAgICAgICAgICAgbm9ybWFsc1JhbmdlOiBuZXcgQm94MygpLAogICAgICAgICAgICAgICAgICAgICAgICB0ZXhDb29yZHNSYW5nZTogbmV3IEJveDIoKSwKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGlmIChub3JtYWxzQXR0cikgewogICAgICAgICAgICAgICAgICAgICAgICBjbHVzdGVyRGF0YS5ub3JtYWxzUmFuZ2Uuc2V0KHJlYWRlci5sb2FkRmxvYXQzMlZlYzMoKSwgcmVhZGVyLmxvYWRGbG9hdDMyVmVjMygpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKHRleENvb3Jkc0F0dHIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RlckRhdGEudGV4Q29vcmRzUmFuZ2Uuc2V0KHJlYWRlci5sb2FkRmxvYXQzMlZlYzIoKSwgcmVhZGVyLmxvYWRGbG9hdDMyVmVjMigpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2x1c3RlcnMucHVzaChjbHVzdGVyRGF0YSk7CiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ICs9IGNvdW50OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy8gRnJvbSAzLjkuMSwgdmVydGV4IGRhdGEgaXMgYSBtaXggb2YgMTZiaXQgYW5kIDggYml0IHF1YW5pdGl6YXRpb24KICAgICAgICAgICAgICAgIGxldCBwb3NpdGlvbnNfcXVhbnRpemVkOwogICAgICAgICAgICAgICAgaWYgKGNvbnRleHQudmVyc2lvbnNbJ3plYS1lbmdpbmUnXS5jb21wYXJlKFszLCA5LCAxXSkgPj0gMCkgewogICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uc19xdWFudGl6ZWQgPSByZWFkZXIubG9hZFVJbnQxNkFycmF5KG51bVZlcnRzICogMywgZmFsc2UpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25zX3F1YW50aXplZCA9IHJlYWRlci5sb2FkVUludDhBcnJheShudW1WZXJ0cyAqIDMsIGZhbHNlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGxldCBub3JtYWxzX3F1YW50aXplZCA9IG51bGw7CiAgICAgICAgICAgICAgICBsZXQgdGV4Q29vcmRzX3F1YW50aXplZCA9IG51bGw7CiAgICAgICAgICAgICAgICBpZiAobm9ybWFsc0F0dHIpIHsKICAgICAgICAgICAgICAgICAgICBub3JtYWxzX3F1YW50aXplZCA9IHJlYWRlci5sb2FkVUludDhBcnJheShudW1WZXJ0cyAqIDMsIGZhbHNlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmICh0ZXhDb29yZHNBdHRyKSB7CiAgICAgICAgICAgICAgICAgICAgdGV4Q29vcmRzX3F1YW50aXplZCA9IHJlYWRlci5sb2FkVUludDhBcnJheShudW1WZXJ0cyAqIDIsIGZhbHNlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQ2x1c3RlcnM7IGkrKykgewogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYm94MyA9IGNsdXN0ZXJzW2ldLmJib3g7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZyb20gMy45LjEsIHZlcnRleCBkYXRhIGlzIGEgbWl4IG9mIDE2Yml0IGFuZCA4IGJpdCBxdWFuaXRpemF0aW9uCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb250ZXh0LnZlcnNpb25zWyd6ZWEtZW5naW5lJ10uY29tcGFyZShbMywgOSwgMV0pID49IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlMTZCaXRQb3NpdGlvbnNBcnJheShjbHVzdGVyc1tpXS5yYW5nZSwgYm94My5wMCwgYm94My5kaWFnb25hbCgpLCBwb3NpdGlvbnNfcXVhbnRpemVkLCBwb3NpdGlvbnNBdHRyKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlOEJpdFBvc2l0aW9uc0FycmF5KGNsdXN0ZXJzW2ldLnJhbmdlLCBib3gzLnAwLCBib3gzLmRpYWdvbmFsKCksIHBvc2l0aW9uc19xdWFudGl6ZWQsIHBvc2l0aW9uc0F0dHIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChub3JtYWxzX3F1YW50aXplZCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBib3gzID0gY2x1c3RlcnNbaV0ubm9ybWFsc1JhbmdlOwogICAgICAgICAgICAgICAgICAgICAgICBwYXJzZThCaXROb3JtYWxzQXJyYXkoY2x1c3RlcnNbaV0ucmFuZ2UsIGJveDMucDAsIGJveDMuZGlhZ29uYWwoKSwgbm9ybWFsc19xdWFudGl6ZWQsIG5vcm1hbHNBdHRyKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKHRleENvb3Jkc19xdWFudGl6ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYm94MiA9IGNsdXN0ZXJzW2ldLnRleENvb3Jkc1JhbmdlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29udGV4dC52ZXJzaW9uc1snemVhLWVuZ2luZSddLmNvbXBhcmUoWzMsIDksIDFdKSA+PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJzZTE2Qml0VGV4dHVyZUNvb3Jkc0FycmF5KFswLCBudW1WZXJ0c10sIGJveDIucDAsIGJveDIuZGlhZ29uYWwoKSwgdGV4Q29vcmRzX3F1YW50aXplZCwgdGV4Q29vcmRzQXR0cik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJzZThCaXRUZXh0dXJlQ29vcmRzQXJyYXkoY2x1c3RlcnNbaV0ucmFuZ2UsIGJveDIucDAsIGJveDIuZGlhZ29uYWwoKSwgdGV4Q29vcmRzX3F1YW50aXplZCwgdGV4Q29vcmRzQXR0cik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAobm9ybWFsc0F0dHIpIHsKICAgICAgICAgICAgICAgICAgICBub3JtYWxzQXR0ci5sb2FkU3BsaXRWYWx1ZXMocmVhZGVyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmICh0ZXhDb29yZHNBdHRyKSB7CiAgICAgICAgICAgICAgICAgICAgdGV4Q29vcmRzQXR0ci5sb2FkU3BsaXRWYWx1ZXMocmVhZGVyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBMb2FkaW5nIHRoZSBhdHRyaWJ1dGVzIG1heSBoYXZlIGRpcnRpZWQgdGhlIGJvdW5kaW5nIGJveC4KICAgICAgICAgICAgLy8gd2Uga29udyB3ZSBhbHJlYWR5IGxvYWRlZCB0aGUgYmJveCwgc28gZm9yY2UgaXQgdG8gYmUgdmFsaWQuCiAgICAgICAgICAgIHRoaXMuYm91bmRpbmdCb3hEaXJ0eSA9IGZhbHNlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdG9KU09OIG1ldGhvZCBlbmNvZGVzIHRoaXMgdHlwZSBhcyBhIGpzb24gb2JqZWN0IGZvciBwZXJzaXN0ZW5jZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIGNvbnN0IGpzb24gPSBzdXBlci50b0pTT04oY29udGV4dCk7CiAgICAgICAgICAgIGlmICghY29udGV4dCB8fCAhY29udGV4dC5za2lwVG9wb2xvZ3kpIHsKICAgICAgICAgICAgICAgIGpzb24ubnVtVmVydGljZXMgPSB0aGlzLiNudW1WZXJ0aWNlcyB8fCAwOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IHZlcnRleEF0dHJpYnV0ZXMgPSB7fTsKICAgICAgICAgICAgZm9yIChjb25zdCBba2V5LCBhdHRyXSBvZiB0aGlzLl9fdmVydGV4QXR0cmlidXRlcy5lbnRyaWVzKCkpIHsKICAgICAgICAgICAgICAgIGlmICghY29udGV4dCB8fCAhKCdza2lwQXR0cmlidXRlcycgaW4gY29udGV4dCkgfHwgIWNvbnRleHQuc2tpcEF0dHJpYnV0ZXMuaW5jbHVkZXMoa2V5KSkKICAgICAgICAgICAgICAgICAgICB2ZXJ0ZXhBdHRyaWJ1dGVzW2tleV0gPSBhdHRyLnRvSlNPTihjb250ZXh0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBqc29uLnZlcnRleEF0dHJpYnV0ZXMgPSB2ZXJ0ZXhBdHRyaWJ1dGVzOwogICAgICAgICAgICByZXR1cm4ganNvbjsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGZyb21KU09OIG1ldGhvZCBkZWNvZGVzIGEganNvbiBvYmplY3QgZm9yIHRoaXMgdHlwZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBqc29uIC0gVGhlIGpzb24gb2JqZWN0IHRoaXMgaXRlbSBtdXN0IGRlY29kZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGZyb21KU09OKGpzb24sIGNvbnRleHQpIHsKICAgICAgICAgICAgdGhpcy5jbGVhcigpOwogICAgICAgICAgICBzdXBlci5mcm9tSlNPTihqc29uLCBjb250ZXh0KTsKICAgICAgICAgICAgdGhpcy5zZXROdW1WZXJ0aWNlcyhqc29uLm51bVZlcnRpY2VzKTsKICAgICAgICAgICAgZm9yIChjb25zdCBuYW1lIGluIGpzb24udmVydGV4QXR0cmlidXRlcykgewogICAgICAgICAgICAgICAgbGV0IGF0dHIgPSB0aGlzLl9fdmVydGV4QXR0cmlidXRlcy5nZXQobmFtZSk7CiAgICAgICAgICAgICAgICBjb25zdCBhdHRySlNPTiA9IGpzb24udmVydGV4QXR0cmlidXRlc1tuYW1lXTsKICAgICAgICAgICAgICAgIGlmICghYXR0ciB8fCBhdHRyLmRhdGFUeXBlTmFtZSAhPSBhdHRySlNPTi5kYXRhVHlwZSkgewogICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoYXR0ckpTT04uZGF0YVR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnVmVjMic6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRyID0gbmV3IFZlYzJBdHRyaWJ1dGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdWZWMyZjE2JzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dHIgPSBuZXcgVmVjMmYxNkF0dHJpYnV0ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ1ZlYzMnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0ciA9IG5ldyBWZWMzQXR0cmlidXRlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnVmVjM2YxNic6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRyID0gbmV3IFZlYzNmMTZBdHRyaWJ1dGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdWZWMzZjgnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0ciA9IG5ldyBWZWMzZjhBdHRyaWJ1dGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdDb2xvcic6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRyID0gbmV3IENvbG9yQXR0cmlidXRlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdJbnZhbGlkIFZlY3RleCBUeXBlOiAnICsgYXR0ci5kYXRhVHlwZU5hbWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGF0dHIuc2V0Q291bnQodGhpcy4jbnVtVmVydGljZXMpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkVmVydGV4QXR0cmlidXRlKG5hbWUsIGF0dHIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKGF0dHIpIHsKICAgICAgICAgICAgICAgICAgICBhdHRyLmZyb21KU09OKGF0dHJKU09OKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignYXR0ciB1bmRlZmluZWQsIGNhbm5vdCBleGVjdXRlIGZyb21KU09OKCknKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLmVtaXQoJ2dlb21EYXRhVG9wb2xvZ3lDaGFuZ2VkJyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgZ2VvbWV0cnkgZGF0YSB2YWx1ZSBpbiBqc29uIGZvcm1hdC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHRvU3RyaW5nKCkgewogICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcy50b0pTT04oKSwgbnVsbCwgMik7CiAgICAgICAgfQogICAgfQoKICAgIC8qKgogICAgICogQ2xhc3MgcmVwcmVzZW50aW5nIGEgcG9pbnQgcHJpbWl0aXZlIGRyYXdpbmcgdHlwZSwgZXZlcnkgdmVydGV4IHNwZWNpZmllZCBpcyBhIHBvaW50LgogICAgICoKICAgICAqIGBgYAogICAgICogY29uc3QgcG9pbnRzID0gbmV3IFBvaW50cygpCiAgICAgKiBgYGAKICAgICAqCiAgICAgKiAqICoqRXZlbnRzKioKICAgICAqICogKipib3VuZGluZ0JveENoYW5nZWQ6KiogVHJpZ2dlcmVkIHdoZW4gdGhlIGJvdW5kaW5nIGJveCBjaGFuZ2VzLgogICAgICoKICAgICAqIEBleHRlbmRzIEJhc2VHZW9tCiAgICAgKi8KICAgIGNsYXNzIFBvaW50cyBleHRlbmRzIEJhc2VHZW9tIHsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgcG9pbnRzLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgICAgICBzdXBlcigpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgY2xlYXIgbWV0aG9kLgogICAgICAgICAqLwogICAgICAgIGNsZWFyKCkgewogICAgICAgICAgICB0aGlzLnNldE51bVZlcnRpY2VzKDApOwogICAgICAgICAgICB0aGlzLmVtaXQoJ2dlb21EYXRhVG9wb2xvZ3lDaGFuZ2VkJyk7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBQZXJzaXN0ZW5jZQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgc3RhdGUgb2YgY3VycmVudCBnZW9tZXRyeShJbmNsdWRpbmcgbGluZSBzZWdtZW50cykgdXNpbmcgYSBiaW5hcnkgcmVhZGVyIG9iamVjdC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSByZWFkZXIgLSBUaGUgcmVhZGVyIHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgcmVhZEJpbmFyeShyZWFkZXIsIGNvbnRleHQpIHsKICAgICAgICAgICAgc3VwZXIubG9hZEJhc2VHZW9tQmluYXJ5KHJlYWRlciwgY29udGV4dCk7CiAgICAgICAgICAgIC8vIHRoaXMuY29tcHV0ZVZlcnRleE5vcm1hbHMoKTsKICAgICAgICAgICAgdGhpcy5lbWl0KCdnZW9tRGF0YUNoYW5nZWQnKTsKICAgICAgICB9CiAgICB9CiAgICBSZWdpc3RyeS5yZWdpc3RlcignUG9pbnRzJywgUG9pbnRzKTsKCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMgKi8KICAgIC8qKgogICAgICoKICAgICAqIENsYXNzIHJlcHJlc2VudGluZyBsaW5lcyBwcmltaXRpdmUgZHJhd2luZyB0eXBlLCBjb25uZWN0aW5nIHZlcnRpY2VzIHVzaW5nIHRoZSBzcGVjaWZpZWQgaW5kaWNlcy4KICAgICAqIGkuZS4gV2UgaGF2ZSA0IHBvaW50cyh2ZXJ0aWNlcykgYnV0IHdlIGRvbid0IGtub3cgaG93IHRoZXkgY29ubmVjdCB0byBlYWNoIG90aGVyLAogICAgICogYW5kIHRoYXQncyB3aHkgd2UgbmVlZCBpbmRpY2VzKE51bWJlcnMgaW5kaWNhdGluZyB3aGljaCB2ZXJ0ZXggY29ubmVjdHMgdG8gd2hpY2gpLgogICAgICogSW4gdGhpcyBjYXNlIGlmIHdlIHNheSB0aGF0IGBpbmRpY2VzYCBpcyBgWzAsMSwyLDNdYCwgaXQgd291bGQgY29ubmVjdCB0aGUgZmlyc3QgdmVydGV4IHRvIHRoZSBzZWNvbmQsCiAgICAgKiBhbmQgdGhlIHRoaXJkIHRvIHRoZSBmb3VydGguCiAgICAgKgogICAgICogYGBgCiAgICAgKiBjb25zdCBsaW5lcyA9IG5ldyBMaW5lcygpCiAgICAgKiBgYGAKICAgICAqCiAgICAgKiAqKkV2ZW50cyoqCiAgICAgKiAqICoqZ2VvbURhdGFDaGFuZ2VkOioqIFRyaWdnZXJlZCB3aGVuIHRoZSBkYXRhIHZhbHVlIG9mIHRoZSBnZW9tZXRyeSBpcyBzZXQoVGhpcyBpbmNsdWRlcyByZWFkaW5nIGJpbmFyeSkKICAgICAqCiAgICAgKiBAZXh0ZW5kcyBCYXNlR2VvbQogICAgICovCiAgICBjbGFzcyBMaW5lcyBleHRlbmRzIEJhc2VHZW9tIHsKICAgICAgICBfX2luZGljZXM7CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlIGxpbmVzLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgICAgICBzdXBlcigpOwogICAgICAgICAgICB0aGlzLl9faW5kaWNlcyA9IG5ldyBVaW50MzJBcnJheSgpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgY2xlYXIgbWV0aG9kLgogICAgICAgICAqLwogICAgICAgIGNsZWFyKCkgewogICAgICAgICAgICB0aGlzLnNldE51bVNlZ21lbnRzKDApOwogICAgICAgICAgICB0aGlzLnNldE51bVZlcnRpY2VzKDApOwogICAgICAgICAgICB0aGlzLmVtaXQoJ2dlb21EYXRhVG9wb2xvZ3lDaGFuZ2VkJyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIHNwZWNpZmllZCBpbmRpY2VzKFZlcnRleCBjb25uZWN0b3JzKQogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSBpbmRpY2VzIGluZGV4IGFycmF5LgogICAgICAgICAqLwogICAgICAgIGdldEluZGljZXMoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9faW5kaWNlczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGxpbmUgc2VnbWVudHMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgbnVtYmVyIG9mIHNlZ21lbnRzLgogICAgICAgICAqLwogICAgICAgIGdldE51bVNlZ21lbnRzKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fX2luZGljZXMubGVuZ3RoIC8gMjsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGxpbmUgc2VnbWVudHMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyB0aGUgbnVtYmVyIG9mIHNlZ21lbnRzLgogICAgICAgICAqLwogICAgICAgIGdldE51bUxpbmVTZWdtZW50cygpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX19pbmRpY2VzLmxlbmd0aCAvIDI7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIG51bWJlciBvZiBsaW5lIHNlZ21lbnRzIGluIHRoZSBsaW5lcyBnZW9tZXRyeS4KICAgICAgICAgKiAqKkltcG9ydGFudDoqKiBJdCByZXNldHMgaW5kaWNlcyB2YWx1ZXMuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbnVtT2ZTZWdtZW50cyAtIFRoZSBjb3VudCB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXROdW1TZWdtZW50cyhudW1PZlNlZ21lbnRzKSB7CiAgICAgICAgICAgIGlmIChudW1PZlNlZ21lbnRzID4gdGhpcy5nZXROdW1TZWdtZW50cygpKSB7CiAgICAgICAgICAgICAgICBjb25zdCBpbmRpY2VzID0gbmV3IFVpbnQzMkFycmF5KG51bU9mU2VnbWVudHMgKiAyKTsKICAgICAgICAgICAgICAgIGluZGljZXMuc2V0KHRoaXMuX19pbmRpY2VzKTsKICAgICAgICAgICAgICAgIHRoaXMuX19pbmRpY2VzID0gaW5kaWNlczsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHRoaXMuX19pbmRpY2VzID0gdGhpcy5fX2luZGljZXMuc2xpY2UoMCwgbnVtT2ZTZWdtZW50cyAqIDIpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgc2VnbWVudCB2YWx1ZXMgaW4gdGhlIHNwZWNpZmllZCBpbmRleC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gcDAgLSBUaGUgcDAgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIHAxIC0gVGhlIHAxIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHNldFNlZ21lbnRWZXJ0ZXhJbmRpY2VzKGluZGV4LCBwMCwgcDEpIHsKICAgICAgICAgICAgaWYgKGluZGV4ID49IHRoaXMuX19pbmRpY2VzLmxlbmd0aCAvIDIpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgbGluZSBpbmRleDonICsgaW5kZXggKyAnLiBOdW0gU2VnbWVudHM6JyArIHRoaXMuX19pbmRpY2VzLmxlbmd0aCAvIDIpOwogICAgICAgICAgICB0aGlzLl9faW5kaWNlc1tpbmRleCAqIDIgKyAwXSA9IHAwOwogICAgICAgICAgICB0aGlzLl9faW5kaWNlc1tpbmRleCAqIDIgKyAxXSA9IHAxOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZ2V0U2VnbWVudFZlcnRleEluZGV4IG1ldGhvZC4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBsaW5lIC0gVGhlIGxpbmUgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIGxpbmVWZXJ0ZXggLSBUaGUgbGluZVZlcnRleCB2YWx1ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKiBAcHJpdmF0ZQogICAgICAgICAqLwogICAgICAgIGdldFNlZ21lbnRWZXJ0ZXhJbmRleChsaW5lLCBsaW5lVmVydGV4KSB7CiAgICAgICAgICAgIGNvbnN0IG51bVNlZ21lbnRzID0gdGhpcy5nZXROdW1TZWdtZW50cygpOwogICAgICAgICAgICBpZiAobGluZSA8IG51bVNlZ21lbnRzKQogICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX19pbmRpY2VzW2xpbmUgKiAyICsgbGluZVZlcnRleF07CiAgICAgICAgICAgIHJldHVybiAtMTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogTWVyZ2VzIGEgc2VwYXJhdGUgZ2VvbWV0cnkgaW50byB0aGlzIG9uZS4gU2ltaWxhciB0byBhICd1bmlvbicgYm9vbGVhbiBvcGVyYXRpb24uCiAgICAgICAgICogQHBhcmFtIG90aGVyIHRoZSBvdGhlciBnZW9tIHRoYXQgd2lsbCBiZSBtZXJnZWQgaW50byB0aGlzIG9uZQogICAgICAgICAqIEBwYXJhbSB4Zm8gdGhlIHRyYW5zZm9ybWF0aW9uIHRvIGJlIGFwcGxpZWQgdG8gdGhlIG90aGVyIGdlb20gYXMgaXQgaXMgbWVyZ2VkIGluLgogICAgICAgICAqLwogICAgICAgIG1lcmdlKG90aGVyLCB4Zm8gPSBuZXcgWGZvKCkpIHsKICAgICAgICAgICAgY29uc3QgcHJldk51bVZlcnRzID0gdGhpcy5nZXROdW1WZXJ0aWNlcygpOwogICAgICAgICAgICBzdXBlci5tZXJnZShvdGhlciwgeGZvKTsKICAgICAgICAgICAgY29uc3Qgb3RoZUluZGljZXMgPSBvdGhlci5fX2luZGljZXM7CiAgICAgICAgICAgIGNvbnN0IGluZGljZXMgPSBuZXcgVWludDMyQXJyYXkodGhpcy5fX2luZGljZXMubGVuZ3RoICsgb3RoZUluZGljZXMubGVuZ3RoKTsKICAgICAgICAgICAgaW5kaWNlcy5zZXQodGhpcy5fX2luZGljZXMsIDApOwogICAgICAgICAgICBpbmRpY2VzLnNldChvdGhlSW5kaWNlcy5tYXAoKGluZGV4KSA9PiBpbmRleCArIHByZXZOdW1WZXJ0cyksIHRoaXMuX19pbmRpY2VzLmxlbmd0aCk7CiAgICAgICAgICAgIHRoaXMuX19pbmRpY2VzID0gaW5kaWNlczsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIE1lbW9yeQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdmVydGV4IGF0dHJpYnV0ZXMgYnVmZmVycyBhbmQgaXRzIGNvdW50LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2VuQnVmZmVycyhvcHRzKSB7CiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlcnMgPSBzdXBlci5nZW5CdWZmZXJzKCk7CiAgICAgICAgICAgIGxldCBpbmRpY2VzOwogICAgICAgICAgICBpZiAoYnVmZmVycy5udW1WZXJ0aWNlcyA8IE1hdGgucG93KDIsIDgpKSB7CiAgICAgICAgICAgICAgICBpbmRpY2VzID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5fX2luZGljZXMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYgKGJ1ZmZlcnMubnVtVmVydGljZXMgPCBNYXRoLnBvdygyLCAxNikpIHsKICAgICAgICAgICAgICAgIGluZGljZXMgPSBuZXcgVWludDE2QXJyYXkodGhpcy5fX2luZGljZXMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgaW5kaWNlcyA9IHRoaXMuX19pbmRpY2VzOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJ1ZmZlcnMuaW5kaWNlcyA9IGluZGljZXM7CiAgICAgICAgICAgIHJldHVybiBidWZmZXJzOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBTZXRzIHN0YXRlIG9mIGN1cnJlbnQgZ2VvbWV0cnkoSW5jbHVkaW5nIGxpbmUgc2VnbWVudHMpIHVzaW5nIGEgYmluYXJ5IHJlYWRlciBvYmplY3QuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHN1cGVyLmxvYWRCYXNlR2VvbUJpbmFyeShyZWFkZXIsIGNvbnRleHQpOwogICAgICAgICAgICB0aGlzLnNldE51bVNlZ21lbnRzKHJlYWRlci5sb2FkVUludDMyKCkpOwogICAgICAgICAgICBjb25zdCBieXRlcyA9IHJlYWRlci5sb2FkVUludDgoKTsKICAgICAgICAgICAgaWYgKGJ5dGVzID09IDEpCiAgICAgICAgICAgICAgICB0aGlzLl9faW5kaWNlcyA9IHJlYWRlci5sb2FkVUludDhBcnJheSgpOwogICAgICAgICAgICBlbHNlIGlmIChieXRlcyA9PSAyKQogICAgICAgICAgICAgICAgdGhpcy5fX2luZGljZXMgPSByZWFkZXIubG9hZFVJbnQxNkFycmF5KCk7CiAgICAgICAgICAgIGVsc2UgaWYgKGJ5dGVzID09IDQpCiAgICAgICAgICAgICAgICB0aGlzLl9faW5kaWNlcyA9IHJlYWRlci5sb2FkVUludDMyQXJyYXkoKTsKICAgICAgICAgICAgdGhpcy5lbWl0KCdnZW9tRGF0YUNoYW5nZWQnKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHRvSlNPTiBtZXRob2QgZW5jb2RlcyB0aGlzIHR5cGUgYXMgYSBqc29uIG9iamVjdCBmb3IgcGVyc2lzdGVuY2UuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBqc29uIG9iamVjdC4KICAgICAgICAgKi8KICAgICAgICB0b0pTT04oY29udGV4dCkgewogICAgICAgICAgICBjb25zdCBqID0gc3VwZXIudG9KU09OKGNvbnRleHQpOwogICAgICAgICAgICBpZiAoIWNvbnRleHQgfHwgIWNvbnRleHQuc2tpcFRvcG9sb2d5KQogICAgICAgICAgICAgICAgai5pbmRpY2VzID0gQXJyYXkuZnJvbSh0aGlzLl9faW5kaWNlcyk7CiAgICAgICAgICAgIHJldHVybiBqOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIGRlY29kZXMgYSBqc29uIG9iamVjdCBmb3IgdGhpcyB0eXBlLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIGogLSBUaGUganNvbiBvYmplY3QgdGhpcyBpdGVtIG11c3QgZGVjb2RlLgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZnJvbUpTT04oaiwgY29udGV4dCkgewogICAgICAgICAgICBzdXBlci5mcm9tSlNPTihqLCBjb250ZXh0KTsKICAgICAgICAgICAgaWYgKGouaW5kaWNlcykKICAgICAgICAgICAgICAgIHRoaXMuX19pbmRpY2VzID0gVWludDMyQXJyYXkuZnJvbShqLmluZGljZXMpOwogICAgICAgIH0KICAgIH0KICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyKCdMaW5lcycsIExpbmVzKTsKCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBwcmVmZXItcmVzdC1wYXJhbXMgKi8KICAgIC8qKgogICAgICogVGhlIE1lc2ggY2xhc3MgcHJvdmlkZXMgYSBmbGV4aWJsZSBhbmQgZmFzdCBwb2x5Z29uIG1lc2ggcmVwcmVzZW50YXRpb24uIEl0IHN1cHBvcnRzIHBvbHlnb25zIG9mIGFyYml0cmFyeSBjb21wbGV4aXR5LAogICAgICogZnJvbSBiYXNpYyB0cmlhbmdsZXMgYW5kIHF1YWRzIHRvIHBlbnRhZ29ucyBtb3JlLgogICAgICogSXQgc3VwcG9ydHMgc3RvcmluZyBwZXIgZmFjZSBhdHRyaWJ1dGVzLCBhbmQgcGVyIGVkZ2UgYXR0cmlidXRlcy4KICAgICAqIFRoZSBNZXNoIGNsYXNzIGhhbmRsZXMgY29udmVydGluZyBpdHMgaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gb2YgcG9seWdvbnMgaW50byBhIHNpbXBsZXIgdHJpYW5nbGVzIHJlcHJlc2VudGF0aW9uIGZvciByZW5kZXJpbmcuCiAgICAgKgogICAgICogYGBgCiAgICAgKiBjb25zdCBtZXNoID0gbmV3IE1lc2goKQogICAgICogYGBgCiAgICAgKgogICAgICogKipFdmVudHMqKgogICAgICogKiAqKmdlb21EYXRhVG9wb2xvZ3lDaGFuZ2VkOioqIFRyaWdnZXJlZCB3aGVuIHRoZSB0b3BvbG9neSBvZiB0aGUgbWVzaCBoYXMgYmVlbiBjaGFuZ2VkLgogICAgICogKiAqKmdlb21EYXRhQ2hhbmdlZDoqKiBUcmlnZ2VyZWQgd2hlbiB0aGUgdmVydGljZXMgb2YgdGhlIG1lc2ggaGF2ZSBjaGFuZ2VkLCBidXQgbm90IG5lY2Vzc2FyaWx5IHRoZSB0b3BvbG9neS4KICAgICAqCiAgICAgKiBAZXh0ZW5kcyBCYXNlR2VvbQogICAgICovCiAgICBjbGFzcyBNZXNoIGV4dGVuZHMgQmFzZUdlb20gewogICAgICAgIGZhY2VDb3VudHM7CiAgICAgICAgZmFjZVZlcnRleEluZGljZXM7CiAgICAgICAgX19sb2dUb3BvbG9neVdhcm5pbmdzOwogICAgICAgIF9fZWRnZUF0dHJpYnV0ZXM7CiAgICAgICAgX19mYWNlQXR0cmlidXRlczsKICAgICAgICBudW1FZGdlczsKICAgICAgICBlZGdlVmVydHM7CiAgICAgICAgZWRnZUFuZ2xlczsKICAgICAgICBlZGdlVmVjczsKICAgICAgICBlZGdlRmFjZXM7CiAgICAgICAgZmFjZUVkZ2VzOwogICAgICAgIHZlcnRleEVkZ2VzOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTWVzaC4KICAgICAgICAgKi8KICAgICAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICAgICAgc3VwZXIoKTsKICAgICAgICAgICAgdGhpcy5lZGdlRmFjZXMgPSBbXTsKICAgICAgICAgICAgdGhpcy5mYWNlRWRnZXMgPSBbW11dOwogICAgICAgICAgICB0aGlzLmZhY2VDb3VudHMgPSBbXTsKICAgICAgICAgICAgdGhpcy5mYWNlVmVydGV4SW5kaWNlcyA9IG5ldyBVaW50MzJBcnJheSgpOwogICAgICAgICAgICB0aGlzLl9fbG9nVG9wb2xvZ3lXYXJuaW5ncyA9IGZhbHNlOwogICAgICAgICAgICB0aGlzLl9fZWRnZUF0dHJpYnV0ZXMgPSBuZXcgTWFwKCk7CiAgICAgICAgICAgIHRoaXMuX19mYWNlQXR0cmlidXRlcyA9IG5ldyBNYXAoKTsKICAgICAgICAgICAgdGhpcy5udW1FZGdlcyA9IDA7CiAgICAgICAgICAgIHRoaXMuZWRnZVZlcnRzID0gW107CiAgICAgICAgICAgIHRoaXMudmVydGV4RWRnZXMgPSBbXTsKICAgICAgICAgICAgdGhpcy5lZGdlQW5nbGVzID0gbmV3IEZsb2F0MzJBcnJheSgpOwogICAgICAgICAgICB0aGlzLmVkZ2VWZWNzID0gW107CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBjbGVhciBtZXRob2QuCiAgICAgICAgICovCiAgICAgICAgY2xlYXIoKSB7CiAgICAgICAgICAgIHN1cGVyLmNsZWFyKCk7CiAgICAgICAgICAgIC8vdGhpcy5pbml0KCkKICAgICAgICAgICAgLy90aGlzLnNldE51bVZlcnRpY2VzKDApCiAgICAgICAgICAgIC8vIGNsZWFyIGVkZ2UgYW5kIGZhY2Ugbm9ybWFscy4KICAgICAgICAgICAgdGhpcy5lZGdlVmVydHMgPSBbXTsKICAgICAgICAgICAgdGhpcy52ZXJ0ZXhFZGdlcyA9IFtdOwogICAgICAgICAgICB0aGlzLm51bUVkZ2VzID0gMDsKICAgICAgICAgICAgdGhpcy5lZGdlQW5nbGVzID0gbmV3IEZsb2F0MzJBcnJheSgpOwogICAgICAgICAgICB0aGlzLmVtaXQoJ2dlb21EYXRhVG9wb2xvZ3lDaGFuZ2VkJyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEFkZHMgYSBuZXcgdmVydGV4IGF0dHJpYnV0ZSB0byB0aGUgZ2VvbWV0cnkuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB2ZXJ0ZXggYXR0cmlidXRlLgogICAgICAgICAqIEBwYXJhbSBhdHRyIC0gVGhlIGF0dHJpYnV0ZSB0byBhZGQgdG8gdGhlIGdlb21ldHJ5CiAgICAgICAgICovCiAgICAgICAgYWRkVmVydGV4QXR0cmlidXRlKG5hbWUsIGF0dHIpIHsKICAgICAgICAgICAgc3VwZXIuYWRkVmVydGV4QXR0cmlidXRlKG5hbWUsIGF0dHIpOwogICAgICAgICAgICBhdHRyLnNldE1lc2godGhpcyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBnZXRGYWNlQ291bnRzIG1ldGhvZC4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRGYWNlQ291bnRzKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5mYWNlQ291bnRzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZ2V0TnVtRmFjZXMgbWV0aG9kLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldE51bUZhY2VzKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5mYWNlQ291bnRzLmxlbmd0aCA9PSAwID8gMCA6IHRoaXMuZmFjZUNvdW50cy5yZWR1Y2UoKG51bUZhY2VzLCBmYykgPT4gKG51bUZhY2VzICs9IGZjKSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBnZXROdW1UcmlhbmdsZXMgbWV0aG9kLgogICAgICAgICAqIEByZXR1cm4ge251bWJlcn0gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldE51bVRyaWFuZ2xlcygpIHsKICAgICAgICAgICAgbGV0IG51bVRyaWFuZ2xlcyA9IDA7CiAgICAgICAgICAgIGxldCBudW1UcmlzUGVyRmFjZSA9IDE7CiAgICAgICAgICAgIGZvciAoY29uc3QgZmMgb2YgdGhpcy5mYWNlQ291bnRzKSB7CiAgICAgICAgICAgICAgICBudW1UcmlhbmdsZXMgKz0gZmMgKiBudW1UcmlzUGVyRmFjZTsKICAgICAgICAgICAgICAgIG51bVRyaXNQZXJGYWNlKys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIG51bVRyaWFuZ2xlczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyB0aGUgbnVtYmVyIG9mIGZhY2VzIG9uIHRoZSBtZXNoIHVzaW5nIGFuIGFycmF5IHNwZWNpZnlpbmcgdGhlIGNvdW50cyBwZXIgcG9seWdvbiBzaXplLgogICAgICAgICAqIFRoZSBmaXJzdCBpdGVtIGluIHRoZSBhcnJheSBzcGVjaWZpZXMgdGhlIG51bWJlciBvZiB0cmlhbmdsZXMsIHRoZSBzZWNvbmQsIHRoZSBudW1iZXIgb2YgcXVhZHMsIHRoZSAzcmQsIHRoZSBudW1iZXIgb2YgNSBzaWRlZCBwb2x5Z29ucyBldGMuLgogICAgICAgICAqIGUuZy4gdG8gc3BlY2lmeSAyIHRyaWFuZ2xlcywgYW5kIDcgcXVhZHMsIHdlIHdvdWxkIHBhc3MgWzIsIDddCiAgICAgICAgICogQHBhcmFtIGZhY2VDb3VudHMgLSBUaGUgZmFjZUNvdW50cyB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBzZXRGYWNlQ291bnRzKGZhY2VDb3VudHMpIHsKICAgICAgICAgICAgLy8gbGV0IG51bUZhY2VzID0gMAogICAgICAgICAgICBsZXQgbnVtRmFjZXNWZXJ0aWNlcyA9IDA7CiAgICAgICAgICAgIGxldCBudW1WZXJ0c1BlckZhY2UgPSAzOwogICAgICAgICAgICBmb3IgKGNvbnN0IGZjIG9mIGZhY2VDb3VudHMpIHsKICAgICAgICAgICAgICAgIC8vIG51bUZhY2VzICs9IGZjCiAgICAgICAgICAgICAgICBudW1GYWNlc1ZlcnRpY2VzICs9IGZjICogbnVtVmVydHNQZXJGYWNlOwogICAgICAgICAgICAgICAgbnVtVmVydHNQZXJGYWNlKys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgcHJldk51bUZhY2VzID0gdGhpcy5nZXROdW1GYWNlcygpOwogICAgICAgICAgICBpZiAocHJldk51bUZhY2VzID09IDApIHsKICAgICAgICAgICAgICAgIHRoaXMuZmFjZVZlcnRleEluZGljZXMgPSBuZXcgVWludDMyQXJyYXkobnVtRmFjZXNWZXJ0aWNlcyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBjb25zdCBmYWNlVmVydGV4SW5kaWNlcyA9IG5ldyBVaW50MzJBcnJheShudW1GYWNlc1ZlcnRpY2VzKTsKICAgICAgICAgICAgICAgIC8vIE5vdyB3ZSBwcmVzZXJ2ZSB0aGUgZXhpc3RpbmcgaW5kaWNlcyBpZiB0aGV5IGZpdCB3aXRoaW4gdGhlIG5ldyBmYWNlVmVydGV4SW5kaWNlcyBhcnJheS4KICAgICAgICAgICAgICAgIGxldCBzdGFydFNyYyA9IDA7CiAgICAgICAgICAgICAgICBsZXQgc3RhcnRUZ3QgPSAwOwogICAgICAgICAgICAgICAgbnVtRmFjZXNWZXJ0aWNlcyA9IDA7CiAgICAgICAgICAgICAgICBudW1WZXJ0c1BlckZhY2UgPSAzOwogICAgICAgICAgICAgICAgZmFjZUNvdW50cy5mb3JFYWNoKChmYywgaW5kZXgpID0+IHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBlbmRTcmMgPSBzdGFydFNyYyArIE1hdGgubWluKGZjLCB0aGlzLmZhY2VDb3VudHNbaW5kZXhdKSAqIG51bVZlcnRzUGVyRmFjZTsKICAgICAgICAgICAgICAgICAgICBmYWNlVmVydGV4SW5kaWNlcy5zZXQodGhpcy5mYWNlVmVydGV4SW5kaWNlcy5zbGljZShzdGFydFNyYywgZW5kU3JjKSwgc3RhcnRUZ3QpOwogICAgICAgICAgICAgICAgICAgIHN0YXJ0U3JjICs9IHRoaXMuZmFjZUNvdW50c1tpbmRleF0gKiBudW1WZXJ0c1BlckZhY2U7CiAgICAgICAgICAgICAgICAgICAgc3RhcnRUZ3QgKz0gZmMgKiBudW1WZXJ0c1BlckZhY2U7CiAgICAgICAgICAgICAgICAgICAgbnVtVmVydHNQZXJGYWNlKys7CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIHRoaXMuZmFjZVZlcnRleEluZGljZXMgPSBmYWNlVmVydGV4SW5kaWNlczsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLmZhY2VDb3VudHMgPSBmYWNlQ291bnRzOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgZmFjZSB2ZXJ0aWNlcwogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldE51bUZhY2VWZXJ0aWNlcygpIHsKICAgICAgICAgICAgbGV0IG51bUZhY2VWZXJ0cyA9IDA7CiAgICAgICAgICAgIHRoaXMuZmFjZUNvdW50cy5mb3JFYWNoKChmYywgaW5kZXgpID0+IHsKICAgICAgICAgICAgICAgIG51bUZhY2VWZXJ0cyArPSBmYyAqIChpbmRleCArIDMpOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgcmV0dXJuIG51bUZhY2VWZXJ0czsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIHZlcnRpY2VzIGluZGV4ZWQgYnkgdGhpcyBmYWNlCiAgICAgICAgICogQHBhcmFtIGZhY2VJbmRleCAtIFRoZSBmYWNlSW5kZXggdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2V0RmFjZVZlcnRleENvdW50KGZhY2VJbmRleCkgewogICAgICAgICAgICBsZXQgaWR4ID0gMDsKICAgICAgICAgICAgbGV0IGNvdW50ID0gMDsKICAgICAgICAgICAgdGhpcy5mYWNlQ291bnRzLnNvbWUoKGZjLCBpbmRleCkgPT4gewogICAgICAgICAgICAgICAgaWR4ICs9IGZjOwogICAgICAgICAgICAgICAgaWYgKGlkeCA+IGZhY2VJbmRleCkgewogICAgICAgICAgICAgICAgICAgIGNvdW50ID0gaW5kZXggKyAzOwogICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgcmV0dXJuIGNvdW50OwogICAgICAgIH0KICAgICAgICBnZXRGYWNlVmVydGV4T2Zmc2V0KGZhY2VJbmRleCkgewogICAgICAgICAgICBsZXQgaWR4ID0gMDsKICAgICAgICAgICAgbGV0IG9mZnNldCA9IDA7CiAgICAgICAgICAgIHRoaXMuZmFjZUNvdW50cy5zb21lKChmYywgaW5kZXgpID0+IHsKICAgICAgICAgICAgICAgIGlmIChpZHggKyBmYyA+IGZhY2VJbmRleCkgewogICAgICAgICAgICAgICAgICAgIG9mZnNldCArPSAoZmFjZUluZGV4IC0gaWR4KSAqIChpbmRleCArIDMpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWR4ICs9IGZjOwogICAgICAgICAgICAgICAgb2Zmc2V0ICs9IGZjICogKGluZGV4ICsgMyk7CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICByZXR1cm4gb2Zmc2V0OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgc2V0RmFjZVZlcnRleEluZGljZXMgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSBmYWNlSW5kZXggLSBUaGUgZmFjZUluZGV4IHZhbHVlLgogICAgICAgICAqIEBwYXJhbSB2ZXJ0ZXhJbmRpY2VzIC0gVGhlIGFycmF5IG9mIHZlcnRleCBpbmRpY2VzIGZvciB0aGlzIGZhY2UgdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgc2V0RmFjZVZlcnRleEluZGljZXMoZmFjZUluZGV4LCB2ZXJ0ZXhJbmRpY2VzKSB7CiAgICAgICAgICAgIGNvbnN0IGZhY2VWZXJ0ZXhDb3VudCA9IHRoaXMuZ2V0RmFjZVZlcnRleENvdW50KGZhY2VJbmRleCk7CiAgICAgICAgICAgIGlmICh2ZXJ0ZXhJbmRpY2VzLmxlbmd0aCAhPSBmYWNlVmVydGV4Q291bnQpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBpbmRpY2VzIGZvciBmYWNlOiR7ZmFjZUluZGV4fSB2ZXJ0ZXhJbmRpY2VzOiR7dmVydGV4SW5kaWNlc30uIEV4cGVjdGVkICR7ZmFjZVZlcnRleENvdW50fSBpbmRpY2VzYCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gdGhpcy5nZXRGYWNlVmVydGV4T2Zmc2V0KGZhY2VJbmRleCk7CiAgICAgICAgICAgIHRoaXMuZmFjZVZlcnRleEluZGljZXMuc2V0KHZlcnRleEluZGljZXMsIG9mZnNldCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEFkZHMgYSBuZXcgZmFjZSB0byB0aGUgbWVzaAogICAgICAgICAqIEBwYXJhbSB2ZXJ0ZXhJbmRpY2VzIC0gVGhlIHZlcnRleCBpbmRpY2VzIG9mIHRoZSBmYWNlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgaW5kZXggb2YgdGhlIGZhY2UgaW4gdGhlIG1lc2guCiAgICAgICAgICovCiAgICAgICAgYWRkRmFjZSh2ZXJ0ZXhJbmRpY2VzKSB7CiAgICAgICAgICAgIGNvbnN0IGZhY2VDb3VudHMgPSBbLi4udGhpcy5mYWNlQ291bnRzXTsKICAgICAgICAgICAgaWYgKGZhY2VDb3VudHMubGVuZ3RoIDw9IHZlcnRleEluZGljZXMubGVuZ3RoIC0gMykgewogICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IGZhY2VDb3VudHMubGVuZ3RoOyBpIDwgdmVydGV4SW5kaWNlcy5sZW5ndGggLSAzOyBpKyspCiAgICAgICAgICAgICAgICAgICAgZmFjZUNvdW50c1tpXSA9IDA7CiAgICAgICAgICAgICAgICBmYWNlQ291bnRzW3ZlcnRleEluZGljZXMubGVuZ3RoIC0gM10gPSAxOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgZmFjZUNvdW50c1t2ZXJ0ZXhJbmRpY2VzLmxlbmd0aCAtIDNdKys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5zZXRGYWNlQ291bnRzKGZhY2VDb3VudHMpOwogICAgICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIG9mZnNldCBpbiB0aGUgZmFjZVZlcnRleEluZGljZXMgb2YgdGhpcyBuZXcgZmFjZS4KICAgICAgICAgICAgbGV0IGZhY2VJbmRleCA9IDA7CiAgICAgICAgICAgIGxldCBvZmZzZXQgPSAwOwogICAgICAgICAgICB0aGlzLmZhY2VDb3VudHMuc29tZSgoZmMsIGluZGV4KSA9PiB7CiAgICAgICAgICAgICAgICBpZiAoaW5kZXggKyAzID09IHZlcnRleEluZGljZXMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgZmFjZUluZGV4ICs9IGZjIC0gMTsKICAgICAgICAgICAgICAgICAgICBvZmZzZXQgKz0gKGZjIC0gMSkgKiAoaW5kZXggKyAzKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZhY2VJbmRleCArPSBmYzsKICAgICAgICAgICAgICAgIG9mZnNldCArPSBmYyAqIChpbmRleCArIDMpOwogICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgdGhpcy5mYWNlVmVydGV4SW5kaWNlcy5zZXQodmVydGV4SW5kaWNlcywgb2Zmc2V0KTsKICAgICAgICAgICAgcmV0dXJuIGZhY2VJbmRleDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgdmVydGV4IGluZGljZXMgb2YgdGhlIHNwZWNpZmllZCBmYWNlLgogICAgICAgICAqIEBwYXJhbSBmYWNlSW5kZXggLSBUaGUgaW5kZXggb2YgdGhlIHNwZWNpZmllZCBmYWNlCiAgICAgICAgICogQHJldHVybiAtIEFuIGFycmF5IG9mIGluZGljZXMgaW50byB0aGUgdmVydGV4IGF0dHJpYnV0ZXMKICAgICAgICAgKi8KICAgICAgICBnZXRGYWNlVmVydGV4SW5kaWNlcyhmYWNlSW5kZXgpIHsKICAgICAgICAgICAgY29uc3QgdmVydGV4SW5kaWNlcyA9IFtdOwogICAgICAgICAgICBjb25zdCBvZmZzZXQgPSB0aGlzLmdldEZhY2VWZXJ0ZXhPZmZzZXQoZmFjZUluZGV4KTsKICAgICAgICAgICAgY29uc3QgY291bnQgPSB0aGlzLmdldEZhY2VWZXJ0ZXhDb3VudChmYWNlSW5kZXgpOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgICAgICAgICAgIHZlcnRleEluZGljZXMucHVzaCh0aGlzLmZhY2VWZXJ0ZXhJbmRpY2VzW29mZnNldCArIGldKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdmVydGV4SW5kaWNlczsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBhIHNpbmdsZSB2ZXJ0ZXggaW5kZXggZm9yIGEgZ2l2ZW4gZmFjZSBhbmQgZmFjZVZlcnRleC4KICAgICAgICAgKiBAcGFyYW0gZmFjZUluZGV4IC0gVGhlIGZhY2VJbmRleCB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gZmFjZVZlcnRleCAtIFRoZSBmYWNlIHZlcnRleCBpcyB0aGUgaW5kZXggd2l0aGluIHRoZSBmYWNlLiBTbyB0aGUgZmlyc3QgdmVydGV4IGluZGV4IGlzIDAuCiAgICAgICAgICogQHJldHVybiAtIFRoZSB2ZXJ0ZXggaW5kZXgKICAgICAgICAgKi8KICAgICAgICBnZXRGYWNlVmVydGV4SW5kZXgoZmFjZUluZGV4LCBmYWNlVmVydGV4KSB7CiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHRoaXMuZ2V0RmFjZVZlcnRleE9mZnNldChmYWNlSW5kZXgpOwogICAgICAgICAgICByZXR1cm4gdGhpcy5mYWNlVmVydGV4SW5kaWNlc1tvZmZzZXQgKyBmYWNlVmVydGV4XTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gRmFjZSBBdHRyaWJ1dGVzCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGFkZEZhY2VBdHRyaWJ1dGUgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGZhY2UgYXR0cmlidXRlIHRvIGFkZC4KICAgICAgICAgKiBAcGFyYW0gYXR0ciAtIFRoZSBhdHRyIHZhbHVlCiAgICAgICAgICovCiAgICAgICAgYWRkRmFjZUF0dHJpYnV0ZShuYW1lLCBhdHRyKSB7CiAgICAgICAgICAgIGF0dHIuc2V0Q291bnQodGhpcy5nZXROdW1GYWNlcygpKTsKICAgICAgICAgICAgdGhpcy5fX2ZhY2VBdHRyaWJ1dGVzLnNldChuYW1lLCBhdHRyKTsKICAgICAgICAgICAgcmV0dXJuIGF0dHI7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBoYXNGYWNlQXR0cmlidXRlIG1ldGhvZC4KICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBmYWNlIGF0dHJpYnV0ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBoYXNGYWNlQXR0cmlidXRlKG5hbWUpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX19mYWNlQXR0cmlidXRlcy5oYXMobmFtZSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBnZXRGYWNlQXR0cmlidXRlIG1ldGhvZC4KICAgICAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBmYWNlIGF0dHJpYnV0ZS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBnZXRGYWNlQXR0cmlidXRlKG5hbWUpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX19mYWNlQXR0cmlidXRlcy5nZXQobmFtZSk7CiAgICAgICAgfQogICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAvLyBFZGdlIEF0dHJpYnV0ZXMKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgYWRkRWRnZUF0dHJpYnV0ZSBtZXRob2QuCiAgICAgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZWRnZSBhdHRyaWJ1dGUgdG8gYWRkLgogICAgICAgICAqIEBwYXJhbSBhdHRyIC0gVGhlIGF0dHIgdmFsdWUKICAgICAgICAgKi8KICAgICAgICBhZGRFZGdlQXR0cmlidXRlKG5hbWUsIGF0dHIpIHsKICAgICAgICAgICAgYXR0ci5zZXRDb3VudCh0aGlzLm51bUVkZ2VzKTsKICAgICAgICAgICAgdGhpcy5fX2VkZ2VBdHRyaWJ1dGVzLnNldChuYW1lLCBhdHRyKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGhhc0VkZ2VBdHRyaWJ1dGUgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGVkZ2UgYXR0cmlidXRlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGhhc0VkZ2VBdHRyaWJ1dGUobmFtZSkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fX2VkZ2VBdHRyaWJ1dGVzLmhhcyhuYW1lKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGdldEVkZ2VBdHRyaWJ1dGUgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGVkZ2UgYXR0cmlidXRlLgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGdldEVkZ2VBdHRyaWJ1dGUobmFtZSkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fX2VkZ2VBdHRyaWJ1dGVzLmdldChuYW1lKTsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGdlblRvcG9sb2d5SW5mbyBtZXRob2QuCiAgICAgICAgICovCiAgICAgICAgZ2VuVG9wb2xvZ3lJbmZvKCkgewogICAgICAgICAgICBsZXQgY29ubmVjdGVkVmVydGljZXMgPSB7fTsgLy8gYWNjZWxlcmF0aW9uIHN0cnVjdHVyZS4KICAgICAgICAgICAgdGhpcy52ZXJ0ZXhFZGdlcyA9IFtdOyAvLyAyZCBhcnJheSBvZiB2ZXJ0ZXggdG8gZWRnZXMuCiAgICAgICAgICAgIC8vIHRoaXMudmVydGV4RmFjZXMgPSBbXTsgLy8gMmQgYXJyYXkgb2YgdmVydGV4IHRvIGZhY2VzLgogICAgICAgICAgICB0aGlzLmVkZ2VGYWNlcyA9IFtdOyAvLyBmbGF0IGFycmF5IG9mIDIgZmFjZSBpbmRpY2VzIHBlciBlZGdlCiAgICAgICAgICAgIHRoaXMuZWRnZVZlcnRzID0gW107IC8vIGZsYXQgYXJyYXkgb2YgMiB2ZXJ0IGluZGljZXMgcGVyIGVkZ2UKICAgICAgICAgICAgdGhpcy5mYWNlRWRnZXMgPSBbXTsgLy8gdGhlIGVkZ2VzIGJvcmRlcmluZyBlYWNoIGZhY2UuCiAgICAgICAgICAgIHRoaXMubnVtRWRnZXMgPSAwOwogICAgICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSB0aGlzLnBvc2l0aW9uczsKICAgICAgICAgICAgY29uc3QgZ2V0RWRnZUluZGV4ID0gKHYwLCB2MSkgPT4gewogICAgICAgICAgICAgICAgbGV0IHRtcDAgPSB2MDsKICAgICAgICAgICAgICAgIGxldCB0bXAxID0gdjE7CiAgICAgICAgICAgICAgICBpZiAodG1wMSA8IHRtcDApIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCB0bXAgPSB0bXAwOwogICAgICAgICAgICAgICAgICAgIHRtcDAgPSB0bXAxOwogICAgICAgICAgICAgICAgICAgIHRtcDEgPSB0bXA7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjb25zdCBrZXkgPSB0bXAwICsgJz4nICsgdG1wMTsKICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gY29ubmVjdGVkVmVydGljZXMpIHsKICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhrZXkgKyAnOicgKyBjb25uZWN0ZWRWZXJ0aWNlc1trZXldICsgIiBmYWNlOiIgKyAoIHYwIDwgdjEgPyAwIDogMSkgKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29ubmVjdGVkVmVydGljZXNba2V5XTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNvbnN0IHAwID0gcG9zaXRpb25zLmdldFZhbHVlKHRtcDApOwogICAgICAgICAgICAgICAgY29uc3QgcDEgPSBwb3NpdGlvbnMuZ2V0VmFsdWUodG1wMSk7CiAgICAgICAgICAgICAgICBjb25zdCBlZGdlVmVjID0gcDEuc3VidHJhY3QocDApOwogICAgICAgICAgICAgICAgY29uc3QgZWRnZUluZGV4ID0gdGhpcy5lZGdlRmFjZXMubGVuZ3RoIC8gMjsKICAgICAgICAgICAgICAgIGNvbnN0IGVkZ2VEYXRhID0gewogICAgICAgICAgICAgICAgICAgIGVkZ2VJbmRleDogZWRnZUluZGV4LAogICAgICAgICAgICAgICAgICAgIGVkZ2VWZWM6IGVkZ2VWZWMsCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgY29ubmVjdGVkVmVydGljZXNba2V5XSA9IGVkZ2VEYXRhOwogICAgICAgICAgICAgICAgdGhpcy5lZGdlRmFjZXMucHVzaCgtMSk7CiAgICAgICAgICAgICAgICB0aGlzLmVkZ2VGYWNlcy5wdXNoKC0xKTsKICAgICAgICAgICAgICAgIHRoaXMuZWRnZVZlcnRzLnB1c2godG1wMCk7CiAgICAgICAgICAgICAgICB0aGlzLmVkZ2VWZXJ0cy5wdXNoKHRtcDEpOwogICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coa2V5ICsgJzonICsgY29ubmVjdGVkVmVydGljZXNba2V5XSArICIgZmFjZToiICsgKCB2MCA8IHYxID8gMCA6IDEpKTsKICAgICAgICAgICAgICAgIHRoaXMubnVtRWRnZXMrKzsKICAgICAgICAgICAgICAgIHJldHVybiBlZGdlRGF0YTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgY29uc3QgYWRkRWRnZSA9ICh2MCwgdjEsIGZhY2VJbmRleCkgPT4gewogICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ2FkZEVkZ2U6JyArIHYwICsgIiA6IiArIHYxICsgIiBmYWNlSW5kZXg6IiArIGZhY2VJbmRleCApOwogICAgICAgICAgICAgICAgY29uc3QgZWRnZURhdGEgPSBnZXRFZGdlSW5kZXgodjAsIHYxKTsKICAgICAgICAgICAgICAgIGNvbnN0IGVkZ2VJbmRleCA9IGVkZ2VEYXRhLmVkZ2VJbmRleDsKICAgICAgICAgICAgICAgIGlmICh2MSA8IHYwKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZWRnZUZhY2VJbmRleCA9IGVkZ2VJbmRleCAqIDIgKyAwOwogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9fbG9nVG9wb2xvZ3lXYXJuaW5ncyAmJiB0aGlzLmVkZ2VGYWNlc1tlZGdlRmFjZUluZGV4XSAhPSAtMSkKICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdFZGdlIHBvbHkgMCBhbHJlYWR5IHNldC4gTWVzaCBpcyBub24tbWFuaWZvbGQuJyk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGdlRmFjZXNbZWRnZUZhY2VJbmRleF0gPSBmYWNlSW5kZXg7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBlZGdlRmFjZUluZGV4ID0gZWRnZUluZGV4ICogMiArIDE7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX19sb2dUb3BvbG9neVdhcm5pbmdzICYmIHRoaXMuZWRnZUZhY2VzW2VkZ2VGYWNlSW5kZXhdICE9IC0xKQogICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0VkZ2UgcG9seSAxIGFscmVhZHkgc2V0LiBNZXNoIGlzIG5vbi1tYW5pZm9sZC4nKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmVkZ2VGYWNlc1tlZGdlRmFjZUluZGV4XSA9IGZhY2VJbmRleDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmICghKGZhY2VJbmRleCBpbiB0aGlzLmZhY2VFZGdlcykpCiAgICAgICAgICAgICAgICAgICAgdGhpcy5mYWNlRWRnZXNbZmFjZUluZGV4XSA9IFtdOwogICAgICAgICAgICAgICAgdGhpcy5mYWNlRWRnZXNbZmFjZUluZGV4XS5wdXNoKGVkZ2VJbmRleCk7CiAgICAgICAgICAgICAgICAvLyBQdXNoIHRoZSBlZGdlIGluZGV4IG9udG8gYm90aCB2ZXJ0ZXggZWRnZSBsaXN0cy4KICAgICAgICAgICAgICAgIC8vIFdlIHVzZSBTZXRzIHRvIGF2b2lkIGFkZGluZyB0aGUgc2FtZSBlZGdlIDJ4IHRvIHRoZSBzYW1lIHZlcnRleC4KICAgICAgICAgICAgICAgIGlmICh0aGlzLnZlcnRleEVkZ2VzW3YwXSA9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLnZlcnRleEVkZ2VzW3YwXSA9IG5ldyBTZXQoKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmICh0aGlzLnZlcnRleEVkZ2VzW3YxXSA9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLnZlcnRleEVkZ2VzW3YxXSA9IG5ldyBTZXQoKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRoaXMudmVydGV4RWRnZXNbdjBdLmFkZChlZGdlSW5kZXgpOwogICAgICAgICAgICAgICAgdGhpcy52ZXJ0ZXhFZGdlc1t2MV0uYWRkKGVkZ2VJbmRleCk7CiAgICAgICAgICAgICAgICAvLyBpZiAodGhpcy52ZXJ0ZXhGYWNlc1t2MF0gPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAvLyAgICAgdGhpcy52ZXJ0ZXhGYWNlc1t2MF0gPSBbXTsKICAgICAgICAgICAgICAgIC8vIH0KICAgICAgICAgICAgICAgIC8vIHRoaXMudmVydGV4RmFjZXNbdjBdLnB1c2goZmFjZUluZGV4KTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgY29uc3QgbnVtRmFjZXMgPSB0aGlzLmdldE51bUZhY2VzKCk7CiAgICAgICAgICAgIGZvciAobGV0IGZhY2VJbmRleCA9IDA7IGZhY2VJbmRleCA8IG51bUZhY2VzOyBmYWNlSW5kZXgrKykgewogICAgICAgICAgICAgICAgY29uc3QgZmFjZVZlcnRzID0gdGhpcy5nZXRGYWNlVmVydGV4SW5kaWNlcyhmYWNlSW5kZXgpOwogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBmYWNlVmVydHMubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCB2MCA9IGZhY2VWZXJ0c1tqXTsKICAgICAgICAgICAgICAgICAgICBjb25zdCB2MSA9IGZhY2VWZXJ0c1soaiArIDEpICUgZmFjZVZlcnRzLmxlbmd0aF07CiAgICAgICAgICAgICAgICAgICAgYWRkRWRnZSh2MCwgdjEsIGZhY2VJbmRleCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ29tcHV0ZXMgYSBub3JtYWwgdmFsdWUgcGVyIGZhY2UgYnkgYXZlcmFnaW5nIHRoZSB0cmlhbmdsZSBub3JtYWxzIG9mIHRoZSBmYWNlLgogICAgICAgICAqLwogICAgICAgIGNvbXB1dGVGYWNlTm9ybWFscygpIHsKICAgICAgICAgICAgY29uc3QgcG9zaXRpb25zID0gdGhpcy5wb3NpdGlvbnM7CiAgICAgICAgICAgIGNvbnN0IGZhY2VOb3JtYWxzID0gbmV3IFZlYzNmOEF0dHJpYnV0ZSgpOwogICAgICAgICAgICB0aGlzLmFkZEZhY2VBdHRyaWJ1dGUoJ25vcm1hbHMnLCBmYWNlTm9ybWFscyk7CiAgICAgICAgICAgIGNvbnN0IG51bUZhY2VzID0gdGhpcy5nZXROdW1GYWNlcygpOwogICAgICAgICAgICBmb3IgKGxldCBmYWNlSW5kZXggPSAwOyBmYWNlSW5kZXggPCBudW1GYWNlczsgZmFjZUluZGV4KyspIHsKICAgICAgICAgICAgICAgIGNvbnN0IGZhY2VWZXJ0cyA9IHRoaXMuZ2V0RmFjZVZlcnRleEluZGljZXMoZmFjZUluZGV4KTsKICAgICAgICAgICAgICAgIGNvbnN0IHAwID0gcG9zaXRpb25zLmdldFZhbHVlKGZhY2VWZXJ0c1swXSk7CiAgICAgICAgICAgICAgICBjb25zdCBwMSA9IHBvc2l0aW9ucy5nZXRWYWx1ZShmYWNlVmVydHNbMV0pOwogICAgICAgICAgICAgICAgbGV0IHByZXYgPSBwMTsKICAgICAgICAgICAgICAgIGNvbnN0IGZhY2VOb3JtYWwgPSBuZXcgVmVjMygpOwogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDI7IGogPCBmYWNlVmVydHMubGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBwbiA9IHBvc2l0aW9ucy5nZXRWYWx1ZShmYWNlVmVydHNbal0pOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHYwID0gcHJldi5zdWJ0cmFjdChwMCk7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdjEgPSBwbi5zdWJ0cmFjdChwMCk7CiAgICAgICAgICAgICAgICAgICAgZmFjZU5vcm1hbC5hZGRJblBsYWNlKHYwLmNyb3NzKHYxKS5ub3JtYWxpemUoKSk7CiAgICAgICAgICAgICAgICAgICAgcHJldiA9IHBuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKGZhY2VOb3JtYWwubGVuZ3RoU3F1YXJlZCgpIDwgTnVtYmVyLkVQU0lMT04pIDsKICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIGZhY2VOb3JtYWxzLnNldFZhbHVlKGZhY2VJbmRleCwgZmFjZU5vcm1hbC5ub3JtYWxpemUoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ2FsY3VsYXRlcyB0aGUgYW5nbGVzIGF0IGVhY2ggZWRnZSBiZXR3ZWVuIHRoZSBhZGpvaW5pbmcgZmFjZXMKICAgICAgICAgKi8KICAgICAgICBjYWxjdWxhdGVFZGdlQW5nbGVzKCkgewogICAgICAgICAgICBpZiAodGhpcy52ZXJ0ZXhFZGdlcy5sZW5ndGggPT0gMCkKICAgICAgICAgICAgICAgIHRoaXMuZ2VuVG9wb2xvZ3lJbmZvKCk7CiAgICAgICAgICAgIHRoaXMuY29tcHV0ZUZhY2VOb3JtYWxzKCk7CiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IHRoaXMucG9zaXRpb25zOwogICAgICAgICAgICBjb25zdCBmYWNlTm9ybWFscyA9IHRoaXMuZ2V0RmFjZUF0dHJpYnV0ZSgnbm9ybWFscycpOwogICAgICAgICAgICB0aGlzLmVkZ2VWZWNzID0gW107CiAgICAgICAgICAgIHRoaXMuZWRnZUFuZ2xlcyA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5udW1FZGdlcyk7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5lZGdlRmFjZXMubGVuZ3RoOyBpICs9IDIpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHYwID0gdGhpcy5lZGdlVmVydHNbaV07CiAgICAgICAgICAgICAgICBjb25zdCB2MSA9IHRoaXMuZWRnZVZlcnRzW2kgKyAxXTsKICAgICAgICAgICAgICAgIGNvbnN0IGVkZ2VWZWMgPSBwb3NpdGlvbnMuZ2V0VmFsdWUodjEpLnN1YnRyYWN0KHBvc2l0aW9ucy5nZXRWYWx1ZSh2MCkpOwogICAgICAgICAgICAgICAgZWRnZVZlYy5ub3JtYWxpemVJblBsYWNlKCk7CiAgICAgICAgICAgICAgICB0aGlzLmVkZ2VWZWNzLnB1c2goZWRnZVZlYyk7CiAgICAgICAgICAgICAgICBjb25zdCBwMCA9IHRoaXMuZWRnZUZhY2VzW2ldOwogICAgICAgICAgICAgICAgY29uc3QgcDEgPSB0aGlzLmVkZ2VGYWNlc1tpICsgMV07CiAgICAgICAgICAgICAgICBpZiAocDAgPT0gLTEgfHwgcDEgPT0gLTEpIHsKICAgICAgICAgICAgICAgICAgICAvLyBGbGFnIHRoZSBlZGdlIGFzIGEgYm9yZGVyIGVkZ2UuLi4uCiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGdlQW5nbGVzW2kgLyAyXSA9IE1hdGguUEkgKiAyLjA7CiAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjb25zdCBuMCA9IGZhY2VOb3JtYWxzLmdldFZhbHVlKHAwKTsKICAgICAgICAgICAgICAgIGNvbnN0IG4xID0gZmFjZU5vcm1hbHMuZ2V0VmFsdWUocDEpOwogICAgICAgICAgICAgICAgdGhpcy5lZGdlQW5nbGVzW2kgLyAyXSA9IG4wLmFuZ2xlVG8objEpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENvbXB1dGUgdmVydGV4IG5vcm1hbHMuCiAgICAgICAgICogQHBhcmFtIGhhcmRBbmdsZSAtIFRoZSBoYXJkQW5nbGUgdmFsdWUgaW4gcmFkaWFucy4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBjb21wdXRlVmVydGV4Tm9ybWFscyhoYXJkQW5nbGUgPSAxLjAgLyogcmFkaWFucyAqLykgewogICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZUVkZ2VBbmdsZXMoKTsKICAgICAgICAgICAgY29uc3QgZmFjZU5vcm1hbHMgPSB0aGlzLmdldEZhY2VBdHRyaWJ1dGUoJ25vcm1hbHMnKTsKICAgICAgICAgICAgY29uc3Qgbm9ybWFsc0F0dHIgPSBuZXcgVmVjM2Y4QXR0cmlidXRlKCk7CiAgICAgICAgICAgIHRoaXMuYWRkVmVydGV4QXR0cmlidXRlKCdub3JtYWxzJywgbm9ybWFsc0F0dHIpOwogICAgICAgICAgICAvLyB0aGVzZSBtZXRob2RzIGFyZSBmYXN0ZXIgdmVyc2lvbnMgdGhhbiB1c2luZyB0aGUgbWV0aG9kcwogICAgICAgICAgICAvLyBwcm92aWRlZCBvbiB0aGUgYXR0cmlidXRlcy4gV2UgY2FjaGUgdmFsdWVzIGFuZCB1c2UgaGFyZCBjb2RlZCBjb25zdGFudHMuCiAgICAgICAgICAgIC8vIGNvbnN0IGZhY2VOb3JtYWxzQnVmZmVyID0gZmFjZU5vcm1hbHMuZGF0YS5idWZmZXIKICAgICAgICAgICAgY29uc3QgZ2V0RmFjZU5vcm1hbCA9IChpbmRleCkgPT4gewogICAgICAgICAgICAgICAgcmV0dXJuIGZhY2VOb3JtYWxzLmdldFZhbHVlKGluZGV4KTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgY29uc3Qgc2V0VmVydGV4Tm9ybWFsID0gKGluZGV4LCB2YWx1ZSkgPT4gewogICAgICAgICAgICAgICAgbm9ybWFsc0F0dHIuc2V0VmFsdWUoaW5kZXgsIHZhbHVlKTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgY29uc3QgZ2V0Q29ubmVjdGVkRWRnZVZlY3MgPSAoZmFjZUluZGV4LCB2ZXJ0ZXhJbmRleCkgPT4gewogICAgICAgICAgICAgICAgbGV0IGUwOwogICAgICAgICAgICAgICAgbGV0IGUxOwogICAgICAgICAgICAgICAgY29uc3QgZmFjZUVkZ2VzID0gdGhpcy5mYWNlRWRnZXNbZmFjZUluZGV4XTsKICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZSBvZiBmYWNlRWRnZXMpIHsKICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5lZGdlVmVydHNbZSAqIDJdID09IHZlcnRleEluZGV4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZTApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlMCA9IHRoaXMuZWRnZVZlY3NbZV07CiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUxID0gdGhpcy5lZGdlVmVjc1tlXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5lZGdlVmVydHNbZSAqIDIgKyAxXSA9PSB2ZXJ0ZXhJbmRleCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWUwKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZTAgPSB0aGlzLmVkZ2VWZWNzW2VdOwogICAgICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlMSA9IHRoaXMuZWRnZVZlY3NbZV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmV0dXJuIFtlMCwgZTFdOwogICAgICAgICAgICB9OwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMudmVydGV4RWRnZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgZmFjZSBpbmRleGluZyBkb2Vzbid0IHN0YXJ0IGF0IDAsIHRoZW4gdGhlIHZlcnRleEVkZ2VzIGRvbid0IGVpdGhlci4KICAgICAgICAgICAgICAgIGlmICh0aGlzLnZlcnRleEVkZ2VzW2ldID09IHVuZGVmaW5lZCkKICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgIGNvbnN0IGVkZ2VzID0gdGhpcy52ZXJ0ZXhFZGdlc1tpXTsKICAgICAgICAgICAgICAgIC8vIEdyb3VwcyBvZiBmYWNlcyBoYXZpbmcgYSBzbW9vdGggbm9ybWFsIGF0IHRoZSBjdXJyZW50IHZlcnRleC4KICAgICAgICAgICAgICAgIGNvbnN0IGZhY2VHcm91cHMgPSBbXTsKICAgICAgICAgICAgICAgIGNvbnN0IGFkZEZhY2VUb0dyb3VwID0gKGZhY2UpID0+IHsKICAgICAgICAgICAgICAgICAgICBsZXQgaW5Hcm91cCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZmFjZUdyb3VwIG9mIGZhY2VHcm91cHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaW5Hcm91cCA9IGZhY2VHcm91cC5pbmNsdWRlcyhmYWNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluR3JvdXApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKCFpbkdyb3VwKQogICAgICAgICAgICAgICAgICAgICAgICBmYWNlR3JvdXBzLnB1c2goW2ZhY2VdKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGUgb2YgZWRnZXMpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBmMCA9IHRoaXMuZWRnZUZhY2VzW2UgKiAyXTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBmMSA9IHRoaXMuZWRnZUZhY2VzW2UgKiAyICsgMV07CiAgICAgICAgICAgICAgICAgICAgaWYgKGYwICE9IC0xICYmIGYxICE9IC0xICYmIHRoaXMuZWRnZUFuZ2xlc1tlXSA8IGhhcmRBbmdsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiAoZjAgIT0gLTEgJiYgZjEgPT0gLTEgJiYgdGhpcy5lZGdlQW5nbGVzW2VdIDwgaGFyZEFuZ2xlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmMGdyb3VwSW5kZXggPSAtMTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGYxZ3JvdXBJbmRleCA9IC0xOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBncm91cEluZGV4ID0gMDsgZ3JvdXBJbmRleCA8IGZhY2VHcm91cHMubGVuZ3RoOyBncm91cEluZGV4KyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmMGdyb3VwSW5kZXggPT0gLTEgJiYgZmFjZUdyb3Vwc1tncm91cEluZGV4XS5pbmNsdWRlcyhmMCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZjBncm91cEluZGV4ID0gZ3JvdXBJbmRleDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmMWdyb3VwSW5kZXggPT0gLTEgJiYgZmFjZUdyb3Vwc1tncm91cEluZGV4XS5pbmNsdWRlcyhmMSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZjFncm91cEluZGV4ID0gZ3JvdXBJbmRleDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZjBncm91cEluZGV4ID09IC0xICYmIGYxZ3JvdXBJbmRleCA9PSAtMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZUdyb3Vwcy5wdXNoKFtmMCwgZjFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChmMGdyb3VwSW5kZXggIT0gLTEgJiYgZjFncm91cEluZGV4ICE9IC0xKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZjBncm91cEluZGV4ICE9IGYxZ3JvdXBJbmRleCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1lcmdlIHRoZSAyIGdyb3VwcyB0aGF0IHRoZSBzbW9vdGggZWRnZSBqb2lucy4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlR3JvdXBzW2YwZ3JvdXBJbmRleF0gPSBmYWNlR3JvdXBzW2YwZ3JvdXBJbmRleF0uY29uY2F0KGZhY2VHcm91cHNbZjFncm91cEluZGV4XSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZUdyb3Vwcy5zcGxpY2UoZjFncm91cEluZGV4LCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmMGdyb3VwSW5kZXggPT0gLTEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlR3JvdXBzW2YxZ3JvdXBJbmRleF0ucHVzaChmMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZjFncm91cEluZGV4ID09IC0xKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZUdyb3Vwc1tmMGdyb3VwSW5kZXhdLnB1c2goZjEpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIGEgaGFyZCBlZGdlIG9yIGEgYm9yZGVyIGVkZ2UuLi4gQWRkIGZhY2VzIHNlcGFyYXRlbHkgZ3JvdXAuCiAgICAgICAgICAgICAgICAgICAgaWYgKGYwICE9IC0xKQogICAgICAgICAgICAgICAgICAgICAgICBhZGRGYWNlVG9Hcm91cChmMCk7CiAgICAgICAgICAgICAgICAgICAgaWYgKGYxICE9IC0xKQogICAgICAgICAgICAgICAgICAgICAgICBhZGRGYWNlVG9Hcm91cChmMSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAvLyBTb3J0IHRoZSBncm91cHMgdG8gaGF2ZSB0aGUgYmlnZ2VzdCBncm91cCBmaXJzdC4KICAgICAgICAgICAgICAgIGZhY2VHcm91cHMuc29ydCgoYSwgYikgPT4gKGEubGVuZ3RoIDwgYi5sZW5ndGggPyAxIDogYS5sZW5ndGggPiBiLmxlbmd0aCA/IC0xIDogMCkpOwogICAgICAgICAgICAgICAgbGV0IGZpcnN0VmVydGV4ID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZmFjZUdyb3VwIG9mIGZhY2VHcm91cHMpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBub3JtYWwgPSBuZXcgVmVjMygpOwogICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZmFjZUluZGV4IG9mIGZhY2VHcm91cCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmYWNlRWRnZXMgPSBnZXRDb25uZWN0ZWRFZGdlVmVjcyhmYWNlSW5kZXgsIGkpOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgd2VpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZmFjZUVkZ2VzWzBdICYmIGZhY2VFZGdlc1sxXSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VpZ2h0ID0gZmFjZUVkZ2VzWzBdLmFuZ2xlVG8oZmFjZUVkZ2VzWzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbC5hZGRJblBsYWNlKGdldEZhY2VOb3JtYWwoZmFjZUluZGV4KS5zY2FsZSh3ZWlnaHQpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybigndmFyaWFibGUgd2VpZ2h0IGlzIHVuZGVmaW5lZCBiZWNhdXNlIGZhY2VFZGdlc1swXSBvciBmYWNlRWRnZXNbMV0gaXMgdW5kZWZpbmVkJyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgKGkgPT0gMSkKICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIGNvbnNvbGUubG9nKCJGYWNlTm9ybWFsOiIgKyBmYWNlSW5kZXggKyAiOiIgKyBnZXRGYWNlTm9ybWFsKGZhY2VJbmRleCkudG9TdHJpbmcoKSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIG5vcm1hbC5ub3JtYWxpemVJblBsYWNlKCk7CiAgICAgICAgICAgICAgICAgICAgaWYgKGZpcnN0VmVydGV4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHNldFZlcnRleE5vcm1hbChpLCBub3JtYWwpOwogICAgICAgICAgICAgICAgICAgICAgICBmaXJzdFZlcnRleCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgbm9ybWFsc0F0dHIuc2V0U3BsaXRWZXJ0ZXhWYWx1ZXMoaSwgZmFjZUdyb3VwLCBub3JtYWwuYXNBcnJheSgpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIG5vcm1hbHNBdHRyOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgY29tcHV0ZUhhcmRFZGdlc0luZGljZXMgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSBoYXJkQW5nbGUgLSBUaGUgaGFyZEFuZ2xlIHZhbHVlIGluIHJhZGlhbnMuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgY29tcHV0ZUhhcmRFZGdlc0luZGljZXMoaGFyZEFuZ2xlID0gMS4wKSB7CiAgICAgICAgICAgIGlmICh0aGlzLmVkZ2VWZXJ0cy5sZW5ndGggPT0gMCkKICAgICAgICAgICAgICAgIHRoaXMuY2FsY3VsYXRlRWRnZUFuZ2xlcygpOwogICAgICAgICAgICBjb25zdCBoYXJkRWRnZXMgPSBbXTsKICAgICAgICAgICAgY29uc3QgYWRkRWRnZSA9IChpbmRleCkgPT4gewogICAgICAgICAgICAgICAgaGFyZEVkZ2VzLnB1c2godGhpcy5lZGdlVmVydHNbaW5kZXhdKTsKICAgICAgICAgICAgICAgIGhhcmRFZGdlcy5wdXNoKHRoaXMuZWRnZVZlcnRzW2luZGV4ICsgMV0pOwogICAgICAgICAgICB9OwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZWRnZUFuZ2xlcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgaWYgKHRoaXMuZWRnZUFuZ2xlc1tpXSA+IGhhcmRBbmdsZSkgewogICAgICAgICAgICAgICAgICAgIGFkZEVkZ2UoaSAqIDIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBVaW50MzJBcnJheS5mcm9tKGhhcmRFZGdlcyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIE1lcmdlcyBhIHNlcGFyYXRlIGdlb21ldHJ5IGludG8gdGhpcyBvbmUuIFNpbWlsYXIgdG8gYSAndW5pb24nIGJvb2xlYW4gb3BlcmF0aW9uLgogICAgICAgICAqIEBwYXJhbSBvdGhlciB0aGUgb3RoZXIgZ2VvbSB0aGF0IHdpbGwgYmUgbWVyZ2VkIGludG8gdGhpcyBvbmUKICAgICAgICAgKiBAcGFyYW0geGZvIHRoZSB0cmFuc2Zvcm1hdGlvbiB0byBiZSBhcHBsaWVkIHRvIHRoZSBvdGhlciBnZW9tIGFzIGl0IGlzIG1lcmdlZCBpbi4KICAgICAgICAgKi8KICAgICAgICBtZXJnZShvdGhlciwgeGZvID0gbmV3IFhmbygpKSB7CiAgICAgICAgICAgIGNvbnN0IHByZXZOdW1WZXJ0cyA9IHRoaXMuZ2V0TnVtVmVydGljZXMoKTsKICAgICAgICAgICAgc3VwZXIubWVyZ2Uob3RoZXIsIHhmbyk7CiAgICAgICAgICAgIGNvbnN0IG90aGVyRmFjZVZlcnRleEluZGljZXMgPSBvdGhlci5mYWNlVmVydGV4SW5kaWNlczsKICAgICAgICAgICAgY29uc3QgZmFjZVZlcnRleEluZGljZXMgPSBuZXcgVWludDMyQXJyYXkodGhpcy5mYWNlVmVydGV4SW5kaWNlcy5sZW5ndGggKyBvdGhlckZhY2VWZXJ0ZXhJbmRpY2VzLmxlbmd0aCk7CiAgICAgICAgICAgIGNvbnN0IG90aGVyRmFjZUNvdW50cyA9IG90aGVyLmdldEZhY2VDb3VudHMoKTsKICAgICAgICAgICAgbGV0IGluZGV4T2Zmc2V0ID0gMDsKICAgICAgICAgICAgbGV0IG90aGVySW5kZXhPZmZzZXQgPSAwOwogICAgICAgICAgICBsZXQgbWVyZ2VkSW5kZXhPZmZzZXQgPSAwOwogICAgICAgICAgICBjb25zdCBudW1Db3VudHMgPSBNYXRoLm1heCh0aGlzLmZhY2VDb3VudHMubGVuZ3RoLCBvdGhlckZhY2VDb3VudHMubGVuZ3RoKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Db3VudHM7IGkrKykgewogICAgICAgICAgICAgICAgaWYgKHRoaXMuZmFjZUNvdW50cy5sZW5ndGggPiBpKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gQWRkICd0aGlzJyBpbmRpY2VzCiAgICAgICAgICAgICAgICAgICAgY29uc3QgbnVtSW5kaWNlc1RoaXMgPSB0aGlzLmZhY2VDb3VudHNbaV0gKiAoaSArIDMpOwogICAgICAgICAgICAgICAgICAgIGZhY2VWZXJ0ZXhJbmRpY2VzLnNldCh0aGlzLmZhY2VWZXJ0ZXhJbmRpY2VzLnNsaWNlKGluZGV4T2Zmc2V0LCBpbmRleE9mZnNldCArIG51bUluZGljZXNUaGlzKSwgbWVyZ2VkSW5kZXhPZmZzZXQpOwogICAgICAgICAgICAgICAgICAgIGluZGV4T2Zmc2V0ICs9IG51bUluZGljZXNUaGlzOwogICAgICAgICAgICAgICAgICAgIG1lcmdlZEluZGV4T2Zmc2V0ICs9IG51bUluZGljZXNUaGlzOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKG90aGVyRmFjZUNvdW50cy5sZW5ndGggPiBpKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gQWRkIHRoZSAnb3RoZXInIGluZGljZXMKICAgICAgICAgICAgICAgICAgICBjb25zdCBudW1JbmRpY2VzT3RoZXIgPSBvdGhlckZhY2VDb3VudHNbaV0gKiAoaSArIDMpOwogICAgICAgICAgICAgICAgICAgIGZhY2VWZXJ0ZXhJbmRpY2VzLnNldChvdGhlckZhY2VWZXJ0ZXhJbmRpY2VzCiAgICAgICAgICAgICAgICAgICAgICAgIC5zbGljZShvdGhlckluZGV4T2Zmc2V0LCBvdGhlckluZGV4T2Zmc2V0ICsgbnVtSW5kaWNlc090aGVyKQogICAgICAgICAgICAgICAgICAgICAgICAubWFwKChpbmRleCkgPT4gaW5kZXggKyBwcmV2TnVtVmVydHMpLCBtZXJnZWRJbmRleE9mZnNldCk7CiAgICAgICAgICAgICAgICAgICAgb3RoZXJJbmRleE9mZnNldCArPSBudW1JbmRpY2VzT3RoZXI7CiAgICAgICAgICAgICAgICAgICAgbWVyZ2VkSW5kZXhPZmZzZXQgKz0gbnVtSW5kaWNlc090aGVyOwogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmZhY2VDb3VudHMubGVuZ3RoID09IGkpCiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmFjZUNvdW50c1tpXSA9IDA7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5mYWNlQ291bnRzW2ldICs9IG90aGVyRmFjZUNvdW50c1tpXTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLmZhY2VWZXJ0ZXhJbmRpY2VzID0gZmFjZVZlcnRleEluZGljZXM7CiAgICAgICAgICAgIC8vIE5vdGU6IHRoZSBtZXJnZSBkb2VzIG5vdCBjb3JyZWN0bHkgbWVyZ2Ugc3BsaXQgdmFsdWVzLCBhcyBpdCBpcyBxdWl0ZSBjb21wbGV4CiAgICAgICAgICAgIC8vIGFuZCB3ZSBkb24ndCBoYXZlIHRpbWUgbm93LiBXZSBjYW4gY29tZSBiYWNrIHRvIHRoaXMsIGJ1dCB0aGUgc3BsaXRzIHN5c3RlbSBpcyBvdmVybHkgY29tcGxleAogICAgICAgICAgICAvLyBhbmQgd2UgY2FuIHByb2JhYmx5IHJlLXdyaXRlLgogICAgICAgICAgICAvLyBmb3IgKGNvbnN0IFthdHRyTmFtZSwgYXR0cl0gb2YgdGhpcy5fX3ZlcnRleEF0dHJpYnV0ZXMpIHsKICAgICAgICAgICAgLy8gICBjb25zdCBvdGhlckF0dHIgPSBvdGhlci5nZXRWZXJ0ZXhBdHRyaWJ1dGUoYXR0ck5hbWUpCiAgICAgICAgICAgIC8vICAgaWYgKG90aGVyQXR0cikgewogICAgICAgICAgICAvLyAgICAgY29uc3QgdGhpc1NwbGl0cyA9IGF0dHIuZ2V0U3BsaXRzKCkKICAgICAgICAgICAgLy8gICAgIGNvbnN0IG90aGVyU3BsaXRzID0gb3RoZXJBdHRyLmdldFNwbGl0cygpCiAgICAgICAgICAgIC8vICAgICAvLyBmb3IgKGxldCBrZXkgaW4gb3RoZXJTcGxpdHMpIHsKICAgICAgICAgICAgLy8gICAgIC8vICAgdGhpc1NwbGl0c1trZXldID0gb3RoZXJTcGxpdHNba2V5XQogICAgICAgICAgICAvLyAgICAgLy8gfQogICAgICAgICAgICAvLyAgIH0KICAgICAgICAgICAgLy8gfQogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUmVuZGVyaW5nCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGdlbkJ1ZmZlcnMgbWV0aG9kLgogICAgICAgICAqIEBwYXJhbSBvcHRzIC0gVGhlIG9wdHMgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgZ2VuQnVmZmVycyhvcHRzKSB7CiAgICAgICAgICAgIC8vIENvbXB1dGUgdGhlIG5vcm1hbHMgb24gZGVtYW5kLgogICAgICAgICAgICAvLyBpZiAoISgnbm9ybWFscycgaW4gdGhpcy5fX3ZlcnRleEF0dHJpYnV0ZXMpKSB7CiAgICAgICAgICAgIC8vICAgICAvLyB0aGlzLmdlb20uY29tcHV0ZVZlcnRleE5vcm1hbHMoKTsKICAgICAgICAgICAgLy8gICAgIHRoaXMuYWRkVmVydGV4QXR0cmlidXRlKCJub3JtYWxzIiwgVmVjMywgMC4wKTsKICAgICAgICAgICAgLy8gfQogICAgICAgICAgICBjb25zdCBzcGxpdEluZGljZXMgPSB7fTsKICAgICAgICAgICAgbGV0IHNwbGl0Q291bnQgPSAwOwogICAgICAgICAgICBmb3IgKGNvbnN0IFssIGF0dHJdIG9mIHRoaXMuX192ZXJ0ZXhBdHRyaWJ1dGVzKSB7CiAgICAgICAgICAgICAgICBjb25zdCBhdHRyU3BsaXRzID0gYXR0ci5nZXRTcGxpdHMoKTsKICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcG9seWdvbiBpbiBhdHRyU3BsaXRzKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCEocG9seWdvbiBpbiBzcGxpdEluZGljZXMpKQogICAgICAgICAgICAgICAgICAgICAgICBzcGxpdEluZGljZXNbcG9seWdvbl0gPSB7fTsKICAgICAgICAgICAgICAgICAgICBjb25zdCB2ZXJ0aWNlcyA9IGF0dHJTcGxpdHNbcG9seWdvbl07CiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCB2IGluIHZlcnRpY2VzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHZlcnRleCA9IHBhcnNlSW50KHYpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoISh2ZXJ0ZXggaW4gc3BsaXRJbmRpY2VzW3BvbHlnb25dKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BsaXRJbmRpY2VzW3BvbHlnb25dW3ZlcnRleF0gPSBzcGxpdENvdW50OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BsaXRDb3VudCsrOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IHRoaXMucG9zaXRpb25zOwogICAgICAgICAgICBjb25zdCBudW1VblNwbGl0VmVydGljZXMgPSBwb3NpdGlvbnMuZ2V0Q291bnQoKTsKICAgICAgICAgICAgY29uc3QgdG90YWxOdW1WZXJ0aWNlcyA9IG51bVVuU3BsaXRWZXJ0aWNlcyArIHNwbGl0Q291bnQ7CiAgICAgICAgICAgIGxldCBpbmRpY2VzOwogICAgICAgICAgICBpZiAoIW9wdHMgfHwgb3B0cy5pbmNsdWRlSW5kaWNlcyAhPSBmYWxzZSkgewogICAgICAgICAgICAgICAgaW5kaWNlcyA9IHRoaXMuZ2VuZXJhdGVUcmlhbmd1bGF0ZWRJbmRpY2VzKHRvdGFsTnVtVmVydGljZXMsIG51bVVuU3BsaXRWZXJ0aWNlcywgc3BsaXRJbmRpY2VzKTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBsZXQgbWF4SW5kZXg7CiAgICAgICAgICAgIC8vIGlmIChkZWJ1Z0F0dHJWYWx1ZXMpCiAgICAgICAgICAgIC8vICAgICBtYXhJbmRleCA9IE1hdGgubWF4KC4uLmluZGljZXMpOwogICAgICAgICAgICBjb25zdCBhdHRyQnVmZmVycyA9IHt9OwogICAgICAgICAgICBmb3IgKGNvbnN0IFthdHRyTmFtZSwgYXR0cl0gb2YgdGhpcy5fX3ZlcnRleEF0dHJpYnV0ZXMpIHsKICAgICAgICAgICAgICAgIGxldCB2YWx1ZXM7CiAgICAgICAgICAgICAgICBpZiAoc3BsaXRDb3VudCA9PSAwKQogICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGF0dHIuYXNBcnJheSgpOwogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGF0dHIuZ2VuZXJhdGVTcGxpdFZhbHVlcyhzcGxpdEluZGljZXMsIHNwbGl0Q291bnQpOwogICAgICAgICAgICAgICAgY29uc3QgZGltZW5zaW9uID0gYXR0ci5zdHJpZGU7CiAgICAgICAgICAgICAgICBjb25zdCBjb3VudCA9IHZhbHVlcy5sZW5ndGggLyBkaW1lbnNpb247CiAgICAgICAgICAgICAgICAvLyBpZiAoZGVidWdBdHRyVmFsdWVzKSB7CiAgICAgICAgICAgICAgICAvLyAgICAgaWYgKGNvdW50IDw9IG1heEluZGV4KQogICAgICAgICAgICAgICAgLy8gICAgICAgICBjb25zb2xlLndhcm4oIkludmFsaWQgaW5kZXhpbmcuIEF0dHIgdmFsdWUgaXMgaW5zdWZmaWNpZW50IGZvciBpbmRleGluZzoiICsgYXR0ck5hbWUgKyAiLiBNYXggSW5kZXg6IiArIG1heEluZGV4ICsgIiBBdHRyIFNpemU6IiArIGNvdW50KTsKICAgICAgICAgICAgICAgIC8vIH0KICAgICAgICAgICAgICAgIGF0dHJCdWZmZXJzW2F0dHJOYW1lXSA9IHsKICAgICAgICAgICAgICAgICAgICB2YWx1ZXM6IHZhbHVlcywKICAgICAgICAgICAgICAgICAgICBjb3VudDogY291bnQsCiAgICAgICAgICAgICAgICAgICAgZGltZW5zaW9uOiBkaW1lbnNpb24sCiAgICAgICAgICAgICAgICAgICAgbm9ybWFsaXplZDogYXR0ck5hbWUgPT0gJ25vcm1hbHMnLAogICAgICAgICAgICAgICAgICAgIGRhdGFUeXBlOiBhdHRyLmdldERhdGFUeXBlTmFtZSgpLAogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCByZXN1bHQgPSB7CiAgICAgICAgICAgICAgICBudW1WZXJ0aWNlczogdGhpcy5udW1WZXJ0aWNlcygpLAogICAgICAgICAgICAgICAgbnVtUmVuZGVyVmVydHM6IHRvdGFsTnVtVmVydGljZXMsCiAgICAgICAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgICAgICAgYXR0ckJ1ZmZlcnMsCiAgICAgICAgICAgIH07CiAgICAgICAgICAgIC8qIERpc2FibGVkIGR1cmluZyBUUyBtaWdyYXRpb24uCiAgICAgICAgICAgIGlmIChvcHRzICYmIG9wdHMuaW5jbHVkZVZlcnRleE5laWdoYm9ycykgewogICAgICAgICAgICAgIGlmICh0aGlzLnZlcnRleEVkZ2VzID09IHVuZGVmaW5lZCkgdGhpcy5nZW5Ub3BvbG9neUluZm8oKQogICAgICAgIAogICAgICAgICAgICAgIGxldCBjb3VudCA9IDAKICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMudmVydGV4RWRnZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgZmFjZSBpbmRleGluZyBkb2Vzbid0IHN0YXJ0IGF0IDAsIHRoZW4gdGhlIHZlcnRleEVkZ2VzIGRvbid0IGVpdGhlci4KICAgICAgICAgICAgICAgIGlmICh0aGlzLnZlcnRleEVkZ2VzW2ldKSBjb3VudCArPSB0aGlzLnZlcnRleEVkZ2VzW2ldLnNpemUKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgLy8gVGhlIGFycmF5IHdpbGwgYmUgc3RydWN0dXJlZCBhcyBhIHN0YXJ0K29mZnNldCBmb3IgZWFjaCB2ZXJ0ZXgsIGZvbGxvd2VkCiAgICAgICAgICAgICAgLy8gYnkgYSAyZCBhcnJheSBvZiBuZWlnaGJvciBpbmRpY2VzLgogICAgICAgICAgICAgIGNvbnN0IHZlcnRleE5laWdoYm9ycyA9IG5ldyBVaW50MzJBcnJheSh0aGlzLnZlcnRleEVkZ2VzLmxlbmd0aCAqIDIgKyBjb3VudCkKICAgICAgICAgICAgICBjb25zdCBzb3J0RmFuRWRnZXMgPSAoZmFuRWRnZXM6IGFueSkgPT4gewogICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmYW5FZGdlcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgICBjb25zdCBmZUEgPSBmYW5FZGdlc1tpXQogICAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGk7IGorKykgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IGZlQiA9IGZhbkVkZ2VzW2pdCiAgICAgICAgICAgICAgICAgICAgaWYgKGZlQVswXSAhPSAtMSAmJiBmZUFbMF0gPT0gZmVCWzFdKSB7CiAgICAgICAgICAgICAgICAgICAgICAvLyAgbW92ZSBmZUEgYWZ0ZXIgZmVCOwogICAgICAgICAgICAgICAgICAgICAgaWYgKGkgIT0gaiArIDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZmFuRWRnZXMuc3BsaWNlKGksIDEpCiAgICAgICAgICAgICAgICAgICAgICAgIGZhbkVkZ2VzLnNwbGljZShqICsgMSwgMCwgZmVBKQogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGZlQVsxXSAhPSAtMSAmJiBmZUFbMV0gPT0gZmVCWzBdKSB7CiAgICAgICAgICAgICAgICAgICAgICAvLyAgbW92ZSBmZUEgYmVmb3JlIGZlQjsKICAgICAgICAgICAgICAgICAgICAgIGZhbkVkZ2VzLnNwbGljZShpLCAxKQogICAgICAgICAgICAgICAgICAgICAgZmFuRWRnZXMuc3BsaWNlKGosIDAsIGZlQSkKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNvbnN0IGNoZWNrRmFuRWRnZXMgPSAoZmFuRWRnZXM6IGFueSkgPT4gewogICAgICAgICAgICAgICAgLy8gbm93IGNoZWNrIHRoYXQgdGhlIGZhY2VzIGFsbCBidWlsZCBhIGZhbi4gTWF5YmUgc3RhcnRpbmcgYW5kIGVuZGluZyB3aXRoIC0xCiAgICAgICAgICAgICAgICBpZiAoZmFuRWRnZXNbMF1bMF0gPT0gLTEgfHwgZmFuRWRnZXNbZmFuRWRnZXMubGVuZ3RoIC0gMV1bMV0gPT0gLTEpIHsKICAgICAgICAgICAgICAgICAgaWYgKGZhbkVkZ2VzWzBdWzBdICE9IC0xIHx8IGZhbkVkZ2VzW2ZhbkVkZ2VzLmxlbmd0aCAtIDFdWzFdICE9IC0xKSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJZiBmYW4gc3RhcnRzIHdpdGggLTEsIGl0IG11c3QgYWxzbyBlbmQgd2l0aCAtMScpCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmFuRWRnZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgICAgY29uc3QgZmUgPSBmYW5FZGdlc1tpXQogICAgICAgICAgICAgICAgICBpZiAoZmVbMF0gPT0gLTEgfHwgZmVbMV0gPT0gLTEpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoaSAhPSAwICYmIGkgIT0gZmFuRWRnZXMubGVuZ3RoIC0gMSkgewogICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCctMSBvbmx5IGFsbG93ZWQgYXQgdGhlIGJlZ2lubmluZyBhbmQgZW5kIG9mIGEgZmFuLicpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChmZVswXSAhPSAtMSkgewogICAgICAgICAgICAgICAgICAgIGxldCBwcmV2ID0gaSAtIDEKICAgICAgICAgICAgICAgICAgICBpZiAocHJldiA8IDApIHByZXYgKz0gZmFuRWRnZXMubGVuZ3RoCiAgICAgICAgICAgICAgICAgICAgaWYgKGZlWzBdICE9IGZhbkVkZ2VzW3ByZXZdWzFdKSB7CiAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhY2VzIGFyZSBub3Qgc2VxdWVudGlhbCcpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChmZVsxXSAhPSAtMSkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IG5leHQgPSAoaSArIDEpICUgZmFuRWRnZXMubGVuZ3RoCiAgICAgICAgICAgICAgICAgICAgaWYgKGZlWzFdICE9IGZhbkVkZ2VzW25leHRdWzBdKSB7CiAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhY2VzIGFyZSBub3Qgc2VxdWVudGlhbCcpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgIAogICAgICAgICAgICAgIC8vIFBvcHVsYXRlIHRoZSBzdGFydCBhbmQgb2Zmc2V0IHZhbHVlcy4KICAgICAgICAgICAgICBsZXQgb2Zmc2V0ID0gdGhpcy52ZXJ0ZXhFZGdlcy5sZW5ndGggKiAyCiAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnZlcnRleEVkZ2VzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBpZiAodGhpcy52ZXJ0ZXhFZGdlc1tpXSA9PSB1bmRlZmluZWQpIGNvbnRpbnVlCiAgICAgICAgICAgICAgICBjb25zdCBlZGdlcyA9IHRoaXMudmVydGV4RWRnZXNbaV0KICAgICAgICAKICAgICAgICAgICAgICAgIC8vIEJ1aWxkIGEgc29ydGVkIGxpc3Qgb2YgZmFjZXMgYmFzZWQgb24gYSBmYW4gYXJvdW5kCiAgICAgICAgICAgICAgICAvLyB0aGUgdmVydGV4LgogICAgICAgICAgICAgICAgY29uc3QgZmFuRWRnZXMgPSBbXQogICAgICAgICAgICAgICAgZm9yIChjb25zdCBlIG9mIGVkZ2VzKSB7CiAgICAgICAgICAgICAgICAgIGNvbnN0IHYwID0gdGhpcy5lZGdlVmVydHNbZSAqIDJdCiAgICAgICAgICAgICAgICAgIGNvbnN0IHYxID0gdGhpcy5lZGdlVmVydHNbZSAqIDIgKyAxXQogICAgICAgICAgICAgICAgICBsZXQgZjAgPSB0aGlzLmVkZ2VGYWNlc1tlICogMl0KICAgICAgICAgICAgICAgICAgbGV0IGYxID0gdGhpcy5lZGdlRmFjZXNbZSAqIDIgKyAxXQogICAgICAgICAgICAgICAgICBsZXQgbmVpZ1ZlcnQKICAgICAgICAgICAgICAgICAgaWYgKHYwID09IGkpIHsKICAgICAgICAgICAgICAgICAgICBuZWlnVmVydCA9IHYxCiAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodjEgPT0gaSkgewogICAgICAgICAgICAgICAgICAgIG5laWdWZXJ0ID0gdjAKICAgICAgICAgICAgICAgICAgICAvLyBzd2FwIHRoZSBmYWNlcwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHRtcCA9IGYwCiAgICAgICAgICAgICAgICAgICAgZjAgPSBmMQogICAgICAgICAgICAgICAgICAgIGYxID0gdG1wCiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHRvcG9sb2d5JykKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBmYW5FZGdlcy5wdXNoKFtmMCwgZjEsIG5laWdWZXJ0XSkKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHNvcnRGYW5FZGdlcyhmYW5FZGdlcykKICAgICAgICAgICAgICAgIGNoZWNrRmFuRWRnZXMoZmFuRWRnZXMpCiAgICAgICAgICAgICAgICBjb25zdCBjbG9zZWQgPSBmYW5FZGdlc1swXVswXSAhPSAtMSB8fCBmYW5FZGdlc1tmYW5FZGdlcy5sZW5ndGggLSAxXVsxXSAhPSAtMQogICAgICAgICAgICAgICAgbGV0IGZsYWdzID0gMAogICAgICAgICAgICAgICAgaWYgKGNsb3NlZCkgZmxhZ3MgKz0gMQogICAgICAgICAgICAgICAgdmVydGV4TmVpZ2hib3JzW2kgKiAyXSA9IG9mZnNldAogICAgICAgICAgICAgICAgdmVydGV4TmVpZ2hib3JzW2kgKiAyICsgMV0gPSBlZGdlcy5zaXplICsgKGZsYWdzIDw8IDgpCiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZlIG9mIGZhbkVkZ2VzKSB7CiAgICAgICAgICAgICAgICAgIHZlcnRleE5laWdoYm9yc1tvZmZzZXRdID0gZmVbMl0KICAgICAgICAgICAgICAgICAgb2Zmc2V0KysKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgOyhyZXN1bHQgYXMgYW55KS52ZXJ0ZXhOZWlnaGJvcnMgPSB2ZXJ0ZXhOZWlnaGJvcnMKICAgICAgICAgICAgfQogICAgICAgICAgICAqLwogICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDb21wdXRlIHRoZSBudW1iZXIgb2YgdHJpYW5nbGVzLiBGb3IgaGlnaGVyIGRlZ3JlZSBwb2x5Z29ucywgdGhleSBhcmUgZGl2aWRlZCBpbnRvIG11bHRpcGxlIHRyaWFuZ2xlcyBmb3IgcmVuZGVyaW5nLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIHRoZSBudW1iZXIgb2YgdHJpYW5nbGVzLgogICAgICAgICAqLwogICAgICAgIGNvbXB1dGVOdW1UcmlhbmdsZXMoKSB7CiAgICAgICAgICAgIGxldCBudW1WZXJ0c1BlckZhY2UgPSAzOwogICAgICAgICAgICBsZXQgdHJpc0NvdW50ID0gMDsKICAgICAgICAgICAgZm9yIChjb25zdCBmYyBvZiB0aGlzLmZhY2VDb3VudHMpIHsKICAgICAgICAgICAgICAgIHRyaXNDb3VudCArPSBmYyAqIChudW1WZXJ0c1BlckZhY2UgLSAyKTsKICAgICAgICAgICAgICAgIG51bVZlcnRzUGVyRmFjZSsrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0cmlzQ291bnQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFRvIHByZXBhcmUgZGF0YSBmb3IgcmVuZGVyaW5nLCB0aGUgaW5kaWNlcyBmb3IgdGhlIHBvbHlnb25zIGlzIHVzZWQgdG8gY29tcHV0ZSBhIG5ldyBpbmRleCBidWZmZXIgYmFzZWQgb24KICAgICAgICAgKiBvbmx5IHRyaWFuZ2xlcy4gVGhpcyBpcyB1c2VkIGR1cmluZyByZW5kZXJpbmcgYW5kIHRoZSByZXN1bHRpbmcgaW5kaWNlcyB1cGxvYWRlZCBvdCB0aGUgR1BVICBieSBHTE1lc2ggY2xhc3MuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gdG90YWxOdW1WZXJ0aWNlcyAtIFRoZSB0b3RhbCBudW1iZXIgb2YgdmVydGljZXMuCiAgICAgICAgICogQHBhcmFtIG51bVVuU3BsaXRWZXJ0aWNlcyAtIFRoZSB0b3RhbCBudW1iZXIgb2YgdW4tc3BsaXQgdmVydGljZXMuCiAgICAgICAgICogQHBhcmFtIHNwbGl0SW5kaWNlcyAtIFRoZSBzcGxpdEluZGljZXMgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSB0eXBlZCBhcnJheSBjb250YWluaW5nIHRoZSB0cmlhbmd1bGF0ZWQgaW5kaWNlcy4KICAgICAgICAgKi8KICAgICAgICBnZW5lcmF0ZVRyaWFuZ3VsYXRlZEluZGljZXModG90YWxOdW1WZXJ0aWNlcywgbnVtVW5TcGxpdFZlcnRpY2VzLCBzcGxpdEluZGljZXMpIHsKICAgICAgICAgICAgY29uc3QgdHJpc0NvdW50ID0gdGhpcy5jb21wdXRlTnVtVHJpYW5nbGVzKCk7CiAgICAgICAgICAgIGxldCB0cmlhbmd1bGF0ZWRJbmRpY2VzOwogICAgICAgICAgICBpZiAodG90YWxOdW1WZXJ0aWNlcyA8IE1hdGgucG93KDIsIDgpKQogICAgICAgICAgICAgICAgdHJpYW5ndWxhdGVkSW5kaWNlcyA9IG5ldyBVaW50OEFycmF5KHRyaXNDb3VudCAqIDMpOwogICAgICAgICAgICBlbHNlIGlmICh0b3RhbE51bVZlcnRpY2VzIDwgTWF0aC5wb3coMiwgMTYpKQogICAgICAgICAgICAgICAgdHJpYW5ndWxhdGVkSW5kaWNlcyA9IG5ldyBVaW50MTZBcnJheSh0cmlzQ291bnQgKiAzKTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgdHJpYW5ndWxhdGVkSW5kaWNlcyA9IG5ldyBVaW50MzJBcnJheSh0cmlzQ291bnQgKiAzKTsKICAgICAgICAgICAgbGV0IHRyaWFuZ2xlVmVydGV4ID0gMDsKICAgICAgICAgICAgY29uc3QgYWRkVHJpYW5nbGVWZXJ0ZXhJbmRleCA9IGZ1bmN0aW9uICh2ZXJ0ZXgsIGZhY2VJbmRleCkgewogICAgICAgICAgICAgICAgaWYgKHZlcnRleCBpbiBzcGxpdEluZGljZXMgJiYgZmFjZUluZGV4IGluIHNwbGl0SW5kaWNlc1t2ZXJ0ZXhdKQogICAgICAgICAgICAgICAgICAgIHZlcnRleCA9IG51bVVuU3BsaXRWZXJ0aWNlcyArIHNwbGl0SW5kaWNlc1t2ZXJ0ZXhdW2ZhY2VJbmRleF07CiAgICAgICAgICAgICAgICB0cmlhbmd1bGF0ZWRJbmRpY2VzW3RyaWFuZ2xlVmVydGV4XSA9IHZlcnRleDsKICAgICAgICAgICAgICAgIHRyaWFuZ2xlVmVydGV4Kys7CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIGNvbnN0IG51bUZhY2VzID0gdGhpcy5nZXROdW1GYWNlcygpOwogICAgICAgICAgICBmb3IgKGxldCBmYWNlSW5kZXggPSAwOyBmYWNlSW5kZXggPCBudW1GYWNlczsgZmFjZUluZGV4KyspIHsKICAgICAgICAgICAgICAgIGNvbnN0IGZhY2VWZXJ0cyA9IHRoaXMuZ2V0RmFjZVZlcnRleEluZGljZXMoZmFjZUluZGV4KTsKICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgZmFjZVZlcnRzLmxlbmd0aDsgaisrKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGogPj0gMykgewogICAgICAgICAgICAgICAgICAgICAgICAvLyBGb3IgZWFjaCBhZGRpdGlvbmFsIHRyaWFuZ2xlLCB3ZSBoYXZlIHRvIGFkZCAyIGluZGljZXMuCiAgICAgICAgICAgICAgICAgICAgICAgIGFkZFRyaWFuZ2xlVmVydGV4SW5kZXgoZmFjZVZlcnRzWzBdLCBmYWNlSW5kZXgpOwogICAgICAgICAgICAgICAgICAgICAgICBhZGRUcmlhbmdsZVZlcnRleEluZGV4KGZhY2VWZXJ0c1tqIC0gMV0sIGZhY2VJbmRleCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFkZFRyaWFuZ2xlVmVydGV4SW5kZXgoZmFjZVZlcnRzW2pdLCBmYWNlSW5kZXgpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0cmlhbmd1bGF0ZWRJbmRpY2VzOwogICAgICAgIH0KICAgICAgICAvLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgLy8gUGVyc2lzdGVuY2UKICAgICAgICAvKioKICAgICAgICAgKiBSZXN0b3JlcyBtZXNoIHByb3BlcnRpZXMgZnJvbSBhIGJpbmFyeSByZWFkZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gcmVhZGVyIC0gVGhlIHJlYWRlciB2YWx1ZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHN1cGVyLmxvYWRCYXNlR2VvbUJpbmFyeShyZWFkZXIsIGNvbnRleHQpOwogICAgICAgICAgICB0aGlzLnNldEZhY2VDb3VudHMoQXJyYXkuZnJvbShyZWFkZXIubG9hZFVJbnQzMkFycmF5KCkpKTsKICAgICAgICAgICAgY29uc3QgbnVtRmFjZXMgPSB0aGlzLmdldE51bUZhY2VzKCk7CiAgICAgICAgICAgIC8vIE5vdGU6IHdlIGNhbiByZW1vdmUgdGhpcy4gV2UgY2FuIGluZmVyIHRoaXMgZnJvbSB0aGUgYWJvdmUgZmFjZUNvdW50cyBhcnJheS4KICAgICAgICAgICAgLy8gRG8gbm90IGNsb25lIHRoZSBkYXRhLCBhcyBpdHMgJ3NjcmF0Y2ggbWVtb3J5JyBpbiBhbnkgY2FzZS4KICAgICAgICAgICAgLy8gV2UgY2FuIGF2b2lkIGEgbG90IG9mIHVubmVjZXNzYXJ5IHRlbXBvcmFyeSBhbGxvY2FpdG9uIGJ5IHVzaW5nIHNoYXJlZCBidWZmZXJzLgogICAgICAgICAgICBjb25zdCBmYWNlVmVydGV4Q291bnRzID0gcmVhZGVyLmxvYWRVSW50OEFycmF5KG51bUZhY2VzLCBmYWxzZSk7CiAgICAgICAgICAgIGNvbnN0IG9mZnNldFJhbmdlID0gcmVhZGVyLmxvYWRTSW50MzJWZWMyKCk7CiAgICAgICAgICAgIGNvbnN0IGJ5dGVzID0gcmVhZGVyLmxvYWRVSW50OCgpOwogICAgICAgICAgICBsZXQgZmFjZVZlcnRleEluZGV4RGVsdGFzOwogICAgICAgICAgICBpZiAoYnl0ZXMgPT0gMSkKICAgICAgICAgICAgICAgIGZhY2VWZXJ0ZXhJbmRleERlbHRhcyA9IHJlYWRlci5sb2FkVUludDhBcnJheSh1bmRlZmluZWQsIGZhbHNlKTsKICAgICAgICAgICAgZWxzZSBpZiAoYnl0ZXMgPT0gMikKICAgICAgICAgICAgICAgIGZhY2VWZXJ0ZXhJbmRleERlbHRhcyA9IHJlYWRlci5sb2FkVUludDE2QXJyYXkodW5kZWZpbmVkLCBmYWxzZSk7CiAgICAgICAgICAgIGVsc2UgaWYgKGJ5dGVzID09IDQpCiAgICAgICAgICAgICAgICBmYWNlVmVydGV4SW5kZXhEZWx0YXMgPSByZWFkZXIubG9hZFVJbnQzMkFycmF5KHVuZGVmaW5lZCwgZmFsc2UpOwogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHRocm93IEVycm9yKCdmYWNlVmVydGV4SW5kZXhEZWx0YXMgdW5kZWZpbmVkJyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgICAgIC8vIE5vdGU6IFRoZSBNZXNoIGNvbXByZXNzaW9uIHN5c3RlbSBuZWVkcyBhIHRob3JvdWdoIHJldmlldy4KICAgICAgICAgICAgLy8gVGhlIEMrKyBjbGFzc2VzIGFyZSBub3Qgc3RvcmluZyBmYWNlIGluZGljZXMgaW4gYSBzb3J0ZWQgbWFubmVyLgogICAgICAgICAgICAvLyBTbyBxdWFkcyBwcmVjZWRlIHRyaWFuZ2xlcyBpbiB0aGUgaW5kZXhpbmcsIHdoaWNoIGlzbid0IHN1cHBvc2VkIHRvIGhhcHBlbi4KICAgICAgICAgICAgLy8gV2Ugc2hvdWxkIGZvcmNlIHRoZSBDKysgY29kZSB0byBzdG9yZSBxdWFkcyBhbmQgdHJpYW5nbGVzIGluIG9yZGVyLgogICAgICAgICAgICAvLyBlLmcuIGltcGxlbWVudCB0aGUgJ2FkZEZhY2UnIG1ldGhvZCBpbiBDKysgc28gaXQgYXV0b21hdGljYWxseSBkb2VzIHRoaXMuCiAgICAgICAgICAgIGxldCBudW1GYWNlVmVydHMgPSAzOwogICAgICAgICAgICBsZXQgb2Zmc2V0ID0gMDsKICAgICAgICAgICAgY29uc3QgZmFjZU9mZnNldHNCeUNvdW50ID0gdGhpcy5mYWNlQ291bnRzLm1hcCgoZmMsIGluZGV4KSA9PiB7CiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBvZmZzZXQ7CiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gZmMgKiBudW1GYWNlVmVydHM7CiAgICAgICAgICAgICAgICBudW1GYWNlVmVydHMrKzsKICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBsZXQgc3JjT2Zmc2V0ID0gMDsKICAgICAgICAgICAgbGV0IHByZXZDb3VudCA9IDA7CiAgICAgICAgICAgIGNvbnN0IGZhY2VPZmZzZXRzID0gW107CiAgICAgICAgICAgIGZvciAobGV0IGZhY2VJbmRleCA9IDA7IGZhY2VJbmRleCA8IG51bUZhY2VzOyBmYWNlSW5kZXgrKykgewogICAgICAgICAgICAgICAgY29uc3QgZmMgPSBmYWNlVmVydGV4Q291bnRzW2ZhY2VJbmRleF07CiAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBmYWNlT2Zmc2V0c0J5Q291bnRbZmNdOwogICAgICAgICAgICAgICAgY29uc3QgY291bnQgPSBmYyArIDM7CiAgICAgICAgICAgICAgICBmYWNlT2Zmc2V0c1tmYWNlSW5kZXhdID0gb2Zmc2V0OwogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBjb3VudDsgaisrKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3JjRmFjZVZlcnRleCA9IHNyY09mZnNldCArIGo7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZmFjZVZlcnRleCA9IG9mZnNldCArIGo7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVsdGEgPSBmYWNlVmVydGV4SW5kZXhEZWx0YXNbc3JjRmFjZVZlcnRleF0gKyBvZmZzZXRSYW5nZS54OwogICAgICAgICAgICAgICAgICAgIGlmIChmYWNlSW5kZXggPT0gMCkKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mYWNlVmVydGV4SW5kaWNlc1tmYWNlVmVydGV4XSA9IGRlbHRhOwogICAgICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcHJldkZhY2VWZXJ0ZXggPSBmYWNlT2Zmc2V0c1tmYWNlSW5kZXggLSAxXTsKICAgICAgICAgICAgICAgICAgICAgICAgcHJldkZhY2VWZXJ0ZXggKz0gaiA8IHByZXZDb3VudCA/IGogOiBwcmV2Q291bnQgLSAxOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZhY2VWZXJ0ZXhJbmRpY2VzW2ZhY2VWZXJ0ZXhdID0gdGhpcy5mYWNlVmVydGV4SW5kaWNlc1twcmV2RmFjZVZlcnRleF0gKyBkZWx0YTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzcmNPZmZzZXQgKz0gY291bnQ7CiAgICAgICAgICAgICAgICBmYWNlT2Zmc2V0c0J5Q291bnRbZmNdICs9IGNvdW50OwogICAgICAgICAgICAgICAgcHJldkNvdW50ID0gY291bnQ7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCF0aGlzLmhhc1ZlcnRleEF0dHJpYnV0ZSgnbm9ybWFscycpKSB7CiAgICAgICAgICAgICAgICB0aGlzLmNvbXB1dGVWZXJ0ZXhOb3JtYWxzKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gdGhpcy5jb21wdXRlVmVydGV4Tm9ybWFscygpOwogICAgICAgICAgICB0aGlzLmVtaXQoJ2dlb21EYXRhQ2hhbmdlZCcpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdG9KU09OIG1ldGhvZCBlbmNvZGVzIHRoaXMgdHlwZSBhcyBhIGpzb24gb2JqZWN0IGZvciBwZXJzaXN0ZW5jZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGNvbnRleHQgdmFsdWUuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdGhlIGpzb24gb2JqZWN0LgogICAgICAgICAqLwogICAgICAgIHRvSlNPTihjb250ZXh0KSB7CiAgICAgICAgICAgIGNvbnN0IGogPSBzdXBlci50b0pTT04oY29udGV4dCk7CiAgICAgICAgICAgIGlmICghY29udGV4dCB8fCAhY29udGV4dC5za2lwVG9wb2xvZ3kpIHsKICAgICAgICAgICAgICAgIGouZmFjZUNvdW50cyA9IEFycmF5LmZyb20odGhpcy5mYWNlQ291bnRzKTsKICAgICAgICAgICAgICAgIGouZmFjZVZlcnRleEluZGljZXMgPSBBcnJheS5mcm9tKHRoaXMuZmFjZVZlcnRleEluZGljZXMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBqOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZnJvbUpTT04gbWV0aG9kIGRlY29kZXMgYSBqc29uIG9iamVjdCBmb3IgdGhpcyB0eXBlLgogICAgICAgICAqCiAgICAgICAgICogZS5nLiB0byBsb2FkIGRhdGEgaW50byB0aGUgbWVzaCBjbGFzcywgcHJvdmlkZSBhIGpzb24gc3RydWN0dXJlIHNpbWlsYXIgdG8gdGhlIGZvbGxvd2luZy4KICAgICAgICAgKiBOb3RlOiBmYWNlQ291bnRzIGlzIGFuIGFycmF5IG9mIGNvdW50IHZhbHVlcywgc3RhcnRpbmcgd2l0aCB0aGUgbnVtYmVyIG9mIHRyaWFuZ2xlcywgdGhlbiB0aGUgbnVtYmVyIG9mIHF1YWRzLiBTZWUgI3NldEZhY2VDb3VudHMKICAgICAgICAgKiBUaGUgZmFjZVZlcnRleEluZGljZXMgYXJyYXkgc2hvdWxkIGFsc28gYmUgc29ydGVkIHRvIGNvbnRhaW4gYWxsIHRoZSB0cmlhbmdsZXMgZmlyc3QsIGZvbGxvd2VkIGJ5IHRoZSBxdWFkcywgYW5kIHRoZW4gdGhlIHBlbnRhZ29ucyBldGMuLgogICAgICAgICAqIGBgYGpzb24KICAgICAgICAgKiAvLyBUaGlzIGNvZGUgd2lsbCBkZWZpbmUgYSBtZXNoIG1hZGUgdXAgb2YgMiB0cmlhbmdsZXMgYW5kIHRoZW4gYSBxdWFkLgogICAgICAgICAqIGNvbnN0IG1lc2ggPSBuZXcgTWVzaCgpCiAgICAgICAgICogbWVzaC5mcm9tSlNPTih7CiAgICAgICAgICogICBmYWNlQ291bnRzOlsyLCAxXSwKICAgICAgICAgKiAgIGZhY2VWZXJ0ZXhJbmRpY2VzOiBbMCwgMSwgMiwgMCwgMiwgMywgMywgMiwgNCwgNV0sCiAgICAgICAgICogICBudW1WZXJ0aWNlczogNiwKICAgICAgICAgKiAgIHZlcnRleEF0dHJpYnV0ZXM6IHsKICAgICAgICAgKiAgICAgcG9zaXRpb25zOiB7CiAgICAgICAgICogICAgICAgZGF0YVR5cGU6ICdWZWMzJwogICAgICAgICAqICAgICAgIGRlZmF1bHRTY2FsYXJWYWx1ZTogMC4wLAogICAgICAgICAqICAgICAgIGRhdGE6IFswLDAsMCwgMCwgMSwgMCwgMSwgMSwgMCwgMSwgMCwgMCwgMiwgMSwgMCwgMiwgMCwgMF0KICAgICAgICAgKiAgICAgfQogICAgICAgICAqICAgfQogICAgICAgICAqIH0KICAgICAgICAgKiBgYGAKICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBqIC0gVGhlIGpzb24gb2JqZWN0IHRoaXMgaXRlbSBtdXN0IGRlY29kZS4KICAgICAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGZyb21KU09OKGosIGNvbnRleHQpIHsKICAgICAgICAgICAgc3VwZXIuZnJvbUpTT04oaiwgY29udGV4dCk7CiAgICAgICAgICAgIGlmIChqLmZhY2VDb3VudHMpCiAgICAgICAgICAgICAgICB0aGlzLmZhY2VDb3VudHMgPSBqLmZhY2VDb3VudHM7CiAgICAgICAgICAgIGlmIChqLmZhY2VWZXJ0ZXhJbmRpY2VzKQogICAgICAgICAgICAgICAgdGhpcy5mYWNlVmVydGV4SW5kaWNlcyA9IFVpbnQzMkFycmF5LmZyb20oai5mYWNlVmVydGV4SW5kaWNlcyk7CiAgICAgICAgfQogICAgfQogICAgUmVnaXN0cnkucmVnaXN0ZXIoJ01lc2gnLCBNZXNoKTsKCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby11bnVzZWQtdmFycyAqLwogICAgLyoqCiAgICAgKiBSZWFkcyBiaW5hcnkgZGF0YSBpbiBhIHNwZWNpZmljIGVuY29kaW5nLiBVc2VkIGluIGxvYWRpbmcgYmluYXJ5IGRhdGEgc3VjaCBhcyB6Y2FkIGZpbGVzLgogICAgICovCiAgICBjbGFzcyBCaW5SZWFkZXIgewogICAgICAgIF9fZGF0YTsKICAgICAgICBfX2J5dGVPZmZzZXQ7CiAgICAgICAgX19kYXRhVmlldzsKICAgICAgICBfX2lzTW9iaWxlRGV2aWNlOwogICAgICAgIHV0ZjhkZWNvZGVyOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZSBhIGJpbiByZWFkZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gZGF0YSAtIFRoZSBkYXRhIGJ1ZmZlci4KICAgICAgICAgKiBAcGFyYW0gYnl0ZU9mZnNldCAtIFRoZSBieXRlIG9mZnNldCB2YWx1ZSB0byBzdGFydCByZWFkaW5nIHRoZSBidWZmZXIuCiAgICAgICAgICogQHBhcmFtIGlzTW9iaWxlRGV2aWNlIC0gVGhlIGlzTW9iaWxlRGV2aWNlIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKGRhdGEsIGJ5dGVPZmZzZXQgPSAwLCBpc01vYmlsZURldmljZSA9IHRydWUpIHsKICAgICAgICAgICAgdGhpcy5fX2RhdGEgPSBkYXRhOwogICAgICAgICAgICB0aGlzLl9fYnl0ZU9mZnNldCA9IGJ5dGVPZmZzZXQ7CiAgICAgICAgICAgIHRoaXMuX19kYXRhVmlldyA9IG5ldyBEYXRhVmlldyh0aGlzLl9fZGF0YSk7CiAgICAgICAgICAgIHRoaXMuX19pc01vYmlsZURldmljZSA9IGlzTW9iaWxlRGV2aWNlOwogICAgICAgICAgICB0aGlzLnV0ZjhkZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgc3RhdGUgb2Ygd2hldGhlciBvciBub3QgdGhlIGBCaW5SZWFkZXJgIG9iamVjdCB3YXMgaW5zdGFudGlhdGVkIGZyb20gYSBtb2JpbGUgZGV2aWNlLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgdHJ1ZSBpcyBhIG1vYmlsZSBkZXZpY2UgaXMgZGV0ZWN0ZWQuCiAgICAgICAgICovCiAgICAgICAgZ2V0IGlzTW9iaWxlRGV2aWNlKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fX2lzTW9iaWxlRGV2aWNlOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBkYXRhIGJ1ZmZlciB3ZSdyZSByZWFkaW5nIGZyb20uCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIGRhdGEgYnVmZmVyIHdlIGFyZSByZWFkaW5nIGZyb20sCiAgICAgICAgICovCiAgICAgICAgZ2V0IGRhdGEoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9fZGF0YTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgbGVuZ3RoIG9mIHRoZSBidWZmZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHRvdGFsIGxlbmd0aCBvZiB0aGUgYnVmZmVyCiAgICAgICAgICovCiAgICAgICAgZ2V0IGJ5dGVMZW5ndGgoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9fZGF0YVZpZXcuYnl0ZUxlbmd0aDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyByZW1haW5pbmcgbGVuZ3RoIG9mIHRoZSBidWZmZXIgdG8gcmVhZC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmVtYWluaW5nIGxlbmd0aCBvZiB0aGUgYnVmZmVyIHRvIHJlYWQuCiAgICAgICAgICovCiAgICAgICAgZ2V0IHJlbWFpbmluZ0J5dGVMZW5ndGgoKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9fZGF0YVZpZXcuYnl0ZUxlbmd0aCAtIHRoaXMuX19ieXRlT2Zmc2V0OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIGN1cnJlbnQgYnl0ZSBvZmZzZXQgaW4gdGhlIGJ1ZmZlci4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIGN1cnJlbnQgb2Zmc2V0IGluIHRoZSBiaW5hcnkgYnVmZmVyCiAgICAgICAgICovCiAgICAgICAgcG9zKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fX2J5dGVPZmZzZXQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgdGhlIGJ5dGUgb2Zmc2V0IHZhbHVlLgogICAgICAgICAqIEBwYXJhbSBieXRlT2Zmc2V0IC0gVGhlIGJ5dGVPZmZzZXQgcGFyYW0uCiAgICAgICAgICovCiAgICAgICAgc2VlayhieXRlT2Zmc2V0KSB7CiAgICAgICAgICAgIHRoaXMuX19ieXRlT2Zmc2V0ID0gYnl0ZU9mZnNldDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQWRkcyBvZmZzZXQgYnl0ZXMgdG8gY3VycmVudCBvZmZzZXQgdmFsdWUuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gYnl0ZU9mZnNldCAtIFRoZSBieXRlIE9mZnNldCBhbW91bnQuCiAgICAgICAgICovCiAgICAgICAgYWR2YW5jZShieXRlT2Zmc2V0KSB7CiAgICAgICAgICAgIHRoaXMuX19ieXRlT2Zmc2V0ICs9IGJ5dGVPZmZzZXQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIHVuc2lnbmVkIFVpbnQ4IHZhbHVlIGF0IGN1cnJlbnQgYnl0ZSBvZmZzZXQgcG9zaXRpb24sCiAgICAgICAgICogYW5kIGFkZHMgb25lIGJ5dGUgdG8gdGhlIG9mZnNldC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGxvYWRVSW50OCgpIHsKICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fX2RhdGFWaWV3LmdldFVpbnQ4KHRoaXMuX19ieXRlT2Zmc2V0KTsKICAgICAgICAgICAgdGhpcy5fX2J5dGVPZmZzZXQgKz0gMTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgdW5zaWduZWQgVWludDE2IHZhbHVlIGF0IGN1cnJlbnQgYnl0ZSBvZmZzZXQgcG9zaXRpb24sCiAgICAgICAgICogYW5kIGFkZHMgdHdvIGJ5dGVzIHRvIHRoZSBvZmZzZXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBsb2FkVUludDE2KCkgewogICAgICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLl9fZGF0YVZpZXcuZ2V0VWludDE2KHRoaXMuX19ieXRlT2Zmc2V0LCB0cnVlKTsKICAgICAgICAgICAgdGhpcy5fX2J5dGVPZmZzZXQgKz0gMjsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgdW5zaWduZWQgVWludDMyIHZhbHVlIGF0IGN1cnJlbnQgYnl0ZSBvZmZzZXQgcG9zaXRpb24sCiAgICAgICAgICogYW5kIGFkZHMgZm91ciBieXRlcyB0byB0aGUgb2Zmc2V0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgbG9hZFVJbnQzMigpIHsKICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fX2RhdGFWaWV3LmdldFVpbnQzMih0aGlzLl9fYnl0ZU9mZnNldCwgdHJ1ZSk7CiAgICAgICAgICAgIHRoaXMuX19ieXRlT2Zmc2V0ICs9IDQ7CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIHNpZ25lZCBJbnQzMiB2YWx1ZSBhdCBjdXJyZW50IGJ5dGUgb2Zmc2V0IHBvc2l0aW9uLAogICAgICAgICAqIGFuZCBhZGRzIGZvdXIgYnl0ZXMgdG8gdGhlIG9mZnNldC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGxvYWRTSW50MzIoKSB7CiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX19kYXRhVmlldy5nZXRJbnQzMih0aGlzLl9fYnl0ZU9mZnNldCwgdHJ1ZSk7CiAgICAgICAgICAgIHRoaXMuX19ieXRlT2Zmc2V0ICs9IDQ7CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgdGhlIEZsb2F0MTYgdmFsdWUgYXQgY3VycmVudCBieXRlIG9mZnNldCBwb3NpdGlvbiwKICAgICAgICAgKiBhbmQgYWRkcyBmb3VyIGJ5dGVzIHRvIHRoZSBvZmZzZXQuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBsb2FkRmxvYXQxNigpIHsKICAgICAgICAgICAgY29uc3QgdWludDE2ID0gdGhpcy5sb2FkVUludDE2KCk7CiAgICAgICAgICAgIHJldHVybiBNYXRoRnVuY3Rpb25zLmRlY29kZTE2Qml0RmxvYXQodWludDE2KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgRmxvYXQxNiB2YWx1ZSBhdCBjdXJyZW50IGJ5dGUgb2Zmc2V0IHBvc2l0aW9uLAogICAgICAgICAqIGFuZCBhZGRzIHR3byBieXRlcyB0byB0aGUgb2Zmc2V0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgbG9hZFVGbG9hdDE2KCkgewogICAgICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmxvYWRGbG9hdDE2KCk7CiAgICAgICAgICAgIGlmIChyZXN1bHQgPCAwLjApIHsKICAgICAgICAgICAgICAgIHJldHVybiAyMDQ4LjAgLSByZXN1bHQ7IC8vIE5vdGU6IHN1YnRyYWN0IGEgbmVnYXRpdmUgbnVtYmVyIHRvIGFkZCBpdC4KICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBhIHNpbmdsZSBzaWduZWQgRmxvYXQxNiB2YWx1ZSBhdCBjdXJyZW50IGJ5dGUgb2Zmc2V0IHBvc2l0aW9uIGZyb20gMiB1bnNpZ25lZCBJbnQ4IHZhbHVlcywKICAgICAgICAgKiBhbmQgYWRkcyB0d28gYnl0ZXMgdG8gdGhlIG9mZnNldC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBUaGUgcmV0dXJuIHZhbHVlLgogICAgICAgICAqLwogICAgICAgIGxvYWRGbG9hdDE2RnJvbTJ4VUludDgoKSB7CiAgICAgICAgICAgIHRocm93IEVycm9yKCdsb2FkRmxvYXQxNkZyb20yeFVJbnQ4IG5vdCBpbXBsZW1lbnRlZCEnKTsKICAgICAgICAgICAgLy8gY29uc3QgcmVzdWx0ID0gdGhpcy5fX2RhdGFWaWV3LmdldEZsb2F0MTYodGhpcy5fX2J5dGVPZmZzZXQsIHRydWUpCiAgICAgICAgICAgIC8vIGNvbnN0IHVpbnQ4cyA9IHRoaXMubG9hZFVJbnQ4QXJyYXkoMik7CiAgICAgICAgICAgIC8vIHJldHVybiBNYXRoLmRlY29kZTE2Qml0RmxvYXQodWludDhzKTsKICAgICAgICAgICAgLy8gdGhpcy5fX2J5dGVPZmZzZXQgKz0gMgogICAgICAgICAgICAvLyByZXR1cm4gcmVzdWx0CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIExvYWRzIGFuZCByZXR1cm5zIGEgc2luZ2xlIFNpZ25lZCBpbnRlZ2VyIHZhbHVlIGZyb20gMiBVbnNpZ25lZCBGbG9hdDE2IHZhbHVlcy4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBsb2FkVUludDMyRnJvbTJ4VUZsb2F0MTYoKSB7CiAgICAgICAgICAgIGNvbnN0IHBhcnRBID0gdGhpcy5sb2FkVUZsb2F0MTYoKTsKICAgICAgICAgICAgY29uc3QgcGFydEIgPSB0aGlzLmxvYWRVRmxvYXQxNigpOwogICAgICAgICAgICByZXR1cm4gcGFydEEgKyBwYXJ0QiAqIDQwOTY7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIExvYWRzIGFuZCByZXR1cm5zIGEgc2luZ2xlIFNpZ25lZCBpbnRlZ2VyIHZhbHVlIGZyb20gMiBzaWduZWQgRmxvYXQxNiB2YWx1ZXMuCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgbG9hZFNJbnQzMkZyb20yeEZsb2F0MTYoKSB7CiAgICAgICAgICAgIGNvbnN0IHBhcnRBID0gdGhpcy5sb2FkRmxvYXQxNigpOwogICAgICAgICAgICBjb25zdCBwYXJ0QiA9IHRoaXMubG9hZEZsb2F0MTYoKTsKICAgICAgICAgICAgcmV0dXJuIHBhcnRBICsgcGFydEIgKiAyMDQ4OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRoZSBGbG9hdDMyIHZhbHVlIGF0IGN1cnJlbnQgYnl0ZSBvZmZzZXQgcG9zaXRpb24sCiAgICAgICAgICogYW5kIGFkZHMgZm91ciBieXRlcyB0byB0aGUgb2Zmc2V0LgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgbG9hZEZsb2F0MzIoKSB7CiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX19kYXRhVmlldy5nZXRGbG9hdDMyKHRoaXMuX19ieXRlT2Zmc2V0LCB0cnVlKTsKICAgICAgICAgICAgdGhpcy5fX2J5dGVPZmZzZXQgKz0gNDsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmVhZHMgYnVmZmVyIGFuZCByZXR1cm4gYSBzaWduZWQgSW50OCBhcnJheSB3aXRoIHRoZSBzcGVjaWZpZWQgc2l6ZSwKICAgICAgICAgKiBzdGFydGluZyBmcm9tIGN1cnJlbnQgYnl0ZSBvZmZzZXQuCiAgICAgICAgICogQnl0ZSBvZmZzZXQgaXMgaW5jcmVhc2VkIGJ5IHRoZSBzcGVjaWZpZWQgYnl0ZSBzaXplLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHNpemUgLSBUaGUgc2l6ZSBwYXJhbS4KICAgICAgICAgKiBAcGFyYW0gY2xvbmUgLSBUaGUgY2xvbmUgcGFyYW0uCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgbG9hZEludDhBcnJheShzaXplLCBjbG9uZSA9IHRydWUpIHsKICAgICAgICAgICAgaWYgKHNpemUgPT0gdW5kZWZpbmVkKQogICAgICAgICAgICAgICAgc2l6ZSA9IHRoaXMubG9hZFVJbnQzMigpOwogICAgICAgICAgICBsZXQgcmVzdWx0OwogICAgICAgICAgICBpZiAoY2xvbmUpIHsKICAgICAgICAgICAgICAgIHJlc3VsdCA9IG5ldyBJbnQ4QXJyYXkodGhpcy5fX2RhdGEuc2xpY2UodGhpcy5fX2J5dGVPZmZzZXQsIHRoaXMuX19ieXRlT2Zmc2V0ICsgc2l6ZSkpOwogICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5sZW5ndGggIT0gc2l6ZSkKICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnYnJva2VuJyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICByZXN1bHQgPSBuZXcgSW50OEFycmF5KHRoaXMuX19kYXRhLCB0aGlzLl9fYnl0ZU9mZnNldCwgc2l6ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5fX2J5dGVPZmZzZXQgKz0gc2l6ZTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmVhZHMgYnVmZmVyIGFuZCByZXR1cm4gYW4gdW5zaWduZWQgSW50OCBhcnJheSB3aXRoIHRoZSBzcGVjaWZpZWQgc2l6ZSwKICAgICAgICAgKiBzdGFydGluZyBmcm9tIGN1cnJlbnQgYnl0ZSBvZmZzZXQuCiAgICAgICAgICogQnl0ZSBvZmZzZXQgaXMgaW5jcmVhc2VkIGJ5IHRoZSBzcGVjaWZpZWQgYnl0ZSBzaXplLgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHNpemUgLSBUaGUgc2l6ZSBwYXJhbS4KICAgICAgICAgKiBAcGFyYW0gY2xvbmUgLSBUaGUgY2xvbmUgcGFyYW0uCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgbG9hZFVJbnQ4QXJyYXkoc2l6ZSwgY2xvbmUgPSB0cnVlKSB7CiAgICAgICAgICAgIGlmIChzaXplID09IHVuZGVmaW5lZCkKICAgICAgICAgICAgICAgIHNpemUgPSB0aGlzLmxvYWRVSW50MzIoKTsKICAgICAgICAgICAgbGV0IHJlc3VsdDsKICAgICAgICAgICAgaWYgKGNsb25lKSB7CiAgICAgICAgICAgICAgICByZXN1bHQgPSBuZXcgVWludDhBcnJheSh0aGlzLl9fZGF0YS5zbGljZSh0aGlzLl9fYnl0ZU9mZnNldCwgdGhpcy5fX2J5dGVPZmZzZXQgKyBzaXplKSk7CiAgICAgICAgICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCAhPSBzaXplKQogICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdicm9rZW4nKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHJlc3VsdCA9IG5ldyBVaW50OEFycmF5KHRoaXMuX19kYXRhLCB0aGlzLl9fYnl0ZU9mZnNldCwgc2l6ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5fX2J5dGVPZmZzZXQgKz0gc2l6ZTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmVhZHMgYnVmZmVyIGFuZCByZXR1cm4gYW4gdW5zaWduZWQgSW50MTYgYXJyYXkgd2l0aCB0aGUgc3BlY2lmaWVkIHNpemUsCiAgICAgICAgICogc3RhcnRpbmcgZnJvbSBjdXJyZW50IGJ5dGUgb2Zmc2V0LgogICAgICAgICAqIEJ5dGUgb2Zmc2V0IGlzIGluY3JlYXNlZCBieSB0aGUgc3BlY2lmaWVkIGJ5dGUgc2l6ZSB4IDIuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc2l6ZSAtIFRoZSBzaXplIHBhcmFtLgogICAgICAgICAqIEBwYXJhbSBjbG9uZSAtIFRoZSBjbG9uZSBwYXJhbS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBsb2FkVUludDE2QXJyYXkoc2l6ZSwgY2xvbmUgPSB0cnVlKSB7CiAgICAgICAgICAgIGlmIChzaXplID09IHVuZGVmaW5lZCkKICAgICAgICAgICAgICAgIHNpemUgPSB0aGlzLmxvYWRVSW50MzIoKTsKICAgICAgICAgICAgaWYgKHNpemUgPT0gMCkKICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVWludDE2QXJyYXkoKTsKICAgICAgICAgICAgdGhpcy5yZWFkUGFkKDIpOwogICAgICAgICAgICBsZXQgcmVzdWx0OwogICAgICAgICAgICBpZiAodGhpcy5fX2lzTW9iaWxlRGV2aWNlKSB7CiAgICAgICAgICAgICAgICByZXN1bHQgPSBuZXcgVWludDE2QXJyYXkoc2l6ZSk7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykgewogICAgICAgICAgICAgICAgICAgIHJlc3VsdFtpXSA9IHRoaXMuX19kYXRhVmlldy5nZXRVaW50MTYodGhpcy5fX2J5dGVPZmZzZXQsIHRydWUpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuX19ieXRlT2Zmc2V0ICs9IDI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBpZiAoY2xvbmUpIHsKICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBuZXcgVWludDE2QXJyYXkodGhpcy5fX2RhdGEuc2xpY2UodGhpcy5fX2J5dGVPZmZzZXQsIHRoaXMuX19ieXRlT2Zmc2V0ICsgc2l6ZSAqIDIpKTsKICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCAhPSBzaXplKQogICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnYnJva2VuJyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBuZXcgVWludDE2QXJyYXkodGhpcy5fX2RhdGEsIHRoaXMuX19ieXRlT2Zmc2V0LCBzaXplKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRoaXMuX19ieXRlT2Zmc2V0ICs9IHNpemUgKiAyOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJlYWRzIGJ1ZmZlciBhbmQgcmV0dXJuIGFuIHVuc2lnbmVkIEludDMyIGFycmF5IHdpdGggdGhlIHNwZWNpZmllZCBzaXplLAogICAgICAgICAqIHN0YXJ0aW5nIGZyb20gY3VycmVudCBieXRlIG9mZnNldC4KICAgICAgICAgKiBCeXRlIG9mZnNldCBpcyBpbmNyZWFzZWQgYnkgdGhlIHNwZWNpZmllZCBieXRlIHNpemUgeCA0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHNpemUgLSBUaGUgc2l6ZSBwYXJhbS4KICAgICAgICAgKiBAcGFyYW0gY2xvbmUgLSBUaGUgY2xvbmUgcGFyYW0uCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgbG9hZFVJbnQzMkFycmF5KHNpemUsIGNsb25lID0gdHJ1ZSkgewogICAgICAgICAgICBpZiAoc2l6ZSA9PSB1bmRlZmluZWQpCiAgICAgICAgICAgICAgICBzaXplID0gdGhpcy5sb2FkVUludDMyKCk7CiAgICAgICAgICAgIGlmIChzaXplID09IDApCiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFVpbnQzMkFycmF5KCk7CiAgICAgICAgICAgIHRoaXMucmVhZFBhZCg0KTsKICAgICAgICAgICAgbGV0IHJlc3VsdDsKICAgICAgICAgICAgaWYgKHRoaXMuX19pc01vYmlsZURldmljZSkgewogICAgICAgICAgICAgICAgcmVzdWx0ID0gbmV3IFVpbnQzMkFycmF5KHNpemUpOwogICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICByZXN1bHRbaV0gPSB0aGlzLl9fZGF0YVZpZXcuZ2V0VWludDMyKHRoaXMuX19ieXRlT2Zmc2V0LCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLl9fYnl0ZU9mZnNldCArPSA0OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgaWYgKGNsb25lKSB7CiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gbmV3IFVpbnQzMkFycmF5KHRoaXMuX19kYXRhLnNsaWNlKHRoaXMuX19ieXRlT2Zmc2V0LCB0aGlzLl9fYnl0ZU9mZnNldCArIHNpemUgKiA0KSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5sZW5ndGggIT0gc2l6ZSkKICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ2Jyb2tlbicpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gbmV3IFVpbnQzMkFycmF5KHRoaXMuX19kYXRhLCB0aGlzLl9fYnl0ZU9mZnNldCwgc2l6ZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB0aGlzLl9fYnl0ZU9mZnNldCArPSBzaXplICogNDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBSZWFkcyBidWZmZXIgYW5kIHJldHVybiBhIEZsb2F0MzIgYXJyYXkgd2l0aCB0aGUgc3BlY2lmaWVkIHNpemUsCiAgICAgICAgICogc3RhcnRpbmcgZnJvbSBjdXJyZW50IGJ5dGUgb2Zmc2V0LgogICAgICAgICAqIEJ5dGUgb2Zmc2V0IGlzIGluY3JlYXNlZCBieSB0aGUgc3BlY2lmaWVkIGJ5dGUgc2l6ZSB4IDQuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc2l6ZSAtIFRoZSBzaXplIHBhcmFtLgogICAgICAgICAqIEBwYXJhbSBjbG9uZSAtIFRoZSBjbG9uZSBwYXJhbS4KICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBsb2FkRmxvYXQzMkFycmF5KHNpemUsIGNsb25lID0gdHJ1ZSkgewogICAgICAgICAgICBpZiAoc2l6ZSA9PSB1bmRlZmluZWQpCiAgICAgICAgICAgICAgICBzaXplID0gdGhpcy5sb2FkVUludDMyKCk7CiAgICAgICAgICAgIGlmIChzaXplID09IDApCiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEZsb2F0MzJBcnJheSgpOwogICAgICAgICAgICB0aGlzLnJlYWRQYWQoNCk7CiAgICAgICAgICAgIGxldCByZXN1bHQ7CiAgICAgICAgICAgIGlmICh0aGlzLl9faXNNb2JpbGVEZXZpY2UpIHsKICAgICAgICAgICAgICAgIHJlc3VsdCA9IG5ldyBGbG9hdDMyQXJyYXkoc2l6ZSk7CiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykgewogICAgICAgICAgICAgICAgICAgIHJlc3VsdFtpXSA9IHRoaXMuX19kYXRhVmlldy5nZXRGbG9hdDMyKHRoaXMuX19ieXRlT2Zmc2V0LCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLl9fYnl0ZU9mZnNldCArPSA0OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgaWYgKGNsb25lKSB7CiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLl9fZGF0YS5zbGljZSh0aGlzLl9fYnl0ZU9mZnNldCwgdGhpcy5fX2J5dGVPZmZzZXQgKyBzaXplICogNCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLl9fZGF0YSwgdGhpcy5fX2J5dGVPZmZzZXQsIHNpemUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhpcy5fX2J5dGVPZmZzZXQgKz0gc2l6ZSAqIDQ7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyBuZXh0IHN0cmluZy4KICAgICAgICAgKiBGaXJzdCBsb29rcyBmb3IgdGhlIHN0cmluZyBsZW5ndGggZGVzY3JpcHRpb24gaW4gdGhlIG5leHQgZm91ciBieXRlcyBpbiB0aGUgYnVmZmVyKFN0YXJ0aW5nIGZyb20gYnl0ZSBvZmZzZXQpLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFRoZSByZXR1cm4gdmFsdWUuCiAgICAgICAgICovCiAgICAgICAgbG9hZFN0cigpIHsKICAgICAgICAgICAgY29uc3QgbnVtQ2hhcnMgPSB0aGlzLmxvYWRVSW50MzIoKTsKICAgICAgICAgICAgY29uc3QgY2hhcnMgPSBuZXcgVWludDhBcnJheSh0aGlzLl9fZGF0YSwgdGhpcy5fX2J5dGVPZmZzZXQsIG51bUNoYXJzKTsKICAgICAgICAgICAgdGhpcy5fX2J5dGVPZmZzZXQgKz0gbnVtQ2hhcnM7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnV0ZjhkZWNvZGVyLmRlY29kZShjaGFycyk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYW4gYXJyYXkgb2Ygc3RyaW5ncy4KICAgICAgICAgKiBGaXJzdCByZWFkaW5nIHRoZSBzaXplIG9mIHRoZSBhcnJheSB0aGVuIHJlYWRpbmcgZWFjaCBzdHJpbmcuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gVGhlIHJldHVybiB2YWx1ZS4KICAgICAgICAgKi8KICAgICAgICBsb2FkU3RyQXJyYXkoKSB7CiAgICAgICAgICAgIGNvbnN0IHNpemUgPSB0aGlzLmxvYWRVSW50MzIoKTsKICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gW107CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CiAgICAgICAgICAgICAgICByZXN1bHRbaV0gPSB0aGlzLmxvYWRTdHIoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGFuZCByZXR1cm5zIGEgYFZlYzJgIG9iamVjdCB3aXRoIHRoZSBuZXh0IHR3byBzaWduZWQgSW50MzIgdmFsdWVzIGluIHRoZSBidWZmZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIFZlYzIuCiAgICAgICAgICovCiAgICAgICAgbG9hZFNJbnQzMlZlYzIoKSB7CiAgICAgICAgICAgIGNvbnN0IHggPSB0aGlzLmxvYWRTSW50MzIoKTsKICAgICAgICAgICAgY29uc3QgeSA9IHRoaXMubG9hZFNJbnQzMigpOwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzIoeCwgeSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYW5kIHJldHVybnMgYSBgVmVjMmAgb2JqZWN0IHdpdGggdGhlIG5leHQgdHdvIHVuc2lnbmVkIEludDMyIHZhbHVlcyBpbiB0aGUgYnVmZmVyLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgVmVjMi4KICAgICAgICAgKi8KICAgICAgICBsb2FkVUludDMyVmVjMigpIHsKICAgICAgICAgICAgY29uc3QgeCA9IHRoaXMubG9hZFVJbnQzMigpOwogICAgICAgICAgICBjb25zdCB5ID0gdGhpcy5sb2FkVUludDMyKCk7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMih4LCB5KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlcyBhbmQgcmV0dXJucyBhIGBWZWMyYCBvYmplY3Qgd2l0aCB0aGUgbmV4dCB0d28gRmxvYXQxNiB2YWx1ZXMgaW4gdGhlIGJ1ZmZlci4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgVmVjMi4KICAgICAgICAgKi8KICAgICAgICBsb2FkRmxvYXQxNlZlYzIoKSB7CiAgICAgICAgICAgIGNvbnN0IHggPSB0aGlzLmxvYWRGbG9hdDE2KCk7CiAgICAgICAgICAgIGNvbnN0IHkgPSB0aGlzLmxvYWRGbG9hdDE2KCk7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMih4LCB5KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlcyBhbmQgcmV0dXJucyBhIGBWZWMyYCBvYmplY3Qgd2l0aCB0aGUgbmV4dCB0d28gRmxvYXQzMiB2YWx1ZXMgaW4gdGhlIGJ1ZmZlci4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIFZlYzIuCiAgICAgICAgICovCiAgICAgICAgbG9hZEZsb2F0MzJWZWMyKCkgewogICAgICAgICAgICBjb25zdCB4ID0gdGhpcy5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICBjb25zdCB5ID0gdGhpcy5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICByZXR1cm4gbmV3IFZlYzIoeCwgeSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYW5kIHJldHVybnMgYSBgVmVjM2Agb2JqZWN0IHdpdGggdGhlIG5leHQgdGhyZWUgRmxvYXQxNiB2YWx1ZXMgaW4gdGhlIGJ1ZmZlci4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgVmVjMy4KICAgICAgICAgKi8KICAgICAgICBsb2FkRmxvYXQxNlZlYzMoKSB7CiAgICAgICAgICAgIGNvbnN0IHggPSB0aGlzLmxvYWRGbG9hdDE2KCk7CiAgICAgICAgICAgIGNvbnN0IHkgPSB0aGlzLmxvYWRGbG9hdDE2KCk7CiAgICAgICAgICAgIGNvbnN0IHogPSB0aGlzLmxvYWRGbG9hdDE2KCk7CiAgICAgICAgICAgIHJldHVybiBuZXcgVmVjMyh4LCB5LCB6KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlcyBhbmQgcmV0dXJucyBhIGBWZWMzYCBvYmplY3Qgd2l0aCB0aGUgbmV4dCB0aHJlZSBGbG9hdDMyIHZhbHVlcyBpbiB0aGUgYnVmZmVyLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBWZWMzLgogICAgICAgICAqLwogICAgICAgIGxvYWRGbG9hdDMyVmVjMygpIHsKICAgICAgICAgICAgY29uc3QgeCA9IHRoaXMubG9hZEZsb2F0MzIoKTsKICAgICAgICAgICAgY29uc3QgeSA9IHRoaXMubG9hZEZsb2F0MzIoKTsKICAgICAgICAgICAgY29uc3QgeiA9IHRoaXMubG9hZEZsb2F0MzIoKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBWZWMzKHgsIHksIHopOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGFuZCByZXR1cm5zIGEgYFF1YXRgIG9iamVjdCB3aXRoIHRoZSBuZXh0IGZvdXIgRmxvYXQxNiB2YWx1ZXMgaW4gdGhlIGJ1ZmZlci4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgUXVhdC4KICAgICAgICAgKi8KICAgICAgICBsb2FkRmxvYXQxNlF1YXQoKSB7CiAgICAgICAgICAgIGNvbnN0IHggPSB0aGlzLmxvYWRGbG9hdDE2KCk7CiAgICAgICAgICAgIGNvbnN0IHkgPSB0aGlzLmxvYWRGbG9hdDE2KCk7CiAgICAgICAgICAgIGNvbnN0IHogPSB0aGlzLmxvYWRGbG9hdDE2KCk7CiAgICAgICAgICAgIGNvbnN0IHcgPSB0aGlzLmxvYWRGbG9hdDE2KCk7CiAgICAgICAgICAgIHJldHVybiBuZXcgUXVhdCh4LCB5LCB6LCB3KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlcyBhbmQgcmV0dXJucyBhIGBRdWF0YCBvYmplY3Qgd2l0aCB0aGUgbmV4dCBmb3VyIEZsb2F0MzIgdmFsdWVzIGluIHRoZSBidWZmZXIuCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBRdWF0LgogICAgICAgICAqLwogICAgICAgIGxvYWRGbG9hdDMyUXVhdCgpIHsKICAgICAgICAgICAgY29uc3QgeCA9IHRoaXMubG9hZEZsb2F0MzIoKTsKICAgICAgICAgICAgY29uc3QgeSA9IHRoaXMubG9hZEZsb2F0MzIoKTsKICAgICAgICAgICAgY29uc3QgeiA9IHRoaXMubG9hZEZsb2F0MzIoKTsKICAgICAgICAgICAgY29uc3QgdyA9IHRoaXMubG9hZEZsb2F0MzIoKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBRdWF0KHgsIHksIHosIHcpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGFuZCByZXR1cm5zIGEgYENvbG9yYCBvYmplY3Qgd2l0aCB0aGUgbmV4dCB0aHJlZSBGbG9hdDMyIHZhbHVlcyBpbiB0aGUgYnVmZmVyLgogICAgICAgICAqCiAgICAgICAgICogQHJldHVybiAtIFJldHVybnMgYSBDb2xvci4KICAgICAgICAgKi8KICAgICAgICBsb2FkUkdCRmxvYXQzMkNvbG9yKCkgewogICAgICAgICAgICBjb25zdCByID0gdGhpcy5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICBjb25zdCBnID0gdGhpcy5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICBjb25zdCBiID0gdGhpcy5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICByZXR1cm4gbmV3IENvbG9yKHIsIGcsIGIpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGFuZCByZXR1cm5zIGEgUkdCQSBgQ29sb3JgIG9iamVjdCB3aXRoIHRoZSBuZXh0IGZvdXIgRmxvYXQzMiB2YWx1ZXMgaW4gdGhlIGJ1ZmZlci4KICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIENvbG9yLgogICAgICAgICAqLwogICAgICAgIGxvYWRSR0JBRmxvYXQzMkNvbG9yKCkgewogICAgICAgICAgICBjb25zdCByID0gdGhpcy5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICBjb25zdCBnID0gdGhpcy5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICBjb25zdCBiID0gdGhpcy5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICBjb25zdCBhID0gdGhpcy5sb2FkRmxvYXQzMigpOwogICAgICAgICAgICByZXR1cm4gbmV3IENvbG9yKHIsIGcsIGIsIGEpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGFuZCByZXR1cm5zIGEgYENvbG9yYCBvYmplY3Qgd2l0aCB0aGUgbmV4dCB0aHJlZSB1bnNpZ25lZCBJbnQ4IHZhbHVlcyBpbiB0aGUgYnVmZmVyLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgQ29sb3IuCiAgICAgICAgICovCiAgICAgICAgbG9hZFJHQlVJbnQ4Q29sb3IoKSB7CiAgICAgICAgICAgIGNvbnN0IHIgPSB0aGlzLmxvYWRVSW50OCgpOwogICAgICAgICAgICBjb25zdCBnID0gdGhpcy5sb2FkVUludDgoKTsKICAgICAgICAgICAgY29uc3QgYiA9IHRoaXMubG9hZFVJbnQ4KCk7CiAgICAgICAgICAgIHJldHVybiBuZXcgQ29sb3IociAvIDI1NSwgZyAvIDI1NSwgYiAvIDI1NSk7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYW5kIHJldHVybnMgYSBSR0JBIGBDb2xvcmAgb2JqZWN0IHdpdGggdGhlIG5leHQgZm91ciB1bnNpZ25lZCBJbnQ4IHZhbHVlcyBpbiB0aGUgYnVmZmVyLgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgQ29sb3IuCiAgICAgICAgICovCiAgICAgICAgbG9hZFJHQkFVSW50OENvbG9yKCkgewogICAgICAgICAgICBjb25zdCByID0gdGhpcy5sb2FkVUludDgoKTsKICAgICAgICAgICAgY29uc3QgZyA9IHRoaXMubG9hZFVJbnQ4KCk7CiAgICAgICAgICAgIGNvbnN0IGIgPSB0aGlzLmxvYWRVSW50OCgpOwogICAgICAgICAgICBjb25zdCBhID0gdGhpcy5sb2FkVUludDgoKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBDb2xvcihyIC8gMjU1LCBnIC8gMjU1LCBiIC8gMjU1LCBhIC8gMjU1KTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogQ3JlYXRlcyBhbmQgcmV0dXJucyBhIGBCb3gyYCBvYmplY3Qgd2l0aCB0aGUgbmV4dCBmb3VyIEZsb2F0MzIgdmFsdWVzIGluIHRoZSBidWZmZXIuCiAgICAgICAgICogTmV4dCBmb3VyIGJlY2F1c2UgaXQgY3JlYXRlcyB0d28gVmVjMi4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gLSBSZXR1cm5zIGEgQm94Mi4KICAgICAgICAgKi8KICAgICAgICBsb2FkQm94MigpIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBCb3gyKHRoaXMubG9hZEZsb2F0MzJWZWMyKCksIHRoaXMubG9hZEZsb2F0MzJWZWMyKCkpOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGFuZCByZXR1cm5zIGEgYEJveDJgIG9iamVjdCB3aXRoIHRoZSBuZXh0IHNpeCBGbG9hdDMyIHZhbHVlcyBpbiB0aGUgYnVmZmVyLgogICAgICAgICAqIE5leHQgZm91ciBiZWNhdXNlIGl0IGNyZWF0ZXMgdHdvIFZlYzMuCiAgICAgICAgICoKICAgICAgICAgKiBAcmV0dXJuIC0gUmV0dXJucyBhIEJveDMuCiAgICAgICAgICovCiAgICAgICAgbG9hZEJveDMoKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgQm94Myh0aGlzLmxvYWRGbG9hdDMyVmVjMygpLCB0aGlzLmxvYWRGbG9hdDMyVmVjMygpKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogR2l2ZW4gYSBzdHJpZGVlIHZhbHVlLCBhZHZhbmNlIHRoZSBwb2ludGVyIHRvIHRoZSBlbmQgb2YgdGhlIGN1cnJlbnQgc3RyaWRlLgogICAgICAgICAqIEBwYXJhbSBzdHJpZGUgLSBUaGUgc3RyaWRlIHBhcmFtLgogICAgICAgICAqLwogICAgICAgIHJlYWRQYWQoc3RyaWRlKSB7CiAgICAgICAgICAgIGNvbnN0IHBhZCA9IHRoaXMuX19ieXRlT2Zmc2V0ICUgc3RyaWRlOwogICAgICAgICAgICBpZiAocGFkICE9IDApCiAgICAgICAgICAgICAgICB0aGlzLl9fYnl0ZU9mZnNldCArPSBzdHJpZGUgLSBwYWQ7CiAgICAgICAgfQogICAgfQoKICAgIC8qKgogICAgICogQ2xhc3MgZGVzaWduZWQgdG8gc3RvcmUgdmVyc2lvbiBkYXRhLiBXaWRlbHkgdXNlZCBpbiB0aGUgemVhIGVuZ2luZSBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuCiAgICAgKi8KICAgIGNsYXNzIFZlcnNpb24gewogICAgICAgIG1ham9yID0gMDsKICAgICAgICBtaW5vciA9IDA7CiAgICAgICAgcGF0Y2ggPSAwOwogICAgICAgIGJyYW5jaCA9ICcnOwogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYSB2ZXJzaW9uLgogICAgICAgICAqIFRoZSB2ZXJzaW9uIHN0cmluZyBzaG91bGQgaGF2ZSB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZToKICAgICAgICAgKiBtYWpvciwgbWlub3IgYW5kIHBhdGNoIHNlcGFyYXRlZCBieSBhIGRvdChgLmApIGFuZCBwYXJ0cyBzZXBhcmF0ZWQgYnkgYSBkYXNoKGAtYCkuCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gYXJnIC0gVGhlIHZlcnNpb24gc3RyaW5nIHZhbHVlLCBvciBhbiBhcnJheSBvZiB2ZXJzaW9uIG51bWJlcnMuCiAgICAgICAgICovCiAgICAgICAgY29uc3RydWN0b3IoYXJnKSB7CiAgICAgICAgICAgIGlmICh0eXBlb2YgYXJnID09ICdzdHJpbmcnKSB7CiAgICAgICAgICAgICAgICBjb25zdCBwYXJ0cyA9IGFyZy5zcGxpdCgnLScpOwogICAgICAgICAgICAgICAgY29uc3QgbnVtYmVycyA9IHBhcnRzWzBdLnNwbGl0KCcuJyk7CiAgICAgICAgICAgICAgICB0aGlzLm1ham9yID0gcGFyc2VJbnQobnVtYmVyc1swXSk7CiAgICAgICAgICAgICAgICB0aGlzLm1pbm9yID0gbnVtYmVycy5sZW5ndGggPiAxID8gcGFyc2VJbnQobnVtYmVyc1sxXSkgOiAwOwogICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IG51bWJlcnMubGVuZ3RoID4gMiA/IHBhcnNlSW50KG51bWJlcnNbMl0pIDogMDsKICAgICAgICAgICAgICAgIGlmIChwYXJ0cy5sZW5ndGggPT0gMikKICAgICAgICAgICAgICAgICAgICB0aGlzLmJyYW5jaCA9IHBhcnRzWzFdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkgewogICAgICAgICAgICAgICAgY29uc3QgbnVtYmVycyA9IGFyZzsKICAgICAgICAgICAgICAgIHRoaXMubWFqb3IgPSBudW1iZXJzWzBdOwogICAgICAgICAgICAgICAgdGhpcy5taW5vciA9IG51bWJlcnMubGVuZ3RoID4gMSA/IG51bWJlcnNbMV0gOiAwOwogICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IG51bWJlcnMubGVuZ3RoID4gMiA/IG51bWJlcnNbMl0gOiAwOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENvbXBhcmUgYSB2ZXJzaW9uIG9iamVjdCBhZ2FpbnN0IGEgdmVyc2lvbiBudW1iZXJzIGFycmF5LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIG51bWJlcnMgLSBBbiBhcnJheSBjb250YWluaW5nIDMgdmVyc2lvbiBudW1iZXJzLiBbTWFqb3IsIE1pbm9yLCBQYXRjaF0KICAgICAgICAgKiBAcmV0dXJuIC0gcmV0dXJuIHBvc2l0aXZlOiB2MSA+IHYyLCB6ZXJvOnYxID09IHYyLCBuZWdhdGl2ZTogdjEgPCB2MgogICAgICAgICAqLwogICAgICAgIGNvbXBhcmUobnVtYmVycykgewogICAgICAgICAgICAvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82ODMyNTk2L2hvdy10by1jb21wYXJlLXNvZnR3YXJlLXZlcnNpb24tbnVtYmVyLXVzaW5nLWpzLW9ubHktbnVtYmVyCiAgICAgICAgICAgIC8vIDJuZCBhbnN3ZXIuCiAgICAgICAgICAgIGNvbnN0IHYxID0gW3RoaXMubWFqb3IsIHRoaXMubWlub3IsIHRoaXMucGF0Y2hdOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7IGkrKykgewogICAgICAgICAgICAgICAgaWYgKHYxW2ldICE9PSBudW1iZXJzW2ldKQogICAgICAgICAgICAgICAgICAgIHJldHVybiB2MVtpXSAtIG51bWJlcnNbaV07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIENvbnZlcnRzIHRoZSBWZXJzaW9uIGNsYXNzIGluc3RhbmNlIGJhY2sgdG8gYW4gYXJyYXkgZm9yIGNvbXBhcmlzb25zIHdpdGggb3RoZXIgdmVyc2lvbiBjbGFzcyBpbnN0YW5jZXMuCiAgICAgICAgICogZS5nLgogICAgICAgICAqIGBgYAogICAgICAgICAqICAgY29uc3QgdmVyc2lvbjEgPSBuZXcgVmVyc2lvbihbMSwgMiwgM10pCiAgICAgICAgICogICBjb25zdCB2ZXJzaW9uMiA9IG5ldyBWZXJzaW9uKFsxLCAyLCA0XSkKICAgICAgICAgKiAgIGNvbnN0IHJlcyA9IHZlcnNpb24xLmNvbXBhcmUodmVyc2lvbjIuYXNBcnJheSgpKQogICAgICAgICAqIGBgYAogICAgICAgICAqIEByZXR1cm5zIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIG1ham9yLCBtaW5vciBhbmQgcGF0Y2ggdmVyc2lvbiBudW1iZXJzLgogICAgICAgICAqLwogICAgICAgIGFzQXJyYXkoKSB7CiAgICAgICAgICAgIHJldHVybiBbdGhpcy5tYWpvciwgdGhpcy5taW5vciwgdGhpcy5wYXRjaF07CiAgICAgICAgfQogICAgICAgIHRvU3RyaW5nKCkgewogICAgICAgICAgICByZXR1cm4gYHYke3RoaXMubWFqb3J9LiR7dGhpcy5taW5vcn0uJHt0aGlzLnBhdGNofWAgKyAodGhpcy5icmFuY2ggIT0gJycgPyBgLSR7dGhpcy5icmFuY2h9YCA6ICcnKTsKICAgICAgICB9CiAgICB9CgogICAgLyoqCiAgICAgKiBAcHJpdmF0ZQogICAgICogQGV4dGVuZHMgQmFzZUdlb20KICAgICAqLwogICAgY2xhc3MgQ29tcG91bmRHZW9tTG9hZGVyIGV4dGVuZHMgQmFzZUdlb20gewogICAgICAgIG51bVN1Ykdlb21zID0gMDsKICAgICAgICBpbmRpY2VzID0gbmV3IFVpbnQ4QXJyYXkoMCk7CiAgICAgICAgb2Zmc2V0cyA9IHt9OwogICAgICAgIGNvdW50cyA9IHt9OwogICAgICAgIC8vIEZvciBlYWNoIHR5cGUgb2YgZ2VvbSAoVFJJQU5HTEVTLCBMSU5FUykKICAgICAgICAvLyBBIG1hdGVyaWFsIGlkLCBhbmQgZWFjaCBzdGFydCBhbmQgZW5kIG9mIHRoZSBibG9jawogICAgICAgIG1hdGVyaWFsU3ViR2VvbXMgPSB7fTsKICAgICAgICBzdWJHZW9tT2Zmc2V0cyA9IHt9OwogICAgICAgIHN1Ykdlb21Db3VudHMgPSB7fTsKICAgICAgICBtYXRlcmlhbExpYnJhcnlJbmRpY2VzID0gbmV3IFVpbnQzMkFycmF5KDApOwogICAgICAgIHN1Ykdlb21NYXRlcmlhbEluZGljZXMgPSBuZXcgVWludDhBcnJheSgwKTsKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGUgcG9pbnRzLgogICAgICAgICAqLwogICAgICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgICAgICBzdXBlcigpOwogICAgICAgIH0KICAgICAgICBnZW5CdWZmZXJzKCkgewogICAgICAgICAgICBjb25zdCBhdHRyQnVmZmVycyA9IHt9OwogICAgICAgICAgICBmb3IgKGNvbnN0IFthdHRyTmFtZSwgYXR0cl0gb2YgdGhpcy5fX3ZlcnRleEF0dHJpYnV0ZXMpIHsKICAgICAgICAgICAgICAgIGF0dHJCdWZmZXJzW2F0dHJOYW1lXSA9IGF0dHIuZ2VuQnVmZmVyKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgbnVtVmVydGljZXMgPSB0aGlzLm51bVZlcnRpY2VzKCk7CiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHsKICAgICAgICAgICAgICAgIG51bVZlcnRpY2VzLAogICAgICAgICAgICAgICAgbnVtUmVuZGVyVmVydHM6IG51bVZlcnRpY2VzLAogICAgICAgICAgICAgICAgaW5kaWNlczogdGhpcy5pbmRpY2VzLAogICAgICAgICAgICAgICAgYXR0ckJ1ZmZlcnMsCiAgICAgICAgICAgICAgICBvZmZzZXRzOiB0aGlzLm9mZnNldHMsCiAgICAgICAgICAgICAgICBjb3VudHM6IHRoaXMuY291bnRzLAogICAgICAgICAgICAgICAgbnVtU3ViR2VvbXM6IHRoaXMubnVtU3ViR2VvbXMsCiAgICAgICAgICAgICAgICBzdWJHZW9tT2Zmc2V0czogdGhpcy5zdWJHZW9tT2Zmc2V0cywKICAgICAgICAgICAgICAgIHN1Ykdlb21Db3VudHM6IHRoaXMuc3ViR2VvbUNvdW50cywKICAgICAgICAgICAgICAgIG1hdGVyaWFsTGlicmFyeUluZGljZXM6IHRoaXMubWF0ZXJpYWxMaWJyYXJ5SW5kaWNlcywKICAgICAgICAgICAgICAgIHN1Ykdlb21NYXRlcmlhbEluZGljZXM6IHRoaXMuc3ViR2VvbU1hdGVyaWFsSW5kaWNlcywKICAgICAgICAgICAgICAgIG1hdGVyaWFsU3ViR2VvbXM6IHRoaXMubWF0ZXJpYWxTdWJHZW9tcywKICAgICAgICAgICAgfTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgIC8vIFBlcnNpc3RlbmNlCiAgICAgICAgLyoqCiAgICAgICAgICogU2V0cyBzdGF0ZSBvZiBjdXJyZW50IGdlb21ldHJ5KEluY2x1ZGluZyBsaW5lIHNlZ21lbnRzKSB1c2luZyBhIGJpbmFyeSByZWFkZXIgb2JqZWN0LgogICAgICAgICAqCiAgICAgICAgICogQHBhcmFtIHtCaW5SZWFkZXJ9IHJlYWRlciAtIFRoZSByZWFkZXIgdmFsdWUuCiAgICAgICAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gY29udGV4dCAtIFRoZSBjb250ZXh0IHZhbHVlLgogICAgICAgICAqLwogICAgICAgIHJlYWRCaW5hcnkocmVhZGVyLCBjb250ZXh0KSB7CiAgICAgICAgICAgIHN1cGVyLmxvYWRCYXNlR2VvbUJpbmFyeShyZWFkZXIsIGNvbnRleHQpOwogICAgICAgICAgICBjb25zdCBnZW9tQ291bnRzQnlUeXBlID0gcmVhZGVyLmxvYWRVSW50MzJBcnJheSgzKTsKICAgICAgICAgICAgdGhpcy5vZmZzZXRzWydUUklBTkdMRVMnXSA9IDA7CiAgICAgICAgICAgIHRoaXMuY291bnRzWydUUklBTkdMRVMnXSA9IGdlb21Db3VudHNCeVR5cGVbMF07CiAgICAgICAgICAgIHRoaXMub2Zmc2V0c1snTElORVMnXSA9IGdlb21Db3VudHNCeVR5cGVbMF07CiAgICAgICAgICAgIHRoaXMuY291bnRzWydMSU5FUyddID0gZ2VvbUNvdW50c0J5VHlwZVsxXTsKICAgICAgICAgICAgdGhpcy5vZmZzZXRzWydQT0lOVFMnXSA9IGdlb21Db3VudHNCeVR5cGVbMF0gKyBnZW9tQ291bnRzQnlUeXBlWzFdOwogICAgICAgICAgICB0aGlzLmNvdW50c1snUE9JTlRTJ10gPSBnZW9tQ291bnRzQnlUeXBlWzJdOwogICAgICAgICAgICBjb25zdCBieXRlcyA9IHJlYWRlci5sb2FkVUludDgoKTsKICAgICAgICAgICAgLy8gTm90ZTogZG8gbm90IGNsb25lIHRoZSBzb3VyY2UgYXJyYXlzIGFzIHdlIHdpbGwgdHJhbnNmZXIgdGhlCiAgICAgICAgICAgIC8vIGVudGlyZSBidWZmZXIgYmFjayB0byB0aGUgbWFpbiB0aHJlYWQgd2hlcmUgaXQgd2lsbCBiZSBmcmVlZCBvbmNlCiAgICAgICAgICAgIC8vIHRoZSBkYXRhIGlzIHVwbG9hZGVkIHRvIHRoZSBHUFUuCiAgICAgICAgICAgIGlmIChieXRlcyA9PSAxKQogICAgICAgICAgICAgICAgdGhpcy5pbmRpY2VzID0gcmVhZGVyLmxvYWRVSW50OEFycmF5KCk7CiAgICAgICAgICAgIGVsc2UgaWYgKGJ5dGVzID09IDIpCiAgICAgICAgICAgICAgICB0aGlzLmluZGljZXMgPSByZWFkZXIubG9hZFVJbnQxNkFycmF5KCk7CiAgICAgICAgICAgIGVsc2UgaWYgKGJ5dGVzID09IDQpCiAgICAgICAgICAgICAgICB0aGlzLmluZGljZXMgPSByZWFkZXIubG9hZFVJbnQzMkFycmF5KCk7CiAgICAgICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgICAgICAvLyBUUklBTkdMRVMgc3ViZ2VvbXMKICAgICAgICAgICAgY29uc3QgYnl0ZXNNZXNoU3ViR2VvbXMgPSByZWFkZXIubG9hZFVJbnQ4KCk7CiAgICAgICAgICAgIGxldCBzdWJHZW9tQ291bnRzTWVzaDsKICAgICAgICAgICAgaWYgKGJ5dGVzTWVzaFN1Ykdlb21zID09IDEpCiAgICAgICAgICAgICAgICBzdWJHZW9tQ291bnRzTWVzaCA9IHJlYWRlci5sb2FkVUludDhBcnJheSgpOwogICAgICAgICAgICBlbHNlIGlmIChieXRlc01lc2hTdWJHZW9tcyA9PSAyKQogICAgICAgICAgICAgICAgc3ViR2VvbUNvdW50c01lc2ggPSByZWFkZXIubG9hZFVJbnQxNkFycmF5KCk7CiAgICAgICAgICAgIGVsc2UgaWYgKGJ5dGVzTWVzaFN1Ykdlb21zID09IDQpCiAgICAgICAgICAgICAgICBzdWJHZW9tQ291bnRzTWVzaCA9IHJlYWRlci5sb2FkVUludDMyQXJyYXkoKTsKICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcignc3ViR2VvbU9mZnNldHMgdW5kZWZpbmVkJyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3Qgc3ViR2VvbU9mZnNldHNNZXNoID0gbmV3IFVpbnQzMkFycmF5KHN1Ykdlb21Db3VudHNNZXNoLmxlbmd0aCk7CiAgICAgICAgICAgIGxldCBvZmZzZXQgPSAwOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHN1Ykdlb21Db3VudHNNZXNoLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBzdWJHZW9tT2Zmc2V0c01lc2hbaV0gPSBvZmZzZXQ7CiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gc3ViR2VvbUNvdW50c01lc2hbaV07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5zdWJHZW9tT2Zmc2V0c1snVFJJQU5HTEVTJ10gPSBzdWJHZW9tT2Zmc2V0c01lc2g7CiAgICAgICAgICAgIHRoaXMuc3ViR2VvbUNvdW50c1snVFJJQU5HTEVTJ10gPSBzdWJHZW9tQ291bnRzTWVzaDsKICAgICAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgICAgIC8vIExJTkVTIHN1Ymdlb21zCiAgICAgICAgICAgIGNvbnN0IGJ5dGVzTGluZXNTdWJHZW9tcyA9IHJlYWRlci5sb2FkVUludDgoKTsKICAgICAgICAgICAgbGV0IHN1Ykdlb21Db3VudHNMaW5lczsKICAgICAgICAgICAgaWYgKGJ5dGVzTGluZXNTdWJHZW9tcyA9PSAxKQogICAgICAgICAgICAgICAgc3ViR2VvbUNvdW50c0xpbmVzID0gcmVhZGVyLmxvYWRVSW50OEFycmF5KCk7CiAgICAgICAgICAgIGVsc2UgaWYgKGJ5dGVzTGluZXNTdWJHZW9tcyA9PSAyKQogICAgICAgICAgICAgICAgc3ViR2VvbUNvdW50c0xpbmVzID0gcmVhZGVyLmxvYWRVSW50MTZBcnJheSgpOwogICAgICAgICAgICBlbHNlIGlmIChieXRlc0xpbmVzU3ViR2VvbXMgPT0gNCkKICAgICAgICAgICAgICAgIHN1Ykdlb21Db3VudHNMaW5lcyA9IHJlYWRlci5sb2FkVUludDMyQXJyYXkoKTsKICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcignc3ViR2VvbU9mZnNldHMgdW5kZWZpbmVkJyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3Qgc3ViR2VvbU9mZnNldHNMaW5lcyA9IG5ldyBVaW50MzJBcnJheShzdWJHZW9tQ291bnRzTGluZXMubGVuZ3RoKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdWJHZW9tQ291bnRzTGluZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIHN1Ykdlb21PZmZzZXRzTGluZXNbaV0gPSBvZmZzZXQ7CiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gc3ViR2VvbUNvdW50c0xpbmVzW2ldOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuc3ViR2VvbU9mZnNldHNbJ0xJTkVTJ10gPSBzdWJHZW9tT2Zmc2V0c0xpbmVzOwogICAgICAgICAgICB0aGlzLnN1Ykdlb21Db3VudHNbJ0xJTkVTJ10gPSBzdWJHZW9tQ291bnRzTGluZXM7CiAgICAgICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgICAgICAvLyBQT0lOVFMgc3ViZ2VvbXMKICAgICAgICAgICAgY29uc3QgbnVtUG9pbnRzU3ViR2VvbXMgPSByZWFkZXIubG9hZFVJbnQzMigpOwogICAgICAgICAgICBjb25zdCBzdWJHZW9tT2Zmc2V0c1BvaW50cyA9IG5ldyBVaW50MzJBcnJheShudW1Qb2ludHNTdWJHZW9tcyk7CiAgICAgICAgICAgIGNvbnN0IHN1Ykdlb21Db3VudHNQb2ludHMgPSBuZXcgVWludDhBcnJheShudW1Qb2ludHNTdWJHZW9tcyk7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtUG9pbnRzU3ViR2VvbXM7IGkrKykgewogICAgICAgICAgICAgICAgc3ViR2VvbU9mZnNldHNQb2ludHNbaV0gPSBvZmZzZXQ7CiAgICAgICAgICAgICAgICBzdWJHZW9tQ291bnRzUG9pbnRzW2ldID0gMTsKICAgICAgICAgICAgICAgIG9mZnNldCsrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuc3ViR2VvbU9mZnNldHNbJ1BPSU5UUyddID0gc3ViR2VvbU9mZnNldHNQb2ludHM7CiAgICAgICAgICAgIHRoaXMuc3ViR2VvbUNvdW50c1snUE9JTlRTJ10gPSBzdWJHZW9tQ291bnRzUG9pbnRzOwogICAgICAgICAgICBpZiAoY29udGV4dC52ZXJzaW9uc1snemVhLWVuZ2luZSddLmNvbXBhcmUoWzMsIDExLCAwXSkgPiAwKSB7CiAgICAgICAgICAgICAgICAvLyBQb2ludHMgc3ViLWdlb21zIHdlcmUgbm90IGJlaW5nIGV4cG9ydGVkIGJlZm9yZSB0aGlzIHJlbGVhc2UuCiAgICAgICAgICAgICAgICB0aGlzLm51bVN1Ykdlb21zID0gc3ViR2VvbUNvdW50c01lc2gubGVuZ3RoICsgc3ViR2VvbUNvdW50c0xpbmVzLmxlbmd0aCArIG51bVBvaW50c1N1Ykdlb21zOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdGhpcy5udW1TdWJHZW9tcyA9IHN1Ykdlb21Db3VudHNNZXNoLmxlbmd0aCArIHN1Ykdlb21Db3VudHNMaW5lcy5sZW5ndGg7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgICAgIC8vIE1hdGVyaWFscwogICAgICAgICAgICBjb25zdCBudW1NYXRlcmlhbHMgPSByZWFkZXIubG9hZFVJbnQzMigpOwogICAgICAgICAgICBpZiAobnVtTWF0ZXJpYWxzID4gMCkgewogICAgICAgICAgICAgICAgdGhpcy5tYXRlcmlhbExpYnJhcnlJbmRpY2VzID0gcmVhZGVyLmxvYWRVSW50MzJBcnJheShudW1NYXRlcmlhbHMpOwogICAgICAgICAgICAgICAgdGhpcy5zdWJHZW9tTWF0ZXJpYWxJbmRpY2VzID0gcmVhZGVyLmxvYWRVSW50OEFycmF5KHRoaXMubnVtU3ViR2VvbXMpOwogICAgICAgICAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgICAgICAgICAvLyBNYXRlcmlhbCBHcm91cHMKICAgICAgICAgICAgICAgIGxldCBvZmZzZXQgPSAwOwogICAgICAgICAgICAgICAgbGV0IGN1cnJNYXRlcmlhbCA9IC05OTsKICAgICAgICAgICAgICAgIGxldCBjdXJyTWF0ZXJpYWxTdWJHZW9tID0gbnVsbDsKICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5udW1TdWJHZW9tczsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IGtleTsKICAgICAgICAgICAgICAgICAgICBsZXQgc3ViR2VvbU9mZnNldCA9IDA7CiAgICAgICAgICAgICAgICAgICAgaWYgKGkgPCB0aGlzLnN1Ykdlb21Db3VudHMuVFJJQU5HTEVTLmxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMubWF0ZXJpYWxTdWJHZW9tcy5UUklBTkdMRVMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hdGVyaWFsU3ViR2VvbXMuVFJJQU5HTEVTID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIGtleSA9ICdUUklBTkdMRVMnOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChpIDwgdGhpcy5zdWJHZW9tQ291bnRzLlRSSUFOR0xFUy5sZW5ndGggKyB0aGlzLnN1Ykdlb21Db3VudHMuTElORVMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1Ykdlb21PZmZzZXQgPSB0aGlzLnN1Ykdlb21Db3VudHMuVFJJQU5HTEVTLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgICAga2V5ID0gJ0xJTkVTJzsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLm1hdGVyaWFsU3ViR2VvbXMuTElORVMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hdGVyaWFsU3ViR2VvbXMuTElORVMgPSBbXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1Ykdlb21PZmZzZXQgPSB0aGlzLnN1Ykdlb21Db3VudHMuVFJJQU5HTEVTLmxlbmd0aCArIHRoaXMuc3ViR2VvbUNvdW50cy5MSU5FUy5sZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgIGtleSA9ICdQT0lOVFMnOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMubWF0ZXJpYWxTdWJHZW9tcy5QT0lOVFMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hdGVyaWFsU3ViR2VvbXMuUE9JTlRTID0gW107CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hdGVyaWFsSWQgPSB0aGlzLnN1Ykdlb21NYXRlcmlhbEluZGljZXNbaV07CiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJNYXRlcmlhbCAhPSBtYXRlcmlhbElkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJNYXRlcmlhbCA9IG1hdGVyaWFsSWQ7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vdGU6IHN1Ykdlb21NYXRlcmlhbEluZGljZXMgaXMgVWludDhBcnJheSwgYW5kIDAgbWVhbnMgbm8gY3VzdG9tCiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1hdGVyaWFsIGlzIGFzc2lnbmVkIHRvIHRoZSBzdWJHZW9tLgogICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWJ0cmFjdCAxIHRvIGdldCB0aGUgYWN0dWFsIG1hdGVyaWFsIGlkLgogICAgICAgICAgICAgICAgICAgICAgICBjdXJyTWF0ZXJpYWxTdWJHZW9tID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWxJZDogbWF0ZXJpYWxJZCAtIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogMCwKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yICg7IGkgPCB0aGlzLm51bVN1Ykdlb21zOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyTWF0ZXJpYWwgIT0gdGhpcy5zdWJHZW9tTWF0ZXJpYWxJbmRpY2VzW2ldKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0byB0aGUgZW5kIG9nIHRoaXMgZ2VvbSB0eXBlIChlLmcgLlRSSUFOR0xFUykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0YXJ0IGEgbmV3IHN1Ymdlb20uCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaSAtIHN1Ykdlb21PZmZzZXQgPT0gdGhpcy5zdWJHZW9tQ291bnRzW2tleV0ubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRm9yY2UgdGhlIG1hdGVyaWFsIGluZGV4IHRvIGJlIHJlc2V0IG9uIGxpbmUgMTYyIGFib3ZlLgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJNYXRlcmlhbCA9IC05OTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJNYXRlcmlhbFN1Ykdlb20uY291bnQgKz0gdGhpcy5zdWJHZW9tQ291bnRzW2tleV1baSAtIHN1Ykdlb21PZmZzZXRdOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldCArPSBjdXJyTWF0ZXJpYWxTdWJHZW9tLmNvdW50OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hdGVyaWFsU3ViR2VvbXNba2V5XS5wdXNoKGN1cnJNYXRlcmlhbFN1Ykdlb20pOwogICAgICAgICAgICAgICAgICAgICAgICBpLS07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy8gTm90ZTogb2xkZXIgdmVyc2lvbiBvZiB6Y2FkIGZpbGVzIHdvdWxkIGxpc3QgbWF0ZXJpYWxzIGZvciBUUklBTkdMRVMgYW5kIExJTkVTLAogICAgICAgICAgICAgICAgLy8gYnV0IG5vdCBwb2ludHMsIGxlYXZpbmcgdGhlIHBvaW50cyB1bnJlbmRlcmVkLgogICAgICAgICAgICAgICAgaWYgKHRoaXMuc3ViR2VvbUNvdW50cy5QT0lOVFMubGVuZ3RoID4gMCAmJiAhdGhpcy5tYXRlcmlhbFN1Ykdlb21zLlBPSU5UUykgewogICAgICAgICAgICAgICAgICAgIHRoaXMubWF0ZXJpYWxTdWJHZW9tcy5QT0lOVFMgPSBbCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGVyaWFsSWQ6IC0xLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnQ6IHRoaXMuc3ViR2VvbUNvdW50cy5QT0lOVFMubGVuZ3RoLAogICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIF07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB0aGlzLm1hdGVyaWFsU3ViR2VvbXMgPSB7fTsKICAgICAgICAgICAgICAgIGxldCBvZmZzZXQgPSAwOwogICAgICAgICAgICAgICAgZm9yIChsZXQga2V5IGluIHRoaXMuY291bnRzKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgY291bnQgPSB0aGlzLmNvdW50c1trZXldOwogICAgICAgICAgICAgICAgICAgIGlmIChjb3VudCA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXRlcmlhbFN1Ykdlb21zW2tleV0gPSBbCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWxJZDogLTEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ICs9IGNvdW50OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuZW1pdCgnZ2VvbURhdGFDaGFuZ2VkJywge30pOwogICAgICAgIH0KICAgIH0KCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBndWFyZC1mb3ItaW4gKi8KICAgIC8vIGtleSwgdG9jLCBnZW9tSW5kZXhPZmZzZXQsIGdlb21zUmFuZ2UsIGlzTW9iaWxlRGV2aWNlLCBidWZmZXJTbGljZSwgZ2VuQnVmZmVyc09wdHMsIGNvbnRleHQKICAgIGNvbnN0IHBhcnNlR2VvbXNCaW5hcnkgPSAoZGF0YSwgY2FsbGJhY2spID0+IHsKICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZ3VhcmQtZm9yLWluCiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZGF0YS5jb250ZXh0LnZlcnNpb25zKSB7CiAgICAgICAgICAgIGNvbnN0IHYgPSBkYXRhLmNvbnRleHQudmVyc2lvbnNba2V5XTsKICAgICAgICAgICAgY29uc3QgdmVyc2lvbiA9IG5ldyBWZXJzaW9uKCcnKTsKICAgICAgICAgICAgdmVyc2lvbi5tYWpvciA9IHYubWFqb3I7CiAgICAgICAgICAgIHZlcnNpb24ubWlub3IgPSB2Lm1pbm9yOwogICAgICAgICAgICB2ZXJzaW9uLnBhdGNoID0gdi5wYXRjaDsKICAgICAgICAgICAgdmVyc2lvbi5icmFuY2ggPSB2LmJyYW5jaDsKICAgICAgICAgICAgZGF0YS5jb250ZXh0LnZlcnNpb25zW2tleV0gPSB2ZXJzaW9uOwogICAgICAgIH0KICAgICAgICBjb25zdCBnZW9tRGF0YXMgPSBbXTsKICAgICAgICBjb25zdCBieXRlT2Zmc2V0ID0gZGF0YS5ieXRlT2Zmc2V0OwogICAgICAgIC8vIGNvbnNvbGUubG9nKCdieXRlT2Zmc2V0OicgKyBieXRlT2Zmc2V0LCAnIGdlb21zUmFuZ2U6JywgZGF0YS5nZW9tc1JhbmdlKQogICAgICAgIGNvbnN0IHRyYW5zZmVyYWJsZXMgPSBbXTsKICAgICAgICBmb3IgKGxldCBpID0gZGF0YS5nZW9tc1JhbmdlWzBdOyBpIDwgZGF0YS5nZW9tc1JhbmdlWzFdOyBpKyspIHsKICAgICAgICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEJpblJlYWRlcihkYXRhLmJ1ZmZlclNsaWNlLCBkYXRhLnRvY1tpXSAtIGJ5dGVPZmZzZXQsIGRhdGEuaXNNb2JpbGVEZXZpY2UpOwogICAgICAgICAgICBjb25zdCBjbGFzc05hbWUgPSByZWFkZXIubG9hZFN0cigpOwogICAgICAgICAgICBjb25zdCBwb3MgPSByZWFkZXIucG9zKCk7CiAgICAgICAgICAgIC8vIGNvbnN0IG5hbWUgPSByZWFkZXIubG9hZFN0cigpCiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKAogICAgICAgICAgICAvLyAgIGkgKwogICAgICAgICAgICAvLyAgICAgJzonICsKICAgICAgICAgICAgLy8gICAgIGJ5dGVPZmZzZXQgKwogICAgICAgICAgICAvLyAgICAgJyBjbGFzc05hbWU6JyArCiAgICAgICAgICAgIC8vICAgICBjbGFzc05hbWUgKwogICAgICAgICAgICAvLyAgICAgJyBuYW1lOicgKwogICAgICAgICAgICAvLyAgICAgbmFtZSAvKiArICIgcG9zOiIgKyAoZGF0YS50b2NbaV0gLSBieXRlT2Zmc2V0KSArICIgYnVmZmVyU2xpY2UuYnl0ZUxlbmd0aDoiICsgIGJ1ZmZlclNsaWNlLmJ5dGVMZW5ndGgqLwogICAgICAgICAgICAvLyApCiAgICAgICAgICAgIGxldCBnZW9tOwogICAgICAgICAgICBzd2l0Y2ggKGNsYXNzTmFtZSkgewogICAgICAgICAgICAgICAgY2FzZSAnUG9pbnRzJzoKICAgICAgICAgICAgICAgICAgICBnZW9tID0gbmV3IFBvaW50cygpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAnTGluZXMnOgogICAgICAgICAgICAgICAgICAgIGdlb20gPSBuZXcgTGluZXMoKTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgJ01lc2gnOgogICAgICAgICAgICAgICAgICAgIGdlb20gPSBuZXcgTWVzaCgpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAnQ29tcG91bmRHZW9tJzoKICAgICAgICAgICAgICAgICAgICBnZW9tID0gbmV3IENvbXBvdW5kR2VvbUxvYWRlcigpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIEdlb20gdHlwZTonICsgY2xhc3NOYW1lKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgcmVhZGVyLnNlZWsocG9zKTsgLy8gUmVzZXQgdGhlIHBvaW50ZXIgdG8gdGhlIHN0YXJ0IG9mIHRoZSBpdGVtIGRhdGEuCiAgICAgICAgICAgICAgICBnZW9tLnJlYWRCaW5hcnkocmVhZGVyLCBkYXRhLmNvbnRleHQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0Vycm9yIGxvYWRpbmc6JyArIGdlb20ubmFtZSArICdcbjonICsgZSk7CiAgICAgICAgICAgICAgICBnZW9tRGF0YXMucHVzaCh7fSk7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBnZW9tQnVmZmVycyA9IGdlb20uZ2VuQnVmZmVycyhkYXRhLmdlbkJ1ZmZlcnNPcHRzKTsKICAgICAgICAgICAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgICAgIC8vIFRyYW5zZmVyYWJsZXMKICAgICAgICAgICAgLy8gVHJhbnNmZXIgYWxsIHRoZSBhdHRyaWJ1dGVzIGFuZCBpbmRpY2VzIGJhY2sgdG8gdGhlIG1haW4gdGhyZWFkLgogICAgICAgICAgICBpZiAoZ2VvbUJ1ZmZlcnMuaW5kaWNlcykKICAgICAgICAgICAgICAgIHRyYW5zZmVyYWJsZXMucHVzaChnZW9tQnVmZmVycy5pbmRpY2VzLmJ1ZmZlcik7CiAgICAgICAgICAgIGZvciAoY29uc3QgYXR0ck5hbWUgaW4gZ2VvbUJ1ZmZlcnMuYXR0ckJ1ZmZlcnMpIHsKICAgICAgICAgICAgICAgIC8vIE5vdGU6IFRoZSB0eXBlIHZhbHVlIGFzc2lnbmVkIHRvIHRoZSBhdHRyaWJ1dGUgY2FuCiAgICAgICAgICAgICAgICAvLyBub3QgYmUgdHJhbnNmZXJyZWQgYmFjayB0byB0aGUgbWFpbiB0aHJlYWQuIENvbnZlcnQgdG8KICAgICAgICAgICAgICAgIC8vIHRoZSB0eXBlIG5hbWUgaGVyZSBhbmQgc2VuZCBiYWNrIGFzIGEgc3RyaW5nLgogICAgICAgICAgICAgICAgY29uc3QgYXR0ckRhdGEgPSBnZW9tQnVmZmVycy5hdHRyQnVmZmVyc1thdHRyTmFtZV07CiAgICAgICAgICAgICAgICB0cmFuc2ZlcmFibGVzLnB1c2goYXR0ckRhdGEudmFsdWVzLmJ1ZmZlcik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gQ29tcG9vdW5kIEdlb20gYnVmZmVycwogICAgICAgICAgICBpZiAoZ2VvbUJ1ZmZlcnMubWF0ZXJpYWxMaWJyYXJ5SW5kaWNlcykgewogICAgICAgICAgICAgICAgdHJhbnNmZXJhYmxlcy5wdXNoKGdlb21CdWZmZXJzLm1hdGVyaWFsTGlicmFyeUluZGljZXMuYnVmZmVyKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoZ2VvbUJ1ZmZlcnMuc3ViR2VvbU1hdGVyaWFsSW5kaWNlcykgewogICAgICAgICAgICAgICAgdHJhbnNmZXJhYmxlcy5wdXNoKGdlb21CdWZmZXJzLnN1Ykdlb21NYXRlcmlhbEluZGljZXMuYnVmZmVyKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoZ2VvbUJ1ZmZlcnMuc3ViR2VvbU9mZnNldHMpIHsKICAgICAgICAgICAgICAgIGZvciAobGV0IGtleSBpbiBnZW9tQnVmZmVycy5zdWJHZW9tT2Zmc2V0cykgewogICAgICAgICAgICAgICAgICAgIHRyYW5zZmVyYWJsZXMucHVzaChnZW9tQnVmZmVycy5zdWJHZW9tT2Zmc2V0c1trZXldLmJ1ZmZlcik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gaWYgKGdlb21CdWZmZXJzLnZlcnRleE5laWdoYm9ycykgewogICAgICAgICAgICAvLyAgIHRyYW5zZmVyYWJsZXMucHVzaChnZW9tQnVmZmVycy52ZXJ0ZXhOZWlnaGJvcnMuYnVmZmVyKQogICAgICAgICAgICAvLyB9CiAgICAgICAgICAgIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgICAgICBnZW9tRGF0YXMucHVzaCh7CiAgICAgICAgICAgICAgICBuYW1lOiBnZW9tLm5hbWUsCiAgICAgICAgICAgICAgICB0eXBlOiBjbGFzc05hbWUsCiAgICAgICAgICAgICAgICBnZW9tQnVmZmVycywKICAgICAgICAgICAgICAgIGJib3g6IGdlb20uZ2V0Qm91bmRpbmdCb3goKSwKICAgICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIGNhbGxiYWNrKHsKICAgICAgICAgICAgdGFza0lkOiBkYXRhLnRhc2tJZCwKICAgICAgICAgICAgZ2VvbUxpYnJhcnlJZDogZGF0YS5nZW9tTGlicmFyeUlkLAogICAgICAgICAgICBnZW9tRmlsZUlEOiBkYXRhLmdlb21GaWxlSUQsCiAgICAgICAgICAgIGdlb21JbmRleE9mZnNldDogZGF0YS5nZW9tSW5kZXhPZmZzZXQsCiAgICAgICAgICAgIGdlb21zUmFuZ2U6IGRhdGEuZ2VvbXNSYW5nZSwKICAgICAgICAgICAgZ2VvbURhdGFzLAogICAgICAgIH0sIHRyYW5zZmVyYWJsZXMpOwogICAgfTsKCiAgICBjb25zdCBoYW5kbGVNZXNzYWdlID0gZnVuY3Rpb24gKHNyY0RhdGEsIHBvc3RNZXNzYWdlKSB7CiAgICAgIHBhcnNlR2VvbXNCaW5hcnkoc3JjRGF0YSwgKHJlc3VsdERhdGEsIHRyYW5zZmVyYWJsZXMpID0+IHsKICAgICAgICBwb3N0TWVzc2FnZShyZXN1bHREYXRhLCB0cmFuc2ZlcmFibGVzKTsKICAgICAgfSk7CiAgICB9OwoKICAgIC8vIENoZWNrIHRvIHNlZSBpZiB3ZSBhcmUgcnVubmluZyBpbiB0aGUgV29ya2VyIGJlZm9yZSBhc3NpZ25pbmcgb25tZXNzYWdlCiAgICBpZiAoZ2xvYmFsVGhpcy5kb2N1bWVudCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGdsb2JhbFRoaXMub25tZXNzYWdlID0gZnVuY3Rpb24gKGV2ZW50KSB7CiAgICAgICAgaWYgKCFldmVudC5kYXRhKSB7CiAgICAgICAgICAvLyBOb3RlOiB3ZSBzZWUgdGhpcyBvY2N1ciB3aGVuIGxvYWRpbmcgb25lIGxhcmdlIGFzc2V0IG1hbnkgdGltZXMuCiAgICAgICAgICAvLyBMaWtlIHdoZW4gbG9hZGluZyB0aGUgcG9ydGFmaWwuCiAgICAgICAgICAvLyBJdCBtYXkgYmUgZHVlIHRvIG1lbW9yeSBpc3N1ZXMsIGJ1dCBpdHMgbm90IGNsZWFyLgogICAgICAgICAgY29uc29sZS53YXJuKCdHZW9tTGlicmFyeSB3b3JrZXIucG9zdE1lc3NhZ2UgZmFpbGVkLiBkYXRhIHdhcyBsb3N0IG9uIHRoZSB3YXkgdG8gdGhlIHdlYiB3b3JrZXIuJyk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgLy8gT3VyIHdvcmtlciBnZXRzIHRyaWdnZXJlZAogICAgICAgIGlmICghZXZlbnQuZGF0YS5jb250ZXh0KSB7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgaGFuZGxlTWVzc2FnZShldmVudC5kYXRhLCBzZWxmLnBvc3RNZXNzYWdlKTsKICAgICAgfTsKICAgIH0KCiAgICBleHBvcnRzLmhhbmRsZU1lc3NhZ2UgPSBoYW5kbGVNZXNzYWdlOwoKICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7CgogICAgcmV0dXJuIGV4cG9ydHM7Cgp9KSh7fSk7Cgo=",null,!1);class GeomParserMainThread extends EventEmitter{constructor(){super()}addTask(A,g){return new Promise((g=>{handleMessage(A,(A=>{A.eventName?this.emit(A.eventName,A):g(A)}))}))}}class GeomParserWorkerPool extends WorkerPool{constructor(){super(!0),this.poolSize=Math.max(1,Math.floor(.5*SystemDesc.hardwareConcurrency))}constructWorker(){const A=new WorkerFactory$1;return Promise.resolve(A)}}let geomParserWorkerPool;geomParserWorkerPool="Node"==SystemDesc.OS?new GeomParserMainThread:new GeomParserWorkerPool;let numGeomLibraries=0;class GeomLibrary extends EventEmitter{assetItem;listenerIDs={};streamInfos={};genBuffersOpts={};loadContext;numGeoms=-1;numGeomFiles=1;geoms=[];basePath="";loadedCount=0;constructor(A){super(),this.assetItem=A,numGeomLibraries++}isLoaded(){return this.loaded}get loaded(){return-1==this.numGeoms||this.loadedCount==this.numGeoms}loadGeomFile(A,g=!1){return g&&resourceLoader.incrementWorkload(1),new Promise((I=>{const C=this.basePath+A+".zgeoms";resourceLoader.loadFile("archive",C,!1).then((C=>{const e=C[Object.keys(C)[0]],i=this.on("streamFileParsed",(C=>{C.geomFileID==A&&(g&&resourceLoader.incrementWorkDone(1),this.off("streamFileParsed",i),I())}));this.readBinaryBuffer(A,e.buffer,this.loadContext)}))}))}loadGeomFilesStream(A,g,I){this.numGeomFiles=A.numGeomFiles?A.numGeomFiles:A.numGeomsPerFile.length,resourceLoader.incrementWorkload(this.numGeomFiles),this.numGeoms=A.numGeoms,this.basePath=g,this.loadContext=I;for(let A=0;A<this.numGeomFiles;A++)this.loadGeomFile(A,!1).finally((()=>resourceLoader.incrementWorkDone()))}setGenBufferOption(A,g){this.genBuffersOpts[A]=g}setNumGeoms(A){this.numGeoms=A}getNumGeoms(){return this.numGeoms}getGeom(A){return A>=this.geoms.length?null:this.geoms[A]}setGeom(A,g){g.libraryIndex=A,this.geoms[A]=g}readBinaryBuffer(A,g,I){const C=new BinReader(g,0,SystemDesc.isMobileDevice),e=C.loadUInt32(),i=C.loadUInt32();if(this.streamInfos[A]={total:e,done:0},0==e){const g=new StreamFileParsedEvent(A,0);return void this.emit("streamFileParsed",g)}-1==this.numGeoms&&(this.numGeoms=e);const t=C.loadUInt32Array(e);if(numGeomLibraries>1||this.numGeomFiles>1){const o=[0,e],a=0;geomParserWorkerPool.addTask({geomFileID:A,toc:t,byteOffset:a,geomIndexOffset:i,geomsRange:o,isMobileDevice:C.isMobileDevice,bufferSlice:g,genBuffersOpts:this.genBuffersOpts,context:{versions:I.versions}},[g]).then((A=>{this.receiveGeomDatas(A)}))}else{const o=2e6;let a=0;for(;a<e;){const B=t[a];let s,l,n=0,d=a;for(;d<e&&n<o;)d++,n=t[d]-B;d>=e?(s=[a,e],l=g.byteLength):(s=[a,d],l=t[s[1]]);const r=0==a&&d==e,c=r?0:t[s[0]],h=r?g:g.slice(B,l);a=d,geomParserWorkerPool.addTask({geomFileID:A,toc:t,byteOffset:c,geomIndexOffset:i,geomsRange:s,isMobileDevice:C.isMobileDevice,bufferSlice:h,genBuffersOpts:this.genBuffersOpts,context:{versions:I.versions}},[h]).then((A=>{this.receiveGeomDatas(A)}))}}}receiveGeomDatas(A){const{geomFileID:g,geomDatas:I,geomIndexOffset:C,geomsRange:e}=A,i=C+e[0],t=[i,C+e[1]];for(let A=0;A<I.length;A++){const g=I[A];if(!g.type)continue;let C;switch(g.type){case"Points":C=new PointsProxy(g);break;case"Lines":C=new LinesProxy(g);break;case"Mesh":case"Plane":case"Sphere":case"Cone":C=new MeshProxy(g);break;case"CompoundGeom":C=new CompoundGeom(g,this.assetItem.getMaterialLibrary());break;default:throw new Error("Unsupported Geom type:")}this.setGeom(i+A,C)}const o=new RangeLoadedEvent(t);this.emit("rangeLoaded",o);const a=t[1]-t[0],B=this.streamInfos[g];if(B.done+=a,B.done==B.total){const A=new StreamFileParsedEvent(g,B.done);this.emit("streamFileParsed",A),resourceLoader.emit("streamGeomsLoaded",A)}return this.loadedCount+=a,this.loadedCount==this.numGeoms&&this.emit("loaded"),this.loadedCount==this.numGeoms}toJSON(){return{numGeoms:this.geoms.length}}toString(){return JSON.stringify(this.toJSON(),null,2)}loadMetadata(A,g){const I=new BinReader(A.buffer,0,SystemDesc.isMobileDevice),C=I.loadUInt32Array();for(let A=0;A<C.length;A++)try{const e=this.geoms[A];e||console.warn("Error loading metadata for geom that was not yet loaded: ",A),e instanceof CompoundGeom&&(I.seek(C[A]),e.loadMetadata(I,g))}catch(g){console.warn("Error loading geom metadata: ",A)}}}class MaterialLibrary extends BaseItem{assetItem;images={};materials=[];__materialsMap={};constructor(A){super(),this.assetItem=A}clear(){this.images={},this.materials=[],this.__materialsMap={}}getPath(){return this.assetItem instanceof BaseItem?[...this.assetItem.getPath(),"MaterialLibrary"]:["MaterialLibrary"]}resolvePath(A,g=0){0==g&&("."!=A[0]&&"MaterialLibrary"!=A[0]||g++);const I=this.getMaterial(A[g]);if(I)return g<A.length?I.resolvePath(A,g+1):I;throw new Error(`Unable to resolve path : [${A.toString()}] after: 'MaterialLibrary' \nNo material called : "${A[g]}"`)}getNumMaterials(){return this.materials.length}getMaterials(){return this.materials}getMaterialNames(){const A=[];return this.materials.forEach((g=>{A.push(g.getName())})),A}hasMaterial(A){return A in this.__materialsMap}addMaterial(A){A.setOwner(this),A.libraryIndex=this.materials.length,this.__materialsMap[A.getName()]=this.materials.length,this.materials.push(A)}getMaterial(A){if("string"==typeof A){const g=this.__materialsMap[A];return null==g?null:this.materials[g]}if(Number.isFinite(A))return this.materials[A]}hasImage(A){return A in this.images}addImage(A){A.setOwner(this),this.images[A.getName()]=A}getImage(A,g=!0){const I=this.images[A];if(!I&&g)throw new Error("Image:"+A+" not found in library:"+this.getImageNames());return I}getImageNames(){const A=[];for(const g in this.images)A.push(g);return A}load(A){const g=new XMLHttpRequest;g.open("GET",A,!0),g.ontimeout=()=>{throw new Error("The request for "+A+" timed out.")},g.onload=()=>{4===g.readyState&&(200===g.status?this.fromJSON(JSON.parse(g.responseText)):console.warn(g.statusText))},g.send(null)}toJSON(A={}){const g={numMaterials:this.getNumMaterials(),images:{},materials:[]};for(const I in this.images)g.images[I]=this.images[I].toJSON(A);for(const I of this.materials)g.materials.push(I.toJSON(A));return g}fromJSON(A,g={}){for(const g in A.textures){const I=new FileImage(g);I.fromJSON(A.textures[g]),this.images[g]=I}for(const g in A.materials){const I=new Material(g);I.fromJSON(A.materials[g]),this.addMaterial(I)}}readBinary(A,g){A.loadStr();const I=A.loadUInt32();for(let C=0;C<I;C++){const I=A.loadStr(),C=Registry.constructClass(I);C.readBinary(A,g),this.images[C.getName()]=C}const C=A.loadUInt32();if(C>0){const I=A.loadUInt32Array(C);for(let e=0;e<C;e++){let C;switch(A.loadStr()){case"StandardMaterial":case"TransparentMaterial":case"StandardSurfaceShader":C=Registry.constructClass("StandardSurfaceMaterial");break;case"SimpleSurfaceShader":case"SimpleSurfaceMaterial":C=Registry.constructClass("SimpleSurfaceMaterial");break;case"PointsShader":case"PointsMaterial":C=Registry.constructClass("PointsMaterial");break;case"FatPointsShader":case"FatPointsMaterial":C=Registry.constructClass("FatPointsMaterial");break;case"LinesShader":case"LinesMaterial":C=Registry.constructClass("LinesMaterial");break;default:C=new Material("")}A.seek(I[e]),C.readBinary(A,g),this.materials[e]=C,C.libraryIndex=e,this.__materialsMap[C.getName()]=e}}this.emit("loaded")}toString(){return JSON.stringify(this.toJSON(),null,2)}}class AssetLoadContext extends EventEmitter{units="meters";versions={};sdk="";url="";folder="";camera=null;assetItem=null;resources=null;xrefs={};xrefLoadCallback=null;lazyLoading;postLoadCallbacks=[];promisses=[];urlStack=[];assetStack=[];addGeomToLayer;constructor(A){super(),A&&(this.units=A.units,this.sdk=A.sdk,this.camera=A.camera,this.resources=A.resources,this.xrefs=A.xrefs,this.xrefLoadCallback=A.xrefLoadCallback,this.urlStack=[...A.urlStack],this.assetStack=[...A.assetStack])}addPromise(A){this.promisses.push(A)}resolvePath(A,g,I){try{const I=this.assetItem.resolvePath(A);g(I)}catch(C){this.postLoadCallbacks.push((()=>{try{const I=this.assetItem.resolvePath(A);g(I)}catch(A){if(!I)throw new Error(A.message);I(A)}}))}}addPLCB(A){this.postLoadCallbacks.push(A)}resolvePLCBs(){for(const A of this.postLoadCallbacks)A();this.postLoadCallbacks=[]}clone(){return new AssetLoadContext(this)}}class BaseGroup extends TreeItem{itemsParam=new ItemSetParameter("Items",(A=>A instanceof TreeItem));itemsEventHandlers=[];searchRoot;constructor(A){super(A),this.addParameter(this.itemsParam),this.itemsParam.on("itemAdded",(A=>{this.bindItem(A.item,A.index),this.emit("itemAdded",A)})),this.itemsParam.on("itemRemoved",(A=>{this.unbindItem(A.item,A.index),this.emit("itemRemoved",A)}))}updateVisibility(){if(super.updateVisibility()){const A=this.isVisible();return Array.from(this.itemsParam.value).forEach((g=>{g.propagateVisibility(A?1:-1)})),!0}return!1}updateOpacity(){super.updateOpacity(),Array.from(this.itemsParam.value).forEach((A=>{A.setInheritedOpacity(this,this.opacity)}))}cleanBoundingBox(){const A=super.cleanBoundingBox();return Array.from(this.itemsParam.value).forEach((g=>{if(g.isVisible()&&g.isPickable()){const I=g.boundingBoxParam.value;I&&A.addBox3(I)}})),A}addHighlight(A,g,I=!0){super.addHighlight(A,g,I),I&&Array.from(this.itemsParam.value).forEach((I=>{I.addHighlight(A,g,!0)}))}removeHighlight(A,g=!0){super.removeHighlight(A,g),g&&Array.from(this.itemsParam.value).forEach((g=>{g.removeHighlight(A,!0)}))}setSearchRoot(A){this.searchRoot=A}setOwner(A){if(A&&!(A instanceof TreeItem))throw new Error("cannot setOwner");this.searchRoot&&this.searchRoot!=this.getOwner()||(this.searchRoot=A),super.setOwner(A)}bindItem(A,g){const I={};I.pointerDown=A.on("pointerDown",(A=>{this.onPointerDown(A)})),I.pointerUp=A.on("pointerUp",(A=>{this.onPointerUp(A)})),I.pointerMove=A.on("pointerMove",(A=>{this.onPointerMove(A)})),I.pointerEnter=A.on("pointerEnter",(A=>{this.onPointerEnter(A)})),I.pointerLeave=A.on("pointerLeave",(A=>{this.onPointerLeave(A)})),I.pointerClick=A.on("pointerClick",(A=>{this.onPointerClick(A)})),I.pointerDoubleClick=A.on("pointerDoubleClick",(A=>{this.onPointerDoubleClick(A)})),I.pointerLongPress=A.on("pointerLongPress",(A=>{this.onPointerLongPress(A)})),I["BoundingBox.valueChanged"]=A.boundingBoxParam.on("valueChanged",(()=>{this.setBoundingBoxDirty()})),this.isVisible()||A.propagateVisibility(-1),this.highlights.forEach((g=>{A.addHighlight(g,this.highlightMapping[g],!0)})),this.itemsEventHandlers.splice(g,0,I)}unbindItem(A,g){const I=this.itemsEventHandlers[g];for(let g in I){const C=g.split(".");if(C.length>1){const e=A.getParameter(C[0]);e&&e.off(C[1],I[g])}else A.off(g,I[g])}this.isVisible()||A.propagateVisibility(1),this.highlights.forEach((g=>{A.removeHighlight(g,!0)})),this.setBoundingBoxDirty(),this.itemsEventHandlers.splice(g,1)}addItem(A,g=!0){A?this.itemsParam.addItem(A,g):console.warn("Error adding item to group. Item is null")}removeItem(A,g=!0){const I=this.itemsParam.value;if(!I)return;const C=Array.from(I).indexOf(A);-1!=C&&this.itemsParam.removeItem(C,g)}clearItems(A=!0){const g=this.itemsParam.value;if(!g)return;const I=Array.from(g);for(let A=I.length-1;A>=0;A--)this.unbindItem(I[A],A);this.itemsParam.clearItems(A)}getItems(){return this.itemsParam.value}setItems(A){this.clearItems(!1),this.itemsParam.setItems(A)}}class SelectionSet extends BaseGroup{#o=!1;highlightedParam=new BooleanParameter("Highlighted",!1);highlightColorParam=new ColorParameter("HighlightColor",new Color(.5,.5,1));highlightFillParam=new NumberParameter("HighlightFill",0,[0,1]);constructor(A){super(A),this.addParameter(this.highlightedParam),this.highlightedParam.on("valueChanged",(()=>{this.updateHighlight()})),this.addParameter(this.highlightColorParam),this.highlightColorParam.on("valueChanged",(()=>{this.updateHighlight()})),this.addParameter(this.highlightFillParam),this.highlightFillParam.on("valueChanged",(()=>{this.updateHighlight()}))}updateHighlight(){this.#o||(this.#o=!0,setTimeout((()=>{this.#a(),this.#o=!1}),0))}#a(){let A,g=this.highlightedParam.value;g&&(A=this.highlightColorParam.value.clone(),A.a=this.highlightFillParam.value);const I="groupItemHighlight"+this.getId();Array.from(this.itemsParam.value).forEach((C=>{g?C.addHighlight(I,A,!0):C.removeHighlight(I,!0)}))}setSelected(A){super.setSelected(A),this.updateHighlight()}bindItem(A,g){if(super.bindItem(A,g),this.highlightedParam.value){const g=this.highlightColorParam.value;g.a=this.highlightFillParam.value,A.addHighlight("groupItemHighlight"+this.getId(),g,!0)}}unbindItem(A,g){super.unbindItem(A,g),this.highlightedParam.value&&A.removeHighlight("groupItemHighlight"+this.getId(),!0)}clone(A){const g=new SelectionSet(this.name+" clone");return g.copyFrom(this,A),g}}Registry.register("SelectionSet",SelectionSet);class GroupGlobalXfoOperator extends CalcGlobalXfoOperator{offsetXfo=new Xfo;bindXfo=new Xfo;invBindXfo=new Xfo;#B=!1;groupTransformXfo=new XfoOperatorOutput("GroupTransformXfo");constructor(A,g,I){super(A,g),this.groupTransformXfo.setParam(I),this.addOutput(this.groupTransformXfo)}set editingPivot(A){this.#B=A,this.setDirty()}get editingPivot(){return this.#B}setBindXfo(A){this.bindXfo=A,this.invBindXfo=A.inverse(),this.setDirty()}backPropagateValue(A){let g;if(g=this.parentGlobal.isConnected()?this.parentGlobal.getValue():new Xfo,this.editingPivot)this.bindXfo=A,this.invBindXfo=this.bindXfo.inverse(),this.offsetXfo=g.inverse().multiply(this.bindXfo),this.setDirty();else{const I=g.multiply(this.offsetXfo);this.localXfo.setValue(I.inverse().multiply(A))}}evaluate(){let A;if(this.parentGlobal.isConnected()){A=this.parentGlobal.getValue().multiply(this.offsetXfo)}else A=this.offsetXfo;if(this.editingPivot){const g=A;this.globalXfo.setClean(g);const I=g.multiply(this.localXfo.getValue()).multiply(this.invBindXfo);this.groupTransformXfo.setClean(I)}else{const g=A.multiply(this.localXfo.getValue());this.globalXfo.setClean(g);const I=g.multiply(this.invBindXfo);this.groupTransformXfo.setClean(I)}}}class GroupMemberXfoOperator extends Operator{#s;groupTransformXfo=new XfoOperatorInput("GroupTransformXfo");memberGlobalXfo=new XfoOperatorOutput("MemberGlobalXfo",OperatorOutputMode.OP_READ_WRITE);constructor(A,g){super(),this.groupTransformXfo.setParam(A),this.memberGlobalXfo.setParam(g),this.addInput(this.groupTransformXfo),this.addOutput(this.memberGlobalXfo),this.#s=!0}disable(){this.#s=!1,this.setDirty()}enable(){this.#s=!0,this.setDirty()}evaluate(){const A=this.memberGlobalXfo.getValue();if(this.#s){const g=this.groupTransformXfo.getValue();this.memberGlobalXfo.setClean(g.multiply(A))}else this.memberGlobalXfo.setClean(A)}backPropagateValue(A){if(this.#s){return this.groupTransformXfo.getValue().inverse().multiply(A)}return A}}const GROUP_XFO_MODES={disabled:0,manual:1,first:2,average:3,globalOri:4};class KinematicGroup extends BaseGroup{calculatingGroupXfo;memberXfoOps;#o=!1;initialXfoModeParam=new MultiChoiceParameter("InitialXfoMode",GROUP_XFO_MODES.average,["manual","first","average","global"]);groupTransformParam=new XfoParameter("GroupTransform",new Xfo);highlightedParam=new BooleanParameter("Highlighted",!1);highlightColorParam=new ColorParameter("HighlightColor",new Color(1,1,0));highlightFillParam=new NumberParameter("HighlightFill",0,[0,1]);constructor(A=""){super(A),this.calculatingGroupXfo=!1,this.memberXfoOps=[],this.addParameter(this.initialXfoModeParam),this.initialXfoModeParam.on("valueChanged",(()=>{this.calcGroupXfo()})),this.addParameter(this.groupTransformParam),this.addParameter(this.highlightedParam),this.highlightedParam.on("valueChanged",(()=>{this.#l()})),this.addParameter(this.highlightColorParam),this.highlightColorParam.on("valueChanged",(()=>{this.#l()})),this.addParameter(this.highlightFillParam),this.highlightFillParam.on("valueChanged",(()=>{this.#l()})),this.globalXfoOp=new GroupGlobalXfoOperator(this.globalXfoParam,this.localXfoParam,this.groupTransformParam)}static get INITIAL_XFO_MODES(){return GROUP_XFO_MODES}get bindXfo(){return this.globalXfoOp.bindXfo}#l(){this.#o||(this.#o=!0,setTimeout((()=>{this.#a(),this.#o=!1}),0))}#a(){let A,g=this.highlightedParam.value;g&&(A=this.highlightColorParam.value.clone(),A.a=this.highlightFillParam.value);const I="groupItemHighlight"+this.getId();Array.from(this.itemsParam.value).forEach((C=>{g?C.addHighlight(I,A,!0):C.removeHighlight(I,!0)}))}calcGroupXfo(){const A=Array.from(this.itemsParam.value);if(0==A.length)return;this.editingPivot=!0;const g=this.initialXfoModeParam.value;let I;if(g==GROUP_XFO_MODES.manual)I=this.globalXfoParam.value;else if(g==GROUP_XFO_MODES.first&&A[0])I=A[0].globalXfoParam.value;else if(g==GROUP_XFO_MODES.average){I=new Xfo,I.ori.set(0,0,0,0);let g=0;A.forEach(((A,C)=>{const e=A.globalXfoParam.value;I.tr.addInPlace(e.tr),0==C&&(I.ori=e.ori),g++})),I.tr.scaleInPlace(1/g),I.ori.normalizeInPlace()}else{if(g!=GROUP_XFO_MODES.globalOri)throw new Error("Invalid GROUP_XFO_MODES.");{I=new Xfo;let g=0;A.forEach(((A,C)=>{const e=A.globalXfoParam.value;I.tr.addInPlace(e.tr),g++})),I.tr.scaleInPlace(1/g)}}this.globalXfoParam.value=I,this.editingPivot=!1}get editingPivot(){return this.globalXfoOp.editingPivot}set editingPivot(A){this.globalXfoOp.editingPivot=A}bindItem(A,g){super.bindItem(A,g);const I=A.globalXfoParam,C=new GroupMemberXfoOperator(this.groupTransformParam,I);if(this.memberXfoOps.splice(g,0,C),this.highlightedParam.value){const g=this.highlightColorParam.value;g.a=this.highlightFillParam.value,A.addHighlight("groupItemHighlight"+this.getId(),g,!0)}}unbindItem(A,g){super.unbindItem(A,g),this.memberXfoOps[g].detach(),this.memberXfoOps.splice(g,1),this.highlightedParam.value&&A.removeHighlight("groupItemHighlight"+this.getId(),!0)}addItem(A,g=!0){super.addItem(A,g),g&&this.calcGroupXfo()}removeItem(A,g=!0){super.removeItem(A,g),g&&this.calcGroupXfo()}setItems(A){super.setItems(A),this.calcGroupXfo()}clearItems(A=!0){super.clearItems(A),this.memberXfoOps=[],A&&this.calcGroupXfo()}clone(A){const g=new KinematicGroup;return g.copyFrom(this,A),g}toJSON(A){const g=super.toJSON(A);g.bindXfo=this.globalXfoOp.bindXfo.toJSON();const I=this.globalXfoOp;return g.offsetXfo=I.offsetXfo.toJSON(),g}fromJSON(A,g){super.fromJSON(A,g);const I=new Xfo;I.fromJSON(A.bindXfo);const C=this.globalXfoOp;C.setBindXfo(I),A.offsetXfo&&C.offsetXfo.fromJSON(A.offsetXfo)}}Registry.register("KinematicGroup",KinematicGroup);class MaterialGroup extends BaseGroup{materialParam=new MaterialParameter("Material");__backupMaterials={};constructor(A){super(A),this.addParameter(this.materialParam),this.materialParam.on("valueChanged",(()=>{this.updateMaterial()}))}updateHighlight(){this.updateHighlightHelper()}updateHighlightHelper(){let A,g=!1;this.isSelected()&&(A=this.getHighlight(),g=!0,A.a=.2);const I="kinematicGroupItemHighlight"+this.getId();Array.from(this.itemsParam.value).forEach((C=>{g?C.addHighlight(I,A,!0):C.removeHighlight(I,!0)}))}setSelected(A){super.setSelected(A),this.updateHighlight()}updateOpacity(){super.updateOpacity(),Array.from(this.itemsParam.value).forEach((A=>{A.opacityParam.value=this.opacity}))}updateMaterial(){this.updateMaterialHelper()}updateMaterialHelper(){const A=this.materialParam.value;Array.from(this.itemsParam.value).forEach((g=>{g.traverse((g=>{if(g instanceof BaseGeomItem){const I=g.materialParam;if(A){const g=I.value;g==A||g&&"LinesShader"==g.getShaderName()||(this.__backupMaterials[I.getId()]=g,I.value=A)}else this.__backupMaterials[I.getId()]&&(I.value=this.__backupMaterials[I.getId()])}}))}))}bindItem(A,g){if(super.bindItem(A,g),this.isSelected()){const g=this.getHighlight();g.a=.2;const I="materialGroupItemHighlight"+this.getId();A.addHighlight(I,g,!0)}const I=this.materialParam.value;I&&A.traverse((A=>{if(A instanceof BaseGeomItem){const g=A.materialParam;if(I){const A=g.value;A==I||A&&"LinesShader"==A.getShaderName()||(this.__backupMaterials[g.getId()]=A,g.value=I)}}}),!0),A.opacityParam.value=this.opacity}unbindItem(A,g){if(super.unbindItem(A,g),this.isSelected()){const g="materialGroupItemHighlight"+this.getId();A.removeHighlight(g,!0)}}clone(A){const g=new MaterialGroup(this.name+"clone");return g.copyFrom(this,A),g}}Registry.register("MaterialGroup",MaterialGroup);class CuttingPlaneOperator extends Operator{groupGlobalXfo=new XfoOperatorInput("GroupGlobalXfo");cuttingPlane=new Vec4OperatorOutput("CuttingPlane");constructor(A,g){super(),this.groupGlobalXfo.setParam(A),this.cuttingPlane.setParam(g),this.addInput(this.groupGlobalXfo),this.addOutput(this.cuttingPlane)}evaluate(){const A=this.groupGlobalXfo.getValue(),g=A.ori.getZaxis(),I=A.tr.dot(g);this.cuttingPlane.setClean(new Vec4(g.x,g.y,g.z,-I))}}class CuttingPlane extends BaseGroup{cutPlaneOp;cutAwayEnabledParam=new BooleanParameter("CutAwayEnabled",!1);cutPlaneParam=new Vec4Parameter("CutPlane",new Vec4(1,0,0));constructor(A=""){super(A),this.addParameter(this.cutAwayEnabledParam),this.addParameter(this.cutPlaneParam),this.cutPlaneOp=new CuttingPlaneOperator(this.globalXfoParam,this.cutPlaneParam),this.cutAwayEnabledParam.on("valueChanged",(A=>{this.updateCutaway(A)})),this.cutPlaneParam.on("valueChanged",(A=>{this.updateCutaway(A)}));const g=new Material("plane","FlatSurfaceShader");g.getParameter("BaseColor").value=new Color(1,1,1,.2);const I=new GeomItem("PlaneGeom",new Plane(1,1),g);this.addChild(I);const C=new Material("border","LinesShader");C.getParameter("BaseColor").value=new Color(1,0,0,1);const e=new GeomItem("BorderGeom",new Rect(1,1),C);this.addChild(e)}updateCutaway(A){const g=this.cutAwayEnabledParam.value,I=this.cutPlaneParam.value,C=I.xyz,e=I.w;A instanceof BaseGeomItem?(A.setCutawayEnabled(g),A.setCutVector(C),A.setCutDist(e)):Array.from(this.itemsParam.value).forEach((A=>{A.traverse((A=>{A instanceof BaseGeomItem&&(A.setCutawayEnabled(g),A.setCutVector(C),A.setCutDist(e))}),!0)}))}bindItem(A,g){this.cutAwayEnabledParam.value&&this.updateCutaway(A)}unbindItem(A,g){super.unbindItem(A,g),A.traverse((A=>{A instanceof BaseGeomItem&&A.setCutawayEnabled(!1)}),!0)}clone(A){const g=new CuttingPlane;return g.copyFrom(this,A),g}}Registry.register("CuttingPlane",CuttingPlane);const getUnitsFactor=A=>{switch(A.toLowerCase()){case"millimeters":return.001;case"centimeters":return.01;case"decimeters":return.1;case"meters":return 1;case"kilometers":return 1e3;case"inches":return.0254;case"feet":return.3048;case"miles":return 1609.34}return 1};class AssetItem extends TreeItem{geomLibrary=new GeomLibrary(this);materialLibrary=new MaterialLibrary(this);loaded=!1;engineDataVersion;unitsScale=1;units="meters";constructor(A=""){super(A)}load(A){return Promise.reject(`This method is not implemented for this Asset Item: ${A}`)}isLoaded(){return this.loaded}getGeometryLibrary(){return this.geomLibrary}getMaterialLibrary(){return this.materialLibrary}readBinary(A,g){g.assetItem=this,g.units||(g.units="meters"),g.versions["zea-engine"]||(g.versions["zea-engine"]=new Version(A.loadStr())),this.engineDataVersion=g.versions["zea-engine"];const I=()=>{if(this.units=A.loadStr(),this.addParameter(new StringParameter("FileUnits",this.units)),this.units!=g.units){const A=getUnitsFactor(this.units),I=getUnitsFactor(g.units);this.unitsScale=A/I}g.units=this.units;const I=this.localXfoParam,C=I.value;C.sc.scaleInPlace(this.unitsScale),I.value=C};let C;g.versions["zea-engine"].compare([0,0,6])>0&&I();const e={};g.addGeomToLayer=(A,g)=>{if(!e[g]){C||(C=new TreeItem("Layers"),this.addChild(C,!1));const A=new BaseGroup(g);C.addChild(A,!1),e[g]=A}e[g].addItem(A)},this.materialLibrary.readBinary(A,g),super.readBinary(A,g),g.versions["zea-engine"].compare([0,0,5])>=0&&g.versions["zea-engine"].compare([0,0,7])<0&&I(),g.resolvePLCBs(),this.loaded=!0}haveGeomsLoaded(){if(!this.geomLibrary.isLoaded())return!1;let A=!0;return this.traverse((g=>g instanceof AssetItem?(g.haveGeomsLoaded()||(A=!1),!1):A),!1),A}toJSON(A={}){A.makeRelative=A=>{const g=this.getPath(),I=A.slice(0,g.length);for(let C=0;C<I.length-1;C++)if(I[C]!=g[C])return console.warn("Param Path is not relative to the asset. May not be able to be resolved at load time:"+A),A;const C=A.slice(g.length-1);return C[0]=".",C},A.assetItem=this;const g=super.toJSON(A);return g.materialLibrary=this.materialLibrary.toJSON(),g}fromJSON(A,g=new AssetLoadContext){g.assetItem=this,this.materialLibrary.fromJSON(A.materialLibrary,g),super.fromJSON(A,g),g.resolvePLCBs()}clone(A){const g=new AssetItem;return g.copyFrom(this,A),g}copyFrom(A,g){if(!(A instanceof AssetItem))throw new Error("cannot copy from src");this.geomLibrary=A.geomLibrary,this.materialLibrary=A.materialLibrary,this.units=A.units,this.loaded=A.loaded,super.copyFrom(A,g),A.loaded?(this.emit("loaded"),A.haveGeomsLoaded()?this.emit("geomsLoaded"):A.once("geomsLoaded",(()=>this.emit("geomsLoaded")))):A.once("loaded",(()=>{this.units=A.units;const I=A.localXfoParam.value,C=this.localXfoParam.value;C.sc=I.sc.clone(),this.localXfoParam.value=C,this.removeAllChildren(),A.getChildren().forEach((A=>{this.addChild(A.clone(g),!1,!1)})),this.loaded=!0,this.emit("loaded"),A.haveGeomsLoaded()?this.emit("geomsLoaded"):A.once("geomsLoaded",(()=>this.emit("geomsLoaded")))}))}}Registry.register("AssetItem",AssetItem);const BillboardAlignment={AlignedToWorld:0,AlignedToCamera:1,AlignedToCameraAndXAxis:2};class BillboardItem extends TreeItem{imageParam=new ImageParameter("Image");pixelsPerMeterParam=new NumberParameter("PixelsPerMeter",1e3);alphaParam=new NumberParameter("Alpha",1);colorParam=new ColorParameter("Color",new Color(1,1,1));alignmentParam=new MultiChoiceParameter("Alignment",0,Object.keys(BillboardAlignment));drawOnTopParam=new BooleanParameter("DrawOnTop",!1);fixedSizeOnscreenParam=new BooleanParameter("FixedSizeOnscreen",!1);frontFacingParam=new BooleanParameter("FrontFacing",!0);pivotParam=new Vec2Parameter("Pivot",new Vec2(.5,0));constructor(A,g){super(A);const I=this.addParameter(this.imageParam);g&&(I.value=g),this.addParameter(this.pixelsPerMeterParam),this.addParameter(this.alphaParam),this.addParameter(this.colorParam),this.addParameter(this.alignmentParam),this.addParameter(this.drawOnTopParam),this.addParameter(this.fixedSizeOnscreenParam),this.addParameter(this.pivotParam)}}Registry.register("BillboardItem",BillboardItem);class CADAsset extends AssetItem{sdk;url;metadataLoadPromise;metadataLoaded=!1;constructor(A){super(A)}clone(A){const g=new CADAsset;return g.copyFrom(this,A),g}copyFrom(A,g){if(!(A instanceof CADAsset))throw new Error("cannot copy from src");super.copyFrom(A,g),this.url=A.url,A.loaded||A.once("geomsLoaded",(A=>{this.emit("geomsLoaded",A)}))}readRootLevelBinary(A,g){g.versions["zea-cad"]=new Version(A.loadStr()),g.sdk=A.loadStr(),this.sdk=g.sdk,super.readBinary(A,g)}async loadZCADEntries(A,g){const I=new BinReader((A.tree2||A.tree).buffer,0,SystemDesc.isMobileDevice);g.versions={},this.removeAllChildren();const C=this.getName();if(this.readRootLevelBinary(I,g),""!=C&&this.setName(C),A.geomsdata&&(this.metadataLoadPromise=new Promise((I=>{this.geomLibrary.once("loaded",(()=>{this.geomLibrary.loadMetadata(A.geomsdata,g),this.metadataLoaded=!0,I()}))}))),A.geoms){const I=-1;this.geomLibrary.readBinaryBuffer(I,A.geoms.buffer,g)}else if(A["geomLibrary.json"]){const I=JSON.parse(new TextDecoder("utf-8").decode(A["geomLibrary.json"])),C=g.url,e=C.lastIndexOf("/")>-1?C.substring(C.lastIndexOf("/")+1):"",i=e.substring(0,e.lastIndexOf(".")),t=g.folder+i;0==I.numGeomFiles?console.error("Corrupt zcad file. Missing 'geoms':",C):this.geomLibrary.loadGeomFilesStream(I,t,g)}return new Promise(((A,I)=>{Promise.allSettled(g.promisses).then((()=>{this.loaded=!0,this.emit("loaded"),A();const g=[];this.geomLibrary.isLoaded()||g.push(new Promise((A=>this.geomLibrary.once("loaded",A))));this.traverse((A=>{A instanceof CADAsset&&!A.geomLibrary.isLoaded()&&g.push(new Promise((g=>A.once("geomsLoaded",g))))}),!1),Promise.allSettled(g).then((()=>this.emit("geomsLoaded")))})).catch((A=>{I(A)}))}))}async load(A,g=new AssetLoadContext){return(g=g.clone()).assetItem=this,new Promise(((I,C)=>{if(resourceLoader.incrementWorkload(1),"string"==typeof A){const e=A,i=e.lastIndexOf("/")>-1?e.substring(0,e.lastIndexOf("/"))+"/":"";this.url=e,g.url=e,g.folder=i,g.urlStack.push(e),g.assetStack.push(this),resourceLoader.loadFile("archive",e).then((A=>{if(!A.tree2&&!A.tree){resourceLoader.incrementWorkDone(1);const A="Corrupt zcad file. Missing 'tree':"+e;return this.emit("error",A),void C(A)}this.loadZCADEntries(A,g).then((()=>{resourceLoader.incrementWorkDone(1),I()}))}),(A=>{resourceLoader.incrementWorkDone(1),this.emit("error",A),C(A)}))}else if(A instanceof ArrayBuffer){resourceLoader.plugins.archive.extractFile(A).then((A=>{this.loadZCADEntries(A,g).then((()=>{resourceLoader.incrementWorkDone(1),I()}))}),(A=>{resourceLoader.incrementWorkDone(1),this.emit("error",A),C(A)}))}}))}loadMetadata(A=""){return this.metadataLoadPromise||(this.metadataLoadPromise=new Promise(((g,I)=>{if(this.metadataLoaded&&g(),""==A){const g=this.url,I=g.substring(0,g.lastIndexOf("."));A=I+".zmetadata"}resourceLoader.incrementWorkload(),resourceLoader.loadFile("archive",A).then((A=>{const I=new AssetLoadContext;I.versions["zea-engine"]=this.engineDataVersion,this.geomLibrary.loadMetadata(A.geomsdata,I),resourceLoader.incrementWorkDone(1),this.metadataLoaded=!0,g()}),(A=>{resourceLoader.incrementWorkDone(1),this.emit("error",A),I(A)}))}))),this.metadataLoadPromise}}Registry.register("CADAsset",CADAsset);class CADAssembly extends TreeItem{constructor(A){super(A)}clone(A){const g=new CADAssembly;return g.copyFrom(this,A),g}}Registry.register("CADAssembly",CADAssembly);class CADPart extends TreeItem{constructor(A){super(A)}clone(A){const g=new CADPart;return g.copyFrom(this,A),g}}Registry.register("CADPart",CADPart);class CADBody extends GeomItem{shattered=!1;constructor(A){super(A)}setShatterState(A){this.shattered!=A&&(this.shattered=A,this.emit("shatterStateChanged",new StateChangedEvent(A)))}clone(A){const g=new CADBody;return g.copyFrom(this,A),g}readBinary(A,g){if(g.versions["zea-engine"].compare([3,9,0])<0){if(BaseGeomItem.prototype.readBinary.call(this,A,g),A.loadSInt32(),g.versions["zea-cad"].compare([0,0,4])<0){const I=A.loadStr();let C=g.assetItem.getMaterialLibrary().getMaterial(I);C||(C=new Material(I,"SimpleSurfaceShader"),C.getParameter("BaseColor").setValue(Color.random(.25)),g.assetItem.getMaterialLibrary().addMaterial(C)),this.materialParam.setValue(C)}if(g.versions["zea-cad"].compare([0,0,2])>=0&&g.versions["zea-cad"].compare([0,0,4])<0){this.layers=A.loadStrArray();for(const A of this.layers)g.addGeomToLayer(this,A)}}else super.readBinary(A,g)}}Registry.register("CADBody",CADBody);const plane=new Cuboid(1,1,1);let planeMaterial=null;class PMIPickingPlane extends GeomItem{addHighlight(A,g,I=!0){}removeHighlight(A,g=!0){}}class PMIItem extends TreeItem{materialMapping={};constructor(A){super(A)}clone(A){const g=new PMIItem;return g.copyFrom(this,A),g}setSelected(A){super.setSelected(A),A?this.activate():this.deactivate()}activate(){}deactivate(){}addHighlight(A,g,I=!0){if(super.addHighlight(A,g,!1),I){const A=g.clone();A.a=1;const I={};this.traverse((g=>{if(g instanceof PMIPickingPlane)return!1;if(g instanceof GeomItem){const C=g.materialParam.value;if(this.materialMapping[g.getId()]=C,!(C.getId()in I)){const e=C.clone();if(e.hasParameter("BaseColor")){const g=e.getParameter("BaseColor");g instanceof MaterialColorParam&&(g.colorSpace=ColorSpace.Gamma),g.setValue(A)}if(e.hasParameter("EdgeColor")){const g=e.getParameter("EdgeColor");g instanceof MaterialColorParam&&(g.colorSpace=ColorSpace.Gamma),g.setValue(A)}e.hasParameter("Overlay")&&e.getParameter("Overlay").setValue(.85),e.__isOpaque=!1,g.materialParam.value=e,I[C.getId()]=e}g.materialParam.value=I[C.getId()]}}))}const C=this.getOwner().getOwner().getOwner();if(C){const I={},e={},i=this.getParameter("LinkedEntities");if(i){i.getValue().forEach(((i,t)=>{if(""==i)return;const o=i.split(", "),a=o.pop();try{const i=C.resolvePath(o);if(i&&i instanceof CADBody)if(0==i.getNumChildren())i.setShatterState(!0),I[i.getId()]||(I[i.getId()]=i,e[i.getId()]=[]),e[i.getId()].push(a);else{const I=i.getChildByName(a);I&&I.addHighlight(A,g,!0)}else console.log("linkedEntity.addHighlight(name, color, true):",o)}catch(A){console.log(t+":"+A.message)}}));for(let C in I){const i=I[C],t=e[C];i.addHighlight(A+":"+t.toString(),g,!0)}}}}removeHighlight(A,g=!0){super.removeHighlight(A,!1),g&&this.traverse((A=>{A instanceof GeomItem&&A.getId()in this.materialMapping&&(A.materialParam.value=this.materialMapping[A.getId()],delete this.materialMapping[A.getId()])}));const I=this.getOwner().getOwner().getOwner();if(I){const g={},C={},e=this.getParameter("LinkedEntities");if(e){e.getValue().forEach((e=>{if(""==e)return;const i=e.split(", "),t=i.pop();try{const e=I.resolvePath(i);if(e&&e instanceof CADBody)if(0==e.getNumChildren())e.setShatterState(!1),g[e.getId()]||(g[e.getId()]=e,C[e.getId()]=[]),C[e.getId()].push(t);else{const g=e.getChildByName(t);g&&g.removeHighlight(A,!0)}else console.log("linkedEntity.addHighlight(name, color, true):failed")}catch(A){console.log(A.message)}}));for(let I in g){const e=g[I],i=C[I];e.removeHighlight(A+":"+i.toString(),!0)}}}}readBinary(A,g){super.readBinary(A,g),this.traverse((A=>{if(A instanceof GeomItem){const g=A.materialParam.value;"StandardSurfaceShader"==g.getShaderName()&&g.setShaderName("FlatSurfaceShader"),A.opacity=.99}})),g.assetItem.getGeometryLibrary().once("loaded",(()=>{this.traverse((A=>{if(A.getName().startsWith("Text")){const g=[];return A.traverse((A=>{if(A instanceof GeomItem){const I=A.geomParam.value.getBoundingBox();planeMaterial||(planeMaterial=new FlatSurfaceMaterial("plane"),planeMaterial.baseColorParam.value=new Color(1,1,0,.001),planeMaterial.overlayParam.value=-.001);const C=new PMIPickingPlane("plane",plane,planeMaterial),e=A.localXfoParam.value.multiply(A.geomOffsetXfoParam.value);e.tr.addInPlace(I.center()),e.sc.multiplyInPlace(I.diagonal()),C.localXfoParam.value=e,g.push(C)}}),!1),g.forEach((g=>A.addChild(g,!1))),!1}}),!1)}))}}Registry.register("PMIItem",PMIItem);class PMIView extends PMIItem{camera;constructor(A){super(A),this.camera=null}clone(A){const g=new PMIView;return g.copyFrom(this,A),g}activate(){super.activate();let A=[];this.hasParameter("GraphicalElements")&&(A=this.getParameter("GraphicalElements").getValue());const g=(()=>{let A=this;for(;A&&!(A instanceof CADAsset);)A=A.getParentItem();return A instanceof CADAsset?A:null})(),I=this.getParentItem().getParentItem(),C=I.getParentItem();if(C){const g=[];I.traverse((A=>{A instanceof PMIView||A instanceof PMIItem&&g.push(A)})),g.forEach((g=>{const I=A.includes(g.getName());g.setVisible(I)}))}if(this.camera){const A=this.localXfoParam.value.clone(),I=this.getParameter("TargetPoint").getValue().clone(),C=this.getParameter("CameraType").getValue();A.tr.scaleInPlace(g.unitsScale),I.scaleInPlace(g.unitsScale);const e=A.tr.distanceTo(I);if(A.sc.set(1,1,1),this.camera.globalXfoParam.value=A,this.camera.setFocalDistance(e),"Camera_Orthographic"==C&&(this.camera.setIsOrthographic(1,0),this.hasParameter("CameraZoom")&&g)){const A=1/this.getParameter("CameraZoom").getValue()*g.unitsScale*2;this.camera.setFrustumHeight(A)}}if(this.hasParameter("ClippingPlaneOrigin")){const A=this.getParameter("ClippingPlaneOrigin").getValue(),I=this.getParameter("ClippingPlaneNormal").getValue(),e=!0,i=-A.dot(I)*g.unitsScale;C.traverse((A=>{if(A instanceof PMIItem)return!1;A instanceof GeomItem&&(A.setCutawayEnabled(e),A.setCutVector(I),A.setCutDist(i))}))}else C.traverse((A=>{if(A instanceof PMIItem)return!1;A instanceof GeomItem&&A.setCutawayEnabled(!1)}))}deactivate(){super.deactivate()}readBinary(A,g){super.readBinary(A,g),g.camera&&(this.camera=g.camera)}}Registry.register("PMIView",PMIView);class XRef extends CADAsset{configurationParam=new StringParameter("Configuration");constructor(A){super(A),this.addParameter(this.configurationParam)}clone(A){const g=new XRef;return g.copyFrom(this,A),g}readBinary(A,g){let I;if(g.versions["zea-engine"].compare([3,13,1])>=0)TreeItem.prototype.readBinary.call(this,A,g),I=A.loadStr();else{A.loadStr();const C=A.loadStr();this.setName(C),I=A.loadStr();const e=new Xfo;g.versions["zea-cad"].compare([3,6,2])>0?(e.tr=A.loadFloat32Vec3(),e.ori=A.loadFloat32Quat(),this.localXfoParam.value=e):""==C&&this.setName(I),g.versions["zea-engine"].compare([3,11,1])>0&&this.readBinaryParams(A,g)}const C=this.getChildByName("Assembly Features");let e;if(C&&this.removeChildByHandle(C),g.resources?g.resources[I]?e=g.resources[I]:(I.includes("/")?I=I.slice(I.lastIndexOf("/")+1):I.includes("\\")&&(I=I.slice(I.lastIndexOf("\\")+1)),g.resources[I]?e=g.resources[I]:g.xrefLoadCallback&&(e=g.xrefLoadCallback.call(g,I,this))):g.xrefLoadCallback?e=g.xrefLoadCallback.call(g,I,this):(I.includes("/")?I=I.slice(I.lastIndexOf("/")+1):I.includes("\\")&&(I=I.slice(I.lastIndexOf("\\")+1)),e=I.endsWith(".zcad")?g.folder+I:g.folder+I+".zcad"),e){if(g.urlStack.includes(e)){const A=g.urlStack.indexOf(e),I=g.assetStack[A];return void console.warn("Circular load occurring at:",I.path)}g.xrefs[e]?g.addPromise(new Promise(((A,I)=>{const i=g.xrefs[e],t=()=>{if(this.url=i.url,this.sdk=i.sdk,this.engineDataVersion=i.engineDataVersion,this.units=i.units,this.units!=g.units){const A=getUnitsFactor(this.units),I=getUnitsFactor(g.units);this.unitsScale=A/I;const C=this.localXfoParam.value;C.sc.scaleInPlace(this.unitsScale),C.tr.scaleInPlace(this.unitsScale),this.localXfoParam.value=C}const I=i.getChild(0);if(I){this.removeAllChildren();const A=new CloneContext,g=I.clone(A);this.addChild(g,!1,!1)}C&&this.applyAssemblyLevelFeatures(C),A()},o=()=>{this.emit("error"),I()};i.loaded?t():(i.once("xrefLoaded",t),i.once("error",o))}))):(g.xrefs[e]=this,g.addPromise(new Promise(((A,I)=>{this.load(e,new AssetLoadContext(g)).then((()=>{this.emit("xrefLoaded");const g=this.localXfoParam.value;g.tr.scaleInPlace(this.unitsScale),this.localXfoParam.value=g,C&&this.applyAssemblyLevelFeatures(C),A()}),(()=>{I()}))}))))}else if(console.warn(`While Loading ${this.getPath()} unable to load XRef: ${I}`),C){const A=C.getChildren();for(const g of A)this.addChild(g,!1)}}applyAssemblyLevelFeatures(A){const g=A.getChild(0),I=this.getChild(0);g&&I&&this.applyFeature(g,I)}applyFeatureToChildren(A,g){const I=[...A.getChildren()];for(const A of I){const I=g.getChildByName(A.name);I?this.applyFeature(A,I):console.log(`Feature node: ${A.path} does not match a node in the assembly tree for the following XRef:`,this.name)}}applyFeature(A,g){if(A.localXfoParam.value.isIdentity()||(g.localXfoParam.value=A.localXfoParam.value),A instanceof GeomItem){const I=A.materialParam.value;g.traverse((A=>{if(A instanceof GeomItem){A.materialParam.value=I;const g=A.geomParam.value;g instanceof CompoundGeom?g.clearMaterials():A.geomParam.once("valueChanged",(()=>{const g=A.geomParam.value;g instanceof CompoundGeom&&g.clearMaterials()}))}}),!0)}else if(A instanceof CADPart){if(g instanceof CADPart){const I=g.localXfoParam.value,C=g.parent;C.removeChildByHandle(g),C.addChild(A,!1,!1),A.localXfoParam.value=I}else(g instanceof XRef||g instanceof InstanceItem)&&(A.localXfoParam.value=new Xfo,g.removeAllChildren(),g.addChild(A,!1,!1));return}g instanceof XRef&&1==g.getNumChildren()&&(g=g.getChild(0)),g&&this.applyFeatureToChildren(A,g)}}Registry.register("XRef",XRef);const PassType={PRE:1,OPAQUE:2,TRANSPARENT:3,OVERLAY:4};class GLPass extends EventEmitter{enabled=!0;passIndex=-1;__gl=null;renderer=null;__renderer=null;constructor(){super(),this.enabled=!0,this.passIndex=0}init(A,g){if(null==g)throw new Error("Missing constructor argument.");this.__gl=A.gl,this.renderer=A,this.__renderer=A,this.passIndex=g}setPassIndex(A){this.passIndex=A}getPassType(){return PassType.OPAQUE}itemAddedToScene(A,g){throw Error(`${this.constructor.name} must implement itemAddedToScene and itemRemovedFromScene`)}itemRemovedFromScene(A,g){throw Error(`${this.constructor.name} must implement itemAddedToScene and itemRemovedFromScene`)}startPresenting(){}stopPresenting(){}draw(A){throw Error("draw not implemented on GLPass")}drawHighlightedGeoms(A){}drawGeomData(A){}getGeomItemAndDist(A){throw Error("getGeomItemAndDist not implemented on GLPass")}}class GLCADPass extends GLPass{constructor(A=!1){super(),console.warn("GLCADPass is deprecated. No need to install this pass in the renderer.")}itemAddedToScene(A,g){return!1}itemRemovedFromScene(A,g){return!1}}const placeHolderItems=new Map;let disableLoading=!1;class PlaceholderGeomItem extends GeomItem{relativePath;loadContext;parentCache;parentChildIndexCache;loading=!1;constructor(A=""){super(A)}clone(A){const g=new PlaceholderGeomItem;return g.copyFrom(this,A),g}copyFrom(A,g){if(!(A instanceof PlaceholderGeomItem))throw new Error("cannot copy from src");super.copyFrom(A),this.relativePath=A.relativePath,this.loadContext=A.loadContext}readBinary(A,g){super.readBinary(A,g),this.relativePath=A.loadStr(),this.loadContext=g}load(){if(this.loading||disableLoading)return;let A;this.loading=!0;const g=()=>{const A=this.loadContext.xrefs[this.relativePath];let g;this.parentCache=this.parent,this.parentChildIndexCache=this.parentCache.getChildIndex(this),this.parentCache.removeChild(this.parentChildIndexCache),placeHolderItems.has(this.relativePath)?(g=placeHolderItems.get(this.relativePath),g.forEach(((A,g)=>{this.parentCache.insertChild(A.clone(),this.parentChildIndexCache+g,!1)}))):(g=[...A.getChildren()],placeHolderItems.set(this.relativePath,g),g.forEach(((A,g)=>{this.parentCache.insertChild(A,this.parentChildIndexCache+g,!1)})))};if(this.relativePath){const I=this.loadContext.folder+this.relativePath;A=this.loadContext.xrefs[this.relativePath],A||(A=new XRef(this.relativePath),A.load(I),this.loadContext.xrefs[this.relativePath]=A),A.loaded&&A.geomLibrary.loaded?g():A.once("geomsLoaded",g)}}unload(){this.parentCache.removeChild(this.parentChildIndexCache),this.parentCache.insertChild(this,this.parentChildIndexCache),this.loading=!1}static disableLoading(){disableLoading=!0}}Registry.register("Placeholder",PlaceholderGeomItem);class Camera extends TreeItem{isOrthographicParam=new NumberParameter("isOrthographic",0);fovParam=new NumberParameter("fov",1);nearParam=new NumberParameter("near",.1);farParam=new NumberParameter("far",1e3);focalDistanceParam=new NumberParameter("focalDistance",5);adjustNearAndFarPlanesToFocalDist=!0;nearDistFactor=.01;farDistFactor=100;frameOnBoundingSphere=!1;viewHeight=0;intervalId=-1;constructor(A="Camera"){super(A),this.addParameter(this.isOrthographicParam),this.addParameter(this.fovParam),this.addParameter(this.nearParam),this.addParameter(this.farParam),this.addParameter(this.focalDistanceParam);const g=A=>{this.emit("projectionParamChanged",A)};this.isOrthographicParam.on("valueChanged",g),this.fovParam.on("valueChanged",g),this.nearParam.on("valueChanged",g),this.farParam.on("valueChanged",g),this.setPositionAndTarget(new Vec3(3,3,1.75),new Vec3(0,0,1)),this.setLensFocalLength("35mm")}getNear(){return this.nearParam.value}setNear(A){this.nearParam.value=A}getFar(){return this.farParam.value}setFar(A){this.farParam.value=A}getFov(){return this.fovParam.value}setFov(A){this.fovParam.value=A}getFrustumHeight(){return this.viewHeight}setFrustumHeight(A){this.viewHeight=A,this.emit("projectionParamChanged")}setLensFocalLength(A){const g={"10mm":100.4,"11mm":95,"12mm":90,"14mm":81.2,"15mm":77.3,"17mm":70.4,"18mm":67.4,"19mm":64.6,"20mm":61.9,"24mm":53.1,"28mm":46.4,"30mm":43.6,"35mm":37.8,"45mm":29.9,"50mm":27,"55mm":24.6,"60mm":22.6,"70mm":19.5,"75mm":18.2,"80mm":17.1,"85mm":16.1,"90mm":15.2,"100mm":13.7,"105mm":13,"120mm":11.4,"125mm":11,"135mm":10.2,"150mm":9.1,"170mm":8.1,"180mm":7.6,"210mm":6.5,"300mm":4.6,"400mm":3.4,"500mm":2.7,"600mm":2.3,"800mm":1.7};A in g?this.fovParam.value=MathFunctions.degToRad(g[A]):console.warn("Camera lense focal length not supported:"+A)}getFocalDistance(){return this.focalDistanceParam.value}setFocalDistance(A){A<1e-4&&console.error("Never set focal distance to zero"),this.focalDistanceParam.value=A,this.adjustNearAndFarPlanesToFocalDist&&(this.nearParam.value=A*this.nearDistFactor,this.farParam.value=A*this.farDistFactor)}isOrthographic(){return 1==this.isOrthographicParam.value}setIsOrthographic(A,g=0){if(this.intervalId&&clearInterval(this.intervalId),A>.5){const A=this.fovParam.value,g=this.focalDistanceParam.value;this.viewHeight=Math.sin(.5*A)*g*2}if(0==g)this.isOrthographicParam.value=A;else{const I=Math.round(g/20);let C=0;const e=this.isOrthographicParam.value,i=()=>{C++;const g=MathFunctions.lerp(e,A,C/I);this.isOrthographicParam.value=g,C<I?this.intervalId=window.setTimeout(i,20):(this.intervalId=-1,this.emit("movementFinished"))};i()}}setPositionAndTarget(A,g){this.setFocalDistance(A.distanceTo(g));const I=new Xfo;I.setLookAt(A,g,new Vec3(0,0,1)),this.globalXfoParam.value=I,this.emit("movementFinished")}getTargetPosition(){const A=this.focalDistanceParam.value,g=this.globalXfoParam.value,I=g.ori.getZaxis();return I.scaleInPlace(-A),I.addInPlace(g.tr),I}frameView(A,g,I,C=0,e=.1){const i=this.focalDistanceParam.value,t=this.fovParam.value,o=this.isOrthographicParam.value,a=this.globalXfoParam.value.clone(),B=A/g,s=2*Math.atan(Math.tan(.5*t)*B);let l=i;if(this.frameOnBoundingSphere){const A=new Box3;for(const g of I)A.addBox3(g.boundingBoxParam.value);if(!A.isValid())return void console.warn("Bounding box not valid.");const g=a.ori.getZaxis().scale(-i),C=a.tr.add(g),e=A.center().subtract(C);a.tr.addInPlace(e),l=A.size()/Math.tan(t)}else{const A=[];if(I.forEach((g=>{g.traverse((g=>{if(!(g instanceof TreeItem))return!1;if(g.disableBoundingBox)return!1;if(!g.isVisible()||!g.isPickable())return!1;if(g instanceof GeomItem){const I=g.geomParam.value;if(I){const C=I.getBoundingBox();if(C.isValid()){const I=g.geomMatParam.value;return A.push(I.transformVec3(C.p0)),A.push(I.transformVec3(new Vec3(C.p0.x,C.p0.y,C.p1.z))),A.push(I.transformVec3(new Vec3(C.p0.x,C.p1.y,C.p0.z))),A.push(I.transformVec3(new Vec3(C.p1.x,C.p0.y,C.p0.z))),A.push(I.transformVec3(new Vec3(C.p0.x,C.p1.y,C.p1.z))),A.push(I.transformVec3(new Vec3(C.p1.x,C.p0.y,C.p1.z))),A.push(I.transformVec3(new Vec3(C.p1.x,C.p1.y,C.p0.z))),void A.push(I.transformVec3(C.p1))}}}if(0==g.getNumChildren()||g instanceof BaseGroup){const I=g.boundingBoxParam.value;if(I.isValid())return A.push(new Vec3(I.p0.x,I.p0.y,I.p0.z)),A.push(new Vec3(I.p0.x,I.p0.y,I.p1.z)),A.push(new Vec3(I.p0.x,I.p1.y,I.p0.z)),A.push(new Vec3(I.p1.x,I.p0.y,I.p0.z)),A.push(new Vec3(I.p0.x,I.p1.y,I.p1.z)),A.push(new Vec3(I.p1.x,I.p0.y,I.p1.z)),A.push(new Vec3(I.p1.x,I.p1.y,I.p0.z)),void A.push(new Vec3(I.p1.x,I.p1.y,I.p1.z))}}),!0)})),0==A.length)return;const g=o?0:s/2,C=o?0:t/2,i={};i.XPos=new Vec3(Math.cos(g),0,Math.sin(g)),i.XNeg=new Vec3(-Math.cos(g),0,Math.sin(g)),i.YPos=new Vec3(0,Math.cos(C),Math.sin(C)),i.YNeg=new Vec3(0,-Math.cos(C),Math.sin(C)),i.ZPos=new Vec3(0,0,1),i.ZNeg=new Vec3(0,0,-1);const n={},d={};for(const A in i)n[A]=a.ori.rotateVec3(i[A]),d[A]=Number.NEGATIVE_INFINITY;const r=new Vec3;A.forEach(((A,g)=>{if(!Number.isFinite(A.x)||!Number.isFinite(A.y)||!Number.isFinite(A.z))return;const I=A.subtract(a.tr);for(const A in i){const g=I.dot(n[A]);g>d[A]&&g!=Number.POSITIVE_INFINITY&&(d[A]=g)}r.addInPlace(A)}));for(const A in d)if(d[A]==Number.POSITIVE_INFINITY)return;r.scaleInPlace(1/A.length);let c=0;if(o){const A=new Vec3(.5*(-d.XNeg+d.XPos),.5*(-d.YNeg+d.YPos),.5*(-d.ZNeg+d.ZPos)),g=d.ZNeg+d.ZPos;c=2*g,A.z=-d.ZNeg+c,a.tr.addInPlace(a.ori.rotateVec3(A)),l=2*g;const I=d.XPos+d.XNeg,C=d.YPos+d.YNeg;this.viewHeight=Math.max(C,I/B),this.viewHeight+=this.viewHeight*e}else{const A=s/2,g=t/2,I=new Vec2(Math.cos(A)*d.XPos,Math.sin(A)*d.XPos),C=I.add(new Vec2(Math.sin(A),-Math.cos(A))),i=new Vec2(-Math.cos(A)*d.XNeg,Math.sin(A)*d.XNeg),o=i.add(new Vec2(-Math.sin(A),-Math.cos(A))),B=Vec2.intersectionOfLines(I,C,i,o),n=new Vec2(Math.cos(g)*d.YPos,Math.sin(g)*d.YPos),h=n.add(new Vec2(Math.sin(g),-Math.cos(g))),G=new Vec2(-Math.cos(g)*d.YNeg,Math.sin(g)*d.YNeg),m=G.add(new Vec2(-Math.sin(g),-Math.cos(g))),b=Vec2.intersectionOfLines(n,h,G,m);if(null===B||null===b)return void console.warn("xP or yP === null");c=Math.max(B.y,b.y);const Z=new Vec3(B.x,b.x,c);a.tr.addInPlace(a.ori.rotateVec3(Z)),l=r.distanceTo(a.tr);const u=l*e;a.tr.addInPlace(a.ori.rotateVec3(new Vec3(0,0,u))),c+=u}if(this.adjustNearAndFarPlanesToFocalDist){d.ZPos-=c,d.ZNeg+=c;const A=d.ZNeg*this.nearDistFactor,g=-d.ZPos*this.farDistFactor;this.nearParam.value=A,this.farParam.value=g}}if(0==C)this.setFocalDistance(l),this.globalXfoParam.value=a,this.emit("movementFinished");else{this.intervalId>0&&window.clearTimeout(this.intervalId);const A=Math.round(C/20);let g=0;const I=this.focalDistanceParam.value,e=this.globalXfoParam.value,i=()=>{g++;const C=g/A,t=MathFunctions.lerp(I,l,C),o=e.lerp(a,C);this.globalXfoParam.value=o,this.setFocalDistance(t),g<A?this.intervalId=window.setTimeout(i,20):(this.intervalId=-1,this.emit("movementFinished"))};i()}}updateProjectionMatrix(A,g){const I=this.isOrthographicParam.value,C=this.fovParam.value,e=this.nearParam.value,i=this.farParam.value,t=new Mat4;if(I>0){const A=.5*this.viewHeight,I=-A,C=A,o=A*-g,a=A*g;t.setOrthographicMatrix(o,a,I,C,e,i)}I<1&&A.setPerspectiveMatrix(C,g,e,i),1==I?A.setFromMat4(t):I>0&&A.set(MathFunctions.lerp(A.m00,t.m00,I),MathFunctions.lerp(A.m01,t.m01,I),MathFunctions.lerp(A.m02,t.m02,I),MathFunctions.lerp(A.m03,t.m03,I),MathFunctions.lerp(A.m10,t.m10,I),MathFunctions.lerp(A.m11,t.m11,I),MathFunctions.lerp(A.m12,t.m12,I),MathFunctions.lerp(A.m13,t.m13,I),MathFunctions.lerp(A.m20,t.m20,I),MathFunctions.lerp(A.m21,t.m21,I),MathFunctions.lerp(A.m22,t.m22,I),MathFunctions.lerp(A.m23,t.m23,I),MathFunctions.lerp(A.m30,t.m30,I),MathFunctions.lerp(A.m31,t.m31,I),MathFunctions.lerp(A.m32,t.m32,I),MathFunctions.lerp(A.m33,t.m33,I))}}Registry.register("Camera",Camera);class GridTreeItem extends TreeItem{constructor(A=5,g=50,I=new Color("#DCDCDC")){super("GridTree"),this.disableBoundingBox=!0,this.pickableParam.value=!1;const C=new LinesMaterial("gridMaterial");C.baseColorParam.value=I,C.overlayParam.value=0;const e=new Grid(A,A,g,g,!0),i=new GeomItem("GridItem",e,C);i.pickableParam.value=!1,this.addChild(i,!1);const t=new Lines;t.setNumVertices(2),t.setNumSegments(1),t.setSegmentVertexIndices(0,0,1);const o=t.getVertexAttribute("positions");o.setValue(0,new Vec3(-.5*A,0,0)),o.setValue(1,new Vec3(.5*A,0,0));const a=new LinesMaterial("gridXAxisMaterial");a.baseColorParam.value=new Color(I.luminance(),0,0),a.overlayParam.value=0;const B=new GeomItem("xAxisLine",t,a);B.pickableParam.value=!1,this.addChild(B,!1);const s=new LinesMaterial("gridYAxisMaterial");s.baseColorParam.value=new Color(0,I.luminance(),0),s.overlayParam.value=0;const l=new GeomItem("yAxisLine",t,s);l.pickableParam.value=!1;const n=new Xfo;n.ori.setFromAxisAndAngle(new Vec3(0,0,1),.5*Math.PI),l.geomOffsetXfoParam.value=n,this.addChild(l,!1)}cleanBoundingBox(){return new Box3}}Registry.register("GridTreeItem",GridTreeItem);const defaultGridColor=new Color("#DCDCDC");class Scene{envMapParam=new ImageParameter("EnvMap");displayEnvMapParam=new BooleanParameter("Display EnvMap",!1);envMapLODParam=new NumberParameter("EnvMapLOD",0);root=new TreeItem("root");constructor(){}getRoot(){return this.root}getResourceLoader(){return resourceLoader}setEnvMap(A){this.envMapParam.value=A}setupGrid(A=5,g=50,I=defaultGridColor){const C=new GridTreeItem(A,g,I);return this.root.addChild(C,!1),C}}class VLAAsset extends AssetItem{constructor(A){super(A),this.geomLibrary.on("loaded",(()=>{this.emit("geomsLoaded")}))}readBinary(A,g){g.versions["zea-engine"]||(g.versions["zea-mesh"]=new Version(A.loadStr()));const I=A.loadUInt32();return super.readBinary(A,g),g.versions["zea-engine"].compare([2,1,0])<0&&A.loadFloat32Vec2(),this.geomLibrary.setNumGeoms(A.loadUInt32()),I}load(A,g=new AssetLoadContext){return new Promise(((I,C)=>{const e=A.lastIndexOf("/")>-1?A.substring(0,A.lastIndexOf("/"))+"/":"",i=A.lastIndexOf("/")>-1?A.substring(A.lastIndexOf("/")+1):"",t=i.substring(0,i.lastIndexOf("."));let o=0;g.assetItem=this,g.url=A,g.folder=e,resourceLoader.incrementWorkload(1),this.geomLibrary.on("loaded",(()=>{resourceLoader.incrementWorkDone(1)})),resourceLoader.loadFile("archive",A).then((A=>{let C;if(A.tree2)C=new BinReader(A.tree2.buffer,0,SystemDesc.isMobileDevice);else{const I=A.tree?A.tree:A[Object.keys(A)[0]];C=new BinReader(I.buffer,0,SystemDesc.isMobileDevice),g.versions["zea-engine"]=new Version}if(o=this.readBinary(C,g),this.loaded=!0,this.emit("loaded"),0==o&&A.geoms)this.geomLibrary.readBinaryBuffer(-1,A.geoms.buffer,g);else{const A=e+t,I={numGeomsPerFile:o,numGeoms:this.geomLibrary.getNumGeoms()};this.geomLibrary.loadGeomFilesStream(I,A,g)}I()}),(A=>{this.emit("error",A),C(A)}))}))}}Registry.register("VLAAsset",VLAAsset);class ObjAsset extends AssetItem{splitObjects=new BooleanParameter("splitObjects",!1);splitGroupsIntoObjects=new BooleanParameter("splitGroupsIntoObjects",!1);loadMtlFile=new BooleanParameter("loadMtlFile",!0);unitsConversion=new NumberParameter("unitsConversion",1);defaultShader=new StringParameter("defaultShader","");splitObjectsParam=new BooleanParameter("splitObjects",!1);splitGroupsIntoObjectsParam=new BooleanParameter("splitGroupsIntoObjects",!1);loadMtlFileParam=new BooleanParameter("loadMtlFile",!0);unitsConversionParam=new NumberParameter("unitsConversion",1);defaultShaderParam=new StringParameter("defaultShader","");constructor(A){super(A),this.addParameter(this.splitObjectsParam),this.addParameter(this.splitGroupsIntoObjectsParam),this.addParameter(this.loadMtlFileParam),this.addParameter(this.unitsConversionParam),this.addParameter(this.defaultShaderParam)}load(A){return this.loaded=!1,new Promise(((g,I)=>{const C=A.substring(0,A.lastIndexOf("/"))+"/",e=A=>{const g=A.split("\n"),I=/\s+/;let e;const i=function(A){if(3==A.length)return new Color(parseFloat(A[0]),parseFloat(A[1]),parseFloat(A[2]));throw new Error("Unable to parse a color from the following parts:"+A.join("_"))},t=(A,g)=>{const I=new FileImage(A);return I.load(C+g),I};for(let A=0;A<g.length;A++){let C=g[A].trim();if(C.startsWith("#"))continue;C.includes("#")&&(C=C.substring(0,C.indexOf("#")).trim());const o=C.split(I),a=o.shift(),B=o.join(" ");switch(a){case"newmtl":e=new StandardSurfaceMaterial(B),this.materialLibrary.addMaterial(e);break;case"Kd":e.baseColorParam.value=i(o),e.baseColorParam.colorSpace,ColorSpace.Linear;break;case"map_Kd":e.baseColorParam.setImage(t("map_Kd",o[0]));break;case"Ks":const A=(parseFloat(o[0])+parseFloat(o[1])+parseFloat(o[2]))/3;e.roughnessParam.value=1-A,e.reflectanceParam.value=A;break;case"map_Ks":e.roughnessParam.setImage(t("map_Ks",o[0])),e.reflectanceParam.value=.2;break;case"d":e.opacityParam.value=parseFloat(B);break;case"map_d":e.opacityParam.setImage(t("map_Kd",o[0]));break;case"map_bump":e.normalParam.setImage(t("normal",o[0]))}}},i=A=>new Promise((g=>{loadTextfile(A,(A=>{resourceLoader.incrementWorkDone(1),e(A),resourceLoader.incrementWorkDone(1),g()}))})),t=[],o=[],a=[],B={},s=async A=>{const g=A.split("\n"),I=/\s+/;let e,s,l=0;const n=A=>{if(A in B){let g=1;for(;A+String(g)in B;)g++;A+=String(g)}e={verticesRemapping:{},texCoordsRemapping:{},normalsRemapping:{},vertexIndices:[],texCoordIndices:[],normalIndices:[],numVertices:0,numTexCoords:0,numNormals:0,faceCounts:[],material:s},B[A]=e,l++};n("geom");const d=this.splitGroupsIntoObjectsParam.value;for(let A=0;A<g.length;A++){let r=g[A].trim();if(r.startsWith("#"))continue;r.includes("#")&&(r=r.substring(0,r.indexOf("#")).trim());const c=r.split(I),h=c.shift(),G=c.join(" ");switch(h){case"":case"s":continue;case"mtllib":if(!this.loadMtlFileParam.value)continue;resourceLoader.incrementWorkload(2);const A=C+G;A&&await i(A);break;case"o":n(G);break;case"usemtl":s=G,n(G+Object.keys(B).length);break;case"g":d&&n(G?c.join("_"):"Group"+l);break;case"v":t.push(c.map((A=>parseFloat(A))));break;case"vt":a.push(c.map((A=>parseFloat(A))));break;case"vn":o.push(c.map((A=>parseFloat(A))));break;case"f":{const A=[],g=[],I=[];for(let C=0,i=c.length;C<i;C++){const i=c[C].split("/").map((A=>parseInt(A)-1)),t=i[0];let o=e.verticesRemapping[t];if(null==o&&(o=e.numVertices,e.verticesRemapping[t]=o,e.numVertices++),A.push(o),i.length>1&&!isNaN(i[1])){const A=i[1];g.push(A)}if(i.length>2&&!isNaN(i[2])){const A=i[2];I.push(A)}}e.vertexIndices.push(A),I.length>0&&e.normalIndices.push(I),g.length>0&&e.texCoordIndices.push(g),null==e.faceCounts[A.length-3]&&(e.faceCounts[A.length-3]=[]),e.faceCounts[A.length-3]++;break}default:console.warn("Unhandled line:"+r)}}},l=()=>{for(const A in B)0!=B[A].numVertices&&n(A,B[A]);this.emit("loaded"),this.getGeometryLibrary().emit("loaded"),this.emit("geomsLoaded"),g()},n=(A,g)=>{for(let A=0;A<g.faceCounts.length;A++)null==g.faceCounts[A]&&(g.faceCounts[A]=0);const I=g.numVertices,C=new Mesh;C.name=A,C.setFaceCounts(g.faceCounts),C.setNumVertices(I);const e=C.getVertexAttribute("positions"),i=this.unitsConversionParam.value;for(const A in g.verticesRemapping){const I=Number.parseInt(A),C=g.verticesRemapping[I];e.setValue(C,new Vec3(t[I][0]*i,t[I][1]*i,t[I][2]*i))}let B,s;g.normalIndices.length>0&&(B=new Vec3Attribute,C.addVertexAttribute("normals",B)),g.texCoordIndices.length>0&&(s=new Vec2Attribute,C.addVertexAttribute("texCoords",s));const l=Array(g.faceCounts.length).fill(0);for(let A=0;A<g.vertexIndices.length;A++){const I=g.vertexIndices[A];let e=0;for(let A=0;A<I.length-3;++A)g.faceCounts[A]&&(e+=g.faceCounts[A]);if(e+=l[I.length-3],l[I.length-3]++,C.setFaceVertexIndices(e,I),B){const I=g.normalIndices[A];for(let A=0;A<I.length;A++){const g=new Vec3(o[I[A]][0],o[I[A]][1],o[I[A]][2]);B.setFaceVertexValue(e,A,g)}}if(s&&g.texCoordIndices.length==g.vertexIndices.length){const I=g.texCoordIndices[A];for(let A=0;A<I.length;A++){const g=new Vec2(a[I[A]][0],a[I[A]][1]);s.setFaceVertexValue(e,A,g)}}}const n=new GeomItem(A,C),d=C.getBoundingBox().center();{const A=d.negate(),g=C.getVertexAttribute("positions");for(let I=0;I<g.getCount();I++)g.setValue(I,g.getValue(I).add(A));C.setBoundingBoxDirty()}if(n.localXfoParam.value=new Xfo(d),null!=g.material&&this.materialLibrary.hasMaterial(g.material))n.materialParam.value=this.materialLibrary.getMaterial(g.material);else{const g=this.defaultShaderParam.value,I=new Material(A+" mat");I.setShaderName(""!=g?g:"StandardSurfaceShader"),this.materialLibrary.addMaterial(I),n.materialParam.value=I}this.addChild(n,!1)};(()=>{resourceLoader.incrementWorkload(2),loadTextfile(A,(A=>{resourceLoader.incrementWorkDone(1),s(A).then((()=>{l(),resourceLoader.incrementWorkDone(1)}))}),(A=>{this.emit("error",A),I(A)}))})()}))}}class BaseTool extends ParameterOwner{__activated=!1;constructor(){super()}activateTool(){this.__activated&&console.warn("Tool already active"),this.__activated=!0,this.emit("activatedChanged",{activated:this.__activated})}deactivateTool(){this.__activated=!1,this.emit("activatedChanged",{activated:this.__activated})}onPointerDown(A){}onPointerMove(A){}onPointerUp(A){}onPointerClick(A){}onPointerDoubleClick(A){}onPointerLongPress(A){}onPointerEnter(A){}onPointerLeave(A){}onWheel(A){}onKeyDown(A){}onKeyUp(A){}onTouchCancel(A){}}const MANIPULATION_MODES={pan:0,dolly:1,zoom:2,look:3,turntable:4,tumbler:5,trackball:6};class CameraManipulator extends BaseTool{appData;orbitAroundCursor=!1;zoomTowardGeomUnderCursor=!1;aimFocusOnTouchTap=2;aimFocusOnMouseClick=2;enabledWASDWalkMode=!1;defaultManipulationState=MANIPULATION_MODES.turntable;prevCursor;manipulationState;pointerDown=!1;dragging=0;keyboardMovement=!1;keysPressed=[];velocity=new Vec3;prevVelocityIntegrationTime=-1;ongoingTouches={};orbitTarget;prevMousePos;focusIntervalId;mouseWheelMovementDist=0;mouseWheelZoomCount=0;mouseWheelZoomId=-1;orbitRateParam=new NumberParameter("OrbitRate",SystemDesc.isMobileDevice?.5:1);dollySpeedParam=new NumberParameter("DollySpeed",.001);mouseWheelDollySpeedParam=new NumberParameter("MouseWheelDollySpeed",.1);walkSpeedParam=new NumberParameter("WalkSpeed",5);walkModeCollisionDetection=new BooleanParameter("WalkModeCollisionDetection",!1);constructor(A){super(),this.appData=A,this.defaultManipulationState=MANIPULATION_MODES.turntable,this.manipulationState=this.defaultManipulationState,this.addParameter(this.orbitRateParam),this.addParameter(this.dollySpeedParam),this.addParameter(this.mouseWheelDollySpeedParam),this.addParameter(this.walkSpeedParam),this.addParameter(this.walkModeCollisionDetection)}activateTool(){super.activateTool(),this.appData&&this.appData.renderer&&(this.prevCursor=this.appData.renderer.getGLCanvas().style.cursor,this.appData.renderer.getGLCanvas().style.cursor="cursor")}deactivateTool(){super.deactivateTool(),this.appData&&this.appData.renderer&&(this.appData.renderer.getGLCanvas().style.cursor=this.prevCursor)}setDefaultManipulationMode(A){if(this.defaultManipulationState="string"==typeof A?MANIPULATION_MODES[A]:A,!Object.values(MANIPULATION_MODES).includes(this.defaultManipulationState))throw new Error("Invalid Camera Manipulation Mode. Must be one of "+Object.keys(MANIPULATION_MODES))}look(A,g){const{viewport:I}=A,C=I.getCamera(),e=this.orbitRateParam.value,i=C.globalXfoParam.value,t=new Quat;t.rotateZ(g.x/I.getWidth()*Math.PI*e),i.ori=t.multiply(i.ori);const o=new Quat;o.rotateX(g.y/I.getHeight()*Math.PI*e),i.ori.multiplyInPlace(o),C.globalXfoParam.value=i}turntable(A,g){const{viewport:I}=A,C=I.getCamera(),e=this.orbitRateParam.value,i=C.globalXfoParam.value,t=i.ori.inverse().rotateVec3(i.tr.subtract(this.orbitTarget)),o=new Quat;o.rotateZ(g.x/I.getWidth()*2*Math.PI*-e),i.ori=o.multiply(i.ori);const a=new Quat;a.rotateX(g.y/I.getHeight()*Math.PI*-e),i.ori.multiplyInPlace(a),i.tr=this.orbitTarget.add(i.ori.rotateVec3(t)),C.globalXfoParam.value=i}tumbler(A,g){const{viewport:I}=A,C=I.getCamera(),e=this.orbitRateParam.value,i=C.globalXfoParam.value,t=i.ori.getXaxis(),o=i.ori.getYaxis(),a=i.ori.getZaxis(),B=t.scale(-g.x).add(o.scale(g.y)).cross(a);B.normalizeInPlace();const s=g.length(),l=i.ori.inverse().rotateVec3(i.tr.subtract(this.orbitTarget)),n=new Quat;n.setFromAxisAndAngle(B,s/I.getWidth()*Math.PI*-e),i.ori=n.multiply(i.ori),i.tr=this.orbitTarget.add(i.ori.rotateVec3(l)),C.globalXfoParam.value=i}trackball(A,g){const{viewport:I}=A,C=I.getCamera(),e=this.orbitRateParam.value,i=C.globalXfoParam.value,t=i.ori.getXaxis(),o=i.ori.getYaxis(),a=i.ori.getZaxis(),B=t.scale(-g.x).add(o.scale(g.y)).cross(a);B.normalizeInPlace();const s=g.length(),l=i.ori.inverse().rotateVec3(i.tr.subtract(this.orbitTarget)),n=new Quat;n.setFromAxisAndAngle(B,s/I.getWidth()*Math.PI*-e),i.ori=n.multiply(i.ori),i.tr=this.orbitTarget.add(i.ori.rotateVec3(l)),C.globalXfoParam.value=i}pan(A,g){const{viewport:I}=A,C=I.getCamera(),e=new Xfo,i=new Vec3(1,0,0),t=new Vec3(0,1,0);if(C.isOrthographic()){const A=C.getFrustumHeight(),o=A*(I.getWidth()/I.getHeight());e.tr=i.scale(-g.x/I.getWidth()*o),e.tr.addInPlace(t.scale(g.y/I.getHeight()*A))}else{const A=C.getFocalDistance(),o=C.getFov(),a=2*A*Math.tan(.5*o),B=a*(I.getWidth()/I.getHeight());e.tr=i.scale(-g.x/I.getWidth()*B),e.tr.addInPlace(t.scale(g.y/I.getHeight()*a))}const o=C.globalXfoParam.value;C.globalXfoParam.value=o.multiply(e)}dolly(A,g,I){const C=A.viewport,e=C.getCamera(),i=e.getFocalDistance(),t=new Vec2(.5*C.getWidth(),.5*C.getHeight()),o=g.subtract(t).normalize(),a=I.dot(o),B=()=>{const A=a*this.dollySpeedParam.value*i,g=new Xfo;g.tr.set(0,0,A);const I=e.globalXfoParam.value;e.globalXfoParam.value=I.multiply(g)},s=()=>{const A=a*this.dollySpeedParam.value,g=e.getFrustumHeight(),I=g*A;e.setFrustumHeight(g+I)};e.isOrthographic()?s():B()}zoom(A,g,I){const C=A.viewport,e=C.getCamera(),i=e.getFocalDistance(),t=new Vec2(.5*C.getWidth()/window.devicePixelRatio,.5*C.getHeight()/window.devicePixelRatio),o=g.subtract(t).normalize(),a=I.dot(o),B=()=>{const A=-a*this.dollySpeedParam.value*i,g=new Xfo;g.tr.set(0,0,A);const I=e.globalXfoParam.value;e.setFocalDistance(i+A),e.globalXfoParam.value=I.multiply(g)},s=()=>{const A=-a*this.dollySpeedParam.value,g=e.getFrustumHeight(),I=g*A;e.setFrustumHeight(g+I)};e.isOrthographic()?s():B()}initDrag(A){this.pointerDown=!0;const g=A.viewport.getCamera(),I=g.globalXfoParam.value;if(this.orbitAroundCursor)if(null!=A.intersectionData&&this.orbitAroundCursor){this.orbitTarget=A.intersectionData.intersectionPos;const C=I.inverse().transformVec3(A.intersectionData.intersectionPos);g.setFocalDistance(-C.z)}else this.orbitTarget||(A.pointerRay?this.orbitTarget=A.pointerRay.pointAtDist(g.getFocalDistance()):this.orbitTarget=I.tr.add(I.ori.getZaxis().scale(-g.getFocalDistance())));else this.orbitTarget=I.tr.add(I.ori.getZaxis().scale(-g.getFocalDistance()));this.dragging=1}endDrag(A){A.getCapture()==this&&A.releaseCapture(),this.dragging=0,this.pointerDown=!1}aimFocus(A,g,I=-1,C=400){this.focusIntervalId&&clearInterval(this.focusIntervalId);const e=Math.round(C/20),i=this.defaultManipulationState;let t=0;const o=()=>{const C=A.globalXfoParam.value,a=A.getFocalDistance(),B=g.subtract(C.tr),s=B.normalizeInPlace(),l=C.clone();if(i==MANIPULATION_MODES.turntable||i==MANIPULATION_MODES.look){{const A=C.ori.getZaxis().clone();A.z=0;const g=B.negate();g.z=0;const I=new Quat;I.setFrom2Vectors(A,g),l.ori=I.multiply(l.ori)}{const A=C.ori.getXaxis().clone(),g=C.ori.getZaxis().clone(),I=B.negate();I.subtractInPlace(A.scale(I.dot(A))),I.normalizeInPlace();const e=new Quat;g.cross(I).dot(A)>0?e.rotateX(g.angleTo(I)):e.rotateX(-g.angleTo(I)),l.ori=l.ori.multiply(e)}{const A=l.ori.getXaxis().clone(),g=A.clone();g.z=0,g.normalizeInPlace();const I=new Quat;I.setFrom2Vectors(A,g),l.ori=I.multiply(l.ori)}}else{const A=C.ori.getZaxis().clone(),g=B.negate(),I=new Quat;I.setFrom2Vectors(A,g),l.ori=I.multiply(l.ori)}const n=Math.pow(t/e,2),d=C.clone();if(d.ori=C.ori.lerp(l.ori,n),I>0){const A=B.scale(s-I);d.tr.addInPlace(A.scale(n))}A.setFocalDistance(a+(s-a)*n),A.globalXfoParam.value=d,t++,t<=e?this.focusIntervalId=setTimeout(o,20):(this.focusIntervalId=void 0,this.emit("movementFinished"),A.emit("movementFinished"))};o()}orientPointOfView(A,g,I,C=0,e=400){this.focusIntervalId&&clearInterval(this.focusIntervalId);const i=Math.round(e/20);let t=0;const o=()=>{const e=A.globalXfoParam.value,a=A.getTargetPosition(),B=Math.pow(t/i,2),s=g.subtract(e.tr),l=s.normalizeInPlace(),n=s.scale(l-C),d=e.tr.add(n.scale(B)),r=a.lerp(I,B);A.setPositionAndTarget(d,r),t++,t<=i?this.focusIntervalId=setTimeout(o,20):(this.focusIntervalId=void 0,this.emit("movementFinished"),A.emit("movementFinished"))};o()}onPointerDoubleClick(A){const g=g=>{const I=A.viewport.getCamera(),C=I.globalXfoParam.value.tr.add(g.dir.scale(A.intersectionData.dist));this.aimFocus(I,C),A.aimTarget=C,A.aimDistance=A.intersectionData.dist,this.emit("aimingFocus",A),I.emit("aimingFocus",A),A.stopPropagation()};if(A.intersectionData&&this.aimFocusOnMouseClick){if(A instanceof ZeaMouseEvent&&2==this.aimFocusOnMouseClick){const I=A;g(I.pointerRay),I.preventDefault()}if(A instanceof ZeaTouchEvent&&2==this.aimFocusOnTouchTap){g(A.pointerRay)}}}onPointerDown(A){if(A instanceof ZeaMouseEvent){1==this.dragging&&this.endDrag(A),this.initDrag(A);const g=A;this.prevMousePos=g.pointerPos,2==g.button?this.manipulationState=MANIPULATION_MODES.pan:g.ctrlKey&&g.altKey?this.manipulationState=MANIPULATION_MODES.dolly:g.ctrlKey||2==g.button?this.manipulationState=MANIPULATION_MODES.look:this.manipulationState=this.defaultManipulationState,g.preventDefault()}else A instanceof ZeaTouchEvent&&this._onTouchStart(A)}onPointerMove(A){0!=this.dragging&&(A instanceof ZeaMouseEvent&&(this._onMouseMove(A),A.preventDefault()),A instanceof ZeaTouchEvent&&this._onTouchMove(A),this.dragging=2,A.setCapture(this),A.stopPropagation())}_onMouseMove(A){if(!this.pointerDown)return;const g=A.pointerPos,I=g.subtract(this.prevMousePos);switch(this.manipulationState){case MANIPULATION_MODES.turntable:this.turntable(A,I);break;case MANIPULATION_MODES.tumbler:this.tumbler(A,I);break;case MANIPULATION_MODES.trackball:this.trackball(A,I);break;case MANIPULATION_MODES.look:this.look(A,I);break;case MANIPULATION_MODES.pan:this.pan(A,g.subtract(this.prevMousePos));break;case MANIPULATION_MODES.dolly:this.dolly(A,g,I);break;case MANIPULATION_MODES.zoom:this.zoom(A,g,I)}this.prevMousePos=g}_onTouchMove(A){const g=A.touches;if(1==g.length){const I=g[0],C=I.touchPos,e=this.ongoingTouches[I.identifier];if(!e)return;const i=C.subtract(e.pos);switch(this.defaultManipulationState){case MANIPULATION_MODES.look:i.scaleInPlace(6),this.look(A,i);break;case MANIPULATION_MODES.turntable:this.turntable(A,i);break;case MANIPULATION_MODES.tumbler:this.tumbler(A,i);break;case MANIPULATION_MODES.trackball:this.trackball(A,i);break;case MANIPULATION_MODES.pan:this.pan(A,i);break;case MANIPULATION_MODES.dolly:this.dolly(A,C,i);break;case MANIPULATION_MODES.zoom:this.zoom(A,e.pos,i)}e.pos=C}else if(2==g.length){const I=g[0],C=this.ongoingTouches[I.identifier],e=g[1],i=this.ongoingTouches[e.identifier];if(!C||!i)return;const t=I.touchPos,o=e.touchPos,a=i.pos.subtract(C.pos).length()-o.subtract(t).length(),B=t.subtract(C.pos),s=o.subtract(i.pos),l=B.add(s);l.scaleInPlace(.5);const n=.002*a,{viewport:d}=A,r=d.getCamera(),c=r.getFocalDistance(),h=r.getFov(),G=new Vec3(1,0,0),m=new Vec3(0,1,0),b=2*c*Math.tan(.5*h),Z=b*(d.getWidth()/d.getHeight()),u=new Xfo;u.tr=G.scale(-l.x/d.getWidth()*Z),u.tr.addInPlace(m.scale(l.y/d.getHeight()*b));const y=n*c;switch(r.setFocalDistance(c+y),u.tr.z+=y,this.defaultManipulationState){case MANIPULATION_MODES.tumbler:case MANIPULATION_MODES.trackball:const A=i.pos.subtract(C.pos),g=o.subtract(t);let I=A.normalize().angleTo(g.normalize());A.cross(g)<0&&(I=-I);const e=new Quat;e.rotateZ(I),u.ori.multiplyInPlace(e)}const E=r.globalXfoParam.value;r.globalXfoParam.value=E.multiply(u),C.pos=t,i.pos=o}}onPointerUp(A){if(1==this.dragging){if(this.endDrag(A),A.intersectionData&&(A instanceof ZeaMouseEvent&&1==this.aimFocusOnMouseClick||A instanceof ZeaTouchEvent&&1==this.aimFocusOnTouchTap)){const g=A.viewport.getCamera(),I=g.globalXfoParam.value,C=A.pointerRay,e=I.tr.add(C.dir.scale(A.intersectionData.dist));this.aimFocus(g,e),A.aimTarget=e,A.aimDistance=A.intersectionData.dist,this.emit("aimingFocus",A),g.emit("aimingFocus",A),A.stopPropagation(),A instanceof ZeaMouseEvent&&A.preventDefault()}}else if(2==this.dragging){if(A instanceof ZeaMouseEvent){this.endDrag(A),A.releaseCapture(),this.emit("movementFinished");A.viewport.getCamera().emit("movementFinished")}else if(A instanceof ZeaTouchEvent){const g=A,{changedTouches:I,touches:C}=g;for(let A=0;A<I.length;A++)this.__endTouch(I[A]);if(0==Object.keys(this.ongoingTouches).length){this.endDrag(A),A.releaseCapture();A.viewport.getCamera().emit("movementFinished")}g.preventDefault()}A.releaseCapture(),A.stopPropagation()}}onPointerLeave(A){this.keysPressed.length>0&&(this.keysPressed=[],this.velocity.set(0,0,0),this.keyboardMovement=!1)}onWheel(A){const g=A.viewport.getCamera(),I=this.mouseWheelDollySpeedParam.value,C=A.shiftKey?.1:.5,e=g.globalXfoParam.value;let i;if(!g.isOrthographic())if(this.zoomTowardGeomUnderCursor)if(null!=A.intersectionData){i=e.tr.subtract(A.intersectionData.intersectionPos),i.normalizeInPlace();const I=e.inverse().transformVec3(A.intersectionData.intersectionPos);g.setFocalDistance(-I.z)}else{const I=A.pointerRay.pointAtDist(g.getFocalDistance());i=e.tr.subtract(I),i.normalizeInPlace()}else i=g.globalXfoParam.value.ori.getZaxis();const t=A.deltaY<0?-1:1,o=()=>{const A=g.getFocalDistance(),I=A*this.mouseWheelMovementDist;e.tr.addInPlace(i.scale(I)),g.setFocalDistance(A+I),g.globalXfoParam.value=e,this.mouseWheelZoomCount++,this.mouseWheelZoomCount<6?this.mouseWheelZoomId=window.setTimeout(o,10):(this.mouseWheelZoomId=-1,this.emit("movementFinished"),g.emit("movementFinished"))},a=()=>{const A=50*this.mouseWheelMovementDist;(new Xfo).tr.set(0,0,A),e.tr.addInPlace(i.scale(A)),g.globalXfoParam.value=e},B=()=>{const I=g.getFrustumHeight(),C=I*this.mouseWheelMovementDist;if(g.setFrustumHeight(I+C),A.intersectionData&&this.zoomTowardGeomUnderCursor){const i=e.tr.subtract(A.intersectionData.intersectionPos),t=e.ori.getZaxis();i.subtractInPlace(t.scale(i.dot(t))),e.tr.addInPlace(i.scale(C/(I+C))),g.globalXfoParam.value=e}this.mouseWheelZoomCount++,this.mouseWheelZoomCount<6?this.mouseWheelZoomId=window.setTimeout(B,10):(this.mouseWheelZoomId=-1,this.emit("movementFinished"),g.emit("movementFinished"))};this.mouseWheelZoomId>0?(this.mouseWheelMovementDist+=t*I*C*.5/6,this.mouseWheelZoomCount=0):(this.mouseWheelMovementDist=t*I*C/6,this.mouseWheelZoomCount=0,g.isOrthographic()?B():A.ctrlKey?a():o()),A.preventDefault(),A.stopPropagation()}integrateVelocityChange(A){const{viewport:g}=A,I=g.getCamera(),C=performance.now();if(this.prevVelocityIntegrationTime>0){const A=(C-this.prevVelocityIntegrationTime)/1e3,e=this.walkSpeedParam.value;if(e>0){const C=new Xfo;C.tr=this.velocity.normalize().scale(e*A);const i=I.globalXfoParam.value.multiply(C);if(this.walkModeCollisionDetection.value){const A=1.5,I=1.5,C=.5,e=new Xfo(i.tr),t=new Ray(i.tr,new Vec3(0,0,-1)),o=g.getRenderer().raycastCluster(e,t,I,C,PassType.OPAQUE);if(o.length>0){let g=0;o.forEach((A=>{g+=A.dist})),g/=o.length,i.tr=t.start.add(t.dir.scale(g-A))}}I.globalXfoParam.value=i}}this.prevVelocityIntegrationTime=C}onKeyDown(A){if(!this.enabledWASDWalkMode)return;const g=A.key.toLowerCase();if(!this.keysPressed.includes(g)){switch(g){case"w":this.velocity.z-=1;break;case"s":this.velocity.z+=1;break;case"a":this.velocity.x-=1;break;case"d":this.velocity.x+=1;break;default:return}if(A.stopPropagation(),this.keysPressed.push(g),!this.keyboardMovement){this.keyboardMovement=!0,this.prevVelocityIntegrationTime=performance.now();const g=()=>{this.integrateVelocityChange(A),this.keyboardMovement&&window.requestAnimationFrame(g)};window.requestAnimationFrame(g)}}}onKeyUp(A){const g=A.key.toLowerCase();if(!this.keysPressed.includes(g))return;switch(g){case"w":this.velocity.z+=1;break;case"s":this.velocity.z-=1;break;case"a":this.velocity.x+=1;break;case"d":this.velocity.x-=1;break;default:return}A.stopPropagation();const I=this.keysPressed.indexOf(g);this.keysPressed.splice(I,1),0==this.keysPressed.length&&(this.keyboardMovement=!1)}__startTouch(A){this.ongoingTouches[A.identifier]={identifier:A.identifier,pos:A.touchPos}}__endTouch(A){delete this.ongoingTouches[A.identifier]}_onTouchStart(A){const g=A.changedTouches;for(let A=0;A<g.length;A++)this.__startTouch(g[A]);this.initDrag(A)}onTouchEnd(A){A.preventDefault(),A.stopPropagation();const g=A.changedTouches;for(let A=0;A<g.length;A++)this.__endTouch(g[A]);0==Object.keys(this.ongoingTouches).length&&this.endDrag(A)}onTouchCancel(A){A.preventDefault();const g=A.touches;for(let A=0;A<g.length;A++)this.__endTouch(g[A]);0==Object.keys(this.ongoingTouches).length&&this.endDrag(A)}static get MANIPULATION_MODES(){return MANIPULATION_MODES}}var GeomType$2;!function(A){A[A.TRIANGLES=0]="TRIANGLES",A[A.LINES=1]="LINES",A[A.POINTS=2]="POINTS"}(GeomType$2||(GeomType$2={}));const create3DContext=function(A,g){let I=null;if(null!=g.webglContextType)try{I=A.getContext(g.webglContextType,g),I.name=g.webglContextType}catch(A){}else{const C=["webgl2","webgl"];for(let e=0;e<C.length;e++){const i=C[e];try{I=A.getContext(i,g),I.name=i}catch(A){}if(I)break}}if(!I)throw new Error("WebGL not supported on your system");return I.sizeInBytes=function(A){switch(A){case this.BYTE:case this.UNSIGNED_BYTE:return 1;case this.SHORT:case this.UNSIGNED_SHORT:return 2;case this.INT:case this.UNSIGNED_INT:case this.FLOAT:return 4;default:throw new Error("unknown type")}},I.floatTexturesSupported=!0,I.__ext_texture_float=I.getExtension("OES_texture_float"),I.__ext_float_linear=I.getExtension("OES_texture_float_linear"),I.__ext_texture_half_float=I.getExtension("OES_texture_half_float"),I.__ext_texture_half_float_linear=I.getExtension("OES_texture_half_float_linear"),I.__ext_color_buffer_float=I.getExtension("EXT_color_buffer_float"),I.setupInstancedQuad=function(){const A=new Float32Array([0,1,2,3]),g=new Uint8Array([0,1,2,2,1,3]);this.__quadVertexIdsBuffer=this.createBuffer(),this.bindBuffer(this.ARRAY_BUFFER,this.__quadVertexIdsBuffer),this.bufferData(this.ARRAY_BUFFER,A,this.STATIC_DRAW),this.__quadIndexBuffer=this.createBuffer(),this.bindBuffer(this.ELEMENT_ARRAY_BUFFER,this.__quadIndexBuffer),this.bufferData(this.ELEMENT_ARRAY_BUFFER,g,this.STATIC_DRAW),this.__quadattrbuffers={vertexIDs:{buffer:this.__quadVertexIdsBuffer,dataType:I.FLOAT,dimension:1,elementSize:4,count:A.length,shared:!0}}},I.drawQuad=function(){this.drawElements(this.TRIANGLES,6,this.UNSIGNED_BYTE,0)},I},processTextureParams=function(A,g){if(!g.width||!g.height){if(!g.width)throw new Error("Invalid texture params. 'width' not provided");if(!g.height)throw new Error("Invalid texture params. 'height' not provided")}const I=A.getParameter(A.MAX_TEXTURE_SIZE);if(g.width<=0||g.width>I||g.height<=0||g.height>I)throw new Error("GLTextureParams: Invalid texture size. width:"+g.width+" height:"+g.height+" maxSize:"+I);const C={width:g.width,height:g.height},e=g=>isNaN(g)?A[g]:g,i=(A,I)=>{A in g?C[A]=e(g[A]):I&&(C[A]=e(I))};if(i("format"),i("internalFormat",C.format),i("type",A.UNSIGNED_BYTE),i("minFilter",g.filter?g.filter:A.LINEAR),i("magFilter",g.filter?g.filter:A.LINEAR),i("wrapS",g.wrapS?g.wrapS:A.CLAMP_TO_EDGE),i("wrapT",g.wrapT?g.wrapT:A.CLAMP_TO_EDGE),i("mipMapped",!1),i("depthInternalFormat"),i("depthFormat"),i("depthType"),g.createDepthTexture&&("webgl2"==A.name||A.__ext_WEBGL_depth_texture?(C.depthFormat=A.DEPTH_COMPONENT,C.depthType=A.UNSIGNED_INT):C.depthType=A.UNSIGNED_SHORT),C.format==A.FLOAT)C.filter!=A.LINEAR||A.__ext_float_linear||(console.warn("Floating point texture filtering not supported on result device"),C.filter=A.NEAREST);else if(C.format==A.HALF_FLOAT);else if("sRGB"==C.format&&!A.__ext_sRGB)throw new Error("EXT_sRGB is not available");return null!=C.format&&C.internalFormat==C.format&&(C.type==A.FLOAT?C.format==A.RED?C.internalFormat=A.R32F:C.format==A.RG?C.internalFormat=A.RG32F:C.format==A.RGB?C.internalFormat=A.RGB32F:C.format==A.RGBA&&(C.internalFormat=A.RGBA32F):C.type==A.HALF_FLOAT?C.format==A.RED?C.internalFormat=A.R16F:C.format==A.RGB?C.internalFormat=A.RGB16F:C.format==A.RGBA&&(C.internalFormat=A.RGBA16F):C.type==A.UNSIGNED_BYTE&&(C.format==A.RED&&(C.internalFormat=A.R8),C.format==A.RGB?C.internalFormat=A.RGB8:C.format==A.RGBA&&(C.internalFormat=A.RGBA8))),null!=C.depthFormat&&(C.depthType==A.UNSIGNED_SHORT?C.depthInternalFormat=A.DEPTH_COMPONENT16:C.depthType==A.UNSIGNED_INT&&(C.depthInternalFormat=A.DEPTH_COMPONENT24)),C};class GLTexture2D extends RefCounted{gl;width=0;height=0;textureType;textureDesc;loaded;image=null;internalFormat=0;format=0;type=0;minFilter=0;magFilter=0;wrapS=0;wrapT=0;mipMapped=!1;invert=!1;gltex=null;constructor(A,g){if(super(),this.gl=A,this.textureType=1,this.textureDesc=[0,0,0,0],this.loaded=!1,null!=g)if(g instanceof BaseImage){this.image=g;const A=()=>{const A=this.image.getParams(),g=A.width,I=A.height,C=A.data;this.bufferData(C,g,I)};this.image.on("updated",A),this.image.isLoaded()?this.configure(this.image.getParams()):this.image.on("loaded",(()=>{this.configure(this.image.getParams())}))}else this.configure(g)}configure(A){const g=this.gl;{const I=processTextureParams(g,A);this.format=I.format,this.internalFormat=I.internalFormat,this.type=I.type,this.minFilter=I.minFilter,this.magFilter=I.magFilter,this.wrapS=I.wrapS,this.wrapT=I.wrapT,this.mipMapped="mipMapped"in A&&A.mipMapped}this.textureType=1,this.textureDesc[0]=this.width,this.textureDesc[1]=this.height,1==this.textureType&&this.format==g.RGBA&&(this.textureType=2),this.gltex&&(g.deleteTexture(this.gltex),this.width=0,this.height=0),this.gltex=g.createTexture(),this.updateGLTexParams();const I=A.data;I?this.bufferData(I,A.width,A.height,!1,!1):this.resize(A.width,A.height,!1,!1),this.loaded||(this.emit("ready"),this.loaded=!0)}activateLastTextureUnit(){const A=this.gl,g=A.getParameter(A.MAX_TEXTURE_IMAGE_UNITS);A.activeTexture(A.TEXTURE0+g-1)}updateGLTexParams(){const A=this.gl;this.activateLastTextureUnit(),A.bindTexture(A.TEXTURE_2D,this.gltex),A.texParameteri(A.TEXTURE_2D,A.TEXTURE_MAG_FILTER,this.minFilter),A.texParameteri(A.TEXTURE_2D,A.TEXTURE_MIN_FILTER,this.magFilter),A.texParameteri(A.TEXTURE_2D,A.TEXTURE_WRAP_S,this.wrapS),A.texParameteri(A.TEXTURE_2D,A.TEXTURE_WRAP_T,this.wrapT)}bufferData(A,g=-1,I=-1,C=!0,e=!0){const i=this.gl;if(null!=A){if(A instanceof WebGLTexture)this.gltex=A;else if(A instanceof HTMLImageElement||A instanceof ImageData||A instanceof HTMLCanvasElement||A instanceof HTMLImageElement||A instanceof HTMLVideoElement)C&&(this.activateLastTextureUnit(),i.bindTexture(i.TEXTURE_2D,this.gltex)),i.texImage2D(i.TEXTURE_2D,0,this.internalFormat,this.format,this.type,A),this.width=A.width,this.height=A.height;else{-1==g&&(g=this.width),-1==I&&(I=this.height);const e=g*I;let t;switch(this.format){case i.RED:case i.RED_INTEGER:case i.ALPHA:case i.LUMINANCE:case i.LUMINANCE_ALPHA:t=1;break;case i.RG:t=2,i.pixelStorei(i.UNPACK_ALIGNMENT,2);break;case i.RGB:case i.RGB_INTEGER:t=3;break;case i.RGBA:case i.RGBA_INTEGER:t=4;break;default:console.warn("Reaching default case: numChannels:=1"),t=1}A.length!=e*t&&console.warn("Invalid data for Image width:"+g+" height:"+I+" Data Length:"+A.length+" Expected:"+e*t);let o=A;this.type==i.HALF_FLOAT&&A instanceof Float32Array&&(o=MathFunctions.convertFloat32ArrayToUInt16Array(A)),C&&(this.activateLastTextureUnit(),i.bindTexture(i.TEXTURE_2D,this.gltex)),i.texImage2D(i.TEXTURE_2D,0,this.internalFormat,g,I,0,this.format,this.type,o,0),this.width=g,this.height=I}this.mipMapped&&i.generateMipmap(i.TEXTURE_2D)}else C&&(this.activateLastTextureUnit(),i.bindTexture(i.TEXTURE_2D,this.gltex)),i.texImage2D(i.TEXTURE_2D,0,this.internalFormat,this.width,this.height,0,this.format,this.type,null),this.width=g,this.height=I;e&&this.emit("updated")}clear(){const A=this.gl,g=this.width*this.height;let I,C;switch(this.format){case A.RED:case A.RED_INTEGER:case A.ALPHA:case A.LUMINANCE:case A.LUMINANCE_ALPHA:I=1;break;case A.RG:I=2;break;case A.RGB:I=3;break;case A.RGBA:I=4;break;default:throw new Error("Invalid Format")}switch(this.type){case A.UNSIGNED_BYTE:C=new Uint8Array(g*I);break;case A.HALF_FLOAT:C=new Uint16Array(g*I);break;case A.FLOAT:C=new Float32Array(g*I);break;default:throw new Error("Invalid Type")}A.texImage2D(A.TEXTURE_2D,0,this.internalFormat,this.width,this.height,0,this.format,this.type,C,0)}resize(A,g,I=!1,C=!0){const e=this.gl;if(this.width!=A||this.height!=g){const i=e.getParameter(e.MAX_TEXTURE_SIZE);if(A<0||A>i||g<0||g>i)throw new Error("gl-texture2d: Invalid texture size. width:"+A+" height:"+g+" maxSize:"+i);if(I){const I=e.createTexture();this.activateLastTextureUnit(),e.bindTexture(e.TEXTURE_2D,I),e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,A,g,0,this.format,this.type,null);const C=e.createFramebuffer();e.bindFramebuffer(e.FRAMEBUFFER,C),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.gltex,0),e.copyTexImage2D(e.TEXTURE_2D,0,this.internalFormat,0,0,this.width,this.height,0),e.bindFramebuffer(e.FRAMEBUFFER,null),e.deleteFramebuffer(C),this.gl.deleteTexture(this.gltex),this.gltex=I,this.updateGLTexParams()}else this.width>0&&this.height>0&&(this.gl.deleteTexture(this.gltex),this.gltex=e.createTexture(),this.updateGLTexParams()),e.bindTexture(e.TEXTURE_2D,this.gltex),e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,A,g,0,this.format,this.type,null);if(this.width=A,this.height=g,C){const I=new ResizedEvent(A,g);this.emit("resized",I)}}}populate(A,g,I,C=0,e=0,i=!0){const t=this.gl;i&&(this.activateLastTextureUnit(),t.bindTexture(t.TEXTURE_2D,this.gltex)),t.texSubImage2D(t.TEXTURE_2D,0,C,e,g,I,this.format,this.type,A),i&&t.bindTexture(t.TEXTURE_2D,null)}getSize(){return[this.width,this.height]}get glTex(){return this.gltex}getTexHdl(){return this.gltex}preBind(A,g){return{textureTypeUnif:g[A.name+"Type"],textureDescUnif:g[A.name+"Desc"]}}bindToUniform(A,g,I){if(!this.loaded)return!1;if(!this.gltex)throw new Error("Unable to bind non-initialized or deleted texture.");if(A.bindTexture(g,this.gltex),I){const A=this.gl;I.textureTypeUnif&&A.uniform1i(I.textureTypeUnif.location,this.textureType),I.textureDescUnif&&A.uniform4fv(I.textureDescUnif.location,this.textureDesc)}return!0}destroy(){super.destroy(),this.gl.deleteTexture(this.gltex),this.gltex=null}}const WHITESPACE_RE=/\s+/;class ShaderLibrary{__shaderModules;materialTemplates;constructor(){this.__shaderModules={},this.materialTemplates={}}setShaderModule(A,g){A in this.__shaderModules||(this.__shaderModules[A]=g)}getShaderModule(A){return this.__shaderModules[A]}getShaderModuleNames(){const A=[];for(const g in this.__shaderModules)A.push(g);return A}parseAttr(A,g,I,C){const e=A[2].slice(0,A[2].length-1),i=A[1],t="int"==i||"uint"==i||"ivec2"==i||"ivec3"==i||"ivec4"==i;I.attributes[e]={glslType:i,instanced:g,integer:t},"color"==A[1]&&(A[1]="vec4",A.join(" "))}handleImport(A,g,I,C,e){if(I in this.__shaderModules){const i=this.__shaderModules[I];if(!i)throw Error("snippet not loaded or does not exists!");const t=this.parseShaderHelper(g,i,C,e);C.push(I),A.glsl=A.glsl+t.glsl,A.numLines+=t.numLines,A.uniforms={...A.uniforms,...t.uniforms},A.attributes={...A.attributes,...t.attributes}}else console.log("shaderName: "+g),console.log("SNIPPET NOT FOUND: "+I)}parseShader(A,g){return this.parseShaderHelper(A,g,[],0)}parseShaderHelper(A,g,I,C){const e=(A,g)=>{A.glsl=A.glsl+g+"\n",A.numLines++};I.push(A);const i={glsl:"",numLines:0,uniforms:{},attributes:{}},t=(g=g.toString()).split("\n");for(let g=0;g<t.length;g++){let o=t[g];const a=o.trim(),B=a.split(WHITESPACE_RE);switch(B[0]){case"<%include":case"import":{const g=a.split(/'|"|`/)[1].split("/").pop();I.includes(g)||this.handleImport(i,A,g,I,C);break}case"attribute":this.parseAttr(B,!1,i,o),e(i,o);break;case"instancedattribute":this.parseAttr(B,!0,i,o),B[0]="attribute",o=B.join(" "),e(i,o);break;case"uniform":{let A=1;4==B.length&&(A=2);const g=B[A],I=B[A+1].slice(0,B[A+1].length-1);I.includes("[")?i.uniforms[I.substring(0,I.indexOf("["))]={glslType:g}:i.uniforms[I]={glslType:g},"struct"==g&&console.log(B),"color"==B[1]&&(B[1]="vec4",o=B.join(" ")),e(i,o);break}default:e(i,o)}}return i}}const shaderLibrary=new ShaderLibrary;class RenderState{gl;renderer;stack=[];top;glShader;shaderkey;directives=[];directivesHash;attrs;unifs;drawItemsTexture;shaderInstancedGeom;glGeom;boundVao;xrviewport;passIndex;pass;vrPresenting;supportsInstancing;viewport;viewports;bindViewports;bindRendererUnifs;boundTextures;boundRendertarget;geometryMaskTextures;viewXfo;viewScale;region;depthRange;cameraMatrix;constructor(A){this.gl=A}pushGLStack(A){this.top,this.top={name:A,enabled:new Set,disabled:new Set,functions:{}},this.stack.push(this.top)}popGLStack(){const A=this.stack.pop();this.top=this.stack[this.stack.length-1],this.stack.length>0&&(A.enabled.forEach((A=>{let g;for(g=this.stack.length-1;g>=0;g--){const I=this.stack[g];if(I.enabled.has(A))break;if(I.disabled.has(A)){this.gl.disable(A);break}}g<0&&this.gl.disable(A)})),A.disabled.forEach((A=>{let g;for(g=this.stack.length-1;g>=0;g--){const I=this.stack[g];if(I.disabled.has(A))break;if(I.enabled.has(A)){this.gl.enable(A);break}}g<0&&this.gl.enable(A)})))}glEnable(A){this.gl.enable(A),this.top.enabled.add(A)}glDisable(A){this.gl.disable(A),this.top.disabled.add(A)}bindTexture(A,g){const I=this.boundTextures++,C=this.gl;C.activeTexture(C.TEXTURE0+I),C.bindTexture(C.TEXTURE_2D,g),C.uniform1i(A.location,I)}}class HighlightRenderState extends RenderState{}class ColorRenderState extends RenderState{envMap;renderMode;outlineMethod;outlineThickness;outlineColor;hiddenLineColor;screenQuad;exposure;gamma;toHighlightRenderState(){const A=new HighlightRenderState(this.gl);return A.boundRendertarget=this.boundRendertarget,A.viewXfo=this.viewXfo,A.viewScale=this.viewScale,A.region=this.region,A.cameraMatrix=this.cameraMatrix,A.viewport=this.viewport,A.vrPresenting=this.vrPresenting,A.bindViewports=this.bindViewports,A.bindRendererUnifs=this.bindRendererUnifs,A}}class GeomDataRenderState extends RenderState{geomDataFbo;floatGeomBuffer;occlusionCulling;debugGeomDataBuffer;pointAndLinePickingSize}let shaderInstanceId=0;class GLShader extends BaseItem{__gl;shaderStagesGLSL={};shaderStages={};shaderProgramHdls={};constructor(A,g){super(g),A&&(this.__gl=A),this.__id=shaderInstanceId++,this.__shaderStages=this.shaderStages}setGLContext(A){this.__gl=A}setShaderStage(A,g){this.shaderStagesGLSL[A]=g,this.clearProgramsCache()}getShaderStage(A){return this.shaderStagesGLSL[A]}clearProgramsCache(){const A=this.__gl;for(const g in this.shaderProgramHdls){const I=this.shaderProgramHdls[g];for(const g in I.shaderHdls)A.deleteShader(I.shaderHdls[g]);A.deleteProgram(I.shaderProgramHdl)}}static isOpaque(){return!0}static isOverlay(){return!1}generateNumberedLines(A,g,I,C){const e=[];for(const i in C){const t=Number.parseInt(i)-1;for(let I=Math.max(0,t-g);I<t;I++)e.push((I+1+" ").padStart(3)+"[34;107;2m"+A[I]+"[m");e.push((t+1+">").padStart(3)+"[41;93;4m"+A[t]+"[m");for(let g=t+1;g<Math.min(A.length-1,t+I);g++)e.push((g+1+" ").padStart(3)+"[34;107;2m"+A[g]+"[m");const o=C[i];for(const A of o)e.push(A)}return e}compileShaderStage(A,g,I,C){const e=this.__gl;if(C){A=C.join("\n")+"\n"+A}A=StringFunctions.replaceAll(A,"attribute","in"),A="vertexShader"==I?StringFunctions.replaceAll(A,"varying","out"):StringFunctions.replaceAll(A,"varying","in");A="#version 300 es\n"+(A=StringFunctions.replaceAll(A,"texture2D","texture"));const i=e.createShader(g);if(!i)throw Error("shaderHdl not defined");if(e.shaderSource(i,A),e.compileShader(i),!e.getShaderParameter(i,e.COMPILE_STATUS)){console.log("Errors in :"+this.constructor.name+"."+I);const g=e.getShaderInfoLog(i).split("\n"),C={};for(let A=0;A<g.length;A++){const I=g[A].split(":");if(I.length>=2){const e=parseInt(I[2]);isNaN(e)||(C[e]?C[e].push(g[A]):C[e]=[g[A]])}}const t=A.split("\n");console.groupCollapsed("ShaderError-All");this.generateNumberedLines(t,t.length,t.length,C).forEach((A=>console.info(A))),console.groupEnd(),console.group("ShaderError-Summary");throw this.generateNumberedLines(t,4,5,C).forEach((A=>console.info(A))),console.groupEnd(),new Error("An error occurred compiling the shader \n=================\n"+this.constructor.name+"."+I)}return i}createProgram(A){const g=this.__gl,I=g.createProgram();if(!I)throw Error("shaderProgramHdl not defined");const C={};{this.shaderStages.VERTEX_SHADER||(this.shaderStages.VERTEX_SHADER=shaderLibrary.parseShader("VERTEX_SHADER",this.shaderStagesGLSL.VERTEX_SHADER));const e=this.shaderStages.VERTEX_SHADER.glsl;if(null!=e){const i=this.compileShaderStage(e,g.VERTEX_SHADER,"vertexShader",A);if(!i)return;g.attachShader(I,i),C[g.VERTEX_SHADER]=i}}{this.shaderStages.FRAGMENT_SHADER||(this.shaderStages.FRAGMENT_SHADER=shaderLibrary.parseShader("FRAGMENT_SHADER",this.shaderStagesGLSL.FRAGMENT_SHADER));const e=this.shaderStages.FRAGMENT_SHADER.glsl;if(null!=e){const i=this.compileShaderStage(e,g.FRAGMENT_SHADER,"fragmentShader",A);if(!i)return;g.attachShader(I,i),C[g.FRAGMENT_SHADER]=i}}if(g.linkProgram(I),!g.getProgramParameter(I,g.LINK_STATUS)){const A=g.getProgramInfoLog(I);if(!A)throw Error("info not defined");if(A.includes("D3D shader compilation failed")){const A=g.getExtension("WEBGL_debug_shaders");if(A){const I=A.getTranslatedShaderSource(C[g.VERTEX_SHADER]);console.log(I)}}throw console.groupCollapsed("vertexShaderGLSL"),console.log(this.shaderStages.VERTEX_SHADER.glsl),console.groupEnd(),console.groupCollapsed("fragmentShaderGLSL"),console.log(this.shaderStages.FRAGMENT_SHADER.glsl),console.groupEnd(),new Error("Unable to link the shader program:"+this.constructor.name+"\n==================\n"+A)}const e=this.extractAttributeAndUniformLocations(I);return{shaderHdls:C,shaderProgramHdl:I,unifs:e.unifs,attrs:e.attrs}}extractAttributeAndUniformLocations(A){const g=this.__gl,I=this.getAttributes(),C={attrs:{},unifs:{}};for(const e in I){const i=g.getAttribLocation(A,e);if(null==i){console.warn("Shader attribute not found:"+e);continue}const t=I[e];C.attrs[e]={name:e,location:i,glslType:t.glslType,instanced:t.instanced,integer:t.integer}}const e=this.getUniforms();for(let I in e){const i=e[I],t=g.getUniformLocation(A,I);null!=t&&(C.unifs[I]={name:I,location:t,glslType:i.glslType})}return C}getAttributes(){const A={};for(const g in this.shaderStages){const I=this.shaderStages[g];for(const g in I.attributes)A[g]=I.attributes[g]}return A}getUniforms(){const A={};for(const g in this.shaderStages){const I=this.shaderStages[g];for(const g in I.uniforms)A[g]=I.uniforms[g]}return A}isCompiledForTarget(A){const g=A+this.getId()+"";return null!=this.shaderProgramHdls[g]}compileForTarget(A,g){const I=A+this.getId()+"";let C=this.shaderProgramHdls[I];return C||(C=this.createProgram(g||[]),C&&(C.shaderkey=A),this.shaderProgramHdls[I]=C,C)}bind(A,g){const I=this.__gl;if(A.glShader!=this){const C=this.compileForTarget(g,A.directives);if(!C)return console.warn(this.constructor.name+" is not compiled for "+g),!1;const e=C.shaderProgramHdl;if(I.useProgram(e),A.glShader=this,A.shaderkey=C.shaderkey,A.unifs=C.unifs,A.attrs=C.attrs,A.boundTextures=0,A.glGeom=void 0,A.bindRendererUnifs&&A.bindRendererUnifs(C.unifs),A.geometryMaskTextures&&A.unifs.frontDepthTexture){const{frontDepthTexture:g,backDepthTexture:C,viewportSize:e}=A.unifs;A.bindTexture(g,A.geometryMaskTextures[0]),A.bindTexture(C,A.geometryMaskTextures[1]),I.uniform2f(e.location,A.region[2]-A.region[0],A.region[3]-A.region[1])}if(A instanceof GeomDataRenderState){const{floatGeomBuffer:g,occlusionCulling:C,debugGeomDataBuffer:e}=A.unifs;g&&I.uniform1i(g.location,A.floatGeomBuffer?1:0),C&&I.uniform1i(C.location,A.occlusionCulling),e&&I.uniform1i(e.location,A.debugGeomDataBuffer?1:0)}}return A.supportsInstancing=!0,!0}unbind(A){return A.glShader=null,A.shaderkey="",A.unifs={},A.attrs={},!0}getGeomDataShaderName(){return""}getSelectedShaderName(){return""}static supportsInstancing(){return!0}static getPackedMaterialData(A){return new Float32Array(4)}static getMaterialTemplate(){throw new Error("Shader does not provide a material template.")}destroy(){const A=this.__gl;for(const g in this.shaderProgramHdls){const I=this.shaderProgramHdls[g];A.deleteProgram(I.shaderProgramHdl)}this.shaderProgramHdls={}}}class GLFbo{colorTextureResizeEventId=-1;__gl;__colorTexture;__createDepthTexture;__clearColor;__depthTexture=null;__fbo=null;__prevBoundFbo=null;constructor(A,g,I=!1){this.__gl=A,this.__colorTexture=g,this.__createDepthTexture=I,this.__clearColor=new Color(0,0,0,0),this.__colorTexture&&(this.colorTextureResizeEventId=this.__colorTexture.on("resized",(()=>{console.warn("This code path will be deprecated. Instead, resize the GLFbo and it will resize the texture."),this.resize(this.__colorTexture.width,this.__colorTexture.height,!1)}))),this.setup()}setClearColor(A){this.__clearColor=A}getWidth(){return this.__colorTexture.width}getHeight(){return this.__colorTexture.height}getSize(){return[this.__colorTexture.width,this.__colorTexture.height]}getColorTexture(){return this.__colorTexture}getDepthTextureGL(){return this.__depthTexture}get width(){return this.__colorTexture.width}get height(){return this.__colorTexture.height}get size(){return[this.__colorTexture.width,this.__colorTexture.height]}get colorTexture(){return this.__colorTexture}setColorTexture(A){const g=this.__gl;this.__colorTexture=A,g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,this.__colorTexture.glTex,0)}get depthTextureGL(){return this.__depthTexture}setup(){const A=this.__gl;this.__fbo=A.createFramebuffer(),A.bindFramebuffer(A.DRAW_FRAMEBUFFER,this.__fbo),this.__colorTexture&&A.framebufferTexture2D(A.DRAW_FRAMEBUFFER,A.COLOR_ATTACHMENT0,A.TEXTURE_2D,this.__colorTexture.glTex,0),this.__createDepthTexture&&this.createDepthTexture(),checkFramebuffer(A,this.width,this.height),A.bindFramebuffer(A.DRAW_FRAMEBUFFER,null)}createDepthTexture(){const A=this.__gl;if("webgl2"==A.name||A.__ext_WEBGL_depth_texture)A.activeTexture(A.TEXTURE0),this.__depthTexture=A.createTexture(),A.bindTexture(A.TEXTURE_2D,this.__depthTexture),A.texParameteri(A.TEXTURE_2D,A.TEXTURE_MAG_FILTER,A.LINEAR),A.texParameteri(A.TEXTURE_2D,A.TEXTURE_MIN_FILTER,A.LINEAR),A.texParameteri(A.TEXTURE_2D,A.TEXTURE_WRAP_S,A.CLAMP_TO_EDGE),A.texParameteri(A.TEXTURE_2D,A.TEXTURE_WRAP_T,A.CLAMP_TO_EDGE),A.texImage2D(A.TEXTURE_2D,0,A.DEPTH_COMPONENT24,this.width,this.height,0,A.DEPTH_COMPONENT,A.UNSIGNED_INT,null),A.framebufferTexture2D(A.DRAW_FRAMEBUFFER,A.DEPTH_ATTACHMENT,A.TEXTURE_2D,this.__depthTexture,0);else{const g=A.createRenderbuffer();A.bindRenderbuffer(A.RENDERBUFFER,g),A.renderbufferStorage(A.RENDERBUFFER,A.DEPTH_COMPONENT16,this.width,this.height),A.framebufferRenderbuffer(A.FRAMEBUFFER,A.DEPTH_ATTACHMENT,A.RENDERBUFFER,g)}}resize(A,g,I=!0){const C=this.__gl;C.bindFramebuffer(C.FRAMEBUFFER,null),C.deleteFramebuffer(this.__fbo),I&&this.__colorTexture.resize(A,g,!1,!1),this.__fbo=C.createFramebuffer(),C.bindFramebuffer(C.DRAW_FRAMEBUFFER,this.__fbo),C.framebufferTexture2D(C.FRAMEBUFFER,C.COLOR_ATTACHMENT0,C.TEXTURE_2D,this.__colorTexture.glTex,0),this.__depthTexture&&(C.deleteTexture(this.__depthTexture),this.createDepthTexture()),checkFramebuffer(C,this.width,this.height),C.bindFramebuffer(C.DRAW_FRAMEBUFFER,null)}bindForWriting(A){A&&(this.__prevBoundFbo=A.boundRendertarget,A.boundRendertarget=this.__fbo);const g=this.__gl;g.bindFramebuffer(g.DRAW_FRAMEBUFFER,this.__fbo),g.viewport(0,0,this.width,this.height)}unbindForWriting(A){A&&(A.boundRendertarget=this.__prevBoundFbo);const g=this.__gl;g.bindFramebuffer(g.DRAW_FRAMEBUFFER,this.__prevBoundFbo)}bind(A){this.bindForWriting(A)}unbind(A){if(A)this.unbindForWriting(A);else{const A=this.__gl;A.bindFramebuffer(A.FRAMEBUFFER,null)}}bindForReading(A){const g=this.__gl;g.bindFramebuffer(g.READ_FRAMEBUFFER,this.__fbo)}unbindForReading(){const A=this.__gl;A.bindFramebuffer(A.READ_FRAMEBUFFER,null)}clear(){const A=this.__gl;A.colorMask(!0,!0,!0,!0);const g=this.__clearColor.asArray();A.clearColor(g[0],g[1],g[2],g[3]),this.__createDepthTexture?A.clear(A.COLOR_BUFFER_BIT|A.DEPTH_BUFFER_BIT):A.clear(A.COLOR_BUFFER_BIT)}bindAndClear(A){this.bind(A),this.clear()}destroy(){const A=this.__gl;A.bindFramebuffer(A.FRAMEBUFFER,null),A.deleteFramebuffer(this.__fbo),this.__fbo=null,this.__colorTexture.off("resized",this.colorTextureResizeEventId)}}function checkFramebuffer(A,g,I){let C;if(C=A.checkFramebufferStatus(A.DRAW_FRAMEBUFFER),C!==A.FRAMEBUFFER_COMPLETE)switch(A.bindTexture(A.TEXTURE_2D,null),A.bindFramebuffer(A.DRAW_FRAMEBUFFER,null),console.warn("Error creating Fbo width:",g,", height:",I),C){case A.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:throw new Error("The attachment types are mismatched or not all framebuffer attachment points are framebuffer attachment complete.");case A.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:throw new Error("There is no attachment.");case A.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:throw new Error("Height and width of the attachment are not the same.");case A.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:throw new Error("The format of the attachment is not supported or if depth and stencil attachments are not the same renderbuffer.");case 36061:throw new Error("The framebuffer is unsupported");default:throw new Error("Incomplete Frambuffer")}}class GLRenderTarget extends EventEmitter{gl;textureTargets;depthTexture;frameBuffer;textureDesc;type;format;internalFormat;depthFormat;depthInternalFormat;depthType;minFilter;magFilter;wrapS=0;wrapT=0;width=0;height=0;clearColor;colorMask;textureType;prevBoundFbo;constructor(A,g){super(),this.gl=A,this.textureTargets=[],this.depthTexture=null,this.textureDesc=[0,0,0,0],this.clearColor=new Color(0,0,0,0),this.colorMask=[!0,!0,!0,!0],g&&this.configure(g)}configure(A){const g=this.gl;{const I=processTextureParams(g,A);this.type=I.type,this.format=I.format,this.internalFormat=I.internalFormat,this.depthType=I.depthType,this.depthFormat=I.depthFormat,this.depthInternalFormat=I.depthInternalFormat,this.minFilter=I.minFilter?I.minFilter:I.filter,this.magFilter=I.magFilter?I.magFilter:I.filter,this.wrapS=I.wrapS,this.wrapT=I.wrapT,this.width=I.width,this.height=I.height}this.textureType=1,this.textureDesc[0]=this.width,this.textureDesc[1]=this.height,this.textureTargets.forEach((A=>{g.deleteTexture(A)})),this.textureTargets=[],this.depthTexture&&(g.deleteTexture(this.depthTexture),this.depthTexture=null),this.frameBuffer&&g.deleteFramebuffer(this.frameBuffer);const I=null!=A.numColorChannels?A.numColorChannels:null!=this.format?1:0;for(let A=0;A<I;A++){g.activeTexture(g.TEXTURE0+1);const A=g.createTexture();g.bindTexture(g.TEXTURE_2D,A),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,this.wrapS),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,this.wrapT),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,this.minFilter),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,this.magFilter),g.texImage2D(g.TEXTURE_2D,0,this.internalFormat,this.width,this.height,0,this.format,this.type,null),this.textureTargets.push(A)}if(this.depthFormat){if("webgl"==g.name&&!g.__ext_WEBGL_depth_texture)throw new Error("Depth textures not support on this device");g.activeTexture(g.TEXTURE0),this.depthTexture=g.createTexture(),g.bindTexture(g.TEXTURE_2D,this.depthTexture),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,this.wrapS),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,this.wrapT),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,this.minFilter),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,this.magFilter),g.texImage2D(g.TEXTURE_2D,0,this.depthInternalFormat,this.width,this.height,0,this.depthFormat,this.depthType,null)}if(this.frameBuffer=g.createFramebuffer(),this.bindForWriting(),this.textureTargets.length>0){this.textureTargets.length>1&&"webgl"==g.name&&g.drawBuffers;const A=[];for(let I=0;I<this.textureTargets.length;I++)g.framebufferTexture2D(g.DRAW_FRAMEBUFFER,g.COLOR_ATTACHMENT0+I,g.TEXTURE_2D,this.textureTargets[I],0),A.push(g.COLOR_ATTACHMENT0+I);this.textureTargets.length>1&&g.drawBuffers(A)}this.depthTexture&&g.framebufferTexture2D(g.DRAW_FRAMEBUFFER,g.DEPTH_ATTACHMENT,g.TEXTURE_2D,this.depthTexture,0),this.checkFramebuffer()}checkFramebuffer(){this.bindForWriting();const A=this.gl,g=A.checkFramebufferStatus(A.DRAW_FRAMEBUFFER);if(g!=A.FRAMEBUFFER_COMPLETE)switch(g){case A.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:throw new Error("The attachment types are mismatched or not all framebuffer attachment points are framebuffer attachment complete.");case A.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:throw new Error("There is no attachment.");case A.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:throw new Error("Height and width of the attachment are not the same.");case A.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:throw new Error("The format of the attachment is not supported or if depth and stencil attachments are not the same renderbuffer.");case 36061:throw new Error("The framebuffer is unsupported");default:throw new Error("Incomplete Frambuffer")}this.unbindForWriting()}bindForWriting(A,g=!1){A&&(this.prevBoundFbo=A.boundRendertarget,A.boundRendertarget=this.frameBuffer);const I=this.gl;I.bindFramebuffer(I.DRAW_FRAMEBUFFER,this.frameBuffer),I.viewport(0,0,this.width,this.height),g&&this.clear()}unbindForWriting(A){A&&(A.boundRendertarget=this.prevBoundFbo);const g=this.gl;g.bindFramebuffer(g.DRAW_FRAMEBUFFER,this.prevBoundFbo),this.prevBoundFbo=null}clear(A=!0){const g=this.gl,I=this.colorMask;g.colorMask(I[0],I[1],I[2],I[3]);const C=this.clearColor.asArray();g.clearColor(C[0],C[1],C[2],C[3]);let e=0;this.textureTargets.length>0&&(e|=g.COLOR_BUFFER_BIT),this.depthTexture&&(e|=g.DEPTH_BUFFER_BIT),g.clear(e)}bindForReading(){const A=this.gl;A.bindFramebuffer(A.READ_FRAMEBUFFER,this.frameBuffer)}unbindForReading(){const A=this.gl;A.bindFramebuffer(A.READ_FRAMEBUFFER,null)}bindColorTexture(A,g,I=0){const C=this.gl,e=A.boundTextures++;return C.uniform1i(g.location,e),C.activeTexture(C.TEXTURE0+e),C.bindTexture(C.TEXTURE_2D,this.textureTargets[I]),!0}bindDepthTexture(A,g){const I=this.gl,C=A.boundTextures++;return I.uniform1i(g.location,C),I.activeTexture(I.TEXTURE0+C),I.bindTexture(I.TEXTURE_2D,this.depthTexture),!0}unbind(A){this.unbindForWriting(A)}resize(A,g,I=!1){const C=this.gl;if(this.width!=A||this.height!=g){const e=C.getParameter(C.MAX_TEXTURE_SIZE);if(A<0||A>e||g<0||g>e)throw new Error(`GLRenderTarget: Invalid texture size. width: ${A} height: ${g} maxSize: ${e}`);I&&this.bindForReading();for(let e=0;e<this.textureTargets.length;e++){const i=C.createTexture();C.bindTexture(C.TEXTURE_2D,i),C.texParameteri(C.TEXTURE_2D,C.TEXTURE_WRAP_S,this.wrapS),C.texParameteri(C.TEXTURE_2D,C.TEXTURE_WRAP_T,this.wrapT),C.texParameteri(C.TEXTURE_2D,C.TEXTURE_MIN_FILTER,this.minFilter),C.texParameteri(C.TEXTURE_2D,C.TEXTURE_MAG_FILTER,this.magFilter),C.texImage2D(C.TEXTURE_2D,0,this.internalFormat,A,g,0,this.format,this.type,null),I&&C.copyTexImage2D(C.TEXTURE_2D,0,this.internalFormat,0,0,Math.min(A,this.width),Math.min(g,this.height),0),C.deleteTexture(this.textureTargets[e]),this.textureTargets[e]=i}if(this.depthFormat){if("webgl"==C.name&&!C.__ext_WEBGL_depth_texture)throw new Error("Depth textures not support on this device");C.activeTexture(C.TEXTURE0);const e=C.createTexture();C.bindTexture(C.TEXTURE_2D,e),C.texParameteri(C.TEXTURE_2D,C.TEXTURE_WRAP_S,this.wrapS),C.texParameteri(C.TEXTURE_2D,C.TEXTURE_WRAP_T,this.wrapT),C.texParameteri(C.TEXTURE_2D,C.TEXTURE_MIN_FILTER,this.minFilter),C.texParameteri(C.TEXTURE_2D,C.TEXTURE_MAG_FILTER,this.magFilter),C.texImage2D(C.TEXTURE_2D,0,this.depthInternalFormat,A,g,0,this.depthFormat,this.depthType,null),I&&C.copyTexImage2D(C.TEXTURE_2D,0,this.internalFormat,0,0,Math.min(A,this.width),Math.min(g,this.height),0),C.deleteTexture(this.depthTexture),this.depthTexture=e}if(I&&this.unbindForReading(),this.width=A,this.height=g,this.frameBuffer&&C.deleteFramebuffer(this.frameBuffer),this.frameBuffer=C.createFramebuffer(),this.bindForWriting(),this.textureTargets.length>0){this.textureTargets.length>1&&"webgl"==C.name&&C.drawBuffers;const A=[];for(let g=0;g<this.textureTargets.length;g++)C.framebufferTexture2D(C.DRAW_FRAMEBUFFER,C.COLOR_ATTACHMENT0+g,C.TEXTURE_2D,this.textureTargets[g],0),A.push(C.COLOR_ATTACHMENT0+g);this.textureTargets.length>1&&C.drawBuffers(A)}this.depthTexture&&C.framebufferTexture2D(C.DRAW_FRAMEBUFFER,C.DEPTH_ATTACHMENT,C.TEXTURE_2D,this.depthTexture,0),this.checkFramebuffer()}}bindToUniform(A,g,I){const C=A.boundTextures++,e=this.gl.TEXTURE0+C,i=this.gl;return i.activeTexture(e),i.bindTexture(i.TEXTURE_2D,this.textureTargets[0]),i.uniform1i(g.location,C),I&&(I.textureTypeUnif&&i.uniform1i(I.textureTypeUnif.location,this.textureType),I.textureDescUnif&&this.gl.uniform4fv(I.textureDescUnif.location,this.textureDesc)),!0}destroy(){const A=this.gl;this.textureTargets.forEach((g=>{A.deleteTexture(g)})),this.textureTargets=[],this.depthTexture&&(A.deleteTexture(this.depthTexture),this.depthTexture=null),this.frameBuffer&&A.deleteFramebuffer(this.frameBuffer)}}var computeViewNormal="#define GLSLIFY 1\n  \n#ifdef ENABLE_ES3\nvec3 computeViewNormal(vec3 viewPos) {\n  vec3 fdx = dFdx(viewPos);\n  vec3 fdy = dFdy(viewPos);\n  return normalize(cross(fdx, fdy));\n}\n#else \nvec3 computeViewNormal(vec3 viewPos) {\n  return vec3(0.0, 0.0, 0.0);\n}\n#endif\n",calcFatLinesViewPos="#define GLSLIFY 1\nimport 'GLSLUtils.glsl'\nvec3 calcFatLinesViewPos(int vertexID, mat4 modelViewMatrix, inout vec3 viewNormal, inout vec2 texCoord, inout vec3 pos) {\n\n  int seqentialIndex_0 = int(mod(segmentIndices.x, 2.));\n  int seqentialIndex_1 = int(mod(segmentIndices.y, 2.));\n  int index_0 = int(segmentIndices.x) / 2;\n  int index_1 = int(segmentIndices.y) / 2;\n\n  vec3 viewPos;\n  vec4 data_0 = fetchTexel(positionsTexture, positionsTextureSize, index_0);\n  vec4 data_1 = fetchTexel(positionsTexture, positionsTextureSize, index_1);\n\n  // During XR sessions, there is a scaling applied to the view matrix\n  // which causes a distortion to the line width. We extract that scale here\n  // and use to correct the distortion.\n  // See also: FatPointsShader\n  vec3 viewZ = modelViewMatrix[2].xyz;\n  float viewScale = length(viewZ);\n\n  vec4 pos_0 = modelViewMatrix * vec4(data_0.xyz, 1.0);\n  vec4 pos_1 = modelViewMatrix * vec4(data_1.xyz, 1.0);\n  // Note: multiply the per-vertex line thickness with the line thickness uniform value;\n  float lineThickness_0 = LineThickness * data_0.w * viewScale;\n  float lineThickness_1 = LineThickness * data_1.w * viewScale;\n\n  if (vertexID < 2) {\n    pos = data_0.xyz;\n    viewPos = pos_0.xyz;\n  }\n  else {\n    pos = data_1.xyz;\n    viewPos = pos_1.xyz;\n  }\n  if (pos_1 != pos_0) {\n    vec3 segmentDir = normalize(pos_1.xyz - pos_0.xyz);\n    vec3 viewVector = normalize(viewPos);\n\n    if (vertexID < 2) {\n      vec3 segmentStartDir = segmentDir;\n      if (seqentialIndex_0 != 0) {\n        //if index_0 == 0, get the last index in the line as previous\n        int index_prev = (index_0 > 0) ? (index_0-1) : (positionsTextureSize-1);\n        vec4 data_prev = fetchTexel(positionsTexture, positionsTextureSize, index_prev);\n        vec4 pos_prev = modelViewMatrix * vec4(data_prev.xyz, 1.0);\n        segmentStartDir = normalize(segmentDir + normalize(pos_0.xyz - pos_prev.xyz));\n        // segmentStartDir = segmentDir;\n      }\n      // vec3 startBiTangent = normalize(cross(segmentStartDir, viewVector));\n      // viewNormal = normalize(cross(segmentStartDir, startBiTangent));\n      vec3 startBiTangent = normalize(vec3(-segmentStartDir.y, segmentStartDir.x, 0.0));\n      viewNormal = normalize(-viewVector);\n      // Move the endpoints to overlap a bit more.\n      //viewPos -= vec3(segmentStartDir * lineThickness_0 * 0.25);\n      if (mod(vertexIDs, 2.0) == 0.0) {\n        viewPos += vec3(startBiTangent * lineThickness_0);\n        texCoord.x = 1.0;\n      }\n      else {\n        viewPos -= vec3(startBiTangent * lineThickness_0);\n        texCoord.x = 0.0;\n      }\n      texCoord.y = 0.0;\n    }\n    else {\n      vec3 segmentEndDir = segmentDir;\n      if (seqentialIndex_1 != 0) {\n        //if index_1 == numPoints-1, get the first index in the line as next\n        int index_next = (index_1 < (positionsTextureSize-1)) ? (index_1+1) : 0;\n        vec4 data_next = fetchTexel(positionsTexture, positionsTextureSize, index_next);\n        vec4 pos_next = modelViewMatrix * vec4(data_next.xyz, 1.0);\n        segmentEndDir = normalize(segmentDir + normalize(pos_next.xyz - pos_1.xyz));\n        // segmentEndDir = segmentDir;\n      }\n      // vec3 endBiTangent = normalize(cross(segmentEndDir, viewVector));\n      // viewNormal = normalize(cross(segmentEndDir, endBiTangent));\n      vec3 endBiTangent = normalize(vec3(-segmentEndDir.y, segmentEndDir.x, 0.0));\n      viewNormal = normalize(-viewVector);\n      // Move the endpoints to overlap a bit more.\n      //viewPos += vec3(segmentEndDir * lineThickness_1 * 0.25);\n      if (mod(vertexIDs, 2.0) == 0.0) {\n        viewPos += vec3(endBiTangent * lineThickness_1);\n        texCoord.x = 1.0;\n      }\n      else {\n        viewPos -= vec3(endBiTangent * lineThickness_1);\n        texCoord.x = 0.0;\n      }\n      texCoord.y = 1.0;\n    }\n\n    // Move the line towards the viewer by the line thickness.\n    // this is to avoid depth issues when lines are rendered over meshes. \n    viewPos.z += (lineThickness_0 + lineThickness_1) * 0.5;\n  }\n\n  return viewPos;\n}\n\n",constants="#define GLSLIFY 1\n#define PI 3.141592653589793\n#define TwoPI (2.0 * PI)\n#define HalfPI (0.5 * PI)\n\n",convolveHelpers="#define GLSLIFY 1\n\n#ifdef ENVMAP_CUBE\n\nuniform samplerCube envMap;\n\nvec4 sampleEnvMap(vec3 dir) {\n  return texture(envMap, dir);\n}\n\n#else \n\nuniform sampler2D   envMap;\n\nimport 'envmap-octahedral.glsl'\n\nvec4 sampleEnvMap(vec3 dir) {\n  vec2 uv = dirToSphOctUv(dir);\n  vec4 texel = texture2D(envMap, vec2(uv.x, 1.0 - uv.y));\n  return vec4(texel.rgb/texel.a, 1.0); // TODO: Check this line. Do we need it?\n}\n\n#endif \n\nvec3 cubeFaceUvToDir(float u, float v, int faceId) {\n\n  // normalize into [-1, 1] range\n  float n_u = 2.0 * u - 1.0;\n  float n_v = 2.0 * v - 1.0;\n\n  vec3 dir;\n  switch (faceId)\n  {\n  case 0: //TEXTURE_CUBE_MAP_POSITIVE_X:\n    dir.x = 1.0f;\n    dir.y = n_v;\n    dir.z = -n_u;\n    break;\n  case 1: //TEXTURE_CUBE_MAP_NEGATIVE_X:\n    dir.x = -1.0f;\n    dir.y = n_v;\n    dir.z = n_u;\n    break;\n  case 3: //TEXTURE_CUBE_MAP_POSITIVE_Y:\n    dir.x = n_u;\n    dir.y = 1.0f;\n    dir.z = -n_v;\n    break;\n  case 2: //TEXTURE_CUBE_MAP_NEGATIVE_Y:\n    dir.x = n_u;\n    dir.y = -1.0f;\n    dir.z = n_v;\n    break;\n  case 4: //TEXTURE_CUBE_MAP_POSITIVE_Z:\n    dir.x = n_u;\n    dir.y = n_v;\n    dir.z = 1.0f;\n    break;\n  case 5: //TEXTURE_CUBE_MAP_NEGATIVE_Z:\n    dir.x = -n_u;\n    dir.y = n_v;\n    dir.z = -1.0f;\n    break;\n  }\n  return normalize(dir);\n}\n\n",cutaways="#define GLSLIFY 1\nuniform color cutColor;\n\n#ifdef ENABLE_FLOAT_TEXTURES\n  vec4 getCutaway(int id) {\n    return fetchTexel(instancesTexture, instancesTextureSize, (id * pixelsPerItem) + 5);\n  }\n\n#else\n\n  uniform vec4 cutawayData;\n\n  vec4 getCutaway(int id) {\n    return cutawayData;\n  }\n\n#endif\n\n#define RAY_EPS 0.0000001\nstruct Ray {\n  vec3 start;\n  vec3 dir;\n};\n\nfloat intersectRayPlane(Ray ray, Ray plane) {\n  vec3 w = ray.start - plane.start;\n  float D = dot(plane.dir, ray.dir);\n  float N = dot(-plane.dir, w);\n\n  if (abs(D) < RAY_EPS) {\n    // segment is parallel to plane\n    if (N == 0.0)\n      return -1.0; // segment lies in plane\n    else\n      return -1.0; // no intersection\n  }\n  // they are not parallel\n  // compute intersect param\n  float sI = N / D;\n  if (sI < -RAY_EPS) {\n    return -1.0; // no intersection\n  }\n  return sI;\n}\n\nbool cutaway(vec3 worldPos, vec3 planeNormal, float planeDist) {\n\n  vec3 planePos = planeNormal * planeDist;\n  vec3 planeDir = worldPos + planePos;\n  float planeOffset = dot(planeDir, planeNormal);\n  if (planeOffset > 0.0) {\n    return true;\n  }\n  return false;\n}\n",debugColors="#define GLSLIFY 1\nimport 'GLSLUtils.glsl'\n\nvec3 getDebugColor(float id) {\n  int sel = int(round(mod(round(id), 16.0)));\n  \n  if (sel==0)\n    return vec3(0.0, 1.0, 1.0);\n  else if (sel==1)\n    return vec3(0.0, 1.0, 0.0);\n  else if (sel==2)\n    return vec3(1.0, 0.0, 1.0);\n  else if (sel==3)\n    return vec3(0.75, 0.75, 0.0);\n  else if (sel==4)\n    return vec3(0.0, 0.75, 0.75);\n  else if (sel==5)\n    return vec3(0.75, 0.0, 0.75);\n  else if (sel==6)\n    return vec3(0.45, 0.95, 0.0);\n  else if (sel==7)\n    return vec3(0.0, 0.45, 0.95);\n  else if (sel==8)\n    return vec3(0.95, 0.0, 0.45);\n  else if (sel==9)\n    return vec3(0.95, 0.45, 0.0);\n  else if (sel==10)\n    return vec3(0.0, 0.95, 0.45);\n  else if (sel==11)\n    return vec3(0.45, 0.0, 0.95);\n  else if (sel==12)\n    return vec3(0.45, 0.45, 0.95);\n  else if (sel==13)\n    return vec3(0.0, 0.0, 0.45);\n  else if (sel==14)\n    return vec3(0.0, 0.45, 0.45);\n  else if (sel==15)\n    return vec3(0.45, 0.0, 0.45);\n  else return vec3(0.2, 0.2, 0.2);\n}\n\n",geomItemId="#define GLSLIFY 1\n\n#ifdef ENABLE_MULTI_DRAW\n\n// On some mobile GPUs the sampler2D defaults to lowp, which implies a maximum\n// resolution of 255. This caused rendering artifacts on larger scenes on mobile\n// devices.\nuniform highp sampler2D drawIdsTexture;\n\n#ifdef EMULATE_MULTI_DRAW\nuniform int drawId;\n#endif // EMULATE_MULTI_DRAW\n\nint getGeomItemId() {\n#ifndef EMULATE_MULTI_DRAW\n  int drawId = gl_DrawID;\n#endif // EMULATE_MULTI_DRAW\n\n  ivec2 texSize = textureSize(drawIdsTexture, 0);\n  ivec2 texelCoords = ivec2(drawId % texSize.x, drawId / texSize.x);\n  return int(texelFetch(drawIdsTexture, texelCoords, 0).r + 0.5);\n}\n\nvec4 getDrawItemIds() {\n#ifndef EMULATE_MULTI_DRAW\n  int drawId = gl_DrawID;\n#endif // EMULATE_MULTI_DRAW\n\n  ivec2 texSize = textureSize(drawIdsTexture, 0);\n  ivec2 texelCoords = ivec2(drawId % texSize.x, drawId / texSize.x);\n  vec4 color = texelFetch(drawIdsTexture, texelCoords, 0);\n  // Note: A 0 value in the texture means no sub-geom index is being rendered.\n  // subtract off 1 to get the true sub-geom index.\n  return vec4(color.r, color.g - 1.0, color.b, color.a);\n}\n\n#else // ENABLE_MULTI_DRAW\n\nuniform int geomItemId;\n\nattribute float instancedIds;    // instanced attribute..\nuniform int instancedDraw;\n\nint getGeomItemId() {\n  if (instancedDraw == 0) {\n    return geomItemId;\n  }\n  else {\n    return int(instancedIds);\n  }\n}\n\nvec4 getDrawItemIds() {\n  if (instancedDraw == 0) {\n    return vec4(float(geomItemId), 0.0, -1.0, -1.0);\n  }\n  else {\n    return vec4(float(instancedIds), 0.0, -1.0, -1.0);\n  }\n}\n\n#endif // ENABLE_MULTI_DRAW\n\n// For backwards compatibility with older plugins (UX.HandleShader)\nint getDrawItemId() {\n  return getGeomItemId();\n}\n",geomItemFlags="#define GLSLIFY 1\nconst int GEOMITEM_FLAG_CUTAWAY = 2; // 1<<1;\nconst int GEOMITEM_INVISIBLE_IN_GEOMDATA = 4; // 1<<2;\nconst int GEOMITEM_TRANSPARENT = 8; // 1<<3;\nconst int GEOMITEM_PLACEHOLDER = 16; // 1<<4;\nconst int GEOMITEM_MASK = 32; // 1<<5;\n",geomType="#define GLSLIFY 1\n\nconst int TRIANGLES = 0;\nconst int LINES = 1;\nconst int POINTS = 2;",geometryMask="#define GLSLIFY 1\nuniform sampler2D frontDepthTexture;\nuniform sampler2D backDepthTexture;\n\nuniform vec2 depthRange;\nuniform vec2 viewportSize;\n\nbool testGeometryMask(vec3 viewPos) {\n  float depth = gl_FragCoord.z;\n  vec2 texCoord = gl_FragCoord.xy / viewportSize;\n  float front = texture2D(frontDepthTexture, texCoord).r;\n  float back = texture2D(backDepthTexture, texCoord).r;\n\n  return depth < front || depth > back;\n}\n",drawItemTexture="#define GLSLIFY 1\nimport 'GLSLUtils.glsl'\n\n// The texture populated by the GLGeomItemLibrary\nuniform sampler2D instancesTexture;\nuniform highp int instancesTextureSize;\n\n// See also: src\\Renderer\\GLSLConstants.js\nconst int pixelsPerItem = 8;\n\nvec4 getInstanceData(int id) {\n  return fetchTexel(instancesTexture, instancesTextureSize, (id * pixelsPerItem) + 0);\n}\n\n",envmapDualfisheye="#define GLSLIFY 1\n\nvec2 dualfisheyeUVsFromDir(vec3 dir) {\n  vec2 result;\n  float angle = 0.465;\n  if (dir.x < 0.0) {\n    result = vec2(((dir.z * -angle) + 0.5) * 0.5, (dir.y * angle) + 0.5);\n  }\n  else {\n    result = vec2( 0.5 + ((dir.z * angle) + 0.5) * 0.5, (dir.y * angle) + 0.5);\n  }\n  return result;\n}\n\n",envmapEquirect="#define GLSLIFY 1 \nimport 'constants.glsl'\n\nvec2 latLongUVsFromDir(vec3 dir) {\n  // Math function taken from...\n  // http://gl.ict.usc.edu/Data/HighResProbes/\n  // Note: Scaling from u=[0,2], v=[0,1] to u=[0,1], v=[0,1]\n  float phi = acos(dir.z);\n  float theta = atan(dir.x, dir.y);\n  return vec2((1.0 + theta / PI) / 2.0, phi / PI);\n}\n\n// Note: when u == 0.5 z = 1.0\nvec3 dirFromLatLongUVs(float u, float v) {\n  // http://gl.ict.usc.edu/Data/HighResProbes/\n  float theta = PI*((u * 2.0) - 1.0);\n  float phi = PI*v;\n  return vec3(sin(phi)*sin(theta), sin(phi)*cos(theta), cos(phi));\n}\n\nvec3 dirFromPolar(vec2 polar) {\n  float u = polar.x / (PI * 2.0);\n  float v = polar.y / PI;\n  return dirFromLatLongUVs(u, v);\n}\n\n",envmapOctahedral="#define GLSLIFY 1\nimport 'constants.glsl'\nimport 'GLSLUtils.glsl'\n#define sectorize(value) step(0.0, (value))*2.0-1.0\n#define sum(value) dot(clamp((value), 1.0, 1.0), (value))\n\nvec2 dirToSphOctUv(vec3 normal) {\n  normal = normalize(normal);\n  vec3 aNorm = abs(normal);\n  vec3 sNorm = sectorize(normal);\n  \n  vec2 dir = aNorm.xy;\n  float orient = atan(dir.x, max(dir.y,0.0000000000000001))/HalfPI;\n\n  dir = vec2(aNorm.z, length(aNorm.xy));\n  float pitch = atan(dir.y, dir.x)/HalfPI;\n\n  vec2 uv = vec2(sNorm.x*orient, sNorm.y*(1.0-orient))*pitch;\n\n  if (normal.z < 0.0) {\n    uv = sNorm.xy - abs(uv.ts)*sNorm.xy;\n  }\n  vec2 res = uv*0.5+0.5;\n  // Flip-v\n  // return res;\n  return vec2(res.x, 1.0 - res.y);\n}\n\nvec3 sphOctUvToDir(vec2 uv) {\n  uv = uv*2.0-1.0;\n  // Flip-v\n  uv.y = -uv.y;\n  vec2 suv = sectorize(uv);\n  float sabsuv = sum(abs(uv));\n  float pitch = sabsuv*HalfPI;\n\n  if (pitch <= 0.0) {\n    return vec3(0.0, 0.0, 1.0);\n  }\n  if (abs(pitch - PI) < 0.000001) {\n    return vec3(0.0, 0.0, -1.0);\n  }\n  if (sabsuv > 1.0) {\n    uv = (1.0-abs(uv.ts))*suv;\n  }\n\n  float orient = (abs(uv.s)/sabsuv)*HalfPI;\n  float sOrient = sin(orient);\n  float cOrient = cos(orient);\n  float sPitch = sin(pitch);\n  float cPitch = cos(pitch);\n\n  return vec3(\n    sOrient*suv.s*sPitch,\n    cOrient*suv.t*sPitch,\n    cPitch\n  );\n}\n\n",GLSLBits='#define GLSLIFY 1\n    \n/////////////////////////////////////////////////////////////////\n// http://concord-consortium.github.io/lab/experiments/webgl-gpgpu/script.js\nfloat shift_right(float v, float amt) {\n  v = floor(v) + 0.5;\n  return floor(v / exp2(amt));\n}\nfloat shift_left(float v, float amt) {\n  return floor(v * exp2(amt) + 0.5);\n}\n\nfloat mask_last(float v, float bits) {\n  return mod(v, shift_left(1.0, bits));\n}\nfloat extract_bits(float num, float from, float to) {\n  from = floor(from + 0.5);\n  to = floor(to + 0.5);\n  return mask_last(shift_right(num, from), to - from);\n}\n\n/////////////////////////////////////////////////////////////////\n// https://stackoverflow.com/questions/18453302/how-do-you-pack-one-32bit-int-into-4-8bit-ints-in-glsl-webgl\n\nconst vec4 bitEnc = vec4(1.,255.,65025.,16581375.);\nconst vec4 bitDec = 1./bitEnc;\nvec4 EncodeFloatRGBA (float v) {\n  vec4 enc = bitEnc * v;\n  enc = fract(enc);\n  enc -= enc.yzww * vec2(1./255., 0.).xxxy;\n  return enc;\n}\nfloat DecodeFloatRGBA (vec4 v) {\n  return dot(v, bitDec);\n}\n\n/////////////////////////////////////////////////////////////////\n// https://gist.github.com/Flexi23/1713774\n// \nvec2 encode16BitFloatInto2xUInt8(float v) {\n  vec2 c = vec2(0.);\n\n  int signum = (v >= 0.) ? 128 : 0;\n  v = abs(v);\n  int exponent = 15;\n  float limit = 1024.; // considering the bias from 2^-5 to 2^10 (==1024)\n  for(int exp = 15; exp > 0; exp--) {\n    if ( v < limit) {\n      limit /= 2.;\n      exponent--;\n    }\n  }\n\n  float rest;\n  if (exponent == 0) {\n    rest = v / limit / 2.;      // "subnormalize" implicite preceding 0. \n  } \n  else {\n    rest = (v - limit)/limit;   // normalize accordingly to implicite preceding 1.\n  }\n\n  int mantissa = int(rest * 2048.);   // 2048 = 2^11 for the (split) 11 bit mantissa\n  int msb = mantissa / 256;           // the most significant 3 bits go into the lower part of the first byte\n  int lsb = mantissa - msb * 256;     // there go the other 8 bit of the lower significance\n\n  c.x = float(signum + exponent * 8 + msb) / 255.;    // color normalization for texture2D\n  c.y = float(lsb) / 255.;\n\n  if (v >= 2048.) {\n    c.y = 1.;\n  }\n\n  return c;\n}\n\nfloat decode16BitFloatFrom2xUInt8(vec2 c) {\n  float v = 0.;\n\n  int ix = int(c.x*255.); // 1st byte: 1 bit signum, 4 bits exponent, 3 bits mantissa (MSB)\n  int iy = int(c.y*255.); // 2nd byte: 8 bit mantissa (LSB)\n\n  int s = (c.x >= 0.5) ? 1 : -1;\n  ix = (s > 0) ? ix - 128 : ix;   // remove the signum bit from exponent\n  int iexp = ix / 8;              // cut off the last 3 bits of the mantissa to select the 4 exponent bits\n  int msb = ix - iexp * 8;        // subtract the exponent bits to select the 3 most significant bits of the mantissa\n\n  int norm = (iexp == 0) ? 0 : 2048;          // distinguish between normalized and subnormalized numbers\n  int mantissa = norm + msb * 256 + iy;       // implicite preceding 1 or 0 added here\n  norm = (iexp == 0) ? 1 : 0;                 // normalization toggle\n  float exponent = pow( 2., float(iexp + norm) - 16.); // -5 for the the exponent bias from 2^-5 to 2^10 plus another -11 for the normalized 12 bit mantissa \n  v = float( s * mantissa ) * exponent;\n\n  return v;\n}\n\n// TODO : Encoding Float32 to 4x UInt8\n// http://concord-consortium.github.io/lab/experiments/webgl-gpgpu/script.js\n// http://ultraist.hatenablog.com/entry/20110608/1307539319\n\n',GLSLUtils="#define GLSLIFY 1\n\nint ftoi(float val) {\n  return int(floor(val + 0.5));\n}\nivec2 ftoi(vec2 v2) {\n  return ivec2(ftoi(v2.x), ftoi(v2.y));\n}\nivec3 ftoi(vec3 v4) {\n  return ivec3(ftoi(v4.x), ftoi(v4.y), ftoi(v4.z));\n}\nivec4 ftoi(vec4 v4) {\n  return ivec4(ftoi(v4.x), ftoi(v4.y), ftoi(v4.z), ftoi(v4.w));\n}\n\n#ifdef ENABLE_ES3\n\nint imod(int x, int y) {\n  return x % y;\n}\n\nvoid setFlag(inout int flags, int flag) {\n  flags |= flag;\n}\n\nvoid clearFlag(inout int flags, int flag) {\n  flags &= ~flag;\n}\n\nbool testFlag(int flags, int flag) {\n  return (flags & flag) != 0;\n}\n\n// private function: Mangle me...\nivec2 _pixelIndexToUV(int index, int textureWidth) {\n  return ivec2(index % textureWidth, index / textureWidth);\n}\n\nvec4 fetchTexel(sampler2D texture, int textureWidth, int index) {\n  return texelFetch(texture, _pixelIndexToUV(index, textureWidth), 0);\n}\n\nvec4 fetchTexel(sampler2D texture, ivec2 textureSize, ivec2 texCoord) {\n  return texelFetch(texture, texCoord, 0);\n}\n\nvec4 fetchTexel(sampler2D texture, ivec2 textureSize, int index) {\n    return texelFetch(texture, _pixelIndexToUV(index, textureSize.x), 0);\n}\n\n#else\n\n// TODO: integrate: https://gist.github.com/mattatz/70b96f8c57d4ba1ad2cd\n\nint max(int a, int b) {\n  return a > b ? a : b;\n}\nint min(int a, int b) {\n  return a < b ? a : b;\n}\n\nfloat round(float val) {\n  return floor(val + 0.4);\n}\n\nint imod(int x, int y) {\n  return x-y*(x/y);\n}\n\nvoid setFlag(inout int flags, int flag) {\n  flags += flag;\n}\nvoid clearFlag(inout int flags, int flag) {\n  flags -= flag;\n}\n\nbool testFlag(int flags, int flag) {\n  return imod(flags / flag, 2) != 0;\n}\n\n// private function: Mangle me...\nvec2 _pixelIndexToUV(int index, int textureSize) {\n  float flTexSize = float(textureSize);\n  float x = (float(imod(index, textureSize))+0.5)/flTexSize;\n  float y = (floor(float(index / textureSize))+0.5)/flTexSize;\n  return vec2(x, y);\n}\n\nvec4 fetchTexel(sampler2D texture, int textureSize, int index) {\n  vec2 texCoord = _pixelIndexToUV(index, textureSize);\n  return texture2D(texture, texCoord);\n}\n\nvec4 fetchTexel(sampler2D texture, ivec2 textureSize, ivec2 texCoord) {\n  vec2 ftextureSize = vec2(textureSize);\n  return texture2D(texture, (vec2(texCoord) + 0.5) / ftextureSize);\n}\n\n#endif // ENABLE_ES3\n\nint uvToPixelIndex(vec2 uv, int textureSize) {\n  return int(uv.x * float(textureSize)) + (int(floor(uv.y * float(textureSize))) * textureSize);\n}\n\n",Hammersley="#define GLSLIFY 1\nfloat RadicalInverse_VdC(uint bits) \n{\n  bits = (bits << 16u) | (bits >> 16u);\n  bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\n  bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\n  bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\n  bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\n  return float(bits) * 2.3283064365386963e-10; // / 0x100000000\n}\n// ----------------------------------------------------------------------------\nvec2 Hammersley(uint i, uint N)\n{\n  return vec2(float(i)/float(N), RadicalInverse_VdC(i));\n} \n",ImportanceSampleGGX="#define GLSLIFY 1\nimport 'constants.glsl'\n\nvec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)\n{\n  float a = roughness*roughness;\n\n  float phi = 2.0 * PI * Xi.x;\n  float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));\n  float sinTheta = sqrt(1.0 - cosTheta*cosTheta);\n\n  // from spherical coordinates to cartesian coordinates\n  vec3 H = vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);\n\n  // from tangent-space vector to world-space sample vector\n  vec3 up        = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\n  vec3 tangent   = normalize(cross(up, N));\n  vec3 bitangent = cross(N, tangent);\n\n  vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;\n  return normalize(sampleVec);\n} \n",materialparams="#define GLSLIFY 1\nimport 'GLSLUtils.glsl'\nimport 'gamma.glsl'\n\nconst int FatPointsShaderId = 1;\nconst int FlatSurfaceShaderId = 2;\nconst int LinesShaderId = 3;\nconst int PointsShaderId = 4;\nconst int ScreenSpaceShaderId = 5;\nconst int SimpleSurfaceShaderId = 6;\nconst int StandardSurfaceShaderId = 7;\n\nconst int HeaderId = 0;\nconst int BaseColorId = 1;\n \nuniform sampler2D materialsTexture;\nuniform highp ivec2 materialsTextureSize;\n\nvec4 getMaterialValue(vec2 materialCoords, int valueIndex) {\n  int index = ftoi(materialCoords.x) + valueIndex;\n  ivec2 texelCoords = ivec2(imod(index, materialsTextureSize.x), index / materialsTextureSize.x);\n  \n  return fetchTexel(materialsTexture, materialsTextureSize, texelCoords);\n}\n\n////////////////////////\n// Material Param Helpers.\n\nvoid getTextureColorValue(inout vec4 value, sampler2D tex, int texType, vec2 texCoord) {\n  if (texType == 1 || texType == 2) {\n    // Note: we assume textures are always in gamma space, and must be converted\n    // to linear. I cann't find evidence that 8-bit textures can be in linear space.\n    // TODO: Use SRGB textures.\n    value = toLinear(texture2D(tex, texCoord));\n  }\n  else if (texType == 3) {\n    // Float HDR Texture. We assume these textures are in linear space.\n    value = texture2D(tex, texCoord);\n  }\n}\n\nvec4 getColorParamValue(in vec4 value, sampler2D tex, int texType, vec2 texCoord) {\n  // for backwards compatiblity with zea-ux shader\n  vec4 tmp = value;\n  getTextureColorValue(tmp, tex, texType, texCoord);\n  return tmp;\n}\n\nfloat luminanceFromRGB(vec3 rgb) {\n  return 0.2126*rgb.r + 0.7152*rgb.g + 0.0722*rgb.b;\n}\n\nvoid getTextureLuminanceValue(inout float value, sampler2D tex, int texType, vec2 texCoord) {\n  if (texType != 0)\n    value = luminanceFromRGB(texture2D(tex, texCoord).rgb);\n}\n\nfloat getLuminanceParamValue(in float value, sampler2D tex, int texType, vec2 texCoord) {\n  // for backwards compatiblity with zea-ux shader\n  float tmp = value;\n  getTextureLuminanceValue(tmp, tex, texType, texCoord);\n  // for backwards compatiblity with zea-ux shader\n  return tmp;\n}\n\n",modelMatrix="#define GLSLIFY 1\n#ifdef ENABLE_FLOAT_TEXTURES\nimport 'GLSLUtils.glsl'\nimport 'transpose.glsl'\nmat4 getMatrix(sampler2D texture, int textureSize, int index) {\n  // Unpack 3 x 4 matrix columns into a 4 x 4 matrix.\n  vec4 col0 = fetchTexel(texture, textureSize, (index * pixelsPerItem) + 1);\n  vec4 col1 = fetchTexel(texture, textureSize, (index * pixelsPerItem) + 2);\n  vec4 col2 = fetchTexel(texture, textureSize, (index * pixelsPerItem) + 3);\n  mat4 result = transpose(mat4(col0, col1, col2, vec4(0.0, 0.0, 0.0, 1.0)));\n  return result;\n}\n\nmat4 getModelMatrix(int id) {\n  return getMatrix(instancesTexture, instancesTextureSize, id);\n}\n\n#else\n\nuniform mat4 modelMatrix;\n\nmat4 getModelMatrix(int id) {\n  return modelMatrix;\n}\n\n#endif\n\n",PBRSurfaceRadiance="#define GLSLIFY 1\nimport 'GLSLUtils.glsl'\nconst int ENVMAP_FLAG_HEADLIGHT =  1; // 1<<0;\n\nstruct MaterialParams {\n  vec3 baseColor;\n  float ambientOcclusion;\n  float metallic;\n  float roughness;\n  float reflectance;\n  float opacity;\n  float emission;\n};\n\n#ifndef ENABLE_PBR\n\nvec4 pbrSurfaceRadiance(in MaterialParams material, vec3 normal, in vec3 viewVector) {\n  vec3 irradiance = vec3(dot(normal, viewVector));\n  float ao = material.ambientOcclusion; \n  return vec4(material.baseColor * ao * irradiance + (material.emission * material.baseColor), material.opacity);\n\n  // return vec4(material.baseColor * ao * irradiance , material.opacity);\n}\n\n#else\n\nuniform int envMapFlags;\nuniform samplerCube irradianceMap;\nuniform samplerCube prefilterMap;\nuniform sampler2D brdfLUT;\n\nvec3 sampleIrradiance(vec3 dir) {\n  return texture(irradianceMap, dir).rgb;\n}\n\nvec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) {\n  return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0);\n}\n\nfloat luminance(vec3 color) {\n  return 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;\n}\n\nvec4 pbrSurfaceRadiance(in MaterialParams material, vec3 normal, in vec3 viewVector) {\n  if (envMapFlags == -1) {\n    vec3 irradiance = vec3(dot(normal, viewVector));\n    float ao = material.ambientOcclusion; \n    return vec4(material.baseColor * ao * irradiance + (material.emission * material.baseColor), material.opacity);\n  }\n\n  vec3 N = normal;\n  vec3 V = viewVector;\n  vec3 R = reflect(-V, N);\n  float roughness = material.roughness * material.roughness;\n  vec3 diffuseColor = (1.0 - material.metallic) * material.baseColor;\n\n  // Note: The specular reflectance of metallic surfaces is chromatic\n  // https://google.github.io/filament/Filament.html#listing_fnormal\n  vec3 F0 = 0.16 * material.reflectance * material.reflectance * (1.0 - material.metallic) + material.baseColor * material.metallic;\n\n  float NdotV = dot(N, V);\n\n  vec3 F = fresnelSchlickRoughness(max(NdotV, 0.0), F0, roughness);\n\n  vec3 kS = F;\n  vec3 kD = 1.0 - kS;\n  kD *= 1.0 - material.metallic;\n  float ao = material.ambientOcclusion; \n  \n  vec3 irradiance;\n  vec3 irradianceSampleDir = normal;\n  \n  bool headLightMode = testFlag(envMapFlags, ENVMAP_FLAG_HEADLIGHT);\n  if (headLightMode) {\n    irradianceSampleDir = viewVector;\n  }\n  irradiance = sampleIrradiance(irradianceSampleDir);\n  // vec3 irradiance = shGetIrradianceAt(shCoefficients, N);\n  vec3 diffuse    = irradiance * diffuseColor;\n  \n  const float MAX_REFLECTION_LOD = 4.0;\n  vec3 prefilteredColor = textureLod(prefilterMap, R,  roughness * MAX_REFLECTION_LOD).rgb;   \n  vec2 envBRDF  = texture(brdfLUT, vec2(max(NdotV, 0.0), roughness)).rg;\n  vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y);\n  \n  vec3 radiance = (kD * diffuse + specular) * ao;\n  \n  // Now handle semi-transparent objects. We need to be able to linearly interpolate\n  // opacity to make objects disappear, so we need a continuous change.\n  float opacity = material.opacity;\n  vec4 transparent = vec4((radiance * opacity) + specular, opacity + luminance(specular) + luminance(F));\n  vec4 result = mix(transparent, vec4(radiance, 1.0), opacity);\n\n  // Add emission on as the final component.\n  // Note: emission allows a material to blend off its specular component, \n  // which can also be used to make an object completely disappear if also transparent.\n  return mix(result, vec4(material.baseColor, opacity), material.emission);\n}\n\n#endif // ENABLE_PBR\n",SHCoeffs="#define GLSLIFY 1\nuniform vec3 shCoeffs[9];\n\nvec3 sampleSHCoeffs(vec3 dir) {\n  // dir is assumed to have unit length\n  float x = dir.x, y = dir.y, z = dir.z;\n  // band 0\n  vec3 result = shCoeffs[ 0 ] * 0.886227;\n  // band 1\n  result += shCoeffs[ 1 ] * 2.0 * 0.511664 * y;\n  result += shCoeffs[ 2 ] * 2.0 * 0.511664 * z;\n  result += shCoeffs[ 3 ] * 2.0 * 0.511664 * x;\n  // band 2\n  result += shCoeffs[ 4 ] * 2.0 * 0.429043 * x * y;\n  result += shCoeffs[ 5 ] * 2.0 * 0.429043 * y * z;\n  result += shCoeffs[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n  result += shCoeffs[ 7 ] * 2.0 * 0.429043 * x * z;\n  result += shCoeffs[ 8 ] * 0.429043 * ( x * x - y * y );\n  return result;\n}\n",gamma="#define GLSLIFY 1\nconst float gamma_const = 2.2;\n\nfloat toLinear(float v) {\n  return pow(v, gamma_const);\n}\n\nvec2 toLinear(vec2 v) {\n  return pow(v, vec2(gamma_const));\n}\n\nvec3 toLinear(vec3 v) {\n  return pow(v, vec3(gamma_const));\n}\n\nvec4 toLinear(vec4 v) {\n  return vec4(toLinear(v.rgb), v.a);\n}\n\nfloat toGamma(float v) {\n  return pow(v, 1.0 / gamma_const);\n}\n\nvec2 toGamma(vec2 v) {\n  return pow(v, vec2(1.0 / gamma_const));\n}\n\nvec3 toGamma(vec3 v) {\n  return pow(v, vec3(1.0 / gamma_const));\n}\n\nvec4 toGamma(vec4 v) {\n  return vec4(toGamma(v.rgb), v.a);\n}\n\nfloat toGamma(float v, float gamma) {\n  return pow(v, 1.0 / gamma);\n}\n\nvec2 toGamma(vec2 v, float gamma) {\n  return pow(v, vec2(1.0 / gamma));\n}\n\nvec3 toGamma(vec3 v, float gamma) {\n  return pow(v, vec3(1.0 / gamma));\n}\n\nvec4 toGamma(vec4 v, float gamma) {\n  return vec4(toGamma(v.rgb, gamma), v.a);\n}\n\n",inverse="#define GLSLIFY 1\n\n#ifndef ENABLE_ES3\n\nfloat inverse(float m) {\n  return 1.0 / m;\n}\n\nmat2 inverse(mat2 m) {\n  return mat2(m[1][1],-m[0][1],\n             -m[1][0], m[0][0]) / (m[0][0]*m[1][1] - m[0][1]*m[1][0]);\n}\n\nmat3 inverse(mat3 m) {\n  float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\n  float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\n  float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\n\n  float b01 = a22 * a11 - a12 * a21;\n  float b11 = -a22 * a10 + a12 * a20;\n  float b21 = a21 * a10 - a11 * a20;\n\n  float det = a00 * b01 + a01 * b11 + a02 * b21;\n\n  return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\n              b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\n              b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\n}\n\nmat4 inverse(mat4 m) {\n  float\n      a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3],\n      a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3],\n      a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3],\n      a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3],\n\n      b00 = a00 * a11 - a01 * a10,\n      b01 = a00 * a12 - a02 * a10,\n      b02 = a00 * a13 - a03 * a10,\n      b03 = a01 * a12 - a02 * a11,\n      b04 = a01 * a13 - a03 * a11,\n      b05 = a02 * a13 - a03 * a12,\n      b06 = a20 * a31 - a21 * a30,\n      b07 = a20 * a32 - a22 * a30,\n      b08 = a20 * a33 - a23 * a30,\n      b09 = a21 * a32 - a22 * a31,\n      b10 = a21 * a33 - a23 * a31,\n      b11 = a22 * a33 - a23 * a32,\n\n      det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n  return mat4(\n      a11 * b11 - a12 * b10 + a13 * b09,\n      a02 * b10 - a01 * b11 - a03 * b09,\n      a31 * b05 - a32 * b04 + a33 * b03,\n      a22 * b04 - a21 * b05 - a23 * b03,\n      a12 * b08 - a10 * b11 - a13 * b07,\n      a00 * b11 - a02 * b08 + a03 * b07,\n      a32 * b02 - a30 * b05 - a33 * b01,\n      a20 * b05 - a22 * b02 + a23 * b01,\n      a10 * b10 - a11 * b08 + a13 * b06,\n      a01 * b08 - a00 * b10 - a03 * b06,\n      a30 * b04 - a31 * b02 + a33 * b00,\n      a21 * b02 - a20 * b04 - a23 * b00,\n      a11 * b07 - a10 * b09 - a12 * b06,\n      a00 * b09 - a01 * b07 + a02 * b06,\n      a31 * b01 - a30 * b03 - a32 * b00,\n      a20 * b03 - a21 * b01 + a22 * b00) / det;\n}\n\n#endif\n\n",transpose="#define GLSLIFY 1\n\n#ifndef ENABLE_ES3\n\nfloat transpose(float m) {\n  return m;\n}\n\nmat2 transpose(mat2 m) {\n  return mat2(m[0][0], m[1][0],\n              m[0][1], m[1][1]);\n}\n\nmat3 transpose(mat3 m) {\n  return mat3(m[0][0], m[1][0], m[2][0],\n              m[0][1], m[1][1], m[2][1],\n              m[0][2], m[1][2], m[2][2]);\n}\n\nmat4 transpose(mat4 m) {\n  return mat4(m[0][0], m[1][0], m[2][0], m[3][0],\n              m[0][1], m[1][1], m[2][1], m[3][1],\n              m[0][2], m[1][2], m[2][2], m[3][2],\n              m[0][3], m[1][3], m[2][3], m[3][3]);\n}\n\n#endif\n\n",quadVertexFromID="#define GLSLIFY 1\nattribute float vertexIDs;\n\nvec2 getQuadVertexPositionFromID() {\n  int vertexID = int(vertexIDs);\n  if (vertexID == 0)\n    return vec2(-0.5, -0.5);\n  else if (vertexID == 1)\n    return vec2(0.5, -0.5);\n  else if (vertexID == 2)\n    return vec2(-0.5, 0.5);\n  else if (vertexID == 3)\n    return vec2(0.5, 0.5);\n  return vec2(0,0);\n}\n",unpackHDR="#define GLSLIFY 1\n\nvec3 decodeHDR(const in vec3 ldrPixel, const in float cdmAlpha) {\n  float avg = (cdmAlpha * 16.0 - 8.0);\n  float scl = 1.0;\n  vec3 color;\n  color.x = (tan((ldrPixel.x-0.5)*1.5)/scl)+avg;\n  color.y = (tan((ldrPixel.y-0.5)*1.5)/scl)+avg;\n  color.z = (tan((ldrPixel.z-0.5)*1.5)/scl)+avg;\n\n  // convert from logarithmic curve to linear curve.\n  // subtract the epsilon that was added during encoding.\n  const float eps = 0.001;\n  color.x = pow(10.0, color.x) - eps;\n  color.y = pow(10.0, color.y) - eps;\n  color.z = pow(10.0, color.z) - eps;\n  return color;\n}\n\nvec3 decodeHDR(sampler2D ldrSampler, sampler2D cdmSampler, vec2 texCoord) {\n#ifdef ENABLE_ES3\n  float cdm = texture2D(cdmSampler, texCoord).r;\n#else\n  float cdm = texture2D(cdmSampler, texCoord).a;\n#endif\n  return decodeHDR(texture2D(ldrSampler, texCoord).rgb, cdm);\n}\n\n",surfaceGeomData="#define GLSLIFY 1\n\n  uniform int floatGeomBuffer; // Remove once we update UX. \n  uniform int passId;\n  uniform int occlusionCulling;\n  uniform int debugGeomDataBuffer;\n\n  import 'geomItemFlags.glsl'\n  import 'GLSLBits.glsl'\n  import 'geomType.glsl'\n  \n  vec4 setFragColor_geomData(vec3 v_viewPos, float geomItemId, float elemItemId, int isOrthographic, int flags, int geomType){\n    vec4 fragColor;\n  \n    if (occlusionCulling != 0) {\n      // Transparent geoms do not render to the occlusion buffer\n      if (testFlag(flags, GEOMITEM_TRANSPARENT)) {\n        discard;\n        return fragColor;\n      }\n\n      // Calculate a simple stochastic transparency to reduce the cost of the reduction shader.\n      // We only need one pixel to be visible to consider the geometry visible, so here we \n      // keep only one in 7x7 (49) pixels. This signficatly reduces the cost of reducing the scene\n      // to the reduction data buffer.\n      // Note: this is not a stochastic transparency, as we are simply setting black pixels to \n      // reduce the number of reduction points for this geometry. The black pixels (not discarded)\n      // still occlude other geometries, but during reduction count to nothing.\n      int x = int(gl_FragCoord.x * 1000.0);\n      int y = int(gl_FragCoord.y * 1000.0);\n      if (x % 7 != 0 || y % 7 != 0) {\n        fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n      } else {\n        // Write out just the green channel for the ReductionShader\n        fragColor.r = float(geomItemId);\n\n        // Write out a value to the Green channel to indicate this is not a BBox.\n        // We propagate this value in the ReductionShader to the output histogram\n        // to determine if we should trigger loading of placeholders. (BBox should not)\n        fragColor.g = 1.0;\n\n        \n        // Note: the alpha value is simply so we can debug the buffer over the top of the viewport.\n        fragColor.a = 1.0;\n      }\n    }\n    else {\n      // When not occlusion culling, we don't render non-selectable objects.\n      //When occlusion culling, we want to draw all the geom data for all objects.\n      if (testFlag(flags, GEOMITEM_INVISIBLE_IN_GEOMDATA)) {\n        discard;\n        return fragColor;\n      }\n\n      float viewDist;\n      if (isOrthographic > 0) {\n        viewDist = abs(v_viewPos.z);\n      } else {\n        viewDist = length(v_viewPos);\n      }\n      \n      fragColor.r = float(passId); \n      fragColor.g = float(geomItemId);\n      fragColor.b = elemItemId;\n      fragColor.a = viewDist;\n      \n      if (debugGeomDataBuffer == 1) {\n        if (geomType == TRIANGLES) {\n          fragColor = vec4(1.0, 0.0, 0.0, 1.0); \n        }\n        else if (geomType == LINES) {\n          fragColor = vec4(0.0, 1.0, 0.0, 1.0); \n        } \n        else if (geomType == POINTS) {\n          fragColor = vec4(0.0, 0.0, 1.0, 1.0); \n        } \n      }\n\n    }\n\n    return fragColor;\n  }\n  vec4 setFragColor_geomData(vec3 v_viewPos, float geomItemId, float elemItemId, int isOrthographic, int flags){\n    return setFragColor_geomData(v_viewPos, geomItemId, 0.0, isOrthographic, flags, TRIANGLES);\n  }\n\n  vec4 setFragColor_geomData(vec3 v_viewPos, int floatGeomBuffer, int passId, float geomItemId, int isOrthographic){\n    return setFragColor_geomData(v_viewPos, geomItemId, 0.0, isOrthographic, 0);\n  }\n  vec4 setFragColor_geomData(vec3 v_viewPos, int floatGeomBuffer, int passId, float geomItemId, float elemItemId, int isOrthographic){\n    return setFragColor_geomData(v_viewPos, geomItemId, elemItemId, isOrthographic, 0);\n  }",surfaceHighlight="#define GLSLIFY 1\nimport 'GLSLUtils.glsl'\nimport 'drawItemTexture.glsl'\n\nvec4 getHighlightColor(int id) {\n  return fetchTexel(instancesTexture, instancesTextureSize, (id * pixelsPerItem) + 4);\n}\n\nvec4 setFragColor_highlight(float geomItemId){\n  vec4 fragColor = getHighlightColor(int(round(geomItemId)));\n  return fragColor;\n}\n",imageAtlas="#define GLSLIFY 1\n// Note: On mobile, I can't seem to pass around a stuct containing sampler2D.\n// I have to unpack the struct and pass its members. :(\n// struct ImageAtlas {\n//     sampler2D layout;\n//     sampler2D image;\n//     vec4 desc;\n// };\n\nimport 'GLSLUtils.glsl'\n\nvec4 getSubImageLayout(int index, in sampler2D atlasLayout, in vec4 atlasDesc){\n    return fetchTexel(atlasLayout, int(floor(atlasDesc.z+0.5)), index);\n}\nvec2 calcSubImageTexCoords(vec2 texCoord, int index, in sampler2D atlasLayout, in vec4 atlasDesc){\n    vec4 layoutData = fetchTexel(atlasLayout, int(floor(atlasDesc.z+0.5)), index);\n    // The following line is a hack to fix artifacts in our PBR lighting\n    // We were seeing loads of lighting garbage on some sufaces that were orthogonal\n    // to the world. The UV coordinates would have been landing right on the edges\n    // of our subimages and were often sampling outside the image. This couuld\n    // have been because of filtering, or an error in the uv coords. \n    texCoord = clamp(texCoord, vec2(0.01, 0.01), vec2(0.99, 0.99));\n    vec2 subimageTexel = texCoord * layoutData.zw;\n    // subimageTexel = clamp(subimageTexel, vec2(0.0, 0.0), vec2(1.0, 1.0));\n    return subimageTexel + layoutData.xy;\n}\nvec4 sampleSubImage(vec2 texCoord, int index, in sampler2D atlasLayout, in sampler2D atlasImage, in vec4 atlasDesc){\n    vec4 layoutData = fetchTexel(atlasLayout, int(floor(atlasDesc.z+0.5)), index);\n    vec2 atlasCoords = calcSubImageTexCoords(texCoord, index, atlasLayout, atlasDesc);\n    return texture2D(atlasImage, atlasCoords);\n}";shaderLibrary.setShaderModule("imageAtlas.glsl",imageAtlas),shaderLibrary.setShaderModule("surfaceGeomData.glsl",surfaceGeomData),shaderLibrary.setShaderModule("surfaceHighlight.glsl",surfaceHighlight),shaderLibrary.setShaderModule("computeViewNormal.glsl",computeViewNormal),shaderLibrary.setShaderModule("calcFatLinesViewPos.glsl",calcFatLinesViewPos),shaderLibrary.setShaderModule("constants.glsl",constants),shaderLibrary.setShaderModule("convolve-helpers.glsl",convolveHelpers),shaderLibrary.setShaderModule("cutaways.glsl",cutaways),shaderLibrary.setShaderModule("debugColors.glsl",debugColors),shaderLibrary.setShaderModule("drawItemId.glsl",geomItemId),shaderLibrary.setShaderModule("geomItemId.glsl",geomItemId),shaderLibrary.setShaderModule("geomItemFlags.glsl",geomItemFlags),shaderLibrary.setShaderModule("geomType.glsl",geomType),shaderLibrary.setShaderModule("geometryMask.glsl",geometryMask),shaderLibrary.setShaderModule("drawItemTexture.glsl",drawItemTexture),shaderLibrary.setShaderModule("envmap-dualfisheye.glsl",envmapDualfisheye),shaderLibrary.setShaderModule("envmap-equirect.glsl",envmapEquirect),shaderLibrary.setShaderModule("envmap-octahedral.glsl",envmapOctahedral),shaderLibrary.setShaderModule("GLSLBits.glsl",GLSLBits),shaderLibrary.setShaderModule("GLSLUtils.glsl",GLSLUtils),shaderLibrary.setShaderModule("Hammersley.glsl",Hammersley),shaderLibrary.setShaderModule("ImportanceSampleGGX.glsl",ImportanceSampleGGX),shaderLibrary.setShaderModule("materialparams.glsl",materialparams),shaderLibrary.setShaderModule("modelMatrix.glsl",modelMatrix),shaderLibrary.setShaderModule("PBRSurfaceRadiance.glsl",PBRSurfaceRadiance),shaderLibrary.setShaderModule("SHCoeffs.glsl",SHCoeffs),shaderLibrary.setShaderModule("gamma.glsl",gamma),shaderLibrary.setShaderModule("inverse.glsl",inverse),shaderLibrary.setShaderModule("transpose.glsl",transpose),shaderLibrary.setShaderModule("quadVertexFromID.glsl",quadVertexFromID),shaderLibrary.setShaderModule("unpackHDR.glsl",unpackHDR);var frag$i=" \nprecision highp float;\n#define GLSLIFY 1\n\nvarying vec2 v_texCoord;\nuniform sampler2D ldrSampler;\nuniform sampler2D cdmSampler;\nuniform vec4 srcRegion; // pos, and size of the source region\n\nimport 'unpackHDR.glsl'\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\nvoid main(void) {\n\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  vec2 srcUv = srcRegion.xy + (v_texCoord * srcRegion.zw);\n\n  fragColor = vec4(decodeHDR(ldrSampler, cdmSampler, srcUv), 1.0);\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n\n",vert$j="\nprecision highp float;\n#define GLSLIFY 1\n\nimport 'quadVertexFromID.glsl'\n\n/* VS Outputs */\nvarying vec2 v_texCoord;\n \nvoid main()\n{\n  vec2 position = getQuadVertexPositionFromID();\n  v_texCoord = position+0.5;\n  gl_Position = vec4(position*2.0, 0.0, 1.0);\n}\n";class UnpackHDRShader extends GLShader{constructor(A){super(A,"UnpackHDRShader"),this.setShaderStage("VERTEX_SHADER",vert$j),this.setShaderStage("FRAGMENT_SHADER",frag$i)}}const genDataTypeDesc=(A,g)=>{let I,C,e;switch(g){case"UInt8":I=1,C=4,e=A.UNSIGNED_BYTE;break;case"SInt8":I=1,C=1,e=A.BYTE;break;case"UInt16":I=1,C=2,e=A.UNSIGNED_SHORT;break;case"SInt16":I=1,C=2,e=A.SHORT;break;case"UInt32":I=1,C=4,e=A.UNSIGNED_INT;break;case"SInt32":I=1,C=4,e=A.INT;break;case"Float32":I=1,C=4,e=A.FLOAT;break;case"Vec2f8":I=2,C=1,e=A.BYTE;break;case"Vec2f16":I=2,C=2,e=A.HALF_FLOAT;break;case"Vec2":I=2,C=4,e=A.FLOAT;break;case"Vec3f8":I=3,C=1,e=A.BYTE;break;case"Vec3f16":I=3,C=2,e=A.HALF_FLOAT;break;case"Vec3":I=3,C=4,e=A.FLOAT;break;case"Vec4":case"Color":I=4,C=4,e=A.FLOAT;break;case"Vec4f8":I=4,C=1,e=A.BYTE;break;case"Vec4f16":I=4,C=2,e=A.HALF_FLOAT;break;case"RGBA":I=4,C=1,e=A.UNSIGNED_BYTE;break;default:throw"Unhandled Type:"+g}return{name:g,dimension:I,elementSize:C,dataType:e}};class IGeomShaderBinding{}class GeomShaderBinding extends IGeomShaderBinding{gl;shaderAttrs;glattrbuffers;indexBuffer;constructor(A,g,I,C){super(),this.gl=A,this.shaderAttrs=g,this.glattrbuffers=I,this.indexBuffer=C}bind(A){const g=this.gl;for(const A in this.shaderAttrs){if("instancedIds"==A)continue;const I=this.shaderAttrs[A],C=I.location;if(-1==C)continue;const e=this.glattrbuffers[A];if(!e){g.disableVertexAttribArray(C);continue}const i=e.dimension,t=e.dataType,o=e.normalized,a=I.integer,B=i*e.elementSize,s=null!=e.offset?e.offset*i*e.elementSize:0,l=I.instanced;g.enableVertexAttribArray(C),g.bindBuffer(g.ARRAY_BUFFER,e.buffer),a?g.vertexAttribIPointer(C,i,t,B,s):g.vertexAttribPointer(C,i,t,o,B,s),1==l?g.vertexAttribDivisor(C,1):g.vertexAttribDivisor(C,0)}return this.indexBuffer&&g.bindBuffer(g.ELEMENT_ARRAY_BUFFER,this.indexBuffer),!0}unbind(A){const g=this.gl;for(const A in this.shaderAttrs){const I=this.shaderAttrs[A],C=I.location;-1==C&&g.enableVertexAttribArray(C),I.instanced&&g.vertexAttribDivisor(C,0)}g.bindBuffer(g.ELEMENT_ARRAY_BUFFER,null)}destroy(){}}class VAOGeomShaderBinding extends IGeomShaderBinding{vao;gl;indexBuffer;constructor(A,g,I,C){super(),this.gl=A,this.vao=A.createVertexArray(),A.bindVertexArray(this.vao);for(const C in g){if("instancedIds"==C)continue;const e=g[C],i=e.location;if(-1==i)continue;let t=I[C],o=0;if(!t&&(C.endsWith("Next")&&(t=I[C.substring(0,C.length-4)],o=1*t.dimension*t.elementSize),!t)){A.disableVertexAttribArray(i);continue}const a=t.dimension,B=t.dataType,s=t.dimension*t.elementSize,l=e.integer,n=e.instanced;if(A.enableVertexAttribArray(i),A.bindBuffer(A.ARRAY_BUFFER,t.buffer),l)A.vertexAttribIPointer(i,a,B,s,o);else{const g=1==t.normalized;A.vertexAttribPointer(i,a,B,g,s,o)}A.vertexAttribDivisor&&(1==n?A.vertexAttribDivisor(i,1):A.vertexAttribDivisor(i,0))}this.indexBuffer=C,this.indexBuffer&&A.bindBuffer(A.ELEMENT_ARRAY_BUFFER,this.indexBuffer)}bind(A){const g=this.gl;return g.bindVertexArray(this.vao),this.indexBuffer&&g.bindBuffer(g.ELEMENT_ARRAY_BUFFER,this.indexBuffer),!0}unbind(A){const g=this.gl;g.bindVertexArray(null),this.indexBuffer&&g.bindBuffer(g.ELEMENT_ARRAY_BUFFER,null)}destroy(){const A=this.gl;this.indexBuffer&&(A.bindVertexArray(this.vao),A.bindBuffer(A.ELEMENT_ARRAY_BUFFER,null)),A.deleteVertexArray(this.vao)}}function generateShaderGeomBinding(A,g,I,C){return null==A.createVertexArray?new GeomShaderBinding(A,g,I,C):new VAOGeomShaderBinding(A,g,I,C)}class GLHDRImage extends GLTexture2D{listenerIDs={};hdrImage;fbo=null;srcLDRTex=null;srcCDMTex=null;unpackHDRShader=null;shaderBinding=null;constructor(A,g){super(A),this.hdrImage=g;const I=()=>{this.__unpackHDRImage(this.hdrImage.getParams())};this.listenerIDs.updated=this.hdrImage.on("updated",I),this.hdrImage.isLoaded()?I():this.listenerIDs.loaded=this.hdrImage.on("loaded",I)}getImage(){return this.hdrImage}__unpackHDRImage(A){const g=this.gl,I=A.data.ldr,C=A.data.cdm;if(this.fbo)this.srcLDRTex.bufferData(I),this.srcCDMTex.bufferData(C);else{this.configure({format:this.gl.RGBA,type:this.gl.HALF_FLOAT,width:I.width,height:I.height,filter:this.gl.LINEAR,wrap:this.gl.CLAMP_TO_EDGE}),this.fbo=new GLFbo(this.gl,this),this.fbo.setClearColor(new Color(0,0,0,0)),this.srcLDRTex=new GLTexture2D(this.gl,{format:this.gl.RGB,type:this.gl.UNSIGNED_BYTE,width:I.width,height:I.height,filter:this.gl.NEAREST,mipMapped:!1,wrap:this.gl.CLAMP_TO_EDGE,data:I}),this.srcCDMTex=new GLTexture2D(this.gl,{format:this.gl.RED,type:this.gl.UNSIGNED_BYTE,width:I.width,height:I.height,filter:this.gl.NEAREST,mipMapped:!1,wrap:this.gl.CLAMP_TO_EDGE,data:C}),this.unpackHDRShader=new UnpackHDRShader(this.gl);const A=this.unpackHDRShader.compileForTarget("GLHDRImage",["#define ENABLE_ES3"]);this.shaderBinding=generateShaderGeomBinding(this.gl,A.attrs,g.__quadattrbuffers,g.__quadIndexBuffer)}const e=new RenderState(this.gl);this.fbo.bindForWriting(e),this.fbo.clear(),this.unpackHDRShader.bind(e,"GLHDRImage"),this.shaderBinding.bind(e);const i=e.unifs;this.srcLDRTex.bindToUniform(e,i.ldrSampler),this.srcCDMTex.bindToUniform(e,i.cdmSampler),g.uniform4fv(i.srcRegion.location,[0,0,1,1]),g.drawQuad(),this.fbo.unbindForWriting(e),this.emit("updated")}bindToUniform(A,g,I){return super.bindToUniform(A,g,I)}destroy(){super.destroy(),this.fbo&&(this.fbo.destroy(),this.srcLDRTex.destroy(),this.srcCDMTex.destroy()),this.unpackHDRShader&&this.unpackHDRShader.destroy(),this.shaderBinding&&this.shaderBinding.destroy(),"loaded"in this.listenerIDs&&this.hdrImage.off("loaded",this.listenerIDs.loaded),this.hdrImage.off("updated",this.listenerIDs.updated)}}class GLGeom extends RefCounted{__gl;geom;numVertices=-1;glattrbuffers={};shaderBindings={};buffersDirty=!0;genBufferOpts={};indexBuffer=null;constructor(A,g){super(),this.__gl=A,this.geom=g;this.geom.on("geomDataChanged",(A=>{this.dirtyBuffers(A)}));this.geom.on("geomDataTopologyChanged",(A=>{this.clearBuffers(),this.dirtyBuffers(A)}))}getGeom(){return this.geom}dirtyBuffers(A){this.genBufferOpts=A,this.buffersDirty=!0,this.emit("updated")}genBuffers(A){const g=this.__gl,I=this.geom.genBuffers();for(const C in I.attrBuffers){if(!A.attrs[C])continue;this.glattrbuffers[C]&&this.glattrbuffers[C].buffer&&g.deleteBuffer(this.glattrbuffers[C].buffer);const e=I.attrBuffers[C],i=genDataTypeDesc(g,e.dataType),t=g.createBuffer();g.bindBuffer(g.ARRAY_BUFFER,t),g.bufferData(g.ARRAY_BUFFER,e.values,g.STATIC_DRAW),this.glattrbuffers[C]={dataType:i.dataType,name:C,dimension:e.dimension,elementSize:i.elementSize,normalized:!1,shared:!1,numValues:e.count,buffer:t}}this.numVertices=this.geom.getNumVertices(),this.buffersDirty=!1}updateBuffers(A){if(this.numVertices!=this.geom.getNumVertices())return void this.genBuffers(A);const g=this.__gl,I=this.geom.genBuffers({includeIndices:!1});for(const A in I.attrBuffers){const C=I.attrBuffers[A],e=this.glattrbuffers[A];g.bindBuffer(g.ARRAY_BUFFER,e.buffer),g.bufferData(g.ARRAY_BUFFER,C.values,g.STATIC_DRAW)}this.buffersDirty=!1}bind(A){this.buffersDirty&&this.updateBuffers(A);let g=this.shaderBindings[A.shaderkey];if(!g){g=generateShaderGeomBinding(this.__gl,A.attrs,this.glattrbuffers,this.indexBuffer),this.shaderBindings[A.shaderkey]=g}g.bind(A)}unbind(A){const g=this.shaderBindings[A.shaderkey];g&&g.unbind(A)}draw(A){throw new Error("Not implemented. Implement this method in a derived class.")}drawInstanced(A,g){throw new Error("Not implemented. Implement this method in a derived class.")}bindAndDraw(A){this.bind(A),this.draw(A)}clearBuffers(){const A=this.__gl;for(const g in this.glattrbuffers){const I=this.glattrbuffers[g];I.shared||A.deleteBuffer(I.buffer)}this.glattrbuffers={};for(const A in this.shaderBindings){this.shaderBindings[A].destroy()}this.shaderBindings={}}destroy(){this.clearBuffers(),super.destroy()}}class GLMesh extends GLGeom{numTriIndices=0;indexDataType=0;numTriangles=0;constructor(A,g){super(A,g)}genBuffers(A){super.genBuffers(A);const g=this.__gl,I=this.geom.genBuffers(),C=I.indices;C instanceof Uint8Array&&(this.indexDataType=this.__gl.UNSIGNED_BYTE),C instanceof Uint16Array&&(this.indexDataType=this.__gl.UNSIGNED_SHORT),C instanceof Uint32Array&&(this.indexDataType=this.__gl.UNSIGNED_INT),this.indexBuffer&&g.deleteBuffer(this.indexBuffer),this.indexBuffer=g.createBuffer(),g.bindBuffer(g.ELEMENT_ARRAY_BUFFER,this.indexBuffer),g.bufferData(g.ELEMENT_ARRAY_BUFFER,I.indices,g.STATIC_DRAW),this.numTriIndices=I.indices.length,this.numTriangles=C.length/3,this.glattrbuffers.textureCoords&&(this.glattrbuffers.texCoords=this.glattrbuffers.textureCoords,delete this.glattrbuffers.textureCoords)}clearBuffers(){this.__gl.deleteBuffer(this.indexBuffer),this.indexBuffer=null,super.clearBuffers()}bind(A){super.bind(A);const{geomType:g}=A.unifs;g&&this.__gl.uniform1i(g.location,0)}draw(A){this.__gl.drawElements(this.__gl.TRIANGLES,this.numTriIndices,this.indexDataType,0)}drawInstanced(A,g){this.__gl.drawElementsInstanced(this.__gl.TRIANGLES,this.numTriIndices,this.indexDataType,0,g)}destroy(){super.destroy();this.__gl.deleteBuffer(this.indexBuffer),this.indexBuffer=null}}const FRAMEBUFFER={MSAA_RENDERBUFFER:0,COLORBUFFER:1,DEPTHBUFFER:2};class GLBaseViewport extends ParameterOwner{__gl;renderer;__renderer;__fbo=null;quad;offscreenBuffer=null;depthTexture=null;highlightedGeomsBufferFbo;__backgroundTexture=null;__backgroundGLTexture=null;offscreenBufferFbo=null;width=0;height=0;__canvasWidth=0;__canvasHeight=0;fb=null;colorRenderbuffer;depthBuffer=null;EXT_frag_depth=null;manipulator;depthRange=[0,0];region=[0,0,0,0];backgroundColorParam=new ColorParameter("BackgroundColor",new Color("#eeeeee"));clickTime=200;doubleClickTime=200;longPressTime=1e3;pointerClickTolerance=5;constructor(A){super(),this.renderer=A,this.__renderer=A;const g=this.__renderer.gl;this.__gl=g,this.quad=new GLMesh(g,new Plane(1,1)),this.highlightedGeomsBufferFbo=new GLRenderTarget(g,{type:g.UNSIGNED_BYTE,format:g.RGBA,filter:g.NEAREST,width:4,height:4,createDepthTexture:!0}),this.highlightedGeomsBufferFbo.clearColor=new Color(0,0,0,0);const I=()=>{const A=this.backgroundColorParam.value;A instanceof BaseImage?A instanceof HDRImage?(this.__backgroundTexture=A,this.__backgroundGLTexture=new GLHDRImage(g,A)):(this.__backgroundTexture=A,this.__backgroundGLTexture=new GLTexture2D(g,A)):A instanceof Color?(this.__backgroundGLTexture&&(this.__backgroundGLTexture.destroy(),this.__backgroundGLTexture=null,this.__backgroundTexture=null),this.offscreenBufferFbo&&(this.offscreenBufferFbo.clearColor=A)):console.warn("Invalid background:"+A),this.emit("updated")};I(),this.backgroundColorParam.on("valueChanged",I)}getRenderer(){return this.renderer}getWidth(){return this.width}getHeight(){return this.height}resize(A,g){if(this.__canvasWidth==A&&this.__canvasHeight==g)return;this.__canvasWidth=A,this.__canvasHeight=g,this.width=A,this.height=g,this.region=[0,0,this.width,this.height],this.resizeRenderTargets(A,g);const I=new ResizedEvent(this.width,this.height);this.emit("resized",I)}resizeRenderTargets(A,g){this.highlightedGeomsBufferFbo&&this.highlightedGeomsBufferFbo.resize(A/devicePixelRatio,g/devicePixelRatio);const I=this.__renderer.gl;if(this.renderer.outlineThickness>0&&"image"==this.renderer.outlineMethod){if("Safari"==SystemDesc.browserName||"webgl"==I.name)return void console.warn("Disabling outlines on Safari due to a regression in WebKit",SystemDesc);this.fb&&(I.deleteFramebuffer(this.fb[FRAMEBUFFER.MSAA_RENDERBUFFER]),I.deleteFramebuffer(this.fb[FRAMEBUFFER.COLORBUFFER]),I.deleteFramebuffer(this.fb[FRAMEBUFFER.DEPTHBUFFER]),this.colorRenderbuffer&&I.deleteRenderbuffer(this.colorRenderbuffer),this.depthBuffer&&I.deleteRenderbuffer(this.depthBuffer)),this.offscreenBuffer&&this.depthTexture?(this.offscreenBuffer.resize(A,g),this.depthTexture.resize(A,g)):(this.offscreenBuffer=new GLTexture2D(I,{type:"UNSIGNED_BYTE",format:"RGBA",filter:"LINEAR",width:4,height:4}),this.depthTexture=new GLTexture2D(I,{type:I.UNSIGNED_INT_24_8,format:I.DEPTH_STENCIL,internalFormat:"webgl"==I.name?I.DEPTH24_STENCIL8:I.DEPTH_COMPONENT,filter:I.NEAREST,wrap:I.CLAMP_TO_EDGE,width:4,height:4})),this.fb=[],this.fb[FRAMEBUFFER.MSAA_RENDERBUFFER]=I.createFramebuffer(),I.bindFramebuffer(I.FRAMEBUFFER,this.fb[FRAMEBUFFER.MSAA_RENDERBUFFER]),this.colorRenderbuffer=I.createRenderbuffer(),I.bindRenderbuffer(I.RENDERBUFFER,this.colorRenderbuffer),this.renderer.multiSampledScreenBuffer?I.renderbufferStorage(I.RENDERBUFFER,I.RGBA8,A,g):I.renderbufferStorageMultisample(I.RENDERBUFFER,4,I.RGBA8,A,g),I.framebufferRenderbuffer(I.FRAMEBUFFER,I.COLOR_ATTACHMENT0,I.RENDERBUFFER,this.colorRenderbuffer),this.depthBuffer=I.createRenderbuffer(),I.bindRenderbuffer(I.RENDERBUFFER,this.depthBuffer),this.renderer.multiSampledScreenBuffer?I.renderbufferStorage(I.RENDERBUFFER,I.DEPTH24_STENCIL8,A,g):I.renderbufferStorageMultisample(I.RENDERBUFFER,4,I.DEPTH24_STENCIL8,A,g),I.framebufferRenderbuffer(I.FRAMEBUFFER,I.DEPTH_ATTACHMENT,I.RENDERBUFFER,this.depthBuffer),this.fb[FRAMEBUFFER.COLORBUFFER]=I.createFramebuffer(),I.bindFramebuffer(I.FRAMEBUFFER,this.fb[FRAMEBUFFER.COLORBUFFER]),I.framebufferTexture2D(I.FRAMEBUFFER,I.COLOR_ATTACHMENT0,I.TEXTURE_2D,this.offscreenBuffer.glTex,0),I.bindFramebuffer(I.FRAMEBUFFER,null),this.fb[FRAMEBUFFER.DEPTHBUFFER]=I.createFramebuffer(),I.bindFramebuffer(I.FRAMEBUFFER,this.fb[FRAMEBUFFER.DEPTHBUFFER]),I.framebufferTexture2D(I.FRAMEBUFFER,I.DEPTH_ATTACHMENT,I.TEXTURE_2D,this.depthTexture.glTex,0),I.bindFramebuffer(I.FRAMEBUFFER,null);const C=I.checkFramebufferStatus("webgl"==I.name?I.DRAW_FRAMEBUFFER:I.FRAMEBUFFER);if(C!==I.FRAMEBUFFER_COMPLETE)switch(C){case I.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:throw new Error("The attachment types are mismatched or not all framebuffer attachment points are framebuffer attachment complete.");case I.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:throw new Error("There is no attachment.");case I.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:throw new Error("Height and width of the attachment are not the same.");case I.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:throw new Error("The format of the attachment is not supported or if depth and stencil attachments are not the same renderbuffer.");case 36061:throw new Error("The framebuffer is unsupported");default:throw new Error("Incomplete Frambuffer")}}}draw(A){const g=this.__renderer.gl;A.pushGLStack("GLBaseViewport.draw");const I=A.boundRendertarget;if(this.renderer.outlineThickness>0&&"image"==this.renderer.outlineMethod){if("Safari"==SystemDesc.browserName||"webgl"==g.name)console.warn("Disabling outlines on Safari due to a regression in WebKit",SystemDesc);else{this.fb||this.resizeRenderTargets(this.width,this.height);const I=this.fb[FRAMEBUFFER.MSAA_RENDERBUFFER];g.bindFramebuffer("webgl"==g.name?g.DRAW_FRAMEBUFFER:g.FRAMEBUFFER,I),A.boundRendertarget=I}}else A.boundRendertarget||g.bindFramebuffer(g.FRAMEBUFFER,null);A.glEnable(g.DEPTH_TEST),this.__renderer.drawScene(A);const C=A.toHighlightRenderState();if(this.drawHighlights(C),0!=C.stack.length&&console.warn(" corrupt highlightRenderState.stack.length:",C.stack.length),this.fb){g.bindFramebuffer(g.READ_FRAMEBUFFER,this.fb[FRAMEBUFFER.MSAA_RENDERBUFFER]),g.bindFramebuffer(g.DRAW_FRAMEBUFFER,this.fb[FRAMEBUFFER.COLORBUFFER]),g.clearBufferfv(g.COLOR,0,[0,0,0,0]),g.blitFramebuffer(0,0,this.width,this.height,0,0,this.width,this.height,g.COLOR_BUFFER_BIT,g.LINEAR),g.bindFramebuffer(g.DRAW_FRAMEBUFFER,I),A.boundRendertarget=I,g.viewport(this.region[0],this.region[1],this.region[2],this.region[3]),g.disable(g.DEPTH_TEST);const C=this.__renderer.screenQuad;C.bindShader(A),C.draw(A,this.offscreenBuffer),g.enable(g.DEPTH_TEST)}A.popGLStack(),this.renderer.emit("redrawOccurred")}drawSilhouettes(A){A.pushGLStack("GLBaseViewport.drawSilhouettes");const g=this.__renderer.gl;g.bindFramebuffer(g.READ_FRAMEBUFFER,this.fb[FRAMEBUFFER.MSAA_RENDERBUFFER]),g.bindFramebuffer(g.DRAW_FRAMEBUFFER,this.fb[FRAMEBUFFER.DEPTHBUFFER]),g.clearBufferfv(g.COLOR,0,[1,1,1,1]),g.blitFramebuffer(0,0,this.width,this.height,0,0,this.width,this.height,g.DEPTH_BUFFER_BIT,g.NEAREST),g.bindFramebuffer(g.DRAW_FRAMEBUFFER,this.fb[FRAMEBUFFER.MSAA_RENDERBUFFER]),A.boundRendertarget=this.fb[FRAMEBUFFER.MSAA_RENDERBUFFER],g.viewport(this.region[0],this.region[1],this.region[2],this.region[3]),A.glEnable(g.BLEND),A.glDisable(g.DEPTH_TEST),g.blendEquation(g.FUNC_ADD),g.blendFuncSeparate(g.SRC_ALPHA,g.ONE_MINUS_SRC_ALPHA,g.ZERO,g.ONE),g.depthMask(!1),this.renderer.silhouetteShader.bind(A);const I=A.unifs;this.depthTexture.bindToUniform(A,I.depthTexture),g.uniform2f(I.screenSize.location,this.width,this.height),g.uniform1f(I.outlineThickness.location,this.renderer.outlineThickness*window.devicePixelRatio);const C=this.renderer.outlineColor.asArray();g.uniform4f(I.outlineColor.location,C[0],C[1],C[2],C[3]),g.uniform1f(I.outlineSensitivity.location,this.renderer.outlineSensitivity),g.uniform1f(I.outlineDepthBias.location,this.renderer.outlineDepthBias),g.uniform2f(I.depthRange.location,this.depthRange[0],this.depthRange[1]),this.quad.bindAndDraw(A),g.depthMask(!0),A.popGLStack()}drawHighlights(A){if(this.highlightedGeomsBufferFbo){const g=this.__renderer.gl;A.pushGLStack("GLBaseViewport.drawHighlights"),this.highlightedGeomsBufferFbo.bindForWriting(A,!0),A.glEnable(g.CULL_FACE),A.glEnable(g.DEPTH_TEST),A.glDisable(g.BLEND),g.depthFunc(g.LESS),g.depthMask(!0),A.glShader=null,this.__renderer.drawHighlightedGeoms(A),this.highlightedGeomsBufferFbo.unbindForWriting(A),g.viewport(this.region[0],this.region[1],this.region[2],this.region[3]);{A.pushGLStack("GLBaseViewport.drawHighlights.highlightsShader"),this.renderer.highlightsShader.bind(A),A.glEnable(g.BLEND),g.blendEquation(g.FUNC_ADD),g.blendFuncSeparate(g.SRC_ALPHA,g.ONE_MINUS_SRC_ALPHA,g.ONE,g.ONE);const I=A.unifs;g.uniform1f(I.outlineThickness.location,this.renderer.highlightOutlineThickness),this.highlightedGeomsBufferFbo.bindColorTexture(A,I.highlightDataTexture),this.quad.bindAndDraw(A),A.popGLStack()}A.popGLStack()}}getManipulator(){return this.manipulator}setManipulator(A){this.manipulator!=A&&(this.manipulator&&this.manipulator.deactivateTool&&this.manipulator.deactivateTool(),this.manipulator=A,this.manipulator.activateTool&&this.manipulator.activateTool())}onPointerDown(A){console.warn("@GLBaseViewport#onPointerDown - Implement me!")}onPointerUp(A){console.warn("@GLBaseViewport#onPointerUp - Implement me!")}onPointerMove(A){console.warn("@GLBaseViewport#onPointerMove - Implement me!")}onPointerEnter(A){console.warn("@GLBaseViewport#onPointerEnter - Implement me!")}onPointerLeave(A){console.warn("@GLBaseViewport#onPointerLeave - Implement me!")}onMouseLeave(A){}onKeyDown(A){}onKeyUp(A){}}class GLViewport extends GLBaseViewport{debugGeomDataBuffer=!1;pointAndLinePickingSize=3;debugOcclusionBuffer=!1;debugReductionBuffer=!1;debugHighlightedGeomsBuffer=!1;mousePointerSearchArea=5;touchPointerSearchArea=45;projectionMatrix;viewportFrustum;camera;bottomLeftCoords=new Vec2(0,0);topRightCoords=new Vec2(1,1);posX=0;posY=0;pointerDownTime=[];pointerDownButton=-1;pointerDownPos=new Vec2(-1,-1);prevClickTime;prevClickPos=new Vec2(-1,-1);prevClickButton=-1;geomDataBufferSizeFactor=window.devicePixelRatio;geomDataRenderTarget;geomDataBufferInvalid=!0;cameraXfo=new Xfo;cameraMat=new Mat4;viewMatrix=new Mat4;screenPos=null;intersectionData;pointerOverItem;longPressId;constructor(A,g,I,C){super(A),this.name=g,this.projectionMatrix=new Mat4,this.viewportFrustum=new Vec4,this.bottomLeftCoords=new Vec2(0,0),this.topRightCoords=new Vec2(1,1),this.prevClickTime=0,SystemDesc.isMobileDevice&&(this.geomDataBufferSizeFactor=8);const e=this.__renderer.gl;this.geomDataRenderTarget=new GLRenderTarget(e,{type:A.floatGeomBuffer?e.FLOAT:e.UNSIGNED_BYTE,format:e.RGBA,filter:e.NEAREST,width:I<=1?1:Math.floor(I/this.geomDataBufferSizeFactor),height:C<=1?1:Math.floor(C/this.geomDataBufferSizeFactor),createDepthTexture:!0}),this.geomDataRenderTarget.clearColor=new Color(0,0,0,0),this.camera=new Camera("DefaultCamera"),this.setCamera(this.camera),this.setManipulator(new CameraManipulator({renderer:A})),this.resize(I,C)}getBl(){return this.bottomLeftCoords}setBl(A){this.bottomLeftCoords=A,this.#n()}getTr(){return this.topRightCoords}setTr(A){this.topRightCoords=A,this.#n()}getPosX(){return this.posX}getPosY(){return this.posY}resize(A,g){this.__canvasWidth=A,this.__canvasHeight=g,this.#n()}#n(){this.posX=Math.round(this.__canvasWidth*this.bottomLeftCoords.x),this.posY=Math.round(this.__canvasWidth*this.bottomLeftCoords.y),this.width=Math.round(this.__canvasWidth*this.topRightCoords.x-this.__canvasWidth*this.bottomLeftCoords.x),this.height=Math.round(this.__canvasHeight*this.topRightCoords.y-this.__canvasHeight*this.bottomLeftCoords.y),this.region=[this.posX,this.posY,this.width,this.height],this.camera&&this.updateProjectionMatrix(),this.resizeRenderTargets(this.width,this.height);const A=new ResizedEvent(this.width,this.height);this.emit("resized",A)}resizeRenderTargets(A,g){super.resizeRenderTargets(A,g),this.geomDataRenderTarget&&(this.geomDataRenderTarget.resize(Math.floor(this.width/this.geomDataBufferSizeFactor),Math.floor(this.height/this.geomDataBufferSizeFactor)),this.invalidateGeomDataBuffer())}getCamera(){return this.camera}setCamera(A){this.camera=A,this.depthRange=[this.camera.getNear(),this.camera.getFar()];const g=A.globalXfoParam,I=()=>{this.cameraXfo=g.value,this.cameraMat=this.cameraXfo.toMat4(),this.viewMatrix=this.cameraMat.inverse()};I(),g.on("valueChanged",(()=>{I(),this.emit("updated"),this.invalidateGeomDataBuffer();const A=new ViewChangedEvent("CameraAndPointer",this.cameraXfo);this.emit("viewChanged",A)})),this.camera.on("projectionParamChanged",(()=>{this.updateProjectionMatrix(),this.depthRange=[this.camera.getNear(),this.camera.getFar()],this.emit("updated")})),this.updateProjectionMatrix()}updateProjectionMatrix(){const A=this.width/this.height;this.camera.updateProjectionMatrix(this.projectionMatrix,A);const g=this.camera.getFocalDistance(),I=this.camera.getFov(),C=this.camera.isOrthographicParam.value,e=Math.tan(I/2)*g*2,i=e*A,t=this.camera.getFrustumHeight(),o=e*A;this.viewportFrustum.set(MathFunctions.lerp(i,o,C),MathFunctions.lerp(e,t,C),g,I)}getProjectionMatrix(){return this.projectionMatrix}getViewMatrix(){return this.viewMatrix}frameView(A,g=0,I=.1){this.width>0&&this.height>0?this.camera.frameView(this.width,this.height,A,g,I):this.once("resized",(()=>this.frameView(A,g,I)))}calcScreenPosFromWorldPos(A){const g=this.projectionMatrix.multiply(this.viewMatrix).transformVec4(new Vec4(A.x,A.y,A.z,1));return g.x/=g.w,g.y/=g.w,new Vec2((.5*g.x+.5)*this.width,(-.5*g.y+.5)*this.height)}calcRayFromScreenPos(A){const g=A.x*window.devicePixelRatio,I=A.y*window.devicePixelRatio,C=this.__canvasHeight*(1-this.topRightCoords.y),e=(g-this.posX)/this.width*2-1,i=(I-C)/this.height*2-1,t=this.cameraMat,o=this.projectionMatrix.inverse();if(null==o)return console.warn(`Unable to generate Ray from screen pos:${A.toString()} in region ${this.region}`),new Ray;let a,B;if(this.camera.isOrthographic()){const A=o.transformVec3(new Vec3(e,-i,-1));A.z=0,a=t.transformVec3(A),B=new Vec3(0,0,-1)}else a=t.translation,B=o.transformVec3(new Vec3(e,-i,-1));return B=t.rotateVec3(B).normalize(),new Ray(a,B)}renderGeomDataFbo(){if(this.geomDataRenderTarget){const A=new GeomDataRenderState(this.renderer.__gl);A.pushGLStack("GLViewport.renderGeomDataFbo"),this.bindGLViewport(A),A.geomDataFbo=this.geomDataRenderTarget,A.debugGeomDataBuffer=this.debugGeomDataBuffer,A.pointAndLinePickingSize=this.pointAndLinePickingSize,this.geomDataRenderTarget.bindForWriting(A,!0),this.__renderer.drawSceneGeomData(A),this.geomDataRenderTarget.unbindForWriting(),A.popGLStack(),this.geomDataBufferInvalid=!1}}invalidateGeomDataBuffer(){this.geomDataBufferInvalid=!0}getGeomDataAtPos(A,g,I=5){if(this.geomDataRenderTarget){if(this.geomDataBufferInvalid&&(this.renderGeomDataFbo(),this.screenPos=null),A===this.screenPos)return this.intersectionData;this.screenPos=A,this.intersectionData=null;const C=this.__renderer.gl;C.finish(),this.geomDataRenderTarget.bindForReading();const e=A.x*window.devicePixelRatio,i=A.y*window.devicePixelRatio,t=I*I,o=this.geomDataRenderTarget.width,a=this.geomDataRenderTarget.height,B=Math.floor(e*(o/this.width))-.5*I,s=Math.floor(a-i*(a/this.height)-1)-.5*I,l=new Float32Array(4*t);let n;C.readPixels(B,s,I,I,C.RGBA,C.FLOAT,l),this.geomDataRenderTarget.unbindForReading();let d=null;const r=new Map,c=A=>{const g=63&Math.round(l[4*A+0]),I=this.__renderer.getPass(g);return I?(n=l.slice(4*A,4*(A+1)),d=I.getGeomItemAndDist(n),!!d):(console.warn("Geom data buffer returns invalid pass id:",g),null)},h=I/2;for(let A=0;A<h&&!d;A++)for(let g=-A;g<=A&&!d;g++)for(let C=-A;C<=A&&!d;C++){if(c(h+g+(h+g)*I))break}if(g||(g=this.calcRayFromScreenPos(A)),d){const I=g.start.add(g.dir.scale(d.dist));this.intersectionData=new IntersectionData(A,g,I,n,d),r.has(d.geomItem)&&(this.intersectionData.componentIds=Array.from(r.get(d.geomItem)))}return this.intersectionData}return null}getGeomVisiblity(A,g){if(this.geomDataRenderTarget){this.geomDataBufferInvalid&&(this.renderGeomDataFbo(),this.screenPos=null);const I=this.__renderer.gl;I.finish();const C=this.geomDataRenderTarget.width,e=this.geomDataRenderTarget.height,i=C/this.width,t=e/this.height,o=Math.round(A.x*i),a=Math.round(A.y*t),B=Math.round(g.x*i),s=Math.round(g.y*t),l=Math.round(e-s),n=Math.round(o),d=Math.round(B-o),r=Math.round(s-a),c=d*r;let h;this.geomDataRenderTarget.bindForReading(),this.__renderer.floatGeomBuffer?(h=new Float32Array(4*c),I.readPixels(n,l,d,r,I.RGBA,I.FLOAT,h)):(h=new Uint8Array(4*c),I.readPixels(n,l,d,r,I.RGBA,I.UNSIGNED_BYTE,h)),this.geomDataRenderTarget.unbindForReading();const G=[],m=[],b=new Map;for(let A=0;A<c;A++){let g;const I=h.subarray(4*A,4*(A+1));if(this.__renderer.floatGeomBuffer){if(0==I[3])continue;g=63&Math.round(I[0])}else{if(0==I[0]&&0==I[1])continue;g=Math.floor(I[1]/64)}const C=I[0]+"-"+I[1],e=b.get(C);if(null!=e){m[e]++;continue}const i=this.__renderer.getPass(g)?.getGeomItemAndDist(I);i&&(b.set(C,m.length),m.push(1),G.push(i.geomItem))}const Z=[];for(let A=0;A<m.length;A++)Z[A]=A;return Z.sort(((A,g)=>m[A]>m[g]?-1:1)),{geomItems:Z.map((A=>G[A])),histogram:Z.map((A=>m[A]))}}return null}getGeomItemsInRect(A,g){const I=this.getGeomVisiblity(A,g),C=new Set;return I.geomItems.forEach((A=>{C.add(A)})),C}__getPointerPos(A,g){return new Vec2(A-this.getPosX(),g-this.getPosY())}prepareUIEvent(A){A.viewport=this}onPointerDown(A){if(this.prepareUIEvent(A),A instanceof ZeaMouseEvent)A.pointerPos=this.__getPointerPos(A.rendererX,A.rendererY),A.pointerRay=this.calcRayFromScreenPos(A.pointerPos),this.pointerDownButton=A.button,this.pointerDownPos=A.pointerPos,this.pointerDownTime[A.button]=Date.now();else if(A instanceof ZeaTouchEvent){const g=A.touches[0];A.pointerPos=this.__getPointerPos(g.rendererX,g.rendererY),A.pointerRay=this.calcRayFromScreenPos(A.pointerPos),this.pointerDownButton=0,this.pointerDownPos=A.pointerPos,this.pointerDownTime[0]=Date.now()}A.propagating&&A.getCapture()&&A.getCapture().onPointerDown(A),A.propagating&&(A.intersectionData=this.getGeomDataAtPos(A.pointerPos,A.pointerRay,this.mousePointerSearchArea),A.intersectionData&&A.intersectionData.geomItem.onPointerDown(A)),A.propagating&&this.emit("pointerDown",A),A.propagating&&this.manipulator&&this.manipulator.onPointerDown(A),null!=this.longPressId&&clearTimeout(this.longPressId),(A instanceof ZeaMouseEvent||A instanceof ZeaTouchEvent&&1==A.changedTouches.length)&&(this.longPressId=setTimeout((()=>{this.longPressId=void 0,A.propagating=!0,A.intersectionData&&A.intersectionData.geomItem&&A.intersectionData.geomItem.onPointerLongPress(A),this.emit("pointerLongPress",A),A.propagating&&this.manipulator&&this.manipulator.onPointerLongPress(A)}),this.longPressTime))}onPointerUp(A){if(this.prepareUIEvent(A),A.pointerType===POINTER_TYPES.mouse){const g=A;g.pointerPos=this.__getPointerPos(g.rendererX,g.rendererY),g.pointerRay=this.calcRayFromScreenPos(g.pointerPos)}else if(A.pointerType===POINTER_TYPES.touch){const g=A;if(1==g.changedTouches.length){const A=g.changedTouches[0];g.pointerPos=this.__getPointerPos(A.rendererX,A.rendererY),g.pointerRay=this.calcRayFromScreenPos(g.pointerPos)}}null!=this.longPressId&&clearTimeout(this.longPressId),A.getCapture()&&A.getCapture().onPointerUp(A),A.propagating&&(A.intersectionData=this.getGeomDataAtPos(A.pointerPos,A.pointerRay,this.mousePointerSearchArea),A.intersectionData&&A.intersectionData.geomItem.onPointerUp(A)),A.propagating&&this.emit("pointerUp",A),A.propagating&&this.manipulator&&this.manipulator.onPointerUp(A);const g=A instanceof ZeaMouseEvent?A.button:0,I=Date.now();if((A instanceof ZeaMouseEvent||A instanceof ZeaTouchEvent&&1==A.changedTouches.length)&&I-this.pointerDownTime[g]<this.clickTime&&A.pointerPos.distanceTo(this.pointerDownPos)<this.pointerClickTolerance&&this.pointerDownButton==g){const C=I;A.propagating=!0,g==this.prevClickButton&&C-this.prevClickTime<this.doubleClickTime?(A.intersectionData&&A.intersectionData.geomItem&&A.intersectionData.geomItem.onPointerDoubleClick(A),A.propagating&&A.propagating&&this.emit("pointerDoubleClick",A),A.propagating&&this.manipulator&&this.manipulator.onPointerDoubleClick(A)):(this.prevClickButton=g,this.prevClickPos=A.pointerPos,this.prevClickTime=C,A.intersectionData&&A.intersectionData.geomItem&&A.intersectionData.geomItem.onPointerClick(A),A.propagating&&this.emit("pointerClick",A),A.propagating&&this.manipulator&&this.manipulator.onPointerClick(A))}}onPointerMove(A){if(this.prepareUIEvent(A),A.pointerType===POINTER_TYPES.mouse){const g=A,I=this.__getPointerPos(g.rendererX,g.rendererY);g.pointerPos=I,g.pointerRay=this.calcRayFromScreenPos(I)}else if(A.pointerType===POINTER_TYPES.touch){const g=A;for(let A=0;A<g.touches.length;A++){const I=g.touches[A];I.touchPos=this.__getPointerPos(I.rendererX,I.rendererY),I.touchRay=this.calcRayFromScreenPos(I.touchPos)}g.pointerPos=g.touches[0].touchPos,g.pointerRay=g.touches[0].touchRay}null!=this.longPressId&&A.pointerPos.distanceTo(this.pointerDownPos)>this.pointerClickTolerance&&(clearTimeout(this.longPressId),this.longPressId=void 0),A.getCapture()&&A.getCapture().onPointerMove(A),A.propagating&&(A.intersectionData=this.getGeomDataAtPos(A.pointerPos,A.pointerRay,this.mousePointerSearchArea),A.intersectionData?(A.intersectionData.geomItem!=this.pointerOverItem&&(this.pointerOverItem&&(A.leftGeometry=this.pointerOverItem,this.pointerOverItem.onPointerLeave(A),A.propagating&&this.emit("pointerLeaveGeom",A)),A.propagating=!0,this.pointerOverItem=A.intersectionData.geomItem,this.pointerOverItem.onPointerEnter(A),A.propagating&&this.emit("pointerEnterGeom",A)),A.propagating=!0,A.intersectionData.geomItem.onPointerMove(A)):A.propagating&&this.pointerOverItem&&(A.leftGeometry=this.pointerOverItem,this.pointerOverItem.onPointerLeave(A),this.pointerOverItem=null,this.emit("pointerLeaveGeom",A))),A.propagating&&this.emit("pointerMove",A),A.propagating&&this.manipulator&&this.manipulator.onPointerMove(A)}onPointerEnter(A){this.prepareUIEvent(A),this.emit("pointerEnter",A),A.propagating&&this.manipulator&&this.manipulator.onPointerEnter&&this.manipulator.onPointerEnter(A)}onPointerLeave(A){this.prepareUIEvent(A),this.emit("pointerLeave",A),A.propagating&&(!this.manipulator||!this.manipulator.onPointerLeave||(this.manipulator.onPointerLeave(A),A.propagating))}onKeyDown(A){this.prepareUIEvent(A),this.manipulator&&(this.manipulator.onKeyDown(A),!A.propagating)||this.emit("keyDown",A)}onKeyUp(A){this.prepareUIEvent(A),this.manipulator&&(this.manipulator.onKeyUp(A),!A.propagating)||this.emit("keyUp",A)}onWheel(A){this.prepareUIEvent(A),A.pointerPos=this.__getPointerPos(A.rendererX,A.rendererY),A.pointerRay=this.calcRayFromScreenPos(A.pointerPos),A.intersectionData=this.getGeomDataAtPos(A.pointerPos,A.pointerRay,this.mousePointerSearchArea),(null==A.intersectionData||(A.intersectionData.geomItem.onWheel(A),A.propagating))&&(this.manipulator?this.manipulator.onWheel(A):this.emit("mouseWheel",A))}onTouchCancel(A){this.prepareUIEvent(A),A.getCapture()&&(A.getCapture().onTouchCancel(A),!A.propagating)||this.manipulator&&(this.manipulator.onTouchCancel(A),!A.propagating)||this.emit("touchCancel",A)}bindGLViewport(A){A.viewXfo=this.cameraXfo,A.viewScale=1,A.region=this.region,A.depthRange=this.depthRange,A.cameraMatrix=this.cameraMat,A.viewport=this;const g=this.__renderer.gl;A.bindRendererUnifs=I=>{const{cameraMatrix:C,viewMatrix:e,projectionMatrix:i,eye:t,isOrthographic:o,viewportFrustum:a}=I;C&&g.uniformMatrix4fv(C.location,!1,A.cameraMatrix.asArray()),e&&g.uniformMatrix4fv(e.location,!1,this.viewMatrix.asArray()),i&&g.uniformMatrix4fv(i.location,!1,this.projectionMatrix.asArray()),t&&g.uniform1i(t.location,0),o&&g.uniform1i(o.location,this.camera.isOrthographic()?1:0),a&&this.viewportFrustum&&g.uniform4f(a.location,this.viewportFrustum.x,this.viewportFrustum.y,this.viewportFrustum.z,this.viewportFrustum.w)},A.bindViewports=(A,g)=>g()}draw(A){if(this.debugGeomDataBuffer){this.renderGeomDataFbo();const A=this.__renderer.gl;A.viewport(this.region[0],this.region[1],this.region[2],this.region[3]);const g=this.backgroundColorParam.value.asArray();A.clearColor(g[0],g[1],g[2],g[3]);const I=new ColorRenderState(this.__renderer.gl),C=this.__renderer.screenQuad;return C.bindShader(I),void C.draw(I,this.geomDataRenderTarget.textureTargets[0])}const g=this.__renderer.gl;this.bindGLViewport(A),A.pushGLStack("GLViewport.draw"),A.glDisable(g.BLEND),A.glEnable(g.DEPTH_TEST),A.glEnable(g.CULL_FACE),g.viewport(this.region[0],this.region[1],this.region[2],this.region[3]);const I=this.backgroundColorParam.value.asArray();if(g.clearColor(I[0],I[1],I[2],I[3]),g.colorMask(!0,!0,!0,!0),g.clear(g.COLOR_BUFFER_BIT|g.DEPTH_BUFFER_BIT),super.draw(A),A.popGLStack(),this.debugHighlightedGeomsBuffer){const A=new ColorRenderState(this.__renderer.gl),g=this.__renderer.screenQuad;g.bindShader(A),g.draw(A,this.highlightedGeomsBufferFbo.textureTargets[0])}if(this.debugOcclusionBuffer){A.pushGLStack("debugOcclusionBuffer"),g.clear(g.COLOR_BUFFER_BIT|g.DEPTH_BUFFER_BIT);const I=this.__renderer.glGeomItemLibrary.occlusionDataBuffer;A.glEnable(g.BLEND),A.glDisable(g.DEPTH_TEST),g.blendEquation(g.FUNC_ADD),g.blendFuncSeparate(g.SRC_ALPHA,g.ONE_MINUS_SRC_ALPHA,g.ONE,g.ONE);const C=this.__renderer.screenQuad;C.bindShader(A),C.draw(A,I.textureTargets[0]),A.popGLStack()}if(this.debugReductionBuffer){const g=this.__renderer.glGeomItemLibrary.reductionDataBuffer,I=this.__renderer.screenQuad;I.bindShader(A);const C=A.unifs.image;g.bindColorTexture(A,C);const e=this.__renderer.gl;e.uniform1i(A.unifs.isTextured.location,1),e.enable(e.BLEND),e.blendEquation(e.FUNC_ADD),e.blendFuncSeparate(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE),I.draw(A,null),e.disable(e.BLEND)}}}var frag$h="\nprecision highp float;\n#define GLSLIFY 1\n\nuniform sampler2D image;\nuniform vec4 color;\nuniform int isTextured;\n\nvarying vec2 v_texCoord;\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\nvoid main(void) {\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  if (isTextured != 0)\n    fragColor = texture2D(image, v_texCoord);\n  else \n    fragColor = color;\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n",vert$i="\nprecision highp float;\n#define GLSLIFY 1\n\nimport 'quadVertexFromID.glsl'\n\nuniform vec2 pos;\nuniform vec2 size;\n\n/* VS Outputs */\nvarying vec2 v_texCoord;\n \nvoid main()\n{\n  vec2 position = getQuadVertexPositionFromID();\n  v_texCoord = position+0.5;\n  gl_Position = vec4(vec2(-1.0, -1.0) + (pos * 2.0) + (v_texCoord * abs(size) * 2.0), 0.0, 1.0);\n  if (size.x < 0.0)\n    v_texCoord.x = 1.0 - v_texCoord.x;\n  if (size.y < 0.0)\n    v_texCoord.y = 1.0 - v_texCoord.y;\n}\n";class ScreenQuadShader extends GLShader{constructor(A){super(A,"ScreenQuadShader"),this.setShaderStage("VERTEX_SHADER",vert$i),this.setShaderStage("FRAGMENT_SHADER",frag$h)}}class GLScreenQuad{__gl;__pos;__size;__glshader;__quadBinding;ready;constructor(A,g){this.__gl=A,this.__pos=[0,0],this.__size=[1,1],this.__glshader=new ScreenQuadShader(A),A.__quadVertexIdsBuffer||A.setupInstancedQuad();const I=this.__glshader.compileForTarget("GLScreenQuad",g);this.__quadBinding=generateShaderGeomBinding(this.__gl,I.attrs,A.__quadattrbuffers,A.__quadIndexBuffer)}bind(A,g,I,C){const e=A.unifs,i=this.__gl;if(g instanceof GLTexture2D)i.uniform1i(e.isTextured.location,1),g.bindToUniform(A,A.unifs.image);else if(g instanceof WebGLTexture){i.uniform1i(e.isTextured.location,1);const I=A.boundTextures++;i.activeTexture(i.TEXTURE0+I),i.bindTexture(i.TEXTURE_2D,g),i.uniform1i(e.image.location,I)}else g&&g instanceof Color&&(i.uniform1i(e.isTextured.location,0),i.uniform4fv(e.color.location,g.asArray()));{const A=e.pos;if(A){let g=I?I instanceof Vec2?I.asArray():I:this.__pos;i.uniform2fv(A.location,g)}}{const A=e.size;if(A){let g=C?C instanceof Vec2?C.asArray():C:this.__size;i.uniform2fv(A.location,g)}}this.__quadBinding.bind(A)}bindShader(A){return this.__glshader.bind(A,"GLScreenQuad")}draw(A,g,I,C){this.bind(A,g,I,C);const e=this.__gl;e.drawElements(e.TRIANGLES,6,e.UNSIGNED_BYTE,0)}}const gltextureCache=new Map;class ParamUniformBinding extends BaseClass{unif;dirty=!1;constructor(A){super(),this.unif=A}bind(A){}unbind(A){}destroy(){}}class Sampler2DBinding extends ParamUniformBinding{boundImage;textureType;textureTypeUnif;dirty=!1;param;texBinding;gltexture=null;constructor(A,g,I,C,e){super(C);const i=I.getName();this.param=I,this.textureTypeUnif=e[i+"Type"];const t=I=>{let C=gltextureCache.get(I);C||(C="HDR"===I.type?new GLHDRImage(A,I):new GLTexture2D(A,I),gltextureCache.set(I,C)),this.texBinding=C.preBind(this.unif,e),C.on("updated",(()=>{g.emit("updated")})),this.gltexture=C,this.gltexture.addRef(this),this.textureType=1,g.emit("updated")};let o;const a=A=>{A.isLoaded()?t(A):o=A.on("loaded",(()=>{t(this.boundImage)})),this.boundImage=A},B=()=>{gltextureCache.get(this.boundImage).removeRef(this),this.texBinding=null,this.gltexture=null,this.textureType=-1,o&&this.boundImage.off("loaded",o),this.boundImage=null,o=null,g.emit("updated")};I.getImage()&&a(I.getImage()),I.on("textureConnected",(()=>{a(I.getImage())})),I.on("textureDisconnected",(()=>{B()})),this.dirty=!0,I.on("valueChanged",(()=>{this.dirty=!0,g.emit("updated")}))}bind(A){this.gltexture&&this.gltexture.bindToUniform(A,this.unif,this.texBinding)}}class SimpleUniformBinding extends ParamUniformBinding{param;textureUnif;textureTypeUnif;texBinding;gltexture=null;textureType=-1;val;uniform1i;uniformXX;update;constructor(A,g,I,C,e){super(C);const i=I.getName();switch(this.param=I,this.unif=C,this.textureUnif=e[i+"Tex"],this.textureTypeUnif=e[i+"TexType"],this.uniform1i=A.uniform1i.bind(A),this.unif.glslType){case"bool":case"int":this.uniformXX=A.uniform1i.bind(A);break;case"uint":this.uniformXX=A.uniform1ui.bind(A);break;case"float":this.uniformXX=A.uniform1f.bind(A)}this.bind=this.bindValue;const t=I=>{let C=gltextureCache.get(I);C||(C="HDR"===I.type?new GLHDRImage(A,I):new GLTexture2D(A,I),gltextureCache.set(I,C)),this.texBinding=C.preBind(this.textureUnif,e),C.on("updated",(()=>{g.emit("updated")})),this.gltexture=C,this.gltexture.addRef(this),this.textureType=1,this.bind=this.bindTexture,g.emit("updated")};let o,a;if(this.update=()=>{try{o||("boolean"==typeof I.value?this.val=I.value?1:0:this.val=I.value)}catch(A){}g.emit("updated")},this.textureUnif&&I instanceof MaterialFloatParam){const A=A=>{A.isLoaded()?t(A):a=A.on("loaded",(()=>{t(o)})),o=A},C=()=>{gltextureCache.get(o).removeRef(this),this.texBinding=null,this.gltexture=null,this.textureType=-1,this.bind=this.bindValue,a&&o.off("loaded",a),o=null,a=null,g.emit("updated")};I.getImage()&&A(I.getImage()),I.on("textureConnected",(()=>{A(I.getImage())})),I.on("textureDisconnected",(()=>{C()}))}this.dirty=!0,I.on("valueChanged",(()=>{this.dirty=!0,g.emit("updated")}))}bindValue(A){this.dirty&&(this.update(),this.dirty=!1),this.unif&&this.uniformXX(this.unif.location,this.val),this.textureTypeUnif&&this.uniform1i(this.textureTypeUnif.location,0)}bindTexture(A){this.dirty&&(this.update(),this.dirty=!1),this.gltexture.bindToUniform(A,this.textureUnif,this.texBinding)}}class ComplexUniformBinding extends ParamUniformBinding{param;values;uniformXX;constructor(A,g,I,C){switch(super(C),this.param=I,this.unif.glslType){case"vec2":this.uniformXX=A.uniform2fv.bind(A);break;case"vec3":this.uniformXX=A.uniform3fv.bind(A);break;case"vec4":this.uniformXX=A.uniform4fv.bind(A)}this.dirty=!0,I.on("valueChanged",(()=>{this.dirty=!0,g.emit("updated")}))}bind(A){this.dirty&&(this.values=this.param.value.asArray(),this.dirty=!1),this.uniformXX(this.unif.location,this.values)}unbind(){}destroy(){}}class MatrixUniformBinding extends ParamUniformBinding{param;uniformMatrixXXX;values=[];constructor(A,g,I,C){switch(super(C),this.param=I,this.unif.glslType){case"mat3":this.uniformMatrixXXX=A.uniformMatrix3fv.bind(A);break;case"mat4":this.uniformMatrixXXX=A.uniformMatrix4fv.bind(A)}this.dirty=!0,I.on("valueChanged",(()=>{this.dirty=!0,g.emit("updated")}))}bind(A){this.dirty&&(this.values=this.param.value.asArray(),this.dirty=!1),this.uniformMatrixXXX(this.unif.location,!1,this.values)}unbind(){}destroy(){}}class ColorUniformBinding extends ParamUniformBinding{param;textureUnif;textureTypeUnif;values=[];gltexture;textureType;texBinding;uniform1i;uniform4fv;update;constructor(A,g,I,C,e){super(C);const i=I.getName();let t,o;if(this.param=I,this.textureUnif=e[i+"Tex"],this.textureTypeUnif=e[i+"TexType"],this.values=[0,0,0,0],this.bind=this.bindValue,this.update=()=>{try{t||this.unif&&(I instanceof MaterialColorParam&&I.colorSpace==ColorSpace.Gamma?this.values=I.value.toLinear().asArray():this.values=I.value.asArray())}catch(A){}g.emit("updated")},this.textureUnif&&I instanceof MaterialColorParam){const C=I=>{t=I;let C=gltextureCache.get(I);C||(C="FLOAT"===I.type?new GLHDRImage(A,I):new GLTexture2D(A,I),gltextureCache.set(I,C)),this.texBinding=C.preBind(this.textureUnif,e),C.on("updated",(()=>{g.emit("updated")})),this.gltexture=C,this.gltexture.addRef(this),this.textureType=1,this.bind=this.bindTexture,g.emit("updated")},i=A=>{A.isLoaded()?C(A):o=A.once("loaded",(()=>{C(A)}))},a=()=>{this.gltexture.removeRef(this),this.gltexture=null,this.texBinding=null,this.textureType=null,o&&t.off("loaded",o),this.bind=this.bindValue,t=null,o=null,g.emit("updated")};I.getImage()&&i(I.getImage()),I.on("textureConnected",(()=>{i(I.getImage())})),I.on("textureDisconnected",(()=>{a()}))}this.dirty=!0,I.on("valueChanged",(()=>{this.dirty=!0})),this.uniform1i=A.uniform1i.bind(A),this.uniform4fv=A.uniform4fv.bind(A)}bindValue(A){this.unif&&(this.dirty&&(this.update(),this.dirty=!1),this.unif&&this.uniform4fv(this.unif.location,this.values),this.textureTypeUnif&&this.uniform1i(this.textureTypeUnif.location,0))}bindTexture(A){this.dirty&&(this.update(),this.dirty=!1),this.gltexture.bindToUniform(A,this.textureUnif,this.texBinding)}}class MaterialShaderBinding{uniformBindings=[];constructor(A,g,I,C){const e=C=>{const e=C.getName(),i=I[e];if(i)switch(i.glslType){case"bool":case"uint":case"int":case"float":this.uniformBindings.push(new SimpleUniformBinding(A,g,C,i,I));break;case"vec2":case"vec3":case"vec4":this.uniformBindings.push(new ComplexUniformBinding(A,g,C,i));break;case"color":this.uniformBindings.push(new ColorUniformBinding(A,g,C,i,I));break;case"mat4":this.uniformBindings.push(new MatrixUniformBinding(A,g,C,i));break;default:return void console.warn("Param :"+e+" has unhandled data type:"+i.glslType)}else{const i=I[e+"Tex"];i&&"sampler2D"==i.glslType&&(C instanceof MaterialColorParam||C instanceof MaterialFloatParam)&&C.getImage()&&i&&"sampler2D"==i.glslType&&this.uniformBindings.push(new Sampler2DBinding(A,g,C,i,I))}},i=g.material.getParameters();for(const A of i)e(A)}bind(A){for(const g of this.uniformBindings)g.bind(A);return!0}unbind(A){for(const g of this.uniformBindings)g.unbind(A)}destroy(){for(const A of this.uniformBindings)A.destroy()}}class GLMaterial extends EventEmitter{gl;material;glShader;shaderBindings;boundTexturesBeforeMaterial;constructor(A,g,I){super(),this.gl=A,this.material=g,this.glShader=I,this.shaderBindings={},g.on("parameterValueChanged",(()=>this.emit("updated")))}bind(A,g){this.boundTexturesBeforeMaterial=A.boundTextures;let I=this.shaderBindings[A.shaderkey];if(!I){const C=this.gl;I=new MaterialShaderBinding(C,this,A.unifs,g),this.shaderBindings[A.shaderkey]=I}I.bind(A)}unbind(A){A.boundTextures=this.boundTexturesBeforeMaterial}}class GLMaterialLibrary extends EventEmitter{renderer;materials=[];materialBindings=new Map;freeIndices=[];dirtyIndices=new Set;materialsAllocator=new Allocator1D;materialsTexture;constructor(A){super(),this.renderer=A,this.materialsAllocator.on("dataReallocated",(A=>{const g=A.id;this.dirtyIndices.add(g)}))}addMaterial(A){const g=this.materialBindings.get(A);if(null!=g)return g.refCount++,g.index;const I=this.freeIndices.length>0?this.freeIndices.pop():this.materials.length;this.materials[I]=A;const C={},e=A.getShaderClass().getPackedMaterialData(A);this.materialsAllocator.allocate(I,e.length/4);return C.parameterValueChanged=A.on("parameterValueChanged",(()=>{this.dirtyIndices.add(I),this.emit("updated")})),this.materialBindings.set(A,{index:I,refCount:1,listenerIDs:C}),this.dirtyIndices.add(I),I}getGLMaterial(A){this.addMaterial(A);const g=this.materialBindings.get(A);if(g.glMaterial)return g.glMaterial;const I=this.renderer.getOrCreateShader(A.getShaderName()),C=this.renderer.gl,e=new GLMaterial(C,A,I);return g.listenerIDs.updated=e.on("updated",(()=>{this.renderer.requestRedraw()})),g.glMaterial=e,e}getMaterialAllocation(A){const g=this.materialBindings.get(A);if(null!=g)return this.materialsAllocator.getAllocation(g.index)}removeMaterial(A){const g=this.materialBindings.get(A);g.refCount--,g.refCount>0||(this.freeIndices.push(g.index),this.materialsAllocator.deallocate(g.index),this.materials[g.index]=null,this.materialBindings.delete(A),g.listenerIDs.updated&&g.glMaterial&&g.glMaterial.off("updated",g.listenerIDs.updated),g.listenerIDs.parameterValueChanged&&A.off("parameterValueChanged",g.listenerIDs.parameterValueChanged),this.dirtyIndices.has(g.index)&&this.dirtyIndices.delete(g.index))}uploadMaterials(A){const g=this.renderer.__gl,I=MathFunctions.nextPow2(Math.ceil(Math.sqrt(this.materialsAllocator.reservedSpace))),C=A.boundTextures++;if(g.activeTexture(g.TEXTURE0+C),this.materialsTexture){if(this.materialsTexture.width<I){this.materialsTexture.resize(I,I);for(let A=0;A<this.materials.length;A++)this.materialsAllocator.getAllocation(A)&&this.dirtyIndices.add(A)}}else this.materialsTexture=new GLTexture2D(this.renderer.__gl,{format:"RGBA",type:"FLOAT",width:I,height:I,filter:"NEAREST",wrap:"CLAMP_TO_EDGE",mipMapped:!1}),this.materialsTexture.clear();const e=this.materialsTexture,i=this.materialsTexture.width;g.bindTexture(g.TEXTURE_2D,e.glTex),this.dirtyIndices.forEach((A=>{const I=this.materialsAllocator.getAllocation(A),C=this.materials[A],t=C.getShaderClass().getPackedMaterialData(C),o=I.start%i,a=Math.ceil((o+I.size)/i);let B=0,s=I.size,l=o;for(let A=0;A<a;A++){let A;l+s>i?(A=i-l,l=0):A=s;const C=(I.start+B)%i,o=Math.floor((I.start+B)/i),a=t.subarray(4*B,4*(B+A));g.texSubImage2D(g.TEXTURE_2D,0,C,o,A,1,e.format,e.type,a),B+=A,s-=A}})),this.dirtyIndices=new Set,g.bindTexture(g.TEXTURE_2D,null),A.boundTextures--}update(A){this.dirtyIndices.size>0&&this.uploadMaterials(A)}bind(A){if(this.dirtyIndices.size>0&&this.uploadMaterials(A),!this.materialsTexture)return!1;const{materialsTexture:g,materialsTextureSize:I}=A.unifs;if(g&&(this.materialsTexture.bindToUniform(A,g),I)){this.renderer.gl.uniform2i(I.location,this.materialsTexture.width,this.materialsTexture.height)}return!0}}class GLPoints extends GLGeom{constructor(A,g){super(A,g)}draw(A){const g=this.__gl;A.shaderInstancedGeom?g.drawElementsInstanced(g.TRIANGLES,A.shaderInstancedGeom.numTriIndices,A.shaderInstancedGeom.indexDataType,0,this.numVertices):g.drawArrays(g.POINTS,0,this.numVertices)}drawInstanced(A,g){this.__gl.drawArraysInstanced(this.__gl.POINTS,0,this.numVertices,g)}}const convertValue=(A,g)=>A instanceof Int16Array||A instanceof Uint16Array||A instanceof Int16Array||A instanceof Uint16Array?MathFunctions.decode16BitFloat(A[g]):A[g],convertBuffer=(A,g,I)=>{const C=g.values,e=g.count*I.dimension;switch(I.dataType){case A.BYTE:if(C instanceof Int8Array)return C;const i=new Int8Array(e);return C instanceof Float32Array&&C.forEach(((A,C)=>{const e=C%g.dimension+Math.floor(C/g.dimension)*I.dimension;i[e]=MathFunctions.remap(A,-1,1,-127,127)})),i;case A.UNSIGNED_BYTE:{if(C instanceof Uint8Array)return C;const A=new Uint8Array(e);return C instanceof Float32Array&&C.forEach(((C,e)=>{const i=e%g.dimension+Math.floor(e/g.dimension)*I.dimension;A[i]=MathFunctions.remap(C,0,1,0,255)})),A}case A.UNSIGNED_SHORT:{if(C instanceof Uint16Array)return C;const A=new Uint16Array(e);for(let e=0;e<g.count;e++)A.set(C.subarray(e*g.dimension,(e+1)*g.dimension),e*I.dimension);return A}case A.SHORT:{if(C instanceof Int16Array)return C;const A=new Int16Array(e);for(let e=0;e<g.count;e++)A.set(C.subarray(e*g.dimension,(e+1)*g.dimension),e*I.dimension);return A}case A.HALF_FLOAT:if(C instanceof Uint16Array)return C;if(C instanceof Float32Array)return MathFunctions.convertFloat32ArrayToUInt16Array(C);throw"Unable to convert from src data array";case A.FLOAT:{if(C instanceof Float32Array)return C;const A=new Float32Array(e);if(C instanceof Uint16Array)for(let g=0;g<C.length;g++)A[g]=MathFunctions.decode16BitFloat(C[g]);return A}default:throw`Unhandled attribute type: ${I.dataType} for ${C.constructor.name}`}};class GLLines extends GLGeom{numSegIndices=-1;fatBuffersNeedUpload=!0;numFatVertices=-1;fatBuffers=null;indexDataType=0;constructor(A,g){super(A,g)}dirtyBuffers(A){super.dirtyBuffers(A),this.fatBuffersNeedUpload=!0,this.emit("updated")}clearBuffers(){const A=this.__gl;if(A.deleteBuffer(this.indexBuffer),this.indexBuffer=null,this.fatBuffers&&this.fatBuffers.positionsTexture){this.fatBuffers.positionsTexture&&(this.fatBuffers.positionsTexture.destroy(),this.fatBuffers.positionsTexture=null);const g=this.fatBuffers.glattrbuffers.segmentIndices;g.buffer&&(A.deleteBuffer(g.buffer),this.fatBuffers.glattrbuffers.segmentIndices=null)}super.clearBuffers()}genFatBuffers(A){const g=this.__gl,I=this.geom.genBuffers(),C=I.indices,e=I.numVertices!=this.numFatVertices;g.__quadVertexIdsBuffer||g.setupInstancedQuad(),this.fatBuffers||(this.fatBuffers={drawCount:0,positionsTexture:null,glattrbuffers:{}},this.fatBuffers.glattrbuffers.vertexIDs=g.__quadattrbuffers.vertexIDs);const i=A.boundTextures++;g.activeTexture(this.__gl.TEXTURE0+i),this.fatBuffers.drawCount=C.length/2;const t=I.attrBuffers.positions,o=I.attrBuffers.lineThickness,a=new Float32Array(4*t.count);for(let A=0;A<t.count;A++)a[4*A+0]=convertValue(t.values,3*A+0),a[4*A+1]=convertValue(t.values,3*A+1),a[4*A+2]=convertValue(t.values,3*A+2),a[4*A+3]=o?convertValue(o.values,A):1;e&&this.fatBuffers.positionsTexture&&(this.fatBuffers.positionsTexture.destroy(),this.fatBuffers.positionsTexture=null),this.fatBuffers.positionsTexture?this.fatBuffers.positionsTexture.bufferData(a,t.count,1):this.fatBuffers.positionsTexture=new GLTexture2D(this.__gl,{format:"RGBA",type:"FLOAT",width:t.count,height:1,filter:"NEAREST",wrap:"CLAMP_TO_EDGE",data:a,mipMapped:!1});const B=()=>{const A=new Float32Array(C.length);for(let g=0;g<C.length;g++){let I;I=g%2==0?g>0?C[g]==C[g-1]:C[g]==C[C.length-1]:g<C.length-1?C[g]==C[g+1]:C[g]==C[0],A[g]=(I?1:0)+2*C[g]}return A};if(this.fatBuffers.glattrbuffers.segmentIndices)(!this.genBufferOpts||this.genBufferOpts&&this.genBufferOpts.topologyChanged)&&(g.bindBuffer(g.ARRAY_BUFFER,this.fatBuffers.glattrbuffers.segmentIndices.buffer),g.bufferData(g.ARRAY_BUFFER,B(),g.STATIC_DRAW));else{const A=g.createBuffer();g.bindBuffer(g.ARRAY_BUFFER,A),g.bufferData(g.ARRAY_BUFFER,B(),g.STATIC_DRAW),this.fatBuffers.glattrbuffers.segmentIndices={dataType:g.FLOAT,name:"segmentIndices",dimension:2,elementSize:4,normalized:!1,shared:!1,numValues:C.length,buffer:A}}g.bindTexture(g.TEXTURE_2D,null),A.boundTextures--,this.numSegIndices=C.length,this.numFatVertices=I.numVertices,this.fatBuffersNeedUpload=!1}genBuffers(A){super.genBuffers(A);const g=this.__gl,I=this.geom.genBuffers(),C=I.indices;this.numSegIndices!=C.length&&(g.deleteBuffer(this.indexBuffer),this.indexBuffer=g.createBuffer()),g.bindBuffer(g.ELEMENT_ARRAY_BUFFER,this.indexBuffer),g.bufferData(g.ELEMENT_ARRAY_BUFFER,C,g.STATIC_DRAW),this.numSegIndices=C.length,this.numVertices=I.numVertices,C instanceof Uint8Array&&(this.indexDataType=this.__gl.UNSIGNED_BYTE),C instanceof Uint16Array&&(this.indexDataType=this.__gl.UNSIGNED_SHORT),C instanceof Uint32Array&&(this.indexDataType=this.__gl.UNSIGNED_INT)}bind(A){const g=this.__gl,I=A.unifs,{LineThickness:C,geomType:e}=A.unifs;if(e&&this.__gl.uniform1i(e.location,1),C&&g.floatTexturesSupported){this.fatBuffersNeedUpload&&this.genFatBuffers(A);const C=this.fatBuffers;let e=this.shaderBindings[A.shaderkey];return e||(e=generateShaderGeomBinding(this.__gl,A.attrs,C.glattrbuffers,g.__quadIndexBuffer),this.shaderBindings[A.shaderkey]=e),e.bind(A),I.positionsTexture&&(C.positionsTexture.bindToUniform(A,I.positionsTexture),g.uniform1i(I.positionsTextureSize.location,C.positionsTexture.width)),!0}return super.bind(A),!0}drawPoints(){this.__gl.drawArrays(this.__gl.POINTS,0,this.geom.getNumVertices())}draw(A){const g=this.__gl;A.unifs.LineThickness&&g.floatTexturesSupported?g.drawElementsInstanced(g.TRIANGLES,6,g.UNSIGNED_BYTE,0,this.fatBuffers.drawCount):g.drawElements(this.__gl.LINES,this.numSegIndices,this.indexDataType,0)}drawInstanced(A,g){const I=this.__gl,{occluded:C}=A.unifs;C&&I.uniform1i(C.location,0),I.drawElementsInstanced(this.__gl.LINES,this.numSegIndices,this.indexDataType,0,g),C&&(I.uniform1i(C.location,1),I.depthFunc(I.GREATER),I.drawElementsInstanced(this.__gl.LINES,this.numSegIndices,this.indexDataType,0,g),I.depthFunc(I.LEQUAL))}}class GLCompoundGeom extends GLGeom{indexDataType=0;drawCounts={};constructor(A,g){super(A,g)}genBuffers(A){super.genBuffers(A);const g=this.__gl,I=this.geom.genBuffers(),C=I.indices;let e=0;C instanceof Uint8Array?(this.indexDataType=this.__gl.UNSIGNED_BYTE,e=1):C instanceof Uint16Array?(this.indexDataType=this.__gl.UNSIGNED_SHORT,e=2):C instanceof Uint32Array&&(this.indexDataType=this.__gl.UNSIGNED_INT,e=4),this.numVertices=this.geom.getNumVertices(),this.indexBuffer&&g.deleteBuffer(this.indexBuffer),this.indexBuffer=g.createBuffer(),g.bindBuffer(g.ELEMENT_ARRAY_BUFFER,this.indexBuffer),g.bufferData(g.ELEMENT_ARRAY_BUFFER,I.indices,g.STATIC_DRAW),this.updateDrawIds(A,I,e),this.buffersDirty=!1}updateDrawIds(A,g,I){g.materials;g.materialSubGeoms;for(let A in g.counts)if(g.counts[A]>0){const C={geomType:GeomType$2[A],offsets:new Int32Array([g.offsets[A]*I]),counts:new Int32Array([g.counts[A]]),materialIds:new Uint8Array(g.counts.length)};this.drawCounts[A]=C}}updateBuffers(A){if(this.__gl,this.numVertices!=this.geom.getNumVertices())return void this.genBuffers(A);super.updateBuffers(A);let g=0;this.indexDataType==this.__gl.UNSIGNED_BYTE&&(g=1),this.indexDataType==this.__gl.UNSIGNED_SHORT&&(g=2),this.indexDataType==this.__gl.UNSIGNED_INT&&(g=4);const I=this.geom.genBuffers({includeIndices:!1});this.updateDrawIds(A,I,g)}clearBuffers(){this.__gl.deleteBuffer(this.indexBuffer),this.indexBuffer=null,super.clearBuffers()}draw(A){this.drawInstanced(A,1)}drawInstanced(A,g){A.pushGLStack("GLCompoundGeom.drawInstanced");const I=this.__gl,{drawIds:C,geomType:e,outlineThickness:i,viewportSize:t,occluded:o}=A.unifs,a=I.getParameter(I.DEPTH_FUNC);let B=null,s=!1,l=!1;if(A instanceof ColorRenderState){B=A.renderMode;const g="flat-noedges"!=B&&"shaded-noedges"!=B&&"pbr-noedges"!=B;s=i&&t&&"geometry"==A.outlineMethod&&A.outlineThickness>0&&g,l="hiddenline"==B&&null!=o}if(this.drawCounts.TRIANGLES){e&&I.uniform1i(e.location,GeomType$2.TRIANGLES),"hiddenline"==B&&I.colorMask(!1,!1,!1,!1),i&&I.uniform1f(i.location,0);const o=this.drawCounts.TRIANGLES,a=o.counts.map((()=>g));if(I.multiDrawElementsInstanced)I.multiDrawElementsInstanced(I.TRIANGLES,o.counts,0,this.indexDataType,o.offsets,0,a,0,o.counts.length);else for(let A=0;A<o.counts.length;A++)C&&I.uniform2i(C.location,A,o.materialIds[A]),this.__gl.drawElementsInstanced(I.TRIANGLES,o.counts[A],this.indexDataType,o.offsets[A],g);if(s){if(A.pushGLStack("GLCompoundGeom.drawingOutlines"),A.glEnable(I.CULL_FACE),I.cullFace(I.FRONT),I.uniform1f(i.location,A.outlineThickness*window.devicePixelRatio),I.uniform2f(t.location,A.region[2]-A.region[0],A.region[3]-A.region[1]),"hiddenline"==B&&I.colorMask(!0,!0,!0,!0),I.multiDrawElementsInstanced)I.multiDrawElementsInstanced(I.TRIANGLES,o.counts,0,this.indexDataType,o.offsets,0,a,0,o.counts.length);else for(let A=0;A<o.counts.length;A++)C&&I.uniform2i(C.location,A,o.materialIds[A]),this.__gl.drawElementsInstanced(I.TRIANGLES,o.counts[A],this.indexDataType,o.offsets[A],g);A.popGLStack(),I.cullFace(I.BACK)}}if(A instanceof ColorRenderState&&(A.glEnable(I.BLEND),I.blendEquation(I.FUNC_ADD),I.blendFuncSeparate(I.SRC_ALPHA,I.ONE_MINUS_SRC_ALPHA,I.ONE,I.ONE)),this.drawCounts.LINES){e&&I.uniform1i(e.location,GeomType$2.LINES);const i=this.drawCounts.LINES,t=i.counts.map((()=>g));if(I.multiDrawElementsInstanced)I.multiDrawElementsInstanced(I.LINES,i.counts,0,this.indexDataType,i.offsets,0,t,0,i.counts.length);else for(let A=0;A<i.counts.length;A++)C&&I.uniform2i(C.location,A,i.materialIds[A]),I.drawElementsInstanced(I.LINES,i.counts[A],this.indexDataType,i.offsets[A],g);if(l){const{hiddenLineColor:e}=A.unifs;if(I.uniform1i(o.location,1),I.uniform4fv(e.location,A.hiddenLineColor.asArray()),I.depthFunc(I.GREATER),I.depthMask(!1),I.multiDrawElementsInstanced)I.multiDrawElementsInstanced(I.LINES,i.counts,0,this.indexDataType,i.offsets,0,t,0,i.counts.length);else for(let A=0;A<i.counts.length;A++)C&&I.uniform2i(C.location,A,i.materialIds[A]),I.drawElementsInstanced(I.LINES,i.counts[A],this.indexDataType,i.offsets[A],g);I.depthFunc(a),I.depthMask(!0),I.uniform1i(o.location,0)}}if(this.drawCounts.POINTS){e&&I.uniform1i(e.location,GeomType$2.POINTS);const C=this.drawCounts.POINTS,i=C.counts.map((()=>g));if(I.multiDrawElementsInstanced(I.POINTS,C.counts,0,this.indexDataType,C.offsets,0,i,0,C.counts.length),l){const{hiddenLineColor:g}=A.unifs;I.uniform1i(o.location,1),I.uniform4fv(g.location,A.hiddenLineColor.asArray()),I.depthFunc(I.GREATER),I.depthMask(!1),I.multiDrawElementsInstanced(I.POINTS,C.counts,0,this.indexDataType,C.offsets,0,i,0,C.counts.length),I.depthFunc(a),I.depthMask(!0),I.uniform1i(o.location,0)}}A.popGLStack()}destroy(){super.destroy();this.__gl.deleteBuffer(this.indexBuffer),this.indexBuffer=null}}class GLImageAtlas extends GLTexture2D{subImages=[];layoutNeedsRegeneration=!1;asyncCount=0;layout=[];freeIndices=[];atlasLayoutTexture;layoutVec4s=[];constructor(A,g,I){super(A),this.format=g,this.type=I}incAsyncCount(A=1){this.asyncCount+=A}decAsyncCount(){this.asyncCount>0&&(this.asyncCount--,0==this.asyncCount&&this.emit("loaded"))}isLoaded(){return 0==this.asyncCount}get needsUpdate(){return this.layoutNeedsRegeneration}addSubImage(A){const g=this.freeIndices.length?this.freeIndices.pop():this.subImages.length;return A.isLoaded()||(this.incAsyncCount(),A.on("loaded",(()=>{A.getParams(),this.decAsyncCount()}))),A.on("updated",(()=>{this.layoutNeedsRegeneration=!0})),this.subImages[g]=A,this.layoutNeedsRegeneration=!0,g}removeSubImage(A){const g=this.subImages.indexOf(A);this.freeIndices.push(g),this.subImages[g]=null,this.layoutNeedsRegeneration=!0}getSubImage(A){return this.subImages[A]}numSubImages(){return this.layout?this.layout.length:this.subImages.length-this.freeIndices.length}generateAtlasLayout(){if(this.subImages.length-this.freeIndices.length==0)return void(this.layoutNeedsRegeneration=!1);const A=[];this.subImages.forEach(((g,I)=>{g&&A.push({w:g.width+4,h:g.height+4,area:g.width*g.height,index:I})})),A.sort(((A,g)=>A.area>g.area?-1:A.area<g.area?1:0));const g=new GrowingPacker;g.fit(A),this.layout=[],A.forEach((A=>{A.fit?this.layout[A.index]={pos:new Vec2(A.fit.x+2,A.fit.y+2),size:new Vec2(A.w,A.h)}:console.warn("Unable to fit image")}));const I=g.root.w,C=g.root.h,e=this.gl;this.glTex?this.resize(I,C):this.configure({width:I,height:C,format:this.format,type:this.type,filter:e.LINEAR});let i=Math.round(Math.sqrt(1*this.layout.length)+.5);if(i=MathFunctions.nextPow2(i),i%1!=0&&(i+=1-i%1),e.floatTexturesSupported){const A=new Float32Array(i*i*4);this.layout.forEach(((g,e)=>{if(!g)return;const i=A.subarray(4*e,4*(e+1));i[0]=g.pos.x/I,i[1]=g.pos.y/C,i[2]=g.size.x/I,i[3]=g.size.y/C})),this.atlasLayoutTexture&&this.atlasLayoutTexture.width==i&&this.atlasLayoutTexture.height==i?this.atlasLayoutTexture.bufferData(A,i,i):(this.atlasLayoutTexture&&this.atlasLayoutTexture.destroy(),this.atlasLayoutTexture=new GLTexture2D(e,{format:e.RGBA,type:e.FLOAT,filter:e.NEAREST,wrap:e.CLAMP_TO_EDGE,mipMapped:!1,width:i,height:i,data:A}))}else this.layoutVec4s=[],this.layout.forEach(((A,g)=>{A&&(this.layoutVec4s[g]=[A.pos.x/I,A.pos.y/C,A.size.x/I,A.size.y/C])}));this.textureDesc[0]=this.width,this.textureDesc[1]=this.height,this.textureDesc[2]=this.atlasLayoutTexture.width,this.layoutNeedsRegeneration=!1}getLayoutData(A){return this.layoutVec4s[A]}renderAtlas(A=!1,g=0){if(this.subImages.length-this.freeIndices.length==0)return;this.layoutNeedsRegeneration&&this.generateAtlasLayout();const I=this.gl;I.bindTexture(I.TEXTURE_2D,this.glTex);for(let A=g;A<this.subImages.length;A++){const g=this.subImages[A];if(!g)continue;const C=this.layout[A],e=g.getParams().data;I.texSubImage2D(I.TEXTURE_2D,0,C.pos.x,C.pos.y,g.width,g.height,this.format,this.type,e)}A&&this.cleanup(),this.emit("updated")}isReady(){return null!=this.atlasLayoutTexture}bindToUniform(A,g){super.bindToUniform(A,g);const I=A.unifs;if(this.atlasLayoutTexture){const C=I[g.name+"_layout"];C&&this.atlasLayoutTexture.bindToUniform(A,C);const e=I[g.name+"_desc"];e&&this.gl.uniform4fv(e.location,this.textureDesc)}else{const A=I[g.name+"_desc"];A&&this.gl.uniform4f(A.location,0,0,0,0)}return!0}cleanup(){this.subImages=[],this.destroy()}destroy(){this.cleanup(),super.destroy()}}class GLFatPoints extends GLPoints{indexArray=new Int32Array(0);distances=new Float32Array(0);pointsAttributesTexture=null;texelsPerPoint=1;prevSortCameraPos=new Vec3;threshold=0;atlas=null;spriteCoords=null;constructor(A,g){super(A,g)}genBuffers(A){const g=this.__gl,I=this.geom,C=this.geom.genBuffers();this.numVertices=this.geom.getNumVertices(),this.texelsPerPoint=1;const e=C.attrBuffers.positions,i=C.attrBuffers.colors,t=C.attrBuffers.sizes;i&&(this.texelsPerPoint=2);const o=C.attrBuffers.spriteIndices,a=I.getParameter("Sprites");if(o&&a&&a.value.length>0){this.texelsPerPoint=3,this.atlas=new GLImageAtlas(g,g.RGBA,g.UNSIGNED_BYTE);const A=A=>this.emit("updated",A);this.atlas.on("loaded",A),this.atlas.on("updated",A);a.value.forEach((A=>this.atlas.addSubImage(A))),this.atlas.isLoaded()?this.atlas.renderAtlas():this.atlas.on("loaded",(()=>{this.atlas.renderAtlas()}))}const B=MathFunctions.nextPow2(Math.round(Math.sqrt(this.numVertices)+.5)),s=new Float32Array(B*this.texelsPerPoint*B*4),l=4*this.texelsPerPoint;for(let A=0;A<e.count;A++)s[A*l+0]=convertValue(e.values,3*A+0),s[A*l+1]=convertValue(e.values,3*A+1),s[A*l+2]=convertValue(e.values,3*A+2),s[A*l+3]=t?t.values[A]:1,i&&s.set(i.values.subarray(4*A,4*(A+1)),A*l+4),o&&(s[A*l+8]=o.values[A]);const n=B*this.texelsPerPoint,d=B;this.pointsAttributesTexture=new GLTexture2D(g,{format:g.RGBA,type:g.FLOAT,width:n,height:d,data:s,filter:g.NEAREST,wrap:g.CLAMP_TO_EDGE,mipMapped:!1}),this.numVertices=C.numVertices,this.buffersDirty=!1}updateBuffers(A){if(this.numVertices!=this.geom.getNumVertices())return void this.genBuffers(A);const g=this.geom.genBuffers(),I=g.attrBuffers.positions,C=g.attrBuffers.sizes,e=g.attrBuffers.colors,i=g.attrBuffers.spriteIndices,t=MathFunctions.nextPow2(Math.round(Math.sqrt(g.numVertices)+.5)),o=new Float32Array(t*this.texelsPerPoint*t*4),a=4*this.texelsPerPoint;for(let A=0;A<I.count;A++)o[A*a+0]=convertValue(I.values,3*A+0),o[A*a+1]=convertValue(I.values,3*A+1),o[A*a+2]=convertValue(I.values,3*A+2),o[A*a+3]=C?C.values[A]:1,e&&o.set(e.values.subarray(4*A,4*(A+1)),A*a+4),i&&(o[A*a+8]=i.values[A]);const B=t*this.texelsPerPoint,s=t;this.pointsAttributesTexture.populate(o,B,s),this.numVertices=g.numVertices,this.buffersDirty=!1}sort(A){const g=this.geom.positions;this.distances=new Float32Array(g.count);let I=!1;this.indexArray.length!=this.distances.length&&(this.indexArray=new Int32Array(this.distances.length),I=!0);for(let I=0;I<g.count;I++){const C=g.getValue(I);this.distances[I]=C.distanceTo(A),this.indexArray[I]=I}this.indexArray.sort(((A,g)=>this.distances[A]>this.distances[g]?-1:1));const C=this.__gl;this.glattrbuffers.drawIndices?I&&(this.glattrbuffers.drawIndices.buffer&&C.deleteBuffer(this.glattrbuffers.drawIndices.buffer),this.glattrbuffers.drawIndices.buffer=C.createBuffer()):this.glattrbuffers.drawIndices={name:"drawIndices",dimension:1,elementSize:4,buffer:C.createBuffer(),dataType:C.INT,normalized:!1,shared:!1,numValues:g.count},C.bindBuffer(C.ARRAY_BUFFER,this.glattrbuffers.drawIndices.buffer),C.bufferData(C.ARRAY_BUFFER,this.indexArray,C.STATIC_DRAW),this.threshold=0}bind(A){if(this.buffersDirty&&this.updateBuffers(A),A.attrs.drawIndices){const g=A.viewXfo.tr;if(g.distanceTo(this.prevSortCameraPos)>this.threshold)if(this.sort(g),this.prevSortCameraPos=g.clone(),this.distances.length>1){const A=this.indexArray[this.indexArray.length-1],g=this.distances[A];this.threshold=.25*g}else this.threshold=9999}let g=this.shaderBindings[A.shaderkey];if(!g){const I=Object.assign(this.glattrbuffers,A.shaderInstancedGeom.attrBuffers);g=generateShaderGeomBinding(this.__gl,A.attrs,I,A.shaderInstancedGeom.indexBuffer),this.shaderBindings[A.shaderkey]=g}g.bind(A);const{pointsAttributes:I,texelsPerPoint:C,atlasSprites:e}=A.unifs;I&&(this.pointsAttributesTexture.bindToUniform(A,I),this.__gl.uniform1i(C.location,this.texelsPerPoint));const{geomType:i}=A.unifs;return i&&this.__gl.uniform1i(i.location,2),e&&this.atlas&&this.atlas.bindToUniform(A,e),!0}draw(A){const g=this.__gl;A.shaderInstancedGeom?g.drawElementsInstanced(g.TRIANGLES,A.shaderInstancedGeom.numTriIndices,A.shaderInstancedGeom.indexDataType,0,this.numVertices):g.drawArrays(g.POINTS,0,this.numVertices)}}const resizeIntArray=(A,g)=>{const I=new Int32Array(g);return I.set(A),I};class GLGeomLibrary extends EventEmitter{renderer;__gl;freeGeomIndices=[];geoms=[];geomRefCounts=[];geomsDict=new Map;glGeomsDict=new Map;geomBuffersTmp=[];shaderAttrSpec={};glattrbuffers={};shaderBindings={};attributesBufferNeedsRealloc=!1;attributesBufferNeedsAlloc=[];attributesAllocator=new Allocator1D;dirtyGeomIndices=new Set;geomVertexOffsets=new Int32Array(1);geomVertexCounts=new Int32Array(1);numIndices=0;indicesBufferNeedsRealloc=!1;indicesAllocator=new Allocator1D;indicesCounts=new Int32Array(1);indicesOffsets=new Int32Array(1);indexBuffer=null;freeDataAfterUpload=!1;__destroyed=!1;geomEventHandlerIds=[];constructor(A){super(),this.renderer=A,this.__gl=A.gl,this.attributesAllocator.on("resized",(()=>{this.attributesBufferNeedsRealloc=!0})),this.attributesAllocator.on("dataReallocated",(A=>{const g=A.id,I=A.allocation;this.dirtyGeomIndices.add(g),this.geomVertexOffsets[g]=I.start,this.geomVertexCounts[g]=I.size})),this.freeGeomIndices.push(0),this.indicesAllocator.on("resized",(()=>{if(Math.log2(this.indicesAllocator.reservedSpace)>=29){if(Math.log2(this.indicesAllocator.allocatedSpace)>=29)throw"Indices buffer too big. WebGL cannot allocate index buffers more than 2Gb";this.indicesAllocator.reservedSpace=536870911}this.indicesBufferNeedsRealloc=!0})),this.indicesAllocator.on("dataReallocated",(A=>{const g=A.id;this.dirtyGeomIndices.add(g)}));const g=2<<19;this.reserveSpace(g,2*g)}reserveSpace(A,g){this.attributesAllocator.reservedSpace=A,this.indicesAllocator.reservedSpace=g,this.attributesBufferNeedsRealloc=!0,this.indicesBufferNeedsRealloc=!0}constructGLGeom(A){let g=this.glGeomsDict.get(A);if(null!=g)return g;const I=this.__gl;if(A instanceof Mesh||A instanceof MeshProxy)g=new GLMesh(I,A);else if(A instanceof Lines||A instanceof LinesProxy)g=new GLLines(I,A);else if(A instanceof FatPoints)g=new GLFatPoints(I,A);else if(A instanceof Points||A instanceof PointsProxy)g=new GLPoints(I,A);else{if(!(A instanceof CompoundGeom))throw new Error("Unsupported geom type:"+A.constructor.name);g=new GLCompoundGeom(I,A)}return this.glGeomsDict.set(A,g),g.on("updated",(()=>{this.renderer.requestRedraw()})),g.addRef(this),g}addGeom(A){let g=this.geomsDict.get(A);if(null!=g)return this.geomRefCounts[g]++,g;if(0==this.freeGeomIndices.length){const A=this.geomVertexCounts.length,g=2*A;this.geomVertexCounts=resizeIntArray(this.geomVertexCounts,g),this.geomVertexOffsets=resizeIntArray(this.geomVertexOffsets,g),this.indicesCounts=resizeIntArray(this.indicesCounts,g),this.indicesOffsets=resizeIntArray(this.indicesOffsets,g);for(let I=g-1;I>=A;I--)this.freeGeomIndices.push(I)}g=this.freeGeomIndices.pop(),this.geoms[g]=A,this.geomRefCounts[g]=1,this.geomsDict.set(A,g),this.dirtyGeomIndices.add(g),this.geomVertexCounts[g]=0,this.geomVertexOffsets[g]=0,this.indicesCounts[g]=0,this.indicesOffsets[g]=0;const I={};if(I.geomDataChanged=A.on("geomDataChanged",(()=>{this.dirtyGeomIndices.add(g),this.emit("updated")})),I.geomDataTopologyChanged=A.on("geomDataTopologyChanged",(()=>{this.dirtyGeomIndices.add(g),this.emit("updated")})),A instanceof CompoundGeom){const C=this.renderer.glMaterialLibrary;A.materials.forEach((A=>{A&&C.addMaterial(A)})),I.materialsChanged=A.on("materialsChanged",(()=>{A.materials.forEach((A=>{A&&C.addMaterial(A)})),this.emit("geomDataChanged",new IndexEvent(g)),this.emit("updated")}))}return this.geomEventHandlerIds[g]=I,g}removeGeom(A){let g;if(A instanceof BaseGeom||A instanceof BaseProxy?g=this.geomsDict.get(A):(g=A,A=this.geoms[g]),null==g)return void console.warn("geom does not exist in the GLGeomLibrary");if(this.geomRefCounts[g]--,this.geomRefCounts[g]>0)return;this.attributesAllocator.getAllocation(g)&&this.attributesAllocator.deallocate(g),this.indicesAllocator.getAllocation(g)&&this.indicesAllocator.deallocate(g),this.dirtyGeomIndices.has(g)&&this.dirtyGeomIndices.delete(g),this.geomVertexCounts[g]=0,this.geomVertexOffsets[g]=0,this.geoms[g]=null,this.freeGeomIndices.push(g),this.geomsDict.delete(A),delete this.geomBuffersTmp[g],this.indicesCounts[g]=0,this.indicesOffsets[g]=0;const I=this.geomEventHandlerIds[g];A.off("geomDataChanged",I.geomDataChanged),A.off("geomDataTopologyChanged",I.geomDataTopologyChanged),A instanceof CompoundGeom&&A.off("materialsChanged",I.materialsChanged)}getGeom(A){return this.geoms[A]}getGeomOffsetAndCount(A){return[this.indicesOffsets[A],this.indicesCounts[A]]}getGeomBuffers(A){return this.geomBuffersTmp[A]}allocateBuffers(A){const g=this.geoms[A];if(!g)return;const I=g.genBuffers(),C=I.numRenderVerts?I.numRenderVerts:I.numVertices;if(this.geomVertexCounts[A]!=C)if(0==C)this.attributesAllocator.deallocate(A),this.geomVertexOffsets[A]=0,this.geomVertexCounts[A]=0;else{const g=this.attributesAllocator.allocate(A,C);this.geomVertexOffsets[A]=g.start,this.geomVertexCounts[A]=g.size}for(const A in I.attrBuffers)if("textureCoords"!=A&&"texCoords"!=A&&!this.shaderAttrSpec[A]){const g=I.attrBuffers[A];this.shaderAttrSpec[A]=genDataTypeDesc(this.__gl,g.dataType),this.shaderAttrSpec[A].normalized=g.normalized,this.attributesBufferNeedsAlloc.push(A)}if(I.indices){const g=I.indices.length;if(this.indicesCounts[A]!=g)if(0==g)this.indicesAllocator.deallocate(A),this.indicesOffsets[A]=0,this.indicesCounts[A]=0;else{const I=this.indicesAllocator.allocate(A,g),C=4;this.indicesOffsets[A]=I.start*C,this.indicesCounts[A]=I.size}}else this.indicesOffsets[A]=this.geomVertexOffsets[A],this.indicesCounts[A]=this.geomVertexCounts[A];this.geomBuffersTmp[A]=I}genAttributesBuffers(){for(const A in this.shaderAttrSpec)this.genAttributesBuffer(A);this.attributesBufferNeedsAlloc=[]}genAttributesBuffer(A){if("textureCoords"==A||"texCoords"==A)return;const g=this.attributesAllocator.reservedSpace,I=this.__gl;{const C=this.shaderAttrSpec[A],e=g*C.dimension,i=I.createBuffer();I.bindBuffer(I.ARRAY_BUFFER,i);const t=e*C.elementSize;I.bufferData(I.ARRAY_BUFFER,t,I.STATIC_DRAW),this.glattrbuffers[A]&&this.glattrbuffers[A].buffer&&(I.bindBuffer(I.COPY_WRITE_BUFFER,i),I.bindBuffer(I.COPY_READ_BUFFER,this.glattrbuffers[A].buffer),I.copyBufferSubData(I.COPY_READ_BUFFER,I.COPY_WRITE_BUFFER,0,0,this.glattrbuffers[A].numValues*C.elementSize),I.deleteBuffer(this.glattrbuffers[A].buffer)),this.glattrbuffers[A]={name:A,elementSize:C.elementSize,buffer:i,dataType:C.dataType,normalized:C.normalized,numValues:e,dimension:C.dimension,shared:!1}}}genIndicesBuffers(){const A=this.indicesAllocator.reservedSpace;if(this.numIndices!=A){const g=this.__gl,I=g.createBuffer();g.bindBuffer(g.ELEMENT_ARRAY_BUFFER,I);const C=4,e=A*C;g.bufferData(g.ELEMENT_ARRAY_BUFFER,e,g.STATIC_DRAW),this.indexBuffer&&(g.bindBuffer(g.COPY_WRITE_BUFFER,I),g.bindBuffer(g.COPY_READ_BUFFER,this.indexBuffer),g.copyBufferSubData(g.COPY_READ_BUFFER,g.COPY_WRITE_BUFFER,0,0,this.numIndices*C),g.deleteBuffer(this.indexBuffer)),this.indexBuffer=I,this.numIndices=A}}uploadBuffers(A){const g=this.__gl;let I=this.geomBuffersTmp[A];if(!I){const g=this.geoms[A];if(!g)return;I=g.genBuffers(),this.geomBuffersTmp[A]=I}const C=this.geomVertexCounts[A],e=I.numRenderVerts?I.numRenderVerts:I.numVertices;if(C!=e)throw new Error("Invalid allocation for this geom");if(0!=e){for(const C in I.attrBuffers){const e=this.shaderAttrSpec[C],i=I.attrBuffers[C],t=this.glattrbuffers[C];if(!i||!t)continue;g.bindBuffer(g.ARRAY_BUFFER,t.buffer);const o=e.elementSize,a=this.geomVertexOffsets[A]*o*e.dimension,B=convertBuffer(g,i,e);g.bufferSubData(g.ARRAY_BUFFER,a,B)}if(g.bindBuffer(g.ARRAY_BUFFER,null),I.indices&&I.indices.length>0){const g=I.indices,C=this.indicesAllocator.getAllocation(A);if(C.size!=g.length)throw new Error("Invalid allocation for this geom");const e=this.attributesAllocator.getAllocation(A),i=new Uint32Array(C.size);for(let A=0;A<g.length;A++)i[A]=I.indices[A]+e.start;const t=this.__gl;t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer);const o=4,a=C.start*o;t.bufferSubData(t.ELEMENT_ARRAY_BUFFER,a,i),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,null)}if(this.freeDataAfterUpload){this.geoms[A].freeBuffers()}this.emit("geomDataChanged",new IndexEvent(A))}else{const g=new IndexEvent(A);this.emit("geomDataChanged",g)}}cleanGeomBuffers(){this.dirtyGeomIndices.forEach((A=>{this.allocateBuffers(A)})),this.attributesBufferNeedsRealloc||this.indicesBufferNeedsRealloc?(this.resetBindings(),this.attributesBufferNeedsRealloc&&(this.genAttributesBuffers(),this.attributesBufferNeedsRealloc=!1),this.indicesBufferNeedsRealloc&&(this.genIndicesBuffers(),this.indicesBufferNeedsRealloc=!1)):this.attributesBufferNeedsAlloc.length>0&&(this.attributesBufferNeedsAlloc.forEach((A=>{this.genAttributesBuffer(A)})),this.attributesBufferNeedsAlloc=[]),this.dirtyGeomIndices.forEach((A=>{this.uploadBuffers(A)})),this.dirtyGeomIndices=new Set}calcMemoryAllocation(){const A={attrs:{},indices:{}},g=1<<20;for(const I in this.shaderAttrSpec){const C=this.shaderAttrSpec[I],e=this.attributesAllocator.reservedSpace,i=this.attributesAllocator.allocatedSpace,t=e*C.dimension*C.elementSize;A.attrs[I]={count:i,MB:t/g}}const I=this.indicesAllocator.reservedSpace,C=this.indicesAllocator.allocatedSpace,e=4*I;return A.indices={count:C,MB:e/g},A}resetBindings(){for(const A in this.shaderBindings){this.shaderBindings[A].destroy()}this.shaderBindings={}}bind(A){this.dirtyGeomIndices.size>0&&this.cleanGeomBuffers();const g=A.glShader.getId()+A.shaderkey;let I=this.shaderBindings[g];if(I)I.bind(A);else{if(I=generateShaderGeomBinding(this.__gl,A.attrs,this.glattrbuffers,this.indexBuffer),this.shaderBindings[g]=I,"Safari"==SystemDesc.browserName&&"15.4"==SystemDesc.fullVersion){const A=this.__gl;A.drawElements(A.POINTS,1,A.UNSIGNED_INT,0),A.drawElements(A.LINES,2,A.UNSIGNED_INT,0),A.drawElements(A.TRIANGLES,3,A.UNSIGNED_INT,0);const g=new Uint32Array(1),I=4,C=this.indicesAllocator.allocatedSpace*I;A.bufferSubData(A.ELEMENT_ARRAY_BUFFER,C,g)}}return!0}unbind(A){const g=A.glShader.getId()+A.shaderkey,I=this.shaderBindings[g];I&&I.unbind(A)}clearBuffers(){const A=this.__gl;for(const g in this.glattrbuffers){const I=this.glattrbuffers[g];I.shared||A.deleteBuffer(I.buffer)}this.glattrbuffers={},this.indexBuffer&&(A.deleteBuffer(this.indexBuffer),this.indexBuffer=null),this.resetBindings()}destroy(){this.clearBuffers(),this.__destroyed=!0,this.emit("destructing")}}const GLGeomItemChangeType={GEOMITEM_CHANGED:0,GEOM_CHANGED:1,VISIBILITY_CHANGED:2,HIGHLIGHT_CHANGED:3},GLGeomItemFlags={GEOMITEM_FLAG_CUTAWAY:2,GEOMITEM_INVISIBLE_IN_GEOMDATA:4,GEOMITEM_TRANSPARENT:8};class GLGeomItem extends EventEmitter{listenerIDs={};GLGeomItemSet;GLShaderGeomSets;gl;geomItem;geomItemId;geomId;materialId;supportInstancing;visible;shattered=!1;culled=!1;geomMatrixDirty=!1;modelMatrixArray;geomData=[];highlightSubIndex=-1;constructor(A,g,I,C,e,i=!1){if(super(),this.gl=A,this.geomItem=g,this.geomItemId=I,this.geomId=C,this.materialId=e,this.supportInstancing=i,this.visible=this.geomItem.isVisible(),this.listenerIDs.visibilityChanged=this.geomItem.on("visibilityChanged",(A=>{const g=!this.culled&&this.visible;this.visible=A.state;const I=!this.culled&&this.visible;g!=I&&this.emit("visibilityChanged",new StateChangedEvent(I))})),g instanceof CADBody&&(this.shattered=g.shattered),this.listenerIDs.shatterStateChanged=this.geomItem.on("shatterStateChanged",(A=>{this.shattered=A.state,this.emit("shatterStateChanged",A)})),!this.supportInstancing){const A=A=>{if(A.name){const g=A.name,I=g.indexOf(":");let C=[];-1!=I&&(C=g.substring(I+1).split(",").map((A=>Number.parseInt(A))),this.highlightSubIndex=C[0])}else this.highlightSubIndex=-1};this.listenerIDs.highlightChanged=this.geomItem.on("highlightChanged",A)}}isVisible(){return!this.culled&&this.visible}setCulled(A){const g=!this.culled&&this.visible;this.culled=A;const I=!this.culled&&this.visible;g!=I&&this.emit("visibilityChanged",new StateChangedEvent(I))}bind(A){const g=this.gl,{highlightSubIndex:I,geomItemId:C}=A.unifs;return I&&g.uniform1i(I.location,this.highlightSubIndex),C&&g.uniform1i(C.location,this.geomItemId),!0}destroy(){this.geomItem.off("visibilityChanged",this.listenerIDs.visibilityChanged),this.supportInstancing||this.geomItem.off("highlightChanged",this.listenerIDs.highlightChanged)}}class ReductionShader extends GLShader{constructor(A){super(A,"ReductionShader"),this.setShaderStage("VERTEX_SHADER","\n\nprecision highp float;\n\nuniform int reductionTextureWidth;\nuniform sampler2D geomDataTexture;\n\nivec2 texelCoordFromVertexId(){\n  ivec2 texSize = textureSize(geomDataTexture, 0);\n  return ivec2(\n    gl_VertexID % texSize.x, \n    gl_VertexID / texSize.x\n    );\n}\n\nvec2 pointPositionFromGeomItemId(int geomItemId){\n  vec2 result = vec2(\n    (float(geomItemId % reductionTextureWidth) + 0.5) / float(reductionTextureWidth), \n    (float(geomItemId / reductionTextureWidth) + 0.5) / float(reductionTextureWidth)\n    );\n  return vec2(-1.0, -1.0) + (result * 2.0);\n}\n\n/* VS Outputs */\nvarying vec4 v_geomDataPixel;\n\nvoid main()\n{\n  // Get the texel coordinate in the source geomdata buffer.\n  // there is one point for every pixel in the geomdata texture.\n  ivec2 texelCoord = texelCoordFromVertexId();\n  v_geomDataPixel = texelFetch(geomDataTexture, texelCoord, 0);\n  int geomItemId = int(v_geomDataPixel.r + 0.5);\n\n  if (geomItemId > 0) {\n    vec2 position = pointPositionFromGeomItemId(geomItemId);\n    gl_Position = vec4(position, 0.0, 1.0);\n    gl_PointSize = 1.0;\n  } else {\n    // Move it off screen\n    gl_Position = vec4(-2.0, -2.0, 0.0, 1.0);\n    gl_PointSize = 0.0;\n  }\n}\n\n"),this.setShaderStage("FRAGMENT_SHADER","\nprecision highp float;\n\n\n/* VS Outputs */\nvarying vec4 v_geomDataPixel;\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\n\nvoid main(void) {\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  fragColor.r = 1.0/255.0;\n\n  // Note: the green channel in the histogram image indicates if the source\n  // pixel contained a real geom or a bounding box.\n  fragColor.g = v_geomDataPixel.g;\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n\n")}}var frag$g="\nprecision highp float;\n#define GLSLIFY 1\n\n/* VS Outputs */\nvarying vec4 v_color;\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\nvoid main(void) {\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  int drawItemId = int(v_color.g);\n  fragColor = v_color;\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n",vert$h="\nprecision highp float;\n#define GLSLIFY 1\n\nattribute vec4 positions;\n\nuniform mat4 viewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 cameraMatrix;\n\nuniform highp int occlusionCulling;\nuniform sampler2D reductionDataTexture;\n\nimport 'transpose.glsl'\nimport 'GLSLUtils.glsl'\nimport 'stack-gl/transpose.glsl'\nimport 'stack-gl/inverse.glsl'\nimport 'geomItemId.glsl'\nimport 'drawItemTexture.glsl'\nimport 'modelMatrix.glsl'\n\nconst int GEOMITEM_INVISIBLE_IN_GEOMDATA = 2; // 1<<1;\n\n/* VS Outputs */\nvarying vec4 v_color;\n\nvoid main(void) {\n\n  int drawItemId = getGeomItemId();\n  vec4 geomItemData  = getInstanceData(drawItemId);\n  int flags = int(geomItemData.r + 0.5);\n\n  if (occlusionCulling != 0) {\n    // Check if in the reduction texture, this item is already flagged as visible.\n    // Note: we only draw bboxes for those that have been flagged as invisible, but might\n    // be just off screen, or onscreen, but were culled in the previous update.\n    float isVisible = fetchTexel(reductionDataTexture, textureSize(reductionDataTexture, 0), drawItemId).r;\n    if (isVisible > 0.0) {\n      return;\n    }\n  }\n\n  vec4 bboxMin = fetchTexel(instancesTexture, instancesTextureSize, (drawItemId * pixelsPerItem) + 6);\n  vec4 bboxMax = fetchTexel(instancesTexture, instancesTextureSize, (drawItemId * pixelsPerItem) + 7);\n  mat4 viewProjectionMatrix = projectionMatrix * viewMatrix;\n\n  if (occlusionCulling != 0) {\n    // Note: write the drawItemId to the red channel.\n    // this aligns with src\\Renderer\\Shaders\\GLSL\\surfaceGeomData.glsl:39\n    // The ReductionShader reads the drawItemId from the red channel, and if the texel\n    // contained a bbox from the green channel. (in this case, it does not)\n    // Note: the alpha value is simply so we can debug the buffer over the top of the viewport.\n    v_color = vec4(float(drawItemId), 0.0, 0.0, 1.0);\n  } else {\n    v_color = fetchTexel(instancesTexture, instancesTextureSize, (drawItemId * pixelsPerItem) + 4);\n  }\n\n  vec4 pos = positions;\n  if (pos.x < 0.0) pos.x = bboxMin.x;\n  else if (pos.x > 0.0) pos.x = bboxMax.x;\n  if (pos.y < 0.0) pos.y = bboxMin.y;\n  else if (pos.y > 0.0) pos.y = bboxMax.y;\n  if (pos.z < 0.0) pos.z = bboxMin.z;\n  else if (pos.z > 0.0) pos.z = bboxMax.z;\n\n  gl_Position = viewProjectionMatrix * pos;\n}\n";class BoundingBoxShader extends GLShader{constructor(A){super(A,"BoundingBoxShader"),this.setShaderStage("VERTEX_SHADER",vert$h),this.setShaderStage("FRAGMENT_SHADER",frag$g)}}var WorkerFactory=createBase64WorkerFactory("Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwp2YXIgd29ya2VyX2NvZGUgPSAoZnVuY3Rpb24gKGV4cG9ydHMpIHsKICAndXNlIHN0cmljdCc7CgogIC8qIGVzbGludC1kaXNhYmxlIGNhbWVsY2FzZSAqLw0KICBjb25zdCB2ZWMzX3N1YnRyYWN0ID0gKHZlYzEsIHZlYzIpID0+IHsNCiAgICByZXR1cm4gW3ZlYzFbMF0gLSB2ZWMyWzBdLCB2ZWMxWzFdIC0gdmVjMlsxXSwgdmVjMVsyXSAtIHZlYzJbMl1dDQogIH07DQogIGNvbnN0IHZlYzNfbGVuZ3RoID0gKHZlYykgPT4gew0KICAgIHJldHVybiBNYXRoLnNxcnQodmVjWzBdICogdmVjWzBdICsgdmVjWzFdICogdmVjWzFdICsgdmVjWzJdICogdmVjWzJdKQ0KICB9Ow0KICBjb25zdCB2ZWMyX3NjYWxlID0gKHZlYywgc2NsKSA9PiB7DQogICAgcmV0dXJuIFt2ZWNbMF0gKiBzY2wsIHZlY1sxXSAqIHNjbF0NCiAgfTsNCiAgY29uc3QgdmVjMl9sZW5ndGggPSAodmVjKSA9PiB7DQogICAgcmV0dXJuIE1hdGguc3FydCh2ZWNbMF0gKiB2ZWNbMF0gKyB2ZWNbMV0gKiB2ZWNbMV0pDQogIH07DQoNCiAgY29uc3QgcXVhdF9jb25qdWdhdGUgPSAocXVhdCkgPT4gew0KICAgIHJldHVybiBbLXF1YXRbMF0sIC1xdWF0WzFdLCAtcXVhdFsyXSwgcXVhdFszXV0NCiAgfTsNCiAgY29uc3QgcXVhdF9tdWx0aXBseSA9IChxdWF0MSwgcXVhdDIpID0+IHsNCiAgICBjb25zdCBheCA9IHF1YXQxWzBdOw0KICAgIGNvbnN0IGF5ID0gcXVhdDFbMV07DQogICAgY29uc3QgYXogPSBxdWF0MVsyXTsNCiAgICBjb25zdCBhdyA9IHF1YXQxWzNdOw0KICAgIGNvbnN0IGJ4ID0gcXVhdDJbMF07DQogICAgY29uc3QgYnkgPSBxdWF0MlsxXTsNCiAgICBjb25zdCBieiA9IHF1YXQyWzJdOw0KICAgIGNvbnN0IGJ3ID0gcXVhdDJbM107DQoNCiAgICByZXR1cm4gWw0KICAgICAgYXggKiBidyArIGF3ICogYnggKyBheSAqIGJ6IC0gYXogKiBieSwNCiAgICAgIGF5ICogYncgKyBhdyAqIGJ5ICsgYXogKiBieCAtIGF4ICogYnosDQogICAgICBheiAqIGJ3ICsgYXcgKiBieiArIGF4ICogYnkgLSBheSAqIGJ4LA0KICAgICAgYXcgKiBidyAtIGF4ICogYnggLSBheSAqIGJ5IC0gYXogKiBieiwNCiAgICBdDQogIH07DQogIGNvbnN0IHF1YXRfcm90YXRlVmVjMyA9IChxdWF0LCB2ZWMzKSA9PiB7DQogICAgY29uc3QgdnEgPSBbdmVjM1swXSwgdmVjM1sxXSwgdmVjM1syXSwgMC4wXTsNCiAgICBjb25zdCBwcSA9IHF1YXRfbXVsdGlwbHkocXVhdF9tdWx0aXBseShxdWF0LCB2cSksIHF1YXRfY29uanVnYXRlKHF1YXQpKTsNCiAgICByZXR1cm4gW3BxWzBdLCBwcVsxXSwgcHFbMl1dDQogIH07DQoNCiAgLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCiAgLy8gRnJ1c3R1bSBDdWxsaW5nIGRhdGEuDQogIGxldCBlbmFibGVPY2NsdXNpb25DdWxsaW5nID0gZmFsc2U7DQogIGNvbnN0IGdlb21JdGVtc0RhdGEgPSBbXTsNCiAgY29uc3Qgb3V0T2ZGcnVzdHVtID0gW107DQogIGxldCBmcnVzdHVtQ3VsbGVkQ291bnQgPSAwOw0KICBsZXQgbmV3bHlDdWxsZWQgPSBbXTsNCiAgbGV0IG5ld2x5VW5DdWxsZWQgPSBbXTsNCg0KICBsZXQgdmlzaWJsZUNvdW50ID0gMDsNCiAgY29uc3QgdG90YWxHZW9tU3RhdHMgPSB7DQogICAgdHJpYW5nbGVzOiAwLA0KICAgIGxpbmVzOiAwLA0KICAgIHBvaW50czogMCwNCiAgfTsNCiAgY29uc3QgdmlzaWJsZUdlb21TdGF0cyA9IHsNCiAgICB0cmlhbmdsZXM6IDAsDQogICAgbGluZXM6IDAsDQogICAgcG9pbnRzOiAwLA0KICB9Ow0KICBjb25zdCBnZW9tU3RhdHNfYWRkVG90YWwgPSAoZ2VvbVN0YXRzKSA9PiB7DQogICAgLy8gY29uc29sZS5sb2coJ2dlb21TdGF0c19hZGQ6JywgZ2VvbVN0YXRzLnRyaWFuZ2xlcywgdmlzaWJsZUdlb21TdGF0cy50cmlhbmdsZXMpDQogICAgdG90YWxHZW9tU3RhdHMudHJpYW5nbGVzICs9IGdlb21TdGF0cy50cmlhbmdsZXM7DQogICAgdG90YWxHZW9tU3RhdHMubGluZXMgKz0gZ2VvbVN0YXRzLmxpbmVzOw0KICAgIHRvdGFsR2VvbVN0YXRzLnBvaW50cyArPSBnZW9tU3RhdHMucG9pbnRzOw0KICB9Ow0KICBjb25zdCBnZW9tU3RhdHNfc3VidHJhY3RUb3RhbCA9IChnZW9tU3RhdHMpID0+IHsNCiAgICAvLyBjb25zb2xlLmxvZygnZ2VvbVN0YXRzX3N1YnRyYWN0OicsIGdlb21TdGF0cy50cmlhbmdsZXMsIHZpc2libGVHZW9tU3RhdHMudHJpYW5nbGVzKQ0KICAgIHRvdGFsR2VvbVN0YXRzLnRyaWFuZ2xlcyAtPSBnZW9tU3RhdHMudHJpYW5nbGVzOw0KICAgIHRvdGFsR2VvbVN0YXRzLmxpbmVzIC09IGdlb21TdGF0cy5saW5lczsNCiAgICB0b3RhbEdlb21TdGF0cy5wb2ludHMgLT0gZ2VvbVN0YXRzLnBvaW50czsNCiAgfTsNCiAgY29uc3QgZ2VvbVN0YXRzX2FkZCA9IChnZW9tU3RhdHMpID0+IHsNCiAgICAvLyBjb25zb2xlLmxvZygnZ2VvbVN0YXRzX2FkZDonLCBnZW9tU3RhdHMudHJpYW5nbGVzLCB2aXNpYmxlR2VvbVN0YXRzLnRyaWFuZ2xlcykNCiAgICB2aXNpYmxlQ291bnQrKzsNCiAgICB2aXNpYmxlR2VvbVN0YXRzLnRyaWFuZ2xlcyArPSBnZW9tU3RhdHMudHJpYW5nbGVzOw0KICAgIHZpc2libGVHZW9tU3RhdHMubGluZXMgKz0gZ2VvbVN0YXRzLmxpbmVzOw0KICAgIHZpc2libGVHZW9tU3RhdHMucG9pbnRzICs9IGdlb21TdGF0cy5wb2ludHM7DQogIH07DQogIGNvbnN0IGdlb21TdGF0c19zdWJ0cmFjdCA9IChnZW9tU3RhdHMpID0+IHsNCiAgICAvLyBjb25zb2xlLmxvZygnZ2VvbVN0YXRzX3N1YnRyYWN0OicsIGdlb21TdGF0cy50cmlhbmdsZXMsIHZpc2libGVHZW9tU3RhdHMudHJpYW5nbGVzKQ0KICAgIHZpc2libGVDb3VudC0tOw0KICAgIHZpc2libGVHZW9tU3RhdHMudHJpYW5nbGVzIC09IGdlb21TdGF0cy50cmlhbmdsZXM7DQogICAgdmlzaWJsZUdlb21TdGF0cy5saW5lcyAtPSBnZW9tU3RhdHMubGluZXM7DQogICAgdmlzaWJsZUdlb21TdGF0cy5wb2ludHMgLT0gZ2VvbVN0YXRzLnBvaW50czsNCiAgfTsNCg0KICBsZXQgY2FtZXJhUG9zOw0KICBsZXQgY2FtZXJhSW52T3JpOw0KICBsZXQgaXNPcnRob2dyYXBoaWMgPSBmYWxzZTsNCiAgbGV0IGZydXN0dW1IZWlnaHQgPSAwOw0KICBsZXQgZnJ1c3R1bVdpZHRoID0gMDsNCiAgbGV0IGZydXN0dW1IYWxmQW5nbGVYID0gMDsNCiAgbGV0IGZydXN0dW1IYWxmQW5nbGVZID0gMDsNCiAgbGV0IHNvbGlkQW5nbGVMaW1pdCA9IDAuMDA0Ow0KICBsZXQgcGxhY2Vob2xkZXJMb2FkVGhyZXNob2xkID0gMjAwOw0KDQogIGNvbnN0IGN1bGwgPSAoaW5kZXgpID0+IHsNCiAgICBpZiAoIW91dE9mRnJ1c3R1bVtpbmRleF0pIHsNCiAgICAgIG91dE9mRnJ1c3R1bVtpbmRleF0gPSB0cnVlOw0KICAgICAgZnJ1c3R1bUN1bGxlZENvdW50Kys7DQogICAgICBuZXdseUN1bGxlZC5wdXNoKGluZGV4KTsNCg0KICAgICAgLy8gV2UgY291bGQgYmUgY3VsbGluZyBzb21ldGhpbmcgdGhhdCB3YXMgYWxyZWFkeQ0KICAgICAgLy8gbm90IHZpc2libGUgaW4gdGhlIG9jY2x1c2lvbiBidWZmZXIuDQogICAgICBpZiAoIWVuYWJsZU9jY2x1c2lvbkN1bGxpbmcgfHwgIW9jY2x1ZGVkW2luZGV4XSkgew0KICAgICAgICBnZW9tU3RhdHNfc3VidHJhY3QoZ2VvbUl0ZW1zRGF0YVtpbmRleF0uZ2VvbVN0YXRzKTsNCiAgICAgIH0NCiAgICB9DQogIH07DQogIGNvbnN0IHVuQ3VsbCA9IChpbmRleCkgPT4gew0KICAgIGlmIChvdXRPZkZydXN0dW1baW5kZXhdKSB7DQogICAgICBvdXRPZkZydXN0dW1baW5kZXhdID0gZmFsc2U7DQogICAgICBmcnVzdHVtQ3VsbGVkQ291bnQtLTsNCiAgICAgIG5ld2x5VW5DdWxsZWQucHVzaChpbmRleCk7DQoNCiAgICAgIC8vIE9jY2x1c2lvbiBjdWxsaW5nIGNhbiBvbmx5IGRldGVybWluZSBpZiBzb21ldGhpbmcgaXMgdmlzaWJsZQ0KICAgICAgLy8gbWVhbmluZyB0aGF0IHdlIGFzc3VtZSBpdCBpcyBub3QsIHVudGlsIGl0IHNob3dzIHVwIGluIHRoZSBvY2NsdXNpb24gYnVmZmVyLg0KICAgICAgLy8gT25jZSBpdCBhcHBlYXJzIGluIHRoZSBvY2NsdXNpb24gYnVmZmVyLCB3ZSBzdGFydCByZW5kZXJpbmcgaXQgYWdhaW4uDQogICAgICAvLyBTbywgd2hlbiBhbiBpdGVtIGNvbWVzIGJhY2sgaW50byB0aGUgZnJ1c3R1bSwgd2Ugc3RhcnQgcmVuZGVyaW5nIGl0cyBiYm94Lg0KICAgICAgLy8gVGhlbiBpZiB0aGUgYmJveCBpcyBzZWVuLCB3ZSB0aGVuIHN0YXJ0IHNob3dpbmcgaXQuDQogICAgICBpZiAoZW5hYmxlT2NjbHVzaW9uQ3VsbGluZyAmJiAhZ2VvbUl0ZW1zRGF0YVtpbmRleF0udHJhbnNwYXJlbnQpIHsNCiAgICAgICAgb2NjbHVkZWRbaW5kZXhdID0gdHJ1ZTsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIGdlb21TdGF0c19hZGQoZ2VvbUl0ZW1zRGF0YVtpbmRleF0uZ2VvbVN0YXRzKTsNCiAgICAgIH0NCiAgICB9DQogIH07DQoNCiAgY29uc3QgY2hlY2tHZW9tSXRlbSA9IChnZW9tSXRlbURhdGEpID0+IHsNCiAgICBpZiAoIWdlb21JdGVtRGF0YSB8fCAhY2FtZXJhUG9zKSByZXR1cm4NCiAgICBpZiAoIWdlb21JdGVtRGF0YS52aXNpYmxlKSB7DQogICAgICByZXR1cm4NCiAgICB9DQoNCiAgICAvLyBTb21lIGl0ZW1zLCBsaWtlIEhhbmRsZXMgYW5kIHRoZSBncmlkLCBvciBvciB0aGUgVlIgY29udHJvbGxlcnMgdGhhdCBzaG91bGQgbm90IGJlIGN1bGxlZC4NCiAgICBpZiAoIWdlb21JdGVtRGF0YS5jdWxsYWJsZSkgew0KICAgICAgdW5DdWxsKGdlb21JdGVtRGF0YS5pZCk7DQogICAgICByZXR1cm4NCiAgICB9DQogICAgY29uc3QgYm91bmRpbmdSYWRpdXMgPSBnZW9tSXRlbURhdGEuYm91bmRpbmdSYWRpdXM7DQoNCiAgICBpZiAoaXNPcnRob2dyYXBoaWMpIHsNCiAgICAgIC8vIEN1bGwgdmVyeSBzbWFsbCBpdGVtcw0KICAgICAgLy8gTm90ZTogd2hlbiBpbiBWUiwgdGhlIEZvViBiZWNvbWVzIHZlcnkgd2lkZSBhbmQgdGhlIHBpeGVsDQogICAgICAvLyBoZWlnaHQgdmFyaWVzLiBJdCBzZWVtcyBtb3JlIGNvbnNpc3RlbnQgdG8ganVzdCB1c2Ugc29saWRBbmdsZQ0KICAgICAgLy8gd2hpY2ggaXMgcmVzb2x1dGlvbiBpbnZhcmlhbnQuDQogICAgICBjb25zdCB2aGVpZ2h0ID0gYm91bmRpbmdSYWRpdXMgLyBmcnVzdHVtSGVpZ2h0Ow0KICAgICAgaWYgKHNvbGlkQW5nbGVMaW1pdCA+IDAgJiYgdmhlaWdodCA8IHNvbGlkQW5nbGVMaW1pdCkgew0KICAgICAgICBjdWxsKGdlb21JdGVtRGF0YS5pZCk7DQogICAgICAgIHJldHVybg0KICAgICAgfQ0KDQogICAgICAvLyBOb3cgd2UgY2hlY2sgaWYgdGhlIGl0ZW0gaXMgd2l0aGluIHRoZSB2aWV3IGZydXN0dW0uDQogICAgICAvLyBXZSBuZWVkIHRoZSBzb2xpZCBhbmdsZSBvZiB0aGUgaXRlbSBmb3IgZWFjaCBheGlzIChYICYgWSkNCiAgICAgIC8vIFRoaXMgaXMgYmVjYXVzZSBhdCB0aGUgY29ybmVycyBvZiB0aGUgc2NyZWVuLCB0aGUgb2JqZWN0IGlzIHNsaWdodGx5DQogICAgICAvLyBmdXJ0aGVyIGF3YXksIHNvIHRoZSBzb2xpZCBhbmdsZSBjYWxjdWxhdGVkIGFib3ZlIGdldHMgc21hbGxlci4NCiAgICAgIC8vIFRoaXMgd2FzIGNhdXNpbmcgaXRlbXMgd2l0aCBiaWcgYm91bmRpbmcgc3BoZXJlcyB0byBiZSBjdWxsZWQgdG9vIGVhcmx5DQogICAgICAvLyBhdCB0aGUgY29ybmVyIG9mIHRoZSBzY3JlZW4uDQogICAgICBjb25zdCB2ZWMgPSB2ZWMzX3N1YnRyYWN0KGdlb21JdGVtRGF0YS5wb3MsIGNhbWVyYVBvcyk7DQogICAgICBjb25zdCB2aWV3UG9zID0gcXVhdF9yb3RhdGVWZWMzKGNhbWVyYUludk9yaSwgdmVjKTsNCiAgICAgIGlmICgNCiAgICAgICAgTWF0aC5hYnModmlld1Bvc1swXSkgLSBib3VuZGluZ1JhZGl1cyA+IGZydXN0dW1XaWR0aCAqIDAuNSB8fA0KICAgICAgICBNYXRoLmFicyh2aWV3UG9zWzFdKSAtIGJvdW5kaW5nUmFkaXVzID4gZnJ1c3R1bUhlaWdodCAqIDAuNQ0KICAgICAgKSB7DQogICAgICAgIGN1bGwoZ2VvbUl0ZW1EYXRhLmlkKTsNCiAgICAgICAgcmV0dXJuDQogICAgICB9DQogICAgfSBlbHNlIHsNCiAgICAgIGNvbnN0IHZlYyA9IHZlYzNfc3VidHJhY3QoZ2VvbUl0ZW1EYXRhLnBvcywgY2FtZXJhUG9zKTsNCiAgICAgIGNvbnN0IGRpc3QgPSB2ZWMzX2xlbmd0aCh2ZWMpOw0KICAgICAgLy8gdW5DdWxsIGl0ZW1zIGNsb3NlIHRvIHRoZSB2aWV3Lg0KICAgICAgaWYgKGRpc3QgPCBib3VuZGluZ1JhZGl1cykgew0KICAgICAgICB1bkN1bGwoZ2VvbUl0ZW1EYXRhLmlkKTsNCiAgICAgICAgcmV0dXJuDQogICAgICB9DQogICAgICAvLyBDdWxsIHZlcnkgc21hbGwgaXRlbXMNCiAgICAgIC8vIE5vdGU6IHdoZW4gaW4gVlIsIHRoZSBGb1YgYmVjb21lcyB2ZXJ5IHdpZGUgYW5kIHRoZSBwaXhlbA0KICAgICAgLy8gaGVpZ2h0IHZhcmllcy4gSXQgc2VlbXMgbW9yZSBjb25zaXN0ZW50IHRvIGp1c3QgdXNlIHNvbGlkQW5nbGUNCiAgICAgIC8vIHdoaWNoIGlzIHJlc29sdXRpb24gaW52YXJpYW50Lg0KICAgICAgY29uc3Qgc29saWRBbmdsZSA9IE1hdGguYXNpbihib3VuZGluZ1JhZGl1cyAvIGRpc3QpOw0KICAgICAgaWYgKHNvbGlkQW5nbGVMaW1pdCA+IDAgJiYgc29saWRBbmdsZSA8IHNvbGlkQW5nbGVMaW1pdCkgew0KICAgICAgICBjdWxsKGdlb21JdGVtRGF0YS5pZCk7DQogICAgICAgIHJldHVybg0KICAgICAgfQ0KDQogICAgICAvLyBOb3cgd2UgY2hlY2sgaWYgdGhlIGl0ZW0gaXMgd2l0aGluIHRoZSB2aWV3IGZydXN0dW0uDQogICAgICAvLyBXZSBuZWVkIHRoZSBzb2xpZCBhbmdsZSBvZiB0aGUgaXRlbSBmb3IgZWFjaCBheGlzIChYICYgWSkNCiAgICAgIC8vIFRoaXMgaXMgYmVjYXVzZSBhdCB0aGUgY29ybmVycyBvZiB0aGUgc2NyZWVuLCB0aGUgb2JqZWN0IGlzIHNsaWdodGx5DQogICAgICAvLyBmdXJ0aGVyIGF3YXksIHNvIHRoZSBzb2xpZCBhbmdsZSBjYWxjdWxhdGVkIGFib3ZlIGdldHMgc21hbGxlci4NCiAgICAgIC8vIFRoaXMgd2FzIGNhdXNpbmcgaXRlbXMgd2l0aCBiaWcgYm91bmRpbmcgc3BoZXJlcyB0byBiZSBjdWxsZWQgdG9vIGVhcmx5DQogICAgICAvLyBhdCB0aGUgY29ybmVyIG9mIHRoZSBzY3JlZW4uDQogICAgICBjb25zdCB2aWV3UG9zID0gcXVhdF9yb3RhdGVWZWMzKGNhbWVyYUludk9yaSwgdmVjKTsNCiAgICAgIGNvbnN0IHZpZXdWZWNYWiA9IFt2aWV3UG9zWzBdLCB2aWV3UG9zWzJdXTsNCiAgICAgIGNvbnN0IHZpZXdWZWNZWiA9IFt2aWV3UG9zWzFdLCB2aWV3UG9zWzJdXTsNCiAgICAgIGNvbnN0IGRpc3RYID0gdmVjMl9sZW5ndGgodmlld1ZlY1haKTsNCiAgICAgIGNvbnN0IGRpc3RZID0gdmVjMl9sZW5ndGgodmlld1ZlY1laKTsNCiAgICAgIGNvbnN0IHNvbGlkQW5nbGVYWiA9IE1hdGguYXNpbihib3VuZGluZ1JhZGl1cyAvIGRpc3RYKTsNCiAgICAgIGNvbnN0IHNvbGlkQW5nbGVZWiA9IE1hdGguYXNpbihib3VuZGluZ1JhZGl1cyAvIGRpc3RZKTsNCiAgICAgIGNvbnN0IHZpZXdWZWNOb3JtWFogPSB2ZWMyX3NjYWxlKHZpZXdWZWNYWiwgMSAvIGRpc3RYKTsNCiAgICAgIGNvbnN0IHZpZXdWZWNOb3JtWVogPSB2ZWMyX3NjYWxlKHZpZXdWZWNZWiwgMSAvIGRpc3RZKTsNCg0KICAgICAgbGV0IHZpZXdBbmdsZTsNCiAgICAgIC8vIElmIGFuIGl0ZW0gaXMgYmVoaW5kIHRoZSB2aWV3ZXINCiAgICAgIGlmICh2aWV3UG9zWzJdID4gMCkgew0KICAgICAgICB2aWV3QW5nbGUgPSBbDQogICAgICAgICAgTWF0aC5QSSAtIE1hdGguYWJzKE1hdGguYXNpbih2aWV3VmVjTm9ybVhaWzBdKSkgLSBzb2xpZEFuZ2xlWFosDQogICAgICAgICAgTWF0aC5QSSAtIE1hdGguYWJzKE1hdGguYXNpbih2aWV3VmVjTm9ybVlaWzBdKSkgLSBzb2xpZEFuZ2xlWVosDQogICAgICAgIF07DQogICAgICB9IGVsc2Ugew0KICAgICAgICB2aWV3QW5nbGUgPSBbDQogICAgICAgICAgTWF0aC5hYnMoTWF0aC5hc2luKHZpZXdWZWNOb3JtWFpbMF0pKSAtIHNvbGlkQW5nbGVYWiwNCiAgICAgICAgICBNYXRoLmFicyhNYXRoLmFzaW4odmlld1ZlY05vcm1ZWlswXSkpIC0gc29saWRBbmdsZVlaLA0KICAgICAgICBdOw0KICAgICAgfQ0KICAgICAgLy8gY29uc29sZS5sb2coZ2VvbUl0ZW1EYXRhLmlkLCAnYW5nbGUgVG8gSXRlbTonLCBmcnVzdHVtSGFsZkFuZ2xlWCwgdmlld0FuZ2xlWzBdLCBmcnVzdHVtSGFsZkFuZ2xlWSwgdmlld0FuZ2xlWzFdKQ0KICAgICAgaWYgKHZpZXdBbmdsZVswXSA+IGZydXN0dW1IYWxmQW5nbGVYIHx8IHZpZXdBbmdsZVsxXSA+IGZydXN0dW1IYWxmQW5nbGVZKSB7DQogICAgICAgIGN1bGwoZ2VvbUl0ZW1EYXRhLmlkKTsNCiAgICAgICAgcmV0dXJuDQogICAgICB9DQogICAgfQ0KDQogICAgdW5DdWxsKGdlb21JdGVtRGF0YS5pZCk7DQogIH07DQoNCiAgY29uc3Qgb25WaWV3UG9ydENoYW5nZWQgPSAoZGF0YSwgcG9zdE1lc3NhZ2UpID0+IHsNCiAgICBpZiAoZGF0YS5pc09ydGhvZ3JhcGhpYykgew0KICAgICAgaXNPcnRob2dyYXBoaWMgPSB0cnVlOw0KICAgICAgZnJ1c3R1bUhlaWdodCA9IGRhdGEuZnJ1c3R1bUhlaWdodDsNCiAgICAgIGZydXN0dW1XaWR0aCA9IGRhdGEuZnJ1c3R1bVdpZHRoOw0KICAgIH0gZWxzZSB7DQogICAgICBpc09ydGhvZ3JhcGhpYyA9IGZhbHNlOw0KICAgICAgZnJ1c3R1bUhhbGZBbmdsZVggPSBkYXRhLmZydXN0dW1IYWxmQW5nbGVYOw0KICAgICAgZnJ1c3R1bUhhbGZBbmdsZVkgPSBkYXRhLmZydXN0dW1IYWxmQW5nbGVZOw0KICAgIH0NCg0KICAgIHNvbGlkQW5nbGVMaW1pdCA9IGRhdGEuc29saWRBbmdsZUxpbWl0Ow0KICAgIGlmIChjYW1lcmFQb3MgJiYgY2FtZXJhSW52T3JpKSB7DQogICAgICBnZW9tSXRlbXNEYXRhLmZvckVhY2goY2hlY2tHZW9tSXRlbSk7DQogICAgICBvbkRvbmVGcnVzdHVtQ3VsbChwb3N0TWVzc2FnZSk7DQogICAgfQ0KICB9Ow0KDQogIGNvbnN0IG9uVmlld0NoYW5nZWQgPSAoZGF0YSwgcG9zdE1lc3NhZ2UpID0+IHsNCiAgICBjYW1lcmFQb3MgPSBkYXRhLmNhbWVyYVBvczsNCiAgICBjYW1lcmFJbnZPcmkgPSBxdWF0X2Nvbmp1Z2F0ZShkYXRhLmNhbWVyYU9yaSk7DQogICAgc29saWRBbmdsZUxpbWl0ID0gZGF0YS5zb2xpZEFuZ2xlTGltaXQ7DQogICAgaWYgKGdlb21JdGVtc0RhdGEubGVuZ3RoID4gMCkgew0KICAgICAgZ2VvbUl0ZW1zRGF0YS5mb3JFYWNoKGNoZWNrR2VvbUl0ZW0pOw0KICAgICAgb25Eb25lRnJ1c3R1bUN1bGwocG9zdE1lc3NhZ2UpOw0KICAgIH0NCiAgfTsNCg0KICBsZXQgaW5GcnVzdHVtRHJhd0lkc0J1ZmZlclBvcHVsYXRlZCA9IGZhbHNlOw0KICBjb25zdCBnZW5lcmF0ZUluRnJ1c3R1bUluZGljZXMgPSAoKSA9PiB7DQogICAgbGV0IG9mZnNldCA9IDA7DQogICAgb3V0T2ZGcnVzdHVtLmZvckVhY2goKHZhbHVlLCBpbmRleCkgPT4gew0KICAgICAgaWYgKGluZGV4ID4gMCAmJiAhdmFsdWUgJiYgZ2VvbUl0ZW1zRGF0YVtpbmRleF0udmlzaWJsZSAmJiAhZ2VvbUl0ZW1zRGF0YVtpbmRleF0udHJhbnNwYXJlbnQpIG9mZnNldCsrOw0KICAgIH0pOw0KICAgIC8vIENyZWF0ZSBhIGZsb2F0IGFycmF5IHRoYXQgY2FuIGJlIHVzZWQgYXMgYW4gaW5zdGFuY2VzDQogICAgLy8gYXR0cmlidXRlIHRvIHBhc3MgaW50byB0aGUgZHJhd2luZyBvZiB0aGUgYm91bmRpbmcgYm94ZXMuDQogICAgY29uc3QgaW5GcnVzdHVtSW5kaWNlcyA9IG5ldyBGbG9hdDMyQXJyYXkob2Zmc2V0KTsNCiAgICBvZmZzZXQgPSAwOw0KICAgIG91dE9mRnJ1c3R1bS5mb3JFYWNoKCh2YWx1ZSwgaW5kZXgpID0+IHsNCiAgICAgIGlmIChpbmRleCA+IDAgJiYgIXZhbHVlICYmIGdlb21JdGVtc0RhdGFbaW5kZXhdLnZpc2libGUgJiYgIWdlb21JdGVtc0RhdGFbaW5kZXhdLnRyYW5zcGFyZW50KSB7DQogICAgICAgIGluRnJ1c3R1bUluZGljZXNbb2Zmc2V0XSA9IGluZGV4Ow0KICAgICAgICBvZmZzZXQrKzsNCiAgICAgIH0NCiAgICB9KTsNCiAgICByZXR1cm4gaW5GcnVzdHVtSW5kaWNlcw0KICB9Ow0KDQogIGNvbnN0IG9uRG9uZUZydXN0dW1DdWxsID0gKHBvc3RNZXNzYWdlKSA9PiB7DQogICAgaWYgKCFlbmFibGVPY2NsdXNpb25DdWxsaW5nKSB7DQogICAgICBjb25zdCBjb3VudEluRnJ1c3R1bSA9IGdlb21JdGVtc0RhdGEubGVuZ3RoIC0gMSAtIGZydXN0dW1DdWxsZWRDb3VudDsNCg0KICAgICAgcG9zdE1lc3NhZ2Uoew0KICAgICAgICB0eXBlOiAnQ3VsbFJlc3VsdHMnLA0KICAgICAgICBuZXdseUN1bGxlZCwNCiAgICAgICAgbmV3bHlVbkN1bGxlZCwNCiAgICAgICAgdmlzaWJsZTogY291bnRJbkZydXN0dW0sDQogICAgICAgIHRvdGFsOiBnZW9tSXRlbXNEYXRhLmxlbmd0aCAtIDEsDQogICAgICAgIHZpc2libGVHZW9tU3RhdHMsDQogICAgICAgIHRvdGFsR2VvbVN0YXRzLA0KICAgICAgfSk7DQogICAgfSBlbHNlIHsNCiAgICAgIC8vIGNvbnNvbGUubG9nKCdGcnVzdHVtQ3VsbFJlc3VsdHM6JywgJ25ld2x5Q3VsbGVkOicsIG5ld2x5Q3VsbGVkLCAnbmV3bHlVbkN1bGxlZDonLCBuZXdseVVuQ3VsbGVkLCBvdXRPZkZydXN0dW0pDQogICAgICAvLyBjb25zdCBjb3VudEluRnJ1c3R1bSA9IGdlb21JdGVtc0RhdGEubGVuZ3RoIC0gMSAtIGZydXN0dW1DdWxsZWRDb3VudA0KDQogICAgICAvLyBpZiAoY291bnRJbkZydXN0dW0gPiAzMDApIHsNCiAgICAgIC8vICAgY29uc29sZS5sb2coJ2NvdW50SW5GcnVzdHVtOicsIGNvdW50SW5GcnVzdHVtKQ0KICAgICAgLy8gfQ0KICAgICAgaWYgKG5ld2x5Q3VsbGVkLmxlbmd0aCA+IDAgfHwgbmV3bHlVbkN1bGxlZC5sZW5ndGggPiAwIHx8ICFpbkZydXN0dW1EcmF3SWRzQnVmZmVyUG9wdWxhdGVkKSB7DQogICAgICAgIGNvbnN0IGluRnJ1c3R1bUluZGljZXMgPSBnZW5lcmF0ZUluRnJ1c3R1bUluZGljZXMoKTsNCg0KICAgICAgICAvLyBXaGVuIG9jY2x1c2lvbiBjdWxsaW5nIGlzIG9uLCB3ZSBvbmx5IHVuY3VsbCBpdGVtcyBhZnRlciB0aGV5DQogICAgICAgIC8vIGFyZSBkZXRlY3RlZCBpbiB0aGUgb2NjbHVzaW9uIGJ1ZmZlci4gVHJhbnNwYXJlbnQgaXRlbXMgYXJlIG5vdA0KICAgICAgICAvLyByZW5kZXJlZCB0byB0aGUgb2NjbHVzaW9uIGJ1ZmZlciwgc28gbXVzdCBiZSB1bmN1bGxlZCBpbW1lZGlhdGVseS4NCiAgICAgICAgY29uc3QgbmV3bHlVbkN1bGxlZF90cmFuc3BhcmVudCA9IFtdOw0KICAgICAgICBuZXdseVVuQ3VsbGVkLmZvckVhY2goKGluZGV4KSA9PiB7DQogICAgICAgICAgaWYgKGluZGV4ID4gMCAmJiBnZW9tSXRlbXNEYXRhW2luZGV4XSAmJiBnZW9tSXRlbXNEYXRhW2luZGV4XS52aXNpYmxlICYmIGdlb21JdGVtc0RhdGFbaW5kZXhdLnRyYW5zcGFyZW50KSB7DQogICAgICAgICAgICBuZXdseVVuQ3VsbGVkX3RyYW5zcGFyZW50LnB1c2goaW5kZXgpOw0KICAgICAgICAgIH0NCiAgICAgICAgfSk7DQogICAgICAgIHBvc3RNZXNzYWdlKA0KICAgICAgICAgIHsNCiAgICAgICAgICAgIHR5cGU6ICdJbkZydXN0dW1JbmRpY2VzJywNCiAgICAgICAgICAgIG5ld2x5Q3VsbGVkLA0KICAgICAgICAgICAgbmV3bHlVbkN1bGxlZDogbmV3bHlVbkN1bGxlZF90cmFuc3BhcmVudCwNCiAgICAgICAgICAgIC8qIFdoZW4gb2NjbHVzaW9uIGN1bGxpbmcgaXMgcnVubmluZyx3ZSBvbmx5IGNvbnNpZGVyDQogICAgICAgICAgICBjdWxsaW5nIGNvbXBsZXRlZCBhZnRlciB0aGUgb2NjbHVzaW9uIGN1bGxpbmcgaXMgZG9uZS4NCiAgICAgICAgICAgIHZpc2libGU6IHZpc2libGVDb3VudCwNCiAgICAgICAgICAgIHRvdGFsOiBnZW9tSXRlbXNEYXRhLmxlbmd0aCAtIDEsDQogICAgICAgICAgICB2aXNpYmxlR2VvbVN0YXRzLA0KICAgICAgICAgICAgdG90YWxHZW9tU3RhdHMsKi8NCiAgICAgICAgICAgIGluRnJ1c3R1bUluZGljZXMsDQogICAgICAgICAgfSwNCiAgICAgICAgICBbaW5GcnVzdHVtSW5kaWNlcy5idWZmZXJdDQogICAgICAgICk7DQogICAgICAgIGluRnJ1c3R1bURyYXdJZHNCdWZmZXJQb3B1bGF0ZWQgPSB0cnVlOw0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgLy8gTm90ZTogdGhlIGluRnJ1c3R1bURyYXdJZHNCdWZmZXIgaXMgYWxyZWFkeSB1cCB0byBkYXRlIHdlIGNhbiBza2lwIHRoaXMuDQogICAgICAgIHBvc3RNZXNzYWdlKHsNCiAgICAgICAgICB0eXBlOiAnSW5GcnVzdHVtSW5kaWNlcycsDQogICAgICAgICAgbmV3bHlDdWxsZWQ6IFtdLA0KICAgICAgICAgIG5ld2x5VW5DdWxsZWQ6IFtdLA0KICAgICAgICAgIHZpc2libGU6IHZpc2libGVDb3VudCwNCiAgICAgICAgICB0b3RhbDogZ2VvbUl0ZW1zRGF0YS5sZW5ndGggLSAxLA0KICAgICAgICAgIHZpc2libGVHZW9tU3RhdHMsDQogICAgICAgICAgdG90YWxHZW9tU3RhdHMsDQogICAgICAgIH0pOw0KICAgICAgfQ0KICAgIH0NCg0KICAgIG5ld2x5Q3VsbGVkID0gW107DQogICAgbmV3bHlVbkN1bGxlZCA9IFtdOw0KICB9Ow0KDQogIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vDQogIC8vIE9jY2x1c2lvbiBDdWxsaW5nIGRhdGEuDQogIGNvbnN0IG9jY2x1ZGVkID0gW107DQogIGNvbnN0IHByb2Nlc3NPY2NsdXNpb25EYXRhID0gKGRhdGEpID0+IHsNCiAgICBjb25zdCByZWR1Y3Rpb25EYXRhQXJyYXkgPSBkYXRhLnJlZHVjdGlvbkRhdGFBcnJheTsgLy8gVWludDhBcnJheQ0KDQogICAgY29uc3QgbmV3bHlDdWxsZWQgPSBbXTsNCiAgICBjb25zdCBuZXdseVVuQ3VsbGVkID0gW107DQogICAgY29uc3QgdmlzaWJsZVBsYWNlaG9sZGVycyA9IFtdOw0KICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVkdWN0aW9uRGF0YUFycmF5Lmxlbmd0aDsgaSArPSAyKSB7DQogICAgICBjb25zdCBpbmRleCA9IGkgLyAyOw0KICAgICAgY29uc3QgdmFsdWUgPSByZWR1Y3Rpb25EYXRhQXJyYXlbaV07DQoNCiAgICAgIGlmIChpbmRleCA9PSAwKSBjb250aW51ZQ0KICAgICAgaWYgKGluZGV4ID49IGdlb21JdGVtc0RhdGEubGVuZ3RoKSB7DQogICAgICAgIGJyZWFrDQogICAgICB9DQoNCiAgICAgIGNvbnN0IGdlb21JdGVtRGF0YSA9IGdlb21JdGVtc0RhdGFbaW5kZXhdOw0KICAgICAgaWYgKCFnZW9tSXRlbURhdGEgfHwgIWdlb21JdGVtRGF0YS5jdWxsYWJsZSB8fCAhZ2VvbUl0ZW1EYXRhLnZpc2libGUgfHwgZ2VvbUl0ZW1EYXRhLnRyYW5zcGFyZW50KSB7DQogICAgICAgIGNvbnRpbnVlDQogICAgICB9DQoNCiAgICAgIGlmIChnZW9tSXRlbURhdGEuaXNQbGFjZWhvbGRlciAmJiB2YWx1ZSA+IHBsYWNlaG9sZGVyTG9hZFRocmVzaG9sZCkgew0KICAgICAgICBjb25zdCBpc05vdEJCb3ggPSByZWR1Y3Rpb25EYXRhQXJyYXlbaSArIDFdID4gMDsNCiAgICAgICAgaWYgKGlzTm90QkJveCkgew0KICAgICAgICAgIHZpc2libGVQbGFjZWhvbGRlcnMucHVzaCh7IGluZGV4LCBjb3VudDogdmFsdWUgfSk7DQogICAgICAgIH0NCiAgICAgIH0NCg0KICAgICAgaWYgKCFvdXRPZkZydXN0dW1baW5kZXhdKSB7DQogICAgICAgIGlmICh2YWx1ZSA9PSAwKSB7DQogICAgICAgICAgLy8gTm90IHRyYW5zcGFyZW50IG9iamVjdCBjYW4gbm90IGJlIG9jY2x1c2lvbiBjdWxsZWQsIGJlY2F1c2Ugd2UgZG8gbm90IHJlbmRlciB0aGVtIHRvIHRoZQ0KICAgICAgICAgIC8vIG9jY2x1c2lvbiBidWZmZXIuIFRoaXMgbWVhbnMgdGhleSBjYW5ub3Qgb2NjbHVkZSwgb3IgYmUgY29uc2lkZXJlZCBvY2NsdWRlZC4NCiAgICAgICAgICBpZiAoIW9jY2x1ZGVkW2luZGV4XSkgew0KICAgICAgICAgICAgb2NjbHVkZWRbaW5kZXhdID0gdHJ1ZTsNCiAgICAgICAgICAgIG5ld2x5Q3VsbGVkLnB1c2goaW5kZXgpOw0KICAgICAgICAgICAgZ2VvbVN0YXRzX3N1YnRyYWN0KGdlb21JdGVtRGF0YS5nZW9tU3RhdHMpOw0KICAgICAgICAgIH0NCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBpZiAob2NjbHVkZWRbaW5kZXhdKSB7DQogICAgICAgICAgICBvY2NsdWRlZFtpbmRleF0gPSBmYWxzZTsNCiAgICAgICAgICAgIG5ld2x5VW5DdWxsZWQucHVzaChpbmRleCk7DQogICAgICAgICAgICBnZW9tU3RhdHNfYWRkKGdlb21JdGVtRGF0YS5nZW9tU3RhdHMpOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgfQ0KICAgIH0NCiAgICAvLyBOb3RlOiBldmVuIGlmIG9jY2x1c2lvbiBjdWxsaW5nIGRpZCBudCBmaWx0ZXIgb3V0IGFueSBtb3JlIGl0ZW1zDQogICAgLy8gd2UgbXVzdCBlbWl0IHRoaXMgbWVzc2FnZSB0byB0aGUgbWFpbnMgd29ya2VyIHNvIGl0IGtub3dzIHRoYXQgY3VsbGluZyBpcyBjb21wbGV0ZWQuDQogICAgcG9zdE1lc3NhZ2Uoew0KICAgICAgdHlwZTogJ0N1bGxSZXN1bHRzJywNCiAgICAgIG5ld2x5Q3VsbGVkLA0KICAgICAgbmV3bHlVbkN1bGxlZCwNCiAgICAgIHZpc2libGU6IHZpc2libGVDb3VudCwNCiAgICAgIHRvdGFsOiBnZW9tSXRlbXNEYXRhLmxlbmd0aCAtIDEsDQogICAgICB2aXNpYmxlR2VvbVN0YXRzLA0KICAgICAgdG90YWxHZW9tU3RhdHMsDQogICAgICB2aXNpYmxlUGxhY2Vob2xkZXJzLA0KICAgIH0pOw0KICB9Ow0KDQogIC8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vDQogIC8vIE1lc3NhZ2luZw0KICBjb25zdCBoYW5kbGVNZXNzYWdlID0gKGRhdGEsIHBvc3RNZXNzYWdlKSA9PiB7DQogICAgaWYgKGRhdGEudHlwZSA9PSAnSW5pdCcpIHsNCiAgICAgIGNvbnNvbGUubG9nKCdJbml0aWFsaXplZCBDdWxsaW5nIFdvcmtlcicpOw0KICAgICAgZW5hYmxlT2NjbHVzaW9uQ3VsbGluZyA9IGRhdGEuZW5hYmxlT2NjbHVzaW9uQ3VsbGluZzsNCiAgICAgIHBsYWNlaG9sZGVyTG9hZFRocmVzaG9sZCA9IGRhdGEucGxhY2Vob2xkZXJMb2FkVGhyZXNob2xkOw0KICAgICAgcG9zdE1lc3NhZ2Uoew0KICAgICAgICB0eXBlOiAnV29ya2VyUmVhZHknLA0KICAgICAgfSk7DQogICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT0gJ1ZpZXdwb3J0Q2hhbmdlZCcpIHsNCiAgICAgIG9uVmlld1BvcnRDaGFuZ2VkKGRhdGEsIHBvc3RNZXNzYWdlKTsNCiAgICB9IGVsc2UgaWYgKGRhdGEudHlwZSA9PSAnVmlld0NoYW5nZWQnKSB7DQogICAgICBvblZpZXdDaGFuZ2VkKGRhdGEsIHBvc3RNZXNzYWdlKTsNCiAgICB9IGVsc2UgaWYgKGRhdGEudHlwZSA9PSAnVXBkYXRlR2VvbUl0ZW1zJykgew0KICAgICAgZGF0YS5yZW1vdmVkSXRlbUluZGljZXMuZm9yRWFjaCgoaW5kZXgpID0+IHsNCiAgICAgICAgY29uc3QgZ2VvbUl0ZW1EYXRhID0gZ2VvbUl0ZW1zRGF0YVtpbmRleF07DQogICAgICAgIGlmIChnZW9tSXRlbURhdGEgJiYgZ2VvbUl0ZW1EYXRhLnZpc2libGUpIHsNCiAgICAgICAgICBnZW9tU3RhdHNfc3VidHJhY3RUb3RhbChnZW9tSXRlbURhdGEuZ2VvbVN0YXRzKTsNCiAgICAgICAgICBpZiAoIWVuYWJsZU9jY2x1c2lvbkN1bGxpbmcgfHwgIW9jY2x1ZGVkW2luZGV4XSkgew0KICAgICAgICAgICAgZ2VvbVN0YXRzX3N1YnRyYWN0KGdlb21JdGVtRGF0YS5nZW9tU3RhdHMpOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICBnZW9tSXRlbXNEYXRhW2luZGV4XSA9IG51bGw7DQogICAgICAgIG91dE9mRnJ1c3R1bVtpbmRleF0gPSB0cnVlOw0KICAgICAgfSk7DQogICAgICBkYXRhLmdlb21JdGVtcy5mb3JFYWNoKChnZW9tSXRlbURhdGEpID0+IHsNCiAgICAgICAgY29uc3QgaW5kZXggPSBnZW9tSXRlbURhdGEuaWQ7DQogICAgICAgIC8vIE5ldyBnZW9tcyBkZWZhdWx0IHRvIGJlaW5nIHVuLWN1bGxlZA0KICAgICAgICAvLyBFeGlzdGluZyBnZW9tcyB0aGF0IG1heSBiZSBjaGFuZ2luZyBzdGF0ZSwgbGlrZSBjaGFuZ2luZw0KICAgICAgICAvLyB2aXNpYmlsaXR5IG9yIHRyYW5zZm9ybWF0aW9ucyBzaG91bGQgc2ltcGx5IHVwZGF0ZS4NCiAgICAgICAgaWYgKCFnZW9tSXRlbXNEYXRhW2luZGV4XSkgew0KICAgICAgICAgIG91dE9mRnJ1c3R1bVtpbmRleF0gPSBmYWxzZTsNCiAgICAgICAgICBpZiAoZ2VvbUl0ZW1EYXRhLnZpc2libGUpIHsNCiAgICAgICAgICAgIGdlb21TdGF0c19hZGRUb3RhbChnZW9tSXRlbURhdGEuZ2VvbVN0YXRzKTsNCiAgICAgICAgICAgIGdlb21TdGF0c19hZGQoZ2VvbUl0ZW1EYXRhLmdlb21TdGF0cyk7DQogICAgICAgICAgfQ0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIC8vIGFyZSBlaXRoZXIgYWRkaW5nIGEgbmV3IGl0ZW0sIG9yIHVuaGlkaW5nIGFuIGV4aXN0aW5nIGl0ZW0uDQogICAgICAgICAgY29uc3QgYmVjb21pbmdWaXNpYmxlID0gIWdlb21JdGVtc0RhdGFbaW5kZXhdLnZpc2libGUgJiYgZ2VvbUl0ZW1EYXRhLnZpc2libGU7DQogICAgICAgICAgY29uc3QgYmVjb21pbmdJblZpc2libGUgPSBnZW9tSXRlbXNEYXRhW2luZGV4XS52aXNpYmxlICYmICFnZW9tSXRlbURhdGEudmlzaWJsZTsNCiAgICAgICAgICBpZiAoYmVjb21pbmdWaXNpYmxlKSB7DQogICAgICAgICAgICBnZW9tU3RhdHNfYWRkVG90YWwoZ2VvbUl0ZW1EYXRhLmdlb21TdGF0cyk7DQogICAgICAgICAgICBvdXRPZkZydXN0dW1baW5kZXhdID0gdHJ1ZTsNCiAgICAgICAgICAgIG9jY2x1ZGVkW2luZGV4XSA9IGZhbHNlOw0KICAgICAgICAgICAgLy8gaWYgKCFvdXRPZkZydXN0dW1baW5kZXhdICYmICFvY2NsdWRlZFtpbmRleF0pIHsNCiAgICAgICAgICAgIC8vICAgZ2VvbVN0YXRzX2FkZChnZW9tSXRlbURhdGEuZ2VvbVN0YXRzKQ0KICAgICAgICAgICAgLy8gfQ0KICAgICAgICAgIH0gZWxzZSBpZiAoYmVjb21pbmdJblZpc2libGUpIHsNCiAgICAgICAgICAgIGdlb21TdGF0c19zdWJ0cmFjdFRvdGFsKGdlb21JdGVtRGF0YS5nZW9tU3RhdHMpOw0KICAgICAgICAgICAgaWYgKCFvdXRPZkZydXN0dW1baW5kZXhdICYmICghZW5hYmxlT2NjbHVzaW9uQ3VsbGluZyB8fCAhb2NjbHVkZWRbaW5kZXhdKSkgew0KICAgICAgICAgICAgICBnZW9tU3RhdHNfc3VidHJhY3QoZ2VvbUl0ZW1EYXRhLmdlb21TdGF0cyk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBvdXRPZkZydXN0dW1baW5kZXhdID0gdHJ1ZTsNCiAgICAgICAgICAgIG9jY2x1ZGVkW2luZGV4XSA9IGZhbHNlOw0KICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICBjb25zdCBiZWNvbWluZ1RyYW5zcGFyZW50ID0gIWdlb21JdGVtc0RhdGFbaW5kZXhdLnRyYW5zcGFyZW50ICYmIGdlb21JdGVtRGF0YS50cmFuc3BhcmVudDsNCiAgICAgICAgICAgIGNvbnN0IGJlY29taW5nT3BhcXVlID0gZ2VvbUl0ZW1zRGF0YVtpbmRleF0udHJhbnNwYXJlbnQgJiYgIWdlb21JdGVtRGF0YS50cmFuc3BhcmVudDsNCiAgICAgICAgICAgIGlmIChiZWNvbWluZ1RyYW5zcGFyZW50KSB7DQogICAgICAgICAgICAgIGlmIChlbmFibGVPY2NsdXNpb25DdWxsaW5nICYmICFvdXRPZkZydXN0dW1baW5kZXhdICYmIG9jY2x1ZGVkW2luZGV4XSkgew0KICAgICAgICAgICAgICAgIC8vIEl0ZW1zIGJlY29taW5nIHRyYW5zcGFyZW50IG11c3QgYmUgdW5jdWxsZWQgaW1tZWRpYXRlbHkuDQogICAgICAgICAgICAgICAgbmV3bHlVbkN1bGxlZC5wdXNoKGluZGV4KTsNCiAgICAgICAgICAgICAgICBnZW9tU3RhdHNfYWRkKGdlb21JdGVtRGF0YS5nZW9tU3RhdHMpOw0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9IGVsc2UgaWYgKGJlY29taW5nT3BhcXVlKSB7DQogICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdCZWNvbWluZyBvcGFxdWU6JywgaW5kZXgpDQogICAgICAgICAgICAgIC8vIEl0ZW1zIGJlY29taW5nIHRyYW5zcGFyZW50IG11c3QgYmUgdW5jdWxsZWQgaW1tZWRpYXRlbHkuDQogICAgICAgICAgICAgIC8vIE9jY2x1c2lvbiBjdWxsaW5nIGNhbiBvbmx5IGRldGVybWluZSBpZiBzb21ldGhpbmcgaXMgdmlzaWJsZQ0KICAgICAgICAgICAgICAvLyBtZWFuaW5nIHRoYXQgd2UgYXNzdW1lIGl0IGlzIG5vdCwgdW50aWwgaXQgc2hvd3MgdXAgaW4gdGhlIG9jY2x1c2lvbiBidWZmZXIuDQogICAgICAgICAgICAgIC8vIE9uY2UgaXQgYXBwZWFycyBpbiB0aGUgb2NjbHVzaW9uIGJ1ZmZlciwgd2Ugc3RhcnQgcmVuZGVyaW5nIGl0IGFnYWluLg0KICAgICAgICAgICAgICAvLyBTbywgd2hlbiBhbiBpdGVtIGNvbWVzIGJhY2sgaW50byB0aGUgZnJ1c3R1bSwgd2Ugc3RhcnQgcmVuZGVyaW5nIGl0cyBiYm94Lg0KICAgICAgICAgICAgICAvLyBUaGVuIGlmIHRoZSBiYm94IGlzIHNlZW4sIHdlIHRoZW4gc3RhcnQgc2hvd2luZyBpdC4NCiAgICAgICAgICAgICAgaWYgKGVuYWJsZU9jY2x1c2lvbkN1bGxpbmcgJiYgIW91dE9mRnJ1c3R1bVtpbmRleF0pIHsNCiAgICAgICAgICAgICAgICBvY2NsdWRlZFtpbmRleF0gPSB0cnVlOw0KICAgICAgICAgICAgICAgIGdlb21TdGF0c19zdWJ0cmFjdChnZW9tSXRlbURhdGEuZ2VvbVN0YXRzKTsNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICBnZW9tSXRlbXNEYXRhW2luZGV4XSA9IGdlb21JdGVtRGF0YTsNCiAgICAgICAgY2hlY2tHZW9tSXRlbShnZW9tSXRlbXNEYXRhW2luZGV4XSk7DQogICAgICB9KTsNCiAgICAgIGluRnJ1c3R1bURyYXdJZHNCdWZmZXJQb3B1bGF0ZWQgPSBmYWxzZTsNCiAgICAgIG9uRG9uZUZydXN0dW1DdWxsKHBvc3RNZXNzYWdlKTsNCiAgICB9IGVsc2UgaWYgKGRhdGEudHlwZSA9PSAnT2NjbHVzaW9uRGF0YScpIHsNCiAgICAgIHByb2Nlc3NPY2NsdXNpb25EYXRhKGRhdGEpOw0KICAgIH0NCiAgfTsNCg0KICBzZWxmLm9ubWVzc2FnZSA9IGZ1bmN0aW9uIChldmVudCkgew0KICAgIGhhbmRsZU1lc3NhZ2UoZXZlbnQuZGF0YSwgc2VsZi5wb3N0TWVzc2FnZSk7DQogIH07CgogIGV4cG9ydHMuaGFuZGxlTWVzc2FnZSA9IGhhbmRsZU1lc3NhZ2U7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7CgogIHJldHVybiBleHBvcnRzOwoKfSkoe30pOwoK",null,!1);const pixelsPerItem$1=8;class AbortController{__abort=!1;abort(){this.__abort=!0}}function clientWaitAsync(A,g,I,C,e){return new Promise(((i,t)=>{const o=setInterval((()=>{if(e.__abort)return clearInterval(o),void i();const C=A.clientWaitSync(g,I,0);if(C==A.WAIT_FAILED)return clearInterval(o),void t();C!=A.TIMEOUT_EXPIRED&&(clearInterval(o),i())}),C)}))}async function getBufferSubDataAsync(A,g,I,C,e,i,t=0,o=0){const a=A.fenceSync(A.SYNC_GPU_COMMANDS_COMPLETE,0);return A.flush(),await clientWaitAsync(A,a,0,10,i),i.__abort||(A.bindBuffer(g,I),A.getBufferSubData(g,C,e,t,o),A.bindBuffer(g,null)),A.deleteSync(a),e}async function readPixelsAsync(A,g,I,C,e,i,t,o,a){const B=A.createBuffer();return A.bindBuffer(A.PIXEL_PACK_BUFFER,B),A.bufferData(A.PIXEL_PACK_BUFFER,o.byteLength,A.STREAM_READ),A.readPixels(g,I,C,e,i,t,0),A.bindBuffer(A.PIXEL_PACK_BUFFER,null),await getBufferSubDataAsync(A,A.PIXEL_PACK_BUFFER,B,0,o,a),A.deleteBuffer(B),o}class BBoxOcclusionLinesCuboid extends Lines{constructor(){super(),this.setNumVertices(8);const A=this.getVertexAttribute("positions");A.setValue(0,new Vec3(.5,-.5,.5)),A.setValue(1,new Vec3(.5,.5,.5)),A.setValue(2,new Vec3(-.5,.5,.5)),A.setValue(3,new Vec3(-.5,-.5,.5)),A.setValue(4,new Vec3(.5,-.5,-.5)),A.setValue(5,new Vec3(.5,.5,-.5)),A.setValue(6,new Vec3(-.5,.5,-.5)),A.setValue(7,new Vec3(-.5,-.5,-.5)),this.setNumSegments(34),this.setSegmentVertexIndices(0,0,1),this.setSegmentVertexIndices(1,0,2),this.setSegmentVertexIndices(2,0,3),this.setSegmentVertexIndices(3,0,4),this.setSegmentVertexIndices(4,0,5),this.setSegmentVertexIndices(5,0,6),this.setSegmentVertexIndices(6,0,7),this.setSegmentVertexIndices(7,1,0),this.setSegmentVertexIndices(8,1,2),this.setSegmentVertexIndices(9,1,3),this.setSegmentVertexIndices(10,1,4),this.setSegmentVertexIndices(11,1,5),this.setSegmentVertexIndices(12,1,6),this.setSegmentVertexIndices(13,1,7),this.setSegmentVertexIndices(14,2,0),this.setSegmentVertexIndices(15,2,1),this.setSegmentVertexIndices(16,2,3),this.setSegmentVertexIndices(17,2,4),this.setSegmentVertexIndices(18,2,5),this.setSegmentVertexIndices(19,2,6),this.setSegmentVertexIndices(20,2,7),this.setSegmentVertexIndices(21,3,1),this.setSegmentVertexIndices(22,3,2),this.setSegmentVertexIndices(23,3,0),this.setSegmentVertexIndices(24,3,4),this.setSegmentVertexIndices(25,3,5),this.setSegmentVertexIndices(26,3,6),this.setSegmentVertexIndices(27,3,7),this.setSegmentVertexIndices(28,4,5),this.setSegmentVertexIndices(29,4,6),this.setSegmentVertexIndices(30,4,7),this.setSegmentVertexIndices(31,5,6),this.setSegmentVertexIndices(32,5,7),this.setSegmentVertexIndices(33,6,7)}}class XRViewport extends GLBaseViewport{projectionMatricesUpdated;tick;stageTreeItem;stageScale;viewXfo=new Xfo;stageXfo=new Xfo;invStageXfo=new Xfo;invStageMatrix=new Mat4;region=[];session=null;refSpace;projectionMatrices=[];viewMatrices=[];cameraMatrices=[];sessionMode="immersive-vr";controllersMap={};controllers=[];controllerPointerDownTime=[];constructor(A,g){super(A),this.clickTime=300,this.doubleClickTime=300,this.sessionMode=g,this.stageTreeItem=new TreeItem("VRStage"),this.stageTreeItem.setVisible(!1),this.__renderer.addTreeItem(this.stageTreeItem);const I=new Xfo;I.ori.setFromAxisAndAngle(new Vec3(1,0,0),.5*Math.PI),this.setXfo(I)}getRenderer(){return this.renderer}getTreeItem(){return this.stageTreeItem}getXfo(){return this.stageXfo}setXfo(A){this.stageXfo=A,this.stageTreeItem.globalXfoParam.value=A,this.invStageXfo=A.inverse(),this.invStageMatrix=this.invStageXfo.toMat4(),this.stageScale=A.sc.x}getControllers(){return this.controllers}isPresenting(){return null!=this.session}startSession(){const A=(g,I)=>{this.session&&(this.session.requestAnimationFrame(A),this.drawXRFrame(I))};this.session.requestAnimationFrame(A)}stopPresenting(){this.session&&this.session.end()}togglePresenting(){this.session?this.stopPresenting():this.startPresenting()}bindCullingViewport(A,g,I){A.viewXfo=this.viewXfo,A.viewScale=1,A.region=this.region,A.cameraMatrix=A.viewXfo.toMat4();const C=A.cameraMatrix.inverse();A.viewport=this;const e=this.__renderer.gl;A.bindRendererUnifs=g=>{const{cameraMatrix:i,viewMatrix:t,projectionMatrix:o,eye:a,isOrthographic:B}=g;i&&e.uniformMatrix4fv(i.location,!1,A.cameraMatrix.asArray()),t&&e.uniformMatrix4fv(t.location,!1,C.asArray()),o&&e.uniformMatrix4fv(o.location,!1,I.asArray()),a&&e.uniform1i(a.location,0),B&&e.uniform1i(B.location,0)},A.bindViewports=(A,g)=>g()}bindXRViewport(A,g){A.viewXfo=this.viewXfo,A.viewScale=1,A.region=this.region,A.cameraMatrix=A.viewXfo.toMat4(),A.viewport=this;const I=this.__renderer.gl;A.bindRendererUnifs=g=>{const{cameraMatrix:C}=g;C&&I.uniformMatrix4fv(C.location,!1,A.cameraMatrix.asArray())},A.bindViewports=(A,C)=>{const{isOrthographic:e}=A;e&&I.uniform1i(e.location,0),g.forEach(((g,e)=>{let i=g.region;I.viewport(i[0],i[1],i[2],i[3]);const{viewMatrix:t,projectionMatrix:o,eye:a}=A;t&&I.uniformMatrix4fv(t.location,!1,g.viewMatrix.asArray()),o&&I.uniformMatrix4fv(o.location,!1,g.projectionMatrix.asArray()),a&&I.uniform1i(a.location,e),C()}))}}}class XRHead{xrvp;treeItem;mat4;localXfo;hmdGeomItem;constructor(A,g){this.xrvp=A,this.treeItem=new TreeItem("XRHead"),g.addChild(this.treeItem),this.mat4=new Mat4,this.localXfo=new Xfo}setVisible(A){if(A&&!this.hmdGeomItem){const A=this.xrvp.getAsset();if(!A)return;const g=A.getChildByName("HMD");if(!g)return;if(this.hmdGeomItem=g.clone({assetItem:A}),this.hmdGeomItem){const A=new Quat;A.setFromAxisAndAngle(new Vec3(0,1,0),Math.PI),this.hmdGeomItem.localXfoParam.value=new Xfo(new Vec3(0,-.035,-.03),A,new Vec3(.001,.001,.001)),this.treeItem.addChild(this.hmdGeomItem,!1)}}this.hmdGeomItem&&(this.hmdGeomItem.visibleParam.value=A)}update(A){this.mat4.fromArray(A.transform.matrix),this.localXfo.setFromMat4(this.mat4),this.treeItem.localXfoParam.value=this.localXfo}getTreeItem(){return this.treeItem}getXfo(){return this.localXfo}}class XRController extends EventEmitter{id;buttonPressed;xrvp;inputSource;pressedButtons=[];treeItem;tipItem;raycastTick=5;raycastArea=.005;raycastDist=.04;pointerRay=new Ray;mat4=new Mat4;xfo=new Xfo;raycastAreaCache=0;raycastDistCache=0;rayCastRenderTargetProjMatrix=new Mat4;tick;hitTested;pointerOverItem;intersectionData;constructor(A,g,I){if(super(),this.xrvp=A,this.inputSource=g,this.id=I,this.buttonPressed=!1,this.inputSource.gamepad.buttons.forEach(((A,g)=>{0!=g&&(this.pressedButtons[g]=A.pressed)})),this.treeItem=new TreeItem("XRController:"+g.handedness+I),!SystemDesc.isMobileDevice&&(this.tipItem=new TreeItem("Tip"),this.tipItem.localXfoParam.value.tr.set(0,-.05,-.13),this.tipItem.localXfoParam.value.ori.setFromAxisAndAngle(new Vec3(1,0,0),.8*Math.PI),this.treeItem.addChild(this.tipItem,!1),A.stageTreeItem.addChild(this.treeItem),"tracked-pointer"==g.targetRayMode)){switch(g.profiles[0]){case"htc-vive":localStorage.setItem("ZeaEngine_XRDevice","Vive");break;case"oculus-touch":case"oculus-touch-v2":case"oculus-touch-v3":localStorage.setItem("ZeaEngine_XRDevice","Oculus")}A.loadHMDResources().then((A=>{if(!A)return;const I=new Xfo;let C;if(I.ori.setFromAxisAndAngle(new Vec3(0,1,0),Math.PI),I.sc.set(.001,.001,.001),"htc-vive"==g.profiles[0])C=A.getChildByName("Controller"),I.tr.set(0,-.035,-.085);else switch(g.handedness){case"left":C=A.getChildByName("LeftController"),I.tr.set(0,-.035,-.085),I.sc.scaleInPlace(.85);break;case"right":C=A.getChildByName("RightController"),I.tr.set(0,-.035,-.085),I.sc.scaleInPlace(.85);break;default:C=A.getChildByName("Controller")}if(C){const g=new CloneContext;g.assetItem=A;const e=C.clone(g);e.localXfoParam.value=I,this.treeItem.addChild(e,!1)}}))}this.tick=0}getHandedness(){return this.inputSource.handedness}getId(){return this.id}getTreeItem(){return this.treeItem}getTipItem(){return this.tipItem}getTipXfo(){return this.tipItem.globalXfoParam.value}isButtonPressed(){return this.buttonPressed}getControllerStageLocalXfo(){return this.xfo}getControllerTipStageLocalXfo(){return this.xfo.multiply(this.tipItem.localXfoParam.value)}updatePose(A,g,I){const C=g.getPose(I.gripSpace,A);if(!C||!C.transform)return;this.mat4.fromArray(C.transform.matrix),this.xfo.setFromMat4(this.mat4),this.treeItem.localXfoParam.value=this.xfo;const e=this.tipItem.globalXfoParam.value;this.pointerRay.start=e.tr,this.pointerRay.dir=e.ori.getZaxis(),this.hitTested=!1;let i=!1;if(this.raycastDist>0&&this.raycastTick>0&&this.tick%this.raycastTick==0){const A=this.getGeomItemAtTip();if(i=!0,null!=A){const g=new XRControllerEvent(this.xrvp,this,0,this.buttonPressed?1:0);g.intersectionData=A,g.pointerRay=this.pointerRay,A.geomItem!=this.pointerOverItem&&(this.pointerOverItem&&(g.leftGeometry=this.pointerOverItem,this.pointerOverItem.onPointerLeave(g),g.propagating&&this.xrvp.emit("pointerLeaveGeom",g)),g.propagating=!0,this.pointerOverItem=A.geomItem,this.pointerOverItem.onPointerEnter(g),g.propagating&&this.xrvp.emit("pointerOverGeom",g)),A.geomItem.onPointerMove(g)}else if(this.pointerOverItem){const A=new XRControllerEvent(this.xrvp,this,0,this.buttonPressed?1:0);A.pointerRay=this.pointerRay,A.leftGeometry=this.pointerOverItem,this.pointerOverItem.onPointerLeave(A),this.pointerOverItem=null}}return this.inputSource.gamepad.buttons.forEach(((A,g)=>{if(0!=g)if(A.pressed&&!this.pressedButtons[g]){this.pressedButtons[g]=!0;const A=new XRControllerEvent(this.xrvp,this,g,1);A.intersectionData=this.getGeomItemAtTip(),A.pointerRay=this.pointerRay,this.emit("buttonPressed",A),i=!0}else if(!A.pressed&&this.pressedButtons[g]){this.pressedButtons[g]=!1;const A=new XRControllerEvent(this.xrvp,this,g,0);this.emit("buttonReleased",A)}})),this.tick++,i}getGeomItemAtTip(){if(this.hitTested)return this.intersectionData;if(this.hitTested=!0,0==this.raycastDist)return null;const A=this.raycastDist*this.xrvp.stageScale,g=this.raycastArea*this.xrvp.stageScale;A==this.raycastDistCache&&g==this.raycastAreaCache||(this.rayCastRenderTargetProjMatrix.setOrthographicMatrix(-.5*g,.5*g,-.5*g,.5*g,0,-A),this.raycastDistCache=A,this.raycastAreaCache=g);const I=this.xrvp.getRenderer(),C=this.tipItem.globalXfoParam.value.clone();return C.sc.set(1,1,1),this.intersectionData=I.raycastWithProjection(C,this.rayCastRenderTargetProjMatrix,this.pointerRay),this.intersectionData}}class VRController extends XRController{}class XRViewManipulator extends BaseTool{enableViewScale=!0;listenerIDs={};controllerTriggersHeld=[];xrvp;vrControllerToolTip;vrControllerToolTipMat;grabPos;stageXfo__GrabStart;grabDir;grabDist;constructor(A){super(),this.xrvp=A,this.vrControllerToolTip=new Cross(.05),this.vrControllerToolTipMat=new Material("VRController Cross","LinesShader"),this.vrControllerToolTipMat.getParameter("BaseColor").value=new Color("#03E3AC")}activateTool(){super.activateTool();const A=A=>{const g=new GeomItem("XRViewManipulatorToolTip",this.vrControllerToolTip,this.vrControllerToolTipMat);g.pickableParam.value=!1,A.getTipItem().removeAllChildren(),A.getTipItem().addChild(g,!1)};for(const g of this.xrvp.getControllers())A(g);this.listenerIDs.controllerAdded=this.xrvp.on("controllerAdded",(g=>{A(g.controller)}))}deactivateTool(){super.deactivateTool();const A=A=>{const g=A.getTipItem().getChildByName("XRViewManipulatorToolTip");A.getTipItem().removeChildByHandle(g)};for(const g of this.xrvp.getControllers())A(g);this.xrvp.off("controllerAdded",this.listenerIDs.controllerAdded)}initMoveStage(){if(1==this.controllerTriggersHeld.length)this.grabPos=this.controllerTriggersHeld[0].getControllerTipStageLocalXfo().tr.clone(),this.stageXfo__GrabStart=this.xrvp.getXfo().clone();else if(2==this.controllerTriggersHeld.length){const A=this.controllerTriggersHeld[0].getControllerTipStageLocalXfo().tr,g=this.controllerTriggersHeld[1].getControllerTipStageLocalXfo().tr;this.grabDir=g.subtract(A),this.grabPos=A.lerp(g,.5),this.grabDir.y=0,this.grabDist=this.grabDir.length(),this.grabDir.scaleInPlace(1/this.grabDist),this.stageXfo__GrabStart=this.xrvp.getXfo().clone()}}onXRControllerButtonDown(A){if(0!=A.button)return;-1==this.controllerTriggersHeld.indexOf(A.controller)&&(this.controllerTriggersHeld.push(A.controller),this.initMoveStage(),A.stopPropagation(),A.setCapture(this))}onXRControllerButtonUp(A){if(0!=A.button)return;const g=this.controllerTriggersHeld.indexOf(A.controller);-1!=g&&(this.controllerTriggersHeld.splice(g,1),this.initMoveStage(),A.stopPropagation(),0==this.controllerTriggersHeld.length&&A.releaseCapture())}onVRControllerDoubleClicked(A){console.log("onVRControllerDoubleClicked:",this.controllerTriggersHeld.length);const g=this.xrvp.getXfo().clone();g.sc.set(1,1,1),this.xrvp.setXfo(g)}onVRPoseChanged(A){if(1==this.controllerTriggersHeld.length){const A=this.controllerTriggersHeld[0].getControllerTipStageLocalXfo().tr,g=new Xfo;g.tr=this.grabPos.subtract(A);const I=this.stageXfo__GrabStart.multiply(g);this.xrvp.setXfo(I)}else if(2==this.controllerTriggersHeld.length){const A=this.controllerTriggersHeld[0].getControllerTipStageLocalXfo().tr,g=this.controllerTriggersHeld[1].getControllerTipStageLocalXfo().tr,I=A.lerp(g,.5),C=g.subtract(A);C.y=0;const e=C.length();if(e<1e-4)return;C.scaleInPlace(1/e);const i=new Xfo;let t=this.grabDir.angleTo(C);this.grabDir.cross(C).y>0&&(t=-t),i.ori.rotateY(t);const o=this.grabPos.subtract(I),a=i.ori.rotateVec3(this.grabPos);if(i.tr.addInPlace(this.grabPos.subtract(a)),this.enableViewScale){const A=Math.max(Math.min(this.grabDist/e,10),.1);i.sc.set(A,A,A);const g=this.grabPos.scale(1-A);i.tr.addInPlace(i.ori.rotateVec3(g)),o.scaleInPlace(A)}i.tr.addInPlace(i.ori.rotateVec3(o));const B=this.stageXfo__GrabStart.multiply(i);this.xrvp.setXfo(B)}}onPointerDown(A){A instanceof XRControllerEvent&&this.onXRControllerButtonDown(A)}onPointerMove(A){A instanceof XRPoseEvent&&this.onVRPoseChanged(A)}onPointerUp(A){A instanceof XRControllerEvent&&this.onXRControllerButtonUp(A)}onPointerDoubleClick(A){A instanceof XRControllerEvent&&this.onVRControllerDoubleClicked(A)}}class VRViewport extends XRViewport{vrAsset;hmd="";hmdAssetPromise;xrhead;constructor(A,g){super(A,g),this.xrhead=new XRHead(this,this.stageTreeItem),this.setManipulator(new XRViewManipulator(this))}getAsset(){return this.vrAsset}getVRHead(){return this.xrhead}getHMDName(){return this.hmd}loadHMDResources(){if(SystemDesc.isMobileDevice)return Promise.resolve(null);let A=localStorage.getItem("ZeaEngine_XRDevice");if(A||(A="Oculus",localStorage.setItem("ZeaEngine_XRDevice",A)),this.hmd!=A)this.hmdAssetPromise=void 0;else if(this.hmdAssetPromise)return this.hmdAssetPromise;return this.hmd=A,this.hmdAssetPromise=new Promise(((g,I)=>{{let I;switch(A){case"Vive":default:I="ZeaEngine/Vive.vla";break;case"Oculus":I="ZeaEngine/Oculus.vla"}if(!resourceLoader.commonResources[I]){const A=new VLAAsset(I);A.load(resourceLoader.systemUrls[I]),resourceLoader.commonResources[I]=A}this.vrAsset=resourceLoader.getCommonResource(I);const C=()=>{const A=this.vrAsset.getMaterialLibrary(),I=A.getMaterialNames();for(const g of I){const I=A.getMaterial(g);I&&I.setShaderName("SimpleSurfaceShader")}this.vrAsset.traverse((A=>{A.pickableParam.value=!1})),g(this.vrAsset)};this.vrAsset.isLoaded()?C():this.vrAsset.once("loaded",C)}})),this.hmdAssetPromise}startPresenting(){return new Promise(((A,g)=>{(()=>{navigator.xr.requestSession("immersive-vr",{requiredFeatures:["local-floor"],optionalFeatures:["bounded-floor"]}).then((I=>{const C=this.__renderer.getViewport();if(C){const A=C.getCamera().globalXfoParam.value,g=new Xfo;g.tr=A.tr.clone(),g.tr.z-=1.3;const I=A.ori.getZaxis();I.z=0,I.normalizeInPlace(),g.ori.setFromDirectionAndUpvector(I,new Vec3(0,0,1)),this.setXfo(g)}I.addEventListener("end",(()=>{this.stageTreeItem.setVisible(!1),this.session=null;const A=this.__renderer.gl;A.bindFramebuffer(A.FRAMEBUFFER,null),this.emit("presentingChanged",new StateChangedEvent(!1))}));const e=A=>{if(this.controllersMap[A.handedness])return void(this.controllersMap[A.handedness].inputSource=A);const g=this.controllers.length;console.log("creating controller:",A.handedness,A.profiles);const I=new XRController(this,A,g);this.controllersMap[A.handedness]=I,this.controllers[g]=I,this.controllerPointerDownTime[g]=[],I.on("buttonPressed",(A=>{this.onPointerDown(A)})),I.on("buttonReleased",(A=>{this.onPointerUp(A)}));const C=new ControllerAddedEvent(I);return this.emit("controllerAdded",C),I};I.addEventListener("selectstart",(A=>{const g=this.controllersMap[A.inputSource.handedness];g&&(g.buttonPressed=!0,this.onPointerDown(new XRControllerEvent(this,g,0,1)))})),I.addEventListener("selectend",(A=>{const g=this.controllersMap[A.inputSource.handedness];g&&(g.buttonPressed=!1,this.onPointerUp(new XRControllerEvent(this,g,0,0)))})),I.addEventListener("inputsourceschange",(A=>{for(const g of A.added)0!=g.profiles.length&&("generic-touchscreen"==g.profiles[0]||e(g))})),this.session=I;const i=new XRWebGLLayer(I,this.__gl);I.updateRenderState({baseLayer:i}),this.width=i.framebufferWidth,this.height=i.framebufferHeight,this.region=[0,0,this.width,this.height],this.depthRange=[I.renderState.depthNear,I.renderState.depthFar],this.resizeRenderTargets(this.width,this.height);const t=g=>{this.refSpace=g,this.stageTreeItem.setVisible(!0),this.emit("presentingChanged",new StateChangedEvent(!0)),this.loadHMDResources().then((()=>{this.startSession(),A()}))};I.requestReferenceSpace("bounded-floor").catch((A=>{console.warn(A.message),console.log("Falling back to local-floor reference space"),I.requestReferenceSpace("local-floor").then(t)})).then((A=>{A&&t(A)})).catch((A=>{console.warn(A.message),g(new Error("Unable to start XR Session:"+A.message))}))})).catch((A=>{console.warn(A.message)}))})()}))}updateControllers(A){let g=!1;const I=this.session.inputSources;for(let C=0;C<I.length;C++){const e=I[C];if(0==e.profiles.length)return;if(!this.controllers[C]){console.warn("Missing controller");continue}const i=this.controllers[C].updatePose(this.refSpace,A,e);g=g||i}return g}drawXRFrame(A){const g=A.session,I=g.renderState.baseLayer,C=A.getViewerPose(this.refSpace);if(!C)return;const e=C.views;if(!this.projectionMatricesUpdated){this.projectionMatrices=[],this.viewMatrices=[],this.cameraMatrices=[];for(let A=0;A<e.length;A++){const g=e[A],I=new Mat4;I.fromArray(g.projectionMatrix),this.projectionMatrices[A]=I,this.viewMatrices[A]=new Mat4,this.cameraMatrices[A]=new Mat4}this.projectionMatricesUpdated=!0}const i=this.__renderer.gl;this.depthRange=[g.renderState.depthNear,g.renderState.depthFar];const t=new ColorRenderState(this.__renderer.gl);t.pushGLStack("VRViewport.drawXRFrame"),t.boundRendertarget=I.framebuffer,t.region=this.region,t.depthRange=this.depthRange,t.viewport=this,t.xrviewport=this;const o=[];for(let A=0;A<e.length;A++){const g=e[A];this.viewMatrices[A].fromArray(g.transform.inverse.matrix),this.viewMatrices[A].multiplyInPlace(this.invStageMatrix);const C=I.getViewport(g);o.push({viewMatrix:this.viewMatrices[A],projectionMatrix:this.projectionMatrices[A],region:[C.x,C.y,C.width,C.height],isOrthographic:0})}this.xrhead.update(C);const a=this.xrhead.getTreeItem().globalXfoParam.value,B=a.toMat4();this.viewXfo=a,t.viewXfo=a,t.cameraMatrix=B,t.viewScale=this.stageScale,t.region=this.region,t.vrPresenting=!0,this.updateControllers(A);const s=new XRPoseEvent(this,this.viewXfo,this.controllers);s.getCapture()&&s.getCapture().onPointerMove(s),this.manipulator&&s.propagating&&this.manipulator.onPointerMove(s),this.bindXRViewport(t,o),i.bindFramebuffer(i.DRAW_FRAMEBUFFER,t.boundRendertarget);let l=this.backgroundColorParam.value.asArray();i.clearColor(l[0],l[1],l[2],l[3]),i.colorMask(!0,!0,!0,!0),i.clear(i.COLOR_BUFFER_BIT|i.DEPTH_BUFFER_BIT),this.draw(t),t.popGLStack(),0!=t.stack.length&&console.warn(" corrupt renderstate.stack.length:",t.stack.length);const n=new XRViewChangedEvent(t.viewXfo);n.hmd=this.hmd,n.controllers=this.controllers,n.viewport=this,n.xrviewport=this,this.emit("viewChanged",n),this.tick++}onPointerDown(A){A.intersectionData=A.controller.getGeomItemAtTip(),A.pointerRay=A.controller.pointerRay;const g=Date.now();if(g-this.controllerPointerDownTime[A.controller.id][A.button]<this.doubleClickTime){if(this.emit("pointerDoubleClick",A),!A.propagating)return;if(this.manipulator&&(this.manipulator.onPointerDoubleClick(A),!A.propagating))return}this.controllerPointerDownTime[A.controller.id][A.button]=g,A.getCapture()&&(A.getCapture().onPointerDown(A),!A.propagating)||(null==A.intersectionData||(A.intersectionData.geomItem.onPointerDown(A),A.propagating))&&(this.emit("pointerDown",A),A.propagating&&this.manipulator&&this.manipulator.onPointerDown(A))}onPointerUp(A){A.pointerRay=A.controller.pointerRay,A.intersectionData=A.controller.getGeomItemAtTip(),A.getCapture()&&A.getCapture().onPointerUp(A),A.propagating&&null!=A.intersectionData&&A.intersectionData.geomItem.onPointerUp(A),A.propagating&&this.emit("pointerUp",A),A.propagating&&this.manipulator&&this.manipulator.onPointerUp(A);const g=this.controllerPointerDownTime[A.controller.id][A.button];Date.now()-g<this.clickTime&&(A.propagating=!0,null!=A.intersectionData&&A.intersectionData.geomItem.onPointerClick(A),A.propagating&&this.emit("pointerClick",A),A.propagating&&this.manipulator&&this.manipulator.onPointerClick(A)),this.controllerPointerDownTime[A.controller.id][A.button]=0}}class ARViewport extends XRViewport{stageXfoSet=!1;xrViewerSpace;xrHitTestSource;reticle;constructor(A,g){super(A,g);const I=new Disc(.1,24),C=new FlatSurfaceMaterial("reticle");C.baseColorParam.value=new Color(.75,.75,.75,.4),this.reticle=new GeomItem("reticle",I,C);const e=new Xfo;e.ori.setFromAxisAndAngle(new Vec3(1,0,0),.5*Math.PI),this.reticle.geomOffsetXfoParam.value=e,this.stageTreeItem.addChild(this.reticle)}startPresenting(){return new Promise(((A,g)=>{(()=>{navigator.xr.requestSession("immersive-ar",{requiredFeatures:["local","hit-test","anchors"]}).then((g=>{g.addEventListener("end",(()=>{this.stageTreeItem.setVisible(!1),this.session=null,this.emit("presentingChanged",new StateChangedEvent(!1))})),this.reticle.setVisible(!0);g.addEventListener("select",(A=>{const g=A.frame.getHitTestResults(this.xrHitTestSource);if(g.length>0){const I=g[0].getPose(this.refSpace);if(this.reticle.isVisible())if(this.stageXfoSet){const I=new XRPointerEvent(this,this.reticle.globalXfoParam.value,A,g);this.emit("pointerPressed",I)}else this.stageXfo.tr=this.reticle.globalXfoParam.value.tr.negate(),this.setXfo(this.stageXfo),this.stageXfoSet=!0;else{const C=new Xfo;C.setFromMat4(new Mat4(...I.transform.matrix));const e=new XRPointerEvent(this,this.stageXfo.multiply(C),A,g);this.emit("pointerPressed",e)}}})),this.session=g;const I=new XRWebGLLayer(g,this.__gl);g.updateRenderState({baseLayer:I}),this.width=I.framebufferWidth,this.height=I.framebufferHeight,this.region=[0,0,this.width,this.height],this.depthRange=[g.renderState.depthNear,g.renderState.depthFar],this.resizeRenderTargets(this.width,this.height),g.requestReferenceSpace("viewer").then((A=>{this.xrViewerSpace=A,g.requestHitTestSource({space:this.xrViewerSpace}).then((A=>{this.xrHitTestSource=A}))})),g.requestReferenceSpace("local").then((g=>{this.refSpace=g,this.stageTreeItem.setVisible(!0),this.emit("presentingChanged",new StateChangedEvent(!0)),this.startSession(),A()}))})).catch((A=>{console.warn(A.message)}))})()}))}drawXRFrame(A){const g=A.session,I=g.renderState.baseLayer,C=A.getViewerPose(this.refSpace);if(!C)return;if(this.xrHitTestSource&&this.reticle.isVisible()){const g=A.getHitTestResults(this.xrHitTestSource);if(g.length>0){const A=g[0].getPose(this.refSpace),I=new Xfo;I.setFromMat4(new Mat4(A.transform.matrix)),this.reticle.localXfoParam.value=I}}const e=C.views;if(!this.projectionMatricesUpdated){this.projectionMatrices=[],this.viewMatrices=[],this.cameraMatrices=[];for(let A=0;A<e.length;A++){const g=e[A],I=new Mat4;I.fromArray(g.projectionMatrix),this.projectionMatrices[A]=I,this.viewMatrices[A]=new Mat4,this.cameraMatrices[A]=new Mat4}this.projectionMatricesUpdated=!0}this.depthRange=[g.renderState.depthNear,g.renderState.depthFar];const i=new ColorRenderState(this.__renderer.gl);i.boundRendertarget=I.framebuffer,i.region=this.region,i.viewport=this,i.xrviewport=this;const t=[];for(let A=0;A<e.length;A++){const g=e[A];this.viewMatrices[A].fromArray(g.transform.inverse.matrix),this.viewMatrices[A].multiplyInPlace(this.invStageMatrix);const C=I.getViewport(g);t.push({viewMatrix:this.viewMatrices[A],projectionMatrix:this.projectionMatrices[A],region:[C.x,C.y,C.width,C.height],isOrthographic:0})}this.viewXfo.setFromMat4(new Mat4(C.transform.matrix)),i.viewXfo=this.stageXfo.multiply(this.viewXfo),i.cameraMatrix=i.viewXfo.toMat4(),i.viewScale=this.stageScale,i.region=this.region,i.vrPresenting=!0,this.bindXRViewport(i,t),this.draw(i);{const A=new XRPoseEvent(this,this.viewXfo);A.getCapture()&&A.getCapture().onPointerMove(A),this.manipulator&&A.propagating&&this.manipulator.onPointerMove(A)}const o=new XRViewChangedEvent(i.viewXfo);o.viewport=this,o.xrviewport=this,this.emit("viewChanged",o),this.tick++}}class GLGeomItemLibrary extends EventEmitter{renderer;glGeomItems=[null];glGeomItemEventHandlers=[];glGeomItemsMap=new Map;glGeomItemsIndexFreeList=[];dirtyItemIndices=new Set;dirtyWorkerItemIndices=new Set;removedItemIndices=[];glGeomItemsTexture=null;enableFrustumCulling;xrViewport;xrPresenting=!1;xrFovY=0;xrProjectionMatrix=new Mat4;enableOcclusionCulling;debugOcclusionBuffer=!1;occlusionDataBuffer;occlusionImage;occlusionImageItem;reductionDataBuffer;reductionDataArray;bbox;reductionShader;boundingBoxShader;inFrustumIndicesCount=0;inFrustumDrawIdsBuffer;abortController=null;cameraMovementInProgress=!1;occlusionDataBufferSizeFactor=window.devicePixelRatio;occlusionDataBufferSizeFactorXR=2;placeholderLoadThreshold=5;timer_query_ext=null;worker;constructor(A,g){super(),this.renderer=A,this.enableFrustumCulling=g.enableFrustumCulling||g.enableOcclusionCulling,this.enableOcclusionCulling=g.enableOcclusionCulling,this.debugOcclusionBuffer=A.getViewport().debugOcclusionBuffer,this.enableFrustumCulling&&this.setupCullingWorker(A)}setupCullingWorker(A){this.worker=new WorkerFactory;let g=!1;this.worker.postMessage({type:"Init",enableOcclusionCulling:this.enableOcclusionCulling,placeholderLoadThreshold:this.placeholderLoadThreshold}),this.worker.onmessage=A=>{"WorkerReady"==A.data.type?(I(),g=!0):"InFrustumIndices"==A.data.type?this.enableOcclusionCulling?(A.data.newlyCulled&&this.applyCullResults(A.data),this.calculateOcclusionCulling(A.data.inFrustumIndices)):(this.applyCullResults(A.data),this.emitCullingUpdateData(A.data),g=!0):"CullResults"==A.data.type?(this.applyCullResults(A.data),this.emitCullingUpdateData(A.data),g=!0):"Done"==A.data.type&&this.renderer.emit("CullingUpdated"),g=!0};const I=()=>{const g=A.getViewport(),I=A.getViewport().getCamera(),C=g.getWidth()/g.getHeight();if(I.isOrthographic()){const g=I.getFrustumHeight(),e=g*C;this.worker.postMessage({type:"ViewportChanged",frustumHeight:g,frustumWidth:e,isOrthographic:!0,solidAngleLimit:A.solidAngleLimit})}else{const g=.5*I.getFov(),e=Math.atan(Math.tan(g)*C);this.worker.postMessage({type:"ViewportChanged",frustumHalfAngleX:e,frustumHalfAngleY:g,isOrthographic:!1,solidAngleLimit:A.solidAngleLimit})}};A.on("resized",I);const C=A.getViewport().getCamera();C.on("projectionParamChanged",(A=>{C.isOrthographic()&&I()})),A.once("xrViewportSetup",(g=>{this.xrViewport=g.xrViewport;const C=g.xrViewport;C.on("presentingChanged",(g=>{if(this.xrPresenting=g.state,g.state){let g,I;if(i=10,C instanceof VRViewport)g=MathFunctions.degToRad(62),I=MathFunctions.degToRad(50);else if(C instanceof ARViewport){const A=C.getWidth()/C.getHeight();I=62*MathFunctions.degToRad(.5),g=Math.atan(Math.tan(I)*A)}this.xrFovY=2*I;const e=I/g,t=C.depthRange[0],o=C.depthRange[1];this.xrProjectionMatrix.setPerspectiveMatrix(this.xrFovY,e,t,o),this.worker.postMessage({type:"ViewportChanged",frustumHalfAngleX:g,frustumHalfAngleY:I,isOrthographic:!1,solidAngleLimit:4*A.solidAngleLimit}),this.occlusionDataBuffer.resize(Math.ceil(C.getWidth()/this.occlusionDataBufferSizeFactorXR),Math.ceil(C.getWidth()/this.occlusionDataBufferSizeFactorXR))}else i=5,I(),t()}))}));let e=0,i=5;A.on("viewChanged",(I=>{if(this.cameraMovementInProgress=!0,g){if(e%i==0){g=!1;const C=I.viewXfo.tr,e=I.viewXfo.ori;this.worker.postMessage({type:"ViewChanged",cameraPos:C.asArray(),cameraOri:e.asArray(),solidAngleLimit:A.solidAngleLimit})}e++}}));const t=()=>{this.cameraMovementInProgress=!1;const g=A.getViewport().getCamera().globalXfoParam.value,I=g.tr,C=g.ori;this.worker.postMessage({type:"ViewChanged",cameraPos:I.asArray(),cameraOri:C.asArray(),solidAngleLimit:A.solidAngleLimit})};if(A.getViewport().getCamera().on("movementFinished",t),t(),this.enableOcclusionCulling){const A=this.renderer.gl,g=Math.ceil(this.renderer.getWidth()/this.occlusionDataBufferSizeFactor),I=Math.ceil(this.renderer.getHeight()/this.occlusionDataBufferSizeFactor);this.occlusionDataBuffer=new GLRenderTarget(A,{type:A.FLOAT,format:A.RGBA,minFilter:A.NEAREST,magFilter:A.NEAREST,width:g,height:I,depthType:A.UNSIGNED_INT,depthFormat:A.DEPTH_COMPONENT,depthInternalFormat:A.DEPTH_COMPONENT24}),this.renderer.on("resized",(A=>{this.xrPresenting||this.occlusionDataBuffer.resize(Math.ceil(A.width/this.occlusionDataBufferSizeFactor),Math.ceil(A.height/this.occlusionDataBufferSizeFactor))})),this.reductionDataBuffer=new GLRenderTarget(A,{type:A.UNSIGNED_BYTE,format:A.RG,internalFormat:A.RG8,minFilter:A.NEAREST,magFilter:A.NEAREST,width:1,height:1}),this.bbox=new GLLines(A,new BBoxOcclusionLinesCuboid),this.reductionShader=new ReductionShader(A),this.boundingBoxShader=new BoundingBoxShader(A),this.boundingBoxShader.compileForTarget("GLGeomItemLibrary",this.renderer.directives),this.inFrustumIndicesCount=0}}applyCullResults(A){A.newlyCulled&&A.newlyCulled.forEach((A=>{const g=this.glGeomItems[A];g&&g.setCulled(!0)})),A.newlyUnCulled&&A.newlyUnCulled.forEach((A=>{const g=this.glGeomItems[A];g&&g.setCulled(!1)})),A.visiblePlaceholders&&A.visiblePlaceholders.length>0&&!this.cameraMovementInProgress&&A.visiblePlaceholders.forEach((A=>{const g=this.glGeomItems[A.index]?.geomItem;g instanceof PlaceholderGeomItem&&!g.loading&&g.load()})),this.renderer.requestRedraw()}emitCullingUpdateData(A){this.renderer.emit("CullingUpdated",{culled:A.newlyCulled?.length,unCulled:A.newlyUnCulled?.length,visible:A.visible,total:A.total,visibleGeomStats:A.visibleGeomStats,totalGeomStats:A.totalGeomStats})}updateCulledDrawIDsBuffer(A){const g=this.renderer.gl;if(!g.floatTexturesSupported)return;this.inFrustumDrawIdsBuffer&&this.inFrustumIndicesCount!=A.length&&(g.deleteBuffer(this.inFrustumDrawIdsBuffer),this.inFrustumDrawIdsBuffer=null),this.inFrustumDrawIdsBuffer||(this.inFrustumDrawIdsBuffer=g.createBuffer(),g.bindBuffer(g.ARRAY_BUFFER,this.inFrustumDrawIdsBuffer)),g.bindBuffer(g.ARRAY_BUFFER,this.inFrustumDrawIdsBuffer),g.bufferData(g.ARRAY_BUFFER,A,g.STATIC_DRAW),this.inFrustumIndicesCount=A.length;const I=Math.max(4,MathFunctions.nextPow2(Math.round(Math.sqrt(this.glGeomItems.length)+.5)));this.reductionDataBuffer.width!=I&&(this.reductionDataBuffer.resize(I,I),this.reductionDataArray=new Uint8Array(I*I*2))}calculateOcclusionCulling(A){if(A&&A.length>0&&this.updateCulledDrawIDsBuffer(A),this.abortController&&this.abortController.abort(),this.abortController=new AbortController,0==this.inFrustumIndicesCount)return;const g=this.renderer.gl,I=new GeomDataRenderState(g);I.pushGLStack("calculateOcclusionCulling"),this.renderer.bindGLRenderer(I),I.directives=[...this.renderer.directives,"#define DRAW_GEOMDATA"],I.floatGeomBuffer=!0,I.occlusionCulling=1,this.xrPresenting?this.xrViewport.bindCullingViewport(I,this.xrFovY,this.xrProjectionMatrix):this.renderer.getViewport().bindGLViewport(I);const C=this.occlusionDataBuffer.width*this.occlusionDataBuffer.height,e=this.timer_query_ext,i=(A,I,i)=>{this.reductionDataBuffer.bindForWriting(A,I),g.enable(g.BLEND),g.blendEquation(g.FUNC_ADD),g.blendFunc(g.ONE,g.ONE),this.reductionShader.bind(A);const{geomDataTexture:t,reductionTextureWidth:o}=A.unifs;t&&this.occlusionDataBuffer.bindToUniform(A,t),o&&g.uniform1i(o.location,this.reductionDataBuffer.width),e&&g.beginQuery(e.TIME_ELAPSED_EXT,i),g.drawArrays(g.POINTS,0,C),e&&g.endQuery(e.TIME_ELAPSED_EXT),g.disable(g.BLEND),this.reductionDataBuffer.unbindForWriting(A)};let t,o,a,B;e&&(t=g.createQuery(),g.beginQuery(e.TIME_ELAPSED_EXT,t)),(A=>{this.occlusionDataBuffer.bindForWriting(A,!0),A.glDisable(g.BLEND),A.glDisable(g.CULL_FACE),A.glEnable(g.DEPTH_TEST),g.depthFunc(g.LESS),g.depthMask(!0);this.renderer.getPass(0).drawGeomData(A);this.renderer.getPass(1).drawGeomData(A),this.occlusionDataBuffer.unbindForWriting(A)})(I),e&&g.endQuery(e.TIME_ELAPSED_EXT),e&&(o=g.createQuery()),i(I,!0,o),e&&(a=g.createQuery(),g.beginQuery(e.TIME_ELAPSED_EXT,a)),(()=>{this.occlusionDataBuffer.bindForWriting(I,!1),this.debugOcclusionBuffer||(g.colorMask(!0,!0,!0,!0),g.clearColor(0,0,0,0),g.clear(g.COLOR_BUFFER_BIT)),this.boundingBoxShader.bind(I,"GLGeomItemLibrary"),this.bbox.bind(I);const{instancesTexture:A,instancesTextureSize:C,instancedDraw:e,reductionDataTexture:i,occlusionCulling:t}=I.unifs;this.glGeomItemsTexture.bindToUniform(I,A),g.uniform1i(C.location,this.glGeomItemsTexture.width),g.uniform1i(e.location,1),this.reductionDataBuffer.bindColorTexture(I,i);const o=I.attrs.instancedIds.location;g.enableVertexAttribArray(o),g.bindBuffer(g.ARRAY_BUFFER,this.inFrustumDrawIdsBuffer),g.vertexAttribPointer(o,1,g.FLOAT,!1,4,0),g.vertexAttribDivisor(o,1),I.bindViewports(I.unifs,(()=>{this.bbox.drawInstanced(I,this.inFrustumIndicesCount)})),this.occlusionDataBuffer.unbindForWriting(I)})(),e&&g.endQuery(e.TIME_ELAPSED_EXT),e&&(B=g.createQuery()),i(I,!1,B),I.popGLStack();const s={numReductionPoints:C},l=(A,I)=>{const C=g.getQueryParameter(I,g.QUERY_RESULT_AVAILABLE),i=g.getParameter(e.GPU_DISJOINT_EXT);if(C&&!i){const C=g.getQueryParameter(I,g.QUERY_RESULT);s[A]=C/1e6,g.deleteQuery(I)}},n=this.reductionDataBuffer.width,d=this.reductionDataBuffer.height,r=g.RG,c=g.UNSIGNED_BYTE;this.reductionDataBuffer.bindForReading();const h=this.abortController;readPixelsAsync(g,0,0,n,d,r,c,this.reductionDataArray,h).then((()=>{this.reductionDataBuffer.unbindForReading(),h.__abort||(e&&(l("queryDrawScene",t),l("queryDrawCulledBBoxes",a),l("queryReduceSceneGeoms",o),l("queryReduceBBoxes",B),this.renderer.emit("occlusionCullingProfilingData",s)),this.worker.postMessage({type:"OcclusionData",reductionDataArray:this.reductionDataArray}),this.abortController=null)}))}addGeomItem(A){let g=this.glGeomItemsMap.get(A);if(null!=g)return this.glGeomItems[g];this.glGeomItemsIndexFreeList.length>0?g=this.glGeomItemsIndexFreeList.pop():(g=this.glGeomItems.length,this.glGeomItems.push(null)),this.removedItemIndices.includes(g)&&this.removedItemIndices.splice(this.removedItemIndices.indexOf(g),1),this.dirtyItemIndices.add(g);const I=A.materialParam;let C=I.value;const e=this.renderer.glMaterialLibrary.addMaterial(C),i=()=>{this.renderer.glMaterialLibrary.removeMaterial(C),C=I.value,a.materialId=C?this.renderer.glMaterialLibrary.addMaterial(C):-1,s(),B()};I.on("valueChanged",i);const t=this.renderer.gl,o=C.getShaderClass().supportsInstancing(),a=new GLGeomItem(t,A,g,-1,e,o),B=()=>{if(this.dirtyItemIndices.has(g))return;this.dirtyItemIndices.add(g);const I=A.isPickable();this.renderer.drawItemChanged(I)};A.geomMatParam.on("valueChanged",B),A.on("cutAwayChanged",B),A.on("highlightChanged",B),A.on("selectabilityChanged",B),A.on("opacityChanged",B),A.on("pickabilityChanged",B);const s=()=>{if(this.enableFrustumCulling&&!this.dirtyWorkerItemIndices.has(g)){this.dirtyWorkerItemIndices.add(g);const I=A.isPickable();this.renderer.drawItemChanged(I)}};return this.enableFrustumCulling&&this.dirtyWorkerItemIndices.add(g),A.on("visibilityChanged",s),A.on("opacityChanged",s),A.geomMatParam.on("valueChanged",s),A.geomParam.on("boundingBoxChanged",s),this.glGeomItems[g]=a,this.glGeomItemEventHandlers[g]={geomItemChanged:B,materialChanged:i,workerItemDataChanged:s},this.glGeomItemsMap.set(A,g),this.renderer.requestRedraw(),a}removeGeomItem(A){const g=this.glGeomItemsMap.get(A);if(null==g)return null;const I=this.glGeomItems[g],C=A.materialParam.value;this.renderer.glMaterialLibrary.removeMaterial(C);const e=this.glGeomItemEventHandlers[g];return A.materialParam.off("valueChanged",e.materialChanged),A.geomMatParam.off("valueChanged",e.geomItemChanged),A.off("cutAwayChanged",e.geomItemChanged),A.off("highlightChanged",e.geomItemChanged),A.off("selectabilityChanged",e.geomItemChanged),A.off("opacityChanged",e.geomItemChanged),A.off("pickabilityChanged",e.geomItemChanged),A.off("visibilityChanged",e.workerItemDataChanged),A.geomMatParam.off("valueChanged",e.workerItemDataChanged),A.off("opacityChanged",e.workerItemDataChanged),A.geomParam.off("boundingBoxChanged",e.workerItemDataChanged),this.glGeomItems[g]=null,this.glGeomItemEventHandlers[g]=null,this.glGeomItemsIndexFreeList.push(g),this.glGeomItemsMap.delete(A),this.removedItemIndices.push(g),this.dirtyWorkerItemIndices.has(g)&&this.dirtyWorkerItemIndices.delete(g),this.renderer.requestRedraw(),I}getGeomItem(A){if(!(A>=this.glGeomItems.length))return this.glGeomItems[A]?.geomItem;console.warn("Invalid Draw Item id:"+A+" NumItems:"+(this.glGeomItems.length-1))}getGLGeomItem(A){const g=this.glGeomItemsMap.get(A);return null!=g?this.glGeomItems[g]:null}populateDrawItemDataArray(A,g,I){const C=this.glGeomItems[A];if(!C)return;const{geomItem:e,geomId:i}=C,t=e.materialParam.value,o=32*g;let a=0;e.isCutawayEnabled()&&(a|=GLGeomItemFlags.GEOMITEM_FLAG_CUTAWAY),e.isPickable()||(a|=GLGeomItemFlags.GEOMITEM_INVISIBLE_IN_GEOMDATA),t.isOpaque()&&e.isOpaque()||(a|=GLGeomItemFlags.GEOMITEM_TRANSPARENT);const B=new Float32Array(I.buffer,4*(o+0),4);B[0]=a,B[1]=e.opacity;const s=this.renderer.glMaterialLibrary.getMaterialAllocation(t);s&&(B[2]=s.start),B[4]=i;const l=e.geomMatParam.value,n=new Float32Array(I.buffer,4*(o+4),4),d=new Float32Array(I.buffer,4*(o+8),4),r=new Float32Array(I.buffer,4*(o+12),4);n.set([l.xAxis.x,l.yAxis.x,l.zAxis.x,l.translation.x]),d.set([l.xAxis.y,l.yAxis.y,l.zAxis.y,l.translation.y]),r.set([l.xAxis.z,l.yAxis.z,l.zAxis.z,l.translation.z]);const c=new Float32Array(I.buffer,4*(o+16),4);if(e.isHighlighted()){const A=e.getHighlight();c.set([A.r,A.g,A.b,A.a])}const h=new Float32Array(I.buffer,4*(o+20),4);if(e.isCutawayEnabled()){const A=e.getCutVector(),g=e.getCutDist();h.set([A.x,A.y,A.z,g])}const G=e.boundingBoxParam.value,m=new Float32Array(I.buffer,4*(o+24)),b=new Float32Array(I.buffer,4*(o+28));m.set([G.p0.x,G.p0.y,G.p0.z,0]),b.set([G.p1.x,G.p1.y,G.p1.z,0])}getCullingWorkerData(A,g){const I=A.boundingBoxParam.value,C=.5*I.size(),e=I.center(),i=A.materialParam.value,t=A.cullable&&!A.isOverlay()&&!i.getShaderClass().isOverlay(),o=!A.isOpaque()||!i.isOpaque(),a=A instanceof PlaceholderGeomItem,B={triangles:0,lines:0,points:0},s=A.geomParam.value;if(s instanceof CompoundGeom)B.triangles+=s.getNumTriangles(),B.lines+=s.getNumLineSegments(),B.points+=s.getNumPoints();else if(s instanceof Mesh||s instanceof MeshProxy)B.triangles+=s.getNumTriangles();else if(s instanceof Lines||s instanceof LinesProxy)B.lines+=s.getNumLineSegments();else{if(!(s instanceof Points||s instanceof PointsProxy))throw new Error("Unsupported geom type:"+s.constructor.name);B.points+=s.getNumVertices()}return{id:g,boundingRadius:C,pos:e.asArray(),cullable:t,visible:A.isVisible(),transparent:o,isPlaceholder:a,geomStats:B}}uploadGeomItemsToWorker(){if(this.enableFrustumCulling){const A=[];this.dirtyWorkerItemIndices.forEach((g=>{const I=this.glGeomItems[g];if(!I)return;const{geomItem:C}=I,e=this.getCullingWorkerData(C,g);e&&A.push(e)})),this.worker.postMessage({type:"UpdateGeomItems",geomItems:A,removedItemIndices:this.removedItemIndices}),this.dirtyWorkerItemIndices.clear(),this.removedItemIndices=[]}}uploadGeomItems(A){const g=this.renderer.gl;if(!g.floatTexturesSupported)return;let I=Math.round(Math.sqrt(8*this.glGeomItems.length)+.5);I=MathFunctions.nextPow2(I),I%8!=0&&(I+=8-I%8),this.glGeomItemsTexture?this.glGeomItemsTexture.width!=I&&(this.glGeomItemsTexture.resize(I,I),this.dirtyItemIndices=new Set(Array(I*I/8).fill(0).map(((A,g)=>g)))):(this.glGeomItemsTexture=new GLTexture2D(g,{format:"RGBA",type:"FLOAT",width:I,height:I,filter:"NEAREST",wrap:"CLAMP_TO_EDGE",mipMapped:!1}),this.glGeomItemsTexture.clear()),g.bindTexture(g.TEXTURE_2D,this.glGeomItemsTexture.glTex);const C=this.glGeomItemsTexture.type,e=Array.from(this.dirtyItemIndices);for(let A=0;A<e.length;A++){const i=e[A],t=Math.floor(8*i/I);let o=i+1;for(let g=A+1;g<e.length;g++){const A=e[g];if(Math.floor(8*A/I)!=t)break;if(A!=o)break;o++}const a=o-i,B=8*i%I,s=8*a,l=1,n=new Float32Array(32*a);for(let A=i;A<o;A++)this.populateDrawItemDataArray(A,A-i,n);if(C==g.FLOAT)this.glGeomItemsTexture.populate(n,s,l,B,t,!1);else{const A=MathFunctions.convertFloat32ArrayToUInt16Array(n);this.glGeomItemsTexture.populate(A,s,l,B,t,!1)}A+=a-1}this.removedItemIndices=[],this.dirtyItemIndices=new Set}bind(A){(this.dirtyWorkerItemIndices.size>0||this.removedItemIndices.length>0)&&this.uploadGeomItemsToWorker(),this.dirtyItemIndices.size>0&&this.uploadGeomItems(A);const g=this.renderer.gl,{instancesTexture:I,instancesTextureSize:C}=A.unifs;I&&(this.glGeomItemsTexture.bindToUniform(A,I),g.uniform1i(C.location,this.glGeomItemsTexture.width))}}var frag$f="\nprecision highp float;\n#define GLSLIFY 1\n\nuniform float outlineThickness;\nuniform sampler2D highlightDataTexture;\n\nvarying vec2 v_texCoord;\n\nfloat M_PI = 3.141592653589793;\nfloat diff(vec4 pixelA, vec4 pixelB)\n{\n  return abs(pixelA.r - pixelB.r) + abs(pixelA.g - pixelB.g) + abs(pixelA.b - pixelB.b) + abs(pixelA.a - pixelB.a);\n}\n\n// find the first pixel which is not the same as the center pixel.\nvec4 RadialSearch(vec2 uv)\n{\n  vec2 texSize = vec2(textureSize(highlightDataTexture, 0));\n  ivec2 pixelCenterCoord = ivec2(uv * texSize);\n  vec4 pixelCenter = texelFetch(highlightDataTexture, pixelCenterCoord, 0);\n\n  vec3 offset = vec3((1.0 / texSize.x), (1.0 / texSize.y), 0.0);\n\n  vec4 result = pixelCenter;\n  float weights = 1.0;\n  float radius = 0.0;\n  int differentPixels = 0;\n  while (radius <= outlineThickness + 0.001) {\n    radius += 1.0;\n    \n    int samples = int(2.0 * M_PI * radius);\n    for (int i =0; i<samples; i++) {\n      float theta = (float(i) / float(samples)) * 2.0 * M_PI;\n      vec2 dir = vec2(radius * cos(theta) * offset.x, radius * sin(theta) * offset.y);\n      \n      ivec2 pixelCoord = ivec2((uv + dir) * texSize);\n      vec4 pixel = texelFetch(highlightDataTexture, pixelCoord, 0);\n      if ((pixel.r > 0.0 || pixel.g > 0.0 || pixel.b > 0.0)) {\n        if (diff(pixel, pixelCenter) > 0.1) differentPixels++;\n        // Blend the outer ring of pixels.\n        // Note: disabled because I ran out of time. We can blend off the highlight towards\n        // the edges to get a nicely anti-aliazed outline. \n        // float dist = length(vec2(pixelCoord) - vec2(pixelCenterCoord));\n        // float blendStart = max(1.0, outlineThickness - 0.5);\n        pixel.a = 1.0; //smoothstep(1.0, 0.0, dist - blendStart);\n\n        result += pixel;\n        weights += pixel.a;\n      }\n    }\n  }\n\n  // Note: at the boundary between 2 highlighted objects, we get a nice blending effect. \n  if (weights > 1.0) {\n    result = result / weights;\n  }\n\n  // If all the pixels found are the same as the center pixel, we just\n  // return the center pixel.\n  if (differentPixels == 0) {\n    return pixelCenter;\n  }\n\n  return result;\n}\n\n#ifdef ENABLE_ES3\nout vec4 fragColor;\n#endif\n\nvoid main(void) {\n    \n  vec4 outlineColor = RadialSearch(v_texCoord);\n  \n  if (outlineColor.a > 0.0001) {\n#ifndef ENABLE_ES3\n    gl_FragColor = outlineColor;\n#else\n    fragColor = outlineColor;\n#endif\n  }\n  else {\n    discard;\n  }\n}\n\n",vert$g="\nprecision highp float;\n#define GLSLIFY 1\n\nattribute vec3 positions;    //(location = 0)\n\n/* VS Outputs */\nvarying vec2 v_texCoord;\n \nvoid main()\n{\n  v_texCoord = positions.xy+0.5;\n  gl_Position = vec4(positions.xy*2.0, 0.0, 1.0);\n}\n\n";class HighlightsShader extends GLShader{constructor(A){super(A,"HighlightsShader"),this.setShaderStage("VERTEX_SHADER",vert$g),this.setShaderStage("FRAGMENT_SHADER",frag$f)}}var frag$e="\n#ifndef ENABLE_ES3\n#extension GL_EXT_frag_depth: enable\n#endif\nprecision highp float;\n#define GLSLIFY 1\n\nuniform sampler2D colorTexture;\nuniform sampler2D depthTexture;\nuniform vec2 screenSize;\nuniform vec2 depthRange;\n\nuniform float outlineThickness;\nuniform color outlineColor;\nuniform float outlineSensitivity;\nuniform float outlineDepthBias;\n\nvarying vec2 v_texCoord;\n\n// http://web.archive.org/web/20130416194336/http://olivers.posterous.com/linear-depth-in-glsl-for-real\nfloat LinearEyeDepth(float z_b) {\n  float z_n = 2.0 * z_b - 1.0;\n  float z_e = 2.0 * depthRange.x * depthRange.y / (depthRange.y + depthRange.x - z_n * (depthRange.y - depthRange.x));\n  return z_e;\n}\n\nfloat LogEyeDepth(float z_b) {\n  return depthRange.x + ((depthRange.y - depthRange.x) * z_b);\n}\n\n// https://www.vertexfragment.com/ramblings/unity-postprocessing-sobel-outline/#depth-based-outline\n// https://github.com/ssell/UnitySobelOutline/blob/2e1f4a5b4e703ae2c96aaf08d5518ce58abbaab9/Assets/Resources/Shaders/SobelOutlineHLSL.shader\n\nfloat SobelDepth(float ldc, float ldl, float ldr, float ldu, float ldd)\n{\n  return abs(ldl - ldc) +\n      abs(ldr - ldc) +\n      abs(ldu - ldc) +\n      abs(ldd - ldc);\n}\n\nfloat SobelSampleDepth(vec2 uv, vec3 offset)\n{\n  float pixelCenter = LinearEyeDepth(texture2D(depthTexture, uv).r);\n  float pixelLeft   = LinearEyeDepth(texture2D(depthTexture, uv - offset.xz).r);\n  float pixelRight  = LinearEyeDepth(texture2D(depthTexture, uv + offset.xz).r);\n  float pixelUp     = LinearEyeDepth(texture2D(depthTexture, uv + offset.zy).r);\n  float pixelDown   = LinearEyeDepth(texture2D(depthTexture, uv - offset.zy).r);\n\n  float  outlineDepthMultiplier = (1.0 / pixelCenter) * outlineSensitivity;\n\n  return SobelDepth(pixelCenter, pixelLeft, pixelRight, pixelUp, pixelDown) * outlineDepthMultiplier;\n}\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\nvoid main(void) {\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  vec3 offset = vec3((1.0 / screenSize.x), (1.0 / screenSize.y), 0.0) * outlineThickness;\n  float sobelDepth = SobelSampleDepth(v_texCoord, offset);\n  float sobelValue = pow(sobelDepth, outlineDepthBias);\n\n  float minEdgeValue = 0.25;\n  float maxEdgeValue = 0.55;\n  sobelDepth = smoothstep(minEdgeValue, maxEdgeValue, sobelValue);\n\n#ifdef ENABLE_ES3\n  fragColor = vec4(outlineColor.rgb, sobelDepth);\n#else\n  fragColor = vec4(mix(texture2D(colorTexture, v_texCoord).rgb, outlineColor.rgb, sobelDepth), 1.0);\n#ifdef  GL_EXT_frag_depth\n  gl_FragDepthEXT = texture2D(depthTexture, v_texCoord).r;\n#endif\n#endif\n\n  // float z = texture2D(depthTexture, v_texCoord).r;\n  // float near = depthRange.x * 2.0;    // the near plane\n  // float far = depthRange.y / 2.0;     // the far plane\n  // float c = (2.0 * near) / (far + near - z * (far - near));  // convert to linear values \n  // fragColor = vec4(vec3(c), 1.0);\n\n  \n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n",vert$f="\nprecision highp float;\n#define GLSLIFY 1\nattribute vec3 positions;    //(location = 0)\n\n/* VS Outputs */\nvarying vec2 v_texCoord;\n \nvoid main()\n{\n  v_texCoord = positions.xy+0.5;\n  gl_Position = vec4(positions.xy*2.0, 0.0, 1.0);\n}\n";class SilhouetteShader extends GLShader{constructor(A){super(A,"SilhouetteShader"),this.setShaderStage("VERTEX_SHADER",vert$f),this.setShaderStage("FRAGMENT_SHADER",frag$e)}}var freeGlobal="object"==typeof global&&global&&global.Object===Object&&global,freeGlobal$1=freeGlobal,freeSelf="object"==typeof self&&self&&self.Object===Object&&self,root=freeGlobal$1||freeSelf||Function("return this")(),root$1=root,Symbol$1=root$1.Symbol,Symbol$2=Symbol$1,objectProto$1=Object.prototype,hasOwnProperty=objectProto$1.hasOwnProperty,nativeObjectToString$1=objectProto$1.toString,symToStringTag$1=Symbol$2?Symbol$2.toStringTag:void 0;function getRawTag(A){var g=hasOwnProperty.call(A,symToStringTag$1),I=A[symToStringTag$1];try{A[symToStringTag$1]=void 0;var C=!0}catch(A){}var e=nativeObjectToString$1.call(A);return C&&(g?A[symToStringTag$1]=I:delete A[symToStringTag$1]),e}var objectProto=Object.prototype,nativeObjectToString=objectProto.toString;function objectToString(A){return nativeObjectToString.call(A)}var nullTag="[object Null]",undefinedTag="[object Undefined]",symToStringTag=Symbol$2?Symbol$2.toStringTag:void 0;function baseGetTag(A){return null==A?void 0===A?undefinedTag:nullTag:symToStringTag&&symToStringTag in Object(A)?getRawTag(A):objectToString(A)}function isObjectLike(A){return null!=A&&"object"==typeof A}var symbolTag="[object Symbol]";function isSymbol(A){return"symbol"==typeof A||isObjectLike(A)&&baseGetTag(A)==symbolTag}var reWhitespace=/\s/;function trimmedEndIndex(A){for(var g=A.length;g--&&reWhitespace.test(A.charAt(g)););return g}var reTrimStart=/^\s+/;function baseTrim(A){return A?A.slice(0,trimmedEndIndex(A)+1).replace(reTrimStart,""):A}function isObject(A){var g=typeof A;return null!=A&&("object"==g||"function"==g)}var NAN=NaN,reIsBadHex=/^[-+]0x[0-9a-f]+$/i,reIsBinary=/^0b[01]+$/i,reIsOctal=/^0o[0-7]+$/i,freeParseInt=parseInt;function toNumber(A){if("number"==typeof A)return A;if(isSymbol(A))return NAN;if(isObject(A)){var g="function"==typeof A.valueOf?A.valueOf():A;A=isObject(g)?g+"":g}if("string"!=typeof A)return 0===A?A:+A;A=baseTrim(A);var I=reIsBinary.test(A);return I||reIsOctal.test(A)?freeParseInt(A.slice(2),I?2:8):reIsBadHex.test(A)?NAN:+A}var now=function(){return root$1.Date.now()},now$1=now,FUNC_ERROR_TEXT$1="Expected a function",nativeMax=Math.max,nativeMin=Math.min;function debounce(A,g,I){var C,e,i,t,o,a,B=0,s=!1,l=!1,n=!0;if("function"!=typeof A)throw new TypeError(FUNC_ERROR_TEXT$1);function d(g){var I=C,i=e;return C=e=void 0,B=g,t=A.apply(i,I)}function r(A){var I=A-a;return void 0===a||I>=g||I<0||l&&A-B>=i}function c(){var A=now$1();if(r(A))return h(A);o=setTimeout(c,function(A){var I=g-(A-a);return l?nativeMin(I,i-(A-B)):I}(A))}function h(A){return o=void 0,n&&C?d(A):(C=e=void 0,t)}function G(){var A=now$1(),I=r(A);if(C=arguments,e=this,a=A,I){if(void 0===o)return function(A){return B=A,o=setTimeout(c,g),s?d(A):t}(a);if(l)return clearTimeout(o),o=setTimeout(c,g),d(a)}return void 0===o&&(o=setTimeout(c,g)),t}return g=toNumber(g)||0,isObject(I)&&(s=!!I.leading,i=(l="maxWait"in I)?nativeMax(toNumber(I.maxWait)||0,g):i,n="trailing"in I?!!I.trailing:n),G.cancel=function(){void 0!==o&&clearTimeout(o),B=0,C=a=e=o=void 0},G.flush=function(){return void 0===o?t:h(now$1())},G}var FUNC_ERROR_TEXT="Expected a function";function throttle(A,g,I){var C=!0,e=!0;if("function"!=typeof A)throw new TypeError(FUNC_ERROR_TEXT);return isObject(I)&&(C="leading"in I?!!I.leading:C,e="trailing"in I?!!I.trailing:e),debounce(A,g,{leading:C,maxWait:g,trailing:e})}let activeGLRenderer,pointerIsDown=!1,pointerLeft=!1;const registeredPasses=[];let requestPostAnimationFrame;requestPostAnimationFrame=globalThis.requestPostAnimationFrame?window.requestPostAnimationFrame:function(A){requestAnimationFrame((()=>{setTimeout(A,0)}))};class GLBaseRenderer extends ParameterOwner{#d=new Map;directives=[];directivesHash;solidAngleLimit=.004;__gl;glcanvas=null;#r=null;#c={};#h=!1;#G={};#m={};#b=new Map;#Z=[];#u=[];#y=void 0;#E=!1;#Q=!1;#V=0;#R=0;#W=0;floatGeomBuffer=!0;multiSampledScreenBuffer=!1;xrViewportPresenting=!1;xrViewport=void 0;#p;glMaterialLibrary;glGeomItemLibrary;glGeomLibrary;highlightsShader;silhouetteShader;screenQuad=null;#S;#F;constructor(A,g={}){if(super(),!SystemDesc.gpuDesc)throw new Error("Unable to create renderer. WebGL not Supported");this.requestRedraw=this.requestRedraw.bind(this),this.__gl=this.setupWebGL(A,g);const I=this.__gl;this.highlightsShader=new HighlightsShader(I),this.silhouetteShader=new SilhouetteShader(I),this.screenQuad=new GLScreenQuad(this.__gl,this.directives),this.bindEventHandlers();const C=this.addViewport("main");C.debugGeomDataBuffer=g.debugGeomDataBuffer,C.debugOcclusionBuffer=g.debugOcclusionBuffer,this.glMaterialLibrary=new GLMaterialLibrary(this),this.glMaterialLibrary.on("updated",(()=>{this.requestRedraw()})),this.glGeomLibrary=new GLGeomLibrary(this),this.glGeomLibrary.on("updated",(()=>{this.requestRedraw()})),this.glGeomItemLibrary=new GLGeomItemLibrary(this,g),this.glGeomItemLibrary.on("updated",(()=>{this.requestRedraw()})),registeredPasses.forEach((A=>{const g=new A.cls;this.addPass(g,A.passType)})),this.#p=new Promise(((A,I)=>{if((g.supportXR??1)&&navigator.xr){const C="AR"==(g.xrMode??"VR")?"immersive-ar":"immersive-vr",e=()=>{this.xrViewport=this.setupXRViewport(C);let g=new XrViewportEvent(this.xrViewport);this.emit("xrViewportSetup",g),A(this.xrViewport)};navigator.xr.isSessionSupported(C).then((A=>{A&&e()})).catch((A=>{console.warn("Unable to setup XR:"+A),I("Unable to setup XR:"+A)}))}}))}setShaderPreprocessorDirective(A,g){this.#c[A]=g;const I=[];let C="";for(const A in this.#c){const g=this.#c[A];I.push(g),C+=g}this.directives=I,this.directivesHash=""+StringFunctions.hashStr(C)}getWidth(){return this.glcanvas.width}getHeight(){return this.glcanvas.height}addViewport(A){const g=new GLViewport(this,A,this.getWidth(),this.getHeight());return g.on("updated",(()=>{this.requestRedraw()})),g.on("viewChanged",(A=>{this.xrViewportPresenting||this.emit("viewChanged",A)})),this.#u.push(g),this.#y=g,g}getViewport(A=0){return this.#u[A]}getViewportAtPos(A,g){for(const I of this.#u){const C=I.getPosX(),e=I.getPosY(),i=I.getWidth(),t=I.getHeight();if(A>=C&&g>=e&&A<=i+C&&g<=t+e)return I}}activateViewport(A){this.#y!=A&&(this.#y=A)}activateViewportAtPos(A,g){if(this.xrViewportPresenting)return;const I=this.getViewportAtPos(A,g);I&&I!=this.#y&&this.activateViewport(I)}getActiveViewport(){return this.#y}suspendDrawing(){this.#V++}resumeDrawing(){this.#V--,0==this.#V&&(this.renderGeomDataFbos(),this.requestRedraw())}renderGeomDataFbos(){if(1==this.#h)return;this.#h=!0;requestPostAnimationFrame((()=>{for(const A of this.#u)A.invalidateGeomDataBuffer();this.#h=!1}))}getScene(){return this.#r}setScene(A){this.#r=A,this.addTreeItem(this.#r.getRoot());let g=new SceneSetEvent(this.#r);this.emit("sceneSet",g)}addTreeItem(A){if(!(A instanceof TreeItem))return;const g={};let I=!0;if(A instanceof GeomItem){const C=A.geomParam;if(null==C.value){const I=()=>{delete g["Geometry.valueChanged"],this.assignTreeItemToGLPass(A)};g["Geometry.valueChanged"]=C.once("valueChanged",I)}else I=this.assignTreeItemToGLPass(A)}else I=this.assignTreeItemToGLPass(A);if(I){for(const g of A.getChildren())g&&this.addTreeItem(g);g.childAdded=A.on("childAdded",(A=>{this.addTreeItem(A.childItem)})),g.childRemoved=A.on("childRemoved",(A=>{this.removeTreeItem(A.childItem)}))}g.visibilityChanged=A.on("visibilityChanged",(()=>{this.renderGeomDataFbos()})),g.pickabilityChanged=A.on("pickabilityChanged",(()=>{this.renderGeomDataFbos()})),this.#d.set(A,g),this.renderGeomDataFbos()}assignTreeItemToGLPass(A){if(A instanceof GeomItem){const g=A;this.glGeomItemLibrary.addGeomItem(g)}for(let g=this.#Z.length-1;g>=0;g--){const I=this.#Z[g],C={continueInSubTree:!0};if(I.itemAddedToScene(A,C))return this.#b.set(A,I),C.continueInSubTree}return!0}removeTreeItem(A){if(!(A instanceof TreeItem))return;const g=this.#d.get(A);this.#d.delete(A),A.off("visibilityChanged",g.visibilityChanged),A.off("pickabilityChanged",g.pickabilityChanged);const I=this.#b.get(A);if(null!=I){const g={continueInSubTree:!0};I.itemRemovedFromScene(A,g),this.#b.delete(A)}if(null!=g.childAdded&&null!=g.childRemoved){A.off("childAdded",g.childAdded),A.off("childRemoved",g.childRemoved);for(const g of A.getChildren())g&&this.removeTreeItem(g)}if(A instanceof GeomItem){const I=A;if(g["Geometry.valueChanged"]){A.geomParam.off("valueChanged",g["Geometry.valueChanged"])}this.glGeomItemLibrary.removeGeomItem(I)}this.renderGeomDataFbos()}get gl(){return this.__gl}getGL(){return this.__gl}handleResize(A,g){if(this.xrViewportPresenting)return;const I=Math.round(Math.max(4,A)*window.devicePixelRatio),C=Math.round(Math.max(4,g)*window.devicePixelRatio);if(this.glcanvas.width!=I||this.glcanvas.height!=C){this.glcanvas.width=I,this.glcanvas.height=C,this.#u.forEach((A=>{A.resize(I,C)}));const A=new ResizedEvent(I,C);this.emit("resized",A),this.requestRedraw()}}getDiv(){return this.glcanvas.parentElement}setupWebGL(A,g={}){const{tagName:I}=A;if(!["DIV","CANVAS"].includes(I))throw new Error("Only CANVAS and DIV are valid root elements.");const C="DIV"===I;this.glcanvas=A,C?(console.warn("@GLBaseRenderer#setupWebGL.","Using a DIV as root element is deprecated.","Use a CANVAS instead.","See: https://docs.zea.live/zea-engine/#/getting-started/get-started-with-engine?id=basic-setup"),this.glcanvas=document.createElement("canvas"),A.appendChild(this.glcanvas)):this.glcanvas=A,this.glcanvas.style["touch-action"]="none",this.glcanvas.style["user-select"]="none",this.glcanvas.style["-webkit-user-select"]="none",this.glcanvas.style["-webkit-touch-callout"]="none",this.glcanvas.parentElement.style.position="relative",this.glcanvas.parentElement.style.overflow="hidden",this.glcanvas.style.width="100%",this.glcanvas.style.height="100%",this.glcanvas.style.position="absolute";const e=throttle((A=>{if(this.__gl)if(this.__gl.isContextLost())console.warn("WebGL Context Lost");else if(Array.isArray(A)&&A.length)for(const g of A){if(!g.contentRect)return;const A=Math.round(g.contentRect.width),I=Math.round(g.contentRect.height);this.handleResize(A,I)}}),500);this.#F=()=>{const A=[{contentRect:{width:this.glcanvas.parentElement.clientWidth,height:this.glcanvas.parentElement.clientHeight}}];e(A)},window.addEventListener("resize",this.#F),this.#S=new ResizeObserver(e);try{this.#S.observe(this.glcanvas.parentNode,{box:"device-pixel-content-box"})}catch(A){this.#S.observe(this.glcanvas.parentNode,{box:"content-box"})}this.handleResize(this.glcanvas.parentElement.clientWidth,this.glcanvas.parentElement.clientHeight);const i="macOS"===SystemDesc.OS&&"Chrome"===SystemDesc.browserName,t=SystemDesc.isIOSDevice,o={preserveDrawingBuffer:!0};o.antialias=!i&&!t&&(g.antialias??!0),o.depth=!0,o.stencil=!0,o.alpha=g.alpha??!0,o.premultipliedAlpha=g.premultipliedAlpha??!1,(navigator.xr||g.supportXR)&&(o.xrCompatible=!0),this.multiSampledScreenBuffer=o.antialias,o.powerPreference=g.powerPreference||"high-performance";const a=create3DContext(this.glcanvas,o);a||alert("Unable to create WebGL context. WebGL not supported."),this.setShaderPreprocessorDirective("ENABLE_ES3","#define ENABLE_ES3"),a.floatTexturesSupported&&this.setShaderPreprocessorDirective("ENABLE_FLOAT_TEXTURES","#define ENABLE_FLOAT_TEXTURES");{const A=a.getExtension("WEBGL_multi_draw");A&&!g.disableMultiDraw?(a.multiDrawArrays=A.multiDrawArraysWEBGL.bind(A),a.multiDrawElements=A.multiDrawElementsWEBGL.bind(A),a.multiDrawElementsInstanced=A.multiDrawElementsInstancedWEBGL.bind(A),a.multiDrawArraysInstanced=A.multiDrawArraysInstancedWEBGL.bind(A)):this.setShaderPreprocessorDirective("EMULATE_MULTI_DRAW","#define EMULATE_MULTI_DRAW")}return"Safari"==SystemDesc.browserName&&"webgl"==a.name?this.floatGeomBuffer=!1:this.floatGeomBuffer=null!=g.floatGeomBuffer?g.floatGeomBuffer:a.floatTexturesSupported,a.floatGeomBuffer=this.floatGeomBuffer,a}bindEventHandlers(){const A=()=>this.getWidth()>0&&this.getHeight(),g=A=>!!SystemDesc.isMobileDevice;this.glcanvas.addEventListener("mousedown",(A=>{if(g())return;const I=new ZeaMouseEvent(A,this.glcanvas.getBoundingClientRect());pointerIsDown=!0,activeGLRenderer=this,this.activateViewportAtPos(I.rendererX,I.rendererY);const C=this.getActiveViewport();C&&C.onPointerDown(I),pointerLeft=!1})),document.addEventListener("mouseup",(I=>{if(g())return;if(activeGLRenderer!=this||!A())return;const C=new ZeaMouseEvent(I,this.glcanvas.getBoundingClientRect());pointerIsDown=!1;const e=this.getActiveViewport();e&&e.onPointerUp(C),pointerLeft&&(e&&e.onPointerLeave(C),activeGLRenderer=void 0)})),document.addEventListener("mousemove",(I=>{if(g())return;if(activeGLRenderer!=this||!A())return;const C=new ZeaMouseEvent(I,this.glcanvas.getBoundingClientRect());pointerIsDown||this.activateViewportAtPos(C.rendererX,C.rendererY);const e=this.getActiveViewport();e&&e.onPointerMove(C)})),this.glcanvas.addEventListener("mouseenter",(A=>{if(!g()&&!pointerIsDown){activeGLRenderer=this;const g=new ZeaMouseEvent(A,this.glcanvas.getBoundingClientRect());if(this.activateViewportAtPos(g.rendererX,g.rendererY),!pointerIsDown){const A=this.getActiveViewport();A&&A.onPointerEnter(g)}pointerLeft=!1}})),this.glcanvas.addEventListener("mouseleave",(I=>{if(g())return;if(activeGLRenderer!=this||!A())return;const C=new ZeaMouseEvent(I,this.glcanvas.getBoundingClientRect());if(pointerIsDown)pointerLeft=!0;else{const A=this.getActiveViewport();A&&A.onPointerLeave(C),activeGLRenderer=void 0}})),document.addEventListener("contextmenu",(g=>{activeGLRenderer==this&&A()&&(g.preventDefault(),g.stopPropagation())})),this.glcanvas.addEventListener("touchstart",(A=>{activeGLRenderer=this;const g=this.getActiveViewport(),I=new ZeaTouchEvent(A,this.glcanvas.getBoundingClientRect());g.onPointerDown(I)}),{passive:!0}),this.glcanvas.addEventListener("touchend",(A=>{const g=this.getActiveViewport(),I=new ZeaTouchEvent(A,this.glcanvas.getBoundingClientRect());g.onPointerUp(I)}),{passive:!0}),this.glcanvas.addEventListener("touchmove",(A=>{const g=this.getActiveViewport(),I=new ZeaTouchEvent(A,this.glcanvas.getBoundingClientRect());g.onPointerMove(I)}),{passive:!0}),this.glcanvas.addEventListener("touchcancel",(A=>{const g=this.getActiveViewport(),I=new ZeaTouchEvent(A,this.glcanvas.getBoundingClientRect());g.onTouchCancel(I)}),{passive:!0});window.addEventListener("wheel",(g=>{if(activeGLRenderer==this&&A()&&activeGLRenderer){const A=new ZeaWheelEvent(g,this.glcanvas.getBoundingClientRect()),I=activeGLRenderer.getActiveViewport();I&&I.onWheel(A)}}),{passive:!1}),document.addEventListener("keydown",(g=>{if(activeGLRenderer!=this||!A())return;const I=new ZeaKeyboardEvent(g),C=activeGLRenderer.getActiveViewport();C&&C.onKeyDown(I)})),document.addEventListener("keyup",(g=>{if(activeGLRenderer!=this||!A())return;const I=new ZeaKeyboardEvent(g),C=activeGLRenderer.getActiveViewport();C&&C.onKeyUp(I)}))}getGLCanvas(){return this.glcanvas}frameAll(A=0,g=0,I=.1){this.#u[A].frameView([this.#r.getRoot()],g,I)}getOrCreateShader(A){let g=this.#G[A];return g||(g=Registry.constructClass(A),g||console.error("@GLBaseRenderer#getOrCreateShader - Shader not registered with the Registry:",A),g.setGLContext(this.__gl),this.#G[A]=g),g}addPass(A,g=-1){-1==g&&(g=A.getPassType()),this.#m[g]||(this.#m[g]=[]);let I=0;for(const A in this.#m){if(A==g.toString())break;I+=this.#m[A].length}I+=this.#m[g].length,A.on("updated",(A=>{this.requestRedraw(),this.renderGeomDataFbos()})),A.init(this,I),this.#m[g].push(A);let C=0;for(const A in this.#m){const g=this.#m[A];g.forEach(((A,g)=>{A.setPassIndex(C+g)})),C+=g.length}return this.#Z.push(A),this.requestRedraw(),I}getPass(A){let g=0;for(const I in this.#m){const C=this.#m[I];if(A-g<C.length)return C[A-g];g+=C.length}}findPassIndex(A){let g=0;for(const I in this.#m){const C=this.#m[I];for(let I=0;I<C.length;I++){if(C[I]instanceof A)return g;g++}}return-1}setupXRViewport(A){const g="immersive-ar"==A?new ARViewport(this,A):new VRViewport(this,A),I=A=>{this.emit("viewChanged",A)};return g.on("presentingChanged",(A=>{const C=A.state;if(this.xrViewportPresenting!=C)if(this.xrViewportPresenting=C,C){for(const A in this.#m){const g=this.#m[A];for(const A of g)A.startPresenting()}g.on("viewChanged",I)}else{g.off("viewChanged",I),this.emit("updated");for(const A in this.#m){const g=this.#m[A];for(const A of g)A.stopPresenting()}const A=this.getViewport().getCamera().globalXfoParam.value,C=new ViewChangedEvent("CameraAndPointer",A);this.emit("viewChanged",C),this.requestRedraw()}})),g}getVRViewport(){return this.xrViewport}getXRViewport(){return this.#p}isXRViewportPresenting(){return this.xrViewportPresenting}isContinuouslyDrawing(){return this.#E}startContinuousDrawing(){if(this.isContinuouslyDrawing()||this.xrViewportPresenting)return;const A=()=>{const g=new ColorRenderState(this.gl);this.#E&&!this.xrViewportPresenting&&window.requestAnimationFrame(A);for(const A of this.#u)A.draw(g)};this.#E=!0,requestPostAnimationFrame(A)}stopContinuousDrawing(){this.#E=!1}toggleContinuousDrawing(){this.#E?this.stopContinuousDrawing():this.startContinuousDrawing()}drawItemChanged(A){if(A)for(const A of this.#u)A.invalidateGeomDataBuffer();this.requestRedraw()}requestRedraw(){if(!this.__gl||this.#Q||this.#E||this.xrViewportPresenting||this.#V>0)return!1;if(this.__gl.isContextLost())return console.warn("WebGL Context Lost"),!1;const A=()=>{this.#Q=!1;const A=performance.now(),g=new ColorRenderState(this.gl);for(const A of this.#u)A.draw(g);0!=g.stack.length&&console.warn(" corrupt renderstate.stack.length:",g.stack.length);const I=performance.now();this.#R=I,this.#W=I-A};return requestAnimationFrame((()=>{const g=performance.now()-this.#R,I=Math.max(0,1e3/60-g-this.#W);setTimeout(A,I)})),this.#Q=!0,!0}forceRender(){if(!this.#Q)return void console.warn("@GlBaseRenderer#forceRender - Scene is not dirty");this.#Q=!1;const A=new ColorRenderState(this.gl);for(const g of this.#u)g.draw(A)}bindGLRenderer(A){A.gl=this.__gl,A.renderer=this,A.directives=this.directives,A.directivesHash=this.directivesHash}drawScene(A){A.directives=[...this.directives,"#define DRAW_COLOR"];for(const g in this.#m){const I=this.#m[g];for(const g of I)g.enabled&&g.draw(A)}}drawHighlightedGeoms(A){this.bindGLRenderer(A),A.directives=[...this.directives,"#define DRAW_HIGHLIGHT"];for(const g in this.#m){const I=this.#m[g];for(const g of I)g.enabled&&g.drawHighlightedGeoms(A)}}drawSceneGeomData(A,g=255){A.pushGLStack("GLBaseRenderer.drawSceneGeomData"),A.glEnable(this.__gl.DEPTH_TEST),A.glEnable(this.__gl.CULL_FACE),this.bindGLRenderer(A),A.directives=[...this.directives,"#define DRAW_GEOMDATA"],A.floatGeomBuffer=this.floatGeomBuffer;for(const I in this.#m){if(!(Number.parseInt(I)&g))continue;const C=this.#m[I];for(const g of C)g.enabled&&g.drawGeomData(A)}A.popGLStack()}static registerPass(A,g){registeredPasses.push({cls:A,passType:g})}destroy(A=!0){if(this.#S.disconnect(),window.removeEventListener("resize",this.#F),A){const A=this.__gl.getExtension("WEBGL_lose_context");A&&A.loseContext()}}}var frag$d="\nprecision highp float;\n#define GLSLIFY 1\n\nvarying vec2 v_texCoord;\n\nimport 'GLSLUtils.glsl'\nimport 'Hammersley.glsl'\nimport 'ImportanceSampleGGX.glsl'\n\nfloat GeometrySchlickGGX(float NdotV, float roughness)\n{\n  float a = roughness;\n  float k = (a * a) / 2.0;\n\n  float nom   = NdotV;\n  float denom = NdotV * (1.0 - k) + k;\n\n  return nom / denom;\n}\n// ----------------------------------------------------------------------------\nfloat GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)\n{\n  float NdotV = max(dot(N, V), 0.0);\n  float NdotL = max(dot(N, L), 0.0);\n  float ggx2 = GeometrySchlickGGX(NdotV, roughness);\n  float ggx1 = GeometrySchlickGGX(NdotL, roughness);\n\n  return ggx1 * ggx2;\n}\n\nvec2 IntegrateBRDF(float NdotV, float roughness)\n{\n  vec3 V;\n  V.x = sqrt(1.0 - NdotV*NdotV);\n  V.y = 0.0;\n  V.z = NdotV;\n\n  float A = 0.0;\n  float B = 0.0;\n\n  vec3 N = vec3(0.0, 0.0, 1.0);\n\n  for(uint i = 0u; i < SAMPLE_COUNT; ++i)\n  {\n    vec2 Xi = Hammersley(i, SAMPLE_COUNT);\n    vec3 H  = ImportanceSampleGGX(Xi, N, roughness);\n    vec3 L  = normalize(2.0 * dot(V, H) * H - V);\n\n    float NdotL = max(L.z, 0.0);\n    float NdotH = max(H.z, 0.0);\n    float VdotH = max(dot(V, H), 0.0);\n\n    if (NdotL > 0.0)\n    {\n      float G = GeometrySmith(N, V, L, roughness);\n      float G_Vis = (G * VdotH) / (NdotH * NdotV);\n      float Fc = pow(1.0 - VdotH, 5.0);\n\n      A += (1.0 - Fc) * G_Vis;\n      B += Fc * G_Vis;\n    }\n  }\n  A /= float(SAMPLE_COUNT);\n  B /= float(SAMPLE_COUNT);\n  return vec2(A, B);\n}\n\nout vec2 fragColor;\nvoid main(void) {\n  vec2 integratedBRDF = IntegrateBRDF(v_texCoord.x, v_texCoord.y);\n  fragColor = integratedBRDF;\n}\n\n",vert$e="\nprecision highp float;\n#define GLSLIFY 1\n\nimport 'quadVertexFromID.glsl'\n\n/* VS Outputs */\nvarying vec2 v_texCoord;\n \nvoid main()\n{\n  vec2 position = getQuadVertexPositionFromID();\n  v_texCoord = position+0.5;\n  gl_Position = vec4(position*2.0, 0.0, 1.0);\n}\n";class PreComputeBRDFShader extends GLShader{constructor(A){super(A,"PreComputeBRDFShader"),this.setShaderStage("VERTEX_SHADER",vert$e),this.setShaderStage("FRAGMENT_SHADER",frag$d)}}var frag$c="\nprecision highp float;\n#define GLSLIFY 1\nimport 'constants.glsl'\nimport 'convolve-helpers.glsl'\n\nuniform int faceId;\nvarying vec2 v_texCoord;\n\nout vec4 fragColor;\nvoid main(void) {\n\n  vec3 N = cubeFaceUvToDir(v_texCoord.x, v_texCoord.y, faceId);   \n\n  vec3 irradiance = vec3(0.0);\n\n  vec3 up        = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\n  vec3 tangent   = normalize(cross(up, N));\n  vec3 bitangent = cross(N, tangent);\n\n  float nrSamples = 0.0; \n  for(float phi = 0.0; phi < 2.0 * PI; phi += SAMPLE_DELTA)\n  {\n    for(float theta = 0.0; theta < 0.5 * PI; theta += SAMPLE_DELTA)\n    {\n      // spherical to cartesian (in tangent space)\n      // from spherical coordinates to cartesian coordinates\n      vec3 H = vec3(cos(phi) * sin(theta), sin(phi) * sin(theta), cos(theta));\n      // tangent space to world\n      vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;\n\n      irradiance += sampleEnvMap(normalize(sampleVec)).rgb * cos(theta) * sin(theta);\n      nrSamples++;\n    }\n  }\n  irradiance = PI * irradiance * (1.0 / float(nrSamples));\n\n  fragColor = vec4(irradiance, 1.0);\n}\n",vert$d="\nprecision highp float;\n#define GLSLIFY 1\n\nimport 'quadVertexFromID.glsl'\n\n/* VS Outputs */\nvarying vec2 v_texCoord;\n \nvoid main()\n{\n  vec2 position = getQuadVertexPositionFromID();\n  v_texCoord = position+0.5;\n  gl_Position = vec4(position*2.0, 0.0, 1.0);\n}\n";class ConvolveIrradianceShader extends GLShader{constructor(A){super(A,"ConvolveIrradianceShader"),this.setShaderStage("VERTEX_SHADER",vert$d),this.setShaderStage("FRAGMENT_SHADER",frag$c)}}var vert$c="\nprecision highp float;\n#define GLSLIFY 1\n\nimport 'quadVertexFromID.glsl'\n\n/* VS Outputs */\nvarying vec2 v_texCoord;\n \nvoid main()\n{\n  vec2 position = getQuadVertexPositionFromID();\n  v_texCoord = position+0.5;\n  gl_Position = vec4(position*2.0, 0.0, 1.0);\n}\n",frag$b="precision highp float;\nprecision highp int;\n#define GLSLIFY 1\n\nimport 'GLSLUtils.glsl'\nimport 'ImportanceSampleGGX.glsl'\nimport 'convolve-helpers.glsl'\nimport 'Hammersley.glsl'\n  \n\nuniform int faceId;\nuniform float roughness;\n\nvarying vec2 v_texCoord;\n\nout vec4 fragColor;\nvoid main(void) {\n\n  vec3 N = cubeFaceUvToDir(v_texCoord.x, v_texCoord.y, faceId);   \n\n  vec3 R = N;\n  vec3 V = R;\n\n  float totalWeight = 0.0;   \n  vec3 prefilteredColor = vec3(0.0);     \n  for(uint i = 0u; i < SAMPLE_COUNT; ++i)\n  {\n    vec2 Xi = Hammersley(i, SAMPLE_COUNT);\n    vec3 H  = ImportanceSampleGGX(Xi, N, roughness);\n    vec3 L  = normalize(2.0 * dot(V, H) * H - V);\n\n    float NdotL = max(dot(N, L), 0.0);\n    if (NdotL > 0.0)\n    {\n      prefilteredColor += sampleEnvMap(L).rgb * NdotL;\n      totalWeight      += NdotL;\n    }\n  }\n  prefilteredColor = prefilteredColor / totalWeight;\n\n  fragColor = vec4(prefilteredColor, 1.0);\n}\n";class ConvolveSpecularShader extends GLShader{constructor(A){super(A,"ConvolveSpecularShader"),this.setShaderStage("VERTEX_SHADER",vert$c),this.setShaderStage("FRAGMENT_SHADER",frag$b)}}class GLProbe extends EventEmitter{gl;textureDesc;maxFragmentShaderTextureUnits;textureType;convolved=!1;brdfLUTTexture;irradianceCubeTex;specularCubetex;constructor(A,g){super(),this.gl=A,this.maxFragmentShaderTextureUnits=A.getParameter(this.gl.MAX_TEXTURE_IMAGE_UNITS),this.gl.__quadVertexIdsBuffer||this.gl.setupInstancedQuad(),this.textureType=1,this.textureDesc=[0,0,0,0],this.convolved=!1}convolveProbe(A){const g=this.gl,I=new RenderState(g);I.directives=["#define ENABLE_ES3","#define ENABLE_FLOAT_TEXTURES"],"Low"==SystemDesc.deviceCategory?(I.directives.push("#define SAMPLE_DELTA 0.1"),I.directives.push("#define SAMPLE_COUNT 64u")):"Medium"==SystemDesc.deviceCategory?(I.directives.push("#define SAMPLE_DELTA 0.08"),I.directives.push("#define SAMPLE_COUNT 256u")):(I.directives.push("#define SAMPLE_DELTA 0.025"),I.directives.push("#define SAMPLE_COUNT 1024u")),this.brdfLUTTexture=g.createTexture(),g.bindTexture(g.TEXTURE_2D,this.brdfLUTTexture),g.texImage2D(g.TEXTURE_2D,0,g.RG16F,512,512,0,g.RG,g.HALF_FLOAT,null),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR);const C=new PreComputeBRDFShader(this.gl),e=C.compileForTarget("GLProbe",I.directives),i=generateShaderGeomBinding(this.gl,e.attrs,g.__quadattrbuffers,g.__quadIndexBuffer),t=g.createFramebuffer();g.bindFramebuffer(g.DRAW_FRAMEBUFFER,t),g.framebufferTexture2D(g.DRAW_FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,this.brdfLUTTexture,0),C.bind(I),i.bind(I),g.clear(g.COLOR_BUFFER_BIT|g.DEPTH_BUFFER_BIT),g.viewport(0,0,512,512),g.drawQuad(),g.bindFramebuffer(g.DRAW_FRAMEBUFFER,null),g.deleteFramebuffer(t),C.unbind(I),C.destroy();{const C=new ConvolveIrradianceShader(this.gl),e=C.compileForTarget("GLProbe",I.directives),i=generateShaderGeomBinding(this.gl,e.attrs,g.__quadattrbuffers,g.__quadIndexBuffer);C.bind(I,"GLProbe"),i.bind(I);const t=I.unifs;A.bindToUniform(I,t.envMap);const o=64;this.irradianceCubeTex=g.createTexture(),g.bindTexture(g.TEXTURE_CUBE_MAP,this.irradianceCubeTex),g.texParameteri(g.TEXTURE_CUBE_MAP,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_CUBE_MAP,g.TEXTURE_MIN_FILTER,g.LINEAR_MIPMAP_LINEAR),g.texParameteri(g.TEXTURE_CUBE_MAP,g.TEXTURE_WRAP_S,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_CUBE_MAP,g.TEXTURE_WRAP_T,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_CUBE_MAP,g.TEXTURE_WRAP_R,g.CLAMP_TO_EDGE);for(let A=0;A<6;A++)g.texImage2D(g.TEXTURE_CUBE_MAP_POSITIVE_X+A,0,g.RGBA16F,o,o,0,g.RGBA,g.HALF_FLOAT,null);const a=g.createFramebuffer();g.bindFramebuffer(g.DRAW_FRAMEBUFFER,a);for(let A=0;A<6;++A)g.uniform1i(t.faceId.location,A),g.framebufferTexture2D(g.DRAW_FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_CUBE_MAP_POSITIVE_X+A,this.irradianceCubeTex,0),g.viewport(0,0,o,o),g.clearColor(1,0,0,1),g.clear(g.COLOR_BUFFER_BIT|g.DEPTH_BUFFER_BIT),g.drawQuad();g.bindFramebuffer(g.DRAW_FRAMEBUFFER,null),g.deleteFramebuffer(a),g.generateMipmap(g.TEXTURE_CUBE_MAP)}{const C=new ConvolveSpecularShader(this.gl),e=C.compileForTarget("GLProbe",I.directives),i=generateShaderGeomBinding(this.gl,e.attrs,g.__quadattrbuffers,g.__quadIndexBuffer);C.bind(I,"GLProbe"),i.bind(I);const t=I.unifs;A.bindToUniform(I,t.envMap),this.specularCubetex=g.createTexture(),g.bindTexture(g.TEXTURE_CUBE_MAP,this.specularCubetex),g.texParameteri(g.TEXTURE_CUBE_MAP,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_CUBE_MAP,g.TEXTURE_MIN_FILTER,g.LINEAR_MIPMAP_LINEAR),g.texParameteri(g.TEXTURE_CUBE_MAP,g.TEXTURE_WRAP_S,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_CUBE_MAP,g.TEXTURE_WRAP_T,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_CUBE_MAP,g.TEXTURE_WRAP_R,g.CLAMP_TO_EDGE);const o=256;for(let A=0;A<6;A++)g.texImage2D(g.TEXTURE_CUBE_MAP_POSITIVE_X+A,0,g.RGBA16F,o,o,0,g.RGBA,g.HALF_FLOAT,null);g.generateMipmap(g.TEXTURE_CUBE_MAP);const a=5;for(let A=0;A<a;++A){const I=o*Math.pow(.5,A),C=o*Math.pow(.5,A),e=g.createFramebuffer();g.bindFramebuffer(g.DRAW_FRAMEBUFFER,e),g.viewport(0,0,I,C);const i=A/(a-1);g.uniform1f(t.roughness.location,i);for(let I=0;I<6;++I)g.uniform1i(t.faceId.location,I),g.framebufferTexture2D(g.DRAW_FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_CUBE_MAP_POSITIVE_X+I,this.specularCubetex,A),g.drawQuad();g.bindFramebuffer(g.DRAW_FRAMEBUFFER,null),g.deleteFramebuffer(e)}C.destroy()}this.convolved=!0}bind(A){const g=this.gl,{irradianceMap:I,prefilterMap:C,brdfLUT:e,envMapFlags:i}=A.unifs;if(!this.convolved)return I&&g.uniform1i(I.location,this.maxFragmentShaderTextureUnits-1),C&&g.uniform1i(C.location,this.maxFragmentShaderTextureUnits-1),i&&g.uniform1i(i.location,-1),!1;if(e){const I=A.boundTextures++;g.activeTexture(this.gl.TEXTURE0+I),g.bindTexture(g.TEXTURE_2D,this.brdfLUTTexture),g.uniform1i(e.location,I)}if(I){const C=A.boundTextures++,e=this.gl.TEXTURE0+C;g.activeTexture(e),g.bindTexture(g.TEXTURE_CUBE_MAP,this.irradianceCubeTex),g.uniform1i(I.location,C)}if(C){const I=A.boundTextures++,e=this.gl.TEXTURE0+I;g.activeTexture(e),g.bindTexture(g.TEXTURE_CUBE_MAP,this.specularCubetex),g.uniform1i(C.location,I)}return i&&g.uniform1i(i.location,0),!0}destroy(){}}var frag$a="\nprecision highp float;\n#define GLSLIFY 1\n\nimport 'GLSLUtils.glsl'\nimport 'gamma.glsl'\nimport 'constants.glsl'\n\nuniform float focus;\nuniform float exposure;\n\n/* VS Outputs */\nvarying vec3 v_worldDir;\nvarying vec2 v_texCoord;\n\n#define ENABLE_INLINE_GAMMACORRECTION\n\n#define ENV_MAP_LATLONG 0\n#define ENV_MAP_OCT 1\n#define ENV_MAP_CUBE 2\n#define ENV_MAP_irradianceMap 8\n#define ENV_MAP_prefilterMap 3\n#define ENV_MAP_STEREO_LATLONG 4\n#define ENV_MAP_DUALFISHEYE 5\n#define ENV_MAP_SH 6\n#define ENV_MAP_BRDF_LUT 7\n\n#define ENV_MAPTYPE ENV_MAP_OCT\n\n#if (ENV_MAPTYPE == ENV_MAP_LATLONG)  \n\nimport 'envmap-equirect.glsl'\n\nuniform sampler2D backgroundImage;\n\nvec4 sampleEnvMap(vec3 dir) {\n  vec2 uv = latLongUVsFromDir(normalize(dir));\n  vec4 texel = texture2D(backgroundImage, uv) * exposure;\n  return vec4(texel.rgb/texel.a, 1.0);\n}\n\n#elif (ENV_MAPTYPE == ENV_MAP_OCT)  \n\nimport 'envmap-octahedral.glsl'\n\nuniform sampler2D   envMap;\n\nvec4 sampleEnvMap(vec3 dir) {\n  vec2 uv = dirToSphOctUv(normalize(dir));\n  if (false) {\n    vec4 texel = texture2D(envMap, uv);\n    return vec4(texel.rgb/texel.a, 1.0);\n  }\n  else {\n    return texture2D(envMap, uv) * exposure;\n  }\n}\n\n#elif (ENV_MAPTYPE == ENV_MAP_CUBE)\n\nuniform samplerCube cubeMap;\n\nvec4 sampleEnvMap(vec3 dir) {\n  return texture(cubeMap, dir, 0.0);// * exposure;\n  // return textureLod(cubeMap, dir, exposure);\n}\n\n#elif (ENV_MAPTYPE == ENV_MAP_irradianceMap)\n\nuniform samplerCube irradianceMap;\n\nvec4 sampleEnvMap(vec3 dir) {\n  return textureLod(irradianceMap, dir, exposure);\n}\n\n#elif (ENV_MAPTYPE == ENV_MAP_prefilterMap)\n\nuniform samplerCube prefilterMap;\n\nvec4 sampleEnvMap(vec3 dir) {\n  return textureLod(prefilterMap, dir, exposure);\n}\n\n#elif (ENV_MAPTYPE == ENV_MAP_STEREO_LATLONG)  \n\nimport 'envmap-equirect.glsl'\nuniform int eye;// L = 0, R = 1;\nuniform sampler2D backgroundImage;\n\nvec4 sampleEnvMap(vec3 dir) {\n  vec2 uv = latLongUVsFromDir(normalize(v_worldDir));\n  uv.y *= 0.5;\n  if (eye == 1) {\n    uv.y += 0.5;\n  }\n  vec4 texel = texture2D(backgroundImage, uv) * exposure;\n  fragColor = vec4(texel.rgb/texel.a, 1.0);\n}\n\n#elif (ENV_MAPTYPE == ENV_MAP_DUALFISHEYE)\n\nimport 'envmap-dualfisheye.glsl'\n\nvec4 sampleEnvMap(vec3 dir) {\n  vec2 uv = dualfisheyeUVsFromDir(dir);\n  return texture2D(backgroundImage, uv) * exposure;\n}\n\n#elif (ENV_MAPTYPE == ENV_MAP_SH)\n\nimport 'SHCoeffs.glsl'\n\nvec4 sampleEnvMap(vec3 dir) {\n\treturn vec4(sampleSHCoeffs(dir) * exposure, 1.0);\n}\n\n#elif (ENV_MAPTYPE == ENV_MAP_BRDF_LUT)\n\nuniform sampler2D brdfLUT;\n\nvec4 sampleEnvMap(vec3 dir) {\n  return texture2D(brdfLUT, v_texCoord);\n}\n#endif\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\n\nvoid main(void) {\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  fragColor = sampleEnvMap(normalize(v_worldDir));\n  fragColor.a = 1.0;\n\n#ifdef ENABLE_INLINE_GAMMACORRECTION\n  fragColor.rgb = toGamma(fragColor.rgb);\n#endif\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n",vert$b="\nprecision highp float;\n#define GLSLIFY 1\n\nimport 'quadVertexFromID.glsl'\n\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\n\nimport 'inverse.glsl'\nimport 'transpose.glsl'\n\n/* VS Outputs */\nvarying vec3 v_worldDir;\nvarying vec2 v_texCoord;\n \nvoid main()\n{\n  vec2 position = getQuadVertexPositionFromID() * 2.0;\n  v_texCoord = position * 0.5 + 0.5;\n\n  mat4 inverseProjection = inverse(projectionMatrix);\n  mat3 inverseModelview = transpose(mat3(viewMatrix));\n\n  // transform from the normalized device coordinates back to the view space\n  vec3 unprojected = (inverseProjection * vec4(position, 0, 1)).xyz;\n\n  // transfrom from the view space back to the world space\n  // and use it as a sampling vector\n  v_worldDir = inverseModelview * unprojected;\n\n  gl_Position = vec4(position, 0, 1);\n}\n";class EnvMapShader extends GLShader{constructor(A){super(A,"EnvMapShader"),this.setShaderStage("VERTEX_SHADER",vert$b),this.setShaderStage("FRAGMENT_SHADER",frag$a)}}class GLEnvMap extends GLProbe{renderer;envMap;backgroundFocus;srcGLTex=null;envMapShader=null;envMapShaderBinding=null;constructor(A,g){super(A.gl,"EnvMap"),this.renderer=A,this.envMap=g,this.backgroundFocus=0,this.envMap.isLoaded()?this.init():this.envMap.once("loaded",(A=>{this.init()}))}get glTex(){return this.srcGLTex}init(){const A=this.renderer.gl;A.__quadVertexIdsBuffer||A.setupInstancedQuad(),this.srcGLTex=new GLHDRImage(A,this.envMap),this.envMapShader=new EnvMapShader(A);const g=this.envMapShader.compileForTarget("GLEnvMap",["#define ENABLE_ES3"]);this.envMapShaderBinding=generateShaderGeomBinding(A,g.attrs,A.__quadattrbuffers,A.__quadIndexBuffer);const I=this.envMap.headlightModeParam,C=()=>{I.value?this.textureDesc[3]|=1:this.textureDesc[3]&=-2};C(),I.on("valueChanged",(()=>{C(),this.emit("updated")})),this.convolveProbe(this.srcGLTex),this.emit("updated")}getEnvMap(){return this.envMap}getBackgroundFocus(){return this.backgroundFocus}setBackgroundFocus(A){this.backgroundFocus=A,this.renderer.requestRedraw()}draw(A){if(this.envMap.isLoaded()){const g=this.gl;{this.envMapShader.bind(A,"GLEnvMap");const I=A.unifs,{envMap:C,focus:e,exposure:i}=A.unifs;C&&this.srcGLTex.bindToUniform(A,C),e&&g.uniform1f(e.location,this.backgroundFocus),i&&g.uniform1f(i.location,A.exposure),this.envMapShaderBinding.bind(A),g.depthMask(!1),A.bindViewports(I,(()=>{g.drawQuad()})),g.depthMask(!0)}}}destroy(){super.destroy(),this.srcGLTex&&this.srcGLTex.destroy()}}const ALL_PASSES=PassType.OPAQUE|PassType.TRANSPARENT|PassType.OVERLAY;class GLRenderer extends GLBaseRenderer{#w=1;#H=2.2;#X=null;#Y;#K;highlightOutlineThickness=1;renderMode="pbr";outlineMethod="geometry";outlineThickness=0;outlineColor=new Color(.15,.15,.15,1);hiddenLineColor=new Color(.15,.15,.15,0);outlineSensitivity=2;outlineDepthBias=.7;#N;#v;#J=null;#f=null;#L=null;#M=new Mat4;constructor(A,g={}){super(A,g),this.#w=1,this.#H=2.2,this.#K=!0,this.#N=0,this.#v=0,this.setShaderPreprocessorDirective("ENABLE_GAMMACORRECTION","#define ENABLE_INLINE_GAMMACORRECTION"),g.disableTextures||this.setShaderPreprocessorDirective("ENABLE_TEXTURES","#define ENABLE_TEXTURES"),g.debugGeomIds&&this.setShaderPreprocessorDirective("DEBUG_GEOM_ID","#define DEBUG_GEOM_ID")}__bindEnvMap(A){const g=this.__gl;if(!(A instanceof EnvMap)){const I=A;if("HDR"===I.type?this.#Y=new GLHDRImage(this.__gl,I):this.#Y=new GLTexture2D(this.__gl,I),this.#Y.on("loaded",(()=>{this.requestRedraw()})),this.#Y.on("updated",(()=>{this.requestRedraw()})),!this.#f){g.__quadVertexIdsBuffer||g.setupInstancedQuad(),this.#f=new EnvMapShader(this.__gl);const A=this.#f.compileForTarget("key",[]);this.#L=generateShaderGeomBinding(this.__gl,A.attrs,g.__quadattrbuffers,g.__quadIndexBuffer)}return}if("webgl2"!==g.name)return;"FLOAT"===A.type&&(this.setShaderPreprocessorDirective("ENABLE_PBR","#define ENABLE_PBR"),this.#X=new GLEnvMap(this,A)),this.#X.on("loaded",(A=>{this.requestRedraw()})),this.#X.on("updated",(A=>{this.requestRedraw()}));const I=new EnvMapAssignedEvent(this.#X);this.emit("envMapAssigned",I)}setScene(A){const g=A.envMapParam;null!=g.value&&this.__bindEnvMap(g.value),g.on("valueChanged",(()=>{this.__bindEnvMap(g.value)}));const I=A.displayEnvMapParam;this.#K=I.value,I.on("valueChanged",(()=>{this.#K=I.value,this.requestRedraw()})),super.setScene(A)}addViewport(A){return super.addViewport(A)}get exposure(){return this.#w}set exposure(A){this.#w=A,this.requestRedraw()}get gamma(){return this.#H}set gamma(A){this.#H=A,this.requestRedraw()}get displayEnvironment(){return this.#K}set displayEnvironment(A){this.#K=A,this.requestRedraw()}bindRaycastViewport(A,g,I){A.viewXfo=g,A.cameraMatrix=g.toMat4(),A.viewScale=1,A.region=[0,0,3,3];const C=A.cameraMatrix.inverse(),e=this.gl;A.bindRendererUnifs=g=>{const{cameraMatrix:i,viewMatrix:t,projectionMatrix:o,eye:a,isOrthographic:B,viewportFrustum:s}=g;i&&e.uniformMatrix4fv(i.location,!1,A.cameraMatrix.asArray()),t&&e.uniformMatrix4fv(t.location,!1,C.asArray()),o&&e.uniformMatrix4fv(o.location,!1,I.asArray()),a&&e.uniform1i(a.location,0),B&&e.uniform1i(B.location,1)},A.bindViewports=(A,g)=>g()}raycastWithRay(A,g,I=.01,C=ALL_PASSES){const e=new Xfo;return e.setLookAt(A.start,A.start.add(A.dir),new Vec3(0,0,1)),this.raycast(e,A,g,I,C)}raycastWithXfo(A,g,I=.01,C=ALL_PASSES){const e=new Ray(A.tr,A.ori.getZaxis().negate());return this.raycast(A,e,g,I,C)}raycast(A,g,I,C=.01,e=ALL_PASSES){return this.#N==I&&this.#v==C||(this.#M.setOrthographicMatrix(-.5*C,.5*C,-.5*C,.5*C,0,I),this.#N=I,this.#v=C),this.raycastWithProjection(A,this.#M,g,e)}raycastWithProjection(A,g,I,C=ALL_PASSES){const e=new GeomDataRenderState(this.__gl);this.bindRaycastViewport(e,A,g);const i=this.__gl;this.#J||(this.#J=new GLRenderTarget(i,{type:i.FLOAT,format:i.RGBA,filter:i.NEAREST,createDepthTexture:!0,width:3,height:3,numColorChannels:1})),this.#J.bindForWriting(e,!0),i.enable(i.CULL_FACE),i.enable(i.DEPTH_TEST),i.depthFunc(i.LEQUAL),i.depthMask(!0),this.drawSceneGeomData(e,C),i.finish(),this.#J.unbindForWriting(),this.#J.bindForReading();const t=new Float32Array(36);i.readPixels(0,0,3,3,i.RGBA,i.FLOAT,t),this.#J.unbindForReading();const o=[4,3,5,1,7];let a;for(const A of o)if(0!=t[4*A+3]){a=t.subarray(4*A,4*A+4);break}if(!a)return null;const B=63&Math.round(a[0]),s=this.getPass(B)?.getGeomItemAndDist(a);if(s){const A=I.start.add(I.dir.scale(s.dist));return{pointerRay:I,intersectionPos:A,geomItem:s.geomItem,componentId:-1,dist:s.dist,geomData:a}}return null}raycastCluster(A,g,I,C=.01,e=ALL_PASSES){const i=this.__gl,t=new GeomDataRenderState(this.__gl);this.bindRaycastViewport(t,A,this.#M),this.#J||(this.#J=new GLRenderTarget(i,{type:"FLOAT",format:"RGBA",filter:"NEAREST",createDepthTexture:!0,width:3,height:3,numColorChannels:1}),this.#M=new Mat4),this.#N==I&&this.#v==C||(this.#M.setOrthographicMatrix(-.5*C,.5*C,-.5*C,.5*C,0,I),this.#N=I,this.#v=C),this.#J.bindForWriting(t,!0),i.enable(i.CULL_FACE),i.enable(i.DEPTH_TEST),i.depthFunc(i.LEQUAL),i.depthMask(!0),this.drawSceneGeomData(t,e),i.finish(),this.#J.unbindForWriting(),this.#J.bindForReading();const o=new Float32Array(36);i.readPixels(0,0,3,3,i.RGBA,i.FLOAT,o),this.#J.unbindForReading();const a=[];for(let A=0;A<9;A++)if(0!=o[4*A+3]){const I=o.subarray(4*A,4*A+4),C=63&Math.round(I[0]),e=this.getPass(C);if(e){const A=e.getGeomItemAndDist(I);if(A){const C=g.start.add(g.dir.scale(A.dist));a.push({pointerRay:g,intersectionPos:C,geomItem:A.geomItem,componentId:-1,dist:A.dist,geomData:I})}}}return a}drawBackground(A){if(this.#Y&&this.#f&&this.#L){if(!this.#Y.isLoaded())return;const g=this.__gl;g.depthMask(!1),this.#f.bind(A);const I=A.unifs;this.#Y.bindToUniform(A,I.backgroundImage),this.#L.bind(A),g.drawQuad()}else this.#X&&this.#X.draw&&this.#X.draw(A)}bindGLRenderer(A){super.bindGLRenderer(A),A instanceof ColorRenderState&&(A.envMap=this.#X,A.exposure=this.#w,A.renderMode=this.renderMode,A.outlineThickness=this.outlineThickness,A.outlineColor=this.outlineColor,A.hiddenLineColor=this.hiddenLineColor,A.outlineMethod=this.outlineMethod,A.screenQuad=this.screenQuad)}drawScene(A){this.bindGLRenderer(A),this.#K&&this.drawBackground(A),super.drawScene(A)}}class GLGeomItemSetMultiDraw extends EventEmitter{renderer;gl;glGeomItems=[];glGeomIdsMapping={};glgeomItemEventHandlers=[];freeIndices=[];viewPos=new Vec3;drawElementCounts=new Int32Array(0);drawElementOffsets=new Int32Array(0);highlightElementCounts=new Int32Array(0);highlightElementOffsets=new Int32Array(0);drawOrderToIndex=[];indexToDrawIndex=[];drawIdsArray=new Float32Array(0);drawIdsBufferDirty=!0;drawIdsTexture=null;highlightedItems=[];highlightedIdsArray=null;highlightedIdsTexture=null;highlightedIdsBufferDirty=!1;dirtyGeomIndices=new Set;constructor(A){super(),this.renderer=A,this.gl=A.gl,this.renderer.glGeomLibrary.on("geomDataChanged",(A=>{null!=this.glGeomIdsMapping[A.index]&&this.dirtyGeomIndices.add(A.index)}))}addGLGeomItem(A){const g=this.freeIndices.length>0?this.freeIndices.pop():this.glGeomItems.length;this.indexToDrawIndex[g]=this.drawOrderToIndex.length,this.drawOrderToIndex.push(g);const I={};I.visibilityChanged=I=>{const C=this.indexToDrawIndex[g];if(I.state){const g=this.renderer.glGeomLibrary.getGeomOffsetAndCount(A.geomId);this.drawElementCounts[C]=g[1]}else this.drawElementCounts[C]=0;this.emit("updated")},A.on("visibilityChanged",I.visibilityChanged),A.geomItem.isHighlighted()&&(this.highlightedItems.push(A),this.highlightedIdsBufferDirty=!0),I.highlightChanged=g=>{if(g&&g.name){if(this.highlightedItems.includes(A))return;this.highlightedItems.push(A)}else this.highlightedItems.splice(this.highlightedItems.indexOf(A),1);this.highlightedIdsBufferDirty=!0,this.emit("updated")},A.geomItem.on("highlightChanged",I.highlightChanged);let C=A.geomItem.geomParam.value;A.geomId=this.renderer.glGeomLibrary.addGeom(C),this.glGeomIdsMapping[A.geomId]?this.glGeomIdsMapping[A.geomId].push(g):this.glGeomIdsMapping[A.geomId]=[g],this.glGeomItems[g]=A,this.glgeomItemEventHandlers[g]=I,this.drawIdsBufferDirty=!0,this.emit("updated")}removeGLGeomItem(A){const g=this.glGeomItems.indexOf(A),I=this.renderer.glGeomLibrary.getGeom(A.geomId);this.renderer.glGeomLibrary.removeGeom(I);const C=this.glGeomIdsMapping[A.geomId];C.splice(C.indexOf(g),1),0==C.length&&(delete this.glGeomIdsMapping[A.geomId],this.dirtyGeomIndices.has(A.geomId)&&this.dirtyGeomIndices.delete(A.geomId));const e=this.glgeomItemEventHandlers[g];A.geomItem.off("highlightChanged",e.highlightChanged),A.off("visibilityChanged",e.visibilityChanged),this.glGeomItems[g]=null,this.glgeomItemEventHandlers[g]=null,this.drawIdsArray[g]=0,this.freeIndices.push(g);const i=this.drawOrderToIndex.indexOf(g);if(this.drawOrderToIndex.splice(i,1),this.indexToDrawIndex[g]=-1,this.drawElementOffsets[i]=0,this.drawElementCounts[i]=0,this.drawIdsBufferDirty=!0,A.geomItem.isHighlighted()){const g=this.highlightedItems.indexOf(A);this.highlightedItems.splice(g,1),this.highlightedIdsBufferDirty=!0}this.emit("updated")}cleanGeomIds(){this.dirtyGeomIndices.forEach((A=>{const g=this.glGeomIdsMapping[A];if(null!=g){const I=this.renderer.glGeomLibrary.getGeomOffsetAndCount(A);g.forEach((A=>{const g=this.glGeomItems[A];if(g.isVisible()){const C=this.indexToDrawIndex[A];this.drawElementOffsets[C]=I[0],this.drawElementCounts[C]=I[1],this.drawIdsArray[C]=g.geomItemId;const e=this.highlightedItems.indexOf(g);-1!=e&&(this.highlightElementOffsets[e]=I[0],this.highlightElementCounts[e]=I[1])}}))}})),this.dirtyGeomIndices=new Set}updateDrawIDsBuffer(A){(!this.drawIdsArray||this.drawOrderToIndex.length>this.drawIdsArray.length)&&(this.drawIdsArray=new Float32Array(this.drawOrderToIndex.length),this.drawElementOffsets=new Int32Array(this.drawOrderToIndex.length+1),this.drawElementCounts=new Int32Array(this.drawOrderToIndex.length+1)),this.drawOrderToIndex.forEach(((A,g)=>{const I=this.glGeomItems[A];if(!I)return;const C=this.renderer.glGeomLibrary.getGeomOffsetAndCount(I.geomId);this.drawElementOffsets[g]=C[0],this.drawElementCounts[g]=I.isVisible()?C[1]:0,this.drawIdsArray[g]=I.geomItemId,this.indexToDrawIndex[A]=g})),this.dirtyGeomIndices=new Set;const g=this.renderer.gl,I=A.boundTextures++;g.activeTexture(g.TEXTURE0+I);const C=2*MathFunctions.nextPow2(Math.ceil(Math.sqrt(this.drawOrderToIndex.length)));this.drawIdsTexture?(this.drawIdsTexture.width<C||this.drawIdsTexture.height<C)&&this.drawIdsTexture.resize(C,C):this.drawIdsTexture=new GLTexture2D(this.gl,{format:this.gl.RED,type:this.gl.FLOAT,width:C,height:C,filter:this.gl.NEAREST,wrap:this.gl.CLAMP_TO_EDGE,mipMapped:!1});{const A=this.drawIdsTexture,I=this.drawIdsTexture.width;g.bindTexture(g.TEXTURE_2D,A.glTex);const C=0,e=0,i=1,t=A.format,o=A.type,a=Math.ceil((e+this.drawOrderToIndex.length)/I);let B=0,s=this.drawOrderToIndex.length,l=e;for(let A=0;A<a;A++){let A;l+s>I?(A=I-l,l=0):A=s;const e=B%I,a=Math.floor(B/I),n=this.drawIdsArray.subarray(B,B+A);g.texSubImage2D(g.TEXTURE_2D,C,e,a,A,i,t,o,n),B+=A,s-=A}}g.bindTexture(g.TEXTURE_2D,null),A.boundTextures--,this.drawIdsBufferDirty=!1}updateHighlightedIDsBuffer(A){if(this.highlightedIdsBufferDirty){(!this.highlightedIdsArray||this.highlightedItems.length>this.highlightedIdsArray.length)&&(this.highlightedIdsArray=new Float32Array(this.highlightedItems.length),this.highlightElementOffsets=new Int32Array(this.highlightedItems.length+1),this.highlightElementCounts=new Int32Array(this.highlightedItems.length+1)),this.highlightedItems.forEach(((A,g)=>{this.highlightedIdsArray[g]=A.geomItemId;const I=this.renderer.glGeomLibrary.getGeomOffsetAndCount(A.geomId);this.highlightElementOffsets[g]=I[0],this.highlightElementCounts[g]=I[1]}));for(let A=this.highlightedItems.length;A<this.highlightElementCounts.length;A++)this.highlightElementOffsets[A]=0,this.highlightElementCounts[A]=0;this.highlightedIdsBufferDirty=!1}const g=this.renderer.gl,I=A.boundTextures++;g.activeTexture(g.TEXTURE0+I);const C=MathFunctions.nextPow2(Math.ceil(Math.sqrt(this.highlightedItems.length)));this.highlightedIdsTexture?(this.highlightedIdsTexture.width<C||this.highlightedIdsTexture.height<C)&&this.highlightedIdsTexture.resize(C,C):this.highlightedIdsTexture=new GLTexture2D(this.gl,{format:this.gl.RED,type:this.gl.FLOAT,width:C,height:C,filter:this.gl.NEAREST,wrap:this.gl.CLAMP_TO_EDGE,mipMapped:!1});{const A=this.highlightedIdsTexture,I=this.highlightedIdsTexture.width;g.bindTexture(g.TEXTURE_2D,A.glTex);const C=0,e=0,i=1,t=A.format,o=A.type,a=Math.ceil((e+this.highlightedIdsArray.length)/I);let B=0,s=this.highlightedIdsArray.length,l=e;for(let A=0;A<a;A++){let A;l+s>I?(A=I-l,l=0):A=s;const e=B%I,a=Math.floor(B/I),n=this.highlightedIdsArray.subarray(B,B+A);g.texSubImage2D(g.TEXTURE_2D,C,e,a,A,i,t,o,n),B+=A,s-=A}}g.bindTexture(g.TEXTURE_2D,null),A.boundTextures--}draw(A){if(this.drawIdsBufferDirty?this.updateDrawIDsBuffer(A):this.dirtyGeomIndices.size>0&&this.cleanGeomIds(),0!=this.drawIdsArray.length){if(this.drawIdsTexture){const{drawIdsTexture:g}=A.unifs;this.drawIdsTexture.bindToUniform(A,g)}this.bindAndRender(A,this.drawElementCounts,this.drawElementOffsets,this.drawOrderToIndex.length)}}drawHighlighted(A){if(0!=this.highlightedItems.length){if(this.highlightedIdsBufferDirty&&this.updateHighlightedIDsBuffer(A),this.highlightedIdsTexture){const{drawIdsTexture:g}=A.unifs;this.highlightedIdsTexture.bindToUniform(A,g)}this.bindAndRender(A,this.highlightElementCounts,this.highlightElementOffsets,this.highlightedItems.length)}}drawGeomData(A){if(this.drawIdsBufferDirty&&this.updateDrawIDsBuffer(A),0!=this.drawOrderToIndex.length){if(this.drawIdsTexture){const{drawIdsTexture:g}=A.unifs;this.drawIdsTexture.bindToUniform(A,g)}this.bindAndRender(A,this.drawElementCounts,this.drawElementOffsets,this.drawOrderToIndex.length)}}bindAndRender(A,g,I,C){const e=this.gl,i=A.unifs;i.instancedDraw&&e.uniform1i(A.unifs.instancedDraw.location,1),A.bindViewports(i,(()=>{this.multiDraw(A,g,I,C)}))}sortItems(A){const g=new Float32Array(this.drawOrderToIndex.length);this.drawOrderToIndex.forEach((I=>{const C=this.glGeomItems[I];if(C){const e=C.geomItem.boundingBoxParam.value,i=e.center(),t=e.size(),o=i.distanceTo(A)-t;g[I]=o}})),this.drawOrderToIndex.sort(((A,I)=>g[I]-g[A])),this.drawOrderToIndex.forEach(((A,g)=>{const I=this.glGeomItems[A];I&&(this.drawIdsArray[g]=I.geomItemId,this.indexToDrawIndex[A]=g)})),this.drawIdsBufferDirty=!0,this.viewPos=A}destroy(){this.drawIdsTexture&&this.drawIdsTexture.destroy(),this.highlightedIdsTexture&&this.highlightedIdsTexture.destroy(),this.emit("destructing")}}class GLPointsItemSet extends GLGeomItemSetMultiDraw{multiDraw(A,g,I,C){const e=this.gl;if(e.multiDrawArrays)e.multiDrawArrays(e.POINTS,I,0,g,0,C);else{const{drawId:i}=A.unifs;for(let A=0;A<C;A++)e.uniform1i(i.location,A),e.drawArrays(e.POINTS,I[A],g[A])}}}class GLLinesItemSet extends GLGeomItemSetMultiDraw{multiDraw(A,g,I,C){const{occluded:e,hiddenLineColor:i}=A.unifs,t=A.hiddenLineColor&&A.hiddenLineColor.a>0&&e&&i,o=this.gl;if(o.multiDrawArrays)o.multiDrawElements(o.LINES,g,0,o.UNSIGNED_INT,I,0,C),t&&(o.uniform1i(e.location,1),o.uniform4fv(i.location,A.hiddenLineColor.asArray()),o.depthFunc(o.GREATER),o.depthMask(!1),o.multiDrawElements(o.LINES,g,0,o.UNSIGNED_INT,I,0,C),o.depthFunc(o.LEQUAL),o.depthMask(!0),o.uniform1i(e.location,0));else{const{drawId:a}=A.unifs;for(let A=0;A<C;A++)o.uniform1i(a.location,A),o.drawElements(o.LINES,g[A],o.UNSIGNED_INT,I[A]);if(t){o.uniform1i(e.location,1),o.uniform4fv(i.location,A.hiddenLineColor.asArray()),o.depthFunc(o.GREATER),o.depthMask(!1);for(let A=0;A<C;A++)o.uniform1i(a.location,A),o.drawElements(o.LINES,g[A],o.UNSIGNED_INT,I[A]);o.depthFunc(o.LEQUAL),o.depthMask(!0),o.uniform1i(e.location,0)}}}}var GeomType$1;!function(A){A[A.TRIANGLES=0]="TRIANGLES",A[A.LINES=1]="LINES",A[A.POINTS=2]="POINTS"}(GeomType$1||(GeomType$1={}));class GLMeshItemSet extends GLGeomItemSetMultiDraw{multiDraw(A,g,I,C){const e=this.gl,i=()=>{if(e.multiDrawElements)e.multiDrawElements(e.TRIANGLES,g,0,e.UNSIGNED_INT,I,0,C);else{const{drawId:i}=A.unifs;for(let A=0;A<C;A++)e.uniform1i(i.location,A),e.drawElements(e.TRIANGLES,g[A],e.UNSIGNED_INT,I[A])}},{geomType:t,outlineThickness:o,viewportSize:a,renderMode:B}=A.unifs,s=A instanceof ColorRenderState&&B?A.renderMode:null,l=A instanceof ColorRenderState&&o&&a&&"geometry"==A.outlineMethod&&A.outlineThickness>0&&"flat-noedges"!=s&&"pbr-noedges"!=s,n=l&&"wireframe"==s;if(n?(e.enable(e.STENCIL_TEST),e.clearStencil(0),e.clear(e.STENCIL_BUFFER_BIT),e.stencilOpSeparate(e.FRONT,e.DECR_WRAP,e.DECR_WRAP,e.DECR_WRAP),e.stencilOpSeparate(e.BACK,e.INCR_WRAP,e.INCR_WRAP,e.INCR_WRAP),e.stencilFunc(e.ALWAYS,0,255),e.enable(e.CULL_FACE),e.cullFace(e.BACK),e.disable(e.DEPTH_TEST),e.depthMask(!1),e.colorMask(!1,!1,!1,!1)):"hiddenline"==s&&e.colorMask(!1,!1,!1,!0),t&&e.uniform1i(t.location,GeomType$1.TRIANGLES),o&&e.uniform1f(o.location,0),i(),l){const g=A;if(e.enable(e.CULL_FACE),e.cullFace(e.FRONT),e.uniform1f(o.location,g.outlineThickness*window.devicePixelRatio),e.uniform2f(a.location,A.region[2]-A.region[0],A.region[3]-A.region[1]),"hiddenline"==s&&e.colorMask(!0,!0,!0,!0),n||(e.enable(e.BLEND),e.blendEquation(e.FUNC_ADD),e.blendFuncSeparate(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE)),i(),e.disable(e.CULL_FACE),e.cullFace(e.BACK),n){e.enable(e.DEPTH_TEST),e.depthMask(!0),e.colorMask(!0,!0,!0,!0),e.stencilFunc(e.NOTEQUAL,0,255),e.stencilOp(e.KEEP,e.KEEP,e.KEEP),e.enable(e.BLEND),e.blendEquation(e.FUNC_ADD),e.blendFuncSeparate(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE);const A=g.glShader,I=g.shaderkey,C=g.screenQuad;C.bindShader(g),C.draw(g,g.outlineColor),A.bind(g,I),this.renderer.glGeomItemLibrary.bind(g),this.renderer.glGeomLibrary.bind(g),this.renderer.glMaterialLibrary.bind(g),e.disable(e.STENCIL_TEST)}}}}class GLGeomItemSet extends EventEmitter{gl;glGeom;id;glGeomItems;glgeomItems_freeIndices;glgeomItemEventHandlers;drawIdsArray=null;drawIdsBuffer=null;drawIdsBufferDirty;highlightedIdsArray=null;highlightedIdsBuffer=null;highlightedIdsBufferDirty;visibleItems;highlightedItems;constructor(A,g){super(),this.gl=A,this.glGeom=g,this.id=g?g.getGeom().getId():this.getId(),this.glGeomItems=[],this.glgeomItems_freeIndices=[],this.glgeomItemEventHandlers=[],this.drawIdsArray=null,this.drawIdsBuffer=null,this.drawIdsBufferDirty=!0,this.highlightedIdsArray=null,this.highlightedIdsBuffer=null,this.highlightedIdsBufferDirty=!0,this.visibleItems=[],this.highlightedItems=[]}getGLGeom(){return this.glGeom}getDrawCount(){return this.visibleItems.length}addGLGeomItem(A){let g;if(this.glgeomItems_freeIndices.length>0?g=this.glgeomItems_freeIndices.pop():(g=this.glGeomItems.length,this.glGeomItems.push(null)),A.geomItem.isVisible()){this.visibleItems.push(g);const A=new CountChangedEvent(1,this.visibleItems.length);this.emit("drawCountChanged",A)}A.geomItem.isHighlighted()&&(this.highlightedItems.push(g),this.highlightedIdsBufferDirty=!0);const I={};I.highlightChanged=I=>{if(A.geomItem.isHighlighted()){if(this.highlightedItems.includes(g))return;this.highlightedItems.push(g);const A=new CountChangedEvent(1,this.highlightedItems.length);this.emit("highlightedCountChanged",A)}else{this.highlightedItems.splice(this.highlightedItems.indexOf(g),1);const A=new CountChangedEvent(-1,this.highlightedItems.length);this.emit("highlightedCountChanged",A)}this.highlightedIdsBufferDirty=!0},A.geomItem.on("highlightChanged",I.highlightChanged),I.visibilityChanged=A=>{if(A.state){this.visibleItems.push(g);const A=new CountChangedEvent(1,this.visibleItems.length);this.emit("drawCountChanged",A)}else{this.visibleItems.splice(this.visibleItems.indexOf(g),1);const A=new CountChangedEvent(-1,this.visibleItems.length);this.emit("drawCountChanged",A)}this.drawIdsBufferDirty=!0},A.geomItem.on("visibilityChanged",I.visibilityChanged),this.glGeomItems[g]=A,this.glgeomItemEventHandlers[g]=I,this.drawIdsBufferDirty=!0,A.GLGeomItemSet=this}removeGLGeomItem(A){const g=this.glGeomItems.indexOf(A),I=this.glgeomItemEventHandlers[g];if(A.geomItem.off("highlightChanged",I.highlightChanged),A.geomItem.off("visibilityChanged",I.visibilityChanged),this.glGeomItems[g]=null,this.glgeomItemEventHandlers[g]=null,A.GLGeomItemSet=null,this.glgeomItems_freeIndices.push(g),A.geomItem.isVisible()){this.visibleItems.splice(this.visibleItems.indexOf(g),1);const A=new CountChangedEvent(-1,this.visibleItems.length);this.emit("drawCountChanged",A)}if(A.geomItem.isHighlighted()){this.highlightedItems.splice(this.highlightedItems.indexOf(g),1);const A=new CountChangedEvent(-1,this.highlightedItems.length);this.emit("highlightedCountChanged",A)}this.drawIdsBufferDirty=!0,this.glGeomItems.length==this.glgeomItems_freeIndices.length&&this.destroy()}updateDrawIDsBuffer(){const A=this.gl;A.floatTexturesSupported?(this.drawIdsBuffer&&this.glGeomItems.length!=this.drawIdsArray.length&&(this.gl.deleteBuffer(this.drawIdsBuffer),this.drawIdsBuffer=null),this.drawIdsBuffer||(this.drawIdsBuffer=A.createBuffer(),A.bindBuffer(A.ARRAY_BUFFER,this.drawIdsBuffer)),A.bindBuffer(A.ARRAY_BUFFER,this.drawIdsBuffer),A.bufferData(A.ARRAY_BUFFER,this.getDrawIdsArray(),A.STATIC_DRAW),this.drawIdsBufferDirty=!1):this.drawIdsBufferDirty=!1}getDrawIdsArray(){return this.drawIdsBufferDirty&&(this.drawIdsArray&&this.glGeomItems.length==this.drawIdsArray.length||(this.drawIdsArray=new Float32Array(this.glGeomItems.length)),this.visibleItems.forEach(((A,g)=>{this.drawIdsArray[g]=this.glGeomItems[A].geomItemId})),this.drawIdsBufferDirty=!1),this.drawIdsArray}updateHighlightedIDsBuffer(){const A=this.gl;A.floatTexturesSupported?(this.highlightedIdsBuffer&&this.glGeomItems.length>this.highlightedIdsArray.length&&(this.gl.deleteBuffer(this.highlightedIdsBuffer),this.highlightedIdsBuffer=null),this.highlightedIdsBuffer||(this.highlightedIdsBuffer=A.createBuffer()),A.bindBuffer(A.ARRAY_BUFFER,this.highlightedIdsBuffer),A.bufferData(A.ARRAY_BUFFER,this.getHighlightedIdsArray(),A.STATIC_DRAW),this.highlightedIdsBufferDirty=!1):this.highlightedIdsBufferDirty=!1}getHighlightedIdsArray(){return this.highlightedIdsBufferDirty&&((!this.highlightedIdsArray||this.highlightedItems.length>this.highlightedIdsArray.length)&&(this.highlightedIdsArray=new Float32Array(this.glGeomItems.length)),this.highlightedItems.forEach(((A,g)=>{this.highlightedIdsArray[g]=this.glGeomItems[A].geomItemId})),this.highlightedIdsBufferDirty=!1),this.highlightedIdsArray}draw(A){0!=this.visibleItems.length&&(this.drawIdsBufferDirty&&this.updateDrawIDsBuffer(),this.bindAndRender(A,this.visibleItems,this.drawIdsBuffer))}drawHighlighted(A){0!=this.highlightedItems.length&&(this.highlightedIdsBufferDirty&&this.updateHighlightedIDsBuffer(),this.bindAndRender(A,this.highlightedItems,this.highlightedIdsBuffer))}drawGeomData(A){0!=this.visibleItems.length&&(this.drawIdsBufferDirty&&this.updateDrawIDsBuffer(),this.bindAndRender(A,this.visibleItems,this.drawIdsBuffer))}bindAndRender(A,g,I){const C=this.gl,e=A.unifs;if(A.glGeom!=this.glGeom&&(this.glGeom.bind(A),A.glGeom=this.glGeom),C.floatTexturesSupported&&C.drawElementsInstanced&&A.supportsInstancing){A.unifs.instancedDraw&&C.uniform1i(A.unifs.instancedDraw.location,1);const i=A.attrs.instancedIds.location;C.enableVertexAttribArray(i),C.bindBuffer(C.ARRAY_BUFFER,I),C.vertexAttribPointer(i,1,C.FLOAT,!1,4,0),C.vertexAttribDivisor(i,1),A.bindViewports(e,(()=>{this.glGeom.drawInstanced(A,g.length)}))}else A.unifs.instancedDraw&&C.uniform1i(A.unifs.instancedDraw.location,0),g.forEach((g=>{this.glGeomItems[g].bind(A),A.bindViewports(e,(()=>{this.glGeom.draw(A)}))}))}destroy(){this.drawIdsBuffer&&(this.gl.deleteBuffer(this.drawIdsBuffer),this.drawIdsBuffer=null),this.highlightedIdsBuffer&&(this.gl.deleteBuffer(this.highlightedIdsBuffer),this.highlightedIdsBuffer=null),this.emit("destructing")}}var vert$a="\nprecision highp float;\n#define GLSLIFY 1\nattribute vec3 positions;  //(location = 0)\n\n/* VS Outputs */\nvarying vec2 v_texCoord;\n \nvoid main()\n{\n  v_texCoord = positions.xy+0.5;\n  gl_Position = vec4(positions.xy*2.0, -1.0, 1.0);\n}\n",frag$9="\nprecision highp float;\n#define GLSLIFY 1\n\nuniform sampler2D colorTexture;\nuniform sampler2D depthTexture;\nuniform vec2 screenSize;\n\nuniform int pointAndLinePickingSize;\n\nvarying vec2 v_texCoord;\n\nbool sampleNeiPixel(vec2 fragCoord, inout vec4 res) {\n  res = texture2D(colorTexture, fragCoord/screenSize);\n  if (res.a > 0.0) {\n    return true;\n  }\n  return false;\n}\n\nvec4 samplePixels(vec2 fragCoord, int dist) {\n  vec4 res = vec4(0.0);\n  \n  \n  // Search surrounding pixels for geoms\n  if (sampleNeiPixel(fragCoord+vec2( dist, 0), res)) return res; // E\n  if (sampleNeiPixel(fragCoord+vec2(-dist, 0), res)) return res; // W\n  if (sampleNeiPixel(fragCoord+vec2( 0, dist), res)) return res; // N\n  if (sampleNeiPixel(fragCoord+vec2( 0,-dist), res)) return res; // S\n  if (sampleNeiPixel(fragCoord+vec2( dist, dist), res)) return res; // NW\n  if (sampleNeiPixel(fragCoord+vec2(-dist, dist), res)) return res; // NE\n  if (sampleNeiPixel(fragCoord+vec2( dist,-dist), res)) return res; // SW\n  if (sampleNeiPixel(fragCoord+vec2(-dist,-dist), res)) return res; // SE\n  \n  return res;\n}\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\nvoid main(void) {\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  sampleNeiPixel(gl_FragCoord.xy, fragColor);\n  if (fragColor.a < 0.0001 && pointAndLinePickingSize > 1) {\n    for (int i=1; i<pointAndLinePickingSize; i++) {\n      fragColor = samplePixels(gl_FragCoord.xy, i);\n      if (fragColor.a > 0.0001) {\n        break;\n      } \n    }\n  }\n\n  if (fragColor.a < 0.0001) {\n    discard; \n  }\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n";class FattenLinesShader extends GLShader{constructor(A){super(A,"FattenLinesShader"),this.setShaderStage("VERTEX_SHADER",vert$a),this.setShaderStage("FRAGMENT_SHADER",frag$9)}}const deepEquals=(A,g)=>A.length==g.length&&!A.some(((A,I)=>A!=g[I]));var GeomType;!function(A){A[A.TRIANGLES=0]="TRIANGLES",A[A.LINES=1]="LINES",A[A.POINTS=2]="POINTS"}(GeomType||(GeomType={}));class GLGeomItemSetMultiDrawCompoundGeom extends EventEmitter{renderer;gl;glGeomItems=[];glGeomIdsMapping={};glgeomItemEventHandlers=[];freeIndices=[];dirtyGeomItems=new Set;drawIdsBufferDirty=!0;drawIdsArraysAllocators={};drawIdsArrays={};drawIdsTextures={};drawElementCounts={};drawElementOffsets={};drawOrderToIndex=[];indexToDrawIndex=[];highlightedItems={};highlightedIdsArraysAllocators={};highlightElementCounts={};highlightElementOffsets={};highlightedIdsArray={};highlightedIdsTextures={};dirtyHighlightedGeomItems=new Set;highlightedIdsBufferDirty=!0;linesGeomDataBuffer=null;fattenLinesShader=null;quad=null;fbo=null;constructor(A){super(),this.renderer=A,this.gl=A.gl,this.renderer.glGeomLibrary.on("geomDataChanged",(A=>{const g=this.glGeomIdsMapping[A.index];null!=g&&g.forEach((A=>{this.dirtyGeomItems.add(A),this.drawIdsBufferDirty||(this.drawIdsBufferDirty=!0,this.emit("updated"))}))}))}addItemToHighlight(A,g){const I=g.indexOf(":");let C=[];-1!=I&&(C=g.substring(I+1).split(",").map((A=>Number.parseInt(A)))),this.highlightedItems[A]&&deepEquals(this.highlightedItems[A],C)||(this.highlightedItems[A]=C,this.highlightedIdsBufferDirty=!0,this.emit("updated"))}addGLGeomItem(A){const g=this.freeIndices.length>0?this.freeIndices.pop():this.glGeomItems.length;this.indexToDrawIndex[g]=this.drawOrderToIndex.length,this.drawOrderToIndex.push(g),this.dirtyGeomItems.add(g);const I={};I.visibilityChanged=A=>{this.dirtyGeomItems.add(g),this.drawIdsBufferDirty=!0,this.emit("updated")},A.on("visibilityChanged",I.visibilityChanged),A.geomItem.isHighlighted()&&this.addItemToHighlight(g,A.geomItem.getHighlightName()),I.highlightChanged=A=>{A&&A.name?this.addItemToHighlight(g,A.name):(delete this.highlightedItems[g],this.highlightedIdsBufferDirty=!0,this.emit("updated"))},A.geomItem.on("highlightChanged",I.highlightChanged),I.shatterStateChanged=A=>{this.dirtyGeomItems.add(g),this.drawIdsBufferDirty=!0,this.renderer.renderGeomDataFbos()},A.on("shatterStateChanged",I.shatterStateChanged);let C=A.geomItem.geomParam.value;A.geomId=this.renderer.glGeomLibrary.addGeom(C),this.glGeomIdsMapping[A.geomId]?this.glGeomIdsMapping[A.geomId].push(g):this.glGeomIdsMapping[A.geomId]=[g],this.glGeomItems[g]=A,this.glgeomItemEventHandlers[g]=I,this.drawIdsBufferDirty=!0,this.emit("updated")}removeGLGeomItem(A){const g=this.glGeomItems.indexOf(A),I=this.glGeomIdsMapping[A.geomId];I.splice(I.indexOf(g),1),0==I.length&&delete this.glGeomIdsMapping[A.geomId],this.renderer.glGeomLibrary.removeGeom(A.geomId);const C=this.glgeomItemEventHandlers[g];A.geomItem.off("highlightChanged",C.highlightChanged),A.off("visibilityChanged",C.visibilityChanged),this.glGeomItems[g]=null,this.glgeomItemEventHandlers[g]=null,this.freeIndices.push(g),this.dirtyGeomItems.has(g)&&this.dirtyGeomItems.delete(g);for(let A in this.drawIdsArraysAllocators){const I=this.drawIdsArraysAllocators[A].getAllocation(g);if(I){for(let g=0;g<I.size;g++)this.drawElementOffsets[A][I.start+g]=0,this.drawElementCounts[A][I.start+g]=0;this.drawIdsArraysAllocators[A].deallocate(g)}}const e=this.drawOrderToIndex.indexOf(g);this.drawOrderToIndex.splice(e,1),this.indexToDrawIndex[g]=-1,this.drawIdsBufferDirty=!0,A.geomItem.isHighlighted()&&(delete this.highlightedItems[g],this.highlightedIdsBufferDirty=!0),this.emit("updated")}updateDrawIDsBuffer(A){this.dirtyGeomItems.forEach((A=>{const g=this.glGeomItems[A];if(g){const I=this.renderer.glGeomLibrary.getGeom(g.geomId).genBuffers();let C={};if(g.shattered)for(let A in I.subGeomCounts)C[A]=I.subGeomCounts[A].length;else for(let A in I.materialSubGeoms)C[A]=I.materialSubGeoms[A].length;for(let g in C){const I=C[g];let e=this.drawIdsArraysAllocators[g];if(e){const C=e.getAllocation(A);if(C){if(C.size==I)continue;for(let A=0;A<C.size;A++)this.drawElementCounts[g][C.start+A]=0}}else e=new Allocator1D,this.drawIdsArraysAllocators[g]=e;e.allocate(A,I)}}}));for(let A in this.drawIdsArraysAllocators){const g=this.drawIdsArraysAllocators[A];if(!this.drawElementCounts[A]||g.reservedSpace>this.drawElementCounts[A].length-1){const I=new Float32Array(4*g.reservedSpace),C=new Int32Array(g.reservedSpace+1),e=new Int32Array(g.reservedSpace+1);this.drawElementCounts[A]&&(I.set(this.drawIdsArrays[A],0),C.set(this.drawElementOffsets[A],0),e.set(this.drawElementCounts[A],0)),this.drawIdsArrays[A]=I,this.drawElementOffsets[A]=C,this.drawElementCounts[A]=e}}this.dirtyGeomItems.forEach((A=>{const g=this.glGeomItems[A];if(!g)return;const I=this.renderer.glGeomLibrary.getGeomOffsetAndCount(g.geomId),C=this.renderer.glGeomLibrary.getGeomBuffers(g.geomId),e=g.isVisible();if(g.shattered){let i=0;const t=(t,o,a)=>{const B=this.drawIdsArraysAllocators[a],s=this.drawIdsArrays[a],l=this.drawElementOffsets[a],n=this.drawElementCounts[a],d=B.getAllocation(A);if(!d)return;const r=C.materials;for(let A=0;A<t.length;A++){const a=d.start+A;l[a]=I[0]+4*t[A],n[a]=e?o[A]:0,s[4*a+0]=g.geomItemId,s[4*a+1]=i+1;const B=C.subGeomMaterialIndices[i];if(r.length>0&&B>0&&B<=C.materials.length){const A=C.materials[B-1],g=this.renderer.glMaterialLibrary.getMaterialAllocation(A);s[4*a+2]=g.start}else s[4*a+2]=0;s[4*a+3]=0,i++}};t(C.subGeomOffsets.TRIANGLES,C.subGeomCounts.TRIANGLES,"TRIANGLES"),t(C.subGeomOffsets.LINES,C.subGeomCounts.LINES,"LINES"),t(C.subGeomOffsets.POINTS,C.subGeomCounts.POINTS,"POINTS")}else{const i=(i,t)=>{const o=this.drawIdsArraysAllocators[t],a=this.drawIdsArrays[t],B=this.drawElementOffsets[t],s=this.drawElementCounts[t],l=o.getAllocation(A);if(!l)return;const n=C.materials;for(let A=0;A<i.length;A++){const t=i[A],o=l.start+A;if(B[o]=I[0]+4*t.offset,s[o]=e?t.count:0,a[4*o+0]=g.geomItemId,a[4*o+1]=0,n.length>0&&t.materialId>=0&&C.materials[t.materialId]){const A=C.materials[t.materialId],g=this.renderer.glMaterialLibrary.getMaterialAllocation(A);a[4*o+2]=g.start}else a[4*o+2]=0;a[4*o+3]=0}};for(let g in C.materialSubGeoms){if(!this.drawIdsArraysAllocators[g].getAllocation(A))continue;i(C.materialSubGeoms[g],g)}}}));const g=this.renderer.gl;let I=!1;const C=C=>{const e=this.drawIdsArrays[C];let i=this.drawIdsTextures[C];const t=this.drawIdsArraysAllocators[C].reservedSpace,o=A.boundTextures++;g.activeTexture(g.TEXTURE0+o);const a=MathFunctions.nextPow2(Math.ceil(Math.sqrt(t)));if(i){if(i.width<a||i.height<a){i.resize(a,a);for(let A=0;A<this.drawOrderToIndex.length;A++)this.dirtyGeomItems.add(A);I=!0}}else i=new GLTexture2D(this.gl,{format:"RGBA",type:"FLOAT",width:a,height:a,filter:"NEAREST",wrap:"CLAMP_TO_EDGE",mipMapped:!1}),this.drawIdsTextures[C]=i,I=!0;{const A=i,t=i.width;g.bindTexture(g.TEXTURE_2D,A.glTex);const o=0,a=0,B=1,s=A.format,l=A.type;if(I){const A=this.drawIdsArraysAllocators[C].allocatedSpace,I=Math.ceil((a+A)/t);let i=0,n=A,d=a;for(let A=0;A<I;A++){let A;d+n>t?(A=t-d,d=0):A=n;const I=i%t,C=Math.floor(i/t),a=e.subarray(4*i,4*(i+A));if(a.length!=4*A)throw new Error("Invalid drawIds subarray :"+a.length+" width:"+A);g.texSubImage2D(g.TEXTURE_2D,o,I,C,A,B,s,l,a),i+=A,n-=A}}else{const A=this.drawIdsArraysAllocators[C];this.dirtyGeomItems.forEach((I=>{const C=A.getAllocation(I);if(!C)return;const i=C.start,a=C.size,n=i%t,d=Math.ceil((n+a)/t);let r=0,c=a,h=n;for(let A=0;A<d;A++){let A;h+c>t?(A=t-h,h=0):A=c;const I=(i+r)%t,C=Math.floor((i+r)/t),a=e.subarray(4*(i+r),4*(i+r+A));if(a.length!=4*A)throw new Error("Invalid drawIds subarray :"+a.length+" width:"+A);g.texSubImage2D(g.TEXTURE_2D,o,I,C,A,B,s,l,a),r+=A,c-=A}}))}}g.bindTexture(g.TEXTURE_2D,null),A.boundTextures--};for(let A in this.drawIdsArrays)C(A);this.dirtyGeomItems=new Set,this.drawIdsBufferDirty=!1}updateHighlightedIDsBuffer(A){if(this.highlightedIdsBufferDirty){this.highlightedIdsArraysAllocators={},this.highlightedIdsArray={},this.highlightElementOffsets={},this.highlightElementCounts={};for(let A in this.highlightedItems){const g=Number.parseInt(A),I=this.highlightedItems[A],C=this.glGeomItems[g],e=this.renderer.glGeomLibrary.getGeomBuffers(C.geomId);let i={TRIANGLES:0,LINES:0,POINTS:0};if(I.length>0)I.forEach((A=>{if(A<e.subGeomCounts.TRIANGLES.length)i.TRIANGLES++;else{const g=A-e.subGeomCounts.TRIANGLES.length;if(g<e.subGeomCounts.LINES.length)i.LINES++;else{g-e.subGeomCounts.LINES.length<e.subGeomCounts.POINTS.length&&i.POINTS++}}}));else for(let A in e.counts)e.counts[A]>0&&(i[A]=1);for(let A in i){const I=i[A];0!=I&&(this.highlightedIdsArraysAllocators[A]||(this.highlightedIdsArraysAllocators[A]=new Allocator1D),this.highlightedIdsArraysAllocators[A].allocate(g,I))}}for(let A in this.highlightedIdsArraysAllocators){const g=this.highlightedIdsArraysAllocators[A];(!this.highlightElementCounts[A]||g.reservedSpace>this.highlightElementCounts[A].length-1)&&(this.highlightedIdsArray[A]=new Float32Array(4*g.reservedSpace),this.highlightElementOffsets[A]=new Int32Array(g.reservedSpace+1),this.highlightElementCounts[A]=new Int32Array(g.reservedSpace+1))}const A=4;for(let g in this.highlightedItems){const I=Number.parseInt(g),C=this.highlightedItems[g],e=this.glGeomItems[I],i=this.renderer.glGeomLibrary.getGeomOffsetAndCount(e.geomId),t=this.renderer.glGeomLibrary.getGeomBuffers(e.geomId);if(0!=C.length){const g={TRIANGLES:0,LINES:0,POINTS:0};C.forEach((C=>{const o=(g,t,o,a,B)=>{const s=this.highlightedIdsArraysAllocators[a],l=this.highlightedIdsArray[a],n=this.highlightElementOffsets[a],d=this.highlightElementCounts[a],r=s.getAllocation(I).start+g;n[r]=i[0]+t[B]*A,d[r]=o[B],l[4*r+0]=e.geomItemId,l[4*r+1]=C+1,l[4*r+2]=0,l[4*r+3]=0};if(C<t.subGeomCounts.TRIANGLES.length)o(g.TRIANGLES,t.subGeomOffsets.TRIANGLES,t.subGeomCounts.TRIANGLES,"TRIANGLES",C),g.TRIANGLES++;else{const A=C-t.subGeomCounts.TRIANGLES.length;if(A<t.subGeomCounts.LINES.length)o(g.LINES,t.subGeomOffsets.LINES,t.subGeomCounts.LINES,"LINES",A),g.LINES++;else{const I=A-t.subGeomCounts.LINES.length;I<t.subGeomCounts.POINTS.length&&(o(g.POINTS,t.subGeomOffsets.POINTS,t.subGeomCounts.POINTS,"POINTS",I),g.POINTS++)}}}))}else for(let g in t.offsets){const C=t.counts[g];if(0==C)continue;const o=t.offsets[g],a=this.highlightedIdsArraysAllocators[g].getAllocation(I).start;this.highlightElementOffsets[g][a]=i[0]+o*A,this.highlightElementCounts[g][a]=C,this.highlightedIdsArray[g][4*a+0]=e.geomItemId}}this.highlightedIdsBufferDirty=!1}const g=this.renderer.gl,I=I=>{const C=this.highlightedIdsArray[I];if(!C||0==C.length)return;let e=this.highlightedIdsTextures[I];const i=this.highlightedIdsArraysAllocators[I].reservedSpace,t=A.boundTextures++;g.activeTexture(g.TEXTURE0+t);const o=MathFunctions.nextPow2(Math.ceil(Math.sqrt(i)));e?(e.width<o||e.height<o)&&e.resize(o,o):(e=new GLTexture2D(this.gl,{format:"RGBA",type:"FLOAT",width:o,height:o,filter:"NEAREST",wrap:"CLAMP_TO_EDGE",mipMapped:!1}),this.highlightedIdsTextures[I]=e);{const A=e,i=e.width;g.bindTexture(g.TEXTURE_2D,A.glTex);const t=0,o=0,a=1,B=A.format,s=A.type,l=this.highlightedIdsArraysAllocators[I].allocatedSpace,n=Math.ceil((o+l)/i);let d=0,r=l,c=o;for(let A=0;A<n;A++){let A;c+r>i?(A=i-c,c=0):A=r;const I=d%i,e=Math.floor(d/i),o=C.subarray(4*d,4*(d+A));if(o.length!=4*A)throw new Error("Invalid drawIds subarray :"+o.length+" width:"+A);g.texSubImage2D(g.TEXTURE_2D,t,I,e,A,a,B,s,o),d+=A,r-=A}}g.bindTexture(g.TEXTURE_2D,null),A.boundTextures--};for(let A in this.highlightedIdsArray)I(A)}draw(A){if(0==this.drawOrderToIndex.length)return;this.drawIdsBufferDirty&&this.updateDrawIDsBuffer(A),A.pushGLStack("GLGeomItemSetMultiDrawCompoundGeom.draw");const g=this.drawIdsArrays,I=this.drawElementCounts,C=this.drawElementOffsets,e=this.drawIdsTextures,i=this.drawIdsArraysAllocators,t=this.gl,o=A.unifs,a=t.getParameter(t.DEPTH_FUNC),{drawIdsTexture:B,geomType:s,outlineThickness:l,viewportSize:n,occluded:d,renderMode:r}=A.unifs,c=A instanceof ColorRenderState&&r?A.renderMode:null,h="flat-noedges"!=c&&"shaded-noedges"!=c&&"pbr-noedges"!=c,G=A instanceof ColorRenderState&&l&&n&&"geometry"==A.outlineMethod&&A.outlineThickness>0&&h,m=G&&"wireframe"==c,b=A.hiddenLineColor&&A.hiddenLineColor.a>0&&d;if(m?(t.enable(t.STENCIL_TEST),t.clearStencil(0),t.clear(t.STENCIL_BUFFER_BIT),t.stencilOpSeparate(t.FRONT,t.DECR_WRAP,t.DECR_WRAP,t.DECR_WRAP),t.stencilOpSeparate(t.BACK,t.INCR_WRAP,t.INCR_WRAP,t.INCR_WRAP),t.stencilFunc(t.ALWAYS,0,255),t.enable(t.CULL_FACE),t.cullFace(t.BACK),t.disable(t.DEPTH_TEST),t.depthMask(!1),t.colorMask(!1,!1,!1,!1)):"hiddenline"==c?t.colorMask(!1,!1,!1,!0):t.disable(t.CULL_FACE),g.TRIANGLES&&i.TRIANGLES.allocatedSpace>0){if(e.TRIANGLES.bindToUniform(A,B),s&&t.uniform1i(s.location,GeomType.TRIANGLES),t.enable(t.POLYGON_OFFSET_FILL),t.polygonOffset(1,1),l&&t.uniform1f(l.location,0),A.bindViewports(o,(()=>{this.multiDrawMeshes(A,I.TRIANGLES,C.TRIANGLES,i.TRIANGLES.allocatedSpace)})),G){if(t.enable(t.CULL_FACE),t.cullFace(t.FRONT),t.uniform1f(l.location,this.renderer.outlineThickness*window.devicePixelRatio),t.uniform2f(n.location,A.region[2]-A.region[0],A.region[3]-A.region[1]),"hiddenline"==c&&t.colorMask(!0,!0,!0,!0),m||(A.glEnable(t.BLEND),t.blendEquation(t.FUNC_ADD),t.blendFuncSeparate(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA,t.ONE,t.ONE)),A.bindViewports(o,(()=>{this.multiDrawMeshes(A,I.TRIANGLES,C.TRIANGLES,i.TRIANGLES.allocatedSpace)})),t.disable(t.CULL_FACE),t.cullFace(t.BACK),m){t.enable(t.DEPTH_TEST),t.depthMask(!0),t.colorMask(!0,!0,!0,!0),t.stencilFunc(t.NOTEQUAL,0,255),t.stencilOp(t.KEEP,t.KEEP,t.KEEP),A.glEnable(t.BLEND),t.blendEquation(t.FUNC_ADD),t.blendFuncSeparate(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA,t.ONE,t.ONE);const g=A.glShader,I=A.shaderkey,C=this.renderer.screenQuad;C.bindShader(A),C.draw(A,this.renderer.outlineColor),g.bind(A,I),this.renderer.glGeomItemLibrary.bind(A),this.renderer.glGeomLibrary.bind(A),this.renderer.glMaterialLibrary.bind(A),t.disable(t.STENCIL_TEST)}}else A.glEnable(t.BLEND),t.blendEquation(t.FUNC_ADD),t.blendFuncSeparate(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA,t.ONE,t.ONE);t.disable(t.POLYGON_OFFSET_FILL)}if(h&&g.LINES&&i.LINES.allocatedSpace>0&&(e.LINES.bindToUniform(A,B),s&&t.uniform1i(s.location,GeomType.LINES),A.bindViewports(o,(()=>{this.multiDrawLines(A,I.LINES,C.LINES,i.LINES.allocatedSpace)})),b)){const{hiddenLineColor:g}=A.unifs;t.uniform1i(d.location,1),t.uniform4fv(g.location,A.hiddenLineColor.asArray()),t.depthFunc(t.GREATER),t.depthMask(!1),A.bindViewports(o,(()=>{this.multiDrawLines(A,I.LINES,C.LINES,i.LINES.allocatedSpace)})),t.depthFunc(a),t.depthMask(!0),t.uniform1i(d.location,0)}if(g.POINTS&&i.POINTS.allocatedSpace>0&&(e.POINTS.bindToUniform(A,B),s&&t.uniform1i(s.location,GeomType.POINTS),A.bindViewports(o,(()=>{this.multiDrawPoints(A,I.POINTS,C.POINTS,i.POINTS.allocatedSpace)})),b)){const{hiddenLineColor:g}=A.unifs;t.uniform1i(d.location,1),t.uniform4fv(g.location,A.hiddenLineColor.asArray()),t.depthFunc(t.GREATER),t.depthMask(!1),A.bindViewports(o,(()=>{this.multiDrawPoints(A,I.POINTS,C.POINTS,i.POINTS.allocatedSpace)})),t.depthFunc(a),t.depthMask(!0),t.uniform1i(d.location,0)}s&&t.uniform1i(s.location,0),A.popGLStack()}drawGeomData(A){this.drawIdsBufferDirty&&this.updateDrawIDsBuffer(A),A.pushGLStack("GLGeomItemSetMultiDrawCompoundGeom.drawGeomData");const g=this.renderer.gl,I=A.unifs,{drawIdsTexture:C,geomType:e}=I,i=this.drawElementCounts,t=this.drawElementOffsets,o=this.drawIdsTextures,a=this.drawIdsArraysAllocators,B=this.drawIdsArrays;"wireframe"!=this.renderer.renderMode&&A.bindViewports(I,(()=>{B.TRIANGLES&&a.TRIANGLES.allocatedSpace>0&&(o.TRIANGLES.bindToUniform(A,C),e&&g.uniform1i(e.location,GeomType.TRIANGLES),g.enable(g.POLYGON_OFFSET_FILL),g.polygonOffset(1,1),this.multiDrawMeshes(A,i.TRIANGLES,t.TRIANGLES,a.TRIANGLES.allocatedSpace),g.disable(g.POLYGON_OFFSET_FILL))}));if(A.geomDataFbo){this.linesGeomDataBuffer||(this.linesGeomDataBuffer=new GLTexture2D(g,{type:this.renderer.floatGeomBuffer?"FLOAT":"UNSIGNED_BYTE",format:"RGBA",filter:"NEAREST",width:1,height:2}),this.fattenLinesShader=new FattenLinesShader(g),this.quad=new GLMesh(g,new Plane(1,1)));const I=A.geomDataFbo,C=I.width,e=I.height;if(this.linesGeomDataBuffer.width!=C||this.linesGeomDataBuffer.height!=e){this.fbo&&(g.deleteFramebuffer(this.fbo),this.fbo=null),this.linesGeomDataBuffer.resize(C,e),this.fbo=g.createFramebuffer();const A=this.linesGeomDataBuffer.glTex,i=I.depthTexture;g.bindFramebuffer(g.DRAW_FRAMEBUFFER,this.fbo),g.framebufferTexture2D(g.DRAW_FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,A,0),g.framebufferTexture2D(g.DRAW_FRAMEBUFFER,g.DEPTH_ATTACHMENT,g.TEXTURE_2D,i,0),checkFramebuffer(g,C,e)}else g.bindFramebuffer(g.DRAW_FRAMEBUFFER,this.fbo);g.colorMask(!0,!0,!0,!0),g.clearColor(0,0,0,0),g.clear(g.COLOR_BUFFER_BIT)}if(A.bindViewports(I,(()=>{B.LINES&&a.LINES.allocatedSpace>0&&(o.LINES.bindToUniform(A,C),e&&g.uniform1i(e.location,GeomType.LINES),this.multiDrawLines(A,i.LINES,t.LINES,a.LINES.allocatedSpace)),B.POINTS&&a.POINTS.allocatedSpace>0&&(o.POINTS.bindToUniform(A,C),e&&g.uniform1i(e.location,GeomType.POINTS),this.multiDrawPoints(A,i.POINTS,t.POINTS,a.POINTS.allocatedSpace))})),this.linesGeomDataBuffer&&A.geomDataFbo){A.boundRendertarget=null,A.geomDataFbo.bindForWriting(A);const I=A.glShader,C=A.shaderkey;this.fattenLinesShader.bind(A),g.disable(g.DEPTH_TEST);const{colorTexture:e,screenSize:i,pointAndLinePickingSize:t}=A.unifs;this.linesGeomDataBuffer.bindToUniform(A,e);const o=A.geomDataFbo;g.uniform2f(i.location,o.width,o.height),g.uniform1i(t.location,A.pointAndLinePickingSize),this.quad.bindAndDraw(A),g.enable(g.DEPTH_TEST),I.bind(A,C),this.renderer.glGeomItemLibrary.bind(A),this.renderer.glGeomLibrary.bind(A),this.renderer.glMaterialLibrary.bind(A)}A.popGLStack()}drawHighlighted(A){if(0==Object.keys(this.highlightedItems).length)return;this.highlightedIdsBufferDirty&&this.updateHighlightedIDsBuffer(A),A.pushGLStack("GLGeomItemSetMultiDrawCompoundGeom.drawHighlighted");const g=this.highlightedIdsArray,I=this.highlightElementCounts,C=this.highlightElementOffsets,e=this.highlightedIdsTextures,i=this.highlightedIdsArraysAllocators,t=A.unifs,o=this.renderer.gl;A.glDisable(o.CULL_FACE);const{drawIdsTexture:a,geomType:B}=A.unifs;A.bindViewports(t,(()=>{g.TRIANGLES&&i.TRIANGLES.allocatedSpace>0&&(e.TRIANGLES.bindToUniform(A,a),o.enable(o.POLYGON_OFFSET_FILL),o.polygonOffset(1,1),B&&o.uniform1i(B.location,GeomType.TRIANGLES),this.multiDrawMeshes(A,I.TRIANGLES,C.TRIANGLES,i.TRIANGLES.allocatedSpace),o.disable(o.POLYGON_OFFSET_FILL)),g.LINES&&i.LINES.allocatedSpace>0&&(e.LINES.bindToUniform(A,a),B&&o.uniform1i(B.location,GeomType.LINES),this.multiDrawLines(A,I.LINES,C.LINES,i.LINES.allocatedSpace)),g.POINTS&&i.POINTS.allocatedSpace>0&&(e.POINTS.bindToUniform(A,a),B&&o.uniform1i(B.location,GeomType.POINTS),this.multiDrawPoints(A,I.POINTS,C.POINTS,i.POINTS.allocatedSpace))})),B&&o.uniform1i(B.location,0),A.popGLStack()}multiDrawMeshes(A,g,I,C){const e=this.gl;if(e.multiDrawElements)e.multiDrawElements(e.TRIANGLES,g,0,e.UNSIGNED_INT,I,0,C);else{const{drawId:i}=A.unifs;for(let A=0;A<C;A++)e.uniform1i(i.location,A),e.drawElements(e.TRIANGLES,g[A],e.UNSIGNED_INT,I[A])}}multiDrawLines(A,g,I,C){const e=this.gl;if(e.multiDrawElements)e.multiDrawElements(e.LINES,g,0,e.UNSIGNED_INT,I,0,C);else{const{drawId:i}=A.unifs;for(let A=0;A<C;A++)e.uniform1i(i.location,A),e.drawElements(e.LINES,g[A],e.UNSIGNED_INT,I[A])}}multiDrawPoints(A,g,I,C){const e=this.gl;if(e.multiDrawElements)e.multiDrawElements(e.POINTS,g,0,e.UNSIGNED_INT,I,0,C);else{const{drawId:i}=A.unifs;for(let A=0;A<C;A++)e.uniform1i(i.location,A),e.drawElements(e.POINTS,g[A],e.UNSIGNED_INT,I[A])}}sortItems(A){this.drawIdsBufferDirty}destroy(){for(let A in this.drawIdsTextures)this.drawIdsTextures[A].destroy();for(let A in this.highlightedIdsTextures)this.highlightedIdsTextures[A].destroy();this.emit("destructing")}}class GLShaderGeomSets extends EventEmitter{renderer;gl;glShader;glGeomItemSets={};constructor(A,g,I){super(),this.renderer=A,this.gl=g,this.glShader=I}getOrCreateGLGeomItemSet(A){let g;if(A instanceof CompoundGeom){if(this.glGeomItemSets.CompoundGeom)return this.glGeomItemSets.CompoundGeom;g=new GLGeomItemSetMultiDrawCompoundGeom(this.renderer),this.glGeomItemSets.CompoundGeom=g}else if(A instanceof Mesh||A instanceof MeshProxy){if(this.glGeomItemSets.GLMesh)return this.glGeomItemSets.GLMesh;g=new GLMeshItemSet(this.renderer),this.glGeomItemSets.GLMesh=g}else if(A instanceof Lines||A instanceof LinesProxy){if(this.glGeomItemSets.GLLines)return this.glGeomItemSets.GLLines;g=new GLLinesItemSet(this.renderer),this.glGeomItemSets.GLLines=g}else{if(!(A instanceof Points||A instanceof PointsProxy))throw new Error("Unsupported geom type:"+A.constructor.name);if(this.glGeomItemSets.GLPoints)return this.glGeomItemSets.GLPoints;g=new GLPointsItemSet(this.renderer),this.glGeomItemSets.GLPoints=g}return g.on("updated",(()=>{this.emit("updated")})),g}addGLGeomItem(A){const g=A.geomItem.geomParam.value,I=this.getOrCreateGLGeomItemSet(g);A.GLGeomItemSet=I,I.addGLGeomItem(A)}removeGLGeomItem(A){A.GLGeomItemSet.removeGLGeomItem(A),A.GLGeomItemSet=null}bindShader(A,g,I){const C=this.gl;if(A.isCompiledForTarget(I)||(C.multiDrawElements?g.directives.push("#define ENABLE_MULTI_DRAW\n#extension GL_ANGLE_multi_draw : enable"):g.directives.push("#define ENABLE_MULTI_DRAW"),A.compileForTarget(I,g.directives),g.directives.pop()),!A.bind(g,I))throw new Error("Unable to bind shader:"+A);this.renderer.glGeomItemLibrary.bind(g),this.renderer.glGeomLibrary.bind(g),this.renderer.glMaterialLibrary.bind(g)}draw(A){this.bindShader(this.glShader,A,"multidraw-draw");for(const g in this.glGeomItemSets)this.glGeomItemSets[g].draw(A);this.glShader.unbind(A)}drawHighlightedGeoms(A){this.bindShader(this.glShader,A,"multidraw-highlight");for(const g in this.glGeomItemSets)this.glGeomItemSets[g].drawHighlighted(A);this.glShader.unbind(A)}drawGeomData(A){this.bindShader(this.glShader,A,"multidraw-geomdata");const g=A.gl,{passId:I}=A.unifs;I&&g.uniform1i(I.location,A.passIndex);for(const g in this.glGeomItemSets)this.glGeomItemSets[g].drawGeomData(A);this.glShader.unbind(A)}sortItems(A){for(const g in this.glGeomItemSets)this.glGeomItemSets[g].sortItems(A)}}class GLMaterialGeomItemSets extends EventEmitter{pass;gl;glMaterial;glGeomItemSets=new Map;listenerIds={};drawCount=0;constructor(A,g){if(super(),this.pass=A,this.gl=A.renderer.gl,g){this.glMaterial=g;const A=g.material,I=()=>{A.off("opacityChanged",I),this.glGeomItemSets.forEach((A=>{for(const g of A.glGeomItems){const A=g.geomItem;this.pass.removeGeomItem(A),this.pass.renderer.assignTreeItemToGLPass(A)}}))};this.listenerIds["material.opacityChanged"]=A.on("opacityChanged",I)}}addGLGeomItem(A,g){let I=this.glGeomItemSets.get(g);I||(I=new GLGeomItemSet(this.gl,g),this.addGeomItemSet(I)),I.addGLGeomItem(A)}drawCountChanged(A){this.drawCount+=A.change,this.emit("updated")}addGeomItemSet(A){this.glGeomItemSets.set(A.getGLGeom(),A);const g=A.on("drawCountChanged",(A=>{this.drawCountChanged(A)}));A.once("destructing",(()=>{if(A.off("drawCountChanged",g),this.glGeomItemSets.delete(A.getGLGeom()),0==this.glGeomItemSets.size&&this.glMaterial){this.glMaterial.material.off("opacityChanged",this.listenerIds["material.opacityChanged"]),this.emit("destructing")}}))}draw(A){if(0==this.drawCount)return;this.glMaterial&&this.glMaterial.bind(A,!0),this.glGeomItemSets.forEach((g=>{g.draw(A)})),this.glMaterial&&this.glMaterial.unbind(A)}drawHighlighted(A){this.glMaterial&&this.glMaterial.bind(A,!1),this.glGeomItemSets.forEach((g=>{g.drawHighlighted(A)})),this.glMaterial&&this.glMaterial.unbind(A)}drawGeomData(A){this.glMaterial&&this.glMaterial.bind(A,!1),this.glGeomItemSets.forEach((g=>{g.drawGeomData(A)})),this.glMaterial&&this.glMaterial.unbind(A)}}class GLShaderMaterials extends EventEmitter{gl;pass;glShader;glShaderKey="";glShaderGeomDataKey="";glShaderHighlightKey="";glMaterialGeomItemSets=new Map;constructor(A,g,I){super(),this.gl=A,this.pass=g,this.glShader=I,this.glShaderKey="draw",this.glShaderGeomDataKey="geomdata",this.glShaderHighlightKey="highlight"}getOrCreateGLMaterialGeomItemSets(A){let g=this.glMaterialGeomItemSets.get(A);return g||(g=new GLMaterialGeomItemSets(this.pass,A),this.addMaterialGeomItemSets(A,g)),g}addGLGeomItem(A,g,I){if(I.material.isTextured()){this.getOrCreateGLMaterialGeomItemSets(I).addGLGeomItem(A,g)}else{this.getOrCreateGLMaterialGeomItemSets(null).addGLGeomItem(A,g)}}addMaterialGeomItemSets(A,g){this.glMaterialGeomItemSets.set(A,g);const I=()=>{this.emit("updated")},C=()=>{g.off("updated",I),g.off("destructing",C),this.glMaterialGeomItemSets.delete(A),0==this.glMaterialGeomItemSets.size&&this.emit("destructing")};g.on("updated",I),g.on("destructing",C)}removeMaterialGeomItemSets(A){this.glMaterialGeomItemSets.delete(A)}draw(A){const g=this.glShader;this.glShader.bind(A,this.glShaderKey)&&(this.pass.renderer.glGeomItemLibrary.bind(A),this.pass.renderer.glMaterialLibrary.bind(A),this.glMaterialGeomItemSets.forEach((g=>{g.draw(A)})),g.unbind(A))}drawHighlightedGeoms(A){this.glShader.bind(A,this.glShaderHighlightKey)&&(this.pass.renderer.glGeomItemLibrary.bind(A),this.pass.renderer.glMaterialLibrary.bind(A),this.glMaterialGeomItemSets.forEach((g=>{g.drawHighlighted(A)})),this.glShader.unbind(A))}drawGeomData(A){if(!this.glShader.bind(A,this.glShaderGeomDataKey))return;this.pass.renderer.glGeomItemLibrary.bind(A),this.pass.renderer.glMaterialLibrary.bind(A);const g=this.gl,{passId:I}=A.unifs;I&&g.uniform1i(I.location,A.passIndex),this.glMaterialGeomItemSets.forEach((g=>{g.drawGeomData(A)})),this.glShader.unbind(A)}}var frag$8="\nprecision highp float;\nprecision highp int;\n#define GLSLIFY 1\n\nimport 'imageAtlas.glsl'\n\nuniform sampler2D atlasBillboards;\n\n/* VS Outputs */\nvarying float v_instanceID;\nvarying vec2 v_texCoord;\nvarying vec4 v_layoutData;\nvarying float v_alpha;\nvarying vec4 v_tint;\nvarying vec3 v_viewPos;\nvarying float v_frontFacing;\n\nuniform sampler2D instancesTexture;\nuniform int instancesTextureSize;\n\n#if defined(DRAW_GEOMDATA)\n  uniform int isOrthographic;\n  import 'surfaceGeomData.glsl'\n#endif // DRAW_GEOMDATA\n\nconst int cols_per_instance = 7;\n\nvec4 getHilightColor(int id) {\n  return fetchTexel(instancesTexture, instancesTextureSize, (id * cols_per_instance) + 6);\n}\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\nvoid main(void) {\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  int instanceID = int(v_instanceID);\n\n  vec2 texCoord = v_texCoord;\n\n  bool frontFacing = bool(v_frontFacing);\n  if (frontFacing && !gl_FrontFacing) {\n    texCoord.x = 1.0 - texCoord.x;\n  }\n  texCoord *= v_layoutData.zw;\n  texCoord += v_layoutData.xy;\n\n  vec4 imageColor = texture2D(atlasBillboards, texCoord) * v_tint;\n  imageColor.a *= v_alpha;\n  if(imageColor.a < 0.1)\n    discard;\n\n#if defined(DRAW_COLOR)\n  fragColor = imageColor;\n  // fragColor.r = 1.0;\n  // fragColor.a = 1.0;\n#elif defined(DRAW_GEOMDATA)\n  fragColor = setFragColor_geomData(v_viewPos, v_instanceID, 0.0, isOrthographic, 0, TRIANGLES);\n#elif defined(DRAW_HIGHLIGHT)\n  fragColor = getHilightColor(instanceID);\n  // Skip unhilighting labels.\n  if(fragColor.r < 0.001 && fragColor.g < 0.001 && fragColor.b < 0.001)\n    discard;\n#endif // DRAW_HIGHLIGHT\n  \n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n",vert$9="\nprecision highp float;\nprecision highp int;\n#define GLSLIFY 1\n\nimport 'quadVertexFromID.glsl'\n\nuniform mat4 viewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 cameraMatrix;\nuniform int isOrthographic;\nuniform vec4 viewportFrustum;\n\nimport 'GLSLUtils.glsl'\n\n#ifdef ENABLE_FLOAT_TEXTURES\n\n// A sorted attribute of instance Ids so we draw from back to front.\ninstancedattribute float instanceIds;\n\nimport 'transpose.glsl'\nimport 'imageAtlas.glsl'\n\nuniform sampler2D atlasBillboards_layout;\nuniform vec4 atlasBillboards_desc;\n\nuniform sampler2D instancesTexture;\nuniform int instancesTextureSize;\n\nconst int cols_per_instance = 7;\n\nconst int ALIGN_TO_CAMERA_FLAG = 1 << 2;\nconst int ALIGN_TO_CAMERA_AND_AXIS_FLAG = 1 << 3;\nconst int DRAW_ON_TOP_FLAG = 1 << 4;\nconst int FIXED_SIZE_ON_SCREEN_FLAG = 1 << 5;\nconst int FRONT_FACING_FLAG = 1 << 6;\n\nmat4 getMatrix(sampler2D texture, int textureSize, int index) {\n  // Unpack 3 x 4 matix columns into a 4 x 4 matrix.\n  vec4 col0 = fetchTexel(texture, textureSize, (index * cols_per_instance) + 0);\n  vec4 col1 = fetchTexel(texture, textureSize, (index * cols_per_instance) + 1);\n  vec4 col2 = fetchTexel(texture, textureSize, (index * cols_per_instance) + 2);\n  mat4 result = mat4(col0, col1, col2, vec4(0.0, 0.0, 0.0, 1.0));\n  return transpose(result);\n  // return mat4(1.0);\n}\n\nmat4 getModelMatrix(int id) {\n  return getMatrix(instancesTexture, instancesTextureSize, id);\n}\nvec4 getInstanceData(int id) {\n  return fetchTexel(instancesTexture, instancesTextureSize, (id * cols_per_instance) + 3);\n}\nvec4 getPivot(int id) {\n  return fetchTexel(instancesTexture, instancesTextureSize, (id * cols_per_instance) + 4);\n}\nvec4 getTintColor(int id) {\n  return fetchTexel(instancesTexture, instancesTextureSize, (id * cols_per_instance) + 5);\n}\n\n#else\n\nuniform vec4 atlasBillboards_desc;\n\nuniform mat4 modelMatrix;\nuniform vec2 pivot;\nuniform vec4 billboardData;\nuniform vec4 tintColor;\nuniform vec4 layoutData;\n\n#endif\n\nuniform int inVR;\n\nmat4 calcAlignToCameraMatrix(mat4 modelMatrix, mat4 cameraMatrix) {\n  vec3 cameraY = vec3(cameraMatrix[1][0], cameraMatrix[1][1], cameraMatrix[1][2]);\n  vec3 cameraZ = vec3(cameraMatrix[2][0], cameraMatrix[2][1], cameraMatrix[2][2]);\n\n  vec3 modelOrigin = vec3(modelMatrix[3][0], modelMatrix[3][1], modelMatrix[3][2]);\n\n  vec3 zAxis = normalize(cameraZ);\n  vec3 xAxis = normalize(cross(cameraY, zAxis));\n  vec3 yAxis = normalize(cross(zAxis, xAxis));\n\n  return mat4(vec4(xAxis, 0.0), vec4(yAxis, 0.0), vec4(zAxis, 0.0), vec4(modelOrigin, 1.0));\n}\n  \n\nmat4 calcAlignToCameraAndXAxisMatrix(mat4 modelMatrix, mat4 cameraMatrix) {\n  vec3 cameraPos = vec3(cameraMatrix[3][0], cameraMatrix[3][1], cameraMatrix[3][2]);\n  vec3 cameraY = vec3(cameraMatrix[1][0], cameraMatrix[1][1], cameraMatrix[1][2]);\n  vec3 cameraZ = vec3(cameraMatrix[2][0], cameraMatrix[2][1], cameraMatrix[2][2]);\n\n  vec3 modelOrigin = vec3(modelMatrix[3][0], modelMatrix[3][1], modelMatrix[3][2]);\n  vec3 modelXAxis = normalize(vec3(modelMatrix[0][0], modelMatrix[0][1], modelMatrix[0][2]));\n  vec3 modelToCamera = normalize(cameraPos - modelOrigin);\n\n  vec3 zAxis;\n  if (isOrthographic > 0) {\n    zAxis = normalize(cameraZ);\n  } else {\n    zAxis = normalize(modelToCamera);\n  }\n  vec3 yAxis = normalize(cross(zAxis, modelXAxis));\n  vec3 xAxis = normalize(cross(zAxis, yAxis));\n\n  if (dot(cameraY, yAxis) < 0.0) {\n    yAxis = -yAxis;\n  }\n\n  return mat4(vec4(xAxis, 0.0), vec4(yAxis, 0.0), vec4(zAxis, 0.0), vec4(modelOrigin, 1.0));\n}\n\nfloat map(float value, float inMin, float inMax, float outMin, float outMax) {\n  return outMin + (outMax - outMin) * (value - inMin) / (inMax - inMin);\n}\n\n/* VS Outputs */\nvarying float v_instanceID;\nvarying vec2 v_texCoord;\nvarying vec4 v_layoutData;\nvarying float v_alpha;\nvarying vec4 v_tint;\nvarying vec3 v_viewPos;\nvarying float v_frontFacing;\n\nvoid main(void) {\n\n#ifdef ENABLE_FLOAT_TEXTURES\n\n  int instanceID = int(instanceIds);\n  v_instanceID = float(instanceID) + 0.25;\n\n  mat4 modelMatrix = getModelMatrix(instanceID);\n  vec2 pivot = getPivot(instanceID).xy;\n  vec4 billboardData = getInstanceData(instanceID);\n  vec4 layoutData = fetchTexel(atlasBillboards_layout, int(atlasBillboards_desc.z), int(billboardData.z));\n  v_tint = getTintColor(instanceID);\n\n#else\n\n  v_tint = tintColor;\n\n#endif\n\n  vec2 quadVertex = getQuadVertexPositionFromID();\n  \n  vec2 pos = quadVertex + vec2(0.5, 0.0) - pivot;\n\n  v_layoutData = layoutData;\n  v_texCoord = vec2(quadVertex.x, -quadVertex.y) + 0.5;\n  v_alpha = billboardData.w;\n\n  float scl = billboardData.x;\n  float width = layoutData.z * atlasBillboards_desc.x * scl;\n  float height = layoutData.w * atlasBillboards_desc.y * scl;\n  int flags = int(billboardData.y);\n\n  // Use cross platform bit flags methods\n  bool alignedToCamera = testFlag(flags, ALIGN_TO_CAMERA_FLAG);\n  bool alignedToCameraAndXAxis = testFlag(flags, ALIGN_TO_CAMERA_AND_AXIS_FLAG);\n  bool drawOnTop = testFlag(flags, DRAW_ON_TOP_FLAG);\n  bool fixedSizeOnscreen = testFlag(flags, FIXED_SIZE_ON_SCREEN_FLAG);\n  bool frontFacing = testFlag(flags, FRONT_FACING_FLAG);\n\n  v_frontFacing = float(frontFacing);\n\n  mat4 modelViewMatrix = viewMatrix * modelMatrix;\n\n  // Note: items in front of the camera will have a negative value here.\n  float sc = 1.0;\n  if (fixedSizeOnscreen) {\n    if (isOrthographic > 0){\n      // At a distance of 1, we should match the orthographic and perspective sizes.\n      // Calculate the size of the handle in perpective projection at 1 meter.\n      // With a 24mm camera, the Fov is 46.4 degrees, or 0.8098327729253689 radians.\n      // (0.81 / 2.0) * focalDist * 2.0\n      // The frustum height at 1m is 0.81.\n      sc = viewportFrustum.y / 0.8098327;\n    } else {\n      sc = -modelViewMatrix[3][2];\n      \n      if (inVR == 1) {\n        // During XR sessions, there is a scaling applied to the view matrix\n        // which causes a distortion to the line width. We extract that scale here\n        // and use to correct the distortion.\n        // See also: FatPointsShader\n        vec3 viewZ = modelViewMatrix[2].xyz;\n        float viewScale = length(viewZ);\n        sc /= viewScale;\n      }\n    }\n  }\n  \n  float aspect = viewportFrustum.x / viewportFrustum.y;\n  if (alignedToCamera || alignedToCameraAndXAxis) {\n    if (alignedToCamera) {\n      mat4 lookAt = calcAlignToCameraMatrix(modelMatrix, cameraMatrix);\n      modelViewMatrix = viewMatrix * lookAt;\n    }\n    else if (alignedToCameraAndXAxis) {\n      // Align the billboard to the camera, while preserving the X axis in the modelMatrix;\n      mat4 lookAt = calcAlignToCameraAndXAxisMatrix(modelMatrix, cameraMatrix);\n      modelViewMatrix = viewMatrix * lookAt;\n    }\n  }\n  v_viewPos =  (modelViewMatrix * vec4(pos.x * width * sc, (pos.y + 0.5) * height * sc, 0.0, 1.0)).xyz;\n  gl_Position = projectionMatrix * vec4(v_viewPos, 1.0);\n  \n\n  // Use cross platform bit flags methods\n  if (drawOnTop) {\n    if (isOrthographic > 0){\n      gl_Position.z = mix(gl_Position.z, -1.0, 0.5);\n    } else {\n      gl_Position.z = mix(gl_Position.z, -gl_Position.z, 0.5);\n    }\n  }\n}\n";class BillboardShader extends GLShader{constructor(A){super(A,"BillboardShader"),this.setShaderStage("VERTEX_SHADER",vert$9),this.setShaderStage("FRAGMENT_SHADER",frag$8)}}var vert$8="\nprecision highp float;\n#define GLSLIFY 1\n\nattribute vec3 positions;    //(location = 0)\n\nuniform mat4 viewMatrix;\nuniform mat4 projectionMatrix;\nuniform vec3 projectionCenter;\n\nimport 'transpose.glsl'\nimport 'GLSLUtils.glsl'\nimport 'stack-gl/transpose.glsl'\nimport 'stack-gl/inverse.glsl'\nimport 'geomItemId.glsl'\nimport 'drawItemTexture.glsl'\nimport 'modelMatrix.glsl'\n\n/* VS Outputs */\nvarying vec3 v_worldDir;\n \nvoid main()\n{\n  int geomItemId = getGeomItemId();\n  vec4 pos = vec4(positions, 1.);\n  mat4 modelMatrix = getModelMatrix(geomItemId);\n  mat4 modelViewProjectionMatrix = projectionMatrix * viewMatrix * modelMatrix;\n\n  gl_Position = modelViewProjectionMatrix * pos;\n\n  vec4 worldPos = modelMatrix * pos;\n  v_worldDir = worldPos.xyz - projectionCenter;\n}\n\n",OctahedralEnvProjectionFrag="\nprecision highp float;\n#define GLSLIFY 1\n\nimport 'GLSLUtils.glsl'\nimport 'envmap-octahedral.glsl'\nimport 'gamma.glsl'\nimport 'materialparams.glsl'\n\nuniform sampler2D envMap;\nuniform int envMapLoaded;\n\n#ifdef ENABLE_INLINE_GAMMACORRECTION\nuniform float exposure;\n#endif\n\nvec4 sampleEnvMap(vec3 dir) {\n  vec2 uv = dirToSphOctUv(dir);\n  vec4 texel = texture2D(envMap, vec2(uv.x, 1.0 - uv.y));\n  return vec4(texel.rgb/texel.a, 1.0); // TODO: Check this line. Do we need it?\n}\n\n/* VS Outputs */\nvarying vec3 v_worldDir;\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\nvoid main(void) {\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  if (envMapLoaded == 0)  {\n    discard;\n    return;\n  }\n\n  fragColor = sampleEnvMap(normalize(v_worldDir));\n\n#ifdef ENABLE_INLINE_GAMMACORRECTION\n  fragColor.rgb = toGamma(fragColor.rgb * exposure);\n#endif\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n";class EnvProjectionShader extends GLShader{constructor(A){super(A,"EnvProjectionShader"),this.setShaderStage("VERTEX_SHADER",vert$8),this.setShaderStage("FRAGMENT_SHADER",OctahedralEnvProjectionFrag)}bind(A,g){if(super.bind(A,g),A instanceof ColorRenderState){const g=A,I=this.__gl,{envMap:C,envMapLoaded:e,exposure:i}=A.unifs;g.envMap&&g.envMap.glTex?(g.envMap.glTex.bindToUniform(A,C),I.uniform1i(e.location,1)):I.uniform1i(e.location,0),i&&I.uniform1f(i.location,g.exposure)}return!0}static supportsInstancing(){return!1}static getMaterialTemplate(){return material$9}}const material$9=new EnvProjectionMaterial;Registry.register("EnvProjectionShader",EnvProjectionShader);var frag$7="\nprecision highp float;\n#define GLSLIFY 1\n\nuniform color BaseColor;\nuniform float Opacity;\nuniform mat4 cameraMatrix;\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\n\n/* VS Outputs */\nvarying vec3 v_viewPos;\nvarying vec3 v_viewNormal;\nvarying vec2 v_texCoord;\nvarying float v_geomItemId;\nvarying vec4 v_geomItemData;\nvarying float v_drawItemID;\nvarying vec3 v_worldPos;\n\nimport 'GLSLUtils.glsl'\nimport 'drawItemTexture.glsl'\nimport 'cutaways.glsl'\nimport 'geometryMask.glsl'\nimport 'GLSLBits.glsl'\nimport 'geomItemFlags.glsl'\n\nuniform int passId;\n\n#if defined(DRAW_HIGHLIGHT)\n  import 'surfaceHighlight.glsl'\n#endif\n\nvoid main(void) {\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n  int geomItemId = int(round(v_geomItemId));\n  int flags = int(round(v_geomItemData.x));\n  float treeItemOpacity = v_geomItemData.y;\n\n  // Cutaways\n  if (testFlag(flags, GEOMITEM_FLAG_CUTAWAY)) {\n    vec4 cutAwayData  = getCutaway(geomItemId);\n    vec3 planeNormal = cutAwayData.xyz;\n    float planeDist = cutAwayData.w;\n    if (length(planeNormal) > 0.5) {\n      if (cutaway(v_worldPos, planeNormal, planeDist)) {\n          discard;\n          return;\n      }\n    } else {\n      if (testGeometryMask(v_viewPos)) {\n        discard;\n        return;\n      }\n    }\n  }\n\n#if defined(DRAW_COLOR)\n  int debugLevel = 0;\n  if (debugLevel == 0) {\n\n    vec3 viewVector = mat3(cameraMatrix) * normalize(-v_viewPos);\n    vec3 normal = mat3(cameraMatrix) * v_viewNormal;\n    float NdotV = dot(normalize(normal), normalize(viewVector));\n\n    // Modulate the lighting using the texture coord so the line looks round.\n    NdotV *= cos((v_texCoord.x - 0.5) * 2.0);\n\n    vec4 color = BaseColor * NdotV;\n    fragColor = vec4(color.rgb, BaseColor.a * Opacity * treeItemOpacity);\n  }\n  else {\n    fragColor = vec4(v_texCoord.x, 0.0, 0.0, 1.0);\n  }\n#elif defined(DRAW_GEOMDATA)\n\n  if (testFlag(flags, GEOMITEM_INVISIBLE_IN_GEOMDATA)) {\n    discard;\n    return;\n  }\n\n  float dist = length(v_viewPos);\n  fragColor.r = float(passId); \n  fragColor.g = float(v_drawItemID);\n  fragColor.b = 0.0;// TODO: store poly-id or something.\n  fragColor.a = dist;\n    \n#elif defined(DRAW_HIGHLIGHT)\n  fragColor = setFragColor_highlight(v_geomItemId);\n#endif\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n",vert$7="\nprecision highp float;\n#define GLSLIFY 1\n\ninstancedattribute vec2 segmentIndices;\nattribute float vertexIDs;\n\nuniform mat4 viewMatrix;\nuniform mat4 projectionMatrix;\nuniform int isOrthographic;\n\nimport 'drawItemTexture.glsl'\nimport 'modelMatrix.glsl'\n\nuniform int geomItemId;\nint getGeomItemId() {\n  return geomItemId;\n}\n\nuniform sampler2D positionsTexture;\nuniform int positionsTextureSize;\n\nuniform float LineThickness;\nuniform float Overlay;\n\nimport 'calcFatLinesViewPos.glsl'\n\nvarying vec3 v_viewPos;\nvarying vec3 v_viewNormal;\nvarying vec2 v_texCoord;\n\nvarying float v_geomItemId;\nvarying vec4 v_geomItemData;\nvarying float v_drawItemID;\nvarying vec3 v_worldPos;\n\nvoid main(void) {\n\n  int geomItemId = getGeomItemId();\n  v_geomItemId = float(geomItemId);\n  v_geomItemData = getInstanceData(geomItemId);\n\n  int vertexID = int(vertexIDs);\n\n  mat4 modelMatrix = getModelMatrix(geomItemId);\n  mat4 modelViewMatrix = viewMatrix * modelMatrix;\n\n  vec3 pos;\n  v_viewPos       = calcFatLinesViewPos(vertexID, modelViewMatrix, v_viewNormal, v_texCoord, pos);\n  v_worldPos      = (modelMatrix * vec4(pos, 1.0)).xyz;\n  v_drawItemID    = float(getGeomItemId());\n\n  gl_Position     = projectionMatrix * vec4(v_viewPos, 1.0);\n\n  if (isOrthographic > 0){\n    gl_Position.z -= mix(gl_Position.z, -1.0, Overlay);\n  } else {\n    gl_Position.z = mix(gl_Position.z, -gl_Position.z, Overlay);\n  }\n\n}\n";class FatLinesShader extends GLShader{constructor(A){super(A,"FatLinesShader"),this.setShaderStage("VERTEX_SHADER",vert$7),this.setShaderStage("FRAGMENT_SHADER",frag$7)}bind(A,g){return!!super.bind(A,g)&&(A.supportsInstancing=!1,!0)}static supportsInstancing(){return!1}static getMaterialTemplate(){return material$8}}const material$8=new FatLinesMaterial("FatLinesShader_template");Registry.register("FatLinesShader",FatLinesShader);var vert$6="\nprecision highp float;\nprecision highp int;\n#define GLSLIFY 1\n\nattribute vec3 positions;\n#ifdef ENABLE_TEXTURES\nattribute vec2 texCoords;\n#endif\n\nuniform mat4 viewMatrix;\nuniform mat4 projectionMatrix;\nuniform int isOrthographic;\n\nimport 'GLSLUtils.glsl'\nimport 'geomItemId.glsl'\nimport 'drawItemTexture.glsl'\nimport 'modelMatrix.glsl'\nimport 'geomItemFlags.glsl'\nimport 'materialparams.glsl'\n\n/* VS Outputs */\nvarying vec4 v_drawItemIds;\nvarying vec4 v_geomItemData;\nvarying vec3 v_viewPos;\n#ifdef ENABLE_TEXTURES\nvarying vec2 v_textureCoord;\n#endif\nvarying vec3 v_worldPos;\n\nvoid main(void) {\n  v_drawItemIds = getDrawItemIds();\n  int geomItemId = int(round(v_drawItemIds.x));\n  v_geomItemData  = getInstanceData(geomItemId);\n\n  mat4 modelMatrix = getModelMatrix(geomItemId);\n  mat4 modelViewMatrix = viewMatrix * modelMatrix;\n\n  vec4 pos = vec4(positions, 1.);\n  vec4 viewPos = (modelViewMatrix * pos);\n  gl_Position = projectionMatrix * viewPos;\n\n  v_viewPos = viewPos.xyz;\n#ifdef ENABLE_TEXTURES\n  v_textureCoord = texCoords;\n  v_textureCoord.y = 1.0 - v_textureCoord.y;// Flip y\n#endif\n\n  //////////////////////////////////////////////\n  // Overlay\n  vec2 materialCoords = v_geomItemData.zw;\n  vec4 materialValue1 = getMaterialValue(materialCoords, 2);\n  float overlay = materialValue1.x;\n\n  if (isOrthographic > 0){\n    gl_Position.z -= overlay;\n  } else {\n    gl_Position.z = mix(gl_Position.z, -gl_Position.z, overlay);\n  }\n\n  //////////////////////////////////////////////\n  \n  v_worldPos      = (modelMatrix * pos).xyz;\n}\n",frag$6="\nprecision highp float;\nprecision highp int;\n#define GLSLIFY 1\n\nimport 'GLSLUtils.glsl'\nimport 'drawItemTexture.glsl'\nimport 'cutaways.glsl'\nimport 'geometryMask.glsl'\nimport 'gamma.glsl'\nimport 'materialparams.glsl'\nimport 'geomItemFlags.glsl'\n\n#ifdef DEBUG_GEOM_ID\nimport 'debugColors.glsl'\n#endif\n\n#ifdef ENABLE_TEXTURES\nuniform sampler2D BaseColorTex;\nuniform int BaseColorTexType;\n#endif\n\n/* VS Outputs */\nvarying vec4 v_drawItemIds;\nvarying vec4 v_geomItemData;\nvarying vec3 v_viewPos;\n#ifdef ENABLE_TEXTURES\nvarying vec2 v_textureCoord;\n#endif\nvarying vec3 v_worldPos;\n\n#ifdef ENABLE_ES3\nout vec4 fragColor;\n#endif\n\n#if defined(DRAW_GEOMDATA)\n  uniform int isOrthographic;\n  import 'surfaceGeomData.glsl'\n#elif defined(DRAW_HIGHLIGHT)\n  import 'surfaceHighlight.glsl'\n#endif // DRAW_HIGHLIGHT\n\nvoid main(void) {\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  int geomItemId = int(round(v_drawItemIds.x));\n  int flags = int(round(v_geomItemData.x));\n  float treeItemOpacity = v_geomItemData.y;\n\n  // We can make geoms invisible to hide them. \n  // Avoid drawing GeomData for geoms that are completely transparent.\n  if (treeItemOpacity < 0.001) {\n    discard;\n    return;\n  }\n  \n  // Cutaways\n  if (testFlag(flags, GEOMITEM_FLAG_CUTAWAY)) \n  {\n    vec4 cutAwayData   = getCutaway(geomItemId);\n    vec3 planeNormal = cutAwayData.xyz;\n    float planeDist = cutAwayData.w;\n    if (length(planeNormal) > 0.5) {\n      if (cutaway(v_worldPos, planeNormal, planeDist)) {\n          discard;\n          return;\n      }\n    } else {\n      if (testGeometryMask(v_viewPos)) {\n        discard;\n        return;\n      }\n    }\n  }\n\n  //////////////////////////////////////////////\n  // Material\n\n  vec2 materialCoords = v_geomItemData.zw;\n  if (v_drawItemIds.z > 0.5) {\n    materialCoords.x = v_drawItemIds.z;\n  }\n  vec4 baseColor = getMaterialValue(materialCoords, 1);\n\n#ifdef ENABLE_TEXTURES\n  getTextureColorValue(baseColor, BaseColorTex, BaseColorTexType, v_textureCoord);\n#endif // ENABLE_TEXTURES\n\n  baseColor.a *= treeItemOpacity;\n\n#if defined(DRAW_COLOR)\n\n  //////////////////////////////////////////////\n  fragColor = baseColor;\n\n#ifdef DEBUG_GEOM_ID\n  // ///////////////////////\n  // Debug Draw ID (this correlates to GeomID within a GLGeomSet)\n  float geomId = v_geomItemData.w;\n  fragColor.rgb = getDebugColor(geomId);\n  // ///////////////////////\n#endif\n\n#ifdef ENABLE_INLINE_GAMMACORRECTION\n  fragColor.rgb = toGamma(fragColor.rgb);\n#endif\n\n#elif defined(DRAW_GEOMDATA)\n\n  fragColor = setFragColor_geomData(v_viewPos, v_drawItemIds.x, v_drawItemIds.y, isOrthographic, flags, TRIANGLES);\n#elif defined(DRAW_HIGHLIGHT)\n  fragColor = setFragColor_highlight(v_drawItemIds.x);\n#endif // DRAW_HIGHLIGHT\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n";class FlatSurfaceShader extends GLShader{constructor(A){super(A,"FlatSurfaceShader"),this.setShaderStage("VERTEX_SHADER",vert$6),this.setShaderStage("FRAGMENT_SHADER",frag$6)}bind(A,g){super.bind(A,g),A.pushGLStack("FlatSurfaceShader.bind");const I=this.__gl;return A.glDisable(I.CULL_FACE),!0}unbind(A){return super.unbind(A),A.popGLStack(),!0}static getPackedMaterialData(A){const g=new Float32Array(12);let I=0;g[4*I+0]=2;const C=A.getParameter("BaseColor");let e;e=C instanceof MaterialColorParam&&C.colorSpace==ColorSpace.Gamma?C.value.toLinear():C.value,I++,g[4*I+0]=e.r,g[4*I+1]=e.g,g[4*I+2]=e.b,g[4*I+3]=e.a,I++;const i=A.getParameter("Overlay");return i&&(g[4*I+0]=i.getValue()),g}static getMaterialTemplate(){return material$7}}const material$7=new FlatSurfaceMaterial("FlatSurfaceShader_template");Registry.register("FlatSurfaceShader",FlatSurfaceShader);var vert$5="\nprecision highp float;\nprecision highp int;\n#define GLSLIFY 1\n\nattribute vec3 positions;\n\nimport 'GLSLUtils.glsl'\nimport 'geomItemId.glsl'\nimport 'drawItemTexture.glsl'\nimport 'modelMatrix.glsl'\nimport 'materialparams.glsl'\n\nuniform mat4 viewMatrix;\nuniform mat4 projectionMatrix;\nuniform int isOrthographic;\n\n/* VS Outputs */\nvarying float v_geomItemId;\nvarying vec4 v_geomItemData;\nvarying vec3 v_viewPos;\nvarying vec3 v_worldPos;\n\nvoid main(void) {\n  int geomItemId = getGeomItemId();\n  v_geomItemId = float(geomItemId);\n  v_geomItemData  = getInstanceData(geomItemId);\n\n  mat4 modelMatrix = getModelMatrix(geomItemId);\n  mat4 modelViewMatrix = viewMatrix * modelMatrix;\n  vec4 viewPos = modelViewMatrix * vec4(positions, 1.0);\n\n  v_viewPos = viewPos.xyz;\n  gl_Position = projectionMatrix * viewPos;\n\n  //////////////////////////////////////////////\n  // Overlay\n  vec2 materialCoords = v_geomItemData.zw;\n  vec4 materialValue1 = getMaterialValue(materialCoords, 2);\n  float overlay = materialValue1.y;\n   \n#if defined(DRAW_GEOMDATA)\n  float _overlay = mix(overlay, 1.0, 0.0001);\n#else\n  float _overlay = overlay;\n#endif\n\n  if (isOrthographic > 0){\n    gl_Position.z -= _overlay;\n  } else {\n    gl_Position.z = mix(gl_Position.z, -gl_Position.z, _overlay);\n  }\n  \n  vec4 pos = vec4(positions, 1.);\n  v_worldPos      = (modelMatrix * pos).xyz;\n}\n",frag$5="\nprecision highp float;\nprecision highp int;\n#define GLSLIFY 1\n\nimport 'GLSLUtils.glsl'\nimport 'drawItemTexture.glsl'\nimport 'cutaways.glsl'\nimport 'geometryMask.glsl'\nimport 'materialparams.glsl'\nimport 'geomItemFlags.glsl'\n\n#if defined(DRAW_COLOR)\n\nuniform int occluded;\nuniform vec4 hiddenLineColor;\n\n#elif defined(DRAW_GEOMDATA)\n\nuniform int isOrthographic;\nimport 'surfaceGeomData.glsl'\n\n#elif defined(DRAW_HIGHLIGHT)\n\n#ifdef ENABLE_FLOAT_TEXTURES\nvec4 getHighlightColor(int id) {\n  return fetchTexel(instancesTexture, instancesTextureSize, (id * pixelsPerItem) + 4);\n}\n#else // ENABLE_FLOAT_TEXTURES\n\nuniform vec4 highlightColor;\n\nvec4 getHighlightColor() {\n  return highlightColor;\n}\n\n#endif // ENABLE_FLOAT_TEXTURES\n\n#endif // DRAW_HIGHLIGHT\n\n/* VS Outputs */\nvarying float v_geomItemId;\nvarying vec4 v_geomItemData;\nvarying vec3 v_viewPos;\nvarying vec3 v_worldPos;\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\n\nvoid main(void) {\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  int geomItemId = int(round(v_geomItemId));\n  int flags = int(round(v_geomItemData.x));\n  float treeItemOpacity = v_geomItemData.y;\n\n  // Cutaways\n  if (testFlag(flags, GEOMITEM_FLAG_CUTAWAY)) \n  {\n    vec4 cutAwayData   = getCutaway(geomItemId);\n    vec3 planeNormal = cutAwayData.xyz;\n    float planeDist = cutAwayData.w;\n    if (length(planeNormal) > 0.5) {\n      if (cutaway(v_worldPos, planeNormal, planeDist)) {\n          discard;\n          return;\n      }\n    } else {\n      if (testGeometryMask(v_viewPos)) {\n        discard;\n        return;\n      }\n    }\n  }\n\n  //////////////////////////////////////////////\n  // Material\n  vec2 materialCoords = v_geomItemData.zw;\n  vec4 BaseColor = getMaterialValue(materialCoords, 1);\n  vec4 matValue1 = getMaterialValue(materialCoords, 2);\n  vec4 matValue2 = getMaterialValue(materialCoords, 3);\n  float Opacity  = matValue1.r;\n\n  //////////////////////////////////////////////\n  // Color\n#if defined(DRAW_COLOR)\n\n  fragColor = BaseColor;\n  \n  if (occluded == 1) {\n    fragColor = hiddenLineColor;\n  }\n\n  fragColor.a *= Opacity * treeItemOpacity;\n\n  //////////////////////////////////////////////\n  // GeomData\n#elif defined(DRAW_GEOMDATA)\n\n  fragColor = setFragColor_geomData(v_viewPos, v_geomItemId, 0.0, isOrthographic, flags, LINES);\n  \n  //////////////////////////////////////////////\n  // Highlight\n#elif defined(DRAW_HIGHLIGHT)\n  \n  fragColor = getHighlightColor(geomItemId);\n\n#endif // DRAW_HIGHLIGHT\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n";class LinesShader extends GLShader{constructor(A){super(A,"LinesShader"),this.setShaderStage("VERTEX_SHADER",vert$5),this.setShaderStage("FRAGMENT_SHADER",frag$5)}static getPackedMaterialData(A){const g=new Float32Array(12);let I=0;g[4*I+0]=3;const C=A.getParameter("BaseColor");let e;return e=C instanceof MaterialColorParam&&C.colorSpace==ColorSpace.Gamma?C.value.toLinear():C.value,I++,g[4*I+0]=e.r,g[4*I+1]=e.g,g[4*I+2]=e.b,g[4*I+3]=e.a,I++,g[4*I+0]=A.getParameter("Opacity").value,g[4*I+1]=A.getParameter("Overlay").value,g}static getMaterialTemplate(){return material$6}}const material$6=new LinesMaterial("LinesShader_template");Registry.register("LinesShader",LinesShader);var frag$4="\nprecision highp float;\n#define GLSLIFY 1\n\nimport 'GLSLUtils.glsl'\nimport 'drawItemTexture.glsl'\nimport 'cutaways.glsl'\nimport 'geometryMask.glsl'\nimport 'materialparams.glsl'\nimport 'geomItemFlags.glsl'\nimport 'surfaceGeomData.glsl'\n\n#if defined(DRAW_GEOMDATA)\n\nimport 'GLSLBits.glsl'\nuniform highp int isOrthographic;\n\n#elif defined(DRAW_HIGHLIGHT)\n\n#ifdef ENABLE_FLOAT_TEXTURES\nvec4 getHighlightColor(int id) {\n  return fetchTexel(instancesTexture, instancesTextureSize, (id * pixelsPerItem) + 4);\n}\n#else // ENABLE_FLOAT_TEXTURES\n\nuniform vec4 highlightColor;\n\nvec4 getHighlightColor() {\n  return highlightColor;\n}\n\n#endif // ENABLE_FLOAT_TEXTURES\n\n#endif // DRAW_HIGHLIGHT\n\n/* VS Outputs */\nvarying vec2 v_drawItemIds;\nvarying vec4 v_geomItemData;\nvarying vec3 v_viewPos;\n/* VS Outputs */\n\n#ifdef ENABLE_ES3\nout vec4 fragColor;\n#endif\n\nvoid main(void) {\n\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  //////////////////////////////////////////////\n  // Color\n#if defined(DRAW_COLOR)\n\n  vec2 materialCoords = v_geomItemData.zw;\n  vec4 baseColor = getMaterialValue(materialCoords, 1);\n  vec4 matValue1 = getMaterialValue(materialCoords, 2);\n  float pointSize     = baseColor.a * matValue1.r;\n  float overlay       = matValue1.g;\n\n  fragColor = baseColor;\n\n  //////////////////////////////////////////////\n  // GeomData\n#elif defined(DRAW_GEOMDATA)\n\n  fragColor = setFragColor_geomData(v_viewPos, v_drawItemIds.x, v_drawItemIds.y, isOrthographic, 0, POINTS);\n\n  //////////////////////////////////////////////\n  // Highlight\n#elif defined(DRAW_HIGHLIGHT)\n  \n  int geomItemId = int(round(v_drawItemIds.x));\n  fragColor = getHighlightColor(geomItemId);\n\n#endif // DRAW_HIGHLIGHT\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n",vert$4="\nprecision highp float;\n#define GLSLIFY 1\n\nattribute vec3 positions;\n\nimport 'GLSLUtils.glsl'\nimport 'geomItemId.glsl'\nimport 'drawItemTexture.glsl'\nimport 'modelMatrix.glsl'\nimport 'materialparams.glsl'\n\nuniform mat4 viewMatrix;\nuniform mat4 projectionMatrix;\nuniform int isOrthographic;\n\n/* VS Outputs */\nvarying vec2 v_drawItemIds;\nvarying vec4 v_geomItemData;\nvarying vec3 v_viewPos;\n\nvoid main(void) {\n  int geomItemId = getGeomItemId();\n  v_drawItemIds.x = float(geomItemId);\n  v_drawItemIds.y = float(gl_VertexID);\n  v_geomItemData  = getInstanceData(geomItemId);\n\n  mat4 modelMatrix = getModelMatrix(geomItemId);\n  mat4 modelViewMatrix = viewMatrix * modelMatrix;\n  \n  vec4 viewPos = modelViewMatrix * vec4(positions, 1.);\n  gl_Position = projectionMatrix * viewPos;\n  \n\n  //////////////////////////////////////////////\n  // Material\n  vec2 materialCoords = v_geomItemData.zw;\n  vec4 materialValue1 = getMaterialValue(materialCoords, 2);\n  float pointSize = materialValue1.x;\n  float overlay = materialValue1.y;\n\n  //////////////////////////////////////////////\n\n  // Note: as of 22/01/2021 gl_PointSize has stopped working again...\n  // It is working again now in Chrome\n  gl_PointSize = pointSize * 1.0 / length(viewPos.xyz);\n\n  if (isOrthographic > 0){\n    gl_Position.z -= overlay;\n  } else {\n    gl_Position.z = mix(gl_Position.z, -gl_Position.z, overlay);\n  }\n  \n  v_viewPos = -viewPos.xyz;\n}\n";class PointsShader extends GLShader{constructor(A){super(A,"PointsShader"),this.setShaderStage("VERTEX_SHADER",vert$4),this.setShaderStage("FRAGMENT_SHADER",frag$4)}static getPackedMaterialData(A){const g=new Float32Array(12);let I=0;g[4*I+0]=4;const C=A.getParameter("BaseColor");let e;return e=C instanceof MaterialColorParam&&C.colorSpace==ColorSpace.Gamma?C.value.toLinear():C.value,I++,g[4*I+0]=e.r,g[4*I+1]=e.g,g[4*I+2]=e.b,g[4*I+3]=e.a,I++,g[4*I+0]=A.getParameter("PointSize").value,g[4*I+1]=A.getParameter("Overlay").value,g}static getMaterialTemplate(){return material$5}}const material$5=new PointsMaterial("PointsShader_template");Registry.register("PointsShader",PointsShader);var vert$3="\nprecision highp float;\nprecision highp int;\n#define GLSLIFY 1\n\ninstancedattribute int drawIndices;\nuniform sampler2D pointsAttributes;\nuniform int texelsPerPoint;\n\nuniform mat4 viewMatrix;\nuniform mat4 projectionMatrix;\nuniform int isOrthographic;\n\nimport 'GLSLUtils.glsl' \nimport 'inverse.glsl'\nimport 'drawItemTexture.glsl'\nimport 'geomItemId.glsl'\nimport 'modelMatrix.glsl'\nimport 'quadVertexFromID.glsl'\nimport 'materialparams.glsl'\n\n/* VS Outputs */\nvarying vec4 v_drawItemIds;\nvarying vec4 v_geomItemData;\nvarying vec3 v_texCoord;\nvarying vec3 v_viewPos;\nvarying vec4 v_color;\n\nvoid main(void) {\n  int geomItemId = getGeomItemId();\n  v_geomItemData  = getInstanceData(geomItemId);\n\n  vec2 quadPointPos = getQuadVertexPositionFromID();\n  v_texCoord.xy = vec2(quadPointPos.x, -quadPointPos.y) + 0.5;\n\n  mat4 modelMatrix = getModelMatrix(geomItemId);\n  mat4 modelViewMatrix = viewMatrix * modelMatrix;\n\n  ivec2 texSize = textureSize(pointsAttributes, 0);\n  int texelIndex = drawIndices * texelsPerPoint;\n  ivec2 texelCoord = ivec2(\n    texelIndex % texSize.x, \n    texelIndex / texSize.x\n  );\n  vec4 texel0 = texelFetch(pointsAttributes, texelCoord, 0);\n\n  vec3 pos = texel0.xyz;\n  float size = texel0.w;\n\n  if (texelsPerPoint >= 2) {\n    vec4 texel1 = texelFetch(pointsAttributes, ivec2(texelCoord.x + 1, texelCoord.y), 0);\n    v_color = texel1;\n  } else {\n    v_color = vec4(1., 1., 1., 1.);\n  }\n\n  if (texelsPerPoint >= 3) {\n    vec4 texel2 = texelFetch(pointsAttributes, ivec2(texelCoord.x + 2, texelCoord.y), 0);\n    v_texCoord.z = texel2.x;\n  } else {\n    v_texCoord.z = -1.0;\n  }\n  \n  //////////////////////////////////////////////\n  // Material\n  vec2 materialCoords = v_geomItemData.zw;\n  vec4 materialValue1 = getMaterialValue(materialCoords, 1);\n  float pointSize = materialValue1.r * size;\n  float overlay = materialValue1.b;\n\n  vec4 viewPos = modelViewMatrix * vec4(pos, 1.0);\n\n  // During XR sessions, there is a scaling applied to the view matrix\n  // which causes a distortion to the line width. We extract that scale here\n  // and use to correct the distortion.\n  // See also: FatLinesShader\n  vec3 viewZ = modelViewMatrix[2].xyz;\n  float viewScale = length(viewZ);\n  viewPos += vec4(vec3(quadPointPos, 0.0) * pointSize * viewScale, 0.);\n\n  // Generate a quad which is 0.5 * PointSize closer towards\n  // us. This allows points to be visualized even if snug on \n  // a surface. (else they get fully clipped)\n  viewPos.z += 0.5 * pointSize;\n\n  v_drawItemIds.x = float(geomItemId);\n  v_drawItemIds.y = float(drawIndices);\n  v_viewPos = -viewPos.xyz;\n  \n  gl_Position = projectionMatrix * viewPos;\n\n  if (isOrthographic > 0){\n    gl_Position.z -= overlay;\n  } else {\n    gl_Position.z = mix(gl_Position.z, -gl_Position.z, overlay);\n  }\n}\n",frag$3="\nprecision highp float;\nprecision highp int;\n#define GLSLIFY 1\n\nimport 'constants.glsl'\nimport 'GLSLUtils.glsl'\nimport 'materialparams.glsl'\n\nuniform sampler2D BaseColorTex;\nuniform int BaseColorTexType;\nuniform int highlightSubIndex;\n\nuniform sampler2D atlasSprites;\nuniform sampler2D atlasSprites_layout;\nuniform vec4 atlasSprites_desc;\n\n/* VS Outputs */\nvarying vec4 v_drawItemIds;\nvarying vec4 v_geomItemData;\nvarying vec3 v_texCoord;\nvarying vec3 v_viewPos;\nvarying vec4 v_color;\n\nvec4 sampleSpriteAtlas(int spriteCoord) {\n  ivec2 atlasSpritesSize = textureSize(atlasSprites_layout, 0);\n  // round to an integer, and avoid floating point issues by adding a small value\n  ivec2 texelCoord = ivec2(\n    spriteCoord % atlasSpritesSize.x, \n    spriteCoord / atlasSpritesSize.x\n  );\n  vec4 layoutData = fetchTexel(atlasSprites_layout, atlasSpritesSize, spriteCoord);\n  vec2 spriteTexCoord = v_texCoord.xy;\n  spriteTexCoord *= layoutData.zw;\n  spriteTexCoord += layoutData.xy;\n  return texture2D(atlasSprites, spriteTexCoord);\n}\n\n#ifdef ENABLE_ES3\nout vec4 fragColor;\n#endif\n\n#if defined(DRAW_GEOMDATA)\n  uniform int isOrthographic;\n  import 'surfaceGeomData.glsl'\n#elif defined(DRAW_HIGHLIGHT)\n  import 'surfaceHighlight.glsl'\n#endif // DRAW_HIGHLIGHT\n\nvoid main(void) {\n\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n#if defined(DRAW_COLOR)\n\n  vec2 materialCoords = v_geomItemData.zw;\n  vec4 baseColor = getMaterialValue(materialCoords, 0);\n  vec4 matValue1 = getMaterialValue(materialCoords, 1);\n  float pointSize     = matValue1.r;\n  float borderWidth   = matValue1.g;\n\n  if (v_texCoord.z > -0.5) {\n    int spriteCoord = int(v_texCoord.z + 0.1);\n    baseColor = sampleSpriteAtlas(spriteCoord) * v_color;\n    if (baseColor.a < 0.0001) discard;\n  } else {\n    \n    float dist = length(v_texCoord.xy - 0.5);\n    if (dist > 0.5) discard;\n\n    if (dist > 0.5 - (borderWidth * 0.5))\n      baseColor = vec4(0.,0.,0.,1.);\n    else {\n      baseColor = baseColor * v_color;\n      ivec2 texSize = textureSize(BaseColorTex, 0);\n      if (texSize.x == 1 && texSize.y > 1) {\n        vec4 gradient = texture2D(BaseColorTex, vec2(0.5, dist * 2.0));\n        baseColor *= gradient;\n      }\n    }\n  }\n\n  fragColor = baseColor;\n#elif defined(DRAW_GEOMDATA)\n  fragColor = setFragColor_geomData(v_viewPos, v_drawItemIds.x, v_drawItemIds.y, isOrthographic, 0, POINTS);\n#elif defined(DRAW_HIGHLIGHT)\n  if (highlightSubIndex != -1 && int(round(v_drawItemIds.y)) != highlightSubIndex) discard;\n  fragColor = setFragColor_highlight(v_drawItemIds.x);\n#endif // DRAW_HIGHLIGHT\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n";class FatPointsShader extends GLShader{constructor(A){super(A,"FatPointsShader"),this.setShaderStage("VERTEX_SHADER",vert$3),this.setShaderStage("FRAGMENT_SHADER",frag$3)}bind(A,g){if(super.bind(A,g)){A.supportsInstancing=!1;const g=this.__gl;return g.__quadVertexIdsBuffer||g.setupInstancedQuad(),A.shaderInstancedGeom={attrBuffers:g.__quadattrbuffers,indexBuffer:g.__quadIndexBuffer,indexDataType:g.UNSIGNED_BYTE,numVertices:4,numTriIndices:6},A.supportsInstancing=!1,!0}return!1}static getPackedMaterialData(A){const g=new Float32Array(8),I=A.getParameter("BaseColor");let C;C=I instanceof MaterialColorParam&&I.colorSpace==ColorSpace.Gamma?I.value.toLinear():I.value;let e=0;return g[4*e+0]=C.r,g[4*e+1]=C.g,g[4*e+2]=C.b,g[4*e+3]=C.a,e++,g[4*e+0]=A.getParameter("PointSize").value,g[4*e+1]=A.getParameter("BorderWidth").value,g[4*e+2]=A.getParameter("Overlay").value,g}static supportsInstancing(){return!1}static getMaterialTemplate(){return material$4}}const material$4=new FatPointsMaterial("FatPointsShader_template");Registry.register("FatPointsShader",FatPointsShader);var frag$2="precision highp float;\n#define GLSLIFY 1\n\nimport 'GLSLUtils.glsl'\nimport 'drawItemTexture.glsl'\nimport 'cutaways.glsl'\nimport 'geometryMask.glsl'\nimport 'gamma.glsl'\nimport 'materialparams.glsl'\nimport 'geomItemFlags.glsl'\n\n#ifdef DEBUG_GEOM_ID\nimport 'debugColors.glsl'\n#endif\n\n/* VS Outputs */\nvarying vec4 v_drawItemIds;\nvarying vec4 v_geomItemData;\nvarying vec3 v_viewPos;\nvarying vec3 v_viewNormal;\n#ifdef ENABLE_TEXTURES\nvarying vec2 v_textureCoord;\n#endif\nvarying vec3 v_worldPos;\n/* VS Outputs */\n\nuniform mat4 cameraMatrix;\nuniform int isOrthographic;\n\n#ifdef ENABLE_ES3\n    out vec4 fragColor;\n#endif\n\n#if defined(DRAW_COLOR)\n\n#ifdef ENABLE_TEXTURES\nuniform sampler2D BaseColorTex;\nuniform int BaseColorTexType;\nuniform sampler2D OpacityTex;\nuniform int OpacityTexType;\nuniform sampler2D EmissiveStrengthTex;\nuniform int EmissiveStrengthTexType;\n#endif // ENABLE_TEXTURES\n\nimport 'computeViewNormal.glsl'\n  \n// end DRAW_COLOR\n#elif defined(DRAW_GEOMDATA)\n  import 'surfaceGeomData.glsl'\n#elif defined(DRAW_HIGHLIGHT)\n  import 'surfaceHighlight.glsl'\n#endif // DRAW_HIGHLIGHT\n\nvoid main(void) {\n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n  int geomItemId = int(round(v_drawItemIds.x));\n  int elemId = int(round(v_drawItemIds.y));\n  int perFaceMaterialId = int(round(v_drawItemIds.z));\n  int flags = int(round(v_geomItemData.x));\n  float treeItemOpacity = v_geomItemData.y;\n\n  // We can make geoms invisible to hide them. \n  // Avoid drawing GeomData for geoms that are completely transparent.\n  if (treeItemOpacity < 0.001 && !testFlag(flags, GEOMITEM_MASK)) {\n    discard;\n    return;\n  }\n  \n  // Cutaways\n  if (testFlag(flags, GEOMITEM_FLAG_CUTAWAY)) \n  {\n    vec4 cutAwayData   = getCutaway(geomItemId);\n    vec3 planeNormal = cutAwayData.xyz;\n    float planeDist = cutAwayData.w;\n    if (length(planeNormal) > 0.5) {\n      if (cutaway(v_worldPos, planeNormal, planeDist)) {\n          discard;\n          return;\n      }\n    } else {\n      if (testGeometryMask(v_viewPos)) {\n        discard;\n        return;\n      }\n    }\n  }\n\n#if defined(DRAW_COLOR)\n\n  //////////////////////////////////////////////\n  // Normals\n  \n  vec3 viewNormal;\n  if (length(v_viewNormal) < 0.1) {\n    viewNormal = computeViewNormal(v_viewPos);\n  } else {\n    viewNormal = normalize(v_viewNormal);\n  }\n  vec3 normal = normalize(mat3(cameraMatrix) * viewNormal);\n  \n  vec3 viewVector;\n  if (isOrthographic == 0)\n    viewVector = normalize(mat3(cameraMatrix) * normalize(v_viewPos));\n  else \n    viewVector = vec3(-cameraMatrix[2][0], -cameraMatrix[2][1], -cameraMatrix[2][2]);\n  \n  //////////////////////////////////////////////\n  // Material\n\n  vec2 materialCoords = v_geomItemData.zw;\n  if (perFaceMaterialId > 0) {\n    materialCoords.x = float(perFaceMaterialId);\n  }\n  vec4 baseColor      = getMaterialValue(materialCoords, 1);\n  vec4 matValue1      = getMaterialValue(materialCoords, 2);\n  float opacity       = baseColor.a * matValue1.r;\n  float emission      = matValue1.g;\n\n#ifdef ENABLE_TEXTURES\n  getTextureColorValue(baseColor, BaseColorTex, BaseColorTexType, v_textureCoord);\n  getTextureLuminanceValue(opacity, OpacityTex, OpacityTexType, v_textureCoord);\n  getTextureLuminanceValue(emission, EmissiveStrengthTex, EmissiveStrengthTexType, v_textureCoord);\n#endif\n\n  // Cutaways\n  if (testFlag(flags, GEOMITEM_FLAG_CUTAWAY) && !gl_FrontFacing) {\n    fragColor = baseColor;\n  } else {\n    // Hacky simple irradiance. \n    float ndotv = dot(normal, viewVector);\n    if (ndotv < 0.0) {\n      normal = -normal;\n      ndotv = dot(normal, viewVector);\n\n      // Note: these 2 lines can be used to debug inverted meshes.\n      //baseColor = vec4(1.0, 0.0, 0.0, 1.0);\n      //ndotv = 1.0;\n    }\n\n    fragColor = vec4((ndotv * baseColor.rgb) + (emission * baseColor.rgb), opacity);\n  }\n\n  // Note: the 'treeItemOpacity' is not an input to the lighting, \n  // as we want to also blend off the specular reflections to make an object\n  // fade away to nothing. (not become a transparent glass object).\n  fragColor.a *= treeItemOpacity;\n\n#ifdef DEBUG_GEOM_ID\n  // ///////////////////////\n  // Debug Draw ID (this correlates to GeomID within a GLGeomSet)\n  float geomId = v_geomItemData.w;\n  fragColor.rgb = getDebugColor(geomId);\n  // ///////////////////////\n#endif\n\n#ifdef ENABLE_INLINE_GAMMACORRECTION\n  fragColor.rgb = toGamma(fragColor.rgb);\n#endif\n\n#elif defined(DRAW_GEOMDATA)\n  fragColor = setFragColor_geomData(v_viewPos, v_drawItemIds.x, v_drawItemIds.y, isOrthographic, flags, TRIANGLES);\n#elif defined(DRAW_HIGHLIGHT)\n  fragColor = setFragColor_highlight(v_drawItemIds.x);\n#endif // DRAW_HIGHLIGHT\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}",vert$2="precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 positions;\nattribute vec3 normals;\n#ifdef ENABLE_TEXTURES\nattribute vec2 texCoords;\n#endif\n\nuniform mat4 viewMatrix;\nuniform mat4 projectionMatrix;\n\nimport 'GLSLUtils.glsl'\nimport 'transpose.glsl'\nimport 'inverse.glsl'\nimport 'geomItemId.glsl'\nimport 'drawItemTexture.glsl'\nimport 'modelMatrix.glsl'\n\n/* VS Outputs */\nvarying vec4 v_drawItemIds;\nvarying vec4 v_geomItemData;\nvarying vec3 v_viewPos;\nvarying vec3 v_viewNormal;\n#ifdef ENABLE_TEXTURES\nvarying vec2 v_textureCoord;\n#endif\nvarying vec3 v_worldPos;\n\nvoid main(void) {\n  v_drawItemIds = getDrawItemIds();\n  int geomItemId = int(round(v_drawItemIds.x));\n  v_geomItemData  = getInstanceData(geomItemId);\n\n  mat4 modelMatrix = getModelMatrix(geomItemId);\n  mat4 modelViewMatrix = viewMatrix * modelMatrix;\n\n  vec4 pos = vec4(positions, 1.);\n  vec4 viewPos    = modelViewMatrix * pos;\n  gl_Position     = projectionMatrix * viewPos;\n\n  mat3 normalMatrix = mat3(transpose(inverse(modelViewMatrix)));\n  v_viewPos       = -viewPos.xyz;\n  v_viewNormal    = normalMatrix * normals; // Note: we normalize in the fragment shader.\n\n#ifdef ENABLE_TEXTURES\n  v_textureCoord = texCoords;\n  v_textureCoord.y = 1.0 - v_textureCoord.y;// Flip y\n#endif\n\n  v_worldPos      = (modelMatrix * pos).xyz;\n}\n";class SimpleSurfaceShader extends GLShader{constructor(A){super(A,"SimpleSurfaceShader"),this.setShaderStage("VERTEX_SHADER",vert$2),this.setShaderStage("FRAGMENT_SHADER",frag$2)}static getPackedMaterialData(A){const g=new Float32Array(12);let I=0;g[4*I+0]=6;const C=A.getParameter("BaseColor");let e;return e=C instanceof MaterialColorParam&&C.colorSpace==ColorSpace.Gamma?C.value.toLinear():C.value,I++,g[4*I+0]=e.r,g[4*I+1]=e.g,g[4*I+2]=e.b,g[4*I+3]=e.a,I++,g[4*I+0]=A.getParameter("Opacity").value,g[4*I+1]=A.getParameter("EmissiveStrength").value,g}static getMaterialTemplate(){return material$3}}const material$3=new SimpleSurfaceMaterial("SimpleSurfaceShader_template");Registry.register("SimpleSurfaceShader",SimpleSurfaceShader);var vert$1="\nprecision highp float;\nprecision highp int;\n#define GLSLIFY 1\n\nattribute vec3 positions;\nattribute vec3 normals;\n#ifdef ENABLE_TEXTURES\nattribute vec2 texCoords;\n#endif\n\nuniform mat4 viewMatrix;\nuniform mat4 projectionMatrix;\nuniform int isOrthographic;\n\n// Now that we render multiple types of geometry from a single shader\n// we need to know what kind of geometry it is...\nuniform int geomType;\n\nuniform float outlineThickness;\nuniform vec2 viewportSize;\n\n// should be imported by bottom 3\nimport 'GLSLUtils.glsl'\nimport 'transpose.glsl'\nimport 'inverse.glsl'\n\nimport 'geomItemId.glsl'\nimport 'geomType.glsl'\nimport 'drawItemTexture.glsl'\nimport 'modelMatrix.glsl'\nimport 'geomItemFlags.glsl'\nimport 'materialparams.glsl'\n\n/* VS Outputs */\nvarying vec4 v_drawItemIds;\nvarying vec4 v_geomItemData;\nvarying vec3 v_viewPos;\nvarying vec3 v_viewNormal;\n#ifdef ENABLE_TEXTURES\nvarying vec2 v_textureCoord;\n#endif\nvarying vec3 v_worldPos;\n/* VS Outputs */\n\n#if defined(DRAW_COLOR)\n#elif defined(DRAW_GEOMDATA)\n#elif defined(DRAW_HIGHLIGHT)\n#endif // DRAW_HIGHLIGHT\n\nvoid main(void) {\n\n  v_drawItemIds = getDrawItemIds();\n  int geomItemId = int(round(v_drawItemIds.x));\n  v_geomItemData = getInstanceData(geomItemId);\n  mat4 modelMatrix = getModelMatrix(geomItemId);\n\n  vec4 pos = vec4(positions, 1.);\n  mat4 modelViewMatrix = viewMatrix * modelMatrix;\n  vec4 viewPos    = modelViewMatrix * pos;\n  gl_Position     = projectionMatrix * viewPos;\n  v_viewPos       = -viewPos.xyz;\n  v_worldPos      = (modelMatrix * pos).xyz;\n\n  mat3 normalMatrix = mat3(transpose(inverse(modelViewMatrix)));\n  v_viewNormal    = normalMatrix * normals; // Note: we normalize in the fragment shader.\n  \n  // offset slightly the lines and points to make them clearly defined.\n  // This ensures that lines drawn over surfaces are solid and not clipped\n  // at all by the surface.\n  if (geomType == TRIANGLES) {\n    if (outlineThickness > 0.00001) {\n      vec2 screenNormal = v_viewNormal.xy;\n      gl_Position.xy += normalize(screenNormal) * ((2.0 / viewportSize) * outlineThickness) * gl_Position.w;\n    }\n  }\n  \n  //////////////////////////////////////////////\n  // Overlay\n  float viewDepth = v_viewPos.z;\n    \n  vec2 materialCoords = v_geomItemData.zw;\n  vec4 materialValue2 = getMaterialValue(materialCoords, 3);\n  vec4 materialValue5 = getMaterialValue(materialCoords, 6);\n  float overlay = materialValue2.b;\n  float pointSize = materialValue5.r;\n\n  if (geomType == POINTS) { // start 'POINTS'\n    // Fixed size on screen points.\n    gl_PointSize = pointSize;\n    overlay += 0.000005 / viewDepth;\n  }  // end 'POINTS'\n\n  if (isOrthographic > 0){\n    gl_Position.z -= overlay;\n  } else {\n    gl_Position.z = mix(gl_Position.z, -gl_Position.z, overlay);\n  }\n\n#ifdef ENABLE_TEXTURES\n  v_textureCoord = texCoords;\n  v_textureCoord.y = 1.0 - v_textureCoord.y;// Flip y\n#endif\n\n}\n",frag$1="precision highp float;\nprecision highp int;\n#define GLSLIFY 1\nimport 'GLSLUtils.glsl'\nimport 'drawItemTexture.glsl' \nimport 'cutaways.glsl'\nimport 'geometryMask.glsl'\nimport 'gamma.glsl'\nimport 'materialparams.glsl'\nimport 'GLSLBits.glsl'\nimport 'geomItemFlags.glsl'\n\n/* VS Outputs */\nvarying vec4 v_drawItemIds;\nvarying vec4 v_geomItemData;\nvarying vec3 v_viewPos;\nvarying vec3 v_viewNormal;\n#ifdef ENABLE_TEXTURES\nvarying vec2 v_textureCoord;\n#endif\nvarying vec3 v_worldPos;\n/* VS Outputs */\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\n\n// Now that we render multiple types of geometry from a single shader\n// we need to know what kind of geometry it is...\nuniform int geomType;\nimport 'geomType.glsl'\n\nuniform int isOrthographic;\n\n#if defined(DRAW_COLOR)\n\nuniform int renderMode;\nuniform int occluded;\nuniform float outlineThickness;\nuniform vec4 hiddenLineColor;\n\n#ifdef ENABLE_INLINE_GAMMACORRECTION\nuniform float exposure;\n#endif\n\nuniform mat4 cameraMatrix;\n\n#ifdef ENABLE_TEXTURES\nuniform sampler2D BaseColorTex;\nuniform int BaseColorTexType;\n\nuniform sampler2D AmbientOcclusionTex;\nuniform int AmbientOcclusionTexType;\n\n#ifdef ENABLE_PBR\nuniform sampler2D RoughnessTex;\nuniform int RoughnessTexType;\n\nuniform sampler2D MetallicTex;\nuniform int MetallicTexType;\n\nuniform sampler2D ReflectanceTex;\nuniform int ReflectanceTexType;\n\nuniform sampler2D NormalTex;\nuniform int NormalTexType;\n#endif // ENABLE_PBR\n\nuniform sampler2D EmissiveStrengthTex;\nuniform int EmissiveStrengthTexType;\n\n#endif // ENABLE_TEXTURES\n\nimport 'PBRSurfaceRadiance.glsl'\n\n#ifdef ENABLE_PBR\nmat3 cotangentFrame( in vec3 normal, in vec3 pos, in vec2 texCoord ) {\n  // https://stackoverflow.com/questions/5255806/how-to-calculate-tangent-and-binormal\n  vec3 n = normal;\n  // derivations of the fragment position\n  vec3 pos_dx = dFdx( pos );\n  vec3 pos_dy = dFdy( pos );\n  // derivations of the texture coordinate\n  vec2 texC_dx = dFdx( texCoord );\n  vec2 texC_dy = dFdy( texCoord );\n  // tangent vector and binormal vector\n  vec3 t = -(texC_dy.y * pos_dx - texC_dx.y * pos_dy);\n  vec3 b = -(texC_dx.x * pos_dy - texC_dy.x * pos_dx);\n\n  t = t - n * dot( t, n ); // orthonormalization ot the tangent vectors\n  b = b - n * dot( b, n ); // orthonormalization of the binormal vectors to the normal vector\n  b = b - t * dot( b, t ); // orthonormalization of the binormal vectors to the tangent vector\n  mat3 tbn = mat3( normalize(t), normalize(b), n );\n\n  return tbn;\n}\n#endif\n\nimport 'computeViewNormal.glsl'\n\n#ifdef DEBUG_GEOM_ID\nimport 'debugColors.glsl'\n#endif\n\n// end DRAW_COLOR\n#elif defined(DRAW_GEOMDATA)\n\nimport 'surfaceGeomData.glsl'\n\n#elif defined(DRAW_HIGHLIGHT)\nimport 'surfaceHighlight.glsl'\n#endif // DRAW_HIGHLIGHT\n\nvoid main(void) {\n  #ifndef ENABLE_ES3\n    vec4 fragColor;\n  #endif\n  \n  int geomItemId = int(round(v_drawItemIds.x));\n  int elemId = int(round(v_drawItemIds.y));\n  int perElementMaterialId = int(round(v_drawItemIds.z));\n  int flags = int(round(v_geomItemData.x));\n  float treeItemOpacity = v_geomItemData.y;\n\n  // We can make geoms invisible to hide them. \n  // Avoid drawing GeomData for geoms that are completely transparent.\n  if (treeItemOpacity < 0.001) {\n    discard;\n    return;\n  }\n  \n  if (testFlag(flags, GEOMITEM_FLAG_CUTAWAY)) {\n    vec4 cutAwayData   = getCutaway(geomItemId);\n    vec3 planeNormal = cutAwayData.xyz;\n    float planeDist = cutAwayData.w;\n    if (length(planeNormal) > 0.5) {\n      if (cutaway(v_worldPos, planeNormal, planeDist)) {\n          discard;\n          return;\n      }\n    } else {\n      if (testGeometryMask(v_viewPos)) {\n        discard;\n        return;\n      }\n    }\n  }\n  vec2 materialCoords = v_geomItemData.zw;\n  if (perElementMaterialId > 0) {\n    materialCoords.x = float(perElementMaterialId);\n  }\n\n  \n  vec4 materialHeader      = getMaterialValue(materialCoords, 0);\n  int materialId = int(materialHeader.x + 0.5);\n  \n#if defined(DRAW_COLOR)\n\n  if (geomType == TRIANGLES) { // start 'TRIANGLES'\n\n    //////////////////////////////////////////////\n    // Normals\n    vec3 viewNormal;\n    if (length(v_viewNormal) < 0.1) {\n      viewNormal = computeViewNormal(v_viewPos);\n    } else {\n      viewNormal = normalize(v_viewNormal);\n    }\n    vec3 normal = normalize(mat3(cameraMatrix) * viewNormal);\n    \n    vec3 viewVector;\n    if (isOrthographic == 0)\n      viewVector = normalize(mat3(cameraMatrix) * normalize(v_viewPos));\n    else \n      viewVector = vec3(cameraMatrix[2][0], cameraMatrix[2][1], cameraMatrix[2][2]);\n      \n    if (dot(normal, viewVector) < 0.0) {\n      normal = -normal;\n      // Note: this line can be used to debug inverted meshes.\n      //material.baseColor = vec3(1.0, 0.0, 0.0);\n    }\n\n    //////////////////////////////////////////////\n    // Material\n\n    MaterialParams material;\n\n    vec4 matValue0      = getMaterialValue(materialCoords, 1);\n    vec4 matValue1      = getMaterialValue(materialCoords, 2);\n    vec4 matValue2      = getMaterialValue(materialCoords, 3);\n\n    vec4 baseColor = matValue0;\n    float opacity = matValue2.g;\n    material.baseColor     = baseColor.rgb;\n    material.ambientOcclusion = matValue1.r;\n    material.metallic      = matValue1.g;\n    material.roughness     = matValue1.b;\n    material.reflectance   = matValue1.a;\n\n    material.emission      = matValue2.r;\n    material.opacity       = opacity * baseColor.a;\n\n#ifdef ENABLE_TEXTURES\n\n    // Planar YZ projection for texturing, repeating every meter.\n    // vec2 texCoord       = v_worldPos.xz * 0.2;\n    vec2 texCoord          = v_textureCoord;\n\n    getTextureColorValue(baseColor, BaseColorTex, BaseColorTexType, texCoord);\n    getTextureLuminanceValue(material.ambientOcclusion, AmbientOcclusionTex, AmbientOcclusionTexType, texCoord);\n    \n    material.baseColor     = baseColor.rgb;\n    material.opacity       = opacity * baseColor.a;\n\n#ifdef ENABLE_PBR\n\n    getTextureLuminanceValue(material.metallic, MetallicTex, MetallicTexType, texCoord);\n    getTextureLuminanceValue(material.roughness, RoughnessTex, RoughnessTexType, texCoord);\n\n    // TODO: Communicate that this tex contains the roughness as well.\n    if (MetallicTexType != 0) {\n      vec4 metallicRoughness = texture2D(MetallicTex, texCoord);\n      material.roughness = metallicRoughness.g;\n      material.metallic = metallicRoughness.b;\n    }\n\n    getTextureLuminanceValue(material.reflectance, ReflectanceTex, ReflectanceTexType, texCoord);\n#endif // ENABLE_PBR\n\n    getTextureLuminanceValue(material.emission, EmissiveStrengthTex, EmissiveStrengthTexType, texCoord);\n#endif // ENABLE_TEXTURES\n\n#ifdef ENABLE_TEXTURES\n#ifdef ENABLE_PBR\n    if (NormalTexType != 0) {\n      mat3 tbn = cotangentFrame(normal, viewVector, texCoord);\n      normal = normalize(tbn * (texture2D(NormalTex, texCoord).rgb * 2.0 - 1.0));\n    }\n#endif // ENABLE_PBR\n#endif // ENABLE_TEXTURES\n\n    if (outlineThickness > 0.00001) {\n      vec4 edgeColor      = getMaterialValue(materialCoords, 4);\n      vec4 matValue2      = getMaterialValue(materialCoords, 3);\n      float opacity       = matValue2.g;\n\n      edgeColor.a = edgeColor.a * opacity * treeItemOpacity;\n      \n      fragColor = edgeColor;\n    } else {\n      \n      if (testFlag(flags, GEOMITEM_FLAG_CUTAWAY) && !gl_FrontFacing) {\n        fragColor = vec4(material.baseColor, material.opacity);\n      }\n      else if (renderMode == 1) { // Flat\n        fragColor = vec4(material.baseColor, material.opacity);\n      } else if (renderMode == 2) { // Shaded\n        // simple irradiance. \n        float ndotv = dot(normal, viewVector);\n        fragColor = vec4((ndotv * material.baseColor) + (material.emission * material.baseColor), material.opacity);\n      } else if (renderMode == 3) { // PBR\n        fragColor = pbrSurfaceRadiance(material, normal, viewVector);\n      }\n      \n      // Note: the 'treeItemOpacity' is not an input to the PBR lighting, \n      // as we want to also blend off the specular reflections to make an object\n      // fade away to nothing. (not become a transparent glass object).\n      fragColor.a *= treeItemOpacity;\n\n      // Debugging code to help understand what might be happening in the shader.\n      // fragColor = vec4(texture2D(NormalTex, texCoord).rgb, 1.0);\n      // fragColor = metallicRoughness;\n      // fragColor = vec4(material.baseColor, 1.0);;\n      // fragColor = vec4(vec3(material.metallic), 1.0);;\n      // fragColor = vec4(vec3(material.roughness), 1.0);;\n      // fragColor = vec4(vec3(material.ambientOcclusion), 1.0);\n    }\n\n  } // end 'TRIANGLES'\n  else if (geomType == LINES) { // start 'LINES'\n    if (occluded == 1) {\n      vec4 matValue2      = getMaterialValue(materialCoords, 3);\n      float opacity       = matValue2.g;\n      fragColor = hiddenLineColor;\n      fragColor.a = hiddenLineColor.a * opacity * treeItemOpacity;\n    } else {\n      vec4 edgeColor;\n      // Note: if a custom material has been assigned to an edge, we use the base color, not the edge color.\n      // The ZeaSpatialBridge actually assigns 'LineColor' to the edges, so they only have a 'baseColor'.\n      \n      if (materialId == StandardSurfaceShaderId) {\n        vec4 matValue2      = getMaterialValue(materialCoords, 3);\n        edgeColor           = getMaterialValue(materialCoords, 4);\n        float opacity       = matValue2.g;\n        float edgeWeight    = matValue2.a;\n        edgeColor.a = edgeColor.a * edgeWeight * opacity * treeItemOpacity;\n      } else {\n        vec4 baseColor      = getMaterialValue(materialCoords, 1);\n        baseColor.a = baseColor.a * treeItemOpacity;\n        edgeColor = baseColor;\n      }\n      fragColor = edgeColor;\n    }\n  } // end 'LINES'\n  else if (geomType == POINTS) { // start 'POINTS'\n    if (materialId == StandardSurfaceShaderId) {\n      vec4 matValue2      = getMaterialValue(materialCoords, 3);\n      vec4 pointColor     = getMaterialValue(materialCoords, 5);\n      float opacity       = matValue2.g;\n      pointColor.a = pointColor.a * opacity * treeItemOpacity;\n      fragColor = pointColor;\n    } else {\n      vec4 baseColor      = getMaterialValue(materialCoords, 1);\n      baseColor.a = baseColor.a * treeItemOpacity;\n      fragColor = baseColor;\n    }\n  }  // end 'POINTS'\n  \n#ifdef DEBUG_GEOM_ID\n  // ///////////////////////\n  // Debug Draw ID (this correlates to GeomID within a GLGeomSet)\n  float geomId = v_geomItemData.w;\n  fragColor.rgb = getDebugColor(geomId);\n  // ///////////////////////\n#endif\n\n#ifdef ENABLE_INLINE_GAMMACORRECTION\n  fragColor.rgb = toGamma(fragColor.rgb * exposure);\n#endif\n\n// end DRAW_COLOR\n#elif defined(DRAW_GEOMDATA)\n\n  fragColor = setFragColor_geomData(v_viewPos, v_drawItemIds.x, v_drawItemIds.y, isOrthographic, flags, geomType);\n   \n#elif defined(DRAW_HIGHLIGHT)\n\n  // we don't render highlighs for non-selectable objects.\n  if (testFlag(flags, GEOMITEM_INVISIBLE_IN_GEOMDATA)) {\n    discard;\n  }\n\n  fragColor = getHighlightColor(geomItemId);\n#endif // DRAW_HIGHLIGHT\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n\n}";class StandardSurfaceShader extends GLShader{constructor(A){super(A,"StandardSuraceShader"),this.setShaderStage("VERTEX_SHADER",vert$1),this.setShaderStage("FRAGMENT_SHADER",frag$1)}bind(A,g){if(super.bind(A,g),A instanceof ColorRenderState){const g=A,I=this.__gl;g.envMap&&g.envMap.bind(g);const{exposure:C,renderMode:e}=g.unifs;C&&I.uniform1f(C.location,g.exposure),g.renderMode&&e&&("flat"==g.renderMode||"flat-noedges"==g.renderMode?I.uniform1i(e.location,1):"shaded"==g.renderMode||"shaded-noedges"==g.renderMode?I.uniform1i(e.location,2):"pbr"!=g.renderMode&&"pbr-noedges"!=g.renderMode||I.uniform1i(e.location,3))}return!0}static getPackedMaterialData(A){const g=new Float32Array(28);let I=0;g[4*I+0]=7;const C=A.getParameter("BaseColor");let e;e=C instanceof MaterialColorParam&&C.colorSpace==ColorSpace.Gamma?C.value.toLinear():C.value,I++,g[4*I+0]=e.r,g[4*I+1]=e.g,g[4*I+2]=e.b,g[4*I+3]=e.a,I++,g[4*I+0]=A.getParameter("AmbientOcclusion").value,g[4*I+1]=A.getParameter("Metallic").value,g[4*I+2]=A.getParameter("Roughness").value,g[4*I+3]=A.getParameter("Reflectance").value,I++,g[4*I+0]=A.getParameter("EmissiveStrength").value,g[4*I+1]=A.getParameter("Opacity").value,g[4*I+2]=A.getParameter("Overlay").value,g[4*I+3]=A.getParameter("EdgeWeight").value,I++;const i=A.getParameter("EdgeColor").value;g[4*I+0]=i.r,g[4*I+1]=i.g,g[4*I+2]=i.b,g[4*I+3]=i.a,I++;const t=A.getParameter("PointColor").value;return g[4*I+0]=t.r,g[4*I+1]=t.g,g[4*I+2]=t.b,g[4*I+3]=t.a,I++,g[4*I+0]=A.getParameter("PointSize").value,g}static getMaterialTemplate(){return material$2}}const material$2=new StandardSurfaceMaterial("StandardSurfaceShader_template");Registry.register("StandardSurfaceShader",StandardSurfaceShader),Registry.register("TransparentSurfaceShader",StandardSurfaceShader);class VertexColorShader extends GLShader{constructor(A){super(A,"VertexColorShader"),this.setShaderStage("VERTEX_SHADER","precision highp float;\n\n\n    attribute vec3 positions;\n    attribute vec3 normals;\n    #ifdef ENABLE_TEXTURES\n    attribute vec2 texCoords;\n    #endif\n    attribute vec4 colors;\n    \n    uniform mat4 viewMatrix;\n    uniform mat4 projectionMatrix;\n    \n    import 'GLSLUtils.glsl'\n    import 'transpose.glsl'\n    import 'inverse.glsl'\n    import 'geomItemId.glsl'\n    import 'drawItemTexture.glsl'\n    import 'modelMatrix.glsl'\n    \n    /* VS Outputs */\n    varying vec4 v_drawItemIds;\n    varying vec4 v_geomItemData;\n    varying vec3 v_viewPos;\n    varying vec3 v_viewNormal;\n    varying vec4 v_vertexColors;\n    #ifdef ENABLE_TEXTURES\n    varying vec2 v_textureCoord;\n    #endif\n    varying vec3 v_worldPos;\n    \n    void main(void) {\n      v_drawItemIds = getDrawItemIds();\n      int geomItemId = int(round(v_drawItemIds.x));\n      v_geomItemData  = getInstanceData(geomItemId);\n      v_vertexColors = colors;\n      \n      mat4 modelMatrix = getModelMatrix(geomItemId);\n      mat4 modelViewMatrix = viewMatrix * modelMatrix;\n    \n      vec4 pos = vec4(positions, 1.);\n      vec4 viewPos    = modelViewMatrix * pos;\n      gl_Position     = projectionMatrix * viewPos;\n    \n      mat3 normalMatrix = mat3(transpose(inverse(modelViewMatrix)));\n      v_viewPos       = -viewPos.xyz;\n      v_viewNormal    = normalMatrix * normals; // Note: we normalize in the fragment shader.\n    \n    #ifdef ENABLE_TEXTURES\n      v_textureCoord  = texCoords;\n      // v_textureCoord.y = 1.0 - v_textureCoord.y;// Flip y\n    #endif\n    \n      v_worldPos      = (modelMatrix * pos).xyz;\n    }\n    "),this.setShaderStage("FRAGMENT_SHADER","precision highp float;\n\n    import 'GLSLUtils.glsl'\n    import 'drawItemTexture.glsl'\n    import 'cutaways.glsl'\n    import 'geometryMask.glsl'\n    import 'gamma.glsl'\n    import 'materialparams.glsl'\n    import 'geomItemFlags.glsl'\n    \n    #ifdef DEBUG_GEOM_ID\n    import 'debugColors.glsl'\n    #endif\n    \n    /* VS Outputs */\n    varying vec4 v_drawItemIds;\n    varying vec4 v_geomItemData;\n    varying vec3 v_viewPos;\n    varying vec3 v_viewNormal;\n    varying vec4 v_vertexColors;\n    #ifdef ENABLE_TEXTURES\n    varying vec2 v_textureCoord;\n    #endif\n    varying vec3 v_worldPos;\n    /* VS Outputs */\n    \n    uniform mat4 cameraMatrix;\n    uniform int isOrthographic;\n    \n    #ifdef ENABLE_ES3\n        out vec4 fragColor;\n    #endif\n    \n    \n    #if defined(DRAW_COLOR)\n    \n    import 'computeViewNormal.glsl'\n      \n    // end DRAW_COLOR\n    #elif defined(DRAW_GEOMDATA)\n      import 'surfaceGeomData.glsl'\n    #elif defined(DRAW_HIGHLIGHT)\n      import 'surfaceHighlight.glsl'\n    #endif // DRAW_HIGHLIGHT\n    \n    \n    void main(void) {\n    #ifndef ENABLE_ES3\n      vec4 fragColor;\n    #endif\n      int geomItemId = int(round(v_drawItemIds.x));\n      int elemId = int(round(v_drawItemIds.y));\n      int perFaceMaterialId = int(round(v_drawItemIds.z));\n      int flags = int(round(v_geomItemData.x));\n      float treeItemOpacity = v_geomItemData.y;\n    \n      // We can make geoms invisible to hide them. \n      // Avoid drawing GeomData for geoms that are completely transparent.\n      if (treeItemOpacity < 0.001) {\n        discard;\n        return;\n      }\n      \n      // Cutaways\n      if (testFlag(flags, GEOMITEM_FLAG_CUTAWAY)) \n      {\n        vec4 cutAwayData   = getCutaway(geomItemId);\n        vec3 planeNormal = cutAwayData.xyz;\n        float planeDist = cutAwayData.w;\n        if (length(planeNormal) > 0.5) {\n          if (cutaway(v_worldPos, planeNormal, planeDist)) {\n              discard;\n              return;\n          }\n        } else {\n          if (testGeometryMask(v_viewPos)) {\n            discard;\n            return;\n          }\n        }\n      }\n    \n    #if defined(DRAW_COLOR)\n    \n      if (testFlag(flags, GEOMITEM_FLAG_CUTAWAY) && !gl_FrontFacing) {\n        fragColor = cutColor;\n        return;\n      } else {\n\n        //////////////////////////////////////////////\n        // Normals\n        \n        vec3 viewNormal;\n        if (length(v_viewNormal) < 0.1) {\n          viewNormal = computeViewNormal(v_viewPos);\n        } else {\n          viewNormal = normalize(v_viewNormal);\n        }\n        vec3 normal = normalize(mat3(cameraMatrix) * viewNormal);\n        \n        vec3 viewVector;\n        if (isOrthographic == 0)\n          viewVector = normalize(mat3(cameraMatrix) * normalize(v_viewPos));\n        else \n          viewVector = vec3(-cameraMatrix[2][0], -cameraMatrix[2][1], -cameraMatrix[2][2]);\n        \n        //////////////////////////////////////////////\n        // Material\n      \n        vec4 baseColor = v_vertexColors;\n      \n        // Hacky simple irradiance. \n        float ndotv = dot(normal, viewVector);\n        if (ndotv < 0.0) {\n          normal = -normal;\n          ndotv = dot(normal, viewVector);\n      \n          // Note: these 2 lines can be used to debug inverted meshes.\n          //baseColor = vec4(1.0, 0.0, 0.0, 1.0);\n          //ndotv = 1.0;\n        }\n\n        fragColor = vec4((ndotv * baseColor.rgb), 1.0);\n      }\n    \n      // Note: the 'treeItemOpacity' is not an input to the lighting, \n      // as we want to also blend off the specular reflections to make an object\n      // fade away to nothing. (not become a transparent glass object).\n      fragColor.a *= treeItemOpacity;\n    \n    \n    #ifdef DEBUG_GEOM_ID\n      // ///////////////////////\n      // Debug Draw ID (this correlates to GeomID within a GLGeomSet)\n      float geomId = v_geomItemData.w;\n      fragColor.rgb = getDebugColor(geomId);\n      // ///////////////////////\n    #endif\n    \n    #ifdef ENABLE_INLINE_GAMMACORRECTION\n      fragColor.rgb = toGamma(fragColor.rgb);\n    #endif\n    \n    #elif defined(DRAW_GEOMDATA)\n      fragColor = setFragColor_geomData(v_viewPos, v_drawItemIds.x, v_drawItemIds.y, isOrthographic, 0, TRIANGLES);\n    #elif defined(DRAW_HIGHLIGHT)\n      fragColor = setFragColor_highlight(v_drawItemIds.x);\n    #endif // DRAW_HIGHLIGHT\n    \n    #ifndef ENABLE_ES3\n      gl_FragColor = fragColor;\n    #endif\n    }")}bind(A,g){if(super.bind(A,g),A instanceof ColorRenderState){const g=this.__gl,{cutColor:I}=A.unifs;I&&g.uniform4f(I.location,.3,0,0,1)}return!0}static getMaterialTemplate(){return material$1}static supportsInstancing(){return!1}}const material$1=new VertexColorMaterial("VertexColorShader_template");Registry.register("VertexColorShader",VertexColorShader);var frag="\nprecision highp float;\n#define GLSLIFY 1\n\nimport 'GLSLUtils.glsl'\nimport 'drawItemTexture.glsl'\n\nimport 'gamma.glsl'\nimport 'materialparams.glsl'\nimport 'geomItemFlags.glsl'\n\n#if defined(DRAW_COLOR)\n\n#ifdef ENABLE_TEXTURES\nuniform sampler2D BaseColorTex;\nuniform int BaseColorTexType;\n#endif\n\n#endif // DRAW_COLOR\n\n/* VS Outputs */\nvarying float v_geomItemId;\nvarying vec4 v_geomItemData;\n#ifdef ENABLE_TEXTURES\nvarying vec2 v_textureCoord;\n#endif\n\n#if defined(DRAW_GEOMDATA)\n  uniform int isOrthographic;\n  import 'surfaceGeomData.glsl'\n#elif defined(DRAW_HIGHLIGHT)\n  import 'surfaceHighlight.glsl'\n#endif // DRAW_HIGHLIGHT\n\n#ifdef ENABLE_ES3\n  out vec4 fragColor;\n#endif\n\nvoid main(void) {\n  \n#ifndef ENABLE_ES3\n  vec4 fragColor;\n#endif\n\n  //////////////////////////////////////////////\n  // Color\n#if defined(DRAW_COLOR)\n\n    vec2 materialCoords = v_geomItemData.zw;\n    vec4 baseColor = getMaterialValue(materialCoords, 0);\n\n  #ifdef ENABLE_TEXTURES\n    getTextureColorValue(baseColor, BaseColorTex, BaseColorTexType, v_textureCoord);\n  #endif\n\n    fragColor = baseColor;\n\n  #ifdef ENABLE_INLINE_GAMMACORRECTION\n    fragColor.rgb = toGamma(fragColor.rgb);\n  #endif\n\n  //////////////////////////////////////////////\n  // GeomData\n#elif defined(DRAW_GEOMDATA)\n  fragColor = setFragColor_geomData(vec3(0,0,0), v_geomItemId, 0.0, isOrthographic, 0, TRIANGLES);\n#elif defined(DRAW_HIGHLIGHT)\n  fragColor = setFragColor_highlight(v_geomItemId);\n#endif // DRAW_HIGHLIGHT\n\n#ifndef ENABLE_ES3\n  gl_FragColor = fragColor;\n#endif\n}\n",vert="\nprecision highp float;\n#define GLSLIFY 1\n\nattribute vec3 positions;\n#ifdef ENABLE_TEXTURES\nattribute vec2 texCoords;\n#endif\n\nimport 'GLSLUtils.glsl'\nimport 'geomItemId.glsl'\nimport 'drawItemTexture.glsl'\nimport 'modelMatrix.glsl'\n\n/* VS Outputs */\nvarying float v_geomItemId;\nvarying vec4 v_geomItemData;\n#ifdef ENABLE_TEXTURES\nvarying vec2 v_textureCoord;\n#endif\n\nvoid main(void) {\n  int geomItemId = getGeomItemId();\n  v_geomItemId = float(geomItemId);\n  v_geomItemData  = getInstanceData(geomItemId);\n\n  mat4 modelMatrix = getModelMatrix(geomItemId);\n\n  gl_Position = (modelMatrix * vec4(positions, 1.0));\n\n  v_textureCoord = texCoords;\n  v_textureCoord.y = 1.0 - v_textureCoord.y;// Flip y\n}\n";class ScreenSpaceShader extends GLShader{constructor(A){super(A,"ScreenSpaceShader"),this.setShaderStage("VERTEX_SHADER",vert),this.setShaderStage("FRAGMENT_SHADER",frag)}static isOverlay(){return!0}static getPackedMaterialData(A){const g=new Float32Array(8);const I=A.getParameter("BaseColor");let C;return C=I instanceof MaterialColorParam&&I.colorSpace==ColorSpace.Gamma?I.value.toLinear():I.value,g[0]=C.r,g[1]=C.g,g[2]=C.b,g[3]=C.a,g}static getMaterialTemplate(){return material}}const material=new ScreenSpaceMaterial("ScreenSpaceShader_template");Registry.register("ScreenSpaceShader",ScreenSpaceShader);class GLStandardGeomsPass extends GLPass{materials=new Map;listenerIDs=new Map;constructor(){super()}init(A,g){super.init(A,g)}itemAddedToScene(A,g){if(A instanceof GeomItem){const g=A;return!!this.filterGeomItem(g)&&(this.addGeomItem(g),!0)}return!1}itemRemovedFromScene(A,g){return A instanceof GeomItem&&(this.removeGeomItem(A),!0)}filterGeomItem(A){return!0}checkMaterial(A){return!0}addGeomItem(A){const g={};this.listenerIDs.set(A,g);const I=()=>{this.removeGeomItem(A),this.renderer.assignTreeItemToGLPass(A)};g["materialParam.valueChanged"]=A.materialParam.on("valueChanged",I),g["geomParam.valueChanged"]=A.geomParam.on("valueChanged",I);const C=A=>{A.isOpaqueStateChanged&&I()},e=A.materialParam.value;this.materials.set(A,e),g["geomItem.opacityChanged"]=A.on("opacityChanged",C),g["material.opacityChanged"]=e.on("opacityChanged",C)}removeGeomItem(A){const g=this.listenerIDs.get(A);this.listenerIDs.delete(A),A.materialParam.off("valueChanged",g["materialParam.valueChanged"]),A.geomParam.off("valueChanged",g["geomParam.valueChanged"]);const I=this.materials.get(A);this.materials.delete(A),A.off("opacityChanged",g["geomItem.opacityChanged"]),I.off("opacityChanged",g["material.opacityChanged"])}constructShader(A){return this.__renderer.getOrCreateShader(A)}getGeomItemAndDist(A){let g,I,C=-1;A instanceof Float32Array?(g=Math.round(A[1]),C=Math.round(A[2]),I=A[3]):(g=A[0]+((63&A[1])<<8),I=MathFunctions.decode16BitFloatFrom2xUInt8(A.slice(2,3)));const e=this.renderer.glGeomItemLibrary.getGeomItem(g);if(e)return{geomItem:e,componentId:C,dist:I}}}class GLOpaqueGeomsPass extends GLStandardGeomsPass{glShaderMaterials=new Map;glShaderGeomSets=new Map;constructor(){super()}getPassType(){return PassType.OPAQUE}filterGeomItem(A){const g=A.materialParam.value;return A.isOpaque()&&g.isOpaque()}checkMaterial(A){return A.isOpaque()}removeAndReAddGeomItem(A){this.removeGeomItem(A),this.__renderer.assignTreeItemToGLPass(A)}addGeomItem(A){super.addGeomItem(A);const g=A.materialParam.value,I=this.renderer.glGeomItemLibrary.getGLGeomItem(A);this.__gl.multiDrawElementsInstanced&&I.supportInstancing&&!g.isTextured()?this.addGeomItemToMultiDraw(A,I):this.addGeomItemToConventionalDraw(A,I)}addGeomItemToMultiDraw(A,g){const I=A.materialParam.value.getShaderName(),C=this.__renderer.getOrCreateShader(I);let e=this.glShaderGeomSets.get(C);e||(e=new GLShaderGeomSets(this.__renderer,this.__gl,C),e.on("updated",(()=>{this.__renderer.requestRedraw()})),this.glShaderGeomSets.set(C,e)),e.addGLGeomItem(g),g.GLShaderGeomSets=e,this.emit("updated")}addGeomItemToConventionalDraw(A,g){const I=A.materialParam.value,C=this.renderer.glGeomLibrary.constructGLGeom(A.geomParam.value),e=I.getShaderName(),i=this.renderer.glMaterialLibrary.getGLMaterial(I),t=i.glShader;let o=this.glShaderMaterials.get(t);if(!o){const A=this.constructShader(e);o=new GLShaderMaterials(this.__gl,this,A),this.glShaderMaterials.set(t,o),o.on("updated",(()=>{this.__renderer.requestRedraw()}))}o.addGLGeomItem(g,C,i)}removeGeomItem(A){super.removeGeomItem(A);const g=this.renderer.glGeomItemLibrary.getGLGeomItem(A);if(g.GLShaderGeomSets){return g.GLShaderGeomSets.removeGLGeomItem(g),void(g.GLShaderGeomSets=null)}if(g.GLGeomItemSet){return g.GLGeomItemSet.removeGLGeomItem(g),void(g.GLGeomItemSet=null)}}removeMaterial(A){const g=this.renderer.glMaterialLibrary.getGLMaterial(A),I=g.glShader;this.glShaderMaterials.get(I).removeMaterialGeomItemSets(g)}traverseTreeAndDraw(A){this.glShaderGeomSets.forEach((g=>{g.draw(A)})),this.glShaderMaterials.forEach((g=>{g.draw(A)})),A.glGeom&&A.glGeom.unbind(A)}draw(A){const g=this.__gl;A.pushGLStack("GLOpaqueGeomsPass.drawGeomData"),A.glDisable(g.BLEND),A.glEnable(g.DEPTH_TEST),A.glDisable(g.CULL_FACE),g.depthFunc(g.LEQUAL),g.depthMask(!0),this.traverseTreeAndDraw(A);const I=this.renderer;I.outlineThickness>0&&"image"==I.outlineMethod&&A.viewport.drawSilhouettes(A),A.popGLStack()}drawHighlightedGeoms(A){const g=this.__gl;g.disable(g.CULL_FACE),this.glShaderGeomSets.forEach((g=>{g.drawHighlightedGeoms(A)})),this.glShaderMaterials.forEach((g=>{g.drawHighlightedGeoms(A)})),A.glGeom&&A.glGeom.unbind(A)}drawGeomData(A){A.passIndex=this.passIndex;const g=this.__gl;g.disable(g.BLEND),g.disable(g.CULL_FACE),g.enable(g.DEPTH_TEST),g.depthFunc(g.LEQUAL),g.depthMask(!0),this.glShaderGeomSets.forEach((g=>{g.drawGeomData(A)})),this.glShaderMaterials.forEach((g=>{g.drawGeomData(A)})),A.glGeom&&A.glGeom.unbind(A)}}GLRenderer.registerPass(GLOpaqueGeomsPass,PassType.OPAQUE);class GLLinesPass extends GLOpaqueGeomsPass{linesGeomDataBuffer=null;fattenLinesShader=null;quad=null;fbo=null;constructor(){super()}init(A,g){super.init(A,g)}filterGeomItem(A){const g=A.geomParam.value;return g instanceof Lines||g instanceof LinesProxy||g instanceof Points||g instanceof PointsProxy}draw(A){const g=this.__gl;A.pushGLStack("GLLinesPass.draw"),A.glEnable(g.BLEND),A.glEnable(g.DEPTH_TEST),g.blendFuncSeparate(g.SRC_ALPHA,g.ONE_MINUS_SRC_ALPHA,g.ONE,g.ONE),g.depthFunc(g.LEQUAL),g.depthMask(!0),this.traverseTreeAndDraw(A),A.popGLStack()}drawGeomData(A){const g=this.__gl;if(A.geomDataFbo&&!A.occlusionCulling){A.pushGLStack("GLLinesPass.drawGeomData"),this.linesGeomDataBuffer||(this.linesGeomDataBuffer=new GLTexture2D(g,{type:this.__renderer.floatGeomBuffer?"FLOAT":"UNSIGNED_BYTE",format:"RGBA",filter:"NEAREST",width:1,height:2}),this.fattenLinesShader=new FattenLinesShader(g),this.quad=new GLMesh(g,new Plane(1,1)));const I=A.geomDataFbo,C=I.width,e=I.height;if(this.linesGeomDataBuffer.width!=C||this.linesGeomDataBuffer.height!=e){this.fbo&&(g.deleteFramebuffer(this.fbo),this.fbo=null),this.linesGeomDataBuffer.resize(C,e),this.fbo=g.createFramebuffer();const A=this.linesGeomDataBuffer.glTex,i=I.depthTexture;g.bindFramebuffer(g.DRAW_FRAMEBUFFER,this.fbo),g.framebufferTexture2D(g.DRAW_FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,A,0),g.framebufferTexture2D(g.DRAW_FRAMEBUFFER,g.DEPTH_ATTACHMENT,g.TEXTURE_2D,i,0),checkFramebuffer(g,C,e)}else g.bindFramebuffer(g.DRAW_FRAMEBUFFER,this.fbo);g.colorMask(!0,!0,!0,!0),g.clearColor(0,0,0,0),g.clear(g.COLOR_BUFFER_BIT)}if(super.drawGeomData(A),A.geomDataFbo&&!A.occlusionCulling){A.popGLStack(),A.boundRendertarget=null,A.geomDataFbo.bindForWriting(A),this.fattenLinesShader.bind(A);const{colorTexture:I,screenSize:C,pointAndLinePickingSize:e}=A.unifs;this.linesGeomDataBuffer.bindToUniform(A,I),g.uniform1i(e.location,A.pointAndLinePickingSize);const i=A.geomDataFbo;g.uniform2f(C.location,i.width,i.height),this.quad.bindAndDraw(A)}}}GLRenderer.registerPass(GLLinesPass,PassType.OPAQUE);class GLTransparentGeomsPass extends GLStandardGeomsPass{itemCount=0;glShaderGeomSets={};transparentItems=[];transparentItemIndices=new Map;freeList=[];visibleItems=[];prevSortCameraPos=new Vec3(999,999,999);sortCameraMovementDistance=.25;reSort=!1;constructor(){super()}init(A,g){super.init(A,g)}getPassType(){return PassType.TRANSPARENT}filterGeomItem(A){const g=A.geomParam.value;if(g instanceof Lines||g instanceof Points||g instanceof PointsProxy||g instanceof LinesProxy)return!1;const I=A.materialParam.value;return!A.isOpaque()||!I.isOpaque()}resortNeeded(){this.reSort=!0}addGeomItem(A){super.addGeomItem(A),this.itemCount++;const g=this.listenerIDs.get(A),I=A.materialParam.value,C=I.getShaderName(),e=this.constructShader(C);if(!I.isTextured()&&I.getShaderClass().supportsInstancing()){let I=this.glShaderGeomSets[C];I||(I=new GLShaderGeomSets(this.__renderer,this.__gl,e),I.on("updated",(()=>{this.renderer.requestRedraw()})),this.glShaderGeomSets[C]=I);const i=this.renderer.glGeomItemLibrary.getGLGeomItem(A);return I.addGLGeomItem(i),g["glGeomItem.visibilityChanged"]=i.on("visibilityChanged",(()=>{this.resortNeeded()})),this.emit("updated"),i.GLShaderGeomSets=I,void(this.reSort=!0)}const i=this.renderer.glGeomLibrary.constructGLGeom(A.geomParam.value),t=this.renderer.glGeomItemLibrary.getGLGeomItem(A);if(!t)throw new Error("glGeomItem not found for geomItem:"+A.getName());const o=this.renderer.glMaterialLibrary.getGLMaterial(I);g["glGeomItem.visibilityChanged"]=t.on("visibilityChanged",(A=>{if(A.state)this.visibleItems.push(a);else{const A=this.visibleItems.indexOf(a);this.visibleItems.splice(A,1)}this.reSort=!0})),g["GeomMat.valueChanged"]=A.geomMatParam.on("valueChanged",(()=>{this.reSort=!0}));const a={geomItem:A,glShader:e,glGeom:i,glMaterial:o,glGeomItem:t,material:I,dist:0};let B;B=this.freeList.length>0?this.freeList.pop():this.transparentItems.length,this.transparentItems[B]=a,this.transparentItemIndices.set(A,B),A.isVisible()&&this.visibleItems.push(a),this.reSort=!0}removeGeomItem(A){this.itemCount--;const g=this.listenerIDs.get(A);super.removeGeomItem(A);const I=this.renderer.glGeomItemLibrary.getGLGeomItem(A);if(!I)throw new Error("glGeomItem not found for geomItem:"+A.getName());if(I.off("visibilityChanged",g["glGeomItem.visibilityChanged"]),I.GLShaderGeomSets){I.GLShaderGeomSets.removeGLGeomItem(I),I.GLShaderGeomSets=null}else{const g=this.transparentItemIndices.get(A),I=this.transparentItems[g];this.transparentItemIndices.delete(A),this.transparentItems[g]=null,this.freeList.push(g);const C=this.visibleItems.indexOf(I);-1!=C&&this.visibleItems.splice(C,1)}return this.emit("updated"),!0}sortItems(A){for(const g in this.glShaderGeomSets)this.glShaderGeomSets[g].sortItems(A);for(const g of this.visibleItems){const I=g.glGeomItem.geomItem.geomMatParam.value;g.dist=I.translation.distanceTo(A)}this.visibleItems.sort(((A,g)=>A.dist>g.dist?-1:A.dist<g.dist?1:0)),this.reSort=!1}drawItem(A,g,I){I.currentGLMaterial!=g.glMaterial&&(I.currentGLMaterial=g.glMaterial,I.currentGLMaterial.bind(A,!1)),I.currentGLGeom!=g.glGeom&&(I.currentGLGeom=g.glGeom,I.currentGLGeom.bind(A));g.glGeomItem.bind(A),A.bindViewports(A.unifs,(()=>{I.currentGLGeom.draw(A)}))}_drawItems(A){for(const g in this.glShaderGeomSets)this.glShaderGeomSets[g].draw(A);const g={currentglShader:null,currentGLMaterial:null,currentGLGeom:null};for(const I of this.visibleItems){const C=I.glShader;if(g.currentglShader!=C){if(!C.bind(A,"color"))continue;const I=this.__gl,e=A.unifs;e.instancedDraw&&I.uniform1i(e.instancedDraw.location,0),this.renderer.glGeomItemLibrary.bind(A),this.renderer.glGeomLibrary.bind(A),this.renderer.glMaterialLibrary.bind(A),g.currentglShader=C}this.drawItem(A,I,g)}g.currentglShader&&g.currentglShader.unbind(A)}draw(A){if(0==this.itemCount)return;const g=this.__gl,I=A.viewXfo.tr;if(this.reSort||I.distanceTo(this.prevSortCameraPos)>this.sortCameraMovementDistance)if(this.sortItems(I),this.prevSortCameraPos=I,A.xrviewport)this.sortCameraMovementDistance=.2*A.viewScale;else if(A.viewport){const g=A.viewport.getCamera();this.sortCameraMovementDistance=.3*g.getFocalDistance()}A.pushGLStack("GLTransparentGeomsPass.draw"),A.glEnable(g.BLEND),A.glEnable(g.DEPTH_TEST),A.glEnable(g.CULL_FACE),g.depthFunc(g.LESS),g.blendEquation(g.FUNC_ADD),A.pass="ADD",g.blendFuncSeparate(g.SRC_ALPHA,g.ONE_MINUS_SRC_ALPHA,g.ONE,g.ONE),g.cullFace(g.BACK),this._drawItems(A),A.popGLStack()}drawHighlightedGeoms(A){const g=this.__gl;g.disable(g.CULL_FACE);for(const g in this.glShaderGeomSets)this.glShaderGeomSets[g].drawHighlightedGeoms(A);const I={currentglShader:null,currentGLMaterial:null,currentGLGeom:null};for(const C of this.visibleItems){if(!C.geomItem.isHighlighted())continue;const e=C.glShader;if(I.currentglShader!=e){if(!e.bind(A,"highlight"))continue;I.currentglShader=e;const{floatGeomBuffer:C,passId:i,instancedDraw:t}=A.unifs;C&&g.uniform1i(C.location,g.floatGeomBuffer?1:0),i&&g.uniform1i(i.location,this.passIndex),t&&g.uniform1i(t.location,0),this.renderer.glGeomItemLibrary.bind(A)}this.drawItem(A,C,I)}I.currentglShader&&I.currentglShader.unbind(A),I.currentGLGeom&&I.currentGLGeom.unbind(A)}drawGeomData(A){const g=this.__gl;A.pushGLStack("GLTransparentGeomsPass.drawGeomData"),A.glEnable(g.DEPTH_TEST),A.glEnable(g.CULL_FACE);for(const g in this.glShaderGeomSets)this.glShaderGeomSets[g].drawGeomData(A);const I={currentglShader:null,currentGLMaterial:null,currentGLGeom:null};for(const C of this.visibleItems){if(!C.glGeomItem.geomItem.isPickable())continue;const e=C.glShader;if(e){if(I.currentglShader!=e){if(!e.bind(A,"geomdata"))continue;I.currentglShader=e;const{floatGeomBuffer:C,passId:i,instancedDraw:t}=A.unifs;C&&g.uniform1i(C.location,g.floatGeomBuffer?1:0),i&&g.uniform1i(i.location,this.passIndex),t&&g.uniform1i(t.location,0),this.renderer.glGeomItemLibrary.bind(A)}this.drawItem(A,C,I)}}I.currentGLGeom&&I.currentGLGeom.unbind(A),I.currentglShader&&I.currentglShader.unbind(A),A.popGLStack()}}GLRenderer.registerPass(GLTransparentGeomsPass,PassType.TRANSPARENT);const pixelsPerItem=7,ALIGN_TO_CAMERA_FLAG=4,ALIGN_TO_CAMERA_AND_AXIS_FLAG=8,DRAW_ON_TOP_FLAG=16,FIXED_SIZE_ON_SCREEN_FLAG=32,FRONT_FACING_FLAG=64;class GLBillboardsPass extends GLPass{billboards=[];billboardIndices=new Map;dirtyBillboards=new Set;freeIndices=[];drawCount=0;threshold=0;prevSortCameraPos=new Vec3;atlas=null;indexArrayUpdateNeeded=!1;instanceIdsBuffer=null;indexArray=new Float32Array(0);glshader=null;shaderBinding=null;modelMatrixArray=[];billboardDataArray=[];tintColorArray=[];drawItemsTexture=null;constructor(){super()}init(A,g){super.init(A,g);const I=this.renderer.gl;this.atlas=new GLImageAtlas(I,I.RGBA,I.UNSIGNED_BYTE);const C=()=>this.emit("updated");this.atlas.on("loaded",C),this.atlas.on("updated",C)}getPassType(){return PassType.TRANSPARENT}itemAddedToScene(A,g){return A instanceof BillboardItem&&(this.addBillboard(A),!0)}itemRemovedFromScene(A,g){return A instanceof BillboardItem&&(this.removeBillboard(A),!0)}addBillboard(A){const g=A.imageParam,I=g.value;if(!I)return void g.on("valueChanged",(()=>this.addBillboard(A)));let C;C=this.freeIndices.length>0?this.freeIndices.pop():this.billboards.length;const e=this.atlas.addSubImage(I);this.billboardIndices.set(A,C);const i=()=>{A.isVisible()?(this.drawCount++,this.dirtyBillboards.add(C)):this.drawCount--,this.reqUpdateIndexArray()};A.on("visibilityChanged",i);const t=()=>{A.isVisible()&&(this.dirtyBillboards.add(C),this.emit("updated"))};A.on("parameterValueChanged",t),A.on("highlightChanged",t),A.isVisible()&&this.drawCount++,this.billboards[C]={billboard:A,imageIndex:e,dist:0,visibilityChanged:i,updateBillboard:t},this.dirtyBillboards.add(C),this.indexArrayUpdateNeeded=!0,this.emit("updated")}removeBillboard(A){const g=this.billboardIndices.get(A);if(-1==g)return void console.warn("Billboard already removed.");const I=this.billboards[g],C=I.billboard.imageParam.value;this.atlas.removeSubImage(C),A.off("visibilityChanged",I.visibilityChanged),A.off("highlightChanged",I.updateBillboard),A.off("parameterValueChanged",I.updateBillboard),A.isVisible()&&this.drawCount--,this.billboards[g]=null,this.billboardIndices.delete(A),this.freeIndices.push(g),this.dirtyBillboards.has(g)&&this.dirtyBillboards.delete(g),this.indexArrayUpdateNeeded=!0,this.emit("updated")}populateBillboardDataArray(A,g,I){const C=A.billboard,e=C.globalXfoParam.value.toMat4(),i=C.pixelsPerMeterParam.value,t=C.pivotParam.value,o=1/i;let a=0;switch(C.alignmentParam.value){case 0:break;case 1:a|=4;break;case 2:a|=8}C.drawOnTopParam.value&&(a|=16),C.fixedSizeOnscreenParam.value&&(a|=32),C.frontFacingParam.value&&(a|=64);const B=C.alphaParam.value,s=C.colorParam.value,l=7*g*4,n=new Float32Array(I.buffer,4*l,4),d=new Float32Array(I.buffer,4*(l+4),4),r=new Float32Array(I.buffer,4*(l+8),4),c=new Float32Array(I.buffer,4*(l+12),4);n.set([e.xAxis.x,e.yAxis.x,e.zAxis.x,e.translation.x]),d.set([e.xAxis.y,e.yAxis.y,e.zAxis.y,e.translation.y]),r.set([e.xAxis.z,e.yAxis.z,e.zAxis.z,e.translation.z]),c.set([o,a,A.imageIndex,B]);new Float32Array(I.buffer,4*(l+16),4).set([t.x,t.y,0,0]);if(new Float32Array(I.buffer,4*(l+20),4).set([s.r,s.g,s.b,s.a]),C.isHighlighted()){const A=C.getHighlight();new Float32Array(I.buffer,4*(l+24),4).set([A.r,A.g,A.b,A.a])}}reqUpdateIndexArray(){this.indexArrayUpdateNeeded||(this.indexArrayUpdateNeeded=!0,this.emit("updated"))}updateIndexArray(){const A=this.__gl;this.indexArray&&this.indexArray.length!=this.drawCount&&(A.deleteBuffer(this.instanceIdsBuffer),this.instanceIdsBuffer=null),this.indexArray=new Float32Array(this.drawCount);let g=0;for(let A=0;A<this.billboards.length;A++)this.billboards[A]&&this.billboards[A].billboard.isVisible()&&(this.indexArray[g]=A,g++);this.instanceIdsBuffer||(this.instanceIdsBuffer=A.createBuffer()),A.bindBuffer(A.ARRAY_BUFFER,this.instanceIdsBuffer),A.bufferData(A.ARRAY_BUFFER,this.indexArray,A.STATIC_DRAW),this.indexArrayUpdateNeeded=!1}updateBillboards(A){const g=new Set(this.dirtyBillboards);this.dirtyBillboards.clear();const I=()=>{this.indexArrayUpdateNeeded&&this.updateIndexArray();const I=this.__gl;if(!this.glshader){I.__quadVertexIdsBuffer||I.setupInstancedQuad(),this.glshader=new BillboardShader(I);const g=this.glshader.compileForTarget("GLBillboardsPass",A.directives);this.shaderBinding=generateShaderGeomBinding(I,g.attrs,I.__quadattrbuffers,I.__quadIndexBuffer)}if(this.atlas.needsUpdate&&this.atlas.renderAtlas(),!I.floatTexturesSupported||!I.drawElementsInstanced)return this.modelMatrixArray=[],this.billboardDataArray=[],this.tintColorArray=[],void g.forEach((A=>{const g=this.billboards[A],I=g.billboard,C=I.globalXfoParam.value.toMat4(),e=1/I.pixelsPerMeterParam.value;let i=0;switch(I.alignmentParam.value){case 0:break;case 1:i|=4;break;case 2:i|=8}I.drawOnTopParam.value&&(i|=8),I.fixedSizeOnscreenParam.value&&(i|=16);const t=I.alphaParam.value,o=I.colorParam.value;this.modelMatrixArray[A]=C.asArray(),this.billboardDataArray[A]=[e,i,g.imageIndex,t],this.tintColorArray[A]=[o.r,o.g,o.b,o.a]}));let C=Math.ceil(Math.sqrt(7*this.billboards.length));if(C%7!=0&&(C+=7-C%7),this.drawItemsTexture)this.drawItemsTexture.width!=C&&(this.drawItemsTexture.resize(C,C),this.billboards.forEach(((A,g)=>{this.dirtyBillboards.add(g)})));else{const A={format:I.RGBA,type:I.FLOAT,width:C,height:C,filter:I.NEAREST,wrap:I.CLAMP_TO_EDGE,mipMapped:!1};this.drawItemsTexture=new GLTexture2D(I,A),this.drawItemsTexture.clear()}g.forEach((A=>{this.updateBillboard(A)}))};this.atlas.isLoaded()?I():this.atlas.on("loaded",I)}updateBillboard(A){if(!this.billboards[A])return;const g=this.billboards[A];if(!g.billboard.isVisible())return;const I=this.__gl,C=new Float32Array(28);this.populateBillboardDataArray(g,0,C),I.bindTexture(I.TEXTURE_2D,this.drawItemsTexture.glTex);const e=7*A%this.drawItemsTexture.width,i=Math.floor(7*A/this.drawItemsTexture.width),t=this.drawItemsTexture.type,o=this.drawItemsTexture.format;if(t==I.FLOAT)I.texSubImage2D(I.TEXTURE_2D,0,e,i,7,1,o,t,C);else{const A=MathFunctions.convertFloat32ArrayToUInt16Array(C);I.texSubImage2D(I.TEXTURE_2D,0,e,i,7,1,o,t,A)}}sort(A){for(const g of this.billboards){if(!g)continue;const{billboard:I}=g;if(I&&I.isVisible()){const C=I.globalXfoParam.value;g.dist=C.tr.distanceTo(A)}}this.indexArray.sort(((A,g)=>-1==A?1:-1==g||this.billboards[A].dist>this.billboards[g].dist?-1:this.billboards[A].dist<this.billboards[g].dist?1:0));const g=this.__gl;g.floatTexturesSupported&&this.instanceIdsBuffer&&(g.bindBuffer(g.ARRAY_BUFFER,this.instanceIdsBuffer),g.bufferData(g.ARRAY_BUFFER,this.indexArray,g.STATIC_DRAW))}__draw(A,g){const I=this.__gl;if(!this.glshader)return;this.glshader.bind(A,g),this.shaderBinding.bind(A);const C=A.unifs,{atlasBillboards:e,passId:i,floatGeomBuffer:t,inVR:o}=A.unifs;if(e&&this.atlas.bindToUniform(A,e),t&&A instanceof GeomDataRenderState&&I.uniform1i(t.location,A.floatGeomBuffer?1:0),i&&I.uniform1i(i.location,this.passIndex),o&&I.uniform1i(o.location,A.vrPresenting?1:0),I.floatTexturesSupported&&I.drawElementsInstanced){const{instancesTexture:g,instancesTextureSize:e}=A.unifs;this.drawItemsTexture.bindToUniform(A,g),I.uniform1i(e.location,this.drawItemsTexture.width);{const g=A.attrs.instanceIds.location;I.enableVertexAttribArray(g),I.bindBuffer(I.ARRAY_BUFFER,this.instanceIdsBuffer),I.vertexAttribPointer(g,1,I.FLOAT,!1,4,0),I.vertexAttribDivisor(g,1)}A.bindViewports(C,(()=>{I.drawElementsInstanced(I.TRIANGLES,6,I.UNSIGNED_BYTE,0,this.drawCount)}))}else{const{modelMatrix:g,billboardData:e,tintColor:i,layoutData:t}=A.unifs,o=this.indexArray.length;for(let a=0;a<o;a++)I.uniformMatrix4fv(g.location,!1,this.modelMatrixArray[a]),I.uniform4fv(e.location,this.billboardDataArray[a]),I.uniform4fv(i.location,this.tintColorArray[a]),I.uniform4fv(t.location,this.atlas.getLayoutData(this.billboards[a].imageIndex)),A.bindViewports(C,(()=>{I.drawQuad()}))}}draw(A){if(0==this.drawCount)return;if(this.dirtyBillboards.size>0&&this.updateBillboards(A),this.indexArrayUpdateNeeded&&this.updateIndexArray(),!this.glshader)return;const g=A.viewXfo.tr;if(g.distanceTo(this.prevSortCameraPos)>this.threshold)if(this.sort(g),this.prevSortCameraPos=g.clone(),this.drawCount>1){const A=this.indexArray[this.indexArray.length-1],g=this.indexArray[this.indexArray.length-2],I=this.billboards[A].billboard,C=this.billboards[g].billboard,e=I.globalXfoParam.value.tr,i=C.globalXfoParam.value.tr;this.threshold=e.distanceTo(i)}else this.threshold=9999;const I=this.__gl;I.depthMask(!1),I.disable(I.CULL_FACE),I.enable(I.BLEND),I.blendEquation(I.FUNC_ADD),I.blendFuncSeparate(I.SRC_ALPHA,I.ONE_MINUS_SRC_ALPHA,I.ONE,I.ONE),this.__draw(A,"DRAW_COLOR"),I.disable(I.BLEND),I.depthMask(!0)}drawHighlightedGeoms(A){0!=this.drawCount&&this.__draw(A,"DRAW_HIGHLIGHT")}drawGeomData(A){0!=this.drawCount&&this.__draw(A,"DRAW_GEOMDATA")}getGeomItemAndDist(A){let g,I;if(A instanceof Float32Array?(g=Math.round(A[1]),I=A[3]):(g=A[0]+((63&A[1])<<8),I=MathFunctions.decode16BitFloatFrom2xUInt8(A.slice(2,3))),!(g>=this.billboards.length))return{geomItem:this.billboards[g].billboard,componentId:0,dist:I};console.warn("Invalid Draw Item id:"+g+" NumBillboards:"+(this.billboards.length-1))}}GLRenderer.registerPass(GLBillboardsPass,PassType.TRANSPARENT);class GLOverlayPass extends GLOpaqueGeomsPass{constructor(){super()}getPassType(){return PassType.OVERLAY}filterGeomItem(A){if(A.isOverlay())return!0;const g=A.materialParam.value.getShaderClass();return!(!g||!g.isOverlay())}draw(A){const g=this.__gl;g.clear(g.DEPTH_BUFFER_BIT),g.enable(g.CULL_FACE),g.cullFace(g.BACK),g.enable(g.BLEND),g.blendEquation(g.FUNC_ADD),A.pass="ADD",g.blendFuncSeparate(g.SRC_ALPHA,g.ONE_MINUS_SRC_ALPHA,g.ONE,g.ONE),this.traverseTreeAndDraw(A),g.disable(g.BLEND)}drawGeomData(A){const g=this.__gl;g.clear(g.DEPTH_BUFFER_BIT),g.enable(g.CULL_FACE),g.cullFace(g.BACK),g.enable(g.BLEND),g.blendEquation(g.FUNC_ADD),A.pass="ADD",g.blendFuncSeparate(g.SRC_ALPHA,g.ONE_MINUS_SRC_ALPHA,g.ONE,g.ONE),super.drawGeomData(A),g.disable(g.BLEND),g.enable(g.DEPTH_TEST)}}GLRenderer.registerPass(GLOverlayPass,PassType.OVERLAY),Registry.register("GLOverlayPass",GLOverlayPass);class GLBoundingBoxPass extends GLPass{boxes=[];dirtyBoxes=new Set;freeIndices=[];idToIndex=new Map;drawCount=0;indexArrayUpdateNeeded=!1;__updateRequested=!1;glgeom;glshader;__modelMatrixArray=[];__treeItemDataArray=[];__tintColorArray=[];__instanceIdsBuffer;__indexArray=new Float32Array(0);__drawItemsTexture;width=0;constructor(){super()}getPassType(){return PassType.OPAQUE}init(A,g){super.init(A,g);const I=this.__renderer.gl;this.glgeom=new GLLines(I,new LinesCuboid(1,1,1)),this.glshader=new BoundingBoxShader(I)}itemAddedToScene(A,g){return!1}itemRemovedFromScene(A,g){return!1}addTreeItem(A,g=!0){if(A instanceof TreeItem&&(this.bindTreeItem(A),g)){for(const g of A.getChildren())g&&this.addTreeItem(g);A.on("childAdded",(A=>{this.addTreeItem(A.childItem)})),A.on("childRemoved",(A=>{this.unbindTreeItem(A.childItem)}))}}bindTreeItem(A){let g,I=this.freeIndices.pop();g=I||this.boxes.length,this.idToIndex.set(A,g);const C=()=>{A.isVisible()?(this.drawCount++,this.dirtyBoxes.add(g)):this.drawCount--,this.indexArrayUpdateNeeded=!0};A.on("visibilityChanged",C);const e=()=>{A.isVisible()&&(this.dirtyBoxes.add(g),this.emit("updated"))};A.globalXfoParam.on("valueChanged",e),A.boundingBoxParam.on("valueChanged",e),A.isVisible()&&this.drawCount++,this.boxes[g]={treeItem:A,visibilityChanged:C,xfoChanged:e},this.indexArrayUpdateNeeded=!0,this.__updateRequested=!0,this.emit("updated")}unbindTreeItem(A){if(!this.idToIndex.has(A))return void console.warn("Billboard already removed.");const g=this.idToIndex.get(A),I=this.boxes[g];A.off("visibilityChanged",I.visibilityChanged),A.globalXfoParam.off("valueChanged",I.xfoChanged),A.boundingBoxParam.off("valueChanged",I.xfoChanged),this.boxes[g]=null,this.freeIndices.push(g),A.isVisible()&&this.drawCount--,this.indexArrayUpdateNeeded=!0,this.__updateRequested=!0,this.__updateBoxes(),this.emit("updated")}__populateBoxesDataArray(A,g,I){const C=A.treeItem;let e,i;C instanceof GeomItem?(e=new Color(1,0,0,1),i=C.geomMatParam.value):(e=new Color(0,0,1,1),i=C.globalXfoParam.value.toMat4());const t=C.boundingBoxParam.value,o=8*g*4,a=new Float32Array(I.buffer,4*o,4),B=new Float32Array(I.buffer,4*(o+4),4),s=new Float32Array(I.buffer,4*(o+8),4),l=new Float32Array(I.buffer,4*(o+12),4),n=new Float32Array(I.buffer,4*(o+16),4),d=new Float32Array(I.buffer,4*(o+24),4),r=new Float32Array(I.buffer,4*(o+28),4);a.set([0,0,0,0]),B.set([i.xAxis.x,i.yAxis.x,i.zAxis.x,i.translation.x]),s.set([i.xAxis.y,i.yAxis.y,i.zAxis.y,i.translation.y]),l.set([i.xAxis.z,i.yAxis.z,i.zAxis.z,i.translation.z]),n.set([e.r,e.g,e.b,e.a]),d.set([t.p0.x,t.p0.y,t.p0.z,0]),r.set([t.p1.x,t.p1.y,t.p1.z,0])}__updateIndexArray(){const A=this.__gl;this.__indexArray&&this.__indexArray.length!=this.drawCount&&(A.deleteBuffer(this.__instanceIdsBuffer),this.__instanceIdsBuffer=void 0),this.__indexArray=new Float32Array(this.drawCount);let g=0;for(let A=0;A<this.boxes.length;A++)this.boxes[A]&&this.boxes[A].treeItem.isVisible()&&(this.__indexArray[g]=A,g++);this.__instanceIdsBuffer||(this.__instanceIdsBuffer=A.createBuffer()),A.bindBuffer(A.ARRAY_BUFFER,this.__instanceIdsBuffer),A.bufferData(A.ARRAY_BUFFER,this.__indexArray,A.STATIC_DRAW),this.indexArrayUpdateNeeded=!1}__updateBoxes(){this.indexArrayUpdateNeeded&&this.__updateIndexArray();const A=this.__renderer.gl;let g=Math.round(Math.sqrt(8*(this.boxes.length-this.freeIndices.length))+.5);g%8!=0&&(g+=8-g%8),this.width=g,this.__drawItemsTexture?this.__drawItemsTexture.resize(g,g):(this.__drawItemsTexture=new GLTexture2D(A,{format:"RGBA",type:"FLOAT",width:g,height:g,filter:"NEAREST",wrap:"CLAMP_TO_EDGE",mipMapped:!1}),this.__drawItemsTexture.clear()),this.__indexArray.forEach((A=>{-1!=A&&this.__updateBox(A)})),this.__updateRequested=!1}__updateBox(A){if(0==this.drawCount||!this.__drawItemsTexture)return;const g=this.boxes[A];if(!g.treeItem.isVisible())return;const I=this.__gl,C=new Float32Array(32);this.__populateBoxesDataArray(g,0,C),I.bindTexture(I.TEXTURE_2D,this.__drawItemsTexture.glTex);const e=8*A%this.width,i=Math.floor(8*A/this.width),t=this.__drawItemsTexture.type,o=this.__drawItemsTexture.format;if(t==I.FLOAT)I.texSubImage2D(I.TEXTURE_2D,0,e,i,8,1,o,t,C);else{const A=MathFunctions.convertFloat32ArrayToUInt16Array(C);I.texSubImage2D(I.TEXTURE_2D,0,e,i,8,1,o,t,A)}}draw(A){if(0==this.drawCount)return;this.__updateRequested&&this.__updateBoxes(),this.dirtyBoxes.size>0&&(this.dirtyBoxes.forEach((A=>{this.__updateBox(A)})),this.dirtyBoxes.clear()),this.indexArrayUpdateNeeded&&this.__updateIndexArray();const g=this.__gl;this.glshader.bind(A),this.glgeom.bind(A);const I=A.unifs;if(g.floatTexturesSupported&&g.drawElementsInstanced){this.__drawItemsTexture.bindToUniform(A,I.instancesTexture),g.uniform1i(I.instancesTextureSize.location,this.width);{const I=A.attrs.instancedIds.location;g.enableVertexAttribArray(I),g.bindBuffer(g.ARRAY_BUFFER,this.__instanceIdsBuffer),g.vertexAttribPointer(I,1,g.FLOAT,!1,4,0),g.vertexAttribDivisor(I,1)}g.uniform1i(I.instancedDraw.location,1),A.bindViewports(I,(()=>{this.glgeom.drawInstanced(A,this.drawCount)}))}else{const C=this.__indexArray.length;for(let e=0;e<C;e++)A.bindViewports(I,(()=>{g.drawQuad()}))}}}class GLMaskGeomsPass extends GLOpaqueGeomsPass{frontRenderTarget;backRenderTarget;itemCount=0;drawMaskGeoms=!1;init(A,g){super.init(A,g);const I=A.gl;this.frontRenderTarget=new GLRenderTarget(I,{numColorChannels:0,minFilter:I.NEAREST,magFilter:I.NEAREST,width:4,height:4,depthType:I.UNSIGNED_SHORT,depthFormat:I.DEPTH_COMPONENT,depthInternalFormat:I.DEPTH_COMPONENT16}),this.frontRenderTarget.clearColor=new Color(0,0,0,0),this.backRenderTarget=new GLRenderTarget(I,{numColorChannels:0,minFilter:I.NEAREST,magFilter:I.NEAREST,width:4,height:4,depthType:I.UNSIGNED_SHORT,depthFormat:I.DEPTH_COMPONENT,depthInternalFormat:I.DEPTH_COMPONENT16}),this.backRenderTarget.clearColor=new Color(0,0,0,0)}filterGeomItem(A){return A.materialParam.value instanceof MaskMaterial}addGeomItem(A){super.addGeomItem(A),this.itemCount++}removeGeomItem(A){super.removeGeomItem(A),this.itemCount--}draw(A){if(0==this.itemCount)return;A.pushGLStack("GLMaskGeomsPass.draw");const g=this.__gl;this.drawMaskGeoms&&(A.glEnable(g.BLEND),g.blendEquation(g.FUNC_ADD),g.blendFuncSeparate(g.SRC_ALPHA,g.ONE_MINUS_SRC_ALPHA,g.ONE,g.ONE),this.traverseTreeAndDraw(A),A.glDisable(g.BLEND),g.clear(g.DEPTH_BUFFER_BIT));const I=A.region[2],C=A.region[3];I==this.frontRenderTarget.width&&C==this.frontRenderTarget.height||(this.frontRenderTarget.resize(I,C),this.backRenderTarget.resize(I,C)),g.depthFunc(g.LESS),g.depthMask(!0),A.glEnable(g.DEPTH_TEST),this.frontRenderTarget.bindForWriting(A,!0),this.traverseTreeAndDraw(A),this.frontRenderTarget.unbindForWriting(A),this.backRenderTarget.bindForWriting(A,!0),g.depthFunc(g.GREATER),g.clearDepth(0),g.clear(g.DEPTH_BUFFER_BIT),g.cullFace(g.FRONT),this.traverseTreeAndDraw(A),this.backRenderTarget.unbindForWriting(A),g.clearDepth(1),g.depthFunc(g.LESS),g.cullFace(g.BACK),A.geometryMaskTextures=[this.frontRenderTarget.depthTexture,this.backRenderTarget.depthTexture],A.popGLStack()}drawGeomData(A){}}GLRenderer.registerPass(GLMaskGeomsPass,PassType.PRE),console.log(`Zea Engine v${version}`);const libsRegistry=new LibsRegistry(version);export{Allocation1D,Allocator1D,AngleParameter,AssetItem,AssetLoadContext,Attribute,BaseClass,BaseEvent,BaseGeom,BaseGeomItem,BaseGroup,BaseImage,BaseItem,BaseProxy,BaseTool,BillboardAlignment,BillboardItem,BillboardShader,BinReader,BinWriter,BooleanOperatorInput,BooleanOperatorOutput,BooleanParameter,Box2,Box2Parameter,Box3,Box3Parameter,CADAssembly,CADAsset,CADBody,CADPart,Camera,CameraManipulator,ChildAddedEvent,Circle,CloneContext,Color,ColorAttribute,ColorOperatorInput,ColorOperatorOutput,ColorParameter,ColorRenderState,ColorSpace,CompoundGeom,Cone,ControllerAddedEvent,CountChangedEvent,Cross,Cuboid,CuttingPlane,Cylinder,DataImage,Disc,EnvMap,EnvMapAssignedEvent,EnvMapShader,EnvProjectionMaterial,EnvProjectionShader,EulerAngles,EulerAnglesAxisOrder,EventEmitter,FRAMEBUFFER,FatLinesMaterial,FatLinesShader,FatPoints,FatPointsMaterial,FatPointsShader,FileImage,FileImage2D,FlatSurfaceMaterial,FlatSurfaceShader,Float32,Float32ArrayParameter,Frustum,GIFImage,GLBaseRenderer,GLBaseViewport,GLBillboardsPass,GLBoundingBoxPass,GLCADPass,GLFbo,GLGeom,GLGeomItem,GLGeomItemChangeType,GLGeomItemFlags,GLGeomItemSet,GLGeomItemSetMultiDraw,GLGeomItemSetMultiDrawCompoundGeom,GLLines,GLLinesItemSet,GLLinesPass,GLMaskGeomsPass,GLMaterial,GLMaterialGeomItemSets,GLMesh,GLMeshItemSet,GLOpaqueGeomsPass,GLOverlayPass,GLPass,GLPoints,GLPointsItemSet,GLRenderTarget,GLRenderer,GLShader,GLShaderGeomSets,GLShaderMaterials,GLStandardGeomsPass,GLTexture2D,GLTransparentGeomsPass,GLViewport,GROUP_XFO_MODES,GeomDataRenderState,GeomItem,GeomLibrary,GeomType$2 as GeomType,GeometryParameter,Grid,GridTreeItem,GrowingPacker,HDRImage,HighlightRenderState,IGeomShaderBinding,ImageParameter,IndexDBCache,IndexEvent,InstanceItem,IntersectionData,ItemEvent,ItemSetParameter,KeyboardEvent,KinematicGroup,LDRImage,LDRVideo,Label,LabelManager,Lines,LinesCuboid,LinesCylinder,LinesMaterial,LinesProxy,LinesShader,LinesSphere,ListParameter,MaskMaterial,Mat3,Mat3OperatorInput,Mat3OperatorOutput,Mat3Parameter,Mat4,Mat4OperatorInput,Mat4OperatorOutput,Mat4Parameter,Material,MaterialColorParam,MaterialFloatParam,MaterialGroup,MaterialLibrary,MaterialParameter,MathFunctions,Mesh,MeshProxy,MultiChoiceParameter,NameChangedEvent,NumberOperatorInput,NumberOperatorOutput,NumberParameter,ObjAsset,OpacityStateChangedEvent,Operator,OperatorInput,OperatorOutput,OperatorOutputMode,PMIItem,PMIView,POINTER_TYPES,Parameter,ParameterAddedEvent,ParameterOwner,ParameterRemovedEvent,PassType,PlaceholderGeomItem,Plane,PlaneType,PointGrid,Points,PointsMaterial,PointsProxy,PointsShader,ProceduralLines,ProceduralMesh,ProceduralPoints,ProgressEvent,Quat,QuatOperatorInput,QuatOperatorOutput,QuatParameter,RGBA,RangeLoadedEvent,Ray,Rect,RefCounted,Registry,RenderState,ResizedEvent,ResourceLoader,SInt16,SInt32,SInt8,Scene,SceneSetEvent,ScreenQuadShader,ScreenSpaceMaterial,ScreenSpaceShader,SelectabilityChangedEvent,SelectedEvent,SelectionSet,ShaderLibrary,ShaderNameChangedEvent,SimpleSurfaceMaterial,SimpleSurfaceShader,Sphere,SphereType,StandardSurfaceMaterial,StandardSurfaceShader,StateChangedEvent,StreamFileParsedEvent,StringFunctions,StringListParameter,StringParameter,StructParameter,SystemDesc,TexturedChangedEvent,Torus,Touch,TreeItem,TreeItemParameter,UInt16,UInt32,UInt8,UnpackHDRShader,VLAAsset,VRController,VRViewport,Vec2,Vec2Attribute,Vec2OperatorInput,Vec2OperatorOutput,Vec2Parameter,Vec3,Vec3Attribute,Vec3OperatorInput,Vec3OperatorOutput,Vec3Parameter,Vec4,Vec4Attribute,Vec4OperatorInput,Vec4OperatorOutput,Vec4Parameter,Version,VertexColorMaterial,VertexColorShader,VideoStreamImage2D,ViewChangedEvent,XRController,XRControllerEvent,XRHead,XRPointerEvent,XRPoseEvent,XRViewChangedEvent,XRViewManipulator,XRViewport,XRef,Xfo,XfoOperatorInput,XfoOperatorOutput,XfoParameter,XrViewportEvent,ZeaKeyboardEvent,ZeaMouseEvent,ZeaPointerEvent,ZeaTouchEvent,ZeaUIEvent,ZeaWheelEvent,archiveUnpackerWorkerPool,checkFramebuffer,create3DContext,genDataTypeDesc,generateShaderGeomBinding,geomParserWorkerPool,getFileFolder,labelManager,libsRegistry,loadBinfile,loadJSONfile,loadTextfile,loadXMLfile,resourceLoader,shaderLibrary};
//# sourceMappingURL=/sm/148b49714453fb395ea07554986a021f8d82c877aecf55dae3d67ec13c232b22.map