brep-io-kernel 1.0.196 → 1.0.197
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apiExamples/BREP_Booleans.html +2 -2
- package/dist/apiExamples/BREP_Export.html +2 -2
- package/dist/apiExamples/BREP_Primitives.html +2 -2
- package/dist/apiExamples/BREP_Transforms.html +2 -2
- package/dist/apiExamples/Embeded_2D_Sketcher.html +2 -2
- package/dist/apiExamples/Embeded_CAD.html +2 -2
- package/dist/apiExamples/Embeded_CAD_Integration_Test.html +2 -2
- package/dist/assets/{SimulationWorkbenchManager-CZU2PaTA.js → SimulationWorkbenchManager-BlXiJ2tl.js} +121 -37
- package/dist/assets/{apiExample_BREP_Booleans-D4_za_tB.js → apiExample_BREP_Booleans-C2hoasf2.js} +1 -1
- package/dist/assets/{apiExample_BREP_Export-u2fTdaNT.js → apiExample_BREP_Export-B9OOBBCX.js} +1 -1
- package/dist/assets/{apiExample_BREP_Primitives-DAoWeXoq.js → apiExample_BREP_Primitives-Do8y8b_w.js} +1 -1
- package/dist/assets/{apiExample_BREP_Transforms-DFpbDf74.js → apiExample_BREP_Transforms-Dg6kSpF5.js} +1 -1
- package/dist/assets/{apiExample_Embeded_2D_Sketcher-BTLB-XJ1.js → apiExample_Embeded_2D_Sketcher-mfrI-BcL.js} +1 -1
- package/dist/assets/{apiExample_Embeded_CAD-BN7Rap4P.js → apiExample_Embeded_CAD-GLEJ5EGM.js} +1 -1
- package/dist/assets/{apiExample_Embeded_CAD_Integration_Test-Dl4HRxKv.js → apiExample_Embeded_CAD_Integration_Test-CsWfKgCS.js} +1 -1
- package/dist/assets/{brep-kernel-CTSjNzN4.js → brep-kernel-D6hhTKa0.js} +1 -1
- package/dist/assets/{browserTests-BeGjo-jd.js → browserTests-gCJmMaIE.js} +1 -1
- package/dist/assets/{index.es-DiqUPvrb.js → index.es-CN_DUH2L.js} +1 -1
- package/dist/assets/{javascript-Bao00j9Y.js → javascript-CamWQzyi.js} +1 -1
- package/dist/assets/{main-cad-A9axj9C3.js → main-cad-BgZQtzIN.js} +5 -5
- package/dist/assets/{test-BiekV37i.js → test-q3OlLTks.js} +3 -3
- package/dist/cad.html +1 -1
- package/dist/test.html +1 -1
- package/dist/viewer.html +1 -1
- package/dist-kernel/brep-kernel.js +1 -1
- package/package.json +1 -1
- package/src/simulation/SimulationWorkbenchManager.js +121 -37
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/brep-kernel-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/brep-kernel-D6hhTKa0.js","assets/preload-helper-ZNr0Qq7Q.js"])))=>i.map(i=>d[i]);
|
|
2
2
|
var H=Object.defineProperty;var c=(e,t)=>H(e,"name",{value:t,configurable:!0});import"./modulepreload-polyfill-BdX5DvLD.js";import{_ as B}from"./preload-helper-ZNr0Qq7Q.js";const $=document.getElementById("status"),J=document.getElementById("log"),w=document.getElementById("btn-create"),V=document.getElementById("btn-destroy"),T=document.getElementById("btn-apply-css"),F=document.getElementById("btn-apply-theme"),L=document.getElementById("btn-export-svg"),G=document.getElementById("geometry-color"),_=document.getElementById("point-color"),N=document.getElementById("constraint-color"),A=document.getElementById("background-color"),P=document.getElementById("point-size-px"),O=document.getElementById("curve-thickness-px"),v=document.getElementById("sidebar-expanded"),g=document.getElementById("grid-visible"),R=document.getElementById("grid-spacing"),D=document.getElementById("css-input"),K=document.getElementById("sketch-status"),U=document.getElementById("sketch-host"),p=document.getElementById("event-output"),y=document.getElementById("svg-preview"),C=document.getElementById("path-output");let n=null,S=0,E=0,k=0;const W=5,a=c((...e)=>{const t=e.map(s=>{if(typeof s=="string")return s;try{return JSON.stringify(s)}catch{return String(s)}}).join(" ");J.textContent+=`${t}
|
|
3
3
|
`,console.log(...e)},"log"),u=c((e,t)=>{$.textContent=e,$.className=`status ${t}`},"setStatus"),o=c(e=>{K.textContent=e},"setSketchStatus"),x=c(e=>{w.disabled=e,V.disabled=!e,T.disabled=!e,F.disabled=!e,L.disabled=!e},"setSketchButtons"),h=c((e,t=null)=>{const s=new Date().toLocaleTimeString(),i=t==null?`[${s}] ${e}`:`[${s}] ${e} ${JSON.stringify(t)}`,l=p.textContent==="(No sketch events yet)"?[]:p.textContent.split(`
|
|
4
4
|
`).filter(Boolean),d=[i,...l].slice(0,W);p.textContent=d.length?d.join(`
|
|
5
|
-
`):"(No sketch events yet)"},"pushEvent"),M=c(()=>({geometryColor:G.value,pointColor:_.value,constraintColor:N.value,backgroundColor:A.value,pointSizePx:Math.max(1,Number(P.value)||10),curveThicknessPx:Math.max(.5,Number(O.value)||2)}),"currentTheme"),b=c(()=>{const e=Number(R.value);return Number.isFinite(e)&&e>0?e:1},"currentGridSpacing"),X=c(async()=>{if(n)return;const{Sketcher2DEmbed:e}=await B(async()=>{const{Sketcher2DEmbed:t}=await import("./brep-kernel-
|
|
6
|
-
`):"(No sketch geometry to export)",o(`Exported ${e.paths.length} SVG paths.`),y.scrollIntoView({behavior:"smooth",block:"start"})},"exportSvg");w.addEventListener("click",()=>{X().catch(e=>{console.error(e),o(`Failed to create sketcher: ${e?.message||String(e)}`)})});V.addEventListener("click",()=>{Y().catch(e=>{console.error(e),o(`Failed to destroy sketcher: ${e?.message||String(e)}`)})});T.addEventListener("click",()=>{q().catch(e=>{console.error(e),o(`Failed to apply CSS: ${e?.message||String(e)}`)})});L.addEventListener("click",()=>{j().catch(e=>{console.error(e),o(`Failed to export SVG: ${e?.message||String(e)}`)})});F.addEventListener("click",()=>{r().catch(e=>{console.error(e),o(`Failed to apply theme: ${e?.message||String(e)}`)})});[G,_,N,A,P,O].forEach(e=>{e.addEventListener("input",()=>{n&&r().catch(t=>{console.error(t),o(`Failed to apply theme: ${t?.message||String(t)}`)})})});v.addEventListener("change",()=>{n&&r().catch(e=>{console.error(e),o(`Failed to apply sidebar state: ${e?.message||String(e)}`)})});g.addEventListener("change",()=>{n&&r().catch(e=>{console.error(e),o(`Failed to apply grid visibility: ${e?.message||String(e)}`)})});R.addEventListener("input",()=>{n&&r().catch(e=>{console.error(e),o(`Failed to apply grid spacing: ${e?.message||String(e)}`)})});x(!1);C.textContent="(No SVG exported yet)";(async()=>{u("Importing bundle...","pending");const e=await B(()=>import("./brep-kernel-
|
|
5
|
+
`):"(No sketch events yet)"},"pushEvent"),M=c(()=>({geometryColor:G.value,pointColor:_.value,constraintColor:N.value,backgroundColor:A.value,pointSizePx:Math.max(1,Number(P.value)||10),curveThicknessPx:Math.max(.5,Number(O.value)||2)}),"currentTheme"),b=c(()=>{const e=Number(R.value);return Number.isFinite(e)&&e>0?e:1},"currentGridSpacing"),X=c(async()=>{if(n)return;const{Sketcher2DEmbed:e}=await B(async()=>{const{Sketcher2DEmbed:t}=await import("./brep-kernel-D6hhTKa0.js");return{Sketcher2DEmbed:t}},__vite__mapDeps([0,1]));n=new e({cssText:D.value,...M(),sidebarExpanded:v.checked,gridVisible:g.checked,gridSpacing:b(),onChange:c(t=>{S+=1;const s=Array.isArray(t?.geometries)?t.geometries.length:0;o(`Sketch updated (${S}). Geometries: ${s}`),h("onChange",{geometries:s})},"onChange"),onFinished:c(t=>{E+=1;const s=Array.isArray(t?.geometries)?t.geometries.length:0;o(`Sketch finished (${E}). Geometries: ${s}`),h("onFinished",{geometries:s}),j().catch(i=>{console.error(i),o(`Failed to export SVG after Finish: ${i?.message||String(i)}`)})},"onFinished"),onCancelled:c(()=>{k+=1,o(`Sketch cancelled (${k}).`),h("onCancelled")},"onCancelled")}),await n.mount(U),await n.getSketch(),x(!0),o("Sketcher iframe mounted. Draw geometry and click Export SVG Paths.")},"attachSketcher"),Y=c(async()=>{n&&(await n.destroy(),n=null,S=0,E=0,k=0,x(!1),o("Sketcher destroyed."),p.textContent="(No sketch events yet)",y.innerHTML="",C.textContent="")},"detachSketcher"),q=c(async()=>{n&&(await n.setCss(D.value),o("Custom CSS applied to iframe."))},"applySketchCss"),r=c(async()=>{n&&(await n.setTheme(M()),await n.setSidebarExpanded(v.checked),typeof n.setGrid=="function"?await n.setGrid({visible:g.checked,spacing:b()}):(typeof n.setGridVisible=="function"&&await n.setGridVisible(g.checked),typeof n.setGridSpacing=="function"&&await n.setGridSpacing(b())),o("Theme + sidebar + grid state applied to iframe."))},"applySketchTheme"),j=c(async()=>{if(!n)return;const e=await n.exportSVG({flipY:!0,precision:3,stroke:"#111111",strokeWidth:1.5,fill:"none",padding:12});await n.getSketch({preferCached:!0}),y.innerHTML=e.svg,C.textContent=e.paths.length?e.paths.map(t=>`id=${t.id} type=${t.type} d="${t.d}"`).join(`
|
|
6
|
+
`):"(No sketch geometry to export)",o(`Exported ${e.paths.length} SVG paths.`),y.scrollIntoView({behavior:"smooth",block:"start"})},"exportSvg");w.addEventListener("click",()=>{X().catch(e=>{console.error(e),o(`Failed to create sketcher: ${e?.message||String(e)}`)})});V.addEventListener("click",()=>{Y().catch(e=>{console.error(e),o(`Failed to destroy sketcher: ${e?.message||String(e)}`)})});T.addEventListener("click",()=>{q().catch(e=>{console.error(e),o(`Failed to apply CSS: ${e?.message||String(e)}`)})});L.addEventListener("click",()=>{j().catch(e=>{console.error(e),o(`Failed to export SVG: ${e?.message||String(e)}`)})});F.addEventListener("click",()=>{r().catch(e=>{console.error(e),o(`Failed to apply theme: ${e?.message||String(e)}`)})});[G,_,N,A,P,O].forEach(e=>{e.addEventListener("input",()=>{n&&r().catch(t=>{console.error(t),o(`Failed to apply theme: ${t?.message||String(t)}`)})})});v.addEventListener("change",()=>{n&&r().catch(e=>{console.error(e),o(`Failed to apply sidebar state: ${e?.message||String(e)}`)})});g.addEventListener("change",()=>{n&&r().catch(e=>{console.error(e),o(`Failed to apply grid visibility: ${e?.message||String(e)}`)})});R.addEventListener("input",()=>{n&&r().catch(e=>{console.error(e),o(`Failed to apply grid spacing: ${e?.message||String(e)}`)})});x(!1);C.textContent="(No SVG exported yet)";(async()=>{u("Importing bundle...","pending");const e=await B(()=>import("./brep-kernel-D6hhTKa0.js"),__vite__mapDeps([0,1]));a("Bundle exports:",Object.keys(e));const{BREP:t}=e;if(!t)throw new Error("BREP export missing from bundle");u("Running kernel checks...","pending");const s=new t.Cube({x:2,y:3,z:4,name:"Cube"}),i=s.volume();a("Cube volume:",i);const l=new t.Sphere({r:1,resolution:24,name:"Sphere"}),d=l.getTriangleCount();a("Sphere triangles:",d);const f=s.union(l),z=f.volume();a("Union volume:",z),a("Union triangles:",f.getTriangleCount());const m=24,I=Math.abs(i-m)<1e-6;if(a("Cube volume check:",I?"OK":"FAIL","(expected",m,")"),!I)throw new Error(`Cube volume mismatch: ${i} vs ${m}`);u("Success: bundle + WASM OK","ok")})().catch(e=>{console.error(e),a("ERROR:",e&&(e.stack||e.message||String(e))),u("Failed: see log","err")});
|
package/dist/cad.html
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
<script type="module" crossorigin src="/assets/ListEntityBase-DIaWtqmZ.js"></script>
|
|
20
20
|
<script type="module" crossorigin src="/assets/PartHistory-CW7D2BZZ.js"></script>
|
|
21
21
|
<script type="module" crossorigin src="/assets/AnnotationRegistry-DxNMMWXW.js"></script>
|
|
22
|
-
<script type="module" crossorigin src="/assets/main-cad-
|
|
22
|
+
<script type="module" crossorigin src="/assets/main-cad-BgZQtzIN.js"></script>
|
|
23
23
|
<link rel="stylesheet" crossorigin href="/assets/main-cad-C3E_anfF.css">
|
|
24
24
|
</head>
|
|
25
25
|
|
package/dist/test.html
CHANGED
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
font-size: 13px;
|
|
168
168
|
}
|
|
169
169
|
</style>
|
|
170
|
-
<script type="module" crossorigin src="/assets/test-
|
|
170
|
+
<script type="module" crossorigin src="/assets/test-q3OlLTks.js"></script>
|
|
171
171
|
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-BdX5DvLD.js">
|
|
172
172
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-ZNr0Qq7Q.js">
|
|
173
173
|
</head>
|
package/dist/viewer.html
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
<script type="module" crossorigin src="/assets/ListEntityBase-DIaWtqmZ.js"></script>
|
|
20
20
|
<script type="module" crossorigin src="/assets/PartHistory-CW7D2BZZ.js"></script>
|
|
21
21
|
<script type="module" crossorigin src="/assets/AnnotationRegistry-DxNMMWXW.js"></script>
|
|
22
|
-
<script type="module" crossorigin src="/assets/main-cad-
|
|
22
|
+
<script type="module" crossorigin src="/assets/main-cad-BgZQtzIN.js"></script>
|
|
23
23
|
<link rel="stylesheet" crossorigin href="/assets/main-cad-C3E_anfF.css">
|
|
24
24
|
</head>
|
|
25
25
|
|
|
@@ -304369,7 +304369,7 @@ const G1e = class G1e {
|
|
|
304369
304369
|
async _ensureSimulationWorkbenchManager() {
|
|
304370
304370
|
return this.simulationWorkbenchManager ? this.simulationWorkbenchManager : this._simulationWorkbenchManagerPromise ? this._simulationWorkbenchManagerPromise : (this._simulationWorkbenchManagerPromise = (async () => {
|
|
304371
304371
|
try {
|
|
304372
|
-
const A = new URL("data:text/javascript;base64,aW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnOwppbXBvcnQgeyBDb21iaW5lZFRyYW5zZm9ybUNvbnRyb2xzIH0gZnJvbSAnLi4vVUkvY29udHJvbHMvQ29tYmluZWRUcmFuc2Zvcm1Db250cm9scy5qcyc7Cgpjb25zdCBGSVhFRF9NRVRBREFUQV9LRVkgPSAnZml4ZWQnOwpjb25zdCBUUkFOU0ZPUk1fTUVUQURBVEFfS0VZID0gJ3NpbXVsYXRpb25UcmFuc2Zvcm0nOwpjb25zdCBTSU1fUFJPWFlfUFJFRklYID0gJ19fU0lNX1BST1hZX18nOwpjb25zdCBWSEFDRF9PUFRJT05TID0gT2JqZWN0LmZyZWV6ZSh7CiAgbWF4SHVsbHM6IDY0LAogIHZveGVsUmVzb2x1dGlvbjogMTAwMDAwMCwKICBtYXhWZXJ0aWNlc1Blckh1bGw6IDY0LAogIHNocmlua1dyYXA6IHRydWUsCiAgZmlsbE1vZGU6ICdmbG9vZCcsCiAgZmluZEJlc3RQbGFuZTogdHJ1ZSwKICBtaW5FZGdlTGVuZ3RoOiAxLAogIG1lc3NhZ2VzOiAnbm9uZScsCn0pOwpjb25zdCBERUZBVUxUX1RSQU5TRk9STSA9IE9iamVjdC5mcmVlemUoewogIHBvc2l0aW9uOiBbMCwgMCwgMF0sCiAgcm90YXRpb25FdWxlcjogWzAsIDAsIDBdLAp9KTsKCmZ1bmN0aW9uIGNsb25lVmVjMyh2YWx1ZSwgZmFsbGJhY2sgPSBbMCwgMCwgMF0pIHsKICBjb25zdCBzcmMgPSBBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlIDogZmFsbGJhY2s7CiAgcmV0dXJuIFsKICAgIE51bWJlci5pc0Zpbml0ZShOdW1iZXIoc3JjWzBdKSkgPyBOdW1iZXIoc3JjWzBdKSA6IGZhbGxiYWNrWzBdLAogICAgTnVtYmVyLmlzRmluaXRlKE51bWJlcihzcmNbMV0pKSA/IE51bWJlcihzcmNbMV0pIDogZmFsbGJhY2tbMV0sCiAgICBOdW1iZXIuaXNGaW5pdGUoTnVtYmVyKHNyY1syXSkpID8gTnVtYmVyKHNyY1syXSkgOiBmYWxsYmFja1syXSwKICBdOwp9CgpmdW5jdGlvbiBub3JtYWxpemVUZXh0KHZhbHVlLCBmYWxsYmFjayA9ICcnKSB7CiAgY29uc3QgbmV4dCA9IFN0cmluZyh2YWx1ZSA9PSBudWxsID8gJycgOiB2YWx1ZSkudHJpbSgpOwogIHJldHVybiBuZXh0IHx8IGZhbGxiYWNrOwp9CgpmdW5jdGlvbiBub3JtYWxpemVUcmFuc2Zvcm0odmFsdWUpIHsKICBjb25zdCByYXcgPSB2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnID8gdmFsdWUgOiB7fTsKICByZXR1cm4gewogICAgcG9zaXRpb246IGNsb25lVmVjMyhyYXcucG9zaXRpb24sIERFRkFVTFRfVFJBTlNGT1JNLnBvc2l0aW9uKSwKICAgIHJvdGF0aW9uRXVsZXI6IGNsb25lVmVjMyhyYXcucm90YXRpb25FdWxlciwgREVGQVVMVF9UUkFOU0ZPUk0ucm90YXRpb25FdWxlciksCiAgfTsKfQoKZnVuY3Rpb24gdHJhbnNmb3JtSXNJZGVudGl0eSh0cmFuc2Zvcm0pIHsKICBjb25zdCBwb3NpdGlvbiA9IGNsb25lVmVjMyh0cmFuc2Zvcm0/LnBvc2l0aW9uLCBERUZBVUxUX1RSQU5TRk9STS5wb3NpdGlvbik7CiAgY29uc3Qgcm90YXRpb25FdWxlciA9IGNsb25lVmVjMyh0cmFuc2Zvcm0/LnJvdGF0aW9uRXVsZXIsIERFRkFVTFRfVFJBTlNGT1JNLnJvdGF0aW9uRXVsZXIpOwogIHJldHVybiBwb3NpdGlvbi5ldmVyeSgodmFsdWUpID0+IE1hdGguYWJzKHZhbHVlKSA8PSAxZS05KQogICAgJiYgcm90YXRpb25FdWxlci5ldmVyeSgodmFsdWUpID0+IE1hdGguYWJzKHZhbHVlKSA8PSAxZS05KTsKfQoKZnVuY3Rpb24gY29weUxvY2FsUG9zZShvYmplY3QpIHsKICByZXR1cm4gewogICAgcG9zaXRpb246IG9iamVjdC5wb3NpdGlvbi5jbG9uZSgpLAogICAgcXVhdGVybmlvbjogb2JqZWN0LnF1YXRlcm5pb24uY2xvbmUoKSwKICAgIHNjYWxlOiBvYmplY3Quc2NhbGUuY2xvbmUoKSwKICB9Owp9CgpmdW5jdGlvbiBidWlsZExvY2FsTWF0cml4KHBvc2UpIHsKICByZXR1cm4gbmV3IFRIUkVFLk1hdHJpeDQoKS5jb21wb3NlKAogICAgcG9zZS5wb3NpdGlvbi5jbG9uZSgpLAogICAgcG9zZS5xdWF0ZXJuaW9uLmNsb25lKCksCiAgICBwb3NlLnNjYWxlLmNsb25lKCksCiAgKTsKfQoKZnVuY3Rpb24gcG9zZVRvT2Zmc2V0KGJhc2VQb3NlLCBjdXJyZW50T2JqZWN0KSB7CiAgY29uc3QgYmFzZU1hdHJpeCA9IGJ1aWxkTG9jYWxNYXRyaXgoYmFzZVBvc2UpOwogIGNvbnN0IGN1cnJlbnRNYXRyaXggPSBuZXcgVEhSRUUuTWF0cml4NCgpLmNvbXBvc2UoCiAgICBjdXJyZW50T2JqZWN0LnBvc2l0aW9uLmNsb25lKCksCiAgICBjdXJyZW50T2JqZWN0LnF1YXRlcm5pb24uY2xvbmUoKSwKICAgIGN1cnJlbnRPYmplY3Quc2NhbGUuY2xvbmUoKSwKICApOwogIGNvbnN0IHJlbGF0aXZlID0gbmV3IFRIUkVFLk1hdHJpeDQoKS5jb3B5KGJhc2VNYXRyaXgpLmludmVydCgpLm11bHRpcGx5KGN1cnJlbnRNYXRyaXgpOwogIGNvbnN0IHBvc2l0aW9uID0gbmV3IFRIUkVFLlZlY3RvcjMoKTsKICBjb25zdCBxdWF0ZXJuaW9uID0gbmV3IFRIUkVFLlF1YXRlcm5pb24oKTsKICBjb25zdCBzY2FsZSA9IG5ldyBUSFJFRS5WZWN0b3IzKCk7CiAgcmVsYXRpdmUuZGVjb21wb3NlKHBvc2l0aW9uLCBxdWF0ZXJuaW9uLCBzY2FsZSk7CiAgY29uc3Qgcm90YXRpb25FdWxlciA9IG5ldyBUSFJFRS5FdWxlcigpLnNldEZyb21RdWF0ZXJuaW9uKHF1YXRlcm5pb24sICdYWVonKTsKICByZXR1cm4gewogICAgcG9zaXRpb246IFtwb3NpdGlvbi54LCBwb3NpdGlvbi55LCBwb3NpdGlvbi56XSwKICAgIHJvdGF0aW9uRXVsZXI6IFtyb3RhdGlvbkV1bGVyLngsIHJvdGF0aW9uRXVsZXIueSwgcm90YXRpb25FdWxlci56XSwKICB9Owp9CgpmdW5jdGlvbiBub3JtYWxpemVNZXNoQXJyYXlzKG1lc2gpIHsKICBpZiAoIW1lc2gpIHJldHVybiBudWxsOwogIGNvbnN0IHN0cmlkZSA9IE1hdGgubWF4KDMsIE51bWJlcihtZXNoLm51bVByb3ApIHx8IDMpOwogIGNvbnN0IHNvdXJjZVBvc2l0aW9ucyA9IEFycmF5LmlzQXJyYXkobWVzaC52ZXJ0UHJvcGVydGllcykgPyBtZXNoLnZlcnRQcm9wZXJ0aWVzIDogQXJyYXkuZnJvbShtZXNoLnZlcnRQcm9wZXJ0aWVzIHx8IFtdKTsKICBjb25zdCBzb3VyY2VJbmRpY2VzID0gQXJyYXkuaXNBcnJheShtZXNoLnRyaVZlcnRzKSA/IG1lc2gudHJpVmVydHMgOiBBcnJheS5mcm9tKG1lc2gudHJpVmVydHMgfHwgW10pOwogIGlmIChzb3VyY2VQb3NpdGlvbnMubGVuZ3RoIDwgOSB8fCBzb3VyY2VJbmRpY2VzLmxlbmd0aCA8IDMpIHJldHVybiBudWxsOwogIGNvbnN0IHBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkoKHNvdXJjZVBvc2l0aW9ucy5sZW5ndGggLyBzdHJpZGUpICogMyk7CiAgZm9yIChsZXQgc3JjID0gMCwgZHN0ID0gMDsgc3JjICsgMiA8IHNvdXJjZVBvc2l0aW9ucy5sZW5ndGg7IHNyYyArPSBzdHJpZGUsIGRzdCArPSAzKSB7CiAgICBwb3NpdGlvbnNbZHN0ICsgMF0gPSBOdW1iZXIoc291cmNlUG9zaXRpb25zW3NyYyArIDBdKSB8fCAwOwogICAgcG9zaXRpb25zW2RzdCArIDFdID0gTnVtYmVyKHNvdXJjZVBvc2l0aW9uc1tzcmMgKyAxXSkgfHwgMDsKICAgIHBvc2l0aW9uc1tkc3QgKyAyXSA9IE51bWJlcihzb3VyY2VQb3NpdGlvbnNbc3JjICsgMl0pIHx8IDA7CiAgfQogIHJldHVybiB7CiAgICBwb3NpdGlvbnMsCiAgICBpbmRpY2VzOiBuZXcgVWludDMyQXJyYXkoc291cmNlSW5kaWNlcyksCiAgfTsKfQoKZnVuY3Rpb24gYnVpbGRQcm94eU1hdGVyaWFsKGJhc2VDb2xvciwgaW5kZXgsIHRvdGFsKSB7CiAgY29uc3QgY29sb3IgPSBuZXcgVEhSRUUuQ29sb3IoYmFzZUNvbG9yIHx8ICcjOWNhM2FmJyk7CiAgY29uc3QgaHNsID0geyBoOiAwLCBzOiAwLCBsOiAwIH07CiAgY29sb3IuZ2V0SFNMKGhzbCk7CiAgY29uc3Qgb2Zmc2V0ID0gdG90YWwgPiAxID8gKGluZGV4IC8gTWF0aC5tYXgoMSwgdG90YWwpKSAqIDAuMTggOiAwOwogIGNvbG9yLnNldEhTTCgoaHNsLmggKyBvZmZzZXQpICUgMSwgTWF0aC5taW4oMSwgTWF0aC5tYXgoMC4zNSwgaHNsLnMgfHwgMC41NSkpLCBNYXRoLm1pbigwLjcyLCBNYXRoLm1heCgwLjQyLCBoc2wubCkpKTsKICByZXR1cm4gbmV3IFRIUkVFLk1lc2hTdGFuZGFyZE1hdGVyaWFsKHsKICAgIGNvbG9yLAogICAgdHJhbnNwYXJlbnQ6IHRydWUsCiAgICBvcGFjaXR5OiAwLjU1LAogICAgcm91Z2huZXNzOiAwLjU1LAogICAgbWV0YWxuZXNzOiAwLjA1LAogICAgZGVwdGhXcml0ZTogdHJ1ZSwKICB9KTsKfQoKZnVuY3Rpb24gZGlzcG9zZUhpZXJhcmNoeShyb290KSB7CiAgaWYgKCFyb290Py50cmF2ZXJzZSkgcmV0dXJuOwogIHJvb3QudHJhdmVyc2UoKG5vZGUpID0+IHsKICAgIGlmIChub2RlPy5nZW9tZXRyeT8uZGlzcG9zZSkgewogICAgICB0cnkgeyBub2RlLmdlb21ldHJ5LmRpc3Bvc2UoKTsgfSBjYXRjaCB7fQogICAgfQogICAgaWYgKEFycmF5LmlzQXJyYXkobm9kZT8ubWF0ZXJpYWwpKSB7CiAgICAgIGZvciAoY29uc3QgbWF0ZXJpYWwgb2Ygbm9kZS5tYXRlcmlhbCkgewogICAgICAgIHRyeSB7IG1hdGVyaWFsPy5kaXNwb3NlPy4oKTsgfSBjYXRjaCB7fQogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0cnkgeyBub2RlPy5tYXRlcmlhbD8uZGlzcG9zZT8uKCk7IH0gY2F0Y2gge30KICAgIH0KICB9KTsKfQoKZXhwb3J0IGNsYXNzIFNpbXVsYXRpb25Xb3JrYmVuY2hNYW5hZ2VyIHsKICBjb25zdHJ1Y3Rvcih2aWV3ZXIpIHsKICAgIHRoaXMudmlld2VyID0gdmlld2VyIHx8IG51bGw7CiAgICB0aGlzLl9hY3RpdmUgPSBmYWxzZTsKICAgIHRoaXMuX2Jhc2VMb2NhbFBvc2UgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9ydW50aW1lU3RhdGUgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9zb3VyY2VWaXNpYmlsaXR5ID0gbmV3IE1hcCgpOwogICAgdGhpcy5fZGVjb21wb3NpdGlvbkNhY2hlID0gbmV3IE1hcCgpOwogICAgdGhpcy5fcHJveHlHcm91cHMgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl90cmFuc2Zvcm1TZXNzaW9uID0gbnVsbDsKICAgIHRoaXMuX3JhcGllciA9IG51bGw7CiAgICB0aGlzLl9yYXBpZXJMb2FkUHJvbWlzZSA9IG51bGw7CiAgICB0aGlzLl92aGFjZCA9IG51bGw7CiAgICB0aGlzLl92aGFjZExvYWRQcm9taXNlID0gbnVsbDsKICAgIHRoaXMuX3BoeXNpY3NXb3JsZCA9IG51bGw7CiAgICB0aGlzLl9ib2R5U3RhdGUgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9saXN0ZW5lcnMgPSBuZXcgU2V0KCk7CiAgICB0aGlzLl9yZW1vdmVTdGF0ZU1hbmFnZXJMaXN0ZW5lciA9IG51bGw7CiAgICB0aGlzLl9pc1BsYXlpbmcgPSBmYWxzZTsKICAgIHRoaXMuX21vdGlvblN0YXRlID0gbmV3IE1hcCgpOwogICAgdGhpcy5fbW92ZWRTb2xpZElkcyA9IG5ldyBTZXQoKTsKICAgIHRoaXMuX3JhZiA9IDA7CiAgICB0aGlzLl9sYXN0U3RlcFRpbWUgPSAwOwogICAgdGhpcy5fc2NyYXRjaCA9IHsKICAgICAgcGFyZW50SW52ZXJzZTogbmV3IFRIUkVFLk1hdHJpeDQoKSwKICAgICAgcGFyZW50V29ybGRNYXRyaXg6IG5ldyBUSFJFRS5NYXRyaXg0KCksCiAgICAgIGxvY2FsTWF0cml4OiBuZXcgVEhSRUUuTWF0cml4NCgpLAogICAgICB3b3JsZE1hdHJpeDogbmV3IFRIUkVFLk1hdHJpeDQoKSwKICAgICAgZGVsdGFNYXRyaXg6IG5ldyBUSFJFRS5NYXRyaXg0KCksCiAgICAgIHdvcmxkUG9zaXRpb246IG5ldyBUSFJFRS5WZWN0b3IzKCksCiAgICAgIGxvY2FsUG9zaXRpb246IG5ldyBUSFJFRS5WZWN0b3IzKCksCiAgICAgIHdvcmxkUXVhdGVybmlvbjogbmV3IFRIUkVFLlF1YXRlcm5pb24oKSwKICAgICAgcGFyZW50UXVhdGVybmlvbjogbmV3IFRIUkVFLlF1YXRlcm5pb24oKSwKICAgICAgcGFyZW50UXVhdGVybmlvbkludmVyc2U6IG5ldyBUSFJFRS5RdWF0ZXJuaW9uKCksCiAgICAgIGJveDogbmV3IFRIUkVFLkJveDMoKSwKICAgICAgY2VudGVyOiBuZXcgVEhSRUUuVmVjdG9yMygpLAogICAgICBheGlzOiBuZXcgVEhSRUUuVmVjdG9yMygpLAogICAgICB0cmFuc2xhdGlvbjogbmV3IFRIUkVFLlZlY3RvcjMoKSwKICAgIH07CiAgICB0aGlzLl9iaW5kU3RhdGVNYW5hZ2VyKCk7CiAgfQoKICBkaXNwb3NlKCkgewogICAgaWYgKHR5cGVvZiB0aGlzLl9yZW1vdmVTdGF0ZU1hbmFnZXJMaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJykgewogICAgICB0cnkgeyB0aGlzLl9yZW1vdmVTdGF0ZU1hbmFnZXJMaXN0ZW5lcigpOyB9IGNhdGNoIHt9CiAgICB9CiAgICB0aGlzLl9yZW1vdmVTdGF0ZU1hbmFnZXJMaXN0ZW5lciA9IG51bGw7CiAgICB0aGlzLnNldEFjdGl2ZShmYWxzZSk7CiAgfQoKICBpc0FjdGl2ZSgpIHsKICAgIHJldHVybiB0aGlzLl9hY3RpdmU7CiAgfQoKICBpc1NpbXVsYXRpb25Xb3JrYmVuY2hBY3RpdmUoKSB7CiAgICByZXR1cm4gdGhpcy52aWV3ZXI/Ll9nZXRBY3RpdmVXb3JrYmVuY2hJZD8uKCkgPT09ICdTSU1VTEFUSU9OJzsKICB9CgogIGFkZExpc3RlbmVyKGxpc3RlbmVyKSB7CiAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKSByZXR1cm4gKCkgPT4ge307CiAgICB0aGlzLl9saXN0ZW5lcnMuYWRkKGxpc3RlbmVyKTsKICAgIHJldHVybiAoKSA9PiB7CiAgICAgIHRyeSB7IHRoaXMuX2xpc3RlbmVycy5kZWxldGUobGlzdGVuZXIpOyB9IGNhdGNoIHt9CiAgICB9OwogIH0KCiAgcmVtb3ZlTGlzdGVuZXIobGlzdGVuZXIpIHsKICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpIHJldHVybjsKICAgIHRyeSB7IHRoaXMuX2xpc3RlbmVycy5kZWxldGUobGlzdGVuZXIpOyB9IGNhdGNoIHt9CiAgfQoKICBpc1BsYXlpbmcoKSB7CiAgICByZXR1cm4gdGhpcy5faXNQbGF5aW5nOwogIH0KCiAgc2V0UGxheWluZyhwbGF5aW5nKSB7CiAgICBjb25zdCBuZXh0ID0gISFwbGF5aW5nOwogICAgaWYgKG5leHQgPT09IHRoaXMuX2lzUGxheWluZykgcmV0dXJuIHRoaXMuX2lzUGxheWluZzsKICAgIHRoaXMuX2lzUGxheWluZyA9IG5leHQ7CiAgICBpZiAodGhpcy5fYWN0aXZlKSB7CiAgICAgIGlmIChuZXh0KSB7CiAgICAgICAgdm9pZCB0aGlzLl9wcmVwYXJlU2ltdWxhdGlvbkFzc2V0cygpLnRoZW4oKCkgPT4gewogICAgICAgICAgdGhpcy5fZW5zdXJlUGh5c2ljc0xvb3AoKTsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLl9zdG9wUGh5c2ljc0xvb3AoKTsKICAgICAgfQogICAgfQogICAgdGhpcy5fZW1pdCgpOwogICAgdHJ5IHsgdGhpcy52aWV3ZXI/LnJlbmRlcj8uKCk7IH0gY2F0Y2gge30KICAgIHJldHVybiB0aGlzLl9pc1BsYXlpbmc7CiAgfQoKICByZXNldFNpbXVsYXRpb25TdGF0ZSgpIHsKICAgIHRoaXMuX3N0b3BUcmFuc2Zvcm1TZXNzaW9uKCk7CiAgICB0aGlzLl9zdG9wUGh5c2ljc0xvb3AoKTsKICAgIHRoaXMuX2Rlc3Ryb3lQaHlzaWNzV29ybGQoKTsKICAgIHRoaXMuX2lzUGxheWluZyA9IGZhbHNlOwogICAgdGhpcy5fbW92ZWRTb2xpZElkcy5jbGVhcigpOwogICAgdGhpcy5fbW90aW9uU3RhdGUuY2xlYXIoKTsKICAgIGZvciAoY29uc3Qgc29saWQgb2YgdGhpcy5fbGlzdFNjZW5lU29saWRzKCkpIHsKICAgICAgdGhpcy5fcnVudGltZVN0YXRlLnNldChzb2xpZC51dWlkLCBub3JtYWxpemVUcmFuc2Zvcm0obnVsbCkpOwogICAgICB0aGlzLnNldFN0b3JlZFRyYW5zZm9ybShzb2xpZCwgbnVsbCk7CiAgICB9CiAgICB0aGlzLl9yZXN0b3JlQmFzZUxvY2FsUG9zZXMoKTsKICAgIGZvciAoY29uc3Qgc29saWQgb2YgdGhpcy5fbGlzdFNjZW5lU29saWRzKCkpIHsKICAgICAgdGhpcy5fc3luY1Byb3h5R3JvdXBUcmFuc2Zvcm0oc29saWQpOwogICAgfQogICAgaWYgKHRoaXMuX2FjdGl2ZSkgewogICAgICB0aGlzLl9yZXNldE1vdGlvblJ1bnRpbWUoKTsKICAgIH0KICAgIHRoaXMuX2VtaXQoKTsKICAgIHRyeSB7IHRoaXMudmlld2VyPy5yZW5kZXI/LigpOyB9IGNhdGNoIHt9CiAgfQoKICBnZXRTb2xpZEZpeGVkKHNvbGlkKSB7CiAgICBpZiAoIXNvbGlkPy5uYW1lKSByZXR1cm4gZmFsc2U7CiAgICBjb25zdCBvd24gPSB0aGlzLnZpZXdlcj8ucGFydEhpc3Rvcnk/Lm1ldGFkYXRhTWFuYWdlcj8uZ2V0T3duTWV0YWRhdGE/Lihzb2xpZC5uYW1lKSB8fCB7fTsKICAgIHJldHVybiBvd25bRklYRURfTUVUQURBVEFfS0VZXSA9PT0gdHJ1ZTsKICB9CgogIHNldFNvbGlkRml4ZWQoc29saWQsIGZpeGVkKSB7CiAgICBpZiAoIXNvbGlkPy5uYW1lKSByZXR1cm4gZmFsc2U7CiAgICBjb25zdCBtYW5hZ2VyID0gdGhpcy52aWV3ZXI/LnBhcnRIaXN0b3J5Py5tZXRhZGF0YU1hbmFnZXI7CiAgICBpZiAoIW1hbmFnZXIpIHJldHVybiBmYWxzZTsKICAgIGNvbnN0IGRhdGEgPSBtYW5hZ2VyLmdldE93bk1ldGFkYXRhKHNvbGlkLm5hbWUpOwogICAgaWYgKGZpeGVkKSBkYXRhW0ZJWEVEX01FVEFEQVRBX0tFWV0gPSB0cnVlOwogICAgZWxzZSBkZWxldGUgZGF0YVtGSVhFRF9NRVRBREFUQV9LRVldOwogICAgbWFuYWdlci5zZXRNZXRhZGF0YU9iamVjdChzb2xpZC5uYW1lLCBkYXRhKTsKICAgIGlmICh0aGlzLl9hY3RpdmUgJiYgdGhpcy5fcGh5c2ljc1dvcmxkKSB7CiAgICAgIHZvaWQgdGhpcy5fcmVidWlsZFBoeXNpY3NXb3JsZCgpOwogICAgfQogICAgcmV0dXJuIHRydWU7CiAgfQoKICBnZXRTdG9yZWRUcmFuc2Zvcm0oc29saWQpIHsKICAgIGlmICghc29saWQ/Lm5hbWUpIHJldHVybiBub3JtYWxpemVUcmFuc2Zvcm0obnVsbCk7CiAgICBjb25zdCBvd24gPSB0aGlzLnZpZXdlcj8ucGFydEhpc3Rvcnk/Lm1ldGFkYXRhTWFuYWdlcj8uZ2V0T3duTWV0YWRhdGE/Lihzb2xpZC5uYW1lKSB8fCB7fTsKICAgIHJldHVybiBub3JtYWxpemVUcmFuc2Zvcm0ob3duW1RSQU5TRk9STV9NRVRBREFUQV9LRVldKTsKICB9CgogIHNldFN0b3JlZFRyYW5zZm9ybShzb2xpZCwgdHJhbnNmb3JtKSB7CiAgICBpZiAoIXNvbGlkPy5uYW1lKSByZXR1cm4gZmFsc2U7CiAgICBjb25zdCBtYW5hZ2VyID0gdGhpcy52aWV3ZXI/LnBhcnRIaXN0b3J5Py5tZXRhZGF0YU1hbmFnZXI7CiAgICBpZiAoIW1hbmFnZXIpIHJldHVybiBmYWxzZTsKICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSBub3JtYWxpemVUcmFuc2Zvcm0odHJhbnNmb3JtKTsKICAgIGNvbnN0IGRhdGEgPSBtYW5hZ2VyLmdldE93bk1ldGFkYXRhKHNvbGlkLm5hbWUpOwogICAgaWYgKHRyYW5zZm9ybUlzSWRlbnRpdHkobm9ybWFsaXplZCkpIGRlbGV0ZSBkYXRhW1RSQU5TRk9STV9NRVRBREFUQV9LRVldOwogICAgZWxzZSBkYXRhW1RSQU5TRk9STV9NRVRBREFUQV9LRVldID0gbm9ybWFsaXplZDsKICAgIG1hbmFnZXIuc2V0TWV0YWRhdGFPYmplY3Qoc29saWQubmFtZSwgZGF0YSk7CiAgICByZXR1cm4gdHJ1ZTsKICB9CgogIHNldEFjdGl2ZShhY3RpdmUpIHsKICAgIGNvbnN0IG5leHQgPSAhIWFjdGl2ZTsKICAgIGlmIChuZXh0ID09PSB0aGlzLl9hY3RpdmUpIHsKICAgICAgaWYgKG5leHQpIHsKICAgICAgICB0aGlzLl9hcHBseVJ1bnRpbWVUcmFuc2Zvcm1zKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fcmVzdG9yZUJhc2VMb2NhbFBvc2VzKCk7CiAgICAgIH0KICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5fYWN0aXZlID0gbmV4dDsKICAgIGlmICh0aGlzLl9hY3RpdmUpIHsKICAgICAgdGhpcy5faXNQbGF5aW5nID0gZmFsc2U7CiAgICAgIHRoaXMuX3N0b3BQaHlzaWNzTG9vcCgpOwogICAgICB0aGlzLl9kZXN0cm95UGh5c2ljc1dvcmxkKCk7CiAgICAgIHRoaXMuX2NhcHR1cmVCYXNlTG9jYWxQb3NlcygpOwogICAgICB0aGlzLl9jYXB0dXJlU291cmNlVmlzaWJpbGl0eSgpOwogICAgICB0aGlzLl9oeWRyYXRlUnVudGltZVN0YXRlRnJvbU1ldGFkYXRhKCk7CiAgICAgIHRoaXMuX3Jlc2V0TW90aW9uUnVudGltZSgpOwogICAgICB0aGlzLl9hcHBseVJ1bnRpbWVUcmFuc2Zvcm1zKCk7CiAgICAgIHRoaXMuX3NldFNvdXJjZVNvbGlkc1Zpc2libGUodHJ1ZSk7CiAgICAgIHZvaWQgdGhpcy5fcHJlcGFyZVZpc3VhbEFzc2V0cygpOwogICAgICB0aGlzLl9lbWl0KCk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX3N0b3BUcmFuc2Zvcm1TZXNzaW9uKCk7CiAgICB0aGlzLl9kZXN0cm95UGh5c2ljc1dvcmxkKCk7CiAgICB0aGlzLl9zdG9wUGh5c2ljc0xvb3AoKTsKICAgIHRoaXMuX2NsZWFyUHJveHlHcm91cHMoKTsKICAgIHRoaXMuX3NldFNvdXJjZVNvbGlkc1Zpc2libGUodHJ1ZSk7CiAgICB0aGlzLl9yZXN0b3JlQmFzZUxvY2FsUG9zZXMoKTsKICAgIHRoaXMuX3J1bnRpbWVTdGF0ZS5jbGVhcigpOwogICAgdGhpcy5fYmFzZUxvY2FsUG9zZS5jbGVhcigpOwogICAgdGhpcy5fc291cmNlVmlzaWJpbGl0eS5jbGVhcigpOwogICAgdGhpcy5fZGVjb21wb3NpdGlvbkNhY2hlLmNsZWFyKCk7CiAgICB0aGlzLl9tb3Rpb25TdGF0ZS5jbGVhcigpOwogICAgdGhpcy5fbW92ZWRTb2xpZElkcy5jbGVhcigpOwogICAgdGhpcy5faXNQbGF5aW5nID0gZmFsc2U7CiAgICB0aGlzLl9lbWl0KCk7CiAgfQoKICB0b2dnbGVTb2xpZFRyYW5zZm9ybShzb2xpZCkgewogICAgaWYgKCFzb2xpZCB8fCBzb2xpZC50eXBlICE9PSAnU09MSUQnKSByZXR1cm47CiAgICBpZiAoIXRoaXMuaXNTaW11bGF0aW9uV29ya2JlbmNoQWN0aXZlKCkpIHJldHVybjsKICAgIGNvbnN0IHNlc3Npb24gPSB0aGlzLl90cmFuc2Zvcm1TZXNzaW9uOwogICAgaWYgKHNlc3Npb24gJiYgc2Vzc2lvbi5zb2xpZCA9PT0gc29saWQpIHsKICAgICAgY29uc3QgY3VycmVudE1vZGUgPSAodHlwZW9mIHNlc3Npb24uY29udHJvbHM/LmdldE1vZGUgPT09ICdmdW5jdGlvbicpCiAgICAgICAgPyBzZXNzaW9uLmNvbnRyb2xzLmdldE1vZGUoKQogICAgICAgIDogKHNlc3Npb24uY29udHJvbHM/Lm1vZGUgfHwgc2Vzc2lvbi5tb2RlIHx8ICd0cmFuc2xhdGUnKTsKICAgICAgaWYgKGN1cnJlbnRNb2RlID09PSAndHJhbnNsYXRlJykgewogICAgICAgIHRyeSB7IHNlc3Npb24uY29udHJvbHM/LnNldE1vZGUoJ3JvdGF0ZScpOyB9IGNhdGNoIHsgc2Vzc2lvbi5jb250cm9scy5tb2RlID0gJ3JvdGF0ZSc7IH0KICAgICAgICBzZXNzaW9uLm1vZGUgPSAncm90YXRlJzsKICAgICAgICB0cnkgeyBzZXNzaW9uLmdsb2JhbFN0YXRlPy51cGRhdGVGb3JDYW1lcmE/LigpOyB9IGNhdGNoIHt9CiAgICAgICAgdHJ5IHsgdGhpcy52aWV3ZXI/LnJlbmRlcj8uKCk7IH0gY2F0Y2gge30KICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhpcy5fc3RvcFRyYW5zZm9ybVNlc3Npb24oKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5fc3RhcnRUcmFuc2Zvcm1TZXNzaW9uKHNvbGlkKTsKICB9CgogIF9jYXB0dXJlQmFzZUxvY2FsUG9zZXMoKSB7CiAgICBmb3IgKGNvbnN0IHNvbGlkIG9mIHRoaXMuX2xpc3RTY2VuZVNvbGlkcygpKSB7CiAgICAgIGlmICghdGhpcy5fYmFzZUxvY2FsUG9zZS5oYXMoc29saWQudXVpZCkpIHsKICAgICAgICB0aGlzLl9iYXNlTG9jYWxQb3NlLnNldChzb2xpZC51dWlkLCBjb3B5TG9jYWxQb3NlKHNvbGlkKSk7CiAgICAgIH0KICAgIH0KICB9CgogIF9jYXB0dXJlU291cmNlVmlzaWJpbGl0eSgpIHsKICAgIGZvciAoY29uc3Qgc29saWQgb2YgdGhpcy5fbGlzdFNjZW5lU29saWRzKCkpIHsKICAgICAgaWYgKCF0aGlzLl9zb3VyY2VWaXNpYmlsaXR5Lmhhcyhzb2xpZC51dWlkKSkgewogICAgICAgIHRoaXMuX3NvdXJjZVZpc2liaWxpdHkuc2V0KHNvbGlkLnV1aWQsIHNvbGlkLnZpc2libGUgIT09IGZhbHNlKTsKICAgICAgfQogICAgfQogIH0KCiAgX2h5ZHJhdGVSdW50aW1lU3RhdGVGcm9tTWV0YWRhdGEoKSB7CiAgICBmb3IgKGNvbnN0IHNvbGlkIG9mIHRoaXMuX2xpc3RTY2VuZVNvbGlkcygpKSB7CiAgICAgIHRoaXMuX3J1bnRpbWVTdGF0ZS5zZXQoc29saWQudXVpZCwgbm9ybWFsaXplVHJhbnNmb3JtKHRoaXMuZ2V0U3RvcmVkVHJhbnNmb3JtKHNvbGlkKSkpOwogICAgfQogIH0KCiAgX3Jlc3RvcmVCYXNlTG9jYWxQb3NlcygpIHsKICAgIGZvciAoY29uc3Qgc29saWQgb2YgdGhpcy5fbGlzdFNjZW5lU29saWRzKCkpIHsKICAgICAgY29uc3QgYmFzZSA9IHRoaXMuX2Jhc2VMb2NhbFBvc2UuZ2V0KHNvbGlkLnV1aWQpOwogICAgICBpZiAoIWJhc2UpIGNvbnRpbnVlOwogICAgICBzb2xpZC5wb3NpdGlvbi5jb3B5KGJhc2UucG9zaXRpb24pOwogICAgICBzb2xpZC5xdWF0ZXJuaW9uLmNvcHkoYmFzZS5xdWF0ZXJuaW9uKTsKICAgICAgc29saWQuc2NhbGUuY29weShiYXNlLnNjYWxlKTsKICAgICAgc29saWQudXBkYXRlTWF0cml4V29ybGQ/Lih0cnVlKTsKICAgIH0KICAgIHRyeSB7IHRoaXMudmlld2VyPy5yZW5kZXI/LigpOyB9IGNhdGNoIHt9CiAgfQoKICBfYXBwbHlSdW50aW1lVHJhbnNmb3JtcygpIHsKICAgIHRoaXMuX2NhcHR1cmVCYXNlTG9jYWxQb3NlcygpOwogICAgZm9yIChjb25zdCBzb2xpZCBvZiB0aGlzLl9saXN0U2NlbmVTb2xpZHMoKSkgewogICAgICB0aGlzLl9hcHBseVJ1bnRpbWVUcmFuc2Zvcm1Ub1NvbGlkKHNvbGlkKTsKICAgIH0KICAgIHRyeSB7IHRoaXMudmlld2VyPy5yZW5kZXI/LigpOyB9IGNhdGNoIHt9CiAgfQoKICBfYXBwbHlSdW50aW1lVHJhbnNmb3JtVG9Tb2xpZChzb2xpZCkgewogICAgY29uc3QgYmFzZSA9IHRoaXMuX2Jhc2VMb2NhbFBvc2UuZ2V0KHNvbGlkLnV1aWQpOwogICAgaWYgKCFiYXNlKSByZXR1cm47CiAgICBjb25zdCBydW50aW1lID0gbm9ybWFsaXplVHJhbnNmb3JtKHRoaXMuX3J1bnRpbWVTdGF0ZS5nZXQoc29saWQudXVpZCkpOwogICAgY29uc3Qgb2Zmc2V0UXVhdGVybmlvbiA9IG5ldyBUSFJFRS5RdWF0ZXJuaW9uKCkuc2V0RnJvbUV1bGVyKAogICAgICBuZXcgVEhSRUUuRXVsZXIoLi4ucnVudGltZS5yb3RhdGlvbkV1bGVyLCAnWFlaJyksCiAgICApOwogICAgY29uc3QgbmV4dE1hdHJpeCA9IGJ1aWxkTG9jYWxNYXRyaXgoYmFzZSkubXVsdGlwbHkoCiAgICAgIG5ldyBUSFJFRS5NYXRyaXg0KCkuY29tcG9zZSgKICAgICAgICBuZXcgVEhSRUUuVmVjdG9yMyguLi5ydW50aW1lLnBvc2l0aW9uKSwKICAgICAgICBvZmZzZXRRdWF0ZXJuaW9uLAogICAgICAgIG5ldyBUSFJFRS5WZWN0b3IzKDEsIDEsIDEpLAogICAgICApLAogICAgKTsKICAgIG5leHRNYXRyaXguZGVjb21wb3NlKHNvbGlkLnBvc2l0aW9uLCBzb2xpZC5xdWF0ZXJuaW9uLCBzb2xpZC5zY2FsZSk7CiAgICBzb2xpZC51cGRhdGVNYXRyaXhXb3JsZD8uKHRydWUpOwogICAgdGhpcy5fc3luY1Byb3h5R3JvdXBUcmFuc2Zvcm0oc29saWQpOwogIH0KCiAgX3VwZGF0ZVJ1bnRpbWVUcmFuc2Zvcm1Gcm9tU29saWQoc29saWQsIHsgcGVyc2lzdCA9IGZhbHNlIH0gPSB7fSkgewogICAgY29uc3QgYmFzZSA9IHRoaXMuX2Jhc2VMb2NhbFBvc2UuZ2V0KHNvbGlkLnV1aWQpOwogICAgaWYgKCFiYXNlKSByZXR1cm47CiAgICBjb25zdCBvZmZzZXQgPSBub3JtYWxpemVUcmFuc2Zvcm0ocG9zZVRvT2Zmc2V0KGJhc2UsIHNvbGlkKSk7CiAgICB0aGlzLl9ydW50aW1lU3RhdGUuc2V0KHNvbGlkLnV1aWQsIG9mZnNldCk7CiAgICBpZiAocGVyc2lzdCkgewogICAgICB0aGlzLnNldFN0b3JlZFRyYW5zZm9ybShzb2xpZCwgb2Zmc2V0KTsKICAgICAgdGhpcy52aWV3ZXI/LnBhcnRIaXN0b3J5Py5xdWV1ZUhpc3RvcnlTbmFwc2hvdD8uKHsgZGVib3VuY2VNczogMCwgcmVhc29uOiAnc2ltdWxhdGlvbi10cmFuc2Zvcm0nIH0pOwogICAgfQogICAgdGhpcy5fc3luY1Byb3h5R3JvdXBUcmFuc2Zvcm0oc29saWQpOwogIH0KCiAgYXN5bmMgX3ByZXBhcmVTaW11bGF0aW9uQXNzZXRzKCkgewogICAgaWYgKCF0aGlzLl9hY3RpdmUpIHJldHVybjsKICAgIHRyeSB7CiAgICAgIGF3YWl0IFByb21pc2UuYWxsKHRoaXMuX2xpc3RTY2VuZVNvbGlkcygpLm1hcCgoc29saWQpID0+IHRoaXMuX2Vuc3VyZURlY29tcG9zaXRpb24oc29saWQpKSk7CiAgICAgIHRoaXMuX2J1aWxkUHJveHlHcm91cHMoKTsKICAgICAgYXdhaXQgdGhpcy5fcmVidWlsZFBoeXNpY3NXb3JsZCgpOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgY29uc29sZS53YXJuKCdbU2ltdWxhdGlvbldvcmtiZW5jaF0gRmFpbGVkIHRvIHByZXBhcmUgc2ltdWxhdGlvbiBhc3NldHM6JywgZXJyb3IpOwogICAgfQogIH0KCiAgYXN5bmMgX3ByZXBhcmVWaXN1YWxBc3NldHMoKSB7CiAgICBpZiAoIXRoaXMuX2FjdGl2ZSkgcmV0dXJuOwogICAgdHJ5IHsKICAgICAgYXdhaXQgUHJvbWlzZS5hbGwodGhpcy5fbGlzdFNjZW5lU29saWRzKCkubWFwKChzb2xpZCkgPT4gdGhpcy5fZW5zdXJlRGVjb21wb3NpdGlvbihzb2xpZCkpKTsKICAgICAgdGhpcy5fYnVpbGRQcm94eUdyb3VwcygpOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgY29uc29sZS53YXJuKCdbU2ltdWxhdGlvbldvcmtiZW5jaF0gRmFpbGVkIHRvIHByZXBhcmUgc2ltdWxhdGlvbiB2aXN1YWxzOicsIGVycm9yKTsKICAgIH0KICB9CgogIGFzeW5jIF9sb2FkUmFwaWVyKCkgewogICAgaWYgKHRoaXMuX3JhcGllcikgcmV0dXJuIHRoaXMuX3JhcGllcjsKICAgIGlmICghdGhpcy5fcmFwaWVyTG9hZFByb21pc2UpIHsKICAgICAgdGhpcy5fcmFwaWVyTG9hZFByb21pc2UgPSBpbXBvcnQoJ0BkaW1mb3JnZS9yYXBpZXIzZC9yYXBpZXIuanMnKQogICAgICAgIC50aGVuKChtb2R1bGUpID0+IG1vZHVsZT8uZGVmYXVsdCB8fCBtb2R1bGUpCiAgICAgICAgLnRoZW4oKHJhcGllcikgPT4gewogICAgICAgICAgdGhpcy5fcmFwaWVyID0gcmFwaWVyOwogICAgICAgICAgcmV0dXJuIHJhcGllcjsKICAgICAgICB9KQogICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHsKICAgICAgICAgIHRoaXMuX3JhcGllckxvYWRQcm9taXNlID0gbnVsbDsKICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIHRoaXMuX3JhcGllckxvYWRQcm9taXNlOwogIH0KCiAgYXN5bmMgX2xvYWRWaGFjZCgpIHsKICAgIGlmICh0aGlzLl92aGFjZCkgcmV0dXJuIHRoaXMuX3ZoYWNkOwogICAgaWYgKCF0aGlzLl92aGFjZExvYWRQcm9taXNlKSB7CiAgICAgIHRoaXMuX3ZoYWNkTG9hZFByb21pc2UgPSBpbXBvcnQoJ3ZoYWNkLWpzL2xpYi92aGFjZC5qcycpCiAgICAgICAgLnRoZW4oKG1vZHVsZSkgPT4gbW9kdWxlPy5Db252ZXhNZXNoRGVjb21wb3NpdGlvbj8uY3JlYXRlPy4oKSkKICAgICAgICAudGhlbigoaW5zdGFuY2UpID0+IHsKICAgICAgICAgIHRoaXMuX3ZoYWNkID0gaW5zdGFuY2UgfHwgbnVsbDsKICAgICAgICAgIHJldHVybiB0aGlzLl92aGFjZDsKICAgICAgICB9KQogICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHsKICAgICAgICAgIHRoaXMuX3ZoYWNkTG9hZFByb21pc2UgPSBudWxsOwogICAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgICAgfSk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5fdmhhY2RMb2FkUHJvbWlzZTsKICB9CgogIGFzeW5jIF9lbnN1cmVEZWNvbXBvc2l0aW9uKHNvbGlkKSB7CiAgICBpZiAoIXNvbGlkPy51dWlkKSByZXR1cm4gW107CiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLl9kZWNvbXBvc2l0aW9uQ2FjaGUuZ2V0KHNvbGlkLnV1aWQpOwogICAgaWYgKGNhY2hlZCkgcmV0dXJuIGNhY2hlZC5odWxsczsKICAgIGNvbnN0IHJhd01lc2ggPSB0aGlzLl9leHRyYWN0U29saWRNZXNoKHNvbGlkKTsKICAgIGlmICghcmF3TWVzaCkgewogICAgICB0aGlzLl9kZWNvbXBvc2l0aW9uQ2FjaGUuc2V0KHNvbGlkLnV1aWQsIHsgaHVsbHM6IFtdIH0pOwogICAgICByZXR1cm4gW107CiAgICB9CiAgICBsZXQgaHVsbHMgPSBbXTsKICAgIHRyeSB7CiAgICAgIGNvbnN0IHZoYWNkID0gYXdhaXQgdGhpcy5fbG9hZFZoYWNkKCk7CiAgICAgIGlmICh2aGFjZD8uY29tcHV0ZUNvbnZleEh1bGxzKSB7CiAgICAgICAgaHVsbHMgPSB2aGFjZC5jb21wdXRlQ29udmV4SHVsbHMocmF3TWVzaCwgVkhBQ0RfT1BUSU9OUykgfHwgW107CiAgICAgIH0KICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIGNvbnNvbGUud2FybignW1NpbXVsYXRpb25Xb3JrYmVuY2hdIEZhaWxlZCB0byBkZWNvbXBvc2UgbWVzaCB3aXRoIHZoYWNkLWpzOicsIGVycm9yKTsKICAgIH0KICAgIGlmICghQXJyYXkuaXNBcnJheShodWxscykgfHwgaHVsbHMubGVuZ3RoID09PSAwKSB7CiAgICAgIGh1bGxzID0gW3Jhd01lc2hdOwogICAgfQogICAgdGhpcy5fZGVjb21wb3NpdGlvbkNhY2hlLnNldChzb2xpZC51dWlkLCB7IGh1bGxzIH0pOwogICAgcmV0dXJuIGh1bGxzOwogIH0KCiAgX2V4dHJhY3RTb2xpZE1lc2goc29saWQpIHsKICAgIGxldCBtZXNoID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIG1lc2ggPSBzb2xpZC5nZXRNZXNoPy4oKTsKICAgICAgcmV0dXJuIG5vcm1hbGl6ZU1lc2hBcnJheXMobWVzaCk7CiAgICB9IGNhdGNoIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9IGZpbmFsbHkgewogICAgICB0cnkgeyBpZiAobWVzaCAmJiB0eXBlb2YgbWVzaC5kZWxldGUgPT09ICdmdW5jdGlvbicpIG1lc2guZGVsZXRlKCk7IH0gY2F0Y2gge30KICAgIH0KICB9CgogIF9idWlsZFByb3h5R3JvdXBzKCkgewogICAgdGhpcy5fY2xlYXJQcm94eUdyb3VwcygpOwogICAgZm9yIChjb25zdCBzb2xpZCBvZiB0aGlzLl9saXN0U2NlbmVTb2xpZHMoKSkgewogICAgICBjb25zdCByZWNvcmQgPSB0aGlzLl9kZWNvbXBvc2l0aW9uQ2FjaGUuZ2V0KHNvbGlkLnV1aWQpOwogICAgICBjb25zdCBodWxscyA9IEFycmF5LmlzQXJyYXkocmVjb3JkPy5odWxscykgPyByZWNvcmQuaHVsbHMgOiBbXTsKICAgICAgY29uc3QgZ3JvdXAgPSB0aGlzLl9jcmVhdGVQcm94eUdyb3VwKHNvbGlkLCBodWxscyk7CiAgICAgIGlmICghZ3JvdXApIGNvbnRpbnVlOwogICAgICB0aGlzLl9wcm94eUdyb3Vwcy5zZXQoc29saWQudXVpZCwgZ3JvdXApOwogICAgICB0aGlzLl9zeW5jUHJveHlHcm91cFRyYW5zZm9ybShzb2xpZCk7CiAgICAgIHRyeSB7IHRoaXMudmlld2VyPy5yZW5kZXI/LigpOyB9IGNhdGNoIHt9CiAgICB9CiAgfQoKICBfY3JlYXRlUHJveHlHcm91cChzb2xpZCwgaHVsbHMpIHsKICAgIGNvbnN0IHBhcmVudCA9IHNvbGlkLnBhcmVudCB8fCB0aGlzLnZpZXdlcj8uc2NlbmUgfHwgbnVsbDsKICAgIGlmICghcGFyZW50Py5hZGQgfHwgIUFycmF5LmlzQXJyYXkoaHVsbHMpIHx8IGh1bGxzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7CiAgICBjb25zdCBncm91cCA9IG5ldyBUSFJFRS5Hcm91cCgpOwogICAgZ3JvdXAubmFtZSA9IGAke1NJTV9QUk9YWV9QUkVGSVh9OiR7c29saWQubmFtZSB8fCBzb2xpZC51dWlkIHx8ICcnfWA7CiAgICBncm91cC51c2VyRGF0YS5leGNsdWRlRnJvbUZpdCA9IGZhbHNlOwogICAgZ3JvdXAudXNlckRhdGEuc2ltdWxhdGlvblByb3h5ID0gdHJ1ZTsKICAgIGdyb3VwLnZpc2libGUgPSBmYWxzZTsKICAgIGNvbnN0IG1ldGFkYXRhQ29sb3IgPSB0aGlzLnZpZXdlcj8ucGFydEhpc3Rvcnk/Lm1ldGFkYXRhTWFuYWdlcj8uZ2V0TWV0YWRhdGE/Lihzb2xpZC5uYW1lIHx8ICcnKT8uY29sb3IgfHwgbnVsbDsKICAgIGh1bGxzLmZvckVhY2goKGh1bGwsIGluZGV4KSA9PiB7CiAgICAgIGNvbnN0IGdlb21ldHJ5ID0gbmV3IFRIUkVFLkJ1ZmZlckdlb21ldHJ5KCk7CiAgICAgIGdlb21ldHJ5LnNldEF0dHJpYnV0ZSgncG9zaXRpb24nLCBuZXcgVEhSRUUuRmxvYXQzMkJ1ZmZlckF0dHJpYnV0ZShBcnJheS5mcm9tKGh1bGwucG9zaXRpb25zIHx8IFtdKSwgMykpOwogICAgICBnZW9tZXRyeS5zZXRJbmRleChBcnJheS5mcm9tKGh1bGwuaW5kaWNlcyB8fCBbXSkpOwogICAgICBnZW9tZXRyeS5jb21wdXRlVmVydGV4Tm9ybWFscygpOwogICAgICBjb25zdCBtZXNoID0gbmV3IFRIUkVFLk1lc2goZ2VvbWV0cnksIGJ1aWxkUHJveHlNYXRlcmlhbChtZXRhZGF0YUNvbG9yLCBpbmRleCwgaHVsbHMubGVuZ3RoKSk7CiAgICAgIG1lc2gudXNlckRhdGEuZXhjbHVkZUZyb21GaXQgPSBmYWxzZTsKICAgICAgbWVzaC51c2VyRGF0YS5zaW11bGF0aW9uUHJveHkgPSB0cnVlOwogICAgICBtZXNoLnVzZXJEYXRhLnNvdXJjZVNvbGlkVXVpZCA9IHNvbGlkLnV1aWQ7CiAgICAgIGdyb3VwLmFkZChtZXNoKTsKCiAgICAgIGNvbnN0IGVkZ2VzID0gbmV3IFRIUkVFLkxpbmVTZWdtZW50cygKICAgICAgICBuZXcgVEhSRUUuRWRnZXNHZW9tZXRyeShnZW9tZXRyeSwgMjApLAogICAgICAgIG5ldyBUSFJFRS5MaW5lQmFzaWNNYXRlcmlhbCh7IGNvbG9yOiAweDIyZDNlZSwgdHJhbnNwYXJlbnQ6IHRydWUsIG9wYWNpdHk6IDAuOSB9KSwKICAgICAgKTsKICAgICAgZWRnZXMudXNlckRhdGEuZXhjbHVkZUZyb21GaXQgPSBmYWxzZTsKICAgICAgZWRnZXMudXNlckRhdGEuc2ltdWxhdGlvblByb3h5ID0gdHJ1ZTsKICAgICAgZ3JvdXAuYWRkKGVkZ2VzKTsKICAgIH0pOwogICAgcGFyZW50LmFkZChncm91cCk7CiAgICByZXR1cm4gZ3JvdXA7CiAgfQoKICBfc3luY1Byb3h5R3JvdXBUcmFuc2Zvcm0oc29saWQpIHsKICAgIGNvbnN0IGdyb3VwID0gdGhpcy5fcHJveHlHcm91cHMuZ2V0KHNvbGlkLnV1aWQpOwogICAgaWYgKCFncm91cCkgcmV0dXJuOwogICAgZ3JvdXAucG9zaXRpb24uY29weShzb2xpZC5wb3NpdGlvbik7CiAgICBncm91cC5xdWF0ZXJuaW9uLmNvcHkoc29saWQucXVhdGVybmlvbik7CiAgICBncm91cC5zY2FsZS5jb3B5KHNvbGlkLnNjYWxlKTsKICAgIGdyb3VwLnZpc2libGUgPSBmYWxzZTsKICAgIGdyb3VwLnVwZGF0ZU1hdHJpeFdvcmxkPy4odHJ1ZSk7CiAgfQoKICBfY2xlYXJQcm94eUdyb3VwcygpIHsKICAgIGZvciAoY29uc3QgZ3JvdXAgb2YgdGhpcy5fcHJveHlHcm91cHMudmFsdWVzKCkpIHsKICAgICAgdHJ5IHsgZ3JvdXAucGFyZW50Py5yZW1vdmU/Lihncm91cCk7IH0gY2F0Y2gge30KICAgICAgZGlzcG9zZUhpZXJhcmNoeShncm91cCk7CiAgICB9CiAgICB0aGlzLl9wcm94eUdyb3Vwcy5jbGVhcigpOwogIH0KCiAgX3NldFNvdXJjZVNvbGlkc1Zpc2libGUodmlzaWJsZSkgewogICAgZm9yIChjb25zdCBzb2xpZCBvZiB0aGlzLl9saXN0U2NlbmVTb2xpZHMoKSkgewogICAgICBpZiAodmlzaWJsZSkgewogICAgICAgIHNvbGlkLnZpc2libGUgPSB0aGlzLl9zb3VyY2VWaXNpYmlsaXR5LmdldChzb2xpZC51dWlkKSAhPT0gZmFsc2U7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgc29saWQudmlzaWJsZSA9IGZhbHNlOwogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IGdyb3VwIG9mIHRoaXMuX3Byb3h5R3JvdXBzLnZhbHVlcygpKSB7CiAgICAgIGdyb3VwLnZpc2libGUgPSBmYWxzZTsKICAgIH0KICAgIHRyeSB7IHRoaXMudmlld2VyPy5yZW5kZXI/LigpOyB9IGNhdGNoIHt9CiAgfQoKICBhc3luYyBfcmVidWlsZFBoeXNpY3NXb3JsZCgpIHsKICAgIGlmICghdGhpcy5fYWN0aXZlKSByZXR1cm47CiAgICBjb25zdCBbcmFwaWVyXSA9IGF3YWl0IFByb21pc2UuYWxsKFsKICAgICAgdGhpcy5fbG9hZFJhcGllcigpLAogICAgICBQcm9taXNlLmFsbCh0aGlzLl9saXN0U2NlbmVTb2xpZHMoKS5tYXAoKHNvbGlkKSA9PiB0aGlzLl9lbnN1cmVEZWNvbXBvc2l0aW9uKHNvbGlkKSkpLAogICAgXSk7CiAgICBpZiAoIXRoaXMuX2FjdGl2ZSB8fCAhcmFwaWVyKSByZXR1cm47CiAgICB0aGlzLl9kZXN0cm95UGh5c2ljc1dvcmxkKCk7CiAgICB0aGlzLl9ib2R5U3RhdGUuY2xlYXIoKTsKICAgIGNvbnN0IHdvcmxkID0gbmV3IHJhcGllci5Xb3JsZCh7IHg6IDAsIHk6IC05LjgxLCB6OiAwIH0pOwogICAgd29ybGQubWF4Q2NkU3Vic3RlcHMgPSAyOwogICAgdGhpcy5fcGh5c2ljc1dvcmxkID0gd29ybGQ7CiAgICBjb25zdCBzZWxlY3RlZFNvbGlkID0gdGhpcy5fdHJhbnNmb3JtU2Vzc2lvbj8uc29saWQgfHwgbnVsbDsKICAgIGZvciAoY29uc3Qgc29saWQgb2YgdGhpcy5fbGlzdFNjZW5lU29saWRzKCkpIHsKICAgICAgY29uc3QgYm9keURlc2MgPSAoc2VsZWN0ZWRTb2xpZCAmJiBzb2xpZCA9PT0gc2VsZWN0ZWRTb2xpZCkKICAgICAgICA/IHJhcGllci5SaWdpZEJvZHlEZXNjLmtpbmVtYXRpY1Bvc2l0aW9uQmFzZWQoKQogICAgICAgIDogKHRoaXMuX2lzU29saWRNb3Rpb25Ecml2ZW4oc29saWQpCiAgICAgICAgICA/IHJhcGllci5SaWdpZEJvZHlEZXNjLmtpbmVtYXRpY1Bvc2l0aW9uQmFzZWQoKQogICAgICAgICAgOiAodGhpcy5nZXRTb2xpZEZpeGVkKHNvbGlkKSA/IHJhcGllci5SaWdpZEJvZHlEZXNjLmZpeGVkKCkgOiByYXBpZXIuUmlnaWRCb2R5RGVzYy5keW5hbWljKCkpKTsKICAgICAgY29uc3QgcG9zaXRpb24gPSBzb2xpZC5nZXRXb3JsZFBvc2l0aW9uKG5ldyBUSFJFRS5WZWN0b3IzKCkpOwogICAgICBjb25zdCBxdWF0ZXJuaW9uID0gc29saWQuZ2V0V29ybGRRdWF0ZXJuaW9uKG5ldyBUSFJFRS5RdWF0ZXJuaW9uKCkpOwogICAgICBib2R5RGVzYy5zZXRUcmFuc2xhdGlvbihwb3NpdGlvbi54LCBwb3NpdGlvbi55LCBwb3NpdGlvbi56KTsKICAgICAgYm9keURlc2Muc2V0Um90YXRpb24oeyB4OiBxdWF0ZXJuaW9uLngsIHk6IHF1YXRlcm5pb24ueSwgejogcXVhdGVybmlvbi56LCB3OiBxdWF0ZXJuaW9uLncgfSk7CiAgICAgIGJvZHlEZXNjLnNldExpbmVhckRhbXBpbmcoMi41KTsKICAgICAgYm9keURlc2Muc2V0QW5ndWxhckRhbXBpbmcoMi41KTsKICAgICAgYm9keURlc2Muc2V0Q2NkRW5hYmxlZCh0cnVlKTsKICAgICAgY29uc3QgYm9keSA9IHdvcmxkLmNyZWF0ZVJpZ2lkQm9keShib2R5RGVzYyk7CiAgICAgIGNvbnN0IGh1bGxzID0gdGhpcy5fZGVjb21wb3NpdGlvbkNhY2hlLmdldChzb2xpZC51dWlkKT8uaHVsbHMgfHwgW107CiAgICAgIGZvciAoY29uc3QgaHVsbCBvZiBodWxscykgewogICAgICAgIGNvbnN0IGNvbGxpZGVyID0gdGhpcy5fY3JlYXRlQ29sbGlkZXJGb3JIdWxsKHJhcGllciwgaHVsbCk7CiAgICAgICAgaWYgKCFjb2xsaWRlcikgY29udGludWU7CiAgICAgICAgY29sbGlkZXIuc2V0UmVzdGl0dXRpb24oMC4wNSk7CiAgICAgICAgY29sbGlkZXIuc2V0RnJpY3Rpb24oMC45KTsKICAgICAgICB3b3JsZC5jcmVhdGVDb2xsaWRlcihjb2xsaWRlciwgYm9keSk7CiAgICAgIH0KICAgICAgdGhpcy5fYm9keVN0YXRlLnNldChzb2xpZC51dWlkLCB7CiAgICAgICAgc29saWQsCiAgICAgICAgYm9keSwKICAgICAgICBwcm94eUdyb3VwOiB0aGlzLl9wcm94eUdyb3Vwcy5nZXQoc29saWQudXVpZCkgfHwgbnVsbCwKICAgICAgfSk7CiAgICB9CiAgfQoKICBfZGVzdHJveVBoeXNpY3NXb3JsZCgpIHsKICAgIHRyeSB7IHRoaXMuX3BoeXNpY3NXb3JsZD8uZnJlZT8uKCk7IH0gY2F0Y2gge30KICAgIHRoaXMuX3BoeXNpY3NXb3JsZCA9IG51bGw7CiAgICB0aGlzLl9ib2R5U3RhdGUuY2xlYXIoKTsKICB9CgogIF9jcmVhdGVDb2xsaWRlckZvckh1bGwocmFwaWVyLCBodWxsKSB7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBodWxsPy5wb3NpdGlvbnMgPyBuZXcgRmxvYXQzMkFycmF5KGh1bGwucG9zaXRpb25zKSA6IG51bGw7CiAgICBjb25zdCBpbmRpY2VzID0gaHVsbD8uaW5kaWNlcyA/IG5ldyBVaW50MzJBcnJheShodWxsLmluZGljZXMpIDogbnVsbDsKICAgIGlmICghcG9zaXRpb25zIHx8IHBvc2l0aW9ucy5sZW5ndGggPCA5IHx8ICFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoIDwgMykgcmV0dXJuIG51bGw7CiAgICBjb25zdCBjb2xsaWRlciA9IHJhcGllci5Db2xsaWRlckRlc2MuY29udmV4TWVzaChwb3NpdGlvbnMsIGluZGljZXMpOwogICAgaWYgKGNvbGxpZGVyKSByZXR1cm4gY29sbGlkZXI7CiAgICByZXR1cm4gcmFwaWVyLkNvbGxpZGVyRGVzYy5jb252ZXhIdWxsKHBvc2l0aW9ucyk7CiAgfQoKICBfZW5zdXJlUGh5c2ljc0xvb3AoKSB7CiAgICBpZiAodGhpcy5fcmFmKSByZXR1cm47CiAgICB0aGlzLl9sYXN0U3RlcFRpbWUgPSAwOwogICAgY29uc3Qgc3RlcCA9ICh0cykgPT4gewogICAgICB0aGlzLl9yYWYgPSAwOwogICAgICBpZiAoIXRoaXMuX2FjdGl2ZSkgcmV0dXJuOwogICAgICB0aGlzLl9zdGVwUGh5c2ljcyh0cyk7CiAgICAgIHRoaXMuX3JhZiA9IHJlcXVlc3RBbmltYXRpb25GcmFtZShzdGVwKTsKICAgIH07CiAgICB0aGlzLl9yYWYgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoc3RlcCk7CiAgfQoKICBfc3RvcFBoeXNpY3NMb29wKCkgewogICAgaWYgKHRoaXMuX3JhZikgewogICAgICBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLl9yYWYpOwogICAgICB0aGlzLl9yYWYgPSAwOwogICAgfQogICAgdGhpcy5fbGFzdFN0ZXBUaW1lID0gMDsKICB9CgogIF9zdGVwUGh5c2ljcyh0aW1lc3RhbXApIHsKICAgIGNvbnN0IHdvcmxkID0gdGhpcy5fcGh5c2ljc1dvcmxkOwogICAgaWYgKCF3b3JsZCkgcmV0dXJuOwogICAgaWYgKCF0aGlzLl9pc1BsYXlpbmcpIHsKICAgICAgdGhpcy5fbGFzdFN0ZXBUaW1lID0gdGltZXN0YW1wOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBkdCA9IHRoaXMuX2xhc3RTdGVwVGltZSA+IDAKICAgICAgPyBNYXRoLm1pbigxIC8gMjAsIE1hdGgubWF4KDEgLyAyNDAsICh0aW1lc3RhbXAgLSB0aGlzLl9sYXN0U3RlcFRpbWUpIC8gMTAwMCkpCiAgICAgIDogMSAvIDYwOwogICAgdGhpcy5fbGFzdFN0ZXBUaW1lID0gdGltZXN0YW1wOwogICAgd29ybGQudGltZXN0ZXAgPSBkdDsKCiAgICBjb25zdCBzZWxlY3RlZFNvbGlkID0gdGhpcy5fdHJhbnNmb3JtU2Vzc2lvbj8uc29saWQgfHwgbnVsbDsKICAgIGxldCBjaGFuZ2VkID0gZmFsc2U7CiAgICBpZiAodGhpcy5faXNQbGF5aW5nKSB7CiAgICAgIGNoYW5nZWQgPSB0aGlzLl9hcHBseU1vdGlvblN0ZXAoZHQpIHx8IGNoYW5nZWQ7CiAgICB9CiAgICBpZiAoc2VsZWN0ZWRTb2xpZCkgewogICAgICBjb25zdCBib2R5U3RhdGUgPSB0aGlzLl9ib2R5U3RhdGUuZ2V0KHNlbGVjdGVkU29saWQudXVpZCk7CiAgICAgIGlmIChib2R5U3RhdGU/LmJvZHkpIHsKICAgICAgICBjb25zdCB3b3JsZFBvc2l0aW9uID0gc2VsZWN0ZWRTb2xpZC5nZXRXb3JsZFBvc2l0aW9uKG5ldyBUSFJFRS5WZWN0b3IzKCkpOwogICAgICAgIGNvbnN0IHdvcmxkUXVhdGVybmlvbiA9IHNlbGVjdGVkU29saWQuZ2V0V29ybGRRdWF0ZXJuaW9uKG5ldyBUSFJFRS5RdWF0ZXJuaW9uKCkpOwogICAgICAgIGJvZHlTdGF0ZS5ib2R5LnNldE5leHRLaW5lbWF0aWNUcmFuc2xhdGlvbih3b3JsZFBvc2l0aW9uKTsKICAgICAgICBib2R5U3RhdGUuYm9keS5zZXROZXh0S2luZW1hdGljUm90YXRpb24od29ybGRRdWF0ZXJuaW9uKTsKICAgICAgfQogICAgfQogICAgaWYgKHRoaXMuX2lzUGxheWluZykgewogICAgICBmb3IgKGNvbnN0IHNvbGlkIG9mIHRoaXMuX2xpc3RTY2VuZVNvbGlkcygpKSB7CiAgICAgICAgaWYgKCF0aGlzLl9pc1NvbGlkTW90aW9uRHJpdmVuKHNvbGlkKSkgY29udGludWU7CiAgICAgICAgY29uc3QgYm9keVN0YXRlID0gdGhpcy5fYm9keVN0YXRlLmdldChzb2xpZC51dWlkKTsKICAgICAgICBpZiAoIWJvZHlTdGF0ZT8uYm9keSkgY29udGludWU7CiAgICAgICAgY29uc3Qgd29ybGRQb3NpdGlvbiA9IHNvbGlkLmdldFdvcmxkUG9zaXRpb24obmV3IFRIUkVFLlZlY3RvcjMoKSk7CiAgICAgICAgY29uc3Qgd29ybGRRdWF0ZXJuaW9uID0gc29saWQuZ2V0V29ybGRRdWF0ZXJuaW9uKG5ldyBUSFJFRS5RdWF0ZXJuaW9uKCkpOwogICAgICAgIGJvZHlTdGF0ZS5ib2R5LnNldE5leHRLaW5lbWF0aWNUcmFuc2xhdGlvbih3b3JsZFBvc2l0aW9uKTsKICAgICAgICBib2R5U3RhdGUuYm9keS5zZXROZXh0S2luZW1hdGljUm90YXRpb24od29ybGRRdWF0ZXJuaW9uKTsKICAgICAgfQogICAgfQoKICAgIHdvcmxkLnN0ZXAoKTsKICAgIGZvciAoY29uc3QgYm9keVN0YXRlIG9mIHRoaXMuX2JvZHlTdGF0ZS52YWx1ZXMoKSkgewogICAgICBjb25zdCB7IHNvbGlkLCBib2R5IH0gPSBib2R5U3RhdGU7CiAgICAgIGlmICghc29saWQgfHwgIWJvZHkpIGNvbnRpbnVlOwogICAgICBpZiAoc2VsZWN0ZWRTb2xpZCAmJiBzb2xpZCA9PT0gc2VsZWN0ZWRTb2xpZCkgewogICAgICAgIHRoaXMuX3N5bmNQcm94eUdyb3VwVHJhbnNmb3JtKHNvbGlkKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAodGhpcy5faXNTb2xpZE1vdGlvbkRyaXZlbihzb2xpZCkpIHsKICAgICAgICB0aGlzLl9zeW5jUHJveHlHcm91cFRyYW5zZm9ybShzb2xpZCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuZ2V0U29saWRGaXhlZChzb2xpZCkpIHsKICAgICAgICB0aGlzLl9zeW5jUHJveHlHcm91cFRyYW5zZm9ybShzb2xpZCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgdHJhbnNsYXRpb24gPSBib2R5LnRyYW5zbGF0aW9uKCk7CiAgICAgIGNvbnN0IHJvdGF0aW9uID0gYm9keS5yb3RhdGlvbigpOwogICAgICBpZiAoIXRyYW5zbGF0aW9uIHx8ICFyb3RhdGlvbikgY29udGludWU7CiAgICAgIHRoaXMuX3NldFNvbGlkV29ybGRQb3NlKHNvbGlkLCB0cmFuc2xhdGlvbiwgcm90YXRpb24pOwogICAgICB0aGlzLl91cGRhdGVSdW50aW1lVHJhbnNmb3JtRnJvbVNvbGlkKHNvbGlkLCB7IHBlcnNpc3Q6IGZhbHNlIH0pOwogICAgICB0aGlzLl9tb3ZlZFNvbGlkSWRzLmFkZChzb2xpZC51dWlkKTsKICAgICAgY2hhbmdlZCA9IHRydWU7CiAgICB9CiAgICBpZiAoY2hhbmdlZCkgewogICAgICB0cnkgeyB0aGlzLnZpZXdlcj8ucmVuZGVyPy4oKTsgfSBjYXRjaCB7fQogICAgfQogIH0KCiAgX3NldFNvbGlkV29ybGRQb3NlKHNvbGlkLCB0cmFuc2xhdGlvbiwgcm90YXRpb24pIHsKICAgIGNvbnN0IHBhcmVudCA9IHNvbGlkLnBhcmVudCB8fCB0aGlzLnZpZXdlcj8uc2NlbmUgfHwgbnVsbDsKICAgIGNvbnN0IHNjcmF0Y2ggPSB0aGlzLl9zY3JhdGNoOwogICAgc2NyYXRjaC53b3JsZFBvc2l0aW9uLnNldCh0cmFuc2xhdGlvbi54LCB0cmFuc2xhdGlvbi55LCB0cmFuc2xhdGlvbi56KTsKICAgIHNjcmF0Y2gud29ybGRRdWF0ZXJuaW9uLnNldChyb3RhdGlvbi54LCByb3RhdGlvbi55LCByb3RhdGlvbi56LCByb3RhdGlvbi53KTsKICAgIGlmIChwYXJlbnQ/LmlzT2JqZWN0M0QpIHsKICAgICAgcGFyZW50LnVwZGF0ZU1hdHJpeFdvcmxkPy4odHJ1ZSk7CiAgICAgIHNjcmF0Y2gucGFyZW50SW52ZXJzZS5jb3B5KHBhcmVudC5tYXRyaXhXb3JsZCkuaW52ZXJ0KCk7CiAgICAgIHBhcmVudC5nZXRXb3JsZFF1YXRlcm5pb24oc2NyYXRjaC5wYXJlbnRRdWF0ZXJuaW9uKTsKICAgICAgc2NyYXRjaC5wYXJlbnRRdWF0ZXJuaW9uSW52ZXJzZS5jb3B5KHNjcmF0Y2gucGFyZW50UXVhdGVybmlvbikuaW52ZXJ0KCk7CiAgICAgIHNjcmF0Y2gubG9jYWxQb3NpdGlvbi5jb3B5KHNjcmF0Y2gud29ybGRQb3NpdGlvbikuYXBwbHlNYXRyaXg0KHNjcmF0Y2gucGFyZW50SW52ZXJzZSk7CiAgICAgIHNvbGlkLnBvc2l0aW9uLmNvcHkoc2NyYXRjaC5sb2NhbFBvc2l0aW9uKTsKICAgICAgc29saWQucXVhdGVybmlvbi5jb3B5KHNjcmF0Y2gucGFyZW50UXVhdGVybmlvbkludmVyc2UubXVsdGlwbHkoc2NyYXRjaC53b3JsZFF1YXRlcm5pb24pKTsKICAgIH0gZWxzZSB7CiAgICAgIHNvbGlkLnBvc2l0aW9uLmNvcHkoc2NyYXRjaC53b3JsZFBvc2l0aW9uKTsKICAgICAgc29saWQucXVhdGVybmlvbi5jb3B5KHNjcmF0Y2gud29ybGRRdWF0ZXJuaW9uKTsKICAgIH0KICAgIHNvbGlkLnVwZGF0ZU1hdHJpeFdvcmxkPy4odHJ1ZSk7CiAgICB0aGlzLl9zeW5jUHJveHlHcm91cFRyYW5zZm9ybShzb2xpZCk7CiAgfQoKICBfc3RhcnRUcmFuc2Zvcm1TZXNzaW9uKHNvbGlkKSB7CiAgICBpZiAoIXNvbGlkIHx8ICF0aGlzLl9hY3RpdmUpIHJldHVybjsKICAgIHRoaXMuX3N0b3BUcmFuc2Zvcm1TZXNzaW9uKCk7CiAgICBjb25zdCBjb250cm9scyA9IG5ldyBDb21iaW5lZFRyYW5zZm9ybUNvbnRyb2xzKHRoaXMudmlld2VyLmNhbWVyYSwgdGhpcy52aWV3ZXIucmVuZGVyZXI/LmRvbUVsZW1lbnQpOwogICAgdHJ5IHsgY29udHJvbHMuc2V0TW9kZSgndHJhbnNsYXRlJyk7IH0gY2F0Y2ggeyBjb250cm9scy5tb2RlID0gJ3RyYW5zbGF0ZSc7IH0KICAgIGNvbnN0IHRhcmdldCA9IG5ldyBUSFJFRS5PYmplY3QzRCgpOwogICAgdGFyZ2V0Lm5hbWUgPSBgU2ltdWxhdGlvblRyYW5zZm9ybVRhcmdldDoke3NvbGlkLm5hbWUgfHwgc29saWQudXVpZCB8fCAnJ31gOwogICAgdGhpcy52aWV3ZXIuc2NlbmUudXBkYXRlTWF0cml4V29ybGQ/Lih0cnVlKTsKICAgIHNvbGlkLnVwZGF0ZU1hdHJpeFdvcmxkPy4odHJ1ZSk7CiAgICBjb25zdCBib3ggPSB0aGlzLl9zY3JhdGNoLmJveDsKICAgIGNvbnN0IGNlbnRlciA9IGJveC5zZXRGcm9tT2JqZWN0KHRoaXMuX3Byb3h5R3JvdXBzLmdldChzb2xpZC51dWlkKSB8fCBzb2xpZCkuaXNFbXB0eSgpCiAgICAgID8gc29saWQuZ2V0V29ybGRQb3NpdGlvbih0aGlzLl9zY3JhdGNoLmNlbnRlcikKICAgICAgOiBib3guZ2V0Q2VudGVyKHRoaXMuX3NjcmF0Y2guY2VudGVyKTsKICAgIGNvbnN0IHdvcmxkUG9zaXRpb24gPSBzb2xpZC5nZXRXb3JsZFBvc2l0aW9uKG5ldyBUSFJFRS5WZWN0b3IzKCkpOwogICAgY29uc3Qgd29ybGRRdWF0ZXJuaW9uID0gc29saWQuZ2V0V29ybGRRdWF0ZXJuaW9uKG5ldyBUSFJFRS5RdWF0ZXJuaW9uKCkpOwogICAgY29uc3Qgb2Zmc2V0TG9jYWwgPSB3b3JsZFBvc2l0aW9uLmNsb25lKCkuc3ViKGNlbnRlcikuYXBwbHlRdWF0ZXJuaW9uKHdvcmxkUXVhdGVybmlvbi5jbG9uZSgpLmludmVydCgpKTsKICAgIHRhcmdldC5wb3NpdGlvbi5jb3B5KGNlbnRlcik7CiAgICB0YXJnZXQucXVhdGVybmlvbi5jb3B5KHdvcmxkUXVhdGVybmlvbik7CiAgICB0aGlzLnZpZXdlci5zY2VuZS5hZGQodGFyZ2V0KTsKICAgIGNvbnRyb2xzLmF0dGFjaCh0YXJnZXQpOwogICAgdGhpcy52aWV3ZXIuc2NlbmUuYWRkKGNvbnRyb2xzKTsKCiAgICBjb25zdCBhcHBseVRvU29saWQgPSAocGVyc2lzdCA9IGZhbHNlKSA9PiB7CiAgICAgIGNvbnN0IHRhcmdldFdvcmxkUG9zaXRpb24gPSB0YXJnZXQuZ2V0V29ybGRQb3NpdGlvbihuZXcgVEhSRUUuVmVjdG9yMygpKTsKICAgICAgY29uc3QgdGFyZ2V0V29ybGRRdWF0ZXJuaW9uID0gdGFyZ2V0LmdldFdvcmxkUXVhdGVybmlvbihuZXcgVEhSRUUuUXVhdGVybmlvbigpKTsKICAgICAgY29uc3Qgc29saWRXb3JsZFBvc2l0aW9uID0gdGFyZ2V0V29ybGRQb3NpdGlvbi5jbG9uZSgpLmFkZChvZmZzZXRMb2NhbC5jbG9uZSgpLmFwcGx5UXVhdGVybmlvbih0YXJnZXRXb3JsZFF1YXRlcm5pb24pKTsKICAgICAgdGhpcy5fc2V0U29saWRXb3JsZFBvc2Uoc29saWQsIHNvbGlkV29ybGRQb3NpdGlvbiwgdGFyZ2V0V29ybGRRdWF0ZXJuaW9uKTsKICAgICAgdGhpcy5fdXBkYXRlUnVudGltZVRyYW5zZm9ybUZyb21Tb2xpZChzb2xpZCwgeyBwZXJzaXN0IH0pOwogICAgICBpZiAocGVyc2lzdCkgewogICAgICAgIGlmICh0aGlzLl9waHlzaWNzV29ybGQpIHsKICAgICAgICAgIHZvaWQgdGhpcy5fcmVidWlsZFBoeXNpY3NXb3JsZCgpOwogICAgICAgIH0KICAgICAgfQogICAgICB0cnkgeyB0aGlzLnZpZXdlcj8ucmVuZGVyPy4oKTsgfSBjYXRjaCB7fQogICAgfTsKCiAgICBjb25zdCBjaGFuZ2VIYW5kbGVyID0gKCkgPT4gYXBwbHlUb1NvbGlkKGZhbHNlKTsKICAgIGNvbnN0IGRyYWdIYW5kbGVyID0gKGV2ZW50KSA9PiB7CiAgICAgIGNvbnN0IGRyYWdnaW5nID0gISFldmVudD8udmFsdWU7CiAgICAgIHRyeSB7IGlmICh0aGlzLnZpZXdlcj8uY29udHJvbHMpIHRoaXMudmlld2VyLmNvbnRyb2xzLmVuYWJsZWQgPSAhZHJhZ2dpbmc7IH0gY2F0Y2gge30KICAgICAgaWYgKCFkcmFnZ2luZykgYXBwbHlUb1NvbGlkKHRydWUpOwogICAgfTsKICAgIGNvbnN0IG9iamVjdENoYW5nZUhhbmRsZXIgPSAoKSA9PiB7CiAgICAgIGlmICghY29udHJvbHMuZHJhZ2dpbmcpIGFwcGx5VG9Tb2xpZCh0cnVlKTsKICAgIH07CiAgICBjb25zdCB1cGRhdGVGb3JDYW1lcmEgPSAoKSA9PiB7CiAgICAgIHRyeSB7IGNvbnRyb2xzLnVwZGF0ZT8uKCk7IH0gY2F0Y2gge30KICAgIH07CiAgICBjb25zdCBjYW1lcmFDaGFuZ2VIYW5kbGVyID0gKCkgPT4gdXBkYXRlRm9yQ2FtZXJhKCk7CiAgICBjb250cm9scy5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCBjaGFuZ2VIYW5kbGVyKTsKICAgIGNvbnRyb2xzLmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdnaW5nLWNoYW5nZWQnLCBkcmFnSGFuZGxlcik7CiAgICBjb250cm9scy5hZGRFdmVudExpc3RlbmVyKCdvYmplY3RDaGFuZ2UnLCBvYmplY3RDaGFuZ2VIYW5kbGVyKTsKICAgIHRyeSB7IHRoaXMudmlld2VyPy5jb250cm9scz8uYWRkRXZlbnRMaXN0ZW5lcj8uKCdjaGFuZ2UnLCBjYW1lcmFDaGFuZ2VIYW5kbGVyKTsgfSBjYXRjaCB7fQoKICAgIGNvbnN0IGdsb2JhbFN0YXRlID0geyBjb250cm9scywgdmlld2VyOiB0aGlzLnZpZXdlciwgdGFyZ2V0LCB1cGRhdGVGb3JDYW1lcmEgfTsKICAgIHRyeSB7IHdpbmRvdy5fX0JSRVBfYWN0aXZlWGZvcm0gPSBnbG9iYWxTdGF0ZTsgfSBjYXRjaCB7fQogICAgdGhpcy5fdHJhbnNmb3JtU2Vzc2lvbiA9IHsKICAgICAgc29saWQsCiAgICAgIGNvbnRyb2xzLAogICAgICB0YXJnZXQsCiAgICAgIGNoYW5nZUhhbmRsZXIsCiAgICAgIGRyYWdIYW5kbGVyLAogICAgICBvYmplY3RDaGFuZ2VIYW5kbGVyLAogICAgICBjYW1lcmFDaGFuZ2VIYW5kbGVyLAogICAgICBnbG9iYWxTdGF0ZSwKICAgICAgbW9kZTogJ3RyYW5zbGF0ZScsCiAgICB9OwogICAgaWYgKHRoaXMuX3BoeXNpY3NXb3JsZCkgewogICAgICB2b2lkIHRoaXMuX3JlYnVpbGRQaHlzaWNzV29ybGQoKTsKICAgIH0KICAgIHVwZGF0ZUZvckNhbWVyYSgpOwogICAgYXBwbHlUb1NvbGlkKGZhbHNlKTsKICB9CgogIF9zdG9wVHJhbnNmb3JtU2Vzc2lvbigpIHsKICAgIGNvbnN0IHNlc3Npb24gPSB0aGlzLl90cmFuc2Zvcm1TZXNzaW9uOwogICAgaWYgKCFzZXNzaW9uKSByZXR1cm47CiAgICB0cnkgeyBzZXNzaW9uLmNvbnRyb2xzPy5yZW1vdmVFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCBzZXNzaW9uLmNoYW5nZUhhbmRsZXIpOyB9IGNhdGNoIHt9CiAgICB0cnkgeyBzZXNzaW9uLmNvbnRyb2xzPy5yZW1vdmVFdmVudExpc3RlbmVyKCdkcmFnZ2luZy1jaGFuZ2VkJywgc2Vzc2lvbi5kcmFnSGFuZGxlcik7IH0gY2F0Y2gge30KICAgIHRyeSB7IHNlc3Npb24uY29udHJvbHM/LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ29iamVjdENoYW5nZScsIHNlc3Npb24ub2JqZWN0Q2hhbmdlSGFuZGxlcik7IH0gY2F0Y2gge30KICAgIHRyeSB7IHRoaXMudmlld2VyPy5jb250cm9scz8ucmVtb3ZlRXZlbnRMaXN0ZW5lcj8uKCdjaGFuZ2UnLCBzZXNzaW9uLmNhbWVyYUNoYW5nZUhhbmRsZXIpOyB9IGNhdGNoIHt9CiAgICB0cnkgeyBzZXNzaW9uLmNvbnRyb2xzPy5kZXRhY2g/LigpOyB9IGNhdGNoIHt9CiAgICB0cnkgeyB0aGlzLnZpZXdlcj8uc2NlbmU/LnJlbW92ZT8uKHNlc3Npb24uY29udHJvbHMpOyB9IGNhdGNoIHt9CiAgICB0cnkgeyB0aGlzLnZpZXdlcj8uc2NlbmU/LnJlbW92ZT8uKHNlc3Npb24udGFyZ2V0KTsgfSBjYXRjaCB7fQogICAgdHJ5IHsgc2Vzc2lvbi5jb250cm9scz8uZGlzcG9zZT8uKCk7IH0gY2F0Y2gge30KICAgIHRyeSB7CiAgICAgIGlmICh3aW5kb3cuX19CUkVQX2FjdGl2ZVhmb3JtID09PSBzZXNzaW9uLmdsb2JhbFN0YXRlKSB7CiAgICAgICAgd2luZG93Ll9fQlJFUF9hY3RpdmVYZm9ybSA9IG51bGw7CiAgICAgIH0KICAgIH0gY2F0Y2gge30KICAgIHRoaXMuX3RyYW5zZm9ybVNlc3Npb24gPSBudWxsOwogICAgdHJ5IHsgaWYgKHRoaXMudmlld2VyPy5jb250cm9scykgdGhpcy52aWV3ZXIuY29udHJvbHMuZW5hYmxlZCA9IHRydWU7IH0gY2F0Y2gge30KICAgIGlmICh0aGlzLl9waHlzaWNzV29ybGQpIHsKICAgICAgdm9pZCB0aGlzLl9yZWJ1aWxkUGh5c2ljc1dvcmxkKCk7CiAgICB9CiAgICB0cnkgeyB0aGlzLnZpZXdlcj8ucmVuZGVyPy4oKTsgfSBjYXRjaCB7fQogIH0KCiAgX2xpc3RTY2VuZVNvbGlkcygpIHsKICAgIGNvbnN0IHNjZW5lID0gdGhpcy52aWV3ZXI/LnBhcnRIaXN0b3J5Py5zY2VuZSB8fCB0aGlzLnZpZXdlcj8uc2NlbmUgfHwgbnVsbDsKICAgIGNvbnN0IHNvbGlkcyA9IFtdOwogICAgaWYgKCFzY2VuZT8udHJhdmVyc2UpIHJldHVybiBzb2xpZHM7CiAgICBzY2VuZS50cmF2ZXJzZSgob2JqKSA9PiB7CiAgICAgIGlmIChvYmo/LnR5cGUgPT09ICdTT0xJRCcpIHNvbGlkcy5wdXNoKG9iaik7CiAgICB9KTsKICAgIHJldHVybiBzb2xpZHM7CiAgfQoKICBfYmluZFN0YXRlTWFuYWdlcigpIHsKICAgIGNvbnN0IG1hbmFnZXIgPSB0aGlzLnZpZXdlcj8ucGFydEhpc3Rvcnk/LnNpbXVsYXRpb25TdGF0ZU1hbmFnZXI7CiAgICBpZiAoIW1hbmFnZXI/LmFkZExpc3RlbmVyKSByZXR1cm47CiAgICB0aGlzLl9yZW1vdmVTdGF0ZU1hbmFnZXJMaXN0ZW5lciA9IG1hbmFnZXIuYWRkTGlzdGVuZXIoKCkgPT4gewogICAgICB0aGlzLl9yZWNvbmNpbGVNb3Rpb25TdGF0ZSgpOwogICAgICBpZiAodGhpcy5fYWN0aXZlICYmIHRoaXMuX3BoeXNpY3NXb3JsZCkgewogICAgICAgIHZvaWQgdGhpcy5fcmVidWlsZFBoeXNpY3NXb3JsZCgpOwogICAgICB9CiAgICAgIHRoaXMuX2VtaXQoKTsKICAgIH0pOwogIH0KCiAgX2VtaXQoKSB7CiAgICBpZiAoIXRoaXMuX2xpc3RlbmVycyB8fCB0aGlzLl9saXN0ZW5lcnMuc2l6ZSA9PT0gMCkgcmV0dXJuOwogICAgY29uc3QgcGF5bG9hZCA9IHsKICAgICAgYWN0aXZlOiB0aGlzLl9hY3RpdmUsCiAgICAgIHBsYXlpbmc6IHRoaXMuX2lzUGxheWluZywKICAgICAgbWFuYWdlcjogdGhpcywKICAgIH07CiAgICBmb3IgKGNvbnN0IGxpc3RlbmVyIG9mIEFycmF5LmZyb20odGhpcy5fbGlzdGVuZXJzKSkgewogICAgICB0cnkgeyBsaXN0ZW5lcihwYXlsb2FkKTsgfSBjYXRjaCB7fQogICAgfQogIH0KCiAgX2dldE1vdGlvbkVudHJpZXMoKSB7CiAgICBjb25zdCBtb3Rpb25zID0gdGhpcy52aWV3ZXI/LnBhcnRIaXN0b3J5Py5zaW11bGF0aW9uU3RhdGVNYW5hZ2VyPy5nZXRNb3Rpb25zPy4oKTsKICAgIHJldHVybiBBcnJheS5pc0FycmF5KG1vdGlvbnMpCiAgICAgID8gbW90aW9ucy5tYXAoKGVudHJ5KSA9PiAoZW50cnk/LmlucHV0UGFyYW1zICYmIHR5cGVvZiBlbnRyeS5pbnB1dFBhcmFtcyA9PT0gJ29iamVjdCcpID8gZW50cnkuaW5wdXRQYXJhbXMgOiBlbnRyeSkuZmlsdGVyKEJvb2xlYW4pCiAgICAgIDogW107CiAgfQoKICBfcmVzZXRNb3Rpb25SdW50aW1lKCkgewogICAgdGhpcy5fbW90aW9uU3RhdGUuY2xlYXIoKTsKICAgIGZvciAoY29uc3QgbW90aW9uIG9mIHRoaXMuX2dldE1vdGlvbkVudHJpZXMoKSkgewogICAgICB0aGlzLl9tb3Rpb25TdGF0ZS5zZXQobW90aW9uLmlkLCB7IHByb2dyZXNzOiAwLCBjb21wbGV0ZWQ6IGZhbHNlIH0pOwogICAgfQogIH0KCiAgX3JlY29uY2lsZU1vdGlvblN0YXRlKCkgewogICAgY29uc3QgYWN0aXZlSWRzID0gbmV3IFNldCgpOwogICAgZm9yIChjb25zdCBtb3Rpb24gb2YgdGhpcy5fZ2V0TW90aW9uRW50cmllcygpKSB7CiAgICAgIGFjdGl2ZUlkcy5hZGQobW90aW9uLmlkKTsKICAgICAgaWYgKCF0aGlzLl9tb3Rpb25TdGF0ZS5oYXMobW90aW9uLmlkKSkgewogICAgICAgIHRoaXMuX21vdGlvblN0YXRlLnNldChtb3Rpb24uaWQsIHsgcHJvZ3Jlc3M6IDAsIGNvbXBsZXRlZDogZmFsc2UgfSk7CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgaWQgb2YgQXJyYXkuZnJvbSh0aGlzLl9tb3Rpb25TdGF0ZS5rZXlzKCkpKSB7CiAgICAgIGlmICghYWN0aXZlSWRzLmhhcyhpZCkpIHRoaXMuX21vdGlvblN0YXRlLmRlbGV0ZShpZCk7CiAgICB9CiAgfQoKICBfaXNTb2xpZE1vdGlvbkRyaXZlbihzb2xpZCkgewogICAgaWYgKCFzb2xpZCB8fCAhdGhpcy5faXNQbGF5aW5nKSByZXR1cm4gZmFsc2U7CiAgICBjb25zdCBuYW1lID0gbm9ybWFsaXplVGV4dChzb2xpZC5uYW1lLCAnJyk7CiAgICBpZiAoIW5hbWUpIHJldHVybiBmYWxzZTsKICAgIHJldHVybiB0aGlzLl9nZXRNb3Rpb25FbnRyaWVzKCkuc29tZSgobW90aW9uKSA9PiBub3JtYWxpemVUZXh0KHRoaXMuX3Jlc29sdmVSZWZlcmVuY2VOYW1lKG1vdGlvbj8uc29saWQpLCAnJykgPT09IG5hbWUpOwogIH0KCiAgX2FwcGx5TW90aW9uU3RlcChkdCkgewogICAgbGV0IGNoYW5nZWQgPSBmYWxzZTsKICAgIGZvciAoY29uc3QgbW90aW9uIG9mIHRoaXMuX2dldE1vdGlvbkVudHJpZXMoKSkgewogICAgICBjb25zdCBzb2xpZCA9IHRoaXMuX3Jlc29sdmVNb3Rpb25Tb2xpZChtb3Rpb24pOwogICAgICBpZiAoIXNvbGlkKSBjb250aW51ZTsKICAgICAgaWYgKG1vdGlvbi50eXBlID09PSAnbGluZWFyJykgY2hhbmdlZCA9IHRoaXMuX2FwcGx5TGluZWFyTW90aW9uU3RlcChzb2xpZCwgbW90aW9uLCBkdCkgfHwgY2hhbmdlZDsKICAgICAgZWxzZSBjaGFuZ2VkID0gdGhpcy5fYXBwbHlSb3RhdGlvbk1vdGlvblN0ZXAoc29saWQsIG1vdGlvbiwgZHQpIHx8IGNoYW5nZWQ7CiAgICB9CiAgICByZXR1cm4gY2hhbmdlZDsKICB9CgogIF9yZXNvbHZlTW90aW9uU29saWQobW90aW9uKSB7CiAgICBjb25zdCBuYW1lID0gbm9ybWFsaXplVGV4dCh0aGlzLl9yZXNvbHZlUmVmZXJlbmNlTmFtZShtb3Rpb24/LnNvbGlkKSwgJycpOwogICAgaWYgKCFuYW1lKSByZXR1cm4gbnVsbDsKICAgIGNvbnN0IG9iamVjdCA9IHRoaXMudmlld2VyPy5wYXJ0SGlzdG9yeT8uZ2V0T2JqZWN0QnlOYW1lPy4obmFtZSkgfHwgbnVsbDsKICAgIHJldHVybiBvYmplY3Q/LnR5cGUgPT09ICdTT0xJRCcgPyBvYmplY3QgOiBudWxsOwogIH0KCiAgX3Jlc29sdmVNb3Rpb25BeGlzKG1vdGlvbikgewogICAgY29uc3Qgb2JqZWN0TmFtZSA9IG5vcm1hbGl6ZVRleHQodGhpcy5fcmVzb2x2ZVJlZmVyZW5jZU5hbWUobW90aW9uPy5heGlzKSwgJycpOwogICAgY29uc3Qgb2JqZWN0ID0gb2JqZWN0TmFtZSA/IHRoaXMudmlld2VyPy5wYXJ0SGlzdG9yeT8uZ2V0T2JqZWN0QnlOYW1lPy4ob2JqZWN0TmFtZSkgOiBudWxsOwogICAgaWYgKCFvYmplY3QpIHJldHVybiBudWxsOwogICAgY29uc3QgbGl2ZSA9IHRoaXMuX2V4dHJhY3RBeGlzUG9pbnRzRnJvbU9iamVjdChvYmplY3QpOwogICAgaWYgKCFsaXZlPy5zdGFydCB8fCAhbGl2ZT8uZW5kKSByZXR1cm4gbnVsbDsKICAgIGNvbnN0IHN0YXJ0VmVjID0gbmV3IFRIUkVFLlZlY3RvcjMoTnVtYmVyKGxpdmUuc3RhcnRbMF0pIHx8IDAsIE51bWJlcihsaXZlLnN0YXJ0WzFdKSB8fCAwLCBOdW1iZXIobGl2ZS5zdGFydFsyXSkgfHwgMCk7CiAgICBjb25zdCBlbmRWZWMgPSBuZXcgVEhSRUUuVmVjdG9yMyhOdW1iZXIobGl2ZS5lbmRbMF0pIHx8IDAsIE51bWJlcihsaXZlLmVuZFsxXSkgfHwgMCwgTnVtYmVyKGxpdmUuZW5kWzJdKSB8fCAwKTsKICAgIGlmIChzdGFydFZlYy5kaXN0YW5jZVRvU3F1YXJlZChlbmRWZWMpIDw9IDFlLTEyKSByZXR1cm4gbnVsbDsKICAgIHJldHVybiB7IHN0YXJ0OiBzdGFydFZlYywgZW5kOiBlbmRWZWMgfTsKICB9CgogIF9yZXNvbHZlUmVmZXJlbmNlTmFtZSh2YWx1ZSkgewogICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7CiAgICAgIHJldHVybiB0aGlzLl9yZXNvbHZlUmVmZXJlbmNlTmFtZSh2YWx1ZVswXSB8fCBudWxsKTsKICAgIH0KICAgIGlmICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7CiAgICAgIHJldHVybiBub3JtYWxpemVUZXh0KHZhbHVlLm5hbWUgfHwgdmFsdWUub2JqZWN0TmFtZSB8fCB2YWx1ZS5sYWJlbCB8fCAnJywgJycpOwogICAgfQogICAgcmV0dXJuIG5vcm1hbGl6ZVRleHQodmFsdWUsICcnKTsKICB9CgogIF9leHRyYWN0QXhpc1BvaW50c0Zyb21PYmplY3Qob2JqZWN0KSB7CiAgICBpZiAoIW9iamVjdCkgcmV0dXJuIG51bGw7CiAgICB0cnkgewogICAgICBpZiAodHlwZW9mIG9iamVjdC5wb2ludHMgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICBjb25zdCBwb2ludHMgPSBvYmplY3QucG9pbnRzKHRydWUpOwogICAgICAgIGlmIChBcnJheS5pc0FycmF5KHBvaW50cykgJiYgcG9pbnRzLmxlbmd0aCA+PSAyKSB7CiAgICAgICAgICBjb25zdCBmaXJzdCA9IHBvaW50c1swXTsKICAgICAgICAgIGNvbnN0IGxhc3QgPSBwb2ludHNbcG9pbnRzLmxlbmd0aCAtIDFdOwogICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgc3RhcnQ6IFtOdW1iZXIoZmlyc3Q/LngpIHx8IDAsIE51bWJlcihmaXJzdD8ueSkgfHwgMCwgTnVtYmVyKGZpcnN0Py56KSB8fCAwXSwKICAgICAgICAgICAgZW5kOiBbTnVtYmVyKGxhc3Q/LngpIHx8IDAsIE51bWJlcihsYXN0Py55KSB8fCAwLCBOdW1iZXIobGFzdD8ueikgfHwgMF0sCiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgfQogICAgfSBjYXRjaCB7fQogICAgdHJ5IHsKICAgICAgb2JqZWN0LnVwZGF0ZU1hdHJpeFdvcmxkPy4odHJ1ZSk7CiAgICAgIGNvbnN0IGF0dHIgPSBvYmplY3QuZ2VvbWV0cnk/LmdldEF0dHJpYnV0ZT8uKCdwb3NpdGlvbicpOwogICAgICBpZiAoIWF0dHIgfHwgYXR0ci5jb3VudCA8IDIpIHJldHVybiBudWxsOwogICAgICBjb25zdCBmaXJzdCA9IG5ldyBUSFJFRS5WZWN0b3IzKGF0dHIuZ2V0WCgwKSwgYXR0ci5nZXRZKDApLCBhdHRyLmdldFooMCkpLmFwcGx5TWF0cml4NChvYmplY3QubWF0cml4V29ybGQpOwogICAgICBjb25zdCBsYXN0SW5kZXggPSBhdHRyLmNvdW50IC0gMTsKICAgICAgY29uc3QgbGFzdCA9IG5ldyBUSFJFRS5WZWN0b3IzKGF0dHIuZ2V0WChsYXN0SW5kZXgpLCBhdHRyLmdldFkobGFzdEluZGV4KSwgYXR0ci5nZXRaKGxhc3RJbmRleCkpLmFwcGx5TWF0cml4NChvYmplY3QubWF0cml4V29ybGQpOwogICAgICByZXR1cm4gewogICAgICAgIHN0YXJ0OiBbZmlyc3QueCwgZmlyc3QueSwgZmlyc3Quel0sCiAgICAgICAgZW5kOiBbbGFzdC54LCBsYXN0LnksIGxhc3Quel0sCiAgICAgIH07CiAgICB9IGNhdGNoIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgfQoKICBfYXBwbHlSb3RhdGlvbk1vdGlvblN0ZXAoc29saWQsIG1vdGlvbiwgZHQpIHsKICAgIGNvbnN0IHN0YXRlID0gdGhpcy5fbW90aW9uU3RhdGUuZ2V0KG1vdGlvbi5pZCkgfHwgeyBwcm9ncmVzczogMCwgY29tcGxldGVkOiBmYWxzZSB9OwogICAgaWYgKHN0YXRlLmNvbXBsZXRlZCkgcmV0dXJuOwogICAgY29uc3QgYXhpcyA9IHRoaXMuX3Jlc29sdmVNb3Rpb25BeGlzKG1vdGlvbik7CiAgICBpZiAoIWF4aXMpIHJldHVybjsKICAgIGNvbnN0IHNwZWVkRGVnID0gTnVtYmVyKG1vdGlvbj8uc3BlZWQpOwogICAgaWYgKCFOdW1iZXIuaXNGaW5pdGUoc3BlZWREZWcpIHx8IE1hdGguYWJzKHNwZWVkRGVnKSA8PSAxZS05KSByZXR1cm47CiAgICBsZXQgZGVsdGFEZWcgPSBzcGVlZERlZyAqIGR0OwogICAgY29uc3QgbGltaXREZWcgPSBOdW1iZXIuaXNGaW5pdGUoTnVtYmVyKG1vdGlvbj8uYW5nbGUpKSA/IE51bWJlcihtb3Rpb24uYW5nbGUpIDogbnVsbDsKICAgIGlmIChsaW1pdERlZyAhPSBudWxsKSB7CiAgICAgIGNvbnN0IHJlbWFpbmluZyA9IGxpbWl0RGVnIC0gc3RhdGUucHJvZ3Jlc3M7CiAgICAgIGlmIChNYXRoLmFicyhyZW1haW5pbmcpIDw9IDFlLTkpIHsKICAgICAgICBzdGF0ZS5jb21wbGV0ZWQgPSB0cnVlOwogICAgICAgIHRoaXMuX21vdGlvblN0YXRlLnNldChtb3Rpb24uaWQsIHN0YXRlKTsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKE1hdGguc2lnbihkZWx0YURlZyB8fCAxKSAhPT0gTWF0aC5zaWduKHJlbWFpbmluZyB8fCAxKSkgewogICAgICAgIGRlbHRhRGVnID0gTWF0aC5zaWduKHJlbWFpbmluZyB8fCAxKSAqIE1hdGguYWJzKGRlbHRhRGVnKTsKICAgICAgfQogICAgICBpZiAoTWF0aC5hYnMoZGVsdGFEZWcpID4gTWF0aC5hYnMocmVtYWluaW5nKSkgZGVsdGFEZWcgPSByZW1haW5pbmc7CiAgICB9CiAgICBpZiAoTWF0aC5hYnMoZGVsdGFEZWcpIDw9IDFlLTkpIHJldHVybiBmYWxzZTsKICAgIHRoaXMuX3JvdGF0ZVNvbGlkQXJvdW5kV29ybGRBeGlzKHNvbGlkLCBheGlzLnN0YXJ0LCBheGlzLmVuZCwgVEhSRUUuTWF0aFV0aWxzLmRlZ1RvUmFkKGRlbHRhRGVnKSk7CiAgICBzdGF0ZS5wcm9ncmVzcyArPSBkZWx0YURlZzsKICAgIGlmIChsaW1pdERlZyAhPSBudWxsICYmIE1hdGguYWJzKGxpbWl0RGVnIC0gc3RhdGUucHJvZ3Jlc3MpIDw9IDFlLTkpIHN0YXRlLmNvbXBsZXRlZCA9IHRydWU7CiAgICB0aGlzLl9tb3Rpb25TdGF0ZS5zZXQobW90aW9uLmlkLCBzdGF0ZSk7CiAgICB0aGlzLl91cGRhdGVSdW50aW1lVHJhbnNmb3JtRnJvbVNvbGlkKHNvbGlkLCB7IHBlcnNpc3Q6IGZhbHNlIH0pOwogICAgdGhpcy5fbW92ZWRTb2xpZElkcy5hZGQoc29saWQudXVpZCk7CiAgICByZXR1cm4gdHJ1ZTsKICB9CgogIF9hcHBseUxpbmVhck1vdGlvblN0ZXAoc29saWQsIG1vdGlvbiwgZHQpIHsKICAgIGNvbnN0IHN0YXRlID0gdGhpcy5fbW90aW9uU3RhdGUuZ2V0KG1vdGlvbi5pZCkgfHwgeyBwcm9ncmVzczogMCwgY29tcGxldGVkOiBmYWxzZSB9OwogICAgaWYgKHN0YXRlLmNvbXBsZXRlZCkgcmV0dXJuOwogICAgY29uc3QgYXhpcyA9IHRoaXMuX3Jlc29sdmVNb3Rpb25BeGlzKG1vdGlvbik7CiAgICBpZiAoIWF4aXMpIHJldHVybjsKICAgIGNvbnN0IHNwZWVkID0gTnVtYmVyKG1vdGlvbj8uc3BlZWQpOwogICAgaWYgKCFOdW1iZXIuaXNGaW5pdGUoc3BlZWQpIHx8IE1hdGguYWJzKHNwZWVkKSA8PSAxZS05KSByZXR1cm47CiAgICBsZXQgZGVsdGEgPSBzcGVlZCAqIGR0OwogICAgY29uc3QgbGltaXQgPSBOdW1iZXIuaXNGaW5pdGUoTnVtYmVyKG1vdGlvbj8uZGlzdGFuY2UpKSA/IE51bWJlcihtb3Rpb24uZGlzdGFuY2UpIDogbnVsbDsKICAgIGlmIChsaW1pdCAhPSBudWxsKSB7CiAgICAgIGNvbnN0IHJlbWFpbmluZyA9IGxpbWl0IC0gc3RhdGUucHJvZ3Jlc3M7CiAgICAgIGlmIChNYXRoLmFicyhyZW1haW5pbmcpIDw9IDFlLTkpIHsKICAgICAgICBzdGF0ZS5jb21wbGV0ZWQgPSB0cnVlOwogICAgICAgIHRoaXMuX21vdGlvblN0YXRlLnNldChtb3Rpb24uaWQsIHN0YXRlKTsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKE1hdGguc2lnbihkZWx0YSB8fCAxKSAhPT0gTWF0aC5zaWduKHJlbWFpbmluZyB8fCAxKSkgewogICAgICAgIGRlbHRhID0gTWF0aC5zaWduKHJlbWFpbmluZyB8fCAxKSAqIE1hdGguYWJzKGRlbHRhKTsKICAgICAgfQogICAgICBpZiAoTWF0aC5hYnMoZGVsdGEpID4gTWF0aC5hYnMocmVtYWluaW5nKSkgZGVsdGEgPSByZW1haW5pbmc7CiAgICB9CiAgICBpZiAoTWF0aC5hYnMoZGVsdGEpIDw9IDFlLTkpIHJldHVybiBmYWxzZTsKICAgIHRoaXMuX3RyYW5zbGF0ZVNvbGlkQWxvbmdXb3JsZEF4aXMoc29saWQsIGF4aXMuc3RhcnQsIGF4aXMuZW5kLCBkZWx0YSk7CiAgICBzdGF0ZS5wcm9ncmVzcyArPSBkZWx0YTsKICAgIGlmIChsaW1pdCAhPSBudWxsICYmIE1hdGguYWJzKGxpbWl0IC0gc3RhdGUucHJvZ3Jlc3MpIDw9IDFlLTkpIHN0YXRlLmNvbXBsZXRlZCA9IHRydWU7CiAgICB0aGlzLl9tb3Rpb25TdGF0ZS5zZXQobW90aW9uLmlkLCBzdGF0ZSk7CiAgICB0aGlzLl91cGRhdGVSdW50aW1lVHJhbnNmb3JtRnJvbVNvbGlkKHNvbGlkLCB7IHBlcnNpc3Q6IGZhbHNlIH0pOwogICAgdGhpcy5fbW92ZWRTb2xpZElkcy5hZGQoc29saWQudXVpZCk7CiAgICByZXR1cm4gdHJ1ZTsKICB9CgogIF9yb3RhdGVTb2xpZEFyb3VuZFdvcmxkQXhpcyhzb2xpZCwgYXhpc1N0YXJ0LCBheGlzRW5kLCBhbmdsZVJhZCkgewogICAgY29uc3QgcGFyZW50ID0gc29saWQucGFyZW50IHx8IHRoaXMudmlld2VyPy5zY2VuZSB8fCBudWxsOwogICAgY29uc3Qgc2NyYXRjaCA9IHRoaXMuX3NjcmF0Y2g7CiAgICBzY3JhdGNoLmF4aXMuY29weShheGlzRW5kKS5zdWIoYXhpc1N0YXJ0KS5ub3JtYWxpemUoKTsKICAgIHNjcmF0Y2gucGFyZW50V29ybGRNYXRyaXguY29weShwYXJlbnQ/Lm1hdHJpeFdvcmxkIHx8IG5ldyBUSFJFRS5NYXRyaXg0KCkpOwogICAgc2NyYXRjaC5wYXJlbnRJbnZlcnNlLmNvcHkoc2NyYXRjaC5wYXJlbnRXb3JsZE1hdHJpeCkuaW52ZXJ0KCk7CiAgICBzY3JhdGNoLndvcmxkTWF0cml4LmNvcHkoc29saWQubWF0cml4V29ybGQpOwogICAgc2NyYXRjaC5kZWx0YU1hdHJpeC5tYWtlVHJhbnNsYXRpb24oYXhpc1N0YXJ0LngsIGF4aXNTdGFydC55LCBheGlzU3RhcnQueik7CiAgICBzY3JhdGNoLmRlbHRhTWF0cml4Lm11bHRpcGx5KG5ldyBUSFJFRS5NYXRyaXg0KCkubWFrZVJvdGF0aW9uQXhpcyhzY3JhdGNoLmF4aXMsIGFuZ2xlUmFkKSk7CiAgICBzY3JhdGNoLmRlbHRhTWF0cml4Lm11bHRpcGx5KG5ldyBUSFJFRS5NYXRyaXg0KCkubWFrZVRyYW5zbGF0aW9uKC1heGlzU3RhcnQueCwgLWF4aXNTdGFydC55LCAtYXhpc1N0YXJ0LnopKTsKICAgIHNjcmF0Y2gud29ybGRNYXRyaXgucHJlbXVsdGlwbHkoc2NyYXRjaC5kZWx0YU1hdHJpeCk7CiAgICBzY3JhdGNoLmxvY2FsTWF0cml4LmNvcHkoc2NyYXRjaC5wYXJlbnRJbnZlcnNlKS5tdWx0aXBseShzY3JhdGNoLndvcmxkTWF0cml4KTsKICAgIHNjcmF0Y2gubG9jYWxNYXRyaXguZGVjb21wb3NlKHNvbGlkLnBvc2l0aW9uLCBzb2xpZC5xdWF0ZXJuaW9uLCBzb2xpZC5zY2FsZSk7CiAgICBzb2xpZC51cGRhdGVNYXRyaXhXb3JsZD8uKHRydWUpOwogICAgdGhpcy5fc3luY1Byb3h5R3JvdXBUcmFuc2Zvcm0oc29saWQpOwogIH0KCiAgX3RyYW5zbGF0ZVNvbGlkQWxvbmdXb3JsZEF4aXMoc29saWQsIGF4aXNTdGFydCwgYXhpc0VuZCwgZGlzdGFuY2UpIHsKICAgIGNvbnN0IHBhcmVudCA9IHNvbGlkLnBhcmVudCB8fCB0aGlzLnZpZXdlcj8uc2NlbmUgfHwgbnVsbDsKICAgIGNvbnN0IHNjcmF0Y2ggPSB0aGlzLl9zY3JhdGNoOwogICAgc2NyYXRjaC5heGlzLmNvcHkoYXhpc0VuZCkuc3ViKGF4aXNTdGFydCkubm9ybWFsaXplKCk7CiAgICBzY3JhdGNoLnRyYW5zbGF0aW9uLmNvcHkoc2NyYXRjaC5heGlzKS5tdWx0aXBseVNjYWxhcihkaXN0YW5jZSk7CiAgICBzY3JhdGNoLnBhcmVudFdvcmxkTWF0cml4LmNvcHkocGFyZW50Py5tYXRyaXhXb3JsZCB8fCBuZXcgVEhSRUUuTWF0cml4NCgpKTsKICAgIHNjcmF0Y2gucGFyZW50SW52ZXJzZS5jb3B5KHNjcmF0Y2gucGFyZW50V29ybGRNYXRyaXgpLmludmVydCgpOwogICAgc2NyYXRjaC53b3JsZE1hdHJpeC5jb3B5KHNvbGlkLm1hdHJpeFdvcmxkKTsKICAgIHNjcmF0Y2guZGVsdGFNYXRyaXgubWFrZVRyYW5zbGF0aW9uKHNjcmF0Y2gudHJhbnNsYXRpb24ueCwgc2NyYXRjaC50cmFuc2xhdGlvbi55LCBzY3JhdGNoLnRyYW5zbGF0aW9uLnopOwogICAgc2NyYXRjaC53b3JsZE1hdHJpeC5wcmVtdWx0aXBseShzY3JhdGNoLmRlbHRhTWF0cml4KTsKICAgIHNjcmF0Y2gubG9jYWxNYXRyaXguY29weShzY3JhdGNoLnBhcmVudEludmVyc2UpLm11bHRpcGx5KHNjcmF0Y2gud29ybGRNYXRyaXgpOwogICAgc2NyYXRjaC5sb2NhbE1hdHJpeC5kZWNvbXBvc2Uoc29saWQucG9zaXRpb24sIHNvbGlkLnF1YXRlcm5pb24sIHNvbGlkLnNjYWxlKTsKICAgIHNvbGlkLnVwZGF0ZU1hdHJpeFdvcmxkPy4odHJ1ZSk7CiAgICB0aGlzLl9zeW5jUHJveHlHcm91cFRyYW5zZm9ybShzb2xpZCk7CiAgfQp9Cg==", import.meta.url).href, { SimulationWorkbenchManager: e } = await import(
|
|
304372
|
+
const A = new URL("data:text/javascript;base64,aW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnOwppbXBvcnQgeyBDb21iaW5lZFRyYW5zZm9ybUNvbnRyb2xzIH0gZnJvbSAnLi4vVUkvY29udHJvbHMvQ29tYmluZWRUcmFuc2Zvcm1Db250cm9scy5qcyc7Cgpjb25zdCBGSVhFRF9NRVRBREFUQV9LRVkgPSAnZml4ZWQnOwpjb25zdCBUUkFOU0ZPUk1fTUVUQURBVEFfS0VZID0gJ3NpbXVsYXRpb25UcmFuc2Zvcm0nOwpjb25zdCBTSU1fUFJPWFlfUFJFRklYID0gJ19fU0lNX1BST1hZX18nOwpjb25zdCBWSEFDRF9PUFRJT05TID0gT2JqZWN0LmZyZWV6ZSh7CiAgbWF4SHVsbHM6IDY0LAogIHZveGVsUmVzb2x1dGlvbjogMTAwMDAwMCwKICBtYXhWZXJ0aWNlc1Blckh1bGw6IDY0LAogIHNocmlua1dyYXA6IHRydWUsCiAgZmlsbE1vZGU6ICdmbG9vZCcsCiAgZmluZEJlc3RQbGFuZTogdHJ1ZSwKICBtaW5FZGdlTGVuZ3RoOiAxLAogIG1lc3NhZ2VzOiAnbm9uZScsCn0pOwpjb25zdCBERUZBVUxUX1RSQU5TRk9STSA9IE9iamVjdC5mcmVlemUoewogIHBvc2l0aW9uOiBbMCwgMCwgMF0sCiAgcm90YXRpb25FdWxlcjogWzAsIDAsIDBdLAp9KTsKCmZ1bmN0aW9uIGNsb25lVmVjMyh2YWx1ZSwgZmFsbGJhY2sgPSBbMCwgMCwgMF0pIHsKICBjb25zdCBzcmMgPSBBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlIDogZmFsbGJhY2s7CiAgcmV0dXJuIFsKICAgIE51bWJlci5pc0Zpbml0ZShOdW1iZXIoc3JjWzBdKSkgPyBOdW1iZXIoc3JjWzBdKSA6IGZhbGxiYWNrWzBdLAogICAgTnVtYmVyLmlzRmluaXRlKE51bWJlcihzcmNbMV0pKSA/IE51bWJlcihzcmNbMV0pIDogZmFsbGJhY2tbMV0sCiAgICBOdW1iZXIuaXNGaW5pdGUoTnVtYmVyKHNyY1syXSkpID8gTnVtYmVyKHNyY1syXSkgOiBmYWxsYmFja1syXSwKICBdOwp9CgpmdW5jdGlvbiBub3JtYWxpemVUZXh0KHZhbHVlLCBmYWxsYmFjayA9ICcnKSB7CiAgY29uc3QgbmV4dCA9IFN0cmluZyh2YWx1ZSA9PSBudWxsID8gJycgOiB2YWx1ZSkudHJpbSgpOwogIHJldHVybiBuZXh0IHx8IGZhbGxiYWNrOwp9CgpmdW5jdGlvbiBub3JtYWxpemVPcHRpb25hbE1vdGlvbkxpbWl0KHZhbHVlKSB7CiAgY29uc3QgbnVtZXJpYyA9IE51bWJlcih2YWx1ZSk7CiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUobnVtZXJpYykpIHJldHVybiBudWxsOwogIHJldHVybiBNYXRoLmFicyhudW1lcmljKSA8PSAxZS05ID8gbnVsbCA6IG51bWVyaWM7Cn0KCmZ1bmN0aW9uIG5vcm1hbGl6ZVRyYW5zZm9ybSh2YWx1ZSkgewogIGNvbnN0IHJhdyA9IHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgPyB2YWx1ZSA6IHt9OwogIHJldHVybiB7CiAgICBwb3NpdGlvbjogY2xvbmVWZWMzKHJhdy5wb3NpdGlvbiwgREVGQVVMVF9UUkFOU0ZPUk0ucG9zaXRpb24pLAogICAgcm90YXRpb25FdWxlcjogY2xvbmVWZWMzKHJhdy5yb3RhdGlvbkV1bGVyLCBERUZBVUxUX1RSQU5TRk9STS5yb3RhdGlvbkV1bGVyKSwKICB9Owp9CgpmdW5jdGlvbiB0cmFuc2Zvcm1Jc0lkZW50aXR5KHRyYW5zZm9ybSkgewogIGNvbnN0IHBvc2l0aW9uID0gY2xvbmVWZWMzKHRyYW5zZm9ybT8ucG9zaXRpb24sIERFRkFVTFRfVFJBTlNGT1JNLnBvc2l0aW9uKTsKICBjb25zdCByb3RhdGlvbkV1bGVyID0gY2xvbmVWZWMzKHRyYW5zZm9ybT8ucm90YXRpb25FdWxlciwgREVGQVVMVF9UUkFOU0ZPUk0ucm90YXRpb25FdWxlcik7CiAgcmV0dXJuIHBvc2l0aW9uLmV2ZXJ5KCh2YWx1ZSkgPT4gTWF0aC5hYnModmFsdWUpIDw9IDFlLTkpCiAgICAmJiByb3RhdGlvbkV1bGVyLmV2ZXJ5KCh2YWx1ZSkgPT4gTWF0aC5hYnModmFsdWUpIDw9IDFlLTkpOwp9CgpmdW5jdGlvbiBjb3B5TG9jYWxQb3NlKG9iamVjdCkgewogIHJldHVybiB7CiAgICBwb3NpdGlvbjogb2JqZWN0LnBvc2l0aW9uLmNsb25lKCksCiAgICBxdWF0ZXJuaW9uOiBvYmplY3QucXVhdGVybmlvbi5jbG9uZSgpLAogICAgc2NhbGU6IG9iamVjdC5zY2FsZS5jbG9uZSgpLAogIH07Cn0KCmZ1bmN0aW9uIGJ1aWxkTG9jYWxNYXRyaXgocG9zZSkgewogIHJldHVybiBuZXcgVEhSRUUuTWF0cml4NCgpLmNvbXBvc2UoCiAgICBwb3NlLnBvc2l0aW9uLmNsb25lKCksCiAgICBwb3NlLnF1YXRlcm5pb24uY2xvbmUoKSwKICAgIHBvc2Uuc2NhbGUuY2xvbmUoKSwKICApOwp9CgpmdW5jdGlvbiBwb3NlVG9PZmZzZXQoYmFzZVBvc2UsIGN1cnJlbnRPYmplY3QpIHsKICBjb25zdCBiYXNlTWF0cml4ID0gYnVpbGRMb2NhbE1hdHJpeChiYXNlUG9zZSk7CiAgY29uc3QgY3VycmVudE1hdHJpeCA9IG5ldyBUSFJFRS5NYXRyaXg0KCkuY29tcG9zZSgKICAgIGN1cnJlbnRPYmplY3QucG9zaXRpb24uY2xvbmUoKSwKICAgIGN1cnJlbnRPYmplY3QucXVhdGVybmlvbi5jbG9uZSgpLAogICAgY3VycmVudE9iamVjdC5zY2FsZS5jbG9uZSgpLAogICk7CiAgY29uc3QgcmVsYXRpdmUgPSBuZXcgVEhSRUUuTWF0cml4NCgpLmNvcHkoYmFzZU1hdHJpeCkuaW52ZXJ0KCkubXVsdGlwbHkoY3VycmVudE1hdHJpeCk7CiAgY29uc3QgcG9zaXRpb24gPSBuZXcgVEhSRUUuVmVjdG9yMygpOwogIGNvbnN0IHF1YXRlcm5pb24gPSBuZXcgVEhSRUUuUXVhdGVybmlvbigpOwogIGNvbnN0IHNjYWxlID0gbmV3IFRIUkVFLlZlY3RvcjMoKTsKICByZWxhdGl2ZS5kZWNvbXBvc2UocG9zaXRpb24sIHF1YXRlcm5pb24sIHNjYWxlKTsKICBjb25zdCByb3RhdGlvbkV1bGVyID0gbmV3IFRIUkVFLkV1bGVyKCkuc2V0RnJvbVF1YXRlcm5pb24ocXVhdGVybmlvbiwgJ1hZWicpOwogIHJldHVybiB7CiAgICBwb3NpdGlvbjogW3Bvc2l0aW9uLngsIHBvc2l0aW9uLnksIHBvc2l0aW9uLnpdLAogICAgcm90YXRpb25FdWxlcjogW3JvdGF0aW9uRXVsZXIueCwgcm90YXRpb25FdWxlci55LCByb3RhdGlvbkV1bGVyLnpdLAogIH07Cn0KCmZ1bmN0aW9uIG5vcm1hbGl6ZU1lc2hBcnJheXMobWVzaCkgewogIGlmICghbWVzaCkgcmV0dXJuIG51bGw7CiAgY29uc3Qgc3RyaWRlID0gTWF0aC5tYXgoMywgTnVtYmVyKG1lc2gubnVtUHJvcCkgfHwgMyk7CiAgY29uc3Qgc291cmNlUG9zaXRpb25zID0gQXJyYXkuaXNBcnJheShtZXNoLnZlcnRQcm9wZXJ0aWVzKSA/IG1lc2gudmVydFByb3BlcnRpZXMgOiBBcnJheS5mcm9tKG1lc2gudmVydFByb3BlcnRpZXMgfHwgW10pOwogIGNvbnN0IHNvdXJjZUluZGljZXMgPSBBcnJheS5pc0FycmF5KG1lc2gudHJpVmVydHMpID8gbWVzaC50cmlWZXJ0cyA6IEFycmF5LmZyb20obWVzaC50cmlWZXJ0cyB8fCBbXSk7CiAgaWYgKHNvdXJjZVBvc2l0aW9ucy5sZW5ndGggPCA5IHx8IHNvdXJjZUluZGljZXMubGVuZ3RoIDwgMykgcmV0dXJuIG51bGw7CiAgY29uc3QgcG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheSgoc291cmNlUG9zaXRpb25zLmxlbmd0aCAvIHN0cmlkZSkgKiAzKTsKICBmb3IgKGxldCBzcmMgPSAwLCBkc3QgPSAwOyBzcmMgKyAyIDwgc291cmNlUG9zaXRpb25zLmxlbmd0aDsgc3JjICs9IHN0cmlkZSwgZHN0ICs9IDMpIHsKICAgIHBvc2l0aW9uc1tkc3QgKyAwXSA9IE51bWJlcihzb3VyY2VQb3NpdGlvbnNbc3JjICsgMF0pIHx8IDA7CiAgICBwb3NpdGlvbnNbZHN0ICsgMV0gPSBOdW1iZXIoc291cmNlUG9zaXRpb25zW3NyYyArIDFdKSB8fCAwOwogICAgcG9zaXRpb25zW2RzdCArIDJdID0gTnVtYmVyKHNvdXJjZVBvc2l0aW9uc1tzcmMgKyAyXSkgfHwgMDsKICB9CiAgcmV0dXJuIHsKICAgIHBvc2l0aW9ucywKICAgIGluZGljZXM6IG5ldyBVaW50MzJBcnJheShzb3VyY2VJbmRpY2VzKSwKICB9Owp9CgpmdW5jdGlvbiBidWlsZFByb3h5TWF0ZXJpYWwoYmFzZUNvbG9yLCBpbmRleCwgdG90YWwpIHsKICBjb25zdCBjb2xvciA9IG5ldyBUSFJFRS5Db2xvcihiYXNlQ29sb3IgfHwgJyM5Y2EzYWYnKTsKICBjb25zdCBoc2wgPSB7IGg6IDAsIHM6IDAsIGw6IDAgfTsKICBjb2xvci5nZXRIU0woaHNsKTsKICBjb25zdCBvZmZzZXQgPSB0b3RhbCA+IDEgPyAoaW5kZXggLyBNYXRoLm1heCgxLCB0b3RhbCkpICogMC4xOCA6IDA7CiAgY29sb3Iuc2V0SFNMKChoc2wuaCArIG9mZnNldCkgJSAxLCBNYXRoLm1pbigxLCBNYXRoLm1heCgwLjM1LCBoc2wucyB8fCAwLjU1KSksIE1hdGgubWluKDAuNzIsIE1hdGgubWF4KDAuNDIsIGhzbC5sKSkpOwogIHJldHVybiBuZXcgVEhSRUUuTWVzaFN0YW5kYXJkTWF0ZXJpYWwoewogICAgY29sb3IsCiAgICB0cmFuc3BhcmVudDogdHJ1ZSwKICAgIG9wYWNpdHk6IDAuNTUsCiAgICByb3VnaG5lc3M6IDAuNTUsCiAgICBtZXRhbG5lc3M6IDAuMDUsCiAgICBkZXB0aFdyaXRlOiB0cnVlLAogIH0pOwp9CgpmdW5jdGlvbiBkaXNwb3NlSGllcmFyY2h5KHJvb3QpIHsKICBpZiAoIXJvb3Q/LnRyYXZlcnNlKSByZXR1cm47CiAgcm9vdC50cmF2ZXJzZSgobm9kZSkgPT4gewogICAgaWYgKG5vZGU/Lmdlb21ldHJ5Py5kaXNwb3NlKSB7CiAgICAgIHRyeSB7IG5vZGUuZ2VvbWV0cnkuZGlzcG9zZSgpOyB9IGNhdGNoIHt9CiAgICB9CiAgICBpZiAoQXJyYXkuaXNBcnJheShub2RlPy5tYXRlcmlhbCkpIHsKICAgICAgZm9yIChjb25zdCBtYXRlcmlhbCBvZiBub2RlLm1hdGVyaWFsKSB7CiAgICAgICAgdHJ5IHsgbWF0ZXJpYWw/LmRpc3Bvc2U/LigpOyB9IGNhdGNoIHt9CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHRyeSB7IG5vZGU/Lm1hdGVyaWFsPy5kaXNwb3NlPy4oKTsgfSBjYXRjaCB7fQogICAgfQogIH0pOwp9CgpleHBvcnQgY2xhc3MgU2ltdWxhdGlvbldvcmtiZW5jaE1hbmFnZXIgewogIGNvbnN0cnVjdG9yKHZpZXdlcikgewogICAgdGhpcy52aWV3ZXIgPSB2aWV3ZXIgfHwgbnVsbDsKICAgIHRoaXMuX2FjdGl2ZSA9IGZhbHNlOwogICAgdGhpcy5fYmFzZUxvY2FsUG9zZSA9IG5ldyBNYXAoKTsKICAgIHRoaXMuX3J1bnRpbWVTdGF0ZSA9IG5ldyBNYXAoKTsKICAgIHRoaXMuX3NvdXJjZVZpc2liaWxpdHkgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9kZWNvbXBvc2l0aW9uQ2FjaGUgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9wcm94eUdyb3VwcyA9IG5ldyBNYXAoKTsKICAgIHRoaXMuX3RyYW5zZm9ybVNlc3Npb24gPSBudWxsOwogICAgdGhpcy5fcmFwaWVyID0gbnVsbDsKICAgIHRoaXMuX3JhcGllckxvYWRQcm9taXNlID0gbnVsbDsKICAgIHRoaXMuX3ZoYWNkID0gbnVsbDsKICAgIHRoaXMuX3ZoYWNkTG9hZFByb21pc2UgPSBudWxsOwogICAgdGhpcy5fcGh5c2ljc1dvcmxkID0gbnVsbDsKICAgIHRoaXMuX2JvZHlTdGF0ZSA9IG5ldyBNYXAoKTsKICAgIHRoaXMuX2xpc3RlbmVycyA9IG5ldyBTZXQoKTsKICAgIHRoaXMuX3JlbW92ZVN0YXRlTWFuYWdlckxpc3RlbmVyID0gbnVsbDsKICAgIHRoaXMuX2lzUGxheWluZyA9IGZhbHNlOwogICAgdGhpcy5fbW90aW9uU3RhdGUgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9tb3ZlZFNvbGlkSWRzID0gbmV3IFNldCgpOwogICAgdGhpcy5fcmFmID0gMDsKICAgIHRoaXMuX2xhc3RTdGVwVGltZSA9IDA7CiAgICB0aGlzLl9zY3JhdGNoID0gewogICAgICBwYXJlbnRJbnZlcnNlOiBuZXcgVEhSRUUuTWF0cml4NCgpLAogICAgICBwYXJlbnRXb3JsZE1hdHJpeDogbmV3IFRIUkVFLk1hdHJpeDQoKSwKICAgICAgbG9jYWxNYXRyaXg6IG5ldyBUSFJFRS5NYXRyaXg0KCksCiAgICAgIHdvcmxkTWF0cml4OiBuZXcgVEhSRUUuTWF0cml4NCgpLAogICAgICBkZWx0YU1hdHJpeDogbmV3IFRIUkVFLk1hdHJpeDQoKSwKICAgICAgd29ybGRQb3NpdGlvbjogbmV3IFRIUkVFLlZlY3RvcjMoKSwKICAgICAgbG9jYWxQb3NpdGlvbjogbmV3IFRIUkVFLlZlY3RvcjMoKSwKICAgICAgd29ybGRRdWF0ZXJuaW9uOiBuZXcgVEhSRUUuUXVhdGVybmlvbigpLAogICAgICBwYXJlbnRRdWF0ZXJuaW9uOiBuZXcgVEhSRUUuUXVhdGVybmlvbigpLAogICAgICBwYXJlbnRRdWF0ZXJuaW9uSW52ZXJzZTogbmV3IFRIUkVFLlF1YXRlcm5pb24oKSwKICAgICAgYm94OiBuZXcgVEhSRUUuQm94MygpLAogICAgICBjZW50ZXI6IG5ldyBUSFJFRS5WZWN0b3IzKCksCiAgICAgIGF4aXM6IG5ldyBUSFJFRS5WZWN0b3IzKCksCiAgICAgIHRyYW5zbGF0aW9uOiBuZXcgVEhSRUUuVmVjdG9yMygpLAogICAgICB2ZWxvY2l0eTogbmV3IFRIUkVFLlZlY3RvcjMoKSwKICAgICAgYW5ndWxhclZlbG9jaXR5OiBuZXcgVEhSRUUuVmVjdG9yMygpLAogICAgICByYWRpdXM6IG5ldyBUSFJFRS5WZWN0b3IzKCksCiAgICB9OwogICAgdGhpcy5fYmluZFN0YXRlTWFuYWdlcigpOwogIH0KCiAgZGlzcG9zZSgpIHsKICAgIGlmICh0eXBlb2YgdGhpcy5fcmVtb3ZlU3RhdGVNYW5hZ2VyTGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHsKICAgICAgdHJ5IHsgdGhpcy5fcmVtb3ZlU3RhdGVNYW5hZ2VyTGlzdGVuZXIoKTsgfSBjYXRjaCB7fQogICAgfQogICAgdGhpcy5fcmVtb3ZlU3RhdGVNYW5hZ2VyTGlzdGVuZXIgPSBudWxsOwogICAgdGhpcy5zZXRBY3RpdmUoZmFsc2UpOwogIH0KCiAgaXNBY3RpdmUoKSB7CiAgICByZXR1cm4gdGhpcy5fYWN0aXZlOwogIH0KCiAgaXNTaW11bGF0aW9uV29ya2JlbmNoQWN0aXZlKCkgewogICAgcmV0dXJuIHRoaXMudmlld2VyPy5fZ2V0QWN0aXZlV29ya2JlbmNoSWQ/LigpID09PSAnU0lNVUxBVElPTic7CiAgfQoKICBhZGRMaXN0ZW5lcihsaXN0ZW5lcikgewogICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJykgcmV0dXJuICgpID0+IHt9OwogICAgdGhpcy5fbGlzdGVuZXJzLmFkZChsaXN0ZW5lcik7CiAgICByZXR1cm4gKCkgPT4gewogICAgICB0cnkgeyB0aGlzLl9saXN0ZW5lcnMuZGVsZXRlKGxpc3RlbmVyKTsgfSBjYXRjaCB7fQogICAgfTsKICB9CgogIHJlbW92ZUxpc3RlbmVyKGxpc3RlbmVyKSB7CiAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKSByZXR1cm47CiAgICB0cnkgeyB0aGlzLl9saXN0ZW5lcnMuZGVsZXRlKGxpc3RlbmVyKTsgfSBjYXRjaCB7fQogIH0KCiAgaXNQbGF5aW5nKCkgewogICAgcmV0dXJuIHRoaXMuX2lzUGxheWluZzsKICB9CgogIHNldFBsYXlpbmcocGxheWluZykgewogICAgY29uc3QgbmV4dCA9ICEhcGxheWluZzsKICAgIGlmIChuZXh0ID09PSB0aGlzLl9pc1BsYXlpbmcpIHJldHVybiB0aGlzLl9pc1BsYXlpbmc7CiAgICB0aGlzLl9pc1BsYXlpbmcgPSBuZXh0OwogICAgaWYgKHRoaXMuX2FjdGl2ZSkgewogICAgICBpZiAobmV4dCkgewogICAgICAgIHZvaWQgdGhpcy5fcHJlcGFyZVNpbXVsYXRpb25Bc3NldHMoKS50aGVuKCgpID0+IHsKICAgICAgICAgIHRoaXMuX2Vuc3VyZVBoeXNpY3NMb29wKCk7CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fc3RvcFBoeXNpY3NMb29wKCk7CiAgICAgIH0KICAgIH0KICAgIHRoaXMuX2VtaXQoKTsKICAgIHRyeSB7IHRoaXMudmlld2VyPy5yZW5kZXI/LigpOyB9IGNhdGNoIHt9CiAgICByZXR1cm4gdGhpcy5faXNQbGF5aW5nOwogIH0KCiAgcmVzZXRTaW11bGF0aW9uU3RhdGUoKSB7CiAgICB0aGlzLl9zdG9wVHJhbnNmb3JtU2Vzc2lvbigpOwogICAgdGhpcy5fc3RvcFBoeXNpY3NMb29wKCk7CiAgICB0aGlzLl9kZXN0cm95UGh5c2ljc1dvcmxkKCk7CiAgICB0aGlzLl9pc1BsYXlpbmcgPSBmYWxzZTsKICAgIHRoaXMuX21vdmVkU29saWRJZHMuY2xlYXIoKTsKICAgIHRoaXMuX21vdGlvblN0YXRlLmNsZWFyKCk7CiAgICBmb3IgKGNvbnN0IHNvbGlkIG9mIHRoaXMuX2xpc3RTY2VuZVNvbGlkcygpKSB7CiAgICAgIHRoaXMuX3J1bnRpbWVTdGF0ZS5zZXQoc29saWQudXVpZCwgbm9ybWFsaXplVHJhbnNmb3JtKG51bGwpKTsKICAgICAgdGhpcy5zZXRTdG9yZWRUcmFuc2Zvcm0oc29saWQsIG51bGwpOwogICAgfQogICAgdGhpcy5fcmVzdG9yZUJhc2VMb2NhbFBvc2VzKCk7CiAgICBmb3IgKGNvbnN0IHNvbGlkIG9mIHRoaXMuX2xpc3RTY2VuZVNvbGlkcygpKSB7CiAgICAgIHRoaXMuX3N5bmNQcm94eUdyb3VwVHJhbnNmb3JtKHNvbGlkKTsKICAgIH0KICAgIGlmICh0aGlzLl9hY3RpdmUpIHsKICAgICAgdGhpcy5fcmVzZXRNb3Rpb25SdW50aW1lKCk7CiAgICB9CiAgICB0aGlzLl9lbWl0KCk7CiAgICB0cnkgeyB0aGlzLnZpZXdlcj8ucmVuZGVyPy4oKTsgfSBjYXRjaCB7fQogIH0KCiAgZ2V0U29saWRGaXhlZChzb2xpZCkgewogICAgaWYgKCFzb2xpZD8ubmFtZSkgcmV0dXJuIGZhbHNlOwogICAgY29uc3Qgb3duID0gdGhpcy52aWV3ZXI/LnBhcnRIaXN0b3J5Py5tZXRhZGF0YU1hbmFnZXI/LmdldE93bk1ldGFkYXRhPy4oc29saWQubmFtZSkgfHwge307CiAgICByZXR1cm4gb3duW0ZJWEVEX01FVEFEQVRBX0tFWV0gPT09IHRydWU7CiAgfQoKICBzZXRTb2xpZEZpeGVkKHNvbGlkLCBmaXhlZCkgewogICAgaWYgKCFzb2xpZD8ubmFtZSkgcmV0dXJuIGZhbHNlOwogICAgY29uc3QgbWFuYWdlciA9IHRoaXMudmlld2VyPy5wYXJ0SGlzdG9yeT8ubWV0YWRhdGFNYW5hZ2VyOwogICAgaWYgKCFtYW5hZ2VyKSByZXR1cm4gZmFsc2U7CiAgICBjb25zdCBkYXRhID0gbWFuYWdlci5nZXRPd25NZXRhZGF0YShzb2xpZC5uYW1lKTsKICAgIGlmIChmaXhlZCkgZGF0YVtGSVhFRF9NRVRBREFUQV9LRVldID0gdHJ1ZTsKICAgIGVsc2UgZGVsZXRlIGRhdGFbRklYRURfTUVUQURBVEFfS0VZXTsKICAgIG1hbmFnZXIuc2V0TWV0YWRhdGFPYmplY3Qoc29saWQubmFtZSwgZGF0YSk7CiAgICBpZiAodGhpcy5fYWN0aXZlICYmIHRoaXMuX3BoeXNpY3NXb3JsZCkgewogICAgICB2b2lkIHRoaXMuX3JlYnVpbGRQaHlzaWNzV29ybGQoKTsKICAgIH0KICAgIHJldHVybiB0cnVlOwogIH0KCiAgZ2V0U3RvcmVkVHJhbnNmb3JtKHNvbGlkKSB7CiAgICBpZiAoIXNvbGlkPy5uYW1lKSByZXR1cm4gbm9ybWFsaXplVHJhbnNmb3JtKG51bGwpOwogICAgY29uc3Qgb3duID0gdGhpcy52aWV3ZXI/LnBhcnRIaXN0b3J5Py5tZXRhZGF0YU1hbmFnZXI/LmdldE93bk1ldGFkYXRhPy4oc29saWQubmFtZSkgfHwge307CiAgICByZXR1cm4gbm9ybWFsaXplVHJhbnNmb3JtKG93bltUUkFOU0ZPUk1fTUVUQURBVEFfS0VZXSk7CiAgfQoKICBzZXRTdG9yZWRUcmFuc2Zvcm0oc29saWQsIHRyYW5zZm9ybSkgewogICAgaWYgKCFzb2xpZD8ubmFtZSkgcmV0dXJuIGZhbHNlOwogICAgY29uc3QgbWFuYWdlciA9IHRoaXMudmlld2VyPy5wYXJ0SGlzdG9yeT8ubWV0YWRhdGFNYW5hZ2VyOwogICAgaWYgKCFtYW5hZ2VyKSByZXR1cm4gZmFsc2U7CiAgICBjb25zdCBub3JtYWxpemVkID0gbm9ybWFsaXplVHJhbnNmb3JtKHRyYW5zZm9ybSk7CiAgICBjb25zdCBkYXRhID0gbWFuYWdlci5nZXRPd25NZXRhZGF0YShzb2xpZC5uYW1lKTsKICAgIGlmICh0cmFuc2Zvcm1Jc0lkZW50aXR5KG5vcm1hbGl6ZWQpKSBkZWxldGUgZGF0YVtUUkFOU0ZPUk1fTUVUQURBVEFfS0VZXTsKICAgIGVsc2UgZGF0YVtUUkFOU0ZPUk1fTUVUQURBVEFfS0VZXSA9IG5vcm1hbGl6ZWQ7CiAgICBtYW5hZ2VyLnNldE1ldGFkYXRhT2JqZWN0KHNvbGlkLm5hbWUsIGRhdGEpOwogICAgcmV0dXJuIHRydWU7CiAgfQoKICBzZXRBY3RpdmUoYWN0aXZlKSB7CiAgICBjb25zdCBuZXh0ID0gISFhY3RpdmU7CiAgICBpZiAobmV4dCA9PT0gdGhpcy5fYWN0aXZlKSB7CiAgICAgIGlmIChuZXh0KSB7CiAgICAgICAgdGhpcy5fYXBwbHlSdW50aW1lVHJhbnNmb3JtcygpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuX3Jlc3RvcmVCYXNlTG9jYWxQb3NlcygpOwogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX2FjdGl2ZSA9IG5leHQ7CiAgICBpZiAodGhpcy5fYWN0aXZlKSB7CiAgICAgIHRoaXMuX2lzUGxheWluZyA9IGZhbHNlOwogICAgICB0aGlzLl9zdG9wUGh5c2ljc0xvb3AoKTsKICAgICAgdGhpcy5fZGVzdHJveVBoeXNpY3NXb3JsZCgpOwogICAgICB0aGlzLl9jYXB0dXJlQmFzZUxvY2FsUG9zZXMoKTsKICAgICAgdGhpcy5fY2FwdHVyZVNvdXJjZVZpc2liaWxpdHkoKTsKICAgICAgdGhpcy5faHlkcmF0ZVJ1bnRpbWVTdGF0ZUZyb21NZXRhZGF0YSgpOwogICAgICB0aGlzLl9yZXNldE1vdGlvblJ1bnRpbWUoKTsKICAgICAgdGhpcy5fYXBwbHlSdW50aW1lVHJhbnNmb3JtcygpOwogICAgICB0aGlzLl9zZXRTb3VyY2VTb2xpZHNWaXNpYmxlKHRydWUpOwogICAgICB2b2lkIHRoaXMuX3ByZXBhcmVWaXN1YWxBc3NldHMoKTsKICAgICAgdGhpcy5fZW1pdCgpOwogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9zdG9wVHJhbnNmb3JtU2Vzc2lvbigpOwogICAgdGhpcy5fZGVzdHJveVBoeXNpY3NXb3JsZCgpOwogICAgdGhpcy5fc3RvcFBoeXNpY3NMb29wKCk7CiAgICB0aGlzLl9jbGVhclByb3h5R3JvdXBzKCk7CiAgICB0aGlzLl9zZXRTb3VyY2VTb2xpZHNWaXNpYmxlKHRydWUpOwogICAgdGhpcy5fcmVzdG9yZUJhc2VMb2NhbFBvc2VzKCk7CiAgICB0aGlzLl9ydW50aW1lU3RhdGUuY2xlYXIoKTsKICAgIHRoaXMuX2Jhc2VMb2NhbFBvc2UuY2xlYXIoKTsKICAgIHRoaXMuX3NvdXJjZVZpc2liaWxpdHkuY2xlYXIoKTsKICAgIHRoaXMuX2RlY29tcG9zaXRpb25DYWNoZS5jbGVhcigpOwogICAgdGhpcy5fbW90aW9uU3RhdGUuY2xlYXIoKTsKICAgIHRoaXMuX21vdmVkU29saWRJZHMuY2xlYXIoKTsKICAgIHRoaXMuX2lzUGxheWluZyA9IGZhbHNlOwogICAgdGhpcy5fZW1pdCgpOwogIH0KCiAgdG9nZ2xlU29saWRUcmFuc2Zvcm0oc29saWQpIHsKICAgIGlmICghc29saWQgfHwgc29saWQudHlwZSAhPT0gJ1NPTElEJykgcmV0dXJuOwogICAgaWYgKCF0aGlzLmlzU2ltdWxhdGlvbldvcmtiZW5jaEFjdGl2ZSgpKSByZXR1cm47CiAgICBjb25zdCBzZXNzaW9uID0gdGhpcy5fdHJhbnNmb3JtU2Vzc2lvbjsKICAgIGlmIChzZXNzaW9uICYmIHNlc3Npb24uc29saWQgPT09IHNvbGlkKSB7CiAgICAgIGNvbnN0IGN1cnJlbnRNb2RlID0gKHR5cGVvZiBzZXNzaW9uLmNvbnRyb2xzPy5nZXRNb2RlID09PSAnZnVuY3Rpb24nKQogICAgICAgID8gc2Vzc2lvbi5jb250cm9scy5nZXRNb2RlKCkKICAgICAgICA6IChzZXNzaW9uLmNvbnRyb2xzPy5tb2RlIHx8IHNlc3Npb24ubW9kZSB8fCAndHJhbnNsYXRlJyk7CiAgICAgIGlmIChjdXJyZW50TW9kZSA9PT0gJ3RyYW5zbGF0ZScpIHsKICAgICAgICB0cnkgeyBzZXNzaW9uLmNvbnRyb2xzPy5zZXRNb2RlKCdyb3RhdGUnKTsgfSBjYXRjaCB7IHNlc3Npb24uY29udHJvbHMubW9kZSA9ICdyb3RhdGUnOyB9CiAgICAgICAgc2Vzc2lvbi5tb2RlID0gJ3JvdGF0ZSc7CiAgICAgICAgdHJ5IHsgc2Vzc2lvbi5nbG9iYWxTdGF0ZT8udXBkYXRlRm9yQ2FtZXJhPy4oKTsgfSBjYXRjaCB7fQogICAgICAgIHRyeSB7IHRoaXMudmlld2VyPy5yZW5kZXI/LigpOyB9IGNhdGNoIHt9CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHRoaXMuX3N0b3BUcmFuc2Zvcm1TZXNzaW9uKCk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX3N0YXJ0VHJhbnNmb3JtU2Vzc2lvbihzb2xpZCk7CiAgfQoKICBfY2FwdHVyZUJhc2VMb2NhbFBvc2VzKCkgewogICAgZm9yIChjb25zdCBzb2xpZCBvZiB0aGlzLl9saXN0U2NlbmVTb2xpZHMoKSkgewogICAgICBpZiAoIXRoaXMuX2Jhc2VMb2NhbFBvc2UuaGFzKHNvbGlkLnV1aWQpKSB7CiAgICAgICAgdGhpcy5fYmFzZUxvY2FsUG9zZS5zZXQoc29saWQudXVpZCwgY29weUxvY2FsUG9zZShzb2xpZCkpOwogICAgICB9CiAgICB9CiAgfQoKICBfY2FwdHVyZVNvdXJjZVZpc2liaWxpdHkoKSB7CiAgICBmb3IgKGNvbnN0IHNvbGlkIG9mIHRoaXMuX2xpc3RTY2VuZVNvbGlkcygpKSB7CiAgICAgIGlmICghdGhpcy5fc291cmNlVmlzaWJpbGl0eS5oYXMoc29saWQudXVpZCkpIHsKICAgICAgICB0aGlzLl9zb3VyY2VWaXNpYmlsaXR5LnNldChzb2xpZC51dWlkLCBzb2xpZC52aXNpYmxlICE9PSBmYWxzZSk7CiAgICAgIH0KICAgIH0KICB9CgogIF9oeWRyYXRlUnVudGltZVN0YXRlRnJvbU1ldGFkYXRhKCkgewogICAgZm9yIChjb25zdCBzb2xpZCBvZiB0aGlzLl9saXN0U2NlbmVTb2xpZHMoKSkgewogICAgICB0aGlzLl9ydW50aW1lU3RhdGUuc2V0KHNvbGlkLnV1aWQsIG5vcm1hbGl6ZVRyYW5zZm9ybSh0aGlzLmdldFN0b3JlZFRyYW5zZm9ybShzb2xpZCkpKTsKICAgIH0KICB9CgogIF9yZXN0b3JlQmFzZUxvY2FsUG9zZXMoKSB7CiAgICBmb3IgKGNvbnN0IHNvbGlkIG9mIHRoaXMuX2xpc3RTY2VuZVNvbGlkcygpKSB7CiAgICAgIGNvbnN0IGJhc2UgPSB0aGlzLl9iYXNlTG9jYWxQb3NlLmdldChzb2xpZC51dWlkKTsKICAgICAgaWYgKCFiYXNlKSBjb250aW51ZTsKICAgICAgc29saWQucG9zaXRpb24uY29weShiYXNlLnBvc2l0aW9uKTsKICAgICAgc29saWQucXVhdGVybmlvbi5jb3B5KGJhc2UucXVhdGVybmlvbik7CiAgICAgIHNvbGlkLnNjYWxlLmNvcHkoYmFzZS5zY2FsZSk7CiAgICAgIHNvbGlkLnVwZGF0ZU1hdHJpeFdvcmxkPy4odHJ1ZSk7CiAgICB9CiAgICB0cnkgeyB0aGlzLnZpZXdlcj8ucmVuZGVyPy4oKTsgfSBjYXRjaCB7fQogIH0KCiAgX2FwcGx5UnVudGltZVRyYW5zZm9ybXMoKSB7CiAgICB0aGlzLl9jYXB0dXJlQmFzZUxvY2FsUG9zZXMoKTsKICAgIGZvciAoY29uc3Qgc29saWQgb2YgdGhpcy5fbGlzdFNjZW5lU29saWRzKCkpIHsKICAgICAgdGhpcy5fYXBwbHlSdW50aW1lVHJhbnNmb3JtVG9Tb2xpZChzb2xpZCk7CiAgICB9CiAgICB0cnkgeyB0aGlzLnZpZXdlcj8ucmVuZGVyPy4oKTsgfSBjYXRjaCB7fQogIH0KCiAgX2FwcGx5UnVudGltZVRyYW5zZm9ybVRvU29saWQoc29saWQpIHsKICAgIGNvbnN0IGJhc2UgPSB0aGlzLl9iYXNlTG9jYWxQb3NlLmdldChzb2xpZC51dWlkKTsKICAgIGlmICghYmFzZSkgcmV0dXJuOwogICAgY29uc3QgcnVudGltZSA9IG5vcm1hbGl6ZVRyYW5zZm9ybSh0aGlzLl9ydW50aW1lU3RhdGUuZ2V0KHNvbGlkLnV1aWQpKTsKICAgIGNvbnN0IG9mZnNldFF1YXRlcm5pb24gPSBuZXcgVEhSRUUuUXVhdGVybmlvbigpLnNldEZyb21FdWxlcigKICAgICAgbmV3IFRIUkVFLkV1bGVyKC4uLnJ1bnRpbWUucm90YXRpb25FdWxlciwgJ1hZWicpLAogICAgKTsKICAgIGNvbnN0IG5leHRNYXRyaXggPSBidWlsZExvY2FsTWF0cml4KGJhc2UpLm11bHRpcGx5KAogICAgICBuZXcgVEhSRUUuTWF0cml4NCgpLmNvbXBvc2UoCiAgICAgICAgbmV3IFRIUkVFLlZlY3RvcjMoLi4ucnVudGltZS5wb3NpdGlvbiksCiAgICAgICAgb2Zmc2V0UXVhdGVybmlvbiwKICAgICAgICBuZXcgVEhSRUUuVmVjdG9yMygxLCAxLCAxKSwKICAgICAgKSwKICAgICk7CiAgICBuZXh0TWF0cml4LmRlY29tcG9zZShzb2xpZC5wb3NpdGlvbiwgc29saWQucXVhdGVybmlvbiwgc29saWQuc2NhbGUpOwogICAgc29saWQudXBkYXRlTWF0cml4V29ybGQ/Lih0cnVlKTsKICAgIHRoaXMuX3N5bmNQcm94eUdyb3VwVHJhbnNmb3JtKHNvbGlkKTsKICB9CgogIF91cGRhdGVSdW50aW1lVHJhbnNmb3JtRnJvbVNvbGlkKHNvbGlkLCB7IHBlcnNpc3QgPSBmYWxzZSB9ID0ge30pIHsKICAgIGNvbnN0IGJhc2UgPSB0aGlzLl9iYXNlTG9jYWxQb3NlLmdldChzb2xpZC51dWlkKTsKICAgIGlmICghYmFzZSkgcmV0dXJuOwogICAgY29uc3Qgb2Zmc2V0ID0gbm9ybWFsaXplVHJhbnNmb3JtKHBvc2VUb09mZnNldChiYXNlLCBzb2xpZCkpOwogICAgdGhpcy5fcnVudGltZVN0YXRlLnNldChzb2xpZC51dWlkLCBvZmZzZXQpOwogICAgaWYgKHBlcnNpc3QpIHsKICAgICAgdGhpcy5zZXRTdG9yZWRUcmFuc2Zvcm0oc29saWQsIG9mZnNldCk7CiAgICAgIHRoaXMudmlld2VyPy5wYXJ0SGlzdG9yeT8ucXVldWVIaXN0b3J5U25hcHNob3Q/Lih7IGRlYm91bmNlTXM6IDAsIHJlYXNvbjogJ3NpbXVsYXRpb24tdHJhbnNmb3JtJyB9KTsKICAgIH0KICAgIHRoaXMuX3N5bmNQcm94eUdyb3VwVHJhbnNmb3JtKHNvbGlkKTsKICB9CgogIGFzeW5jIF9wcmVwYXJlU2ltdWxhdGlvbkFzc2V0cygpIHsKICAgIGlmICghdGhpcy5fYWN0aXZlKSByZXR1cm47CiAgICB0cnkgewogICAgICBhd2FpdCBQcm9taXNlLmFsbCh0aGlzLl9saXN0U2NlbmVTb2xpZHMoKS5tYXAoKHNvbGlkKSA9PiB0aGlzLl9lbnN1cmVEZWNvbXBvc2l0aW9uKHNvbGlkKSkpOwogICAgICB0aGlzLl9idWlsZFByb3h5R3JvdXBzKCk7CiAgICAgIGF3YWl0IHRoaXMuX3JlYnVpbGRQaHlzaWNzV29ybGQoKTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIGNvbnNvbGUud2FybignW1NpbXVsYXRpb25Xb3JrYmVuY2hdIEZhaWxlZCB0byBwcmVwYXJlIHNpbXVsYXRpb24gYXNzZXRzOicsIGVycm9yKTsKICAgIH0KICB9CgogIGFzeW5jIF9wcmVwYXJlVmlzdWFsQXNzZXRzKCkgewogICAgaWYgKCF0aGlzLl9hY3RpdmUpIHJldHVybjsKICAgIHRyeSB7CiAgICAgIGF3YWl0IFByb21pc2UuYWxsKHRoaXMuX2xpc3RTY2VuZVNvbGlkcygpLm1hcCgoc29saWQpID0+IHRoaXMuX2Vuc3VyZURlY29tcG9zaXRpb24oc29saWQpKSk7CiAgICAgIHRoaXMuX2J1aWxkUHJveHlHcm91cHMoKTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIGNvbnNvbGUud2FybignW1NpbXVsYXRpb25Xb3JrYmVuY2hdIEZhaWxlZCB0byBwcmVwYXJlIHNpbXVsYXRpb24gdmlzdWFsczonLCBlcnJvcik7CiAgICB9CiAgfQoKICBhc3luYyBfbG9hZFJhcGllcigpIHsKICAgIGlmICh0aGlzLl9yYXBpZXIpIHJldHVybiB0aGlzLl9yYXBpZXI7CiAgICBpZiAoIXRoaXMuX3JhcGllckxvYWRQcm9taXNlKSB7CiAgICAgIHRoaXMuX3JhcGllckxvYWRQcm9taXNlID0gaW1wb3J0KCdAZGltZm9yZ2UvcmFwaWVyM2QvcmFwaWVyLmpzJykKICAgICAgICAudGhlbigobW9kdWxlKSA9PiBtb2R1bGU/LmRlZmF1bHQgfHwgbW9kdWxlKQogICAgICAgIC50aGVuKChyYXBpZXIpID0+IHsKICAgICAgICAgIHRoaXMuX3JhcGllciA9IHJhcGllcjsKICAgICAgICAgIHJldHVybiByYXBpZXI7CiAgICAgICAgfSkKICAgICAgICAuY2F0Y2goKGVycm9yKSA9PiB7CiAgICAgICAgICB0aGlzLl9yYXBpZXJMb2FkUHJvbWlzZSA9IG51bGw7CiAgICAgICAgICB0aHJvdyBlcnJvcjsKICAgICAgICB9KTsKICAgIH0KICAgIHJldHVybiB0aGlzLl9yYXBpZXJMb2FkUHJvbWlzZTsKICB9CgogIGFzeW5jIF9sb2FkVmhhY2QoKSB7CiAgICBpZiAodGhpcy5fdmhhY2QpIHJldHVybiB0aGlzLl92aGFjZDsKICAgIGlmICghdGhpcy5fdmhhY2RMb2FkUHJvbWlzZSkgewogICAgICB0aGlzLl92aGFjZExvYWRQcm9taXNlID0gaW1wb3J0KCd2aGFjZC1qcy9saWIvdmhhY2QuanMnKQogICAgICAgIC50aGVuKChtb2R1bGUpID0+IG1vZHVsZT8uQ29udmV4TWVzaERlY29tcG9zaXRpb24/LmNyZWF0ZT8uKCkpCiAgICAgICAgLnRoZW4oKGluc3RhbmNlKSA9PiB7CiAgICAgICAgICB0aGlzLl92aGFjZCA9IGluc3RhbmNlIHx8IG51bGw7CiAgICAgICAgICByZXR1cm4gdGhpcy5fdmhhY2Q7CiAgICAgICAgfSkKICAgICAgICAuY2F0Y2goKGVycm9yKSA9PiB7CiAgICAgICAgICB0aGlzLl92aGFjZExvYWRQcm9taXNlID0gbnVsbDsKICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIHRoaXMuX3ZoYWNkTG9hZFByb21pc2U7CiAgfQoKICBhc3luYyBfZW5zdXJlRGVjb21wb3NpdGlvbihzb2xpZCkgewogICAgaWYgKCFzb2xpZD8udXVpZCkgcmV0dXJuIFtdOwogICAgY29uc3QgY2FjaGVkID0gdGhpcy5fZGVjb21wb3NpdGlvbkNhY2hlLmdldChzb2xpZC51dWlkKTsKICAgIGlmIChjYWNoZWQpIHJldHVybiBjYWNoZWQuaHVsbHM7CiAgICBjb25zdCByYXdNZXNoID0gdGhpcy5fZXh0cmFjdFNvbGlkTWVzaChzb2xpZCk7CiAgICBpZiAoIXJhd01lc2gpIHsKICAgICAgdGhpcy5fZGVjb21wb3NpdGlvbkNhY2hlLnNldChzb2xpZC51dWlkLCB7IGh1bGxzOiBbXSB9KTsKICAgICAgcmV0dXJuIFtdOwogICAgfQogICAgbGV0IGh1bGxzID0gW107CiAgICB0cnkgewogICAgICBjb25zdCB2aGFjZCA9IGF3YWl0IHRoaXMuX2xvYWRWaGFjZCgpOwogICAgICBpZiAodmhhY2Q/LmNvbXB1dGVDb252ZXhIdWxscykgewogICAgICAgIGh1bGxzID0gdmhhY2QuY29tcHV0ZUNvbnZleEh1bGxzKHJhd01lc2gsIFZIQUNEX09QVElPTlMpIHx8IFtdOwogICAgICB9CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgICBjb25zb2xlLndhcm4oJ1tTaW11bGF0aW9uV29ya2JlbmNoXSBGYWlsZWQgdG8gZGVjb21wb3NlIG1lc2ggd2l0aCB2aGFjZC1qczonLCBlcnJvcik7CiAgICB9CiAgICBpZiAoIUFycmF5LmlzQXJyYXkoaHVsbHMpIHx8IGh1bGxzLmxlbmd0aCA9PT0gMCkgewogICAgICBodWxscyA9IFtyYXdNZXNoXTsKICAgIH0KICAgIHRoaXMuX2RlY29tcG9zaXRpb25DYWNoZS5zZXQoc29saWQudXVpZCwgeyBodWxscyB9KTsKICAgIHJldHVybiBodWxsczsKICB9CgogIF9leHRyYWN0U29saWRNZXNoKHNvbGlkKSB7CiAgICBsZXQgbWVzaCA9IG51bGw7CiAgICB0cnkgewogICAgICBtZXNoID0gc29saWQuZ2V0TWVzaD8uKCk7CiAgICAgIHJldHVybiBub3JtYWxpemVNZXNoQXJyYXlzKG1lc2gpOwogICAgfSBjYXRjaCB7CiAgICAgIHJldHVybiBudWxsOwogICAgfSBmaW5hbGx5IHsKICAgICAgdHJ5IHsgaWYgKG1lc2ggJiYgdHlwZW9mIG1lc2guZGVsZXRlID09PSAnZnVuY3Rpb24nKSBtZXNoLmRlbGV0ZSgpOyB9IGNhdGNoIHt9CiAgICB9CiAgfQoKICBfYnVpbGRQcm94eUdyb3VwcygpIHsKICAgIHRoaXMuX2NsZWFyUHJveHlHcm91cHMoKTsKICAgIGZvciAoY29uc3Qgc29saWQgb2YgdGhpcy5fbGlzdFNjZW5lU29saWRzKCkpIHsKICAgICAgY29uc3QgcmVjb3JkID0gdGhpcy5fZGVjb21wb3NpdGlvbkNhY2hlLmdldChzb2xpZC51dWlkKTsKICAgICAgY29uc3QgaHVsbHMgPSBBcnJheS5pc0FycmF5KHJlY29yZD8uaHVsbHMpID8gcmVjb3JkLmh1bGxzIDogW107CiAgICAgIGNvbnN0IGdyb3VwID0gdGhpcy5fY3JlYXRlUHJveHlHcm91cChzb2xpZCwgaHVsbHMpOwogICAgICBpZiAoIWdyb3VwKSBjb250aW51ZTsKICAgICAgdGhpcy5fcHJveHlHcm91cHMuc2V0KHNvbGlkLnV1aWQsIGdyb3VwKTsKICAgICAgdGhpcy5fc3luY1Byb3h5R3JvdXBUcmFuc2Zvcm0oc29saWQpOwogICAgICB0cnkgeyB0aGlzLnZpZXdlcj8ucmVuZGVyPy4oKTsgfSBjYXRjaCB7fQogICAgfQogIH0KCiAgX2NyZWF0ZVByb3h5R3JvdXAoc29saWQsIGh1bGxzKSB7CiAgICBjb25zdCBwYXJlbnQgPSBzb2xpZC5wYXJlbnQgfHwgdGhpcy52aWV3ZXI/LnNjZW5lIHx8IG51bGw7CiAgICBpZiAoIXBhcmVudD8uYWRkIHx8ICFBcnJheS5pc0FycmF5KGh1bGxzKSB8fCBodWxscy5sZW5ndGggPT09IDApIHJldHVybiBudWxsOwogICAgY29uc3QgZ3JvdXAgPSBuZXcgVEhSRUUuR3JvdXAoKTsKICAgIGdyb3VwLm5hbWUgPSBgJHtTSU1fUFJPWFlfUFJFRklYfToke3NvbGlkLm5hbWUgfHwgc29saWQudXVpZCB8fCAnJ31gOwogICAgZ3JvdXAudXNlckRhdGEuZXhjbHVkZUZyb21GaXQgPSBmYWxzZTsKICAgIGdyb3VwLnVzZXJEYXRhLnNpbXVsYXRpb25Qcm94eSA9IHRydWU7CiAgICBncm91cC52aXNpYmxlID0gZmFsc2U7CiAgICBjb25zdCBtZXRhZGF0YUNvbG9yID0gdGhpcy52aWV3ZXI/LnBhcnRIaXN0b3J5Py5tZXRhZGF0YU1hbmFnZXI/LmdldE1ldGFkYXRhPy4oc29saWQubmFtZSB8fCAnJyk/LmNvbG9yIHx8IG51bGw7CiAgICBodWxscy5mb3JFYWNoKChodWxsLCBpbmRleCkgPT4gewogICAgICBjb25zdCBnZW9tZXRyeSA9IG5ldyBUSFJFRS5CdWZmZXJHZW9tZXRyeSgpOwogICAgICBnZW9tZXRyeS5zZXRBdHRyaWJ1dGUoJ3Bvc2l0aW9uJywgbmV3IFRIUkVFLkZsb2F0MzJCdWZmZXJBdHRyaWJ1dGUoQXJyYXkuZnJvbShodWxsLnBvc2l0aW9ucyB8fCBbXSksIDMpKTsKICAgICAgZ2VvbWV0cnkuc2V0SW5kZXgoQXJyYXkuZnJvbShodWxsLmluZGljZXMgfHwgW10pKTsKICAgICAgZ2VvbWV0cnkuY29tcHV0ZVZlcnRleE5vcm1hbHMoKTsKICAgICAgY29uc3QgbWVzaCA9IG5ldyBUSFJFRS5NZXNoKGdlb21ldHJ5LCBidWlsZFByb3h5TWF0ZXJpYWwobWV0YWRhdGFDb2xvciwgaW5kZXgsIGh1bGxzLmxlbmd0aCkpOwogICAgICBtZXNoLnVzZXJEYXRhLmV4Y2x1ZGVGcm9tRml0ID0gZmFsc2U7CiAgICAgIG1lc2gudXNlckRhdGEuc2ltdWxhdGlvblByb3h5ID0gdHJ1ZTsKICAgICAgbWVzaC51c2VyRGF0YS5zb3VyY2VTb2xpZFV1aWQgPSBzb2xpZC51dWlkOwogICAgICBncm91cC5hZGQobWVzaCk7CgogICAgICBjb25zdCBlZGdlcyA9IG5ldyBUSFJFRS5MaW5lU2VnbWVudHMoCiAgICAgICAgbmV3IFRIUkVFLkVkZ2VzR2VvbWV0cnkoZ2VvbWV0cnksIDIwKSwKICAgICAgICBuZXcgVEhSRUUuTGluZUJhc2ljTWF0ZXJpYWwoeyBjb2xvcjogMHgyMmQzZWUsIHRyYW5zcGFyZW50OiB0cnVlLCBvcGFjaXR5OiAwLjkgfSksCiAgICAgICk7CiAgICAgIGVkZ2VzLnVzZXJEYXRhLmV4Y2x1ZGVGcm9tRml0ID0gZmFsc2U7CiAgICAgIGVkZ2VzLnVzZXJEYXRhLnNpbXVsYXRpb25Qcm94eSA9IHRydWU7CiAgICAgIGdyb3VwLmFkZChlZGdlcyk7CiAgICB9KTsKICAgIHBhcmVudC5hZGQoZ3JvdXApOwogICAgcmV0dXJuIGdyb3VwOwogIH0KCiAgX3N5bmNQcm94eUdyb3VwVHJhbnNmb3JtKHNvbGlkKSB7CiAgICBjb25zdCBncm91cCA9IHRoaXMuX3Byb3h5R3JvdXBzLmdldChzb2xpZC51dWlkKTsKICAgIGlmICghZ3JvdXApIHJldHVybjsKICAgIGdyb3VwLnBvc2l0aW9uLmNvcHkoc29saWQucG9zaXRpb24pOwogICAgZ3JvdXAucXVhdGVybmlvbi5jb3B5KHNvbGlkLnF1YXRlcm5pb24pOwogICAgZ3JvdXAuc2NhbGUuY29weShzb2xpZC5zY2FsZSk7CiAgICBncm91cC52aXNpYmxlID0gZmFsc2U7CiAgICBncm91cC51cGRhdGVNYXRyaXhXb3JsZD8uKHRydWUpOwogIH0KCiAgX2NsZWFyUHJveHlHcm91cHMoKSB7CiAgICBmb3IgKGNvbnN0IGdyb3VwIG9mIHRoaXMuX3Byb3h5R3JvdXBzLnZhbHVlcygpKSB7CiAgICAgIHRyeSB7IGdyb3VwLnBhcmVudD8ucmVtb3ZlPy4oZ3JvdXApOyB9IGNhdGNoIHt9CiAgICAgIGRpc3Bvc2VIaWVyYXJjaHkoZ3JvdXApOwogICAgfQogICAgdGhpcy5fcHJveHlHcm91cHMuY2xlYXIoKTsKICB9CgogIF9zZXRTb3VyY2VTb2xpZHNWaXNpYmxlKHZpc2libGUpIHsKICAgIGZvciAoY29uc3Qgc29saWQgb2YgdGhpcy5fbGlzdFNjZW5lU29saWRzKCkpIHsKICAgICAgaWYgKHZpc2libGUpIHsKICAgICAgICBzb2xpZC52aXNpYmxlID0gdGhpcy5fc291cmNlVmlzaWJpbGl0eS5nZXQoc29saWQudXVpZCkgIT09IGZhbHNlOwogICAgICB9IGVsc2UgewogICAgICAgIHNvbGlkLnZpc2libGUgPSBmYWxzZTsKICAgICAgfQogICAgfQogICAgZm9yIChjb25zdCBncm91cCBvZiB0aGlzLl9wcm94eUdyb3Vwcy52YWx1ZXMoKSkgewogICAgICBncm91cC52aXNpYmxlID0gZmFsc2U7CiAgICB9CiAgICB0cnkgeyB0aGlzLnZpZXdlcj8ucmVuZGVyPy4oKTsgfSBjYXRjaCB7fQogIH0KCiAgYXN5bmMgX3JlYnVpbGRQaHlzaWNzV29ybGQoKSB7CiAgICBpZiAoIXRoaXMuX2FjdGl2ZSkgcmV0dXJuOwogICAgY29uc3QgW3JhcGllcl0gPSBhd2FpdCBQcm9taXNlLmFsbChbCiAgICAgIHRoaXMuX2xvYWRSYXBpZXIoKSwKICAgICAgUHJvbWlzZS5hbGwodGhpcy5fbGlzdFNjZW5lU29saWRzKCkubWFwKChzb2xpZCkgPT4gdGhpcy5fZW5zdXJlRGVjb21wb3NpdGlvbihzb2xpZCkpKSwKICAgIF0pOwogICAgaWYgKCF0aGlzLl9hY3RpdmUgfHwgIXJhcGllcikgcmV0dXJuOwogICAgdGhpcy5fZGVzdHJveVBoeXNpY3NXb3JsZCgpOwogICAgdGhpcy5fYm9keVN0YXRlLmNsZWFyKCk7CiAgICBjb25zdCB3b3JsZCA9IG5ldyByYXBpZXIuV29ybGQoeyB4OiAwLCB5OiAtOS44MSwgejogMCB9KTsKICAgIHdvcmxkLm1heENjZFN1YnN0ZXBzID0gMjsKICAgIHRoaXMuX3BoeXNpY3NXb3JsZCA9IHdvcmxkOwogICAgY29uc3Qgc2VsZWN0ZWRTb2xpZCA9IHRoaXMuX3RyYW5zZm9ybVNlc3Npb24/LnNvbGlkIHx8IG51bGw7CiAgICBmb3IgKGNvbnN0IHNvbGlkIG9mIHRoaXMuX2xpc3RTY2VuZVNvbGlkcygpKSB7CiAgICAgIGNvbnN0IGJvZHlEZXNjID0gKHNlbGVjdGVkU29saWQgJiYgc29saWQgPT09IHNlbGVjdGVkU29saWQpCiAgICAgICAgPyByYXBpZXIuUmlnaWRCb2R5RGVzYy5raW5lbWF0aWNQb3NpdGlvbkJhc2VkKCkKICAgICAgICA6ICh0aGlzLl9pc1NvbGlkS2luZW1hdGljTW90aW9uRHJpdmVuKHNvbGlkKQogICAgICAgICAgPyByYXBpZXIuUmlnaWRCb2R5RGVzYy5raW5lbWF0aWNQb3NpdGlvbkJhc2VkKCkKICAgICAgICAgIDogKHRoaXMuZ2V0U29saWRGaXhlZChzb2xpZCkgPyByYXBpZXIuUmlnaWRCb2R5RGVzYy5maXhlZCgpIDogcmFwaWVyLlJpZ2lkQm9keURlc2MuZHluYW1pYygpKSk7CiAgICAgIGNvbnN0IHBvc2l0aW9uID0gc29saWQuZ2V0V29ybGRQb3NpdGlvbihuZXcgVEhSRUUuVmVjdG9yMygpKTsKICAgICAgY29uc3QgcXVhdGVybmlvbiA9IHNvbGlkLmdldFdvcmxkUXVhdGVybmlvbihuZXcgVEhSRUUuUXVhdGVybmlvbigpKTsKICAgICAgYm9keURlc2Muc2V0VHJhbnNsYXRpb24ocG9zaXRpb24ueCwgcG9zaXRpb24ueSwgcG9zaXRpb24ueik7CiAgICAgIGJvZHlEZXNjLnNldFJvdGF0aW9uKHsgeDogcXVhdGVybmlvbi54LCB5OiBxdWF0ZXJuaW9uLnksIHo6IHF1YXRlcm5pb24ueiwgdzogcXVhdGVybmlvbi53IH0pOwogICAgICBib2R5RGVzYy5zZXRMaW5lYXJEYW1waW5nKDIuNSk7CiAgICAgIGJvZHlEZXNjLnNldEFuZ3VsYXJEYW1waW5nKDIuNSk7CiAgICAgIGJvZHlEZXNjLnNldENjZEVuYWJsZWQodHJ1ZSk7CiAgICAgIGNvbnN0IGJvZHkgPSB3b3JsZC5jcmVhdGVSaWdpZEJvZHkoYm9keURlc2MpOwogICAgICBjb25zdCBodWxscyA9IHRoaXMuX2RlY29tcG9zaXRpb25DYWNoZS5nZXQoc29saWQudXVpZCk/Lmh1bGxzIHx8IFtdOwogICAgICBmb3IgKGNvbnN0IGh1bGwgb2YgaHVsbHMpIHsKICAgICAgICBjb25zdCBjb2xsaWRlciA9IHRoaXMuX2NyZWF0ZUNvbGxpZGVyRm9ySHVsbChyYXBpZXIsIGh1bGwpOwogICAgICAgIGlmICghY29sbGlkZXIpIGNvbnRpbnVlOwogICAgICAgIGNvbGxpZGVyLnNldFJlc3RpdHV0aW9uKDAuMDUpOwogICAgICAgIGNvbGxpZGVyLnNldEZyaWN0aW9uKDAuOSk7CiAgICAgICAgd29ybGQuY3JlYXRlQ29sbGlkZXIoY29sbGlkZXIsIGJvZHkpOwogICAgICB9CiAgICAgIHRoaXMuX2JvZHlTdGF0ZS5zZXQoc29saWQudXVpZCwgewogICAgICAgIHNvbGlkLAogICAgICAgIGJvZHksCiAgICAgICAgcHJveHlHcm91cDogdGhpcy5fcHJveHlHcm91cHMuZ2V0KHNvbGlkLnV1aWQpIHx8IG51bGwsCiAgICAgIH0pOwogICAgfQogIH0KCiAgX2Rlc3Ryb3lQaHlzaWNzV29ybGQoKSB7CiAgICB0cnkgeyB0aGlzLl9waHlzaWNzV29ybGQ/LmZyZWU/LigpOyB9IGNhdGNoIHt9CiAgICB0aGlzLl9waHlzaWNzV29ybGQgPSBudWxsOwogICAgdGhpcy5fYm9keVN0YXRlLmNsZWFyKCk7CiAgfQoKICBfY3JlYXRlQ29sbGlkZXJGb3JIdWxsKHJhcGllciwgaHVsbCkgewogICAgY29uc3QgcG9zaXRpb25zID0gaHVsbD8ucG9zaXRpb25zID8gbmV3IEZsb2F0MzJBcnJheShodWxsLnBvc2l0aW9ucykgOiBudWxsOwogICAgY29uc3QgaW5kaWNlcyA9IGh1bGw/LmluZGljZXMgPyBuZXcgVWludDMyQXJyYXkoaHVsbC5pbmRpY2VzKSA6IG51bGw7CiAgICBpZiAoIXBvc2l0aW9ucyB8fCBwb3NpdGlvbnMubGVuZ3RoIDwgOSB8fCAhaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA8IDMpIHJldHVybiBudWxsOwogICAgY29uc3QgY29sbGlkZXIgPSByYXBpZXIuQ29sbGlkZXJEZXNjLmNvbnZleE1lc2gocG9zaXRpb25zLCBpbmRpY2VzKTsKICAgIGlmIChjb2xsaWRlcikgcmV0dXJuIGNvbGxpZGVyOwogICAgcmV0dXJuIHJhcGllci5Db2xsaWRlckRlc2MuY29udmV4SHVsbChwb3NpdGlvbnMpOwogIH0KCiAgX2Vuc3VyZVBoeXNpY3NMb29wKCkgewogICAgaWYgKHRoaXMuX3JhZikgcmV0dXJuOwogICAgdGhpcy5fbGFzdFN0ZXBUaW1lID0gMDsKICAgIGNvbnN0IHN0ZXAgPSAodHMpID0+IHsKICAgICAgdGhpcy5fcmFmID0gMDsKICAgICAgaWYgKCF0aGlzLl9hY3RpdmUpIHJldHVybjsKICAgICAgdGhpcy5fc3RlcFBoeXNpY3ModHMpOwogICAgICB0aGlzLl9yYWYgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoc3RlcCk7CiAgICB9OwogICAgdGhpcy5fcmFmID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHN0ZXApOwogIH0KCiAgX3N0b3BQaHlzaWNzTG9vcCgpIHsKICAgIGlmICh0aGlzLl9yYWYpIHsKICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5fcmFmKTsKICAgICAgdGhpcy5fcmFmID0gMDsKICAgIH0KICAgIHRoaXMuX2xhc3RTdGVwVGltZSA9IDA7CiAgfQoKICBfc3RlcFBoeXNpY3ModGltZXN0YW1wKSB7CiAgICBjb25zdCB3b3JsZCA9IHRoaXMuX3BoeXNpY3NXb3JsZDsKICAgIGlmICghd29ybGQpIHJldHVybjsKICAgIGlmICghdGhpcy5faXNQbGF5aW5nKSB7CiAgICAgIHRoaXMuX2xhc3RTdGVwVGltZSA9IHRpbWVzdGFtcDsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgZHQgPSB0aGlzLl9sYXN0U3RlcFRpbWUgPiAwCiAgICAgID8gTWF0aC5taW4oMSAvIDIwLCBNYXRoLm1heCgxIC8gMjQwLCAodGltZXN0YW1wIC0gdGhpcy5fbGFzdFN0ZXBUaW1lKSAvIDEwMDApKQogICAgICA6IDEgLyA2MDsKICAgIHRoaXMuX2xhc3RTdGVwVGltZSA9IHRpbWVzdGFtcDsKICAgIHdvcmxkLnRpbWVzdGVwID0gZHQ7CgogICAgY29uc3Qgc2VsZWN0ZWRTb2xpZCA9IHRoaXMuX3RyYW5zZm9ybVNlc3Npb24/LnNvbGlkIHx8IG51bGw7CiAgICBsZXQgY2hhbmdlZCA9IGZhbHNlOwogICAgaWYgKHRoaXMuX2lzUGxheWluZykgewogICAgICBjaGFuZ2VkID0gdGhpcy5fYXBwbHlNb3Rpb25TdGVwKGR0KSB8fCBjaGFuZ2VkOwogICAgfQogICAgaWYgKHNlbGVjdGVkU29saWQpIHsKICAgICAgY29uc3QgYm9keVN0YXRlID0gdGhpcy5fYm9keVN0YXRlLmdldChzZWxlY3RlZFNvbGlkLnV1aWQpOwogICAgICBpZiAoYm9keVN0YXRlPy5ib2R5KSB7CiAgICAgICAgY29uc3Qgd29ybGRQb3NpdGlvbiA9IHNlbGVjdGVkU29saWQuZ2V0V29ybGRQb3NpdGlvbihuZXcgVEhSRUUuVmVjdG9yMygpKTsKICAgICAgICBjb25zdCB3b3JsZFF1YXRlcm5pb24gPSBzZWxlY3RlZFNvbGlkLmdldFdvcmxkUXVhdGVybmlvbihuZXcgVEhSRUUuUXVhdGVybmlvbigpKTsKICAgICAgICBib2R5U3RhdGUuYm9keS5zZXROZXh0S2luZW1hdGljVHJhbnNsYXRpb24od29ybGRQb3NpdGlvbik7CiAgICAgICAgYm9keVN0YXRlLmJvZHkuc2V0TmV4dEtpbmVtYXRpY1JvdGF0aW9uKHdvcmxkUXVhdGVybmlvbik7CiAgICAgIH0KICAgIH0KICAgIHdvcmxkLnN0ZXAoKTsKICAgIGZvciAoY29uc3QgYm9keVN0YXRlIG9mIHRoaXMuX2JvZHlTdGF0ZS52YWx1ZXMoKSkgewogICAgICBjb25zdCB7IHNvbGlkLCBib2R5IH0gPSBib2R5U3RhdGU7CiAgICAgIGlmICghc29saWQgfHwgIWJvZHkpIGNvbnRpbnVlOwogICAgICBpZiAoc2VsZWN0ZWRTb2xpZCAmJiBzb2xpZCA9PT0gc2VsZWN0ZWRTb2xpZCkgewogICAgICAgIHRoaXMuX3N5bmNQcm94eUdyb3VwVHJhbnNmb3JtKHNvbGlkKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAodGhpcy5nZXRTb2xpZEZpeGVkKHNvbGlkKSkgewogICAgICAgIHRoaXMuX3N5bmNQcm94eUdyb3VwVHJhbnNmb3JtKHNvbGlkKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB0cmFuc2xhdGlvbiA9IGJvZHkudHJhbnNsYXRpb24oKTsKICAgICAgY29uc3Qgcm90YXRpb24gPSBib2R5LnJvdGF0aW9uKCk7CiAgICAgIGlmICghdHJhbnNsYXRpb24gfHwgIXJvdGF0aW9uKSBjb250aW51ZTsKICAgICAgdGhpcy5fc2V0U29saWRXb3JsZFBvc2Uoc29saWQsIHRyYW5zbGF0aW9uLCByb3RhdGlvbik7CiAgICAgIHRoaXMuX3VwZGF0ZVJ1bnRpbWVUcmFuc2Zvcm1Gcm9tU29saWQoc29saWQsIHsgcGVyc2lzdDogZmFsc2UgfSk7CiAgICAgIHRoaXMuX21vdmVkU29saWRJZHMuYWRkKHNvbGlkLnV1aWQpOwogICAgICBjaGFuZ2VkID0gdHJ1ZTsKICAgIH0KICAgIGlmIChjaGFuZ2VkKSB7CiAgICAgIHRyeSB7IHRoaXMudmlld2VyPy5yZW5kZXI/LigpOyB9IGNhdGNoIHt9CiAgICB9CiAgfQoKICBfc2V0U29saWRXb3JsZFBvc2Uoc29saWQsIHRyYW5zbGF0aW9uLCByb3RhdGlvbikgewogICAgY29uc3QgcGFyZW50ID0gc29saWQucGFyZW50IHx8IHRoaXMudmlld2VyPy5zY2VuZSB8fCBudWxsOwogICAgY29uc3Qgc2NyYXRjaCA9IHRoaXMuX3NjcmF0Y2g7CiAgICBzY3JhdGNoLndvcmxkUG9zaXRpb24uc2V0KHRyYW5zbGF0aW9uLngsIHRyYW5zbGF0aW9uLnksIHRyYW5zbGF0aW9uLnopOwogICAgc2NyYXRjaC53b3JsZFF1YXRlcm5pb24uc2V0KHJvdGF0aW9uLngsIHJvdGF0aW9uLnksIHJvdGF0aW9uLnosIHJvdGF0aW9uLncpOwogICAgaWYgKHBhcmVudD8uaXNPYmplY3QzRCkgewogICAgICBwYXJlbnQudXBkYXRlTWF0cml4V29ybGQ/Lih0cnVlKTsKICAgICAgc2NyYXRjaC5wYXJlbnRJbnZlcnNlLmNvcHkocGFyZW50Lm1hdHJpeFdvcmxkKS5pbnZlcnQoKTsKICAgICAgcGFyZW50LmdldFdvcmxkUXVhdGVybmlvbihzY3JhdGNoLnBhcmVudFF1YXRlcm5pb24pOwogICAgICBzY3JhdGNoLnBhcmVudFF1YXRlcm5pb25JbnZlcnNlLmNvcHkoc2NyYXRjaC5wYXJlbnRRdWF0ZXJuaW9uKS5pbnZlcnQoKTsKICAgICAgc2NyYXRjaC5sb2NhbFBvc2l0aW9uLmNvcHkoc2NyYXRjaC53b3JsZFBvc2l0aW9uKS5hcHBseU1hdHJpeDQoc2NyYXRjaC5wYXJlbnRJbnZlcnNlKTsKICAgICAgc29saWQucG9zaXRpb24uY29weShzY3JhdGNoLmxvY2FsUG9zaXRpb24pOwogICAgICBzb2xpZC5xdWF0ZXJuaW9uLmNvcHkoc2NyYXRjaC5wYXJlbnRRdWF0ZXJuaW9uSW52ZXJzZS5tdWx0aXBseShzY3JhdGNoLndvcmxkUXVhdGVybmlvbikpOwogICAgfSBlbHNlIHsKICAgICAgc29saWQucG9zaXRpb24uY29weShzY3JhdGNoLndvcmxkUG9zaXRpb24pOwogICAgICBzb2xpZC5xdWF0ZXJuaW9uLmNvcHkoc2NyYXRjaC53b3JsZFF1YXRlcm5pb24pOwogICAgfQogICAgc29saWQudXBkYXRlTWF0cml4V29ybGQ/Lih0cnVlKTsKICAgIHRoaXMuX3N5bmNQcm94eUdyb3VwVHJhbnNmb3JtKHNvbGlkKTsKICB9CgogIF9zdGFydFRyYW5zZm9ybVNlc3Npb24oc29saWQpIHsKICAgIGlmICghc29saWQgfHwgIXRoaXMuX2FjdGl2ZSkgcmV0dXJuOwogICAgdGhpcy5fc3RvcFRyYW5zZm9ybVNlc3Npb24oKTsKICAgIGNvbnN0IGNvbnRyb2xzID0gbmV3IENvbWJpbmVkVHJhbnNmb3JtQ29udHJvbHModGhpcy52aWV3ZXIuY2FtZXJhLCB0aGlzLnZpZXdlci5yZW5kZXJlcj8uZG9tRWxlbWVudCk7CiAgICB0cnkgeyBjb250cm9scy5zZXRNb2RlKCd0cmFuc2xhdGUnKTsgfSBjYXRjaCB7IGNvbnRyb2xzLm1vZGUgPSAndHJhbnNsYXRlJzsgfQogICAgY29uc3QgdGFyZ2V0ID0gbmV3IFRIUkVFLk9iamVjdDNEKCk7CiAgICB0YXJnZXQubmFtZSA9IGBTaW11bGF0aW9uVHJhbnNmb3JtVGFyZ2V0OiR7c29saWQubmFtZSB8fCBzb2xpZC51dWlkIHx8ICcnfWA7CiAgICB0aGlzLnZpZXdlci5zY2VuZS51cGRhdGVNYXRyaXhXb3JsZD8uKHRydWUpOwogICAgc29saWQudXBkYXRlTWF0cml4V29ybGQ/Lih0cnVlKTsKICAgIGNvbnN0IGJveCA9IHRoaXMuX3NjcmF0Y2guYm94OwogICAgY29uc3QgY2VudGVyID0gYm94LnNldEZyb21PYmplY3QodGhpcy5fcHJveHlHcm91cHMuZ2V0KHNvbGlkLnV1aWQpIHx8IHNvbGlkKS5pc0VtcHR5KCkKICAgICAgPyBzb2xpZC5nZXRXb3JsZFBvc2l0aW9uKHRoaXMuX3NjcmF0Y2guY2VudGVyKQogICAgICA6IGJveC5nZXRDZW50ZXIodGhpcy5fc2NyYXRjaC5jZW50ZXIpOwogICAgY29uc3Qgd29ybGRQb3NpdGlvbiA9IHNvbGlkLmdldFdvcmxkUG9zaXRpb24obmV3IFRIUkVFLlZlY3RvcjMoKSk7CiAgICBjb25zdCB3b3JsZFF1YXRlcm5pb24gPSBzb2xpZC5nZXRXb3JsZFF1YXRlcm5pb24obmV3IFRIUkVFLlF1YXRlcm5pb24oKSk7CiAgICBjb25zdCBvZmZzZXRMb2NhbCA9IHdvcmxkUG9zaXRpb24uY2xvbmUoKS5zdWIoY2VudGVyKS5hcHBseVF1YXRlcm5pb24od29ybGRRdWF0ZXJuaW9uLmNsb25lKCkuaW52ZXJ0KCkpOwogICAgdGFyZ2V0LnBvc2l0aW9uLmNvcHkoY2VudGVyKTsKICAgIHRhcmdldC5xdWF0ZXJuaW9uLmNvcHkod29ybGRRdWF0ZXJuaW9uKTsKICAgIHRoaXMudmlld2VyLnNjZW5lLmFkZCh0YXJnZXQpOwogICAgY29udHJvbHMuYXR0YWNoKHRhcmdldCk7CiAgICB0aGlzLnZpZXdlci5zY2VuZS5hZGQoY29udHJvbHMpOwoKICAgIGNvbnN0IGFwcGx5VG9Tb2xpZCA9IChwZXJzaXN0ID0gZmFsc2UpID0+IHsKICAgICAgY29uc3QgdGFyZ2V0V29ybGRQb3NpdGlvbiA9IHRhcmdldC5nZXRXb3JsZFBvc2l0aW9uKG5ldyBUSFJFRS5WZWN0b3IzKCkpOwogICAgICBjb25zdCB0YXJnZXRXb3JsZFF1YXRlcm5pb24gPSB0YXJnZXQuZ2V0V29ybGRRdWF0ZXJuaW9uKG5ldyBUSFJFRS5RdWF0ZXJuaW9uKCkpOwogICAgICBjb25zdCBzb2xpZFdvcmxkUG9zaXRpb24gPSB0YXJnZXRXb3JsZFBvc2l0aW9uLmNsb25lKCkuYWRkKG9mZnNldExvY2FsLmNsb25lKCkuYXBwbHlRdWF0ZXJuaW9uKHRhcmdldFdvcmxkUXVhdGVybmlvbikpOwogICAgICB0aGlzLl9zZXRTb2xpZFdvcmxkUG9zZShzb2xpZCwgc29saWRXb3JsZFBvc2l0aW9uLCB0YXJnZXRXb3JsZFF1YXRlcm5pb24pOwogICAgICB0aGlzLl91cGRhdGVSdW50aW1lVHJhbnNmb3JtRnJvbVNvbGlkKHNvbGlkLCB7IHBlcnNpc3QgfSk7CiAgICAgIGlmIChwZXJzaXN0KSB7CiAgICAgICAgaWYgKHRoaXMuX3BoeXNpY3NXb3JsZCkgewogICAgICAgICAgdm9pZCB0aGlzLl9yZWJ1aWxkUGh5c2ljc1dvcmxkKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHRyeSB7IHRoaXMudmlld2VyPy5yZW5kZXI/LigpOyB9IGNhdGNoIHt9CiAgICB9OwoKICAgIGNvbnN0IGNoYW5nZUhhbmRsZXIgPSAoKSA9PiBhcHBseVRvU29saWQoZmFsc2UpOwogICAgY29uc3QgZHJhZ0hhbmRsZXIgPSAoZXZlbnQpID0+IHsKICAgICAgY29uc3QgZHJhZ2dpbmcgPSAhIWV2ZW50Py52YWx1ZTsKICAgICAgdHJ5IHsgaWYgKHRoaXMudmlld2VyPy5jb250cm9scykgdGhpcy52aWV3ZXIuY29udHJvbHMuZW5hYmxlZCA9ICFkcmFnZ2luZzsgfSBjYXRjaCB7fQogICAgICBpZiAoIWRyYWdnaW5nKSBhcHBseVRvU29saWQodHJ1ZSk7CiAgICB9OwogICAgY29uc3Qgb2JqZWN0Q2hhbmdlSGFuZGxlciA9ICgpID0+IHsKICAgICAgaWYgKCFjb250cm9scy5kcmFnZ2luZykgYXBwbHlUb1NvbGlkKHRydWUpOwogICAgfTsKICAgIGNvbnN0IHVwZGF0ZUZvckNhbWVyYSA9ICgpID0+IHsKICAgICAgdHJ5IHsgY29udHJvbHMudXBkYXRlPy4oKTsgfSBjYXRjaCB7fQogICAgfTsKICAgIGNvbnN0IGNhbWVyYUNoYW5nZUhhbmRsZXIgPSAoKSA9PiB1cGRhdGVGb3JDYW1lcmEoKTsKICAgIGNvbnRyb2xzLmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIGNoYW5nZUhhbmRsZXIpOwogICAgY29udHJvbHMuYWRkRXZlbnRMaXN0ZW5lcignZHJhZ2dpbmctY2hhbmdlZCcsIGRyYWdIYW5kbGVyKTsKICAgIGNvbnRyb2xzLmFkZEV2ZW50TGlzdGVuZXIoJ29iamVjdENoYW5nZScsIG9iamVjdENoYW5nZUhhbmRsZXIpOwogICAgdHJ5IHsgdGhpcy52aWV3ZXI/LmNvbnRyb2xzPy5hZGRFdmVudExpc3RlbmVyPy4oJ2NoYW5nZScsIGNhbWVyYUNoYW5nZUhhbmRsZXIpOyB9IGNhdGNoIHt9CgogICAgY29uc3QgZ2xvYmFsU3RhdGUgPSB7IGNvbnRyb2xzLCB2aWV3ZXI6IHRoaXMudmlld2VyLCB0YXJnZXQsIHVwZGF0ZUZvckNhbWVyYSB9OwogICAgdHJ5IHsgd2luZG93Ll9fQlJFUF9hY3RpdmVYZm9ybSA9IGdsb2JhbFN0YXRlOyB9IGNhdGNoIHt9CiAgICB0aGlzLl90cmFuc2Zvcm1TZXNzaW9uID0gewogICAgICBzb2xpZCwKICAgICAgY29udHJvbHMsCiAgICAgIHRhcmdldCwKICAgICAgY2hhbmdlSGFuZGxlciwKICAgICAgZHJhZ0hhbmRsZXIsCiAgICAgIG9iamVjdENoYW5nZUhhbmRsZXIsCiAgICAgIGNhbWVyYUNoYW5nZUhhbmRsZXIsCiAgICAgIGdsb2JhbFN0YXRlLAogICAgICBtb2RlOiAndHJhbnNsYXRlJywKICAgIH07CiAgICBpZiAodGhpcy5fcGh5c2ljc1dvcmxkKSB7CiAgICAgIHZvaWQgdGhpcy5fcmVidWlsZFBoeXNpY3NXb3JsZCgpOwogICAgfQogICAgdXBkYXRlRm9yQ2FtZXJhKCk7CiAgICBhcHBseVRvU29saWQoZmFsc2UpOwogIH0KCiAgX3N0b3BUcmFuc2Zvcm1TZXNzaW9uKCkgewogICAgY29uc3Qgc2Vzc2lvbiA9IHRoaXMuX3RyYW5zZm9ybVNlc3Npb247CiAgICBpZiAoIXNlc3Npb24pIHJldHVybjsKICAgIHRyeSB7IHNlc3Npb24uY29udHJvbHM/LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIHNlc3Npb24uY2hhbmdlSGFuZGxlcik7IH0gY2F0Y2gge30KICAgIHRyeSB7IHNlc3Npb24uY29udHJvbHM/LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RyYWdnaW5nLWNoYW5nZWQnLCBzZXNzaW9uLmRyYWdIYW5kbGVyKTsgfSBjYXRjaCB7fQogICAgdHJ5IHsgc2Vzc2lvbi5jb250cm9scz8ucmVtb3ZlRXZlbnRMaXN0ZW5lcignb2JqZWN0Q2hhbmdlJywgc2Vzc2lvbi5vYmplY3RDaGFuZ2VIYW5kbGVyKTsgfSBjYXRjaCB7fQogICAgdHJ5IHsgdGhpcy52aWV3ZXI/LmNvbnRyb2xzPy5yZW1vdmVFdmVudExpc3RlbmVyPy4oJ2NoYW5nZScsIHNlc3Npb24uY2FtZXJhQ2hhbmdlSGFuZGxlcik7IH0gY2F0Y2gge30KICAgIHRyeSB7IHNlc3Npb24uY29udHJvbHM/LmRldGFjaD8uKCk7IH0gY2F0Y2gge30KICAgIHRyeSB7IHRoaXMudmlld2VyPy5zY2VuZT8ucmVtb3ZlPy4oc2Vzc2lvbi5jb250cm9scyk7IH0gY2F0Y2gge30KICAgIHRyeSB7IHRoaXMudmlld2VyPy5zY2VuZT8ucmVtb3ZlPy4oc2Vzc2lvbi50YXJnZXQpOyB9IGNhdGNoIHt9CiAgICB0cnkgeyBzZXNzaW9uLmNvbnRyb2xzPy5kaXNwb3NlPy4oKTsgfSBjYXRjaCB7fQogICAgdHJ5IHsKICAgICAgaWYgKHdpbmRvdy5fX0JSRVBfYWN0aXZlWGZvcm0gPT09IHNlc3Npb24uZ2xvYmFsU3RhdGUpIHsKICAgICAgICB3aW5kb3cuX19CUkVQX2FjdGl2ZVhmb3JtID0gbnVsbDsKICAgICAgfQogICAgfSBjYXRjaCB7fQogICAgdGhpcy5fdHJhbnNmb3JtU2Vzc2lvbiA9IG51bGw7CiAgICB0cnkgeyBpZiAodGhpcy52aWV3ZXI/LmNvbnRyb2xzKSB0aGlzLnZpZXdlci5jb250cm9scy5lbmFibGVkID0gdHJ1ZTsgfSBjYXRjaCB7fQogICAgaWYgKHRoaXMuX3BoeXNpY3NXb3JsZCkgewogICAgICB2b2lkIHRoaXMuX3JlYnVpbGRQaHlzaWNzV29ybGQoKTsKICAgIH0KICAgIHRyeSB7IHRoaXMudmlld2VyPy5yZW5kZXI/LigpOyB9IGNhdGNoIHt9CiAgfQoKICBfbGlzdFNjZW5lU29saWRzKCkgewogICAgY29uc3Qgc2NlbmUgPSB0aGlzLnZpZXdlcj8ucGFydEhpc3Rvcnk/LnNjZW5lIHx8IHRoaXMudmlld2VyPy5zY2VuZSB8fCBudWxsOwogICAgY29uc3Qgc29saWRzID0gW107CiAgICBpZiAoIXNjZW5lPy50cmF2ZXJzZSkgcmV0dXJuIHNvbGlkczsKICAgIHNjZW5lLnRyYXZlcnNlKChvYmopID0+IHsKICAgICAgaWYgKG9iaj8udHlwZSA9PT0gJ1NPTElEJykgc29saWRzLnB1c2gob2JqKTsKICAgIH0pOwogICAgcmV0dXJuIHNvbGlkczsKICB9CgogIF9iaW5kU3RhdGVNYW5hZ2VyKCkgewogICAgY29uc3QgbWFuYWdlciA9IHRoaXMudmlld2VyPy5wYXJ0SGlzdG9yeT8uc2ltdWxhdGlvblN0YXRlTWFuYWdlcjsKICAgIGlmICghbWFuYWdlcj8uYWRkTGlzdGVuZXIpIHJldHVybjsKICAgIHRoaXMuX3JlbW92ZVN0YXRlTWFuYWdlckxpc3RlbmVyID0gbWFuYWdlci5hZGRMaXN0ZW5lcigoKSA9PiB7CiAgICAgIHRoaXMuX3JlY29uY2lsZU1vdGlvblN0YXRlKCk7CiAgICAgIGlmICh0aGlzLl9hY3RpdmUgJiYgdGhpcy5fcGh5c2ljc1dvcmxkKSB7CiAgICAgICAgdm9pZCB0aGlzLl9yZWJ1aWxkUGh5c2ljc1dvcmxkKCk7CiAgICAgIH0KICAgICAgdGhpcy5fZW1pdCgpOwogICAgfSk7CiAgfQoKICBfZW1pdCgpIHsKICAgIGlmICghdGhpcy5fbGlzdGVuZXJzIHx8IHRoaXMuX2xpc3RlbmVycy5zaXplID09PSAwKSByZXR1cm47CiAgICBjb25zdCBwYXlsb2FkID0gewogICAgICBhY3RpdmU6IHRoaXMuX2FjdGl2ZSwKICAgICAgcGxheWluZzogdGhpcy5faXNQbGF5aW5nLAogICAgICBtYW5hZ2VyOiB0aGlzLAogICAgfTsKICAgIGZvciAoY29uc3QgbGlzdGVuZXIgb2YgQXJyYXkuZnJvbSh0aGlzLl9saXN0ZW5lcnMpKSB7CiAgICAgIHRyeSB7IGxpc3RlbmVyKHBheWxvYWQpOyB9IGNhdGNoIHt9CiAgICB9CiAgfQoKICBfZ2V0TW90aW9uRW50cmllcygpIHsKICAgIGNvbnN0IG1vdGlvbnMgPSB0aGlzLnZpZXdlcj8ucGFydEhpc3Rvcnk/LnNpbXVsYXRpb25TdGF0ZU1hbmFnZXI/LmdldE1vdGlvbnM/LigpOwogICAgcmV0dXJuIEFycmF5LmlzQXJyYXkobW90aW9ucykKICAgICAgPyBtb3Rpb25zLm1hcCgoZW50cnkpID0+IChlbnRyeT8uaW5wdXRQYXJhbXMgJiYgdHlwZW9mIGVudHJ5LmlucHV0UGFyYW1zID09PSAnb2JqZWN0JykgPyBlbnRyeS5pbnB1dFBhcmFtcyA6IGVudHJ5KS5maWx0ZXIoQm9vbGVhbikKICAgICAgOiBbXTsKICB9CgogIF9yZXNldE1vdGlvblJ1bnRpbWUoKSB7CiAgICB0aGlzLl9tb3Rpb25TdGF0ZS5jbGVhcigpOwogICAgZm9yIChjb25zdCBtb3Rpb24gb2YgdGhpcy5fZ2V0TW90aW9uRW50cmllcygpKSB7CiAgICAgIHRoaXMuX21vdGlvblN0YXRlLnNldChtb3Rpb24uaWQsIHsgcHJvZ3Jlc3M6IDAsIGNvbXBsZXRlZDogZmFsc2UgfSk7CiAgICB9CiAgfQoKICBfcmVjb25jaWxlTW90aW9uU3RhdGUoKSB7CiAgICBjb25zdCBhY3RpdmVJZHMgPSBuZXcgU2V0KCk7CiAgICBmb3IgKGNvbnN0IG1vdGlvbiBvZiB0aGlzLl9nZXRNb3Rpb25FbnRyaWVzKCkpIHsKICAgICAgYWN0aXZlSWRzLmFkZChtb3Rpb24uaWQpOwogICAgICBpZiAoIXRoaXMuX21vdGlvblN0YXRlLmhhcyhtb3Rpb24uaWQpKSB7CiAgICAgICAgdGhpcy5fbW90aW9uU3RhdGUuc2V0KG1vdGlvbi5pZCwgeyBwcm9ncmVzczogMCwgY29tcGxldGVkOiBmYWxzZSB9KTsKICAgICAgfQogICAgfQogICAgZm9yIChjb25zdCBpZCBvZiBBcnJheS5mcm9tKHRoaXMuX21vdGlvblN0YXRlLmtleXMoKSkpIHsKICAgICAgaWYgKCFhY3RpdmVJZHMuaGFzKGlkKSkgdGhpcy5fbW90aW9uU3RhdGUuZGVsZXRlKGlkKTsKICAgIH0KICB9CgogIF9pc1NvbGlkTW90aW9uRHJpdmVuKHNvbGlkKSB7CiAgICBpZiAoIXNvbGlkIHx8ICF0aGlzLl9pc1BsYXlpbmcpIHJldHVybiBmYWxzZTsKICAgIGNvbnN0IG5hbWUgPSBub3JtYWxpemVUZXh0KHNvbGlkLm5hbWUsICcnKTsKICAgIGlmICghbmFtZSkgcmV0dXJuIGZhbHNlOwogICAgcmV0dXJuIHRoaXMuX2dldE1vdGlvbkVudHJpZXMoKS5zb21lKChtb3Rpb24pID0+IG5vcm1hbGl6ZVRleHQodGhpcy5fcmVzb2x2ZVJlZmVyZW5jZU5hbWUobW90aW9uPy5zb2xpZCksICcnKSA9PT0gbmFtZSk7CiAgfQoKICBfaXNTb2xpZEtpbmVtYXRpY01vdGlvbkRyaXZlbihzb2xpZCkgewogICAgcmV0dXJuICEhc29saWQgJiYgdGhpcy5nZXRTb2xpZEZpeGVkKHNvbGlkKSAmJiB0aGlzLl9pc1NvbGlkTW90aW9uRHJpdmVuKHNvbGlkKTsKICB9CgogIF9hcHBseU1vdGlvblN0ZXAoZHQpIHsKICAgIGNvbnN0IHNlbGVjdGVkU29saWQgPSB0aGlzLl90cmFuc2Zvcm1TZXNzaW9uPy5zb2xpZCB8fCBudWxsOwogICAgY29uc3QgY29tbWFuZHMgPSBuZXcgTWFwKCk7CiAgICBmb3IgKGNvbnN0IHNvbGlkIG9mIHRoaXMuX2xpc3RTY2VuZVNvbGlkcygpKSB7CiAgICAgIGlmICghdGhpcy5faXNTb2xpZE1vdGlvbkRyaXZlbihzb2xpZCkpIGNvbnRpbnVlOwogICAgICBpZiAoc2VsZWN0ZWRTb2xpZCAmJiBzb2xpZCA9PT0gc2VsZWN0ZWRTb2xpZCkgY29udGludWU7CiAgICAgIGlmICh0aGlzLl9pc1NvbGlkS2luZW1hdGljTW90aW9uRHJpdmVuKHNvbGlkKSkgY29udGludWU7CiAgICAgIGNvbnN0IGJvZHkgPSB0aGlzLl9ib2R5U3RhdGUuZ2V0KHNvbGlkLnV1aWQpPy5ib2R5OwogICAgICBpZiAoIWJvZHkpIGNvbnRpbnVlOwogICAgICBib2R5LnNldExpbnZlbCh7IHg6IDAsIHk6IDAsIHo6IDAgfSwgdHJ1ZSk7CiAgICAgIGJvZHkuc2V0QW5ndmVsKHsgeDogMCwgeTogMCwgejogMCB9LCB0cnVlKTsKICAgIH0KICAgIGZvciAoY29uc3QgbW90aW9uIG9mIHRoaXMuX2dldE1vdGlvbkVudHJpZXMoKSkgewogICAgICBjb25zdCBzb2xpZCA9IHRoaXMuX3Jlc29sdmVNb3Rpb25Tb2xpZChtb3Rpb24pOwogICAgICBpZiAoIXNvbGlkKSBjb250aW51ZTsKICAgICAgaWYgKHNlbGVjdGVkU29saWQgJiYgc29saWQgPT09IHNlbGVjdGVkU29saWQpIGNvbnRpbnVlOwogICAgICBpZiAobW90aW9uLnR5cGUgPT09ICdsaW5lYXInKSB0aGlzLl9hcHBseUxpbmVhck1vdGlvblN0ZXAoc29saWQsIG1vdGlvbiwgZHQsIGNvbW1hbmRzKTsKICAgICAgZWxzZSB0aGlzLl9hcHBseVJvdGF0aW9uTW90aW9uU3RlcChzb2xpZCwgbW90aW9uLCBkdCwgY29tbWFuZHMpOwogICAgfQogICAgZm9yIChjb25zdCBbc29saWRVdWlkLCBjb21tYW5kXSBvZiBjb21tYW5kcy5lbnRyaWVzKCkpIHsKICAgICAgY29uc3QgYm9keSA9IHRoaXMuX2JvZHlTdGF0ZS5nZXQoc29saWRVdWlkKT8uYm9keTsKICAgICAgaWYgKCFib2R5KSBjb250aW51ZTsKICAgICAgYm9keS5zZXRMaW52ZWwoY29tbWFuZC5saW5lYXIsIHRydWUpOwogICAgICBib2R5LnNldEFuZ3ZlbChjb21tYW5kLmFuZ3VsYXIsIHRydWUpOwogICAgfQogICAgcmV0dXJuIGNvbW1hbmRzLnNpemUgPiAwOwogIH0KCiAgX3Jlc29sdmVNb3Rpb25Tb2xpZChtb3Rpb24pIHsKICAgIGNvbnN0IG5hbWUgPSBub3JtYWxpemVUZXh0KHRoaXMuX3Jlc29sdmVSZWZlcmVuY2VOYW1lKG1vdGlvbj8uc29saWQpLCAnJyk7CiAgICBpZiAoIW5hbWUpIHJldHVybiBudWxsOwogICAgY29uc3Qgb2JqZWN0ID0gdGhpcy52aWV3ZXI/LnBhcnRIaXN0b3J5Py5nZXRPYmplY3RCeU5hbWU/LihuYW1lKSB8fCBudWxsOwogICAgcmV0dXJuIG9iamVjdD8udHlwZSA9PT0gJ1NPTElEJyA/IG9iamVjdCA6IG51bGw7CiAgfQoKICBfcmVzb2x2ZU1vdGlvbkF4aXMobW90aW9uKSB7CiAgICBjb25zdCBvYmplY3ROYW1lID0gbm9ybWFsaXplVGV4dCh0aGlzLl9yZXNvbHZlUmVmZXJlbmNlTmFtZShtb3Rpb24/LmF4aXMpLCAnJyk7CiAgICBjb25zdCBvYmplY3QgPSBvYmplY3ROYW1lID8gdGhpcy52aWV3ZXI/LnBhcnRIaXN0b3J5Py5nZXRPYmplY3RCeU5hbWU/LihvYmplY3ROYW1lKSA6IG51bGw7CiAgICBpZiAoIW9iamVjdCkgcmV0dXJuIG51bGw7CiAgICBjb25zdCBsaXZlID0gdGhpcy5fZXh0cmFjdEF4aXNQb2ludHNGcm9tT2JqZWN0KG9iamVjdCk7CiAgICBpZiAoIWxpdmU/LnN0YXJ0IHx8ICFsaXZlPy5lbmQpIHJldHVybiBudWxsOwogICAgY29uc3Qgc3RhcnRWZWMgPSBuZXcgVEhSRUUuVmVjdG9yMyhOdW1iZXIobGl2ZS5zdGFydFswXSkgfHwgMCwgTnVtYmVyKGxpdmUuc3RhcnRbMV0pIHx8IDAsIE51bWJlcihsaXZlLnN0YXJ0WzJdKSB8fCAwKTsKICAgIGNvbnN0IGVuZFZlYyA9IG5ldyBUSFJFRS5WZWN0b3IzKE51bWJlcihsaXZlLmVuZFswXSkgfHwgMCwgTnVtYmVyKGxpdmUuZW5kWzFdKSB8fCAwLCBOdW1iZXIobGl2ZS5lbmRbMl0pIHx8IDApOwogICAgaWYgKHN0YXJ0VmVjLmRpc3RhbmNlVG9TcXVhcmVkKGVuZFZlYykgPD0gMWUtMTIpIHJldHVybiBudWxsOwogICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0VmVjLCBlbmQ6IGVuZFZlYyB9OwogIH0KCiAgX3Jlc29sdmVSZWZlcmVuY2VOYW1lKHZhbHVlKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgcmV0dXJuIHRoaXMuX3Jlc29sdmVSZWZlcmVuY2VOYW1lKHZhbHVlWzBdIHx8IG51bGwpOwogICAgfQogICAgaWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHsKICAgICAgcmV0dXJuIG5vcm1hbGl6ZVRleHQodmFsdWUubmFtZSB8fCB2YWx1ZS5vYmplY3ROYW1lIHx8IHZhbHVlLmxhYmVsIHx8ICcnLCAnJyk7CiAgICB9CiAgICByZXR1cm4gbm9ybWFsaXplVGV4dCh2YWx1ZSwgJycpOwogIH0KCiAgX2V4dHJhY3RBeGlzUG9pbnRzRnJvbU9iamVjdChvYmplY3QpIHsKICAgIGlmICghb2JqZWN0KSByZXR1cm4gbnVsbDsKICAgIHRyeSB7CiAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LnBvaW50cyA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIGNvbnN0IHBvaW50cyA9IG9iamVjdC5wb2ludHModHJ1ZSk7CiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocG9pbnRzKSAmJiBwb2ludHMubGVuZ3RoID49IDIpIHsKICAgICAgICAgIGNvbnN0IGZpcnN0ID0gcG9pbnRzWzBdOwogICAgICAgICAgY29uc3QgbGFzdCA9IHBvaW50c1twb2ludHMubGVuZ3RoIC0gMV07CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBzdGFydDogW051bWJlcihmaXJzdD8ueCkgfHwgMCwgTnVtYmVyKGZpcnN0Py55KSB8fCAwLCBOdW1iZXIoZmlyc3Q/LnopIHx8IDBdLAogICAgICAgICAgICBlbmQ6IFtOdW1iZXIobGFzdD8ueCkgfHwgMCwgTnVtYmVyKGxhc3Q/LnkpIHx8IDAsIE51bWJlcihsYXN0Py56KSB8fCAwXSwKICAgICAgICAgIH07CiAgICAgICAgfQogICAgICB9CiAgICB9IGNhdGNoIHt9CiAgICB0cnkgewogICAgICBvYmplY3QudXBkYXRlTWF0cml4V29ybGQ/Lih0cnVlKTsKICAgICAgY29uc3QgYXR0ciA9IG9iamVjdC5nZW9tZXRyeT8uZ2V0QXR0cmlidXRlPy4oJ3Bvc2l0aW9uJyk7CiAgICAgIGlmICghYXR0ciB8fCBhdHRyLmNvdW50IDwgMikgcmV0dXJuIG51bGw7CiAgICAgIGNvbnN0IGZpcnN0ID0gbmV3IFRIUkVFLlZlY3RvcjMoYXR0ci5nZXRYKDApLCBhdHRyLmdldFkoMCksIGF0dHIuZ2V0WigwKSkuYXBwbHlNYXRyaXg0KG9iamVjdC5tYXRyaXhXb3JsZCk7CiAgICAgIGNvbnN0IGxhc3RJbmRleCA9IGF0dHIuY291bnQgLSAxOwogICAgICBjb25zdCBsYXN0ID0gbmV3IFRIUkVFLlZlY3RvcjMoYXR0ci5nZXRYKGxhc3RJbmRleCksIGF0dHIuZ2V0WShsYXN0SW5kZXgpLCBhdHRyLmdldFoobGFzdEluZGV4KSkuYXBwbHlNYXRyaXg0KG9iamVjdC5tYXRyaXhXb3JsZCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgc3RhcnQ6IFtmaXJzdC54LCBmaXJzdC55LCBmaXJzdC56XSwKICAgICAgICBlbmQ6IFtsYXN0LngsIGxhc3QueSwgbGFzdC56XSwKICAgICAgfTsKICAgIH0gY2F0Y2ggewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICB9CgogIF9nZXRNb3Rpb25Db21tYW5kKGNvbW1hbmRzLCBzb2xpZCkgewogICAgaWYgKCFzb2xpZD8udXVpZCkgcmV0dXJuIG51bGw7CiAgICBsZXQgY29tbWFuZCA9IGNvbW1hbmRzLmdldChzb2xpZC51dWlkKTsKICAgIGlmICghY29tbWFuZCkgewogICAgICBjb21tYW5kID0gewogICAgICAgIGxpbmVhcjogeyB4OiAwLCB5OiAwLCB6OiAwIH0sCiAgICAgICAgYW5ndWxhcjogeyB4OiAwLCB5OiAwLCB6OiAwIH0sCiAgICAgIH07CiAgICAgIGNvbW1hbmRzLnNldChzb2xpZC51dWlkLCBjb21tYW5kKTsKICAgIH0KICAgIHJldHVybiBjb21tYW5kOwogIH0KCiAgX2FwcGx5Um90YXRpb25Nb3Rpb25TdGVwKHNvbGlkLCBtb3Rpb24sIGR0LCBjb21tYW5kcykgewogICAgY29uc3Qgc3RhdGUgPSB0aGlzLl9tb3Rpb25TdGF0ZS5nZXQobW90aW9uLmlkKSB8fCB7IHByb2dyZXNzOiAwLCBjb21wbGV0ZWQ6IGZhbHNlIH07CiAgICBpZiAoc3RhdGUuY29tcGxldGVkKSByZXR1cm4gZmFsc2U7CiAgICBjb25zdCBheGlzID0gdGhpcy5fcmVzb2x2ZU1vdGlvbkF4aXMobW90aW9uKTsKICAgIGlmICghYXhpcykgcmV0dXJuIGZhbHNlOwogICAgY29uc3QgYm9keSA9IHRoaXMuX2JvZHlTdGF0ZS5nZXQoc29saWQudXVpZCk/LmJvZHkgfHwgbnVsbDsKICAgIGlmICghYm9keSkgcmV0dXJuIGZhbHNlOwogICAgY29uc3Qgc3BlZWREZWcgPSBOdW1iZXIobW90aW9uPy5zcGVlZCk7CiAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShzcGVlZERlZykgfHwgTWF0aC5hYnMoc3BlZWREZWcpIDw9IDFlLTkpIHJldHVybiBmYWxzZTsKICAgIGxldCBkZWx0YURlZyA9IHNwZWVkRGVnICogZHQ7CiAgICBjb25zdCBsaW1pdERlZyA9IG5vcm1hbGl6ZU9wdGlvbmFsTW90aW9uTGltaXQobW90aW9uPy5hbmdsZSk7CiAgICBpZiAobGltaXREZWcgIT0gbnVsbCkgewogICAgICBjb25zdCByZW1haW5pbmcgPSBsaW1pdERlZyAtIHN0YXRlLnByb2dyZXNzOwogICAgICBpZiAoTWF0aC5hYnMocmVtYWluaW5nKSA8PSAxZS05KSB7CiAgICAgICAgc3RhdGUuY29tcGxldGVkID0gdHJ1ZTsKICAgICAgICB0aGlzLl9tb3Rpb25TdGF0ZS5zZXQobW90aW9uLmlkLCBzdGF0ZSk7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChNYXRoLnNpZ24oZGVsdGFEZWcgfHwgMSkgIT09IE1hdGguc2lnbihyZW1haW5pbmcgfHwgMSkpIHsKICAgICAgICBkZWx0YURlZyA9IE1hdGguc2lnbihyZW1haW5pbmcgfHwgMSkgKiBNYXRoLmFicyhkZWx0YURlZyk7CiAgICAgIH0KICAgICAgaWYgKE1hdGguYWJzKGRlbHRhRGVnKSA+IE1hdGguYWJzKHJlbWFpbmluZykpIGRlbHRhRGVnID0gcmVtYWluaW5nOwogICAgfQogICAgaWYgKE1hdGguYWJzKGRlbHRhRGVnKSA8PSAxZS05KSByZXR1cm4gZmFsc2U7CiAgICBpZiAodGhpcy5faXNTb2xpZEtpbmVtYXRpY01vdGlvbkRyaXZlbihzb2xpZCkpIHsKICAgICAgdGhpcy5fcm90YXRlU29saWRBcm91bmRXb3JsZEF4aXMoc29saWQsIGF4aXMuc3RhcnQsIGF4aXMuZW5kLCBUSFJFRS5NYXRoVXRpbHMuZGVnVG9SYWQoZGVsdGFEZWcpKTsKICAgICAgY29uc3Qgd29ybGRQb3NpdGlvbiA9IHNvbGlkLmdldFdvcmxkUG9zaXRpb24obmV3IFRIUkVFLlZlY3RvcjMoKSk7CiAgICAgIGNvbnN0IHdvcmxkUXVhdGVybmlvbiA9IHNvbGlkLmdldFdvcmxkUXVhdGVybmlvbihuZXcgVEhSRUUuUXVhdGVybmlvbigpKTsKICAgICAgYm9keS5zZXROZXh0S2luZW1hdGljVHJhbnNsYXRpb24od29ybGRQb3NpdGlvbik7CiAgICAgIGJvZHkuc2V0TmV4dEtpbmVtYXRpY1JvdGF0aW9uKHdvcmxkUXVhdGVybmlvbik7CiAgICAgIHRoaXMuX3VwZGF0ZVJ1bnRpbWVUcmFuc2Zvcm1Gcm9tU29saWQoc29saWQsIHsgcGVyc2lzdDogZmFsc2UgfSk7CiAgICAgIHRoaXMuX21vdmVkU29saWRJZHMuYWRkKHNvbGlkLnV1aWQpOwogICAgICBzdGF0ZS5wcm9ncmVzcyArPSBkZWx0YURlZzsKICAgICAgaWYgKGxpbWl0RGVnICE9IG51bGwgJiYgTWF0aC5hYnMobGltaXREZWcgLSBzdGF0ZS5wcm9ncmVzcykgPD0gMWUtOSkgc3RhdGUuY29tcGxldGVkID0gdHJ1ZTsKICAgICAgdGhpcy5fbW90aW9uU3RhdGUuc2V0KG1vdGlvbi5pZCwgc3RhdGUpOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGNvbnN0IG9tZWdhID0gVEhSRUUuTWF0aFV0aWxzLmRlZ1RvUmFkKGRlbHRhRGVnKSAvIE1hdGgubWF4KGR0LCAxZS05KTsKICAgIGNvbnN0IHNjcmF0Y2ggPSB0aGlzLl9zY3JhdGNoOwogICAgY29uc3QgY29tbWFuZCA9IHRoaXMuX2dldE1vdGlvbkNvbW1hbmQoY29tbWFuZHMsIHNvbGlkKTsKICAgIGNvbnN0IHRyYW5zbGF0aW9uID0gYm9keS50cmFuc2xhdGlvbigpOwogICAgc2NyYXRjaC5heGlzLmNvcHkoYXhpcy5lbmQpLnN1YihheGlzLnN0YXJ0KS5ub3JtYWxpemUoKS5tdWx0aXBseVNjYWxhcihvbWVnYSk7CiAgICBzY3JhdGNoLnJhZGl1cy5zZXQoCiAgICAgIE51bWJlcih0cmFuc2xhdGlvbj8ueCkgfHwgMCwKICAgICAgTnVtYmVyKHRyYW5zbGF0aW9uPy55KSB8fCAwLAogICAgICBOdW1iZXIodHJhbnNsYXRpb24/LnopIHx8IDAsCiAgICApLnN1YihheGlzLnN0YXJ0KTsKICAgIHNjcmF0Y2gudmVsb2NpdHkuY29weShzY3JhdGNoLmF4aXMpLmNyb3NzKHNjcmF0Y2gucmFkaXVzKTsKICAgIGNvbW1hbmQuYW5ndWxhci54ICs9IHNjcmF0Y2guYXhpcy54OwogICAgY29tbWFuZC5hbmd1bGFyLnkgKz0gc2NyYXRjaC5heGlzLnk7CiAgICBjb21tYW5kLmFuZ3VsYXIueiArPSBzY3JhdGNoLmF4aXMuejsKICAgIGNvbW1hbmQubGluZWFyLnggKz0gc2NyYXRjaC52ZWxvY2l0eS54OwogICAgY29tbWFuZC5saW5lYXIueSArPSBzY3JhdGNoLnZlbG9jaXR5Lnk7CiAgICBjb21tYW5kLmxpbmVhci56ICs9IHNjcmF0Y2gudmVsb2NpdHkuejsKICAgIHN0YXRlLnByb2dyZXNzICs9IGRlbHRhRGVnOwogICAgaWYgKGxpbWl0RGVnICE9IG51bGwgJiYgTWF0aC5hYnMobGltaXREZWcgLSBzdGF0ZS5wcm9ncmVzcykgPD0gMWUtOSkgc3RhdGUuY29tcGxldGVkID0gdHJ1ZTsKICAgIHRoaXMuX21vdGlvblN0YXRlLnNldChtb3Rpb24uaWQsIHN0YXRlKTsKICAgIHJldHVybiB0cnVlOwogIH0KCiAgX2FwcGx5TGluZWFyTW90aW9uU3RlcChzb2xpZCwgbW90aW9uLCBkdCwgY29tbWFuZHMpIHsKICAgIGNvbnN0IHN0YXRlID0gdGhpcy5fbW90aW9uU3RhdGUuZ2V0KG1vdGlvbi5pZCkgfHwgeyBwcm9ncmVzczogMCwgY29tcGxldGVkOiBmYWxzZSB9OwogICAgaWYgKHN0YXRlLmNvbXBsZXRlZCkgcmV0dXJuIGZhbHNlOwogICAgY29uc3QgYXhpcyA9IHRoaXMuX3Jlc29sdmVNb3Rpb25BeGlzKG1vdGlvbik7CiAgICBpZiAoIWF4aXMpIHJldHVybiBmYWxzZTsKICAgIGNvbnN0IGJvZHkgPSB0aGlzLl9ib2R5U3RhdGUuZ2V0KHNvbGlkLnV1aWQpPy5ib2R5IHx8IG51bGw7CiAgICBpZiAoIWJvZHkpIHJldHVybiBmYWxzZTsKICAgIGNvbnN0IHNwZWVkID0gTnVtYmVyKG1vdGlvbj8uc3BlZWQpOwogICAgaWYgKCFOdW1iZXIuaXNGaW5pdGUoc3BlZWQpIHx8IE1hdGguYWJzKHNwZWVkKSA8PSAxZS05KSByZXR1cm4gZmFsc2U7CiAgICBsZXQgZGVsdGEgPSBzcGVlZCAqIGR0OwogICAgY29uc3QgbGltaXQgPSBub3JtYWxpemVPcHRpb25hbE1vdGlvbkxpbWl0KG1vdGlvbj8uZGlzdGFuY2UpOwogICAgaWYgKGxpbWl0ICE9IG51bGwpIHsKICAgICAgY29uc3QgcmVtYWluaW5nID0gbGltaXQgLSBzdGF0ZS5wcm9ncmVzczsKICAgICAgaWYgKE1hdGguYWJzKHJlbWFpbmluZykgPD0gMWUtOSkgewogICAgICAgIHN0YXRlLmNvbXBsZXRlZCA9IHRydWU7CiAgICAgICAgdGhpcy5fbW90aW9uU3RhdGUuc2V0KG1vdGlvbi5pZCwgc3RhdGUpOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoTWF0aC5zaWduKGRlbHRhIHx8IDEpICE9PSBNYXRoLnNpZ24ocmVtYWluaW5nIHx8IDEpKSB7CiAgICAgICAgZGVsdGEgPSBNYXRoLnNpZ24ocmVtYWluaW5nIHx8IDEpICogTWF0aC5hYnMoZGVsdGEpOwogICAgICB9CiAgICAgIGlmIChNYXRoLmFicyhkZWx0YSkgPiBNYXRoLmFicyhyZW1haW5pbmcpKSBkZWx0YSA9IHJlbWFpbmluZzsKICAgIH0KICAgIGlmIChNYXRoLmFicyhkZWx0YSkgPD0gMWUtOSkgcmV0dXJuIGZhbHNlOwogICAgaWYgKHRoaXMuX2lzU29saWRLaW5lbWF0aWNNb3Rpb25Ecml2ZW4oc29saWQpKSB7CiAgICAgIHRoaXMuX3RyYW5zbGF0ZVNvbGlkQWxvbmdXb3JsZEF4aXMoc29saWQsIGF4aXMuc3RhcnQsIGF4aXMuZW5kLCBkZWx0YSk7CiAgICAgIGNvbnN0IHdvcmxkUG9zaXRpb24gPSBzb2xpZC5nZXRXb3JsZFBvc2l0aW9uKG5ldyBUSFJFRS5WZWN0b3IzKCkpOwogICAgICBjb25zdCB3b3JsZFF1YXRlcm5pb24gPSBzb2xpZC5nZXRXb3JsZFF1YXRlcm5pb24obmV3IFRIUkVFLlF1YXRlcm5pb24oKSk7CiAgICAgIGJvZHkuc2V0TmV4dEtpbmVtYXRpY1RyYW5zbGF0aW9uKHdvcmxkUG9zaXRpb24pOwogICAgICBib2R5LnNldE5leHRLaW5lbWF0aWNSb3RhdGlvbih3b3JsZFF1YXRlcm5pb24pOwogICAgICB0aGlzLl91cGRhdGVSdW50aW1lVHJhbnNmb3JtRnJvbVNvbGlkKHNvbGlkLCB7IHBlcnNpc3Q6IGZhbHNlIH0pOwogICAgICB0aGlzLl9tb3ZlZFNvbGlkSWRzLmFkZChzb2xpZC51dWlkKTsKICAgICAgc3RhdGUucHJvZ3Jlc3MgKz0gZGVsdGE7CiAgICAgIGlmIChsaW1pdCAhPSBudWxsICYmIE1hdGguYWJzKGxpbWl0IC0gc3RhdGUucHJvZ3Jlc3MpIDw9IDFlLTkpIHN0YXRlLmNvbXBsZXRlZCA9IHRydWU7CiAgICAgIHRoaXMuX21vdGlvblN0YXRlLnNldChtb3Rpb24uaWQsIHN0YXRlKTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBjb25zdCB2ZWxvY2l0eVNjYWxlID0gZGVsdGEgLyBNYXRoLm1heChkdCwgMWUtOSk7CiAgICBjb25zdCBzY3JhdGNoID0gdGhpcy5fc2NyYXRjaDsKICAgIGNvbnN0IGNvbW1hbmQgPSB0aGlzLl9nZXRNb3Rpb25Db21tYW5kKGNvbW1hbmRzLCBzb2xpZCk7CiAgICBjb25zdCB0cmFuc2xhdGlvbiA9IGJvZHkudHJhbnNsYXRpb24oKTsKICAgIHNjcmF0Y2guYXhpcy5jb3B5KGF4aXMuZW5kKS5zdWIoYXhpcy5zdGFydCkubm9ybWFsaXplKCk7CiAgICBzY3JhdGNoLnRyYW5zbGF0aW9uLmNvcHkoc2NyYXRjaC5heGlzKS5tdWx0aXBseVNjYWxhcihkZWx0YSk7CiAgICBib2R5LnNldFRyYW5zbGF0aW9uKHsKICAgICAgeDogKE51bWJlcih0cmFuc2xhdGlvbj8ueCkgfHwgMCkgKyBzY3JhdGNoLnRyYW5zbGF0aW9uLngsCiAgICAgIHk6IChOdW1iZXIodHJhbnNsYXRpb24/LnkpIHx8IDApICsgc2NyYXRjaC50cmFuc2xhdGlvbi55LAogICAgICB6OiAoTnVtYmVyKHRyYW5zbGF0aW9uPy56KSB8fCAwKSArIHNjcmF0Y2gudHJhbnNsYXRpb24ueiwKICAgIH0sIHRydWUpOwogICAgc2NyYXRjaC5heGlzLm11bHRpcGx5U2NhbGFyKHZlbG9jaXR5U2NhbGUpOwogICAgY29tbWFuZC5saW5lYXIueCArPSBzY3JhdGNoLmF4aXMueDsKICAgIGNvbW1hbmQubGluZWFyLnkgKz0gc2NyYXRjaC5heGlzLnk7CiAgICBjb21tYW5kLmxpbmVhci56ICs9IHNjcmF0Y2guYXhpcy56OwogICAgYm9keS5zZXRBbmd2ZWwoeyB4OiAwLCB5OiAwLCB6OiAwIH0sIHRydWUpOwogICAgc3RhdGUucHJvZ3Jlc3MgKz0gZGVsdGE7CiAgICBpZiAobGltaXQgIT0gbnVsbCAmJiBNYXRoLmFicyhsaW1pdCAtIHN0YXRlLnByb2dyZXNzKSA8PSAxZS05KSBzdGF0ZS5jb21wbGV0ZWQgPSB0cnVlOwogICAgdGhpcy5fbW90aW9uU3RhdGUuc2V0KG1vdGlvbi5pZCwgc3RhdGUpOwogICAgcmV0dXJuIHRydWU7CiAgfQoKICBfcm90YXRlU29saWRBcm91bmRXb3JsZEF4aXMoc29saWQsIGF4aXNTdGFydCwgYXhpc0VuZCwgYW5nbGVSYWQpIHsKICAgIGNvbnN0IHBhcmVudCA9IHNvbGlkLnBhcmVudCB8fCB0aGlzLnZpZXdlcj8uc2NlbmUgfHwgbnVsbDsKICAgIGNvbnN0IHNjcmF0Y2ggPSB0aGlzLl9zY3JhdGNoOwogICAgc2NyYXRjaC5heGlzLmNvcHkoYXhpc0VuZCkuc3ViKGF4aXNTdGFydCkubm9ybWFsaXplKCk7CiAgICBzY3JhdGNoLnBhcmVudFdvcmxkTWF0cml4LmNvcHkocGFyZW50Py5tYXRyaXhXb3JsZCB8fCBuZXcgVEhSRUUuTWF0cml4NCgpKTsKICAgIHNjcmF0Y2gucGFyZW50SW52ZXJzZS5jb3B5KHNjcmF0Y2gucGFyZW50V29ybGRNYXRyaXgpLmludmVydCgpOwogICAgc2NyYXRjaC53b3JsZE1hdHJpeC5jb3B5KHNvbGlkLm1hdHJpeFdvcmxkKTsKICAgIHNjcmF0Y2guZGVsdGFNYXRyaXgubWFrZVRyYW5zbGF0aW9uKGF4aXNTdGFydC54LCBheGlzU3RhcnQueSwgYXhpc1N0YXJ0LnopOwogICAgc2NyYXRjaC5kZWx0YU1hdHJpeC5tdWx0aXBseShuZXcgVEhSRUUuTWF0cml4NCgpLm1ha2VSb3RhdGlvbkF4aXMoc2NyYXRjaC5heGlzLCBhbmdsZVJhZCkpOwogICAgc2NyYXRjaC5kZWx0YU1hdHJpeC5tdWx0aXBseShuZXcgVEhSRUUuTWF0cml4NCgpLm1ha2VUcmFuc2xhdGlvbigtYXhpc1N0YXJ0LngsIC1heGlzU3RhcnQueSwgLWF4aXNTdGFydC56KSk7CiAgICBzY3JhdGNoLndvcmxkTWF0cml4LnByZW11bHRpcGx5KHNjcmF0Y2guZGVsdGFNYXRyaXgpOwogICAgc2NyYXRjaC5sb2NhbE1hdHJpeC5jb3B5KHNjcmF0Y2gucGFyZW50SW52ZXJzZSkubXVsdGlwbHkoc2NyYXRjaC53b3JsZE1hdHJpeCk7CiAgICBzY3JhdGNoLmxvY2FsTWF0cml4LmRlY29tcG9zZShzb2xpZC5wb3NpdGlvbiwgc29saWQucXVhdGVybmlvbiwgc29saWQuc2NhbGUpOwogICAgc29saWQudXBkYXRlTWF0cml4V29ybGQ/Lih0cnVlKTsKICAgIHRoaXMuX3N5bmNQcm94eUdyb3VwVHJhbnNmb3JtKHNvbGlkKTsKICB9CgogIF90cmFuc2xhdGVTb2xpZEFsb25nV29ybGRBeGlzKHNvbGlkLCBheGlzU3RhcnQsIGF4aXNFbmQsIGRpc3RhbmNlKSB7CiAgICBjb25zdCBwYXJlbnQgPSBzb2xpZC5wYXJlbnQgfHwgdGhpcy52aWV3ZXI/LnNjZW5lIHx8IG51bGw7CiAgICBjb25zdCBzY3JhdGNoID0gdGhpcy5fc2NyYXRjaDsKICAgIHNjcmF0Y2guYXhpcy5jb3B5KGF4aXNFbmQpLnN1YihheGlzU3RhcnQpLm5vcm1hbGl6ZSgpOwogICAgc2NyYXRjaC50cmFuc2xhdGlvbi5jb3B5KHNjcmF0Y2guYXhpcykubXVsdGlwbHlTY2FsYXIoZGlzdGFuY2UpOwogICAgc2NyYXRjaC5wYXJlbnRXb3JsZE1hdHJpeC5jb3B5KHBhcmVudD8ubWF0cml4V29ybGQgfHwgbmV3IFRIUkVFLk1hdHJpeDQoKSk7CiAgICBzY3JhdGNoLnBhcmVudEludmVyc2UuY29weShzY3JhdGNoLnBhcmVudFdvcmxkTWF0cml4KS5pbnZlcnQoKTsKICAgIHNjcmF0Y2gud29ybGRNYXRyaXguY29weShzb2xpZC5tYXRyaXhXb3JsZCk7CiAgICBzY3JhdGNoLmRlbHRhTWF0cml4Lm1ha2VUcmFuc2xhdGlvbihzY3JhdGNoLnRyYW5zbGF0aW9uLngsIHNjcmF0Y2gudHJhbnNsYXRpb24ueSwgc2NyYXRjaC50cmFuc2xhdGlvbi56KTsKICAgIHNjcmF0Y2gud29ybGRNYXRyaXgucHJlbXVsdGlwbHkoc2NyYXRjaC5kZWx0YU1hdHJpeCk7CiAgICBzY3JhdGNoLmxvY2FsTWF0cml4LmNvcHkoc2NyYXRjaC5wYXJlbnRJbnZlcnNlKS5tdWx0aXBseShzY3JhdGNoLndvcmxkTWF0cml4KTsKICAgIHNjcmF0Y2gubG9jYWxNYXRyaXguZGVjb21wb3NlKHNvbGlkLnBvc2l0aW9uLCBzb2xpZC5xdWF0ZXJuaW9uLCBzb2xpZC5zY2FsZSk7CiAgICBzb2xpZC51cGRhdGVNYXRyaXhXb3JsZD8uKHRydWUpOwogICAgdGhpcy5fc3luY1Byb3h5R3JvdXBUcmFuc2Zvcm0oc29saWQpOwogIH0KfQo=", import.meta.url).href, { SimulationWorkbenchManager: e } = await import(
|
|
304373
304373
|
/* @vite-ignore */
|
|
304374
304374
|
A
|
|
304375
304375
|
);
|
package/package.json
CHANGED
|
@@ -33,6 +33,12 @@ function normalizeText(value, fallback = '') {
|
|
|
33
33
|
return next || fallback;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
function normalizeOptionalMotionLimit(value) {
|
|
37
|
+
const numeric = Number(value);
|
|
38
|
+
if (!Number.isFinite(numeric)) return null;
|
|
39
|
+
return Math.abs(numeric) <= 1e-9 ? null : numeric;
|
|
40
|
+
}
|
|
41
|
+
|
|
36
42
|
function normalizeTransform(value) {
|
|
37
43
|
const raw = value && typeof value === 'object' ? value : {};
|
|
38
44
|
return {
|
|
@@ -171,6 +177,9 @@ export class SimulationWorkbenchManager {
|
|
|
171
177
|
center: new THREE.Vector3(),
|
|
172
178
|
axis: new THREE.Vector3(),
|
|
173
179
|
translation: new THREE.Vector3(),
|
|
180
|
+
velocity: new THREE.Vector3(),
|
|
181
|
+
angularVelocity: new THREE.Vector3(),
|
|
182
|
+
radius: new THREE.Vector3(),
|
|
174
183
|
};
|
|
175
184
|
this._bindStateManager();
|
|
176
185
|
}
|
|
@@ -606,7 +615,7 @@ export class SimulationWorkbenchManager {
|
|
|
606
615
|
for (const solid of this._listSceneSolids()) {
|
|
607
616
|
const bodyDesc = (selectedSolid && solid === selectedSolid)
|
|
608
617
|
? rapier.RigidBodyDesc.kinematicPositionBased()
|
|
609
|
-
: (this.
|
|
618
|
+
: (this._isSolidKinematicMotionDriven(solid)
|
|
610
619
|
? rapier.RigidBodyDesc.kinematicPositionBased()
|
|
611
620
|
: (this.getSolidFixed(solid) ? rapier.RigidBodyDesc.fixed() : rapier.RigidBodyDesc.dynamic()));
|
|
612
621
|
const position = solid.getWorldPosition(new THREE.Vector3());
|
|
@@ -695,18 +704,6 @@ export class SimulationWorkbenchManager {
|
|
|
695
704
|
bodyState.body.setNextKinematicRotation(worldQuaternion);
|
|
696
705
|
}
|
|
697
706
|
}
|
|
698
|
-
if (this._isPlaying) {
|
|
699
|
-
for (const solid of this._listSceneSolids()) {
|
|
700
|
-
if (!this._isSolidMotionDriven(solid)) continue;
|
|
701
|
-
const bodyState = this._bodyState.get(solid.uuid);
|
|
702
|
-
if (!bodyState?.body) continue;
|
|
703
|
-
const worldPosition = solid.getWorldPosition(new THREE.Vector3());
|
|
704
|
-
const worldQuaternion = solid.getWorldQuaternion(new THREE.Quaternion());
|
|
705
|
-
bodyState.body.setNextKinematicTranslation(worldPosition);
|
|
706
|
-
bodyState.body.setNextKinematicRotation(worldQuaternion);
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
|
|
710
707
|
world.step();
|
|
711
708
|
for (const bodyState of this._bodyState.values()) {
|
|
712
709
|
const { solid, body } = bodyState;
|
|
@@ -715,10 +712,6 @@ export class SimulationWorkbenchManager {
|
|
|
715
712
|
this._syncProxyGroupTransform(solid);
|
|
716
713
|
continue;
|
|
717
714
|
}
|
|
718
|
-
if (this._isSolidMotionDriven(solid)) {
|
|
719
|
-
this._syncProxyGroupTransform(solid);
|
|
720
|
-
continue;
|
|
721
|
-
}
|
|
722
715
|
if (this.getSolidFixed(solid)) {
|
|
723
716
|
this._syncProxyGroupTransform(solid);
|
|
724
717
|
continue;
|
|
@@ -923,15 +916,36 @@ export class SimulationWorkbenchManager {
|
|
|
923
916
|
return this._getMotionEntries().some((motion) => normalizeText(this._resolveReferenceName(motion?.solid), '') === name);
|
|
924
917
|
}
|
|
925
918
|
|
|
919
|
+
_isSolidKinematicMotionDriven(solid) {
|
|
920
|
+
return !!solid && this.getSolidFixed(solid) && this._isSolidMotionDriven(solid);
|
|
921
|
+
}
|
|
922
|
+
|
|
926
923
|
_applyMotionStep(dt) {
|
|
927
|
-
|
|
924
|
+
const selectedSolid = this._transformSession?.solid || null;
|
|
925
|
+
const commands = new Map();
|
|
926
|
+
for (const solid of this._listSceneSolids()) {
|
|
927
|
+
if (!this._isSolidMotionDriven(solid)) continue;
|
|
928
|
+
if (selectedSolid && solid === selectedSolid) continue;
|
|
929
|
+
if (this._isSolidKinematicMotionDriven(solid)) continue;
|
|
930
|
+
const body = this._bodyState.get(solid.uuid)?.body;
|
|
931
|
+
if (!body) continue;
|
|
932
|
+
body.setLinvel({ x: 0, y: 0, z: 0 }, true);
|
|
933
|
+
body.setAngvel({ x: 0, y: 0, z: 0 }, true);
|
|
934
|
+
}
|
|
928
935
|
for (const motion of this._getMotionEntries()) {
|
|
929
936
|
const solid = this._resolveMotionSolid(motion);
|
|
930
937
|
if (!solid) continue;
|
|
931
|
-
if (
|
|
932
|
-
|
|
938
|
+
if (selectedSolid && solid === selectedSolid) continue;
|
|
939
|
+
if (motion.type === 'linear') this._applyLinearMotionStep(solid, motion, dt, commands);
|
|
940
|
+
else this._applyRotationMotionStep(solid, motion, dt, commands);
|
|
933
941
|
}
|
|
934
|
-
|
|
942
|
+
for (const [solidUuid, command] of commands.entries()) {
|
|
943
|
+
const body = this._bodyState.get(solidUuid)?.body;
|
|
944
|
+
if (!body) continue;
|
|
945
|
+
body.setLinvel(command.linear, true);
|
|
946
|
+
body.setAngvel(command.angular, true);
|
|
947
|
+
}
|
|
948
|
+
return commands.size > 0;
|
|
935
949
|
}
|
|
936
950
|
|
|
937
951
|
_resolveMotionSolid(motion) {
|
|
@@ -994,15 +1008,30 @@ export class SimulationWorkbenchManager {
|
|
|
994
1008
|
}
|
|
995
1009
|
}
|
|
996
1010
|
|
|
997
|
-
|
|
1011
|
+
_getMotionCommand(commands, solid) {
|
|
1012
|
+
if (!solid?.uuid) return null;
|
|
1013
|
+
let command = commands.get(solid.uuid);
|
|
1014
|
+
if (!command) {
|
|
1015
|
+
command = {
|
|
1016
|
+
linear: { x: 0, y: 0, z: 0 },
|
|
1017
|
+
angular: { x: 0, y: 0, z: 0 },
|
|
1018
|
+
};
|
|
1019
|
+
commands.set(solid.uuid, command);
|
|
1020
|
+
}
|
|
1021
|
+
return command;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
_applyRotationMotionStep(solid, motion, dt, commands) {
|
|
998
1025
|
const state = this._motionState.get(motion.id) || { progress: 0, completed: false };
|
|
999
|
-
if (state.completed) return;
|
|
1026
|
+
if (state.completed) return false;
|
|
1000
1027
|
const axis = this._resolveMotionAxis(motion);
|
|
1001
|
-
if (!axis) return;
|
|
1028
|
+
if (!axis) return false;
|
|
1029
|
+
const body = this._bodyState.get(solid.uuid)?.body || null;
|
|
1030
|
+
if (!body) return false;
|
|
1002
1031
|
const speedDeg = Number(motion?.speed);
|
|
1003
|
-
if (!Number.isFinite(speedDeg) || Math.abs(speedDeg) <= 1e-9) return;
|
|
1032
|
+
if (!Number.isFinite(speedDeg) || Math.abs(speedDeg) <= 1e-9) return false;
|
|
1004
1033
|
let deltaDeg = speedDeg * dt;
|
|
1005
|
-
const limitDeg =
|
|
1034
|
+
const limitDeg = normalizeOptionalMotionLimit(motion?.angle);
|
|
1006
1035
|
if (limitDeg != null) {
|
|
1007
1036
|
const remaining = limitDeg - state.progress;
|
|
1008
1037
|
if (Math.abs(remaining) <= 1e-9) {
|
|
@@ -1016,24 +1045,53 @@ export class SimulationWorkbenchManager {
|
|
|
1016
1045
|
if (Math.abs(deltaDeg) > Math.abs(remaining)) deltaDeg = remaining;
|
|
1017
1046
|
}
|
|
1018
1047
|
if (Math.abs(deltaDeg) <= 1e-9) return false;
|
|
1019
|
-
this.
|
|
1048
|
+
if (this._isSolidKinematicMotionDriven(solid)) {
|
|
1049
|
+
this._rotateSolidAroundWorldAxis(solid, axis.start, axis.end, THREE.MathUtils.degToRad(deltaDeg));
|
|
1050
|
+
const worldPosition = solid.getWorldPosition(new THREE.Vector3());
|
|
1051
|
+
const worldQuaternion = solid.getWorldQuaternion(new THREE.Quaternion());
|
|
1052
|
+
body.setNextKinematicTranslation(worldPosition);
|
|
1053
|
+
body.setNextKinematicRotation(worldQuaternion);
|
|
1054
|
+
this._updateRuntimeTransformFromSolid(solid, { persist: false });
|
|
1055
|
+
this._movedSolidIds.add(solid.uuid);
|
|
1056
|
+
state.progress += deltaDeg;
|
|
1057
|
+
if (limitDeg != null && Math.abs(limitDeg - state.progress) <= 1e-9) state.completed = true;
|
|
1058
|
+
this._motionState.set(motion.id, state);
|
|
1059
|
+
return true;
|
|
1060
|
+
}
|
|
1061
|
+
const omega = THREE.MathUtils.degToRad(deltaDeg) / Math.max(dt, 1e-9);
|
|
1062
|
+
const scratch = this._scratch;
|
|
1063
|
+
const command = this._getMotionCommand(commands, solid);
|
|
1064
|
+
const translation = body.translation();
|
|
1065
|
+
scratch.axis.copy(axis.end).sub(axis.start).normalize().multiplyScalar(omega);
|
|
1066
|
+
scratch.radius.set(
|
|
1067
|
+
Number(translation?.x) || 0,
|
|
1068
|
+
Number(translation?.y) || 0,
|
|
1069
|
+
Number(translation?.z) || 0,
|
|
1070
|
+
).sub(axis.start);
|
|
1071
|
+
scratch.velocity.copy(scratch.axis).cross(scratch.radius);
|
|
1072
|
+
command.angular.x += scratch.axis.x;
|
|
1073
|
+
command.angular.y += scratch.axis.y;
|
|
1074
|
+
command.angular.z += scratch.axis.z;
|
|
1075
|
+
command.linear.x += scratch.velocity.x;
|
|
1076
|
+
command.linear.y += scratch.velocity.y;
|
|
1077
|
+
command.linear.z += scratch.velocity.z;
|
|
1020
1078
|
state.progress += deltaDeg;
|
|
1021
1079
|
if (limitDeg != null && Math.abs(limitDeg - state.progress) <= 1e-9) state.completed = true;
|
|
1022
1080
|
this._motionState.set(motion.id, state);
|
|
1023
|
-
this._updateRuntimeTransformFromSolid(solid, { persist: false });
|
|
1024
|
-
this._movedSolidIds.add(solid.uuid);
|
|
1025
1081
|
return true;
|
|
1026
1082
|
}
|
|
1027
1083
|
|
|
1028
|
-
_applyLinearMotionStep(solid, motion, dt) {
|
|
1084
|
+
_applyLinearMotionStep(solid, motion, dt, commands) {
|
|
1029
1085
|
const state = this._motionState.get(motion.id) || { progress: 0, completed: false };
|
|
1030
|
-
if (state.completed) return;
|
|
1086
|
+
if (state.completed) return false;
|
|
1031
1087
|
const axis = this._resolveMotionAxis(motion);
|
|
1032
|
-
if (!axis) return;
|
|
1088
|
+
if (!axis) return false;
|
|
1089
|
+
const body = this._bodyState.get(solid.uuid)?.body || null;
|
|
1090
|
+
if (!body) return false;
|
|
1033
1091
|
const speed = Number(motion?.speed);
|
|
1034
|
-
if (!Number.isFinite(speed) || Math.abs(speed) <= 1e-9) return;
|
|
1092
|
+
if (!Number.isFinite(speed) || Math.abs(speed) <= 1e-9) return false;
|
|
1035
1093
|
let delta = speed * dt;
|
|
1036
|
-
const limit =
|
|
1094
|
+
const limit = normalizeOptionalMotionLimit(motion?.distance);
|
|
1037
1095
|
if (limit != null) {
|
|
1038
1096
|
const remaining = limit - state.progress;
|
|
1039
1097
|
if (Math.abs(remaining) <= 1e-9) {
|
|
@@ -1047,12 +1105,38 @@ export class SimulationWorkbenchManager {
|
|
|
1047
1105
|
if (Math.abs(delta) > Math.abs(remaining)) delta = remaining;
|
|
1048
1106
|
}
|
|
1049
1107
|
if (Math.abs(delta) <= 1e-9) return false;
|
|
1050
|
-
this.
|
|
1108
|
+
if (this._isSolidKinematicMotionDriven(solid)) {
|
|
1109
|
+
this._translateSolidAlongWorldAxis(solid, axis.start, axis.end, delta);
|
|
1110
|
+
const worldPosition = solid.getWorldPosition(new THREE.Vector3());
|
|
1111
|
+
const worldQuaternion = solid.getWorldQuaternion(new THREE.Quaternion());
|
|
1112
|
+
body.setNextKinematicTranslation(worldPosition);
|
|
1113
|
+
body.setNextKinematicRotation(worldQuaternion);
|
|
1114
|
+
this._updateRuntimeTransformFromSolid(solid, { persist: false });
|
|
1115
|
+
this._movedSolidIds.add(solid.uuid);
|
|
1116
|
+
state.progress += delta;
|
|
1117
|
+
if (limit != null && Math.abs(limit - state.progress) <= 1e-9) state.completed = true;
|
|
1118
|
+
this._motionState.set(motion.id, state);
|
|
1119
|
+
return true;
|
|
1120
|
+
}
|
|
1121
|
+
const velocityScale = delta / Math.max(dt, 1e-9);
|
|
1122
|
+
const scratch = this._scratch;
|
|
1123
|
+
const command = this._getMotionCommand(commands, solid);
|
|
1124
|
+
const translation = body.translation();
|
|
1125
|
+
scratch.axis.copy(axis.end).sub(axis.start).normalize();
|
|
1126
|
+
scratch.translation.copy(scratch.axis).multiplyScalar(delta);
|
|
1127
|
+
body.setTranslation({
|
|
1128
|
+
x: (Number(translation?.x) || 0) + scratch.translation.x,
|
|
1129
|
+
y: (Number(translation?.y) || 0) + scratch.translation.y,
|
|
1130
|
+
z: (Number(translation?.z) || 0) + scratch.translation.z,
|
|
1131
|
+
}, true);
|
|
1132
|
+
scratch.axis.multiplyScalar(velocityScale);
|
|
1133
|
+
command.linear.x += scratch.axis.x;
|
|
1134
|
+
command.linear.y += scratch.axis.y;
|
|
1135
|
+
command.linear.z += scratch.axis.z;
|
|
1136
|
+
body.setAngvel({ x: 0, y: 0, z: 0 }, true);
|
|
1051
1137
|
state.progress += delta;
|
|
1052
1138
|
if (limit != null && Math.abs(limit - state.progress) <= 1e-9) state.completed = true;
|
|
1053
1139
|
this._motionState.set(motion.id, state);
|
|
1054
|
-
this._updateRuntimeTransformFromSolid(solid, { persist: false });
|
|
1055
|
-
this._movedSolidIds.add(solid.uuid);
|
|
1056
1140
|
return true;
|
|
1057
1141
|
}
|
|
1058
1142
|
|