diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index d802340..0000000 --- a/dist/index.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! For license information please see index.js.LICENSE.txt */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("three"),require("plotly.js-dist"),require("three/examples/jsm/Addons"),require("three/examples/jsm/libs/stats.module")):"function"==typeof define&&define.amd?define(["three","plotly.js-dist","three/examples/jsm/Addons","three/examples/jsm/libs/stats.module"],e):"object"==typeof exports?exports.nbody=e(require("three"),require("plotly.js-dist"),require("three/examples/jsm/Addons"),require("three/examples/jsm/libs/stats.module")):t.nbody=e(t.three,t["plotly.js-dist"],t["three/examples/jsm/Addons"],t["three/examples/jsm/libs/stats.module"])}(this,((t,e,i,s)=>(()=>{"use strict";var n={924:t=>{t.exports=e},604:e=>{e.exports=t},987:t=>{t.exports=i},686:t=>{t.exports=s}},o={};function r(t){var e=o[t];if(void 0!==e)return e.exports;var i=o[t]={exports:{}};return n[t](i,i.exports,r),i.exports}r.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return r.d(e,{a:e}),e},r.d=(t,e)=>{for(var i in e)r.o(e,i)&&!r.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},r.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var l={};return(()=>{r.r(l),r.d(l,{BodyCenterTransformation:()=>P,CelestialBody:()=>t,CentripetalForce:()=>s,CoMTransformation:()=>G,CombinedForce:()=>n,ExplicitEulerSim:()=>h,Gravity:()=>i,LambdaSim:()=>u,LambdaTransformation:()=>Y,RealTimeVisualizer:()=>z,RealTimeVisualizer3D:()=>O,RecordingVisualizer:()=>j,RecordingVisualizer3D:()=>U,RotateTransformation:()=>R,RungeKutta4Sim:()=>c,SemiImplicitEulerSim:()=>d,Simulation:()=>H,State:()=>o,Universe:()=>K,Vector3:()=>e.Vector3,VelocityVerletSim:()=>a});class t{constructor(t,e,i,s,n){this.label=t,this.mass=e,this.position=i,this.velocity=s,this.acceleration=n}clone(e,i,s){return new t(this.label,this.mass,void 0===e?this.position.clone():e,void 0===i?this.velocity.clone():i,void 0===s?this.acceleration.clone():s)}}var e=r(604);class i{constructor(t=6674e-14){this.G=t}getForces(t){let i=t.length,s=[];for(let t=0;t{const e=this.center.clone().sub(t.position);return e.setLength(t.mass*t.velocity.lengthSq()/e.length())}))}}class n{constructor(t){this.forces=t}getForces(t){const i=t.map((()=>new e.Vector3(0,0,0)));return this.forces.forEach((e=>{e.getForces(t).forEach(((t,e)=>{i[e].add(t)}))})),i}}class o{constructor(t){this.bodies=t}clone(){return new o(this.bodies.map((t=>t.clone())))}}class a{constructor(t){this.forceCalculator=t}simulate(t,e){if(t<=0)return e.clone();let i=e.bodies.map((e=>{let i=e.clone();return i.position=this.calcNewPos(i.position,i.velocity,i.acceleration,t),i})),s=this.forceCalculator.getForces(i);return new o(i.map(((e,i)=>{let n=s[i].divideScalar(e.mass);return e.velocity.add(e.acceleration.add(n).multiplyScalar(t/2)),e.acceleration=n,e})))}calcNewPos(t,e,i,s){return t.clone().add(e.clone().multiplyScalar(s)).add(i.clone().multiplyScalar(s*s*.5))}}class h{constructor(t){this.force=t}simulate(t,e){const i=e.bodies.map((e=>e.clone(this.rateUpdate(e.position,e.velocity,t),this.rateUpdate(e.velocity,e.acceleration,t)))),s=this.force.getForces(i);return i.forEach(((t,e)=>{t.acceleration=s[e].divideScalar(t.mass)})),new o(i)}rateUpdate(t,e,i){return e.clone().multiplyScalar(i).add(t)}}class d{constructor(t){this.force=t}simulate(t,e){const i=e.bodies.map((e=>{const i=this.rateUpdate(e.velocity,e.acceleration,t);return e.clone(this.rateUpdate(e.position,i,t),i)})),s=this.force.getForces(i);return i.forEach(((t,e)=>{t.acceleration=s[e].divideScalar(t.mass)})),new o(i)}rateUpdate(t,e,i){return e.clone().multiplyScalar(i).add(t)}}class c{constructor(t,e){if(this.force=t,4!==e.length)throw new Error("Weights for RK4 must be of length 4");this.weights=e}simulate(t,i){let s=i.bodies.map((t=>({kv:[t.acceleration.clone()],kx:[t.velocity.clone()]})));const n=this.getInterKV(i.bodies,s,0,t/2),r=this.getInterKX(i.bodies,s,0,t/2);s.forEach(((t,e)=>{t.kv.push(n[e]),t.kx.push(r[e])}));const l=this.getInterKV(i.bodies,s,1,t/2),a=this.getInterKX(i.bodies,s,1,t/2);s.forEach(((t,e)=>{t.kv.push(l[e]),t.kx.push(a[e])}));const h=this.getInterKV(i.bodies,s,2,t),d=this.getInterKX(i.bodies,s,2,t);s.forEach(((t,e)=>{t.kv.push(h[e]),t.kx.push(d[e])}));const c=i.bodies.map(((i,n)=>{const o=new e.Vector3,r=new e.Vector3;return s[n].kx.forEach(((t,e)=>{o.add(t.multiplyScalar(this.weights[e]))})),s[n].kv.forEach(((t,e)=>{r.add(t.multiplyScalar(this.weights[e]))})),i.clone(o.multiplyScalar(t/6).add(i.position),r.multiplyScalar(t/6).add(i.velocity))})),u=this.force.getForces(c);return c.forEach(((t,e)=>{t.acceleration=u[e].divideScalar(t.mass)})),new o(c)}getInterKV(t,e,i,s){let n=t.map(((t,n)=>{let o=t.clone();return o.position.add(e[n].kx[i].clone().multiplyScalar(s)),o}));return this.force.getForces(n).map(((e,i)=>e.divideScalar(t[i].mass)))}getInterKX(t,e,i,s){return t.map(((t,n)=>t.velocity.clone().add(e[n].kv[i].clone().multiplyScalar(s))))}}class u{constructor(t){this.fn=t}simulate(t,e,i){return this.fn(t,e,i)}}class p{constructor(t,e,i,s,n="div"){this.parent=t,this.object=e,this.property=i,this._disabled=!1,this._hidden=!1,this.initialValue=this.getValue(),this.domElement=document.createElement(n),this.domElement.classList.add("controller"),this.domElement.classList.add(s),this.$name=document.createElement("div"),this.$name.classList.add("name"),p.nextNameID=p.nextNameID||0,this.$name.id="lil-gui-name-"+ ++p.nextNameID,this.$widget=document.createElement("div"),this.$widget.classList.add("widget"),this.$disable=this.$widget,this.domElement.appendChild(this.$name),this.domElement.appendChild(this.$widget),this.domElement.addEventListener("keydown",(t=>t.stopPropagation())),this.domElement.addEventListener("keyup",(t=>t.stopPropagation())),this.parent.children.push(this),this.parent.controllers.push(this),this.parent.$children.appendChild(this.domElement),this._listenCallback=this._listenCallback.bind(this),this.name(i)}name(t){return this._name=t,this.$name.textContent=t,this}onChange(t){return this._onChange=t,this}_callOnChange(){this.parent._callOnChange(this),void 0!==this._onChange&&this._onChange.call(this,this.getValue()),this._changed=!0}onFinishChange(t){return this._onFinishChange=t,this}_callOnFinishChange(){this._changed&&(this.parent._callOnFinishChange(this),void 0!==this._onFinishChange&&this._onFinishChange.call(this,this.getValue())),this._changed=!1}reset(){return this.setValue(this.initialValue),this._callOnFinishChange(),this}enable(t=!0){return this.disable(!t)}disable(t=!0){return t===this._disabled||(this._disabled=t,this.domElement.classList.toggle("disabled",t),this.$disable.toggleAttribute("disabled",t)),this}show(t=!0){return this._hidden=!t,this.domElement.style.display=this._hidden?"none":"",this}hide(){return this.show(!1)}options(t){const e=this.parent.add(this.object,this.property,t);return e.name(this._name),this.destroy(),e}min(t){return this}max(t){return this}step(t){return this}decimals(t){return this}listen(t=!0){return this._listening=t,void 0!==this._listenCallbackID&&(cancelAnimationFrame(this._listenCallbackID),this._listenCallbackID=void 0),this._listening&&this._listenCallback(),this}_listenCallback(){this._listenCallbackID=requestAnimationFrame(this._listenCallback);const t=this.save();t!==this._listenPrevValue&&this.updateDisplay(),this._listenPrevValue=t}getValue(){return this.object[this.property]}setValue(t){return this.getValue()!==t&&(this.object[this.property]=t,this._callOnChange(),this.updateDisplay()),this}updateDisplay(){return this}load(t){return this.setValue(t),this._callOnFinishChange(),this}save(){return this.getValue()}destroy(){this.listen(!1),this.parent.children.splice(this.parent.children.indexOf(this),1),this.parent.controllers.splice(this.parent.controllers.indexOf(this),1),this.parent.$children.removeChild(this.domElement)}}class m extends p{constructor(t,e,i){super(t,e,i,"boolean","label"),this.$input=document.createElement("input"),this.$input.setAttribute("type","checkbox"),this.$input.setAttribute("aria-labelledby",this.$name.id),this.$widget.appendChild(this.$input),this.$input.addEventListener("change",(()=>{this.setValue(this.$input.checked),this._callOnFinishChange()})),this.$disable=this.$input,this.updateDisplay()}updateDisplay(){return this.$input.checked=this.getValue(),this}}function g(t){let e,i;return(e=t.match(/(#|0x)?([a-f0-9]{6})/i))?i=e[2]:(e=t.match(/rgb\(\s*(\d*)\s*,\s*(\d*)\s*,\s*(\d*)\s*\)/))?i=parseInt(e[1]).toString(16).padStart(2,0)+parseInt(e[2]).toString(16).padStart(2,0)+parseInt(e[3]).toString(16).padStart(2,0):(e=t.match(/^#?([a-f0-9])([a-f0-9])([a-f0-9])$/i))&&(i=e[1]+e[1]+e[2]+e[2]+e[3]+e[3]),!!i&&"#"+i}const v={isPrimitive:!0,match:t=>"number"==typeof t,fromHexString:t=>parseInt(t.substring(1),16),toHexString:t=>"#"+t.toString(16).padStart(6,0)},b={isPrimitive:!1,match:t=>Array.isArray(t),fromHexString(t,e,i=1){const s=v.fromHexString(t);e[0]=(s>>16&255)/255*i,e[1]=(s>>8&255)/255*i,e[2]=(255&s)/255*i},toHexString:([t,e,i],s=1)=>v.toHexString(t*(s=255/s)<<16^e*s<<8^i*s)},f={isPrimitive:!1,match:t=>Object(t)===t,fromHexString(t,e,i=1){const s=v.fromHexString(t);e.r=(s>>16&255)/255*i,e.g=(s>>8&255)/255*i,e.b=(255&s)/255*i},toHexString:({r:t,g:e,b:i},s=1)=>v.toHexString(t*(s=255/s)<<16^e*s<<8^i*s)},w=[{isPrimitive:!0,match:t=>"string"==typeof t,fromHexString:g,toHexString:g},v,b,f];class y extends p{constructor(t,e,i,s){var n;super(t,e,i,"color"),this.$input=document.createElement("input"),this.$input.setAttribute("type","color"),this.$input.setAttribute("tabindex",-1),this.$input.setAttribute("aria-labelledby",this.$name.id),this.$text=document.createElement("input"),this.$text.setAttribute("type","text"),this.$text.setAttribute("spellcheck","false"),this.$text.setAttribute("aria-labelledby",this.$name.id),this.$display=document.createElement("div"),this.$display.classList.add("display"),this.$display.appendChild(this.$input),this.$widget.appendChild(this.$display),this.$widget.appendChild(this.$text),this._format=(n=this.initialValue,w.find((t=>t.match(n)))),this._rgbScale=s,this._initialValueHexString=this.save(),this._textFocused=!1,this.$input.addEventListener("input",(()=>{this._setValueFromHexString(this.$input.value)})),this.$input.addEventListener("blur",(()=>{this._callOnFinishChange()})),this.$text.addEventListener("input",(()=>{const t=g(this.$text.value);t&&this._setValueFromHexString(t)})),this.$text.addEventListener("focus",(()=>{this._textFocused=!0,this.$text.select()})),this.$text.addEventListener("blur",(()=>{this._textFocused=!1,this.updateDisplay(),this._callOnFinishChange()})),this.$disable=this.$text,this.updateDisplay()}reset(){return this._setValueFromHexString(this._initialValueHexString),this}_setValueFromHexString(t){if(this._format.isPrimitive){const e=this._format.fromHexString(t);this.setValue(e)}else this._format.fromHexString(t,this.getValue(),this._rgbScale),this._callOnChange(),this.updateDisplay()}save(){return this._format.toHexString(this.getValue(),this._rgbScale)}load(t){return this._setValueFromHexString(t),this._callOnFinishChange(),this}updateDisplay(){return this.$input.value=this._format.toHexString(this.getValue(),this._rgbScale),this._textFocused||(this.$text.value=this.$input.value.substring(1)),this.$display.style.backgroundColor=this.$input.value,this}}class A extends p{constructor(t,e,i){super(t,e,i,"function"),this.$button=document.createElement("button"),this.$button.appendChild(this.$name),this.$widget.appendChild(this.$button),this.$button.addEventListener("click",(t=>{t.preventDefault(),this.getValue().call(this.object),this._callOnChange()})),this.$button.addEventListener("touchstart",(()=>{}),{passive:!0}),this.$disable=this.$button}}class x extends p{constructor(t,e,i,s,n,o){super(t,e,i,"number"),this._initInput(),this.min(s),this.max(n);const r=void 0!==o;this.step(r?o:this._getImplicitStep(),r),this.updateDisplay()}decimals(t){return this._decimals=t,this.updateDisplay(),this}min(t){return this._min=t,this._onUpdateMinMax(),this}max(t){return this._max=t,this._onUpdateMinMax(),this}step(t,e=!0){return this._step=t,this._stepExplicit=e,this}updateDisplay(){const t=this.getValue();if(this._hasSlider){let e=(t-this._min)/(this._max-this._min);e=Math.max(0,Math.min(e,1)),this.$fill.style.width=100*e+"%"}return this._inputFocused||(this.$input.value=void 0===this._decimals?t:t.toFixed(this._decimals)),this}_initInput(){this.$input=document.createElement("input"),this.$input.setAttribute("type","text"),this.$input.setAttribute("aria-labelledby",this.$name.id),window.matchMedia("(pointer: coarse)").matches&&(this.$input.setAttribute("type","number"),this.$input.setAttribute("step","any")),this.$widget.appendChild(this.$input),this.$disable=this.$input;const t=t=>{const e=parseFloat(this.$input.value);isNaN(e)||(this._snapClampSetValue(e+t),this.$input.value=this.getValue())};let e,i,s,n,o,r=!1;const l=t=>{if(r){const s=t.clientX-e,n=t.clientY-i;Math.abs(n)>5?(t.preventDefault(),this.$input.blur(),r=!1,this._setDraggingStyle(!0,"vertical")):Math.abs(s)>5&&a()}if(!r){const e=t.clientY-s;o-=e*this._step*this._arrowKeyMultiplier(t),n+o>this._max?o=this._max-n:n+o{this._setDraggingStyle(!1,"vertical"),this._callOnFinishChange(),window.removeEventListener("mousemove",l),window.removeEventListener("mouseup",a)};this.$input.addEventListener("input",(()=>{let t=parseFloat(this.$input.value);isNaN(t)||(this._stepExplicit&&(t=this._snap(t)),this.setValue(this._clamp(t)))})),this.$input.addEventListener("keydown",(e=>{"Enter"===e.key&&this.$input.blur(),"ArrowUp"===e.code&&(e.preventDefault(),t(this._step*this._arrowKeyMultiplier(e))),"ArrowDown"===e.code&&(e.preventDefault(),t(this._step*this._arrowKeyMultiplier(e)*-1))})),this.$input.addEventListener("wheel",(e=>{this._inputFocused&&(e.preventDefault(),t(this._step*this._normalizeMouseWheel(e)))}),{passive:!1}),this.$input.addEventListener("mousedown",(t=>{e=t.clientX,i=s=t.clientY,r=!0,n=this.getValue(),o=0,window.addEventListener("mousemove",l),window.addEventListener("mouseup",a)})),this.$input.addEventListener("focus",(()=>{this._inputFocused=!0})),this.$input.addEventListener("blur",(()=>{this._inputFocused=!1,this.updateDisplay(),this._callOnFinishChange()}))}_initSlider(){this._hasSlider=!0,this.$slider=document.createElement("div"),this.$slider.classList.add("slider"),this.$fill=document.createElement("div"),this.$fill.classList.add("fill"),this.$slider.appendChild(this.$fill),this.$widget.insertBefore(this.$slider,this.$input),this.domElement.classList.add("hasSlider");const t=t=>{const e=this.$slider.getBoundingClientRect();let i=(s=t,n=e.left,o=e.right,r=this._min,(s-n)/(o-n)*(this._max-r)+r);var s,n,o,r;this._snapClampSetValue(i)},e=e=>{t(e.clientX)},i=()=>{this._callOnFinishChange(),this._setDraggingStyle(!1),window.removeEventListener("mousemove",e),window.removeEventListener("mouseup",i)};let s,n,o=!1;const r=e=>{e.preventDefault(),this._setDraggingStyle(!0),t(e.touches[0].clientX),o=!1},l=e=>{if(o){const t=e.touches[0].clientX-s,i=e.touches[0].clientY-n;Math.abs(t)>Math.abs(i)?r(e):(window.removeEventListener("touchmove",l),window.removeEventListener("touchend",a))}else e.preventDefault(),t(e.touches[0].clientX)},a=()=>{this._callOnFinishChange(),this._setDraggingStyle(!1),window.removeEventListener("touchmove",l),window.removeEventListener("touchend",a)},h=this._callOnFinishChange.bind(this);let d;this.$slider.addEventListener("mousedown",(s=>{this._setDraggingStyle(!0),t(s.clientX),window.addEventListener("mousemove",e),window.addEventListener("mouseup",i)})),this.$slider.addEventListener("touchstart",(t=>{t.touches.length>1||(this._hasScrollBar?(s=t.touches[0].clientX,n=t.touches[0].clientY,o=!0):r(t),window.addEventListener("touchmove",l,{passive:!1}),window.addEventListener("touchend",a))}),{passive:!1}),this.$slider.addEventListener("wheel",(t=>{if(Math.abs(t.deltaX)this._max&&(t=this._max),t}_snapClampSetValue(t){this.setValue(this._clamp(this._snap(t)))}get _hasScrollBar(){const t=this.parent.root.$children;return t.scrollHeight>t.clientHeight}get _hasMin(){return void 0!==this._min}get _hasMax(){return void 0!==this._max}}class E extends p{constructor(t,e,i,s){super(t,e,i,"option"),this.$select=document.createElement("select"),this.$select.setAttribute("aria-labelledby",this.$name.id),this.$display=document.createElement("div"),this.$display.classList.add("display"),this.$select.addEventListener("change",(()=>{this.setValue(this._values[this.$select.selectedIndex]),this._callOnFinishChange()})),this.$select.addEventListener("focus",(()=>{this.$display.classList.add("focus")})),this.$select.addEventListener("blur",(()=>{this.$display.classList.remove("focus")})),this.$widget.appendChild(this.$select),this.$widget.appendChild(this.$display),this.$disable=this.$select,this.options(s)}options(t){return this._values=Array.isArray(t)?t:Object.values(t),this._names=Array.isArray(t)?t:Object.keys(t),this.$select.replaceChildren(),this._names.forEach((t=>{const e=document.createElement("option");e.textContent=t,this.$select.appendChild(e)})),this.updateDisplay(),this}updateDisplay(){const t=this.getValue(),e=this._values.indexOf(t);return this.$select.selectedIndex=e,this.$display.textContent=-1===e?t:this._names[e],this}}class S extends p{constructor(t,e,i){super(t,e,i,"string"),this.$input=document.createElement("input"),this.$input.setAttribute("type","text"),this.$input.setAttribute("spellcheck","false"),this.$input.setAttribute("aria-labelledby",this.$name.id),this.$input.addEventListener("input",(()=>{this.setValue(this.$input.value)})),this.$input.addEventListener("keydown",(t=>{"Enter"===t.code&&this.$input.blur()})),this.$input.addEventListener("blur",(()=>{this._callOnFinishChange()})),this.$widget.appendChild(this.$input),this.$disable=this.$input,this.updateDisplay()}updateDisplay(){return this.$input.value=this.getValue(),this}}let _=!1;class ${constructor({parent:t,autoPlace:e=void 0===t,container:i,width:s,title:n="Controls",closeFolders:o=!1,injectStyles:r=!0,touchStyles:l=!0}={}){if(this.parent=t,this.root=t?t.root:this,this.children=[],this.controllers=[],this.folders=[],this._closed=!1,this._hidden=!1,this.domElement=document.createElement("div"),this.domElement.classList.add("lil-gui"),this.$title=document.createElement("div"),this.$title.classList.add("title"),this.$title.setAttribute("role","button"),this.$title.setAttribute("aria-expanded",!0),this.$title.setAttribute("tabindex",0),this.$title.addEventListener("click",(()=>this.openAnimated(this._closed))),this.$title.addEventListener("keydown",(t=>{"Enter"!==t.code&&"Space"!==t.code||(t.preventDefault(),this.$title.click())})),this.$title.addEventListener("touchstart",(()=>{}),{passive:!0}),this.$children=document.createElement("div"),this.$children.classList.add("children"),this.domElement.appendChild(this.$title),this.domElement.appendChild(this.$children),this.title(n),this.parent)return this.parent.children.push(this),this.parent.folders.push(this),void this.parent.$children.appendChild(this.domElement);this.domElement.classList.add("root"),l&&this.domElement.classList.add("allow-touch-styles"),!_&&r&&(function(t){const e=document.createElement("style");e.innerHTML='.lil-gui {\n font-family: var(--font-family);\n font-size: var(--font-size);\n line-height: 1;\n font-weight: normal;\n font-style: normal;\n text-align: left;\n color: var(--text-color);\n user-select: none;\n -webkit-user-select: none;\n touch-action: manipulation;\n --background-color: #1f1f1f;\n --text-color: #ebebeb;\n --title-background-color: #111111;\n --title-text-color: #ebebeb;\n --widget-color: #424242;\n --hover-color: #4f4f4f;\n --focus-color: #595959;\n --number-color: #2cc9ff;\n --string-color: #a2db3c;\n --font-size: 11px;\n --input-font-size: 11px;\n --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;\n --font-family-mono: Menlo, Monaco, Consolas, "Droid Sans Mono", monospace;\n --padding: 4px;\n --spacing: 4px;\n --widget-height: 20px;\n --title-height: calc(var(--widget-height) + var(--spacing) * 1.25);\n --name-width: 45%;\n --slider-knob-width: 2px;\n --slider-input-width: 27%;\n --color-input-width: 27%;\n --slider-input-min-width: 45px;\n --color-input-min-width: 45px;\n --folder-indent: 7px;\n --widget-padding: 0 0 0 3px;\n --widget-border-radius: 2px;\n --checkbox-size: calc(0.75 * var(--widget-height));\n --scrollbar-width: 5px;\n}\n.lil-gui, .lil-gui * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n.lil-gui.root {\n width: var(--width, 245px);\n display: flex;\n flex-direction: column;\n background: var(--background-color);\n}\n.lil-gui.root > .title {\n background: var(--title-background-color);\n color: var(--title-text-color);\n}\n.lil-gui.root > .children {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.lil-gui.root > .children::-webkit-scrollbar {\n width: var(--scrollbar-width);\n height: var(--scrollbar-width);\n background: var(--background-color);\n}\n.lil-gui.root > .children::-webkit-scrollbar-thumb {\n border-radius: var(--scrollbar-width);\n background: var(--focus-color);\n}\n@media (pointer: coarse) {\n .lil-gui.allow-touch-styles, .lil-gui.allow-touch-styles .lil-gui {\n --widget-height: 28px;\n --padding: 6px;\n --spacing: 6px;\n --font-size: 13px;\n --input-font-size: 16px;\n --folder-indent: 10px;\n --scrollbar-width: 7px;\n --slider-input-min-width: 50px;\n --color-input-min-width: 65px;\n }\n}\n.lil-gui.force-touch-styles, .lil-gui.force-touch-styles .lil-gui {\n --widget-height: 28px;\n --padding: 6px;\n --spacing: 6px;\n --font-size: 13px;\n --input-font-size: 16px;\n --folder-indent: 10px;\n --scrollbar-width: 7px;\n --slider-input-min-width: 50px;\n --color-input-min-width: 65px;\n}\n.lil-gui.autoPlace {\n max-height: 100%;\n position: fixed;\n top: 0;\n right: 15px;\n z-index: 1001;\n}\n\n.lil-gui .controller {\n display: flex;\n align-items: center;\n padding: 0 var(--padding);\n margin: var(--spacing) 0;\n}\n.lil-gui .controller.disabled {\n opacity: 0.5;\n}\n.lil-gui .controller.disabled, .lil-gui .controller.disabled * {\n pointer-events: none !important;\n}\n.lil-gui .controller > .name {\n min-width: var(--name-width);\n flex-shrink: 0;\n white-space: pre;\n padding-right: var(--spacing);\n line-height: var(--widget-height);\n}\n.lil-gui .controller .widget {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n min-height: var(--widget-height);\n}\n.lil-gui .controller.string input {\n color: var(--string-color);\n}\n.lil-gui .controller.boolean {\n cursor: pointer;\n}\n.lil-gui .controller.color .display {\n width: 100%;\n height: var(--widget-height);\n border-radius: var(--widget-border-radius);\n position: relative;\n}\n@media (hover: hover) {\n .lil-gui .controller.color .display:hover:before {\n content: " ";\n display: block;\n position: absolute;\n border-radius: var(--widget-border-radius);\n border: 1px solid #fff9;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n }\n}\n.lil-gui .controller.color input[type=color] {\n opacity: 0;\n width: 100%;\n height: 100%;\n cursor: pointer;\n}\n.lil-gui .controller.color input[type=text] {\n margin-left: var(--spacing);\n font-family: var(--font-family-mono);\n min-width: var(--color-input-min-width);\n width: var(--color-input-width);\n flex-shrink: 0;\n}\n.lil-gui .controller.option select {\n opacity: 0;\n position: absolute;\n width: 100%;\n max-width: 100%;\n}\n.lil-gui .controller.option .display {\n position: relative;\n pointer-events: none;\n border-radius: var(--widget-border-radius);\n height: var(--widget-height);\n line-height: var(--widget-height);\n max-width: 100%;\n overflow: hidden;\n word-break: break-all;\n padding-left: 0.55em;\n padding-right: 1.75em;\n background: var(--widget-color);\n}\n@media (hover: hover) {\n .lil-gui .controller.option .display.focus {\n background: var(--focus-color);\n }\n}\n.lil-gui .controller.option .display.active {\n background: var(--focus-color);\n}\n.lil-gui .controller.option .display:after {\n font-family: "lil-gui";\n content: "↕";\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n padding-right: 0.375em;\n}\n.lil-gui .controller.option .widget,\n.lil-gui .controller.option select {\n cursor: pointer;\n}\n@media (hover: hover) {\n .lil-gui .controller.option .widget:hover .display {\n background: var(--hover-color);\n }\n}\n.lil-gui .controller.number input {\n color: var(--number-color);\n}\n.lil-gui .controller.number.hasSlider input {\n margin-left: var(--spacing);\n width: var(--slider-input-width);\n min-width: var(--slider-input-min-width);\n flex-shrink: 0;\n}\n.lil-gui .controller.number .slider {\n width: 100%;\n height: var(--widget-height);\n background: var(--widget-color);\n border-radius: var(--widget-border-radius);\n padding-right: var(--slider-knob-width);\n overflow: hidden;\n cursor: ew-resize;\n touch-action: pan-y;\n}\n@media (hover: hover) {\n .lil-gui .controller.number .slider:hover {\n background: var(--hover-color);\n }\n}\n.lil-gui .controller.number .slider.active {\n background: var(--focus-color);\n}\n.lil-gui .controller.number .slider.active .fill {\n opacity: 0.95;\n}\n.lil-gui .controller.number .fill {\n height: 100%;\n border-right: var(--slider-knob-width) solid var(--number-color);\n box-sizing: content-box;\n}\n\n.lil-gui-dragging .lil-gui {\n --hover-color: var(--widget-color);\n}\n.lil-gui-dragging * {\n cursor: ew-resize !important;\n}\n\n.lil-gui-dragging.lil-gui-vertical * {\n cursor: ns-resize !important;\n}\n\n.lil-gui .title {\n height: var(--title-height);\n line-height: calc(var(--title-height) - 4px);\n font-weight: 600;\n padding: 0 var(--padding);\n -webkit-tap-highlight-color: transparent;\n cursor: pointer;\n outline: none;\n text-decoration-skip: objects;\n}\n.lil-gui .title:before {\n font-family: "lil-gui";\n content: "▾";\n padding-right: 2px;\n display: inline-block;\n}\n.lil-gui .title:active {\n background: var(--title-background-color);\n opacity: 0.75;\n}\n@media (hover: hover) {\n body:not(.lil-gui-dragging) .lil-gui .title:hover {\n background: var(--title-background-color);\n opacity: 0.85;\n }\n .lil-gui .title:focus {\n text-decoration: underline var(--focus-color);\n }\n}\n.lil-gui.root > .title:focus {\n text-decoration: none !important;\n}\n.lil-gui.closed > .title:before {\n content: "▸";\n}\n.lil-gui.closed > .children {\n transform: translateY(-7px);\n opacity: 0;\n}\n.lil-gui.closed:not(.transition) > .children {\n display: none;\n}\n.lil-gui.transition > .children {\n transition-duration: 300ms;\n transition-property: height, opacity, transform;\n transition-timing-function: cubic-bezier(0.2, 0.6, 0.35, 1);\n overflow: hidden;\n pointer-events: none;\n}\n.lil-gui .children:empty:before {\n content: "Empty";\n padding: 0 var(--padding);\n margin: var(--spacing) 0;\n display: block;\n height: var(--widget-height);\n font-style: italic;\n line-height: var(--widget-height);\n opacity: 0.5;\n}\n.lil-gui.root > .children > .lil-gui > .title {\n border: 0 solid var(--widget-color);\n border-width: 1px 0;\n transition: border-color 300ms;\n}\n.lil-gui.root > .children > .lil-gui.closed > .title {\n border-bottom-color: transparent;\n}\n.lil-gui + .controller {\n border-top: 1px solid var(--widget-color);\n margin-top: 0;\n padding-top: var(--spacing);\n}\n.lil-gui .lil-gui .lil-gui > .title {\n border: none;\n}\n.lil-gui .lil-gui .lil-gui > .children {\n border: none;\n margin-left: var(--folder-indent);\n border-left: 2px solid var(--widget-color);\n}\n.lil-gui .lil-gui .controller {\n border: none;\n}\n\n.lil-gui label, .lil-gui input, .lil-gui button {\n -webkit-tap-highlight-color: transparent;\n}\n.lil-gui input {\n border: 0;\n outline: none;\n font-family: var(--font-family);\n font-size: var(--input-font-size);\n border-radius: var(--widget-border-radius);\n height: var(--widget-height);\n background: var(--widget-color);\n color: var(--text-color);\n width: 100%;\n}\n@media (hover: hover) {\n .lil-gui input:hover {\n background: var(--hover-color);\n }\n .lil-gui input:active {\n background: var(--focus-color);\n }\n}\n.lil-gui input:disabled {\n opacity: 1;\n}\n.lil-gui input[type=text],\n.lil-gui input[type=number] {\n padding: var(--widget-padding);\n -moz-appearance: textfield;\n}\n.lil-gui input[type=text]:focus,\n.lil-gui input[type=number]:focus {\n background: var(--focus-color);\n}\n.lil-gui input[type=checkbox] {\n appearance: none;\n width: var(--checkbox-size);\n height: var(--checkbox-size);\n border-radius: var(--widget-border-radius);\n text-align: center;\n cursor: pointer;\n}\n.lil-gui input[type=checkbox]:checked:before {\n font-family: "lil-gui";\n content: "✓";\n font-size: var(--checkbox-size);\n line-height: var(--checkbox-size);\n}\n@media (hover: hover) {\n .lil-gui input[type=checkbox]:focus {\n box-shadow: inset 0 0 0 1px var(--focus-color);\n }\n}\n.lil-gui button {\n outline: none;\n cursor: pointer;\n font-family: var(--font-family);\n font-size: var(--font-size);\n color: var(--text-color);\n width: 100%;\n height: var(--widget-height);\n text-transform: none;\n background: var(--widget-color);\n border-radius: var(--widget-border-radius);\n border: none;\n}\n@media (hover: hover) {\n .lil-gui button:hover {\n background: var(--hover-color);\n }\n .lil-gui button:focus {\n box-shadow: inset 0 0 0 1px var(--focus-color);\n }\n}\n.lil-gui button:active {\n background: var(--focus-color);\n}\n\n@font-face {\n font-family: "lil-gui";\n src: url("data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAUsAAsAAAAACJwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAAH4AAADAImwmYE9TLzIAAAGIAAAAPwAAAGBKqH5SY21hcAAAAcgAAAD0AAACrukyyJBnbHlmAAACvAAAAF8AAACEIZpWH2hlYWQAAAMcAAAAJwAAADZfcj2zaGhlYQAAA0QAAAAYAAAAJAC5AHhobXR4AAADXAAAABAAAABMAZAAAGxvY2EAAANsAAAAFAAAACgCEgIybWF4cAAAA4AAAAAeAAAAIAEfABJuYW1lAAADoAAAASIAAAIK9SUU/XBvc3QAAATEAAAAZgAAAJCTcMc2eJxVjbEOgjAURU+hFRBK1dGRL+ALnAiToyMLEzFpnPz/eAshwSa97517c/MwwJmeB9kwPl+0cf5+uGPZXsqPu4nvZabcSZldZ6kfyWnomFY/eScKqZNWupKJO6kXN3K9uCVoL7iInPr1X5baXs3tjuMqCtzEuagm/AAlzQgPAAB4nGNgYRBlnMDAysDAYM/gBiT5oLQBAwuDJAMDEwMrMwNWEJDmmsJwgCFeXZghBcjlZMgFCzOiKOIFAB71Bb8AeJy1kjFuwkAQRZ+DwRAwBtNQRUGKQ8OdKCAWUhAgKLhIuAsVSpWz5Bbkj3dEgYiUIszqWdpZe+Z7/wB1oCYmIoboiwiLT2WjKl/jscrHfGg/pKdMkyklC5Zs2LEfHYpjcRoPzme9MWWmk3dWbK9ObkWkikOetJ554fWyoEsmdSlt+uR0pCJR34b6t/TVg1SY3sYvdf8vuiKrpyaDXDISiegp17p7579Gp3p++y7HPAiY9pmTibljrr85qSidtlg4+l25GLCaS8e6rRxNBmsnERunKbaOObRz7N72ju5vdAjYpBXHgJylOAVsMseDAPEP8LYoUHicY2BiAAEfhiAGJgZWBgZ7RnFRdnVJELCQlBSRlATJMoLV2DK4glSYs6ubq5vbKrJLSbGrgEmovDuDJVhe3VzcXFwNLCOILB/C4IuQ1xTn5FPilBTj5FPmBAB4WwoqAHicY2BkYGAA4sk1sR/j+W2+MnAzpDBgAyEMQUCSg4EJxAEAwUgFHgB4nGNgZGBgSGFggJMhDIwMqEAYAByHATJ4nGNgAIIUNEwmAABl3AGReJxjYAACIQYlBiMGJ3wQAEcQBEV4nGNgZGBgEGZgY2BiAAEQyQWEDAz/wXwGAAsPATIAAHicXdBNSsNAHAXwl35iA0UQXYnMShfS9GPZA7T7LgIu03SSpkwzYTIt1BN4Ak/gKTyAeCxfw39jZkjymzcvAwmAW/wgwHUEGDb36+jQQ3GXGot79L24jxCP4gHzF/EIr4jEIe7wxhOC3g2TMYy4Q7+Lu/SHuEd/ivt4wJd4wPxbPEKMX3GI5+DJFGaSn4qNzk8mcbKSR6xdXdhSzaOZJGtdapd4vVPbi6rP+cL7TGXOHtXKll4bY1Xl7EGnPtp7Xy2n00zyKLVHfkHBa4IcJ2oD3cgggWvt/V/FbDrUlEUJhTn/0azVWbNTNr0Ens8de1tceK9xZmfB1CPjOmPH4kitmvOubcNpmVTN3oFJyjzCvnmrwhJTzqzVj9jiSX911FjeAAB4nG3HMRKCMBBA0f0giiKi4DU8k0V2GWbIZDOh4PoWWvq6J5V8If9NVNQcaDhyouXMhY4rPTcG7jwYmXhKq8Wz+p762aNaeYXom2n3m2dLTVgsrCgFJ7OTmIkYbwIbC6vIB7WmFfAAAA==") format("woff");\n}';const i=document.querySelector("head link[rel=stylesheet], head style");i?document.head.insertBefore(e,i):document.head.appendChild(e)}(),_=!0),i?i.appendChild(this.domElement):e&&(this.domElement.classList.add("autoPlace"),document.body.appendChild(this.domElement)),s&&this.domElement.style.setProperty("--width",s+"px"),this._closeFolders=o}add(t,e,i,s,n){if(Object(i)===i)return new E(this,t,e,i);const o=t[e];switch(typeof o){case"number":return new x(this,t,e,i,s,n);case"boolean":return new m(this,t,e);case"string":return new S(this,t,e);case"function":return new A(this,t,e)}console.error("gui.add failed\n\tproperty:",e,"\n\tobject:",t,"\n\tvalue:",o)}addColor(t,e,i=1){return new y(this,t,e,i)}addFolder(t){const e=new $({parent:this,title:t});return this.root._closeFolders&&e.close(),e}load(t,e=!0){return t.controllers&&this.controllers.forEach((e=>{e instanceof A||e._name in t.controllers&&e.load(t.controllers[e._name])})),e&&t.folders&&this.folders.forEach((e=>{e._title in t.folders&&e.load(t.folders[e._title])})),this}save(t=!0){const e={controllers:{},folders:{}};return this.controllers.forEach((t=>{if(!(t instanceof A)){if(t._name in e.controllers)throw new Error(`Cannot save GUI with duplicate property "${t._name}"`);e.controllers[t._name]=t.save()}})),t&&this.folders.forEach((t=>{if(t._title in e.folders)throw new Error(`Cannot save GUI with duplicate folder "${t._title}"`);e.folders[t._title]=t.save()})),e}open(t=!0){return this._setClosed(!t),this.$title.setAttribute("aria-expanded",!this._closed),this.domElement.classList.toggle("closed",this._closed),this}close(){return this.open(!1)}_setClosed(t){this._closed!==t&&(this._closed=t,this._callOnOpenClose(this))}show(t=!0){return this._hidden=!t,this.domElement.style.display=this._hidden?"none":"",this}hide(){return this.show(!1)}openAnimated(t=!0){return this._setClosed(!t),this.$title.setAttribute("aria-expanded",!this._closed),requestAnimationFrame((()=>{const e=this.$children.clientHeight;this.$children.style.height=e+"px",this.domElement.classList.add("transition");const i=t=>{t.target===this.$children&&(this.$children.style.height="",this.domElement.classList.remove("transition"),this.$children.removeEventListener("transitionend",i))};this.$children.addEventListener("transitionend",i);const s=t?this.$children.scrollHeight:0;this.domElement.classList.toggle("closed",!t),requestAnimationFrame((()=>{this.$children.style.height=s+"px"}))})),this}title(t){return this._title=t,this.$title.textContent=t,this}reset(t=!0){return(t?this.controllersRecursive():this.controllers).forEach((t=>t.reset())),this}onChange(t){return this._onChange=t,this}_callOnChange(t){this.parent&&this.parent._callOnChange(t),void 0!==this._onChange&&this._onChange.call(this,{object:t.object,property:t.property,value:t.getValue(),controller:t})}onFinishChange(t){return this._onFinishChange=t,this}_callOnFinishChange(t){this.parent&&this.parent._callOnFinishChange(t),void 0!==this._onFinishChange&&this._onFinishChange.call(this,{object:t.object,property:t.property,value:t.getValue(),controller:t})}onOpenClose(t){return this._onOpenClose=t,this}_callOnOpenClose(t){this.parent&&this.parent._callOnOpenClose(t),void 0!==this._onOpenClose&&this._onOpenClose.call(this,t)}destroy(){this.parent&&(this.parent.children.splice(this.parent.children.indexOf(this),1),this.parent.folders.splice(this.parent.folders.indexOf(this),1)),this.domElement.parentElement&&this.domElement.parentElement.removeChild(this.domElement),Array.from(this.children).forEach((t=>t.destroy()))}controllersRecursive(){let t=Array.from(this.controllers);return this.folders.forEach((e=>{t=t.concat(e.controllersRecursive())})),t}foldersRecursive(){let t=Array.from(this.folders);return this.folders.forEach((e=>{t=t.concat(e.foldersRecursive())})),t}}const C=$;var L=r(924),T=r.n(L),k=r(987),F=r(686),M=r.n(F);let I=null;function D(t,e,i){return ti?i:t}class V{constructor(t,e){this.data={x:[],y:[],mode:"markers",marker:{size:1,color:"white"}},this.data.marker.color=e,this.trailLength=0,this.maxTrailLength=t,this.trailInd=0}addTrail(t,e){this.trailLength{!1===t&&this.universeTrails.forEach((t=>t.popAllTrails())),i.showTrails=t}));const s=e.addFolder("Show Universe");s.open(!1),this.simulation.universes.forEach(((t,e)=>{s.add(i.showUniverse,t.label).onChange((s=>{!1===s&&this.universeTrails[e].popAllTrails(),i.showUniverse[t.label]=s}))}))}start(t,e,i){if(""!==this.divId)return void console.error("Simulation already playing. Stop the current playtime before initiating a new one.");this.divId=t;let s=document.getElementById(t);if(null===s)return;let n=0,o=0;this.simulation.universes.forEach((t=>t.currState.bodies.forEach((t=>{n=Math.max(n,Math.abs(t.position.x)),o=Math.max(o,Math.abs(t.position.y))}))));const r=.5*Math.min(i/o,e/n),l={paper_bgcolor:"#000000",plot_bgcolor:"#000000",font:{color:"#bfbfbf"},xaxis:{autorange:!1,range:[-e/2/r,e/2/r]},yaxis:{autorange:!1,range:[-i/2/r,i/2/r]},showlegend:!1};let a;"ui"===this.simulation.controller&&this.addControls(s),this.simulation.showDebugInfo&&(a=new(M()),a.dom.style.position="absolute",a.dom.style.bottom="0px",a.dom.style.removeProperty("top"),s.appendChild(a.dom));const h=this.simulation.universes.flatMap((t=>{const e=new V(this.simulation.getMaxTrailLength(),"string"==typeof t.color?t.color:t.color[0]);this.universeTrails.push(e);const i={x:t.currState.bodies.map((t=>t.position.x)),y:t.currState.bodies.map((t=>t.position.y)),type:"scatter",mode:"markers",marker:{color:t.color,sizemin:6,size:t.currState.bodies.map((t=>Math.min(10,t.mass)))}};return this.simulation.getShowTrails()?(t.currState.bodies.forEach((t=>{e.addTrail(t.position.x,t.position.y)})),[i,e.data]):[i,{x:[],y:[]}]}));T().newPlot(t,h,l,{scrollZoom:!0,modeBarButtonsToRemove:["lasso2d","select2d","toImage","resetScale2d"]});const d=1e3/this.simulation.maxFrameRate;if(null!==I)return;let c=0,u=0;const p=t=>{this.simulation.simulateStep(this.simulation.controls.speed*Math.min(t-u,33.33)/1e3),u=t},m=e=>{if(0===this.simulation.controls.speed||this.simulation.controls.paused)return void(I=requestAnimationFrame(m));if(p(e),d>0&&e-c{if(!this.simulation.getShowUniverse(t.label))return[{x:[],y:[]},{}];const i={x:t.currState.bodies.map((t=>t.position.x)),y:t.currState.bodies.map((t=>t.position.y)),hovertext:t.currState.bodies.map((t=>t.label)),marker:{size:t.currState.bodies.map((t=>Math.min(10,t.mass))),color:t.color,sizemin:6},mode:"markers"};let s={};if(this.simulation.getShowTrails()){const i=this.universeTrails[e];t.currState.bodies.forEach((t=>{i.addTrail(t.position.x,t.position.y)})),s=i.data}return[i,s]}));T().react(t,i,l),this.simulation.showDebugInfo&&a&&a.update(),I=requestAnimationFrame(m)};I=requestAnimationFrame(m)}stop(){T().purge(this.divId),this.divId="",this.universeTrails.forEach((t=>{t.popAllTrails()})),this.universeTrails=[]}}class B{constructor(t,i,s,n){const o=new e.BufferGeometry;o.setAttribute("position",new e.BufferAttribute(new Float32Array(0),3)),this.trails=new e.Points(o,new e.PointsMaterial({color:i,size:.005*n})),s.add(this.trails),this.trailInd=0,this.trailLength=0,this.maxTrailLength=t}addTrail(t){if(this.trailLength{!1===t&&this.universeTrails.forEach((t=>{t.popAllTrails()})),i.showTrails=t}));const s=e.addFolder("Show Universe");s.open(!1),this.simulation.universes.forEach(((t,e)=>{s.add(i.showUniverse,t.label).onChange((s=>{!1===s&&this.universeTrails[e].popAllTrails(),i.showUniverse[t.label]=s}))}))}start(t,i,s){if(void 0!==this.scene)return void console.error("Simulation already playing. Stop the current playtime before initiating a new one.");let n=document.getElementById(t);if(null===n)return;n.style.position="relative";let o=0,r=0;this.simulation.universes.forEach((t=>t.currState.bodies.forEach((t=>{o=Math.max(o,Math.abs(t.position.x)),r=Math.max(r,Math.abs(t.position.y))}))));const l=.5*Math.min(s/r,i/o);this.scene=new e.Scene;const a=new e.OrthographicCamera(i/-2,i/2,s/2,s/-2,0,1e10);a.position.set(0,0,Math.max(i,s));const h=new e.WebGLRenderer;let d;h.setSize(i,s),h.autoClear=!1,n.appendChild(h.domElement),this.simulation.showDebugInfo&&(d=new(M()),d.dom.style.position="absolute",d.dom.style.right="0px",d.dom.style.removeProperty("left"),n.appendChild(d.dom)),"ui"===this.simulation.controller&&this.addControls(n);const c=new k.OrbitControls(a,h.domElement);c.listenToKeyEvents(window),c.update();const u=new e.AxesHelper(i);this.scene.add(u);const p=new k.ViewHelper(a,h.domElement);let m=[];this.simulation.universes.forEach((t=>{this.universeTrails.push(new B(this.simulation.maxTrailLength,"string"==typeof t.color?t.color:t.color[0],this.scene,l)),t.currState.bodies.forEach((i=>{const s=new e.SphereGeometry(D(Math.log2(i.mass)-70,10,40),8,8),n=new e.WireframeGeometry(s),o=new e.LineSegments(n,new e.LineBasicMaterial({color:new e.Color(t.color)}));this.scene.add(o),o.position.copy(i.position.clone().multiplyScalar(l)),m.push(o)}))}));const g=1e3/this.simulation.maxFrameRate;let v=performance.now(),b=performance.now();const f=t=>{this.simulation.simulateStep(this.simulation.controls.speed*Math.min(t-v,16.67)/1e3),v=t},w=t=>{if(0===this.simulation.controls.speed||this.simulation.controls.paused)return requestAnimationFrame(w),h.clear(),h.render(this.scene,a),p.render(h),void c.update();if(f(t),g>0&&t-b{this.simulation.controls.showUniverse[t.label]?t.currState.bodies.forEach((t=>{m[e].visible=!0,m[e].position.copy(t.position.clone().multiplyScalar(l)),this.simulation.controls.showTrails&&this.universeTrails[i].addTrail(m[e].position),e++})):t.currState.bodies.forEach((t=>{m[e].visible=!1,e++}))})),requestAnimationFrame(w),h.clear(),h.render(this.scene,a),p.render(h),c.update()};requestAnimationFrame(w)}stop(){var t;null===(t=this.scene)||void 0===t||t.clear(),this.scene=void 0,this.universeTrails.forEach((t=>{t.popAllTrails()})),this.universeTrails=[]}}class j{constructor(t){this.divId="",this.universeTrails=[],this.simulation=t}addControls(t){const e=new C({container:t});e.domElement.style.position="absolute",e.domElement.style.top="0",e.domElement.style.left="0",e.domElement.style.zIndex="1000";const i=this.simulation.controls;e.add(i,"speed"),e.add(i,"showTrails").onChange((t=>{!1===t&&this.universeTrails.forEach((t=>t.popAllTrails())),i.showTrails=t}));const s=e.addFolder("Show Universe");s.open(!1),this.simulation.universes.forEach(((t,e)=>{s.add(i.showUniverse,t.label).onChange((s=>{!1===s&&this.universeTrails[e].popAllTrails(),i.showUniverse[t.label]=s}))}))}start(t,e,i,s){if(""!==this.divId)return void console.error("Simulation already playing. Stop the current playtime before initiating a new one.");this.divId=t;let n=document.getElementById(t);if(null===n)return;let o=0,r=0;this.simulation.universes.forEach((t=>t.currState.bodies.forEach((t=>{o=Math.max(o,Math.abs(t.position.x)),r=Math.max(r,Math.abs(t.position.y))}))));const l=.5*Math.min(i/r,e/o),a=[],h=this.simulation.maxFrameRate*s;let d=1;this.simulation.universes.forEach((t=>{a.push([t.currState.clone()])}));for(let t=0;t{a[e].push(t.currState.clone())}));const c={paper_bgcolor:"#000000",plot_bgcolor:"#000000",font:{color:"#bfbfbf"},xaxis:{autorange:!1,range:[-e/2/l,e/2/l]},yaxis:{autorange:!1,range:[-i/2/l,i/2/l]},showlegend:!1};let u;"ui"===this.simulation.controller&&this.addControls(n),this.simulation.showDebugInfo&&(u=new(M()),u.dom.style.position="absolute",u.dom.style.bottom="0px",u.dom.style.removeProperty("top"),n.appendChild(u.dom));const p=this.simulation.universes.flatMap((t=>{const e=new V(this.simulation.getMaxTrailLength(),"string"==typeof t.color?t.color:t.color[0]);this.universeTrails.push(e);const i={x:t.currState.bodies.map((t=>t.position.x)),y:t.currState.bodies.map((t=>t.position.y)),type:"scatter",mode:"markers",marker:{color:t.color,sizemin:6,size:t.currState.bodies.map((t=>Math.min(10,t.mass)))}};return this.simulation.getShowTrails()?(t.currState.bodies.forEach((t=>{e.addTrail(t.position.x,t.position.y)})),[i,e.data]):[i,{x:[],y:[]}]}));if(T().newPlot(t,p,c,{scrollZoom:!0,modeBarButtonsToRemove:["zoom2d","lasso2d","select2d","toImage","resetScale2d"]}),null!==I)return;const m=e=>{if(0===this.simulation.controls.speed||this.simulation.controls.paused)return void(I=requestAnimationFrame(m));const i=Math.round(d),s=this.simulation.universes.flatMap(((t,e)=>{if(!this.simulation.getShowUniverse(t.label))return[{x:[],y:[]},{}];const s=a[e][i],n={x:s.bodies.map((t=>t.position.x)),y:s.bodies.map((t=>t.position.y)),hovertext:s.bodies.map((t=>t.label)),marker:{size:s.bodies.map((t=>Math.min(10,t.mass))),color:t.color,sizemin:6},mode:"markers"};let o={};if(this.simulation.getShowTrails()){const t=this.universeTrails[e];s.bodies.forEach((e=>{t.addTrail(e.position.x,e.position.y)})),o=t.data}return[n,o]}));T().react(t,s,c),this.simulation.showDebugInfo&&u&&u.update(),d=Math.round(d+this.simulation.controls.speed),d<0?d=this.simulation.looped?(d%h+h)%h:0:d>=h&&(this.simulation.looped?d%=h:d=h-1),I=requestAnimationFrame(m)};I=requestAnimationFrame(m)}stop(){T().purge(this.divId),this.divId="",this.universeTrails=[]}}class U{constructor(t){this.universeTrails=[],this.simulation=t}addControls(t){const e=new C({container:t});e.domElement.style.position="absolute",e.domElement.style.top="0",e.domElement.style.left="0",e.domElement.style.zIndex="1000";const i=this.simulation.controls;e.add(i,"speed"),e.add(i,"showTrails").onChange((t=>{!1===t&&this.universeTrails.forEach((t=>{t.popAllTrails()})),i.showTrails=t}));const s=e.addFolder("Show Universe");s.open(!1),this.simulation.universes.forEach(((t,e)=>{s.add(i.showUniverse,t.label).onChange((s=>{!1===s&&this.universeTrails[e].popAllTrails(),i.showUniverse[t.label]=s}))}))}start(t,i,s,n){if(void 0!==this.scene)return void console.error("Simulation already playing. Stop the current playtime before initiating a new one.");let o=document.getElementById(t);if(null===o)return;let r=0,l=0;this.simulation.universes.forEach((t=>t.currState.bodies.forEach((t=>{r=Math.max(r,Math.abs(t.position.x)),l=Math.max(l,Math.abs(t.position.y))}))));const a=.5*Math.min(s/l,i/r);this.scene=new e.Scene;const h=new e.OrthographicCamera(i/-2,i/2,s/2,s/-2,0,1e10);h.position.set(0,0,Math.max(i,s));const d=new e.WebGLRenderer;let c;d.setSize(i,s),d.autoClear=!1,o.appendChild(d.domElement),this.simulation.showDebugInfo&&(c=new(M()),c.dom.style.position="absolute",c.dom.style.right="0px",c.dom.style.removeProperty("left"),o.appendChild(c.dom)),"ui"===this.simulation.controller&&this.addControls(o);const u=new k.OrbitControls(h,d.domElement);u.listenToKeyEvents(window),u.update();const p=new e.AxesHelper(i);this.scene.add(p);const m=new k.ViewHelper(h,d.domElement);let g=[];this.simulation.universes.forEach((t=>{this.universeTrails.push(new B(this.simulation.maxTrailLength,"string"==typeof t.color?t.color:t.color[0],this.scene,a)),t.currState.bodies.forEach((i=>{const s=new e.SphereGeometry(D(Math.log2(i.mass)-70,10,40),8,8),n=new e.WireframeGeometry(s),o=new e.LineSegments(n,new e.LineBasicMaterial({color:new e.Color(t.color)}));this.scene.add(o),o.position.copy(i.position.clone().multiplyScalar(a)),g.push(o)}))}));const v=[],b=this.simulation.maxFrameRate*n;let f=1;this.simulation.universes.forEach((t=>{v.push([t.currState.clone()])}));for(let t=0;t{v[e].push(t.currState.clone())}));const w=t=>{if(0===this.simulation.controls.speed||this.simulation.controls.paused)return requestAnimationFrame(w),d.clear(),d.render(this.scene,h),m.render(d),void u.update();let e=0;this.simulation.universes.forEach(((t,i)=>{this.simulation.controls.showUniverse[t.label]?v[i][f].bodies.forEach((t=>{g[e].visible=!0,g[e].position.copy(t.position.clone().multiplyScalar(a)),this.simulation.controls.showTrails&&this.universeTrails[i].addTrail(g[e].position),e++})):t.currState.bodies.forEach((()=>{g[e].visible=!1,e++}))})),this.simulation.showDebugInfo&&c&&c.update(),f=Math.round(f+this.simulation.controls.speed),f<0?f=this.simulation.looped?(f%b+b)%b:0:f>=b&&(this.simulation.looped?f%=b:f=b-1),requestAnimationFrame(w),d.clear(),d.render(this.scene,h),m.render(d),u.update()};requestAnimationFrame(w)}stop(){var t;null===(t=this.scene)||void 0===t||t.clear(),this.scene=void 0,this.universeTrails.forEach((t=>{t.popAllTrails()})),this.universeTrails=[]}}class H{constructor(t,{visType:e="2D",record:i=!1,looped:s=!0,controller:n="none",showTrails:o=!1,showDebugInfo:r=!1,maxFrameRate:l=-1,maxTrailLength:a=100}){if(this.controls={speed:1,paused:!0,showTrails:!1,showUniverse:{}},this.universes=Array.isArray(t)?t:[t],this.universes.length>10)throw new Error("Too many universes");if(new Set(this.universes.map((t=>t.label))).size!==this.universes.length)throw new Error("Duplicate label in universes");this.controller=n,this.universes.forEach((t=>{this.controls.showUniverse[t.label]=!0})),this.controls.showTrails=o,this.showDebugInfo=r,this.maxFrameRate=l,this.maxTrailLength=a,this.looped=s,i?(this.maxFrameRate=60,this.visualizer="2D"===e?new j(this):new U(this)):this.visualizer="2D"===e?new z(this):new O(this)}getSpeed(){return this.controls.speed}setSpeed(t){"code"===this.controller&&(this.controls.speed=t)}isPlaying(){return!this.controls.paused}pause(){"code"===this.controller&&(this.controls.paused=!0)}resume(){"code"===this.controller&&(this.controls.paused=!1)}getShowTrails(){return this.controls.showTrails}setShowTrails(t){"code"===this.controller&&(this.controls.showTrails=t)}getShowUniverse(t){return this.controls.showUniverse[t]}setShowUniverse(t,e){"code"===this.controller&&(this.controls.showUniverse[t]=e)}getMaxTrailLength(){return this.maxTrailLength}setMaxTrailLength(t){"code"===this.controller&&(this.maxTrailLength=t)}simulateStep(t){this.universes.forEach((e=>{e.simulateStep(t)}))}start(t,e,i,s=1,n=!1,o=0){if(void 0===o)throw new Error("recordFor must be defined if record is true");this.controls.paused=n,this.controls.speed=s,this.visualizer.start(t,e,i,o)}stop(){this.visualizer.stop()}}class P{transform(t){const e=t.bodies[0].position.clone();return t.bodies.forEach((t=>{t.position.sub(e)})),t}}class G{transform(t){let i=0,s=new e.Vector3;return t.bodies.forEach((t=>{i+=t.mass,s.add(t.position.clone().multiplyScalar(t.mass))})),s.divideScalar(i),t.bodies.forEach((t=>{t.position.sub(s)})),t}}class R{constructor(t,e){this.axis=t,this.angle=e}transform(t){return t.bodies.forEach((t=>{t.position.applyAxisAngle(this.axis,this.angle),t.velocity.applyAxisAngle(this.axis,this.angle),t.acceleration.applyAxisAngle(this.axis,this.angle)})),t}}class Y{constructor(t){this.fn=t}transform(t,e){return this.fn(t,e)}}class K{constructor(t){if(void 0===t.currState)throw new Error("Missing Current State in Universe");if(void 0===t.simFunc)throw new Error("Missing Simulation Function in Universe");this.label=void 0===t.label?"Universe":t.label,this.prevState=void 0===t.prevState?t.currState:t.prevState,this.currState=t.currState,this.color=void 0===t.color?"rgba(255, 255, 255, 1)":t.color,this.simFunc=t.simFunc,this.transformations=void 0===t.transformations?[]:Array.isArray(t.transformations)?t.transformations:[t.transformations]}simulateStep(t){let e=this.simFunc.simulate(t,this.currState,this.prevState);this.prevState=this.currState,this.transformations.forEach((i=>{e=i.transform(e,t)})),this.currState=e}clone(){return new K({prevState:this.prevState.clone(),currState:this.currState.clone(),color:this.color,label:this.label,simFunc:this.simFunc,transformations:this.transformations})}}})(),l})())); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,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SCxLQUFLOEUsVUFDdEI5RSxLQUFLNGdCLGdCQUFnQnZjLFNBQVN5YyxJQUM1QkQsRUFBV0MsRUFBRWIsVUFBVVksRUFBVWhjLEVBQU8sSUFFMUM3RSxLQUFLOEUsVUFBWStiLENBQ25CLENBTUEsS0FBQXRlLEdBQ0UsT0FBTyxJQUFJbWUsRUFBUyxDQUNsQnBaLFVBQVd0SCxLQUFLc0gsVUFBVS9FLFFBQzFCdUMsVUFBVzlFLEtBQUs4RSxVQUFVdkMsUUFDMUJ1VixNQUFPOVgsS0FBSzhYLE1BQ1o1VixNQUFPbEMsS0FBS2tDLE1BQ1p5ZSxRQUFTM2dCLEtBQUsyZ0IsUUFDZEMsZ0JBQWlCNWdCLEtBQUs0Z0IsaUJBRTFCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbmJvZHkvd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uIiwid2VicGFjazovL25ib2R5L2V4dGVybmFsIHVtZCBcInBsb3RseS5qcy1kaXN0XCIiLCJ3ZWJwYWNrOi8vbmJvZHkvZXh0ZXJuYWwgdW1kIFwidGhyZWVcIiIsIndlYnBhY2s6Ly9uYm9keS9leHRlcm5hbCB1bWQgXCJ0aHJlZS9leGFtcGxlcy9qc20vQWRkb25zXCIiLCJ3ZWJwYWNrOi8vbmJvZHkvZXh0ZXJuYWwgdW1kIFwidGhyZWUvZXhhbXBsZXMvanNtL2xpYnMvc3RhdHMubW9kdWxlXCIiLCJ3ZWJwYWNrOi8vbmJvZHkvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vbmJvZHkvd2VicGFjay9ydW50aW1lL2NvbXBhdCBnZXQgZGVmYXVsdCBleHBvcnQiLCJ3ZWJwYWNrOi8vbmJvZHkvd2VicGFjay9ydW50aW1lL2RlZmluZSBwcm9wZXJ0eSBnZXR0ZXJzIiwid2VicGFjazovL25ib2R5L3dlYnBhY2svcnVudGltZS9oYXNPd25Qcm9wZXJ0eSBzaG9ydGhhbmQiLCJ3ZWJwYWNrOi8vbmJvZHkvd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly9uYm9keS8uL3NyYy9DZWxlc3RpYWxCb2R5LnRzIiwid2VicGFjazovL25ib2R5Ly4vc3JjL2xpYnJhcnkvRm9yY2UudHMiLCJ3ZWJwYWNrOi8vbmJvZHkvLi9zcmMvU3RhdGUudHMiLCJ3ZWJwYWNrOi8vbmJvZHkvLi9zcmMvbGlicmFyeS9TaW11bGF0ZUZ1bmN0aW9uLnRzIiwid2VicGFjazovL25ib2R5Ly4vc3JjL1NpbXVsYXRlRnVuY3Rpb24udHMiLCJ3ZWJwYWNrOi8vbmJvZHkvLi9ub2RlX21vZHVsZXMvbGlsLWd1aS9kaXN0L2xpbC1ndWkuZXNtLmpzIiwid2VicGFjazovL25ib2R5Ly4vc3JjL2xpYnJhcnkvVmlzdWFsaXplci50cyIsIndlYnBhY2s6Ly9uYm9keS8uL3NyYy9TaW11bGF0aW9uLnRzIiwid2VicGFjazovL25ib2R5Ly4vc3JjL2xpYnJhcnkvVHJhbnNmb3JtYXRpb24udHMiLCJ3ZWJwYWNrOi8vbmJvZHkvLi9zcmMvVHJhbnNmb3JtYXRpb24udHMiLCJ3ZWJwYWNrOi8vbmJvZHkvLi9zcmMvVW5pdmVyc2UudHMiXSwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIHdlYnBhY2tVbml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnKVxuXHRcdG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKFwidGhyZWVcIiksIHJlcXVpcmUoXCJwbG90bHkuanMtZGlzdFwiKSwgcmVxdWlyZShcInRocmVlL2V4YW1wbGVzL2pzbS9BZGRvbnNcIiksIHJlcXVpcmUoXCJ0aHJlZS9leGFtcGxlcy9qc20vbGlicy9zdGF0cy5tb2R1bGVcIikpO1xuXHRlbHNlIGlmKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZClcblx0XHRkZWZpbmUoW1widGhyZWVcIiwgXCJwbG90bHkuanMtZGlzdFwiLCBcInRocmVlL2V4YW1wbGVzL2pzbS9BZGRvbnNcIiwgXCJ0aHJlZS9leGFtcGxlcy9qc20vbGlicy9zdGF0cy5tb2R1bGVcIl0sIGZhY3RvcnkpO1xuXHRlbHNlIGlmKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0Jylcblx0XHRleHBvcnRzW1wibmJvZHlcIl0gPSBmYWN0b3J5KHJlcXVpcmUoXCJ0aHJlZVwiKSwgcmVxdWlyZShcInBsb3RseS5qcy1kaXN0XCIpLCByZXF1aXJlKFwidGhyZWUvZXhhbXBsZXMvanNtL0FkZG9uc1wiKSwgcmVxdWlyZShcInRocmVlL2V4YW1wbGVzL2pzbS9saWJzL3N0YXRzLm1vZHVsZVwiKSk7XG5cdGVsc2Vcblx0XHRyb290W1wibmJvZHlcIl0gPSBmYWN0b3J5KHJvb3RbXCJ0aHJlZVwiXSwgcm9vdFtcInBsb3RseS5qcy1kaXN0XCJdLCByb290W1widGhyZWUvZXhhbXBsZXMvanNtL0FkZG9uc1wiXSwgcm9vdFtcInRocmVlL2V4YW1wbGVzL2pzbS9saWJzL3N0YXRzLm1vZHVsZVwiXSk7XG59KSh0aGlzLCAoX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV9fNjA0X18sIF9fV0VCUEFDS19FWFRFUk5BTF9NT0RVTEVfXzkyNF9fLCBfX1dFQlBBQ0tfRVhURVJOQUxfTU9EVUxFX185ODdfXywgX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV9fNjg2X18pID0+IHtcbnJldHVybiAiLCJtb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19FWFRFUk5BTF9NT0RVTEVfXzkyNF9fOyIsIm1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV9fNjA0X187IiwibW9kdWxlLmV4cG9ydHMgPSBfX1dFQlBBQ0tfRVhURVJOQUxfTU9EVUxFX185ODdfXzsiLCJtb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19FWFRFUk5BTF9NT0RVTEVfXzY4Nl9fOyIsIi8vIFRoZSBtb2R1bGUgY2FjaGVcbnZhciBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX18gPSB7fTtcblxuLy8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbmZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG5cdHZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdO1xuXHRpZiAoY2FjaGVkTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcblx0XHRyZXR1cm4gY2FjaGVkTW9kdWxlLmV4cG9ydHM7XG5cdH1cblx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcblx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XG5cdFx0Ly8gbm8gbW9kdWxlLmlkIG5lZWRlZFxuXHRcdC8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkXG5cdFx0ZXhwb3J0czoge31cblx0fTtcblxuXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cblx0X193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0obW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cblx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcblx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xufVxuXG4iLCIvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuX193ZWJwYWNrX3JlcXVpcmVfXy5uID0gKG1vZHVsZSkgPT4ge1xuXHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cblx0XHQoKSA9PiAobW9kdWxlWydkZWZhdWx0J10pIDpcblx0XHQoKSA9PiAobW9kdWxlKTtcblx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgeyBhOiBnZXR0ZXIgfSk7XG5cdHJldHVybiBnZXR0ZXI7XG59OyIsIi8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb25zIGZvciBoYXJtb255IGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uZCA9IChleHBvcnRzLCBkZWZpbml0aW9uKSA9PiB7XG5cdGZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHtcblx0XHRpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZGVmaW5pdGlvbiwga2V5KSAmJiAhX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIGtleSkpIHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7XG5cdFx0fVxuXHR9XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18ubyA9IChvYmosIHByb3ApID0+IChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSkiLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJpbXBvcnQgeyB0eXBlIFZlY3RvcjMgfSBmcm9tICd0aHJlZSc7XHJcblxyXG4vKipcclxuICogUmVwcmVzZW50cyBhIGNlbGVzdGlhbCBib2R5IHdpdGggYWxsIG9mIGl0cyBraW5lbWF0aWMgcHJvcGVydGllcy5cclxuICogQGNhdGVnb3J5IEJ1aWxkaW5nIGJsb2Nrc1xyXG4gKi9cclxuZXhwb3J0IGNsYXNzIENlbGVzdGlhbEJvZHkge1xyXG4gIC8qKlxyXG4gICAqIExhYmVsIG9mIHRoZSBib2R5LlxyXG4gICAqL1xyXG4gIHJlYWRvbmx5IGxhYmVsOiBzdHJpbmc7XHJcbiAgLyoqXHJcbiAgICogTWVhbiBtYXNzIG9mIHRoZSBib2R5LlxyXG4gICAqL1xyXG4gIHJlYWRvbmx5IG1hc3M6IG51bWJlcjsgLy8gbWVhbiBtYXNzXHJcbiAgLyoqXHJcbiAgICogUG9zaXRpb24gdmVjdG9yIG9mIHRoZSBib2R5LlxyXG4gICAqL1xyXG4gIHBvc2l0aW9uOiBWZWN0b3IzO1xyXG4gIC8qKlxyXG4gICAqIFZlbG9jaXR5IHZlY3RvciBvZiB0aGUgYm9keS5cclxuICAgKi9cclxuICB2ZWxvY2l0eTogVmVjdG9yMztcclxuICAvKipcclxuICAgKiBBY2NlbGVyYXRpb24gdmVjdG9yIG9mIHRoZSBib2R5LlxyXG4gICAqL1xyXG4gIGFjY2VsZXJhdGlvbjogVmVjdG9yMztcclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlIGEgbmV3IENlbGVzdGlhbEJvZHkgd2l0aCB0aGUgcHJvdmlkZWQgaW5mb3JtYXRpb24uXHJcbiAgICogQHBhcmFtIGxhYmVsIGxhYmVsIG9mIHRoZSBib2R5LlxyXG4gICAqIEBwYXJhbSBtYXNzIG1hc3Mgb2YgdGhlIGJvZHkuXHJcbiAgICogQHBhcmFtIHBvc2l0aW9uIHBvc2l0aW9uIG9mIHRoZSBib2R5LlxyXG4gICAqIEBwYXJhbSB2ZWxvY2l0eSB2ZWxvY2l0eSBvZiB0aGUgYm9keS5cclxuICAgKiBAcGFyYW0gYWNjZWxlcmF0aW9uIGFjY2VsZXJhdGlvbiBvZiB0aGUgYm9keS5cclxuICAgKi9cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIGxhYmVsOiBzdHJpbmcsXHJcbiAgICBtYXNzOiBudW1iZXIsXHJcbiAgICBwb3NpdGlvbjogVmVjdG9yMyxcclxuICAgIHZlbG9jaXR5OiBWZWN0b3IzLFxyXG4gICAgYWNjZWxlcmF0aW9uOiBWZWN0b3IzLFxyXG4gICkge1xyXG4gICAgdGhpcy5sYWJlbCA9IGxhYmVsO1xyXG4gICAgdGhpcy5tYXNzID0gbWFzcztcclxuICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjtcclxuICAgIHRoaXMudmVsb2NpdHkgPSB2ZWxvY2l0eTtcclxuICAgIHRoaXMuYWNjZWxlcmF0aW9uID0gYWNjZWxlcmF0aW9uO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRGVlcCBjb3B5IHRoZSBjdXJyZW50IENlbGVzdGlhbEJvZHkgd2l0aCB0aGUgdXBkYXRlZCBraW5lbWF0aWMgcHJvcGVydGllcy5cclxuICAgKiBAcGFyYW0gcG9zaXRpb24gbmV3IHBvc2l0aW9uLlxyXG4gICAqIEBwYXJhbSB2ZWxvY2l0eSBuZXcgdmVsb2NpdHkuXHJcbiAgICogQHBhcmFtIGFjY2VsZXJhdGlvbiBuZXcgYWNjZWxlcmF0aW9uLlxyXG4gICAqIEByZXR1cm5zIGEgbmV3IENlbGVzdGlhbEJvZHkgaW5zdGFuY2Ugd2l0aCB0aGUgdXBkYXRlZCBwcm9wZXJ0aWVzLlxyXG4gICAqL1xyXG4gIGNsb25lKHBvc2l0aW9uPzogVmVjdG9yMyxcclxuICAgIHZlbG9jaXR5PzogVmVjdG9yMyxcclxuICAgIGFjY2VsZXJhdGlvbj86IFZlY3RvcjMpOiBDZWxlc3RpYWxCb2R5IHtcclxuICAgIHJldHVybiBuZXcgQ2VsZXN0aWFsQm9keShcclxuICAgICAgdGhpcy5sYWJlbCxcclxuICAgICAgdGhpcy5tYXNzLFxyXG4gICAgICBwb3NpdGlvbiA9PT0gdW5kZWZpbmVkID8gdGhpcy5wb3NpdGlvbi5jbG9uZSgpIDogcG9zaXRpb24sXHJcbiAgICAgIHZlbG9jaXR5ID09PSB1bmRlZmluZWQgPyB0aGlzLnZlbG9jaXR5LmNsb25lKCkgOiB2ZWxvY2l0eSxcclxuICAgICAgYWNjZWxlcmF0aW9uID09PSB1bmRlZmluZWQgPyB0aGlzLmFjY2VsZXJhdGlvbi5jbG9uZSgpIDogYWNjZWxlcmF0aW9uLFxyXG4gICAgKTtcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgVmVjdG9yMyB9IGZyb20gJ3RocmVlJztcclxuaW1wb3J0IHsgdHlwZSBDZWxlc3RpYWxCb2R5IH0gZnJvbSAnLi4vQ2VsZXN0aWFsQm9keSc7XHJcbmltcG9ydCB7IHR5cGUgRm9yY2UgfSBmcm9tICcuLi9Gb3JjZSc7XHJcblxyXG4vKipcclxuICogUmVwcmVzZW50cyBhIFtOZXd0b25pYW4gR3Jhdml0YXRpb25hbCBmb3JjZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTmV3dG9uJTI3c19sYXdfb2ZfdW5pdmVyc2FsX2dyYXZpdGF0aW9uKSBvYmplY3QuXHJcbiAqIEBjYXRlZ29yeSBGb3JjZXNcclxuICovXHJcbmV4cG9ydCBjbGFzcyBHcmF2aXR5IGltcGxlbWVudHMgRm9yY2Uge1xyXG4gIC8qKlxyXG4gICAqIEdyYXZpdGF0aW9uYWwgY29uc3RhbnQuXHJcbiAgICogQGRlZmF1bHRWYWx1ZSA2LjY3NGUtMTFcclxuICAgKi9cclxuICByZWFkb25seSBHOiBudW1iZXI7XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZSBhIG5ldyBHcmF2aXR5IHdpdGggdGhlIHByb3ZpZGVkIGdyYXZpdGF0aW9uYWwgY29uc3RhbnQuXHJcbiAgICogQHBhcmFtIEcgZ3Jhdml0YXRpb25hbCBjb25zdGFudC5cclxuICAgKi9cclxuICBjb25zdHJ1Y3RvcihHOiBudW1iZXIgPSA2LjY3NGUtMTEpIHtcclxuICAgIHRoaXMuRyA9IEc7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDYWxjdWxhdGUgYW5kIHJldHVybiB0aGUgZm9yY2VzIGFjdGluZyBvbiB0aGUgYm9kaWVzLiBhcnJbaV0gcmVwcmVzZW50cyB0aGUgZm9yY2UgYWN0aW5nIG9uIHRoZSBpdGggYm9keSBhcyBhIHJlc3VsdCBvZiBhbGwgb3RoZXIgYm9kaWVzLlxyXG4gICAqIEBwYXJhbSBib2RpZXMgY2VsZXN0aWFsIGJvZGllc1xyXG4gICAqIEByZXR1cm5zIGZvcmNlc1xyXG4gICAqL1xyXG4gIGdldEZvcmNlcyhib2RpZXM6IENlbGVzdGlhbEJvZHlbXSk6IFZlY3RvcjNbXSB7XHJcbiAgICBsZXQgbiA9IGJvZGllcy5sZW5ndGg7XHJcbiAgICBsZXQgYW5zOiBWZWN0b3IzW10gPSBbXTtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgIGFucy5wdXNoKG5ldyBWZWN0b3IzKDAsIDAsIDApKTtcclxuICAgIH1cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgIGZvciAobGV0IGogPSBpICsgMTsgaiA8IG47IGorKykge1xyXG4gICAgICAgIGxldCBjdXJyRm9yY2UgPSB0aGlzLmNhbGNOZXd0b25pYW4oYm9kaWVzW2ldLCBib2RpZXNbal0pO1xyXG4gICAgICAgIGFuc1tpXS5hZGQoY3VyckZvcmNlKTtcclxuICAgICAgICBhbnNbal0uc3ViKGN1cnJGb3JjZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBhbnM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDYWxjdWxhdGUgdGhlIGdyYXZpdGF0aW9uYWwgZm9yY2UgYWN0aW5nIG9uIGJvZHkgYSBkdWUgdG8gYm9keSBiLlxyXG4gICAqIEBwYXJhbSBhIGJvZHkgYS5cclxuICAgKiBAcGFyYW0gYiBib2R5IGIuXHJcbiAgICogQHJldHVybnMgZ3Jhdml0YXRpb25hbCBmb3JjZSBvZiBhIG9uIGIuXHJcbiAgICogQGhpZGRlblxyXG4gICAqL1xyXG4gIHByaXZhdGUgY2FsY05ld3RvbmlhbihhOiBDZWxlc3RpYWxCb2R5LCBiOiBDZWxlc3RpYWxCb2R5KTogVmVjdG9yMyB7XHJcbiAgICBsZXQgZGlzdFNxID0gYS5wb3NpdGlvbi5kaXN0YW5jZVRvU3F1YXJlZChiLnBvc2l0aW9uKTtcclxuICAgIGxldCBmb3JjZVZhbCA9ICh0aGlzLkcgKiBhLm1hc3MgKiBiLm1hc3MpIC8gZGlzdFNxO1xyXG4gICAgcmV0dXJuIGIucG9zaXRpb25cclxuICAgICAgLmNsb25lKClcclxuICAgICAgLnN1YihhLnBvc2l0aW9uKVxyXG4gICAgICAubm9ybWFsaXplKClcclxuICAgICAgLm11bHRpcGx5U2NhbGFyKGZvcmNlVmFsKTtcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXByZXNlbnRzIGEgW0NlbnRyaXBldGFsIGZvcmNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DZW50cmlwZXRhbF9mb3JjZSkgb2JqZWN0LiBUbyBiZSB1c2VkIHRvIGNhbGN1bGF0ZSB0aGUgZm9yY2UgcmVxdWlyZWQgdG8ga2VlcCB0aGUgYm9kaWVzIGluIGNpcmN1bGFyIG1vdGlvbiBhcm91bmQgYSBnaXZlbiBjZW50ZXIuXHJcbiAqIEBjYXRlZ29yeSBGb3JjZXNcclxuICovXHJcbmV4cG9ydCBjbGFzcyBDZW50cmlwZXRhbEZvcmNlIGltcGxlbWVudHMgRm9yY2Uge1xyXG4gIC8qKlxyXG4gICAqIENlbnRlciBvZiBmb3JjZS5cclxuICAgKi9cclxuICByZWFkb25seSBjZW50ZXI6IFZlY3RvcjM7XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZSBhIG5ldyBDZW50cmlwZXRhbEZvcmNlIHdpdGggdGhlIHByb3ZpZGVkIGNlbnRlciBvZiBmb3JjZS5cclxuICAgKiBAcGFyYW0gY2VudGVyIGNlbnRlciBvZiBmb3JjZS5cclxuICAgKi9cclxuICBjb25zdHJ1Y3RvcihjZW50ZXI6IFZlY3RvcjMgPSBuZXcgVmVjdG9yMygwLCAwLCAwKSkge1xyXG4gICAgdGhpcy5jZW50ZXIgPSBjZW50ZXI7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDYWxjdWxhdGUgdGhlIGZvcmNlIHJlcXVpcmVkIHRvIGtlZXAgdGhlIGJvZGllcyBpbiBjaXJjdWxhciBtb3Rpb24gYXJvdW5kIHRoZSBjZW50ZXIuIGFycltpXSByZXByZXNlbnRzIHRoZSBjZW50cmlwZXRhbCBmb3JjZSByZXF1aXJlZCBmb3IgdGhlIGl0aCBib2R5LlxyXG4gICAqIEBwYXJhbSBib2RpZXMgY2VsZXN0aWFsIGJvZGllcy5cclxuICAgKiBAcmV0dXJucyBmb3JjZXMuXHJcbiAgICovXHJcbiAgZ2V0Rm9yY2VzKGJvZGllczogQ2VsZXN0aWFsQm9keVtdKTogVmVjdG9yM1tdIHtcclxuICAgIC8vIFRPRE86IG12XjIvciBzaW4gb3IgY29zIHRoZXRoYT9cclxuICAgIHJldHVybiBib2RpZXMubWFwKChib2R5KSA9PiB7XHJcbiAgICAgIGNvbnN0IGRpcmVjdGlvblZlY3RvciA9IHRoaXMuY2VudGVyLmNsb25lKClcclxuICAgICAgICAuc3ViKGJvZHkucG9zaXRpb24pO1xyXG4gICAgICByZXR1cm4gZGlyZWN0aW9uVmVjdG9yLnNldExlbmd0aChcclxuICAgICAgICAoYm9keS5tYXNzICogYm9keS52ZWxvY2l0eS5sZW5ndGhTcSgpKSAvIGRpcmVjdGlvblZlY3Rvci5sZW5ndGgoKSxcclxuICAgICAgKTtcclxuICAgIH0pO1xyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFJlcHJlc2VudHMgYSBjb21iaW5lZCBmb3JjZSBvYmplY3QuIFRvIGJlIHVzZWQgdG8gYWRkaXRpdmVseSBjb21iaW5lIG11bHRpcGxlIGZvcmNlcyBhY3Rpbmcgb24gYSBzeXN0ZW0gb2YgYm9kaWVzLlxyXG4gKiBAY2F0ZWdvcnkgRm9yY2VzXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgQ29tYmluZWRGb3JjZSBpbXBsZW1lbnRzIEZvcmNlIHtcclxuICBmb3JjZXM6IEZvcmNlW107XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZSBhIG5ldyBDb21iaW5lZEZvcmNlIHdpdGggdGhlIHByb3ZpZGVkIGZvcmNlcy5cclxuICAgKiBAcGFyYW0gZm9yY2VzIGFycmF5IG9mIGZvcmNlcy5cclxuICAgKi9cclxuICBjb25zdHJ1Y3Rvcihmb3JjZXM6IEZvcmNlW10pIHtcclxuICAgIHRoaXMuZm9yY2VzID0gZm9yY2VzO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0IHRoZSBjb21iaW5lZCBmb3JjZXMgYWN0aW5nIG9uIHRoZSBib2RpZXMuIGFycltpXSByZXByZXNlbnRzIHRoZSBjb21iaW5lZCBmb3JjZSBhY3Rpbmcgb24gdGhlIGl0aCBib2R5IGFzIGEgcmVzdWx0IG9mIGFsbCBmb3JjZSBzeXN0ZW1zLlxyXG4gICAqIEBwYXJhbSBib2RpZXMgY2VsZXN0aWFsIGJvZGllcy5cclxuICAgKiBAcmV0dXJucyBlbGVtZW50LXdpc2UgY29tYmluZWQgZm9yY2VzLlxyXG4gICAqL1xyXG4gIGdldEZvcmNlcyhib2RpZXM6IENlbGVzdGlhbEJvZHlbXSk6IFZlY3RvcjNbXSB7XHJcbiAgICBjb25zdCBmb3JjZVZhbDogVmVjdG9yM1tdID0gYm9kaWVzLm1hcCgoKSA9PiBuZXcgVmVjdG9yMygwLCAwLCAwKSk7XHJcbiAgICB0aGlzLmZvcmNlcy5mb3JFYWNoKChmb3JjZSkgPT4ge1xyXG4gICAgICBmb3JjZS5nZXRGb3JjZXMoYm9kaWVzKVxyXG4gICAgICAgIC5mb3JFYWNoKCh2YWwsIGluZGV4KSA9PiB7XHJcbiAgICAgICAgICBmb3JjZVZhbFtpbmRleF0uYWRkKHZhbCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBmb3JjZVZhbDtcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHR5cGUgeyBDZWxlc3RpYWxCb2R5IH0gZnJvbSAnLi9DZWxlc3RpYWxCb2R5JztcclxuXHJcbi8qKlxyXG4gKiBSZXByZXNlbnRzIGEgVW5pdmVyc2UncyBzdGF0ZSBzbmFwc2hvdC5cclxuICogQGNhdGVnb3J5IEJ1aWxkaW5nIGJsb2Nrc1xyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFN0YXRlIHtcclxuICAvKipcclxuICAgKiBBcnJheSBvZiBjZWxlc3RpYWwgYm9kaWVzIHRoYXQgbWFrZSB1cCB0aGlzIHN0YXRlIG9mIHRoZSBVbml2ZXJzZS5cclxuICAgKi9cclxuICByZWFkb25seSBib2RpZXM6IENlbGVzdGlhbEJvZHlbXTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlIGEgbmV3IFN0YXRlIHdpdGggdGhlIGdpdmVuIGNlbGVzdGlhbCBib2RpZXMuXHJcbiAgICogQHBhcmFtIGJvZGllcyBhcnJheSBvZiBjZWxlc3RpYWwgYm9kaWVzLlxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKGJvZGllczogQ2VsZXN0aWFsQm9keVtdKSB7XHJcbiAgICB0aGlzLmJvZGllcyA9IGJvZGllcztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIERlZXAgY29weSB0aGlzIHN0YXRlXHJcbiAgICogQHJldHVybnMgYSBuZXcgU3RhdGUgaW5zdGFuY2UuXHJcbiAgICovXHJcbiAgY2xvbmUoKTogU3RhdGUge1xyXG4gICAgcmV0dXJuIG5ldyBTdGF0ZSh0aGlzLmJvZGllcy5tYXAoKGJvZHkpID0+IGJvZHkuY2xvbmUoKSkpO1xyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBWZWN0b3IzIH0gZnJvbSAndGhyZWUnO1xyXG5pbXBvcnQgeyB0eXBlIENlbGVzdGlhbEJvZHkgfSBmcm9tICcuLi9DZWxlc3RpYWxCb2R5JztcclxuaW1wb3J0IHsgdHlwZSBGb3JjZSB9IGZyb20gJy4uL0ZvcmNlJztcclxuaW1wb3J0IHsgdHlwZSBTaW11bGF0ZUZ1bmN0aW9uIH0gZnJvbSAnLi4vU2ltdWxhdGVGdW5jdGlvbic7XHJcbmltcG9ydCB7IFN0YXRlIH0gZnJvbSAnLi4vU3RhdGUnO1xyXG5cclxuLy8gZXhwb3J0IGNsYXNzIFZlcmxldFNpbSBpbXBsZW1lbnRzIFNpbXVsYXRlRnVuY3Rpb24ge1xyXG4vLyAgIGZvcmNlQ2FsY3VsYXRvcjogRm9yY2U7XHJcbi8vICAgcHJldkRlbHRhVDogbnVtYmVyIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xyXG5cclxuLy8gICBjb25zdHJ1Y3Rvcihmb3JjZUNhbGN1bGF0b3I6IEZvcmNlKSB7XHJcbi8vICAgICB0aGlzLmZvcmNlQ2FsY3VsYXRvciA9IGZvcmNlQ2FsY3VsYXRvcjtcclxuLy8gICB9XHJcblxyXG4vLyAgIHByaXZhdGUgZnJvbU9uZVN0YXRlKFxyXG4vLyAgICAgY3VyclN0YXRlOiBTdGF0ZSxcclxuLy8gICAgIGRlbHRhVDogbnVtYmVyLFxyXG4vLyAgICAgZm9yY2VzOiBWZWN0b3IzW11cclxuLy8gICApOiBTdGF0ZSB7XHJcbi8vICAgICBsZXQgdXBkYXRlZEJvZGllczogQ2VsZXN0aWFsQm9keVtdID0gY3VyclN0YXRlLmJvZGllcy5tYXAoKGJvZHksIGluZGV4KSA9PiB7XHJcbi8vICAgICAgIGNvbnN0IGN1cnJBY2NlbCA9IGZvcmNlc1tpbmRleF0uZGl2aWRlU2NhbGFyKGJvZHkubWFzcyk7XHJcbi8vICAgICAgIGNvbnN0IG5ld1BvcyA9IGN1cnJBY2NlbFxyXG4vLyAgICAgICAgIC5jbG9uZSgpXHJcbi8vICAgICAgICAgLm11bHRpcGx5U2NhbGFyKGRlbHRhVCAvIDIpXHJcbi8vICAgICAgICAgLmFkZChib2R5LnZlbG9jaXR5KVxyXG4vLyAgICAgICAgIC5tdWx0aXBseVNjYWxhcihkZWx0YVQpXHJcbi8vICAgICAgICAgLmFkZChib2R5LnBvc2l0aW9uKTtcclxuLy8gICAgICAgcmV0dXJuIGJvZHkuY2xvbmUoXHJcbi8vICAgICAgICAgbmV3UG9zLFxyXG4vLyAgICAgICAgIHRoaXMudmVybGV0VmVsKGJvZHkucG9zaXRpb24sIG5ld1BvcywgZGVsdGFUKSxcclxuLy8gICAgICAgICBjdXJyQWNjZWxcclxuLy8gICAgICAgKTtcclxuLy8gICAgIH0pO1xyXG5cclxuLy8gICAgIHRoaXMucHJldkRlbHRhVCA9IGRlbHRhVDtcclxuLy8gICAgIHJldHVybiBuZXcgU3RhdGUodXBkYXRlZEJvZGllcyk7XHJcbi8vICAgfVxyXG5cclxuLy8gICBzaW11bGF0ZShkZWx0YVQ6IG51bWJlciwgY3VyclN0YXRlOiBTdGF0ZSwgcHJldlN0YXRlPzogU3RhdGUpOiBTdGF0ZSB7XHJcbi8vICAgICBpZiAoZGVsdGFUIDw9IDApIHtcclxuLy8gICAgICAgcmV0dXJuIGN1cnJTdGF0ZS5jbG9uZSgpO1xyXG4vLyAgICAgfVxyXG5cclxuLy8gICAgIGxldCBmb3JjZXMgPSB0aGlzLmZvcmNlQ2FsY3VsYXRvci5nZXRGb3JjZXMoY3VyclN0YXRlLmJvZGllcyk7XHJcbi8vICAgICBpZiAoZm9yY2VzLmxlbmd0aCAhPT0gY3VyclN0YXRlLmJvZGllcy5sZW5ndGgpIHtcclxuLy8gICAgICAgY29uc29sZS5lcnJvcihgZm9yY2VzIGxlbmd0aCAhPT0gbnVtYmVyIG9mIGJvZGllc2ApO1xyXG4vLyAgICAgICByZXR1cm4gY3VyclN0YXRlLmNsb25lKCk7XHJcbi8vICAgICB9XHJcblxyXG4vLyAgICAgaWYgKHByZXZTdGF0ZSA9PT0gdW5kZWZpbmVkKSB7XHJcbi8vICAgICAgIHJldHVybiB0aGlzLmZyb21PbmVTdGF0ZShjdXJyU3RhdGUsIGRlbHRhVCwgZm9yY2VzKTtcclxuLy8gICAgIH1cclxuXHJcbi8vICAgICBsZXQgdXBkYXRlZEJvZGllczogQ2VsZXN0aWFsQm9keVtdID0gY3VyclN0YXRlLmJvZGllcy5tYXAoKGJvZHksIGluZGV4KSA9PiB7XHJcbi8vICAgICAgIGNvbnN0IGN1cnJBY2NlbCA9IGZvcmNlc1tpbmRleF0uZGl2aWRlU2NhbGFyKGJvZHkubWFzcyk7XHJcbi8vICAgICAgIGNvbnN0IG5ld1BvcyA9IHRoaXMudmVybGV0UG9zKFxyXG4vLyAgICAgICAgIHByZXZTdGF0ZS5ib2RpZXNbaW5kZXhdLnBvc2l0aW9uLFxyXG4vLyAgICAgICAgIGJvZHkucG9zaXRpb24sXHJcbi8vICAgICAgICAgY3VyckFjY2VsLFxyXG4vLyAgICAgICAgIGRlbHRhVFxyXG4vLyAgICAgICApO1xyXG4vLyAgICAgICByZXR1cm4gYm9keS5jbG9uZShcclxuLy8gICAgICAgICBuZXdQb3MsXHJcbi8vICAgICAgICAgdGhpcy52ZXJsZXRWZWwoYm9keS5wb3NpdGlvbiwgbmV3UG9zLCBkZWx0YVQpLFxyXG4vLyAgICAgICAgIGN1cnJBY2NlbFxyXG4vLyAgICAgICApO1xyXG4vLyAgICAgfSk7XHJcblxyXG4vLyAgICAgdGhpcy5wcmV2RGVsdGFUID0gZGVsdGFUO1xyXG4vLyAgICAgcmV0dXJuIG5ldyBTdGF0ZSh1cGRhdGVkQm9kaWVzKTtcclxuLy8gICB9XHJcblxyXG4vLyAgIHZlcmxldFBvcyhcclxuLy8gICAgIG9sZFBvczogVmVjdG9yMyxcclxuLy8gICAgIGN1cnJQb3M6IFZlY3RvcjMsXHJcbi8vICAgICBjdXJyQWNjZWw6IFZlY3RvcjMsXHJcbi8vICAgICBkZWx0YVQ6IG51bWJlclxyXG4vLyAgICk6IFZlY3RvcjMge1xyXG4vLyAgICAgY29uc3QgcHJldkRUID0gdGhpcy5wcmV2RGVsdGFUID09PSB1bmRlZmluZWQgPyBkZWx0YVQgOiB0aGlzLnByZXZEZWx0YVQ7XHJcblxyXG4vLyAgICAgcmV0dXJuIGN1cnJBY2NlbFxyXG4vLyAgICAgICAuY2xvbmUoKVxyXG4vLyAgICAgICAubXVsdGlwbHlTY2FsYXIoKHByZXZEVCArIGRlbHRhVCkgLyAyKVxyXG4vLyAgICAgICAuYWRkKGN1cnJQb3MuY2xvbmUoKS5zdWIob2xkUG9zKS5kaXZpZGVTY2FsYXIocHJldkRUKSlcclxuLy8gICAgICAgLm11bHRpcGx5U2NhbGFyKGRlbHRhVClcclxuLy8gICAgICAgLmFkZChjdXJyUG9zKTtcclxuLy8gICB9XHJcblxyXG4vLyAgIHZlcmxldFZlbChjdXJyUG9zOiBWZWN0b3IzLCBuZXdQb3M6IFZlY3RvcjMsIGRlbHRhVDogbnVtYmVyKTogVmVjdG9yMyB7XHJcbi8vICAgICByZXR1cm4gbmV3UG9zLmNsb25lKCkuc3ViKGN1cnJQb3MpLmRpdmlkZVNjYWxhcihkZWx0YVQpO1xyXG4vLyAgIH1cclxuLy8gfVxyXG5cclxuLyoqXHJcbiAqIFJlcHJlc2VudHMgYSBzaW11bGF0aW9uIGZ1bmN0aW9uIG9iamVjdCB0aGF0IHVzZXMgdGhlIFtWZWxvY2l0eSBWZXJsZXQgaW50ZWdyYXRpb24gbWV0aG9kXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9WZXJsZXRfaW50ZWdyYXRpb24jVmVsb2NpdHlfVmVybGV0KSB0byBzaW11bGF0ZSB0aGUgbW90aW9uIG9mIGJvZGllcy5cclxuICogQGNhdGVnb3J5IFNpbXVsYXRlRnVuY3Rpb25zXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgVmVsb2NpdHlWZXJsZXRTaW0gaW1wbGVtZW50cyBTaW11bGF0ZUZ1bmN0aW9uIHtcclxuICAvKipcclxuICAgKiBGb3JjZSBvYmplY3QgdG8gY2FsY3VsYXRlIGZvcmNlcyBvbiBib2RpZXMgaW4gdGhlIFVuaXZlcnNlLlxyXG4gICAqL1xyXG4gIGZvcmNlQ2FsY3VsYXRvcjogRm9yY2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZSBhIG5ldyBWZWxvY2l0eVZlcmxldFNpbSB3aXRoIHRoZSBwcm92aWRlZCBmb3JjZSBjYWxjdWxhdG9yLCB3aGljaCBpcyBpbnZva2VkIG9uIGV2ZXJ5IHNpbXVsYXRpb24gc3RlcC5cclxuICAgKiBAcGFyYW0gZm9yY2VDYWxjdWxhdG9yIGZvcmNlIGNhbGN1bGF0b3IuXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IoZm9yY2VDYWxjdWxhdG9yOiBGb3JjZSkge1xyXG4gICAgdGhpcy5mb3JjZUNhbGN1bGF0b3IgPSBmb3JjZUNhbGN1bGF0b3I7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTaW11bGF0ZSBhIHN0ZXAgaW4gdGhlIFVuaXZlcnNlIGJ5IHVzaW5nIHRoZSBwcmV2aW91cyBhbmQvb3IgY3VycmVudCBzdGF0ZSBhbmQgYSB0aW1lIHN0ZXAsIHVzaW5nIHRoZSBWZWxvY2l0eSBWZXJsZXQgaW50ZWdyYXRpb24gbWV0aG9kLlxyXG4gICAqIEBwYXJhbSBkZWx0YVQgdGltZSBzdGVwLlxyXG4gICAqIEBwYXJhbSBjdXJyU3RhdGUgY3VycmVudCBzdGF0ZS5cclxuICAgKiBAcmV0dXJucyBuZXcgc3RhdGUgYWZ0ZXIgdGhlIHNpbXVsYXRpb24gc3RlcC5cclxuICAgKi9cclxuICBzaW11bGF0ZShkZWx0YVQ6IG51bWJlciwgY3VyclN0YXRlOiBTdGF0ZSk6IFN0YXRlIHtcclxuICAgIGlmIChkZWx0YVQgPD0gMCkge1xyXG4gICAgICByZXR1cm4gY3VyclN0YXRlLmNsb25lKCk7XHJcbiAgICB9XHJcbiAgICAvLyB4KHQgKyBkdCkgPSB4KHQpICsgKHYodCkgKiBkdCkgKyAoMC41ICogYSh0KSAqIGR0ICogZHQpXHJcbiAgICBsZXQgdXBkYXRlZEJvZGllcyA9IGN1cnJTdGF0ZS5ib2RpZXMubWFwKCh2KSA9PiB7XHJcbiAgICAgIGxldCB1cGRhdGVkQm9keSA9IHYuY2xvbmUoKTtcclxuICAgICAgdXBkYXRlZEJvZHkucG9zaXRpb24gPSB0aGlzLmNhbGNOZXdQb3MoXHJcbiAgICAgICAgdXBkYXRlZEJvZHkucG9zaXRpb24sXHJcbiAgICAgICAgdXBkYXRlZEJvZHkudmVsb2NpdHksXHJcbiAgICAgICAgdXBkYXRlZEJvZHkuYWNjZWxlcmF0aW9uLFxyXG4gICAgICAgIGRlbHRhVCxcclxuICAgICAgKTtcclxuICAgICAgcmV0dXJuIHVwZGF0ZWRCb2R5O1xyXG4gICAgfSk7XHJcbiAgICAvLyBhKHQgKyBkdCkgPSBhY2NlbCBhdCB4KHQgKyBkdClcclxuICAgIGxldCBuZXdGb3JjZXMgPSB0aGlzLmZvcmNlQ2FsY3VsYXRvci5nZXRGb3JjZXModXBkYXRlZEJvZGllcyk7XHJcbiAgICByZXR1cm4gbmV3IFN0YXRlKFxyXG4gICAgICB1cGRhdGVkQm9kaWVzLm1hcCgoYjogQ2VsZXN0aWFsQm9keSwgaTogbnVtYmVyKSA9PiB7XHJcbiAgICAgICAgbGV0IG5ld0FjY2VsID0gbmV3Rm9yY2VzW2ldLmRpdmlkZVNjYWxhcihiLm1hc3MpO1xyXG4gICAgICAgIC8vIHYodCArIGR0KSA9IHYodCkgKyAwLjUgKiAoYSh0KSArIGEodCArIGR0KSkgKiBkdFxyXG4gICAgICAgIGIudmVsb2NpdHkuYWRkKGIuYWNjZWxlcmF0aW9uLmFkZChuZXdBY2NlbClcclxuICAgICAgICAgIC5tdWx0aXBseVNjYWxhcihkZWx0YVQgLyAyKSk7XHJcbiAgICAgICAgYi5hY2NlbGVyYXRpb24gPSBuZXdBY2NlbDtcclxuICAgICAgICByZXR1cm4gYjtcclxuICAgICAgfSksXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2FsY3VsYXRlIHRoZSBuZXcgcG9zaXRpb24gb2YgYSBib2R5IGluIHRoZSBmb2xsb3dpbmcgd2F5OlxyXG4gICAqXHJcbiAgICogbmV3UG9zID0gY3VyclBvcyArIGN1cnJWZWwgKiBkZWx0YVQgKyAwLjUgKiBjdXJyQWNjZWwgKiBkZWx0YVReMi5cclxuICAgKiBAcGFyYW0gY3VyclBvcyBjdXJyZW50IHBvc2l0aW9uLlxyXG4gICAqIEBwYXJhbSBjdXJyVmVsIGN1cnJlbnQgdmVsb2NpdHkuXHJcbiAgICogQHBhcmFtIGN1cnJBY2NlbCBjdXJyZW50IGFjY2VsZXJhdGlvbi5cclxuICAgKiBAcGFyYW0gZGVsdGFUIHRpbWUgc3RlcC5cclxuICAgKiBAcmV0dXJucyBuZXcgcG9zaXRpb24uXHJcbiAgICogQGhpZGRlblxyXG4gICAqL1xyXG4gIHByaXZhdGUgY2FsY05ld1BvcyhcclxuICAgIGN1cnJQb3M6IFZlY3RvcjMsXHJcbiAgICBjdXJyVmVsOiBWZWN0b3IzLFxyXG4gICAgY3VyckFjY2VsOiBWZWN0b3IzLFxyXG4gICAgZGVsdGFUOiBudW1iZXIsXHJcbiAgKTogVmVjdG9yMyB7XHJcbiAgICByZXR1cm4gY3VyclBvc1xyXG4gICAgICAuY2xvbmUoKVxyXG4gICAgICAuYWRkKGN1cnJWZWwuY2xvbmUoKVxyXG4gICAgICAgIC5tdWx0aXBseVNjYWxhcihkZWx0YVQpKVxyXG4gICAgICAuYWRkKGN1cnJBY2NlbC5jbG9uZSgpXHJcbiAgICAgICAgLm11bHRpcGx5U2NhbGFyKGRlbHRhVCAqIGRlbHRhVCAqIDAuNSkpO1xyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFJlcHJlc2VudHMgYSBzaW11bGF0aW9uIGZ1bmN0aW9uIG9iamVjdCB0aGF0IHVzZXMgdGhlIFtFdWxlciBpbnRlZ3JhdGlvbiBtZXRob2RdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0V1bGVyX21ldGhvZCkgdG8gc2ltdWxhdGUgbW90aW9ucyBvZiBib2RpZXMuXHJcbiAqIEBjYXRlZ29yeSBTaW11bGF0ZUZ1bmN0aW9uc1xyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEV4cGxpY2l0RXVsZXJTaW0gaW1wbGVtZW50cyBTaW11bGF0ZUZ1bmN0aW9uIHtcclxuICAvKipcclxuICAgKiBGb3JjZSBvYmplY3QgdG8gY2FsY3VsYXRlIGZvcmNlcyBvbiBib2RpZXMgaW4gdGhlIFVuaXZlcnNlLlxyXG4gICAqL1xyXG4gIGZvcmNlOiBGb3JjZTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlIGEgbmV3IEV4cGxpY2l0RXVsZXJTaW0gd2l0aCB0aGUgcHJvdmlkZWQgZm9yY2UgY2FsY3VsYXRvciwgd2hpY2ggaXMgaW52b2tlZCBvbiBldmVyeSBzaW11bGF0aW9uIHN0ZXAuXHJcbiAgICogQHBhcmFtIGZvcmNlIGZvcmNlIGNhbGN1bGF0b3IuXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IoZm9yY2U6IEZvcmNlKSB7XHJcbiAgICB0aGlzLmZvcmNlID0gZm9yY2U7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTaW11bGF0ZSBhIHN0ZXAgaW4gdGhlIFVuaXZlcnNlIGJ5IHVzaW5nIHRoZSBjdXJyZW50IHN0YXRlIGFuZCBhIHRpbWUgc3RlcCwgdXNpbmcgdGhlIEV1bGVyIGludGVncmF0aW9uIG1ldGhvZC5cclxuICAgKiBAcGFyYW0gZGVsdGFUIHRpbWUgc3RlcC5cclxuICAgKiBAcGFyYW0gY3VyclN0YXRlIGN1cnJlbnQgc3RhdGUuXHJcbiAgICogQHJldHVybnMgbmV3IHN0YXRlIGFmdGVyIHRoZSBzaW11bGF0aW9uIHN0ZXAuXHJcbiAgICovXHJcbiAgc2ltdWxhdGUoXHJcbiAgICBkZWx0YVQ6IG51bWJlcixcclxuICAgIGN1cnJTdGF0ZTogU3RhdGUsXHJcbiAgKTogU3RhdGUge1xyXG4gICAgY29uc3QgdXBkYXRlZEJvZGllcyA9IGN1cnJTdGF0ZS5ib2RpZXMubWFwKChiKSA9PiBiLmNsb25lKFxyXG4gICAgICAvLyB4KHQgKyBkdCkgPSB4KHQpICsgdih0KSAqIGR0XHJcbiAgICAgIHRoaXMucmF0ZVVwZGF0ZShiLnBvc2l0aW9uLCBiLnZlbG9jaXR5LCBkZWx0YVQpLFxyXG4gICAgICAvLyB2KHQgKyBkdCkgPSB2KHQpICsgYSh0KSAqIGR0XHJcbiAgICAgIHRoaXMucmF0ZVVwZGF0ZShiLnZlbG9jaXR5LCBiLmFjY2VsZXJhdGlvbiwgZGVsdGFUKSxcclxuICAgICkpO1xyXG4gICAgY29uc3QgdXBkYXRlZEZvcmNlcyA9IHRoaXMuZm9yY2UuZ2V0Rm9yY2VzKHVwZGF0ZWRCb2RpZXMpO1xyXG4gICAgdXBkYXRlZEJvZGllcy5mb3JFYWNoKChiLCBpKSA9PiB7XHJcbiAgICAgIC8vIGEodCArIGR0KSA9IGFjY2VsIGF0IHgodCArIGR0KVxyXG4gICAgICBiLmFjY2VsZXJhdGlvbiA9IHVwZGF0ZWRGb3JjZXNbaV0uZGl2aWRlU2NhbGFyKGIubWFzcyk7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBuZXcgU3RhdGUodXBkYXRlZEJvZGllcyk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGUgYSB2ZWN0b3IgcXVhbnRpdHkgdXNpbmcgdGhlIHJhdGUgb2YgY2hhbmdlIGFuZCBhIHRpbWUgc3RlcC5cclxuICAgKiBAcGFyYW0gcHJldiBwcmV2aW91cyB2YWx1ZS5cclxuICAgKiBAcGFyYW0gcmF0ZSByYXRlIG9mIGNoYW5nZS5cclxuICAgKiBAcGFyYW0gZGVsdGFUIHRpbWUgc3RlcC5cclxuICAgKiBAcmV0dXJucyB1cGRhdGVkIHZhbHVlLlxyXG4gICAqIEBoaWRkZW5cclxuICAgKi9cclxuICBwcml2YXRlIHJhdGVVcGRhdGUocHJldjogVmVjdG9yMywgcmF0ZTogVmVjdG9yMywgZGVsdGFUOiBudW1iZXIpIHtcclxuICAgIHJldHVybiByYXRlLmNsb25lKClcclxuICAgICAgLm11bHRpcGx5U2NhbGFyKGRlbHRhVClcclxuICAgICAgLmFkZChwcmV2KTtcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXByZXNlbnRzIGEgc2ltdWxhdGlvbiBmdW5jdGlvbiBvYmplY3QgdGhhdCB1c2VzIHRoZSBbU2VtaS1JbXBsaWNpdCBFdWxlciBpbnRlZ3JhdGlvbiBtZXRob2RdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NlbWktaW1wbGljaXRfRXVsZXJfbWV0aG9kKSB0byBzaW11bGF0ZSB0aGUgbW90aW9uIG9mIGJvZGllcy5cclxuICogQGNhdGVnb3J5IFNpbXVsYXRlRnVuY3Rpb25zXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgU2VtaUltcGxpY2l0RXVsZXJTaW0gaW1wbGVtZW50cyBTaW11bGF0ZUZ1bmN0aW9uIHtcclxuICAvKipcclxuICAgKiBGb3JjZSBvYmplY3QgdG8gY2FsY3VsYXRlIGZvcmNlcyBvbiBib2RpZXMgaW4gdGhlIFVuaXZlcnNlLlxyXG4gICAqL1xyXG4gIGZvcmNlOiBGb3JjZTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlIGEgbmV3IFNlbWlJbXBsaWNpdEV1bGVyU2ltIHdpdGggdGhlIHByb3ZpZGVkIGZvcmNlIGNhbGN1bGF0b3IsIHdoaWNoIGlzIGludm9rZWQgb24gZXZlcnkgc2ltdWxhdGlvbiBzdGVwLlxyXG4gICAqIEBwYXJhbSBmb3JjZSBmb3JjZSBjYWxjdWxhdG9yLlxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKGZvcmNlOiBGb3JjZSkge1xyXG4gICAgdGhpcy5mb3JjZSA9IGZvcmNlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2ltdWxhdGUgYSBzdGVwIGluIHRoZSBVbml2ZXJzZSBieSB1c2luZyB0aGUgY3VycmVudCBzdGF0ZSBhbmQgYSB0aW1lIHN0ZXAsIHVzaW5nIHRoZSBTZW1pLUltcGxpY2l0IEV1bGVyIGludGVncmF0aW9uIG1ldGhvZC5cclxuICAgKiBAcGFyYW0gZGVsdGFUIHRpbWUgc3RlcC5cclxuICAgKiBAcGFyYW0gY3VyclN0YXRlIGN1cnJlbnQgc3RhdGUuXHJcbiAgICogQHJldHVybnMgbmV3IHN0YXRlIGFmdGVyIHRoZSBzaW11bGF0aW9uIHN0ZXAuXHJcbiAgICovXHJcbiAgc2ltdWxhdGUoXHJcbiAgICBkZWx0YVQ6IG51bWJlcixcclxuICAgIGN1cnJTdGF0ZTogU3RhdGUsXHJcbiAgKTogU3RhdGUge1xyXG4gICAgY29uc3QgdXBkYXRlZEJvZGllcyA9IGN1cnJTdGF0ZS5ib2RpZXMubWFwKChiKSA9PiB7XHJcbiAgICAgIC8vIHYodCArIGR0KSA9IHYodCkgKyBhKHQpICogZHRcclxuICAgICAgY29uc3QgdXBkYXRlZFZlbCA9IHRoaXMucmF0ZVVwZGF0ZShiLnZlbG9jaXR5LCBiLmFjY2VsZXJhdGlvbiwgZGVsdGFUKTtcclxuICAgICAgcmV0dXJuIGIuY2xvbmUoXHJcbiAgICAgICAgLy8geCh0ICsgZHQpID0geCh0KSArIHYodCArIGR0KSAqIGR0XHJcbiAgICAgICAgdGhpcy5yYXRlVXBkYXRlKGIucG9zaXRpb24sIHVwZGF0ZWRWZWwsIGRlbHRhVCksXHJcbiAgICAgICAgdXBkYXRlZFZlbCxcclxuICAgICAgKTtcclxuICAgIH0pO1xyXG4gICAgY29uc3QgdXBkYXRlZEZvcmNlcyA9IHRoaXMuZm9yY2UuZ2V0Rm9yY2VzKHVwZGF0ZWRCb2RpZXMpO1xyXG4gICAgdXBkYXRlZEJvZGllcy5mb3JFYWNoKChiLCBpKSA9PiB7XHJcbiAgICAgIC8vIGEodCArIGR0KSA9IGFjY2VsIGF0IHgodCArIGR0KVxyXG4gICAgICBiLmFjY2VsZXJhdGlvbiA9IHVwZGF0ZWRGb3JjZXNbaV0uZGl2aWRlU2NhbGFyKGIubWFzcyk7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBuZXcgU3RhdGUodXBkYXRlZEJvZGllcyk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGUgYSB2ZWN0b3IgcXVhbnRpdHkgdXNpbmcgdGhlIHJhdGUgb2YgY2hhbmdlIGFuZCBhIHRpbWUgc3RlcC5cclxuICAgKiBAcGFyYW0gcHJldiBwcmV2aW91cyB2YWx1ZS5cclxuICAgKiBAcGFyYW0gcmF0ZSByYXRlIG9mIGNoYW5nZS5cclxuICAgKiBAcGFyYW0gZGVsdGFUIHRpbWUgc3RlcC5cclxuICAgKiBAcmV0dXJucyB1cGRhdGVkIHZhbHVlLlxyXG4gICAqIEBoaWRkZW5cclxuICAgKi9cclxuICBwcml2YXRlIHJhdGVVcGRhdGUocHJldjogVmVjdG9yMywgcmF0ZTogVmVjdG9yMywgZGVsdGFUOiBudW1iZXIpIHtcclxuICAgIHJldHVybiByYXRlLmNsb25lKClcclxuICAgICAgLm11bHRpcGx5U2NhbGFyKGRlbHRhVClcclxuICAgICAgLmFkZChwcmV2KTtcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDb250YWluZXIgZm9yIGludGVybWVkaWF0ZSBraW5lbWF0aWMgcmF0ZSB2YWx1ZXMgaW4gdGhlIFJ1bmdlLUt1dHRhIDQgaW50ZWdyYXRpb24gbWV0aG9kLlxyXG4gKi9cclxudHlwZSBSdW5nZUt1dHRhU3RlcHMgPSB7XHJcbiAgLyoqXHJcbiAgICogSW50ZXJtZWRpYXRlIHZlbG9jaXR5IHJhdGUgdmFsdWVzLlxyXG4gICAqL1xyXG4gIGt2OiBWZWN0b3IzW107XHJcbiAgLyoqXHJcbiAgICogSW50ZXJtZWRpYXRlIHBvc2l0aW9uIHJhdGUgdmFsdWVzLlxyXG4gICAqL1xyXG4gIGt4OiBWZWN0b3IzW107XHJcbn07XHJcblxyXG4vKipcclxuICogUmVwcmVzZW50cyBhIHNpbXVsYXRpb24gZnVuY3Rpb24gb2JqZWN0IHRoYXQgdXNlcyB0aGUgW1J1bmdlLUt1dHRhIDQgaW50ZWdyYXRpb24gbWV0aG9kXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9SdW5nZSVFMiU4MCU5M0t1dHRhX21ldGhvZHMpIHRvIHNpbXVsYXRlIHRoZSBtb3Rpb24gb2YgYm9kaWVzLlxyXG4gKiBAY2F0ZWdvcnkgU2ltdWxhdGVGdW5jdGlvbnNcclxuICovXHJcbmV4cG9ydCBjbGFzcyBSdW5nZUt1dHRhNFNpbSBpbXBsZW1lbnRzIFNpbXVsYXRlRnVuY3Rpb24ge1xyXG4gIC8qKlxyXG4gICAqIEZvcmNlIG9iamVjdCB0byBjYWxjdWxhdGUgZm9yY2VzIG9uIGJvZGllcyBpbiB0aGUgVW5pdmVyc2UuXHJcbiAgICovXHJcbiAgZm9yY2U6IEZvcmNlO1xyXG4gIC8qKlxyXG4gICAqIFdlaWdodHMgZm9yIHdlaWdodGVkIGF2ZXJhZ2UuXHJcbiAgICovXHJcbiAgd2VpZ2h0czogbnVtYmVyW107XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZSBhIG5ldyBSdW5nZUt1dHRhNFNpbSB3aXRoIHRoZSBwcm92aWRlZCB3ZWlnaHRzIGZvciBhdmVyYWdlIGZvcmNlIGNhbGN1bGF0b3IsIHdoaWNoIGlzIGludm9rZWQgb24gZXZlcnkgc2ltdWxhdGlvbiBzdGVwLlxyXG4gICAqIEBwYXJhbSBmb3JjZSBmb3JjZSBjYWxjdWxhdG9yLlxyXG4gICAqIEBwYXJhbSB3ZWlnaHRzIHdlaWdodHMgZm9yIHdlaWdodGVkIGF2ZXJhZ2UuXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IoZm9yY2U6IEZvcmNlLCB3ZWlnaHRzOiBudW1iZXJbXSkge1xyXG4gICAgdGhpcy5mb3JjZSA9IGZvcmNlO1xyXG4gICAgaWYgKHdlaWdodHMubGVuZ3RoICE9PSA0KSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcignV2VpZ2h0cyBmb3IgUks0IG11c3QgYmUgb2YgbGVuZ3RoIDQnKTtcclxuICAgIH1cclxuICAgIHRoaXMud2VpZ2h0cyA9IHdlaWdodHM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTaW11bGF0ZSBhIHN0ZXAgaW4gdGhlIFVuaXZlcnNlIGJ5IHVzaW5nIHRoZSBjdXJyZW50IHN0YXRlIGFuZCBhIHRpbWUgc3RlcCwgdXNpbmcgdGhlIFJ1bmdlLUt1dHRhIDQgaW50ZWdyYXRpb24gbWV0aG9kLlxyXG4gICAqIEBwYXJhbSBkZWx0YVQgdGltZSBzdGVwLlxyXG4gICAqIEBwYXJhbSBjdXJyU3RhdGUgY3VycmVudCBzdGF0ZS5cclxuICAgKiBAcmV0dXJucyBuZXcgc3RhdGUgYWZ0ZXIgdGhlIHNpbXVsYXRpb24gc3RlcC5cclxuICAgKi9cclxuICBzaW11bGF0ZShcclxuICAgIGRlbHRhVDogbnVtYmVyLFxyXG4gICAgY3VyclN0YXRlOiBTdGF0ZSxcclxuICApOiBTdGF0ZSB7XHJcbiAgICBsZXQgYm9kaWVzSzogUnVuZ2VLdXR0YVN0ZXBzW10gPSBjdXJyU3RhdGUuYm9kaWVzLm1hcCgodikgPT4gKHtcclxuICAgICAgLy8gazF2ID0gYSh4KHQpKVxyXG4gICAgICBrdjogW3YuYWNjZWxlcmF0aW9uLmNsb25lKCldLFxyXG4gICAgICAvLyBrMXIgPSB2KHQpXHJcbiAgICAgIGt4OiBbdi52ZWxvY2l0eS5jbG9uZSgpXSxcclxuICAgIH0pKTtcclxuICAgIC8vIGsydiA9IGEoeCh0KSArIGsxeCAqIGR0IC8gMilcclxuICAgIGNvbnN0IGsydiA9IHRoaXMuZ2V0SW50ZXJLVihjdXJyU3RhdGUuYm9kaWVzLCBib2RpZXNLLCAwLCBkZWx0YVQgLyAyKTtcclxuICAgIC8vIGsyeCA9IHYodCkgKyBrMXYgKiBkdCAvIDJcclxuICAgIGNvbnN0IGsyeCA9IHRoaXMuZ2V0SW50ZXJLWChjdXJyU3RhdGUuYm9kaWVzLCBib2RpZXNLLCAwLCBkZWx0YVQgLyAyKTtcclxuICAgIGJvZGllc0suZm9yRWFjaCgodiwgaSkgPT4ge1xyXG4gICAgICB2Lmt2LnB1c2goazJ2W2ldKTtcclxuICAgICAgdi5reC5wdXNoKGsyeFtpXSk7XHJcbiAgICB9KTtcclxuICAgIC8vIGszdiA9IGEoeCh0KSArIGsyeCAqIGR0IC8gMilcclxuICAgIGNvbnN0IGszdiA9IHRoaXMuZ2V0SW50ZXJLVihjdXJyU3RhdGUuYm9kaWVzLCBib2RpZXNLLCAxLCBkZWx0YVQgLyAyKTtcclxuICAgIC8vIGszeCA9IHYodCkgKyBrMnYgKiBkdCAvIDJcclxuICAgIGNvbnN0IGszeCA9IHRoaXMuZ2V0SW50ZXJLWChjdXJyU3RhdGUuYm9kaWVzLCBib2RpZXNLLCAxLCBkZWx0YVQgLyAyKTtcclxuICAgIGJvZGllc0suZm9yRWFjaCgodiwgaSkgPT4ge1xyXG4gICAgICB2Lmt2LnB1c2goazN2W2ldKTtcclxuICAgICAgdi5reC5wdXNoKGszeFtpXSk7XHJcbiAgICB9KTtcclxuICAgIC8vIGszdiA9IGEoeCh0KSArIGszeCAqIGR0KVxyXG4gICAgY29uc3QgazR2ID0gdGhpcy5nZXRJbnRlcktWKGN1cnJTdGF0ZS5ib2RpZXMsIGJvZGllc0ssIDIsIGRlbHRhVCk7XHJcbiAgICAvLyBrNHggPSB2KHQpICsgazN2ICogZHRcclxuICAgIGNvbnN0IGs0eCA9IHRoaXMuZ2V0SW50ZXJLWChjdXJyU3RhdGUuYm9kaWVzLCBib2RpZXNLLCAyLCBkZWx0YVQpO1xyXG4gICAgYm9kaWVzSy5mb3JFYWNoKCh2LCBpKSA9PiB7XHJcbiAgICAgIHYua3YucHVzaChrNHZbaV0pO1xyXG4gICAgICB2Lmt4LnB1c2goazR4W2ldKTtcclxuICAgIH0pO1xyXG4gICAgY29uc3QgdXBkYXRlZEJvZGllcyA9IGN1cnJTdGF0ZS5ib2RpZXMubWFwKChiLCBpKSA9PiB7XHJcbiAgICAgIGNvbnN0IHdlaWdodGVkWFJhdGUgPSBuZXcgVmVjdG9yMygpO1xyXG4gICAgICBjb25zdCB3ZWlnaHRlZFZSYXRlID0gbmV3IFZlY3RvcjMoKTtcclxuICAgICAgYm9kaWVzS1tpXS5reC5mb3JFYWNoKCh2LCBqKSA9PiB7XHJcbiAgICAgICAgd2VpZ2h0ZWRYUmF0ZS5hZGQodi5tdWx0aXBseVNjYWxhcih0aGlzLndlaWdodHNbal0pKTtcclxuICAgICAgfSk7XHJcbiAgICAgIGJvZGllc0tbaV0ua3YuZm9yRWFjaCgodiwgaikgPT4ge1xyXG4gICAgICAgIHdlaWdodGVkVlJhdGUuYWRkKHYubXVsdGlwbHlTY2FsYXIodGhpcy53ZWlnaHRzW2pdKSk7XHJcbiAgICAgIH0pO1xyXG4gICAgICByZXR1cm4gYi5jbG9uZShcclxuICAgICAgICB3ZWlnaHRlZFhSYXRlLm11bHRpcGx5U2NhbGFyKGRlbHRhVCAvIDYpXHJcbiAgICAgICAgICAuYWRkKGIucG9zaXRpb24pLFxyXG4gICAgICAgIHdlaWdodGVkVlJhdGUubXVsdGlwbHlTY2FsYXIoZGVsdGFUIC8gNilcclxuICAgICAgICAgIC5hZGQoYi52ZWxvY2l0eSksXHJcbiAgICAgICk7XHJcbiAgICB9KTtcclxuICAgIGNvbnN0IHVwZGF0ZWRGb3JjZXMgPSB0aGlzLmZvcmNlLmdldEZvcmNlcyh1cGRhdGVkQm9kaWVzKTtcclxuICAgIHVwZGF0ZWRCb2RpZXMuZm9yRWFjaCgodiwgaSkgPT4ge1xyXG4gICAgICB2LmFjY2VsZXJhdGlvbiA9IHVwZGF0ZWRGb3JjZXNbaV0uZGl2aWRlU2NhbGFyKHYubWFzcyk7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBuZXcgU3RhdGUodXBkYXRlZEJvZGllcyk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgaW50ZXJtZWRpYXRlIHZlbG9jaXR5IHJhdGUgdmFsdWVzLlxyXG4gICAqIEBwYXJhbSBib2RpZXMgY3VycmVudCBib2RpZXMuXHJcbiAgICogQHBhcmFtIGJvZGllc0sgaW50ZXJtZWRpYXRlIGtpbmVtYXRpYyByYXRlIHZhbHVlcyBmb3IgYWxsIGJvZGllcy5cclxuICAgKiBAcGFyYW0ga3JJbmQgaW5kZXggb2YgaW50ZXJtZWRpYXRlIGtpbmVtYXRpYyByYXRlIHZhbHVlIHRvIGJhc2UgdGhlIG5ldyBpbnRlcm1lZGlhdGUgdmFsdWUgb24uXHJcbiAgICogQHBhcmFtIGRlbHRhVCB0aW1lIHN0ZXAuXHJcbiAgICogQHJldHVybnMgbmV4dCBpbnRlcm1lZGlhdGUgdmVsb2NpdHkgcmF0ZSB2YWx1ZXMgZm9yIGFsbCBib2RpZXMuXHJcbiAgICogQGhpZGRlblxyXG4gICAqL1xyXG4gIHByaXZhdGUgZ2V0SW50ZXJLVihcclxuICAgIGJvZGllczogQ2VsZXN0aWFsQm9keVtdLFxyXG4gICAgYm9kaWVzSzogUnVuZ2VLdXR0YVN0ZXBzW10sXHJcbiAgICBrckluZDogbnVtYmVyLFxyXG4gICAgZGVsdGFUOiBudW1iZXIsXHJcbiAgKTogVmVjdG9yM1tdIHtcclxuICAgIC8vIG5ld1ggPSB4KHQpICsgayhrSW5kKXggKiBkZWx0YVxyXG4gICAgbGV0IG5ld0JvZGllcyA9IGJvZGllcy5tYXAoKHYsIGkpID0+IHtcclxuICAgICAgbGV0IG5ld0JvZHkgPSB2LmNsb25lKCk7XHJcbiAgICAgIG5ld0JvZHkucG9zaXRpb24uYWRkKGJvZGllc0tbaV0ua3hba3JJbmRdLmNsb25lKClcclxuICAgICAgICAubXVsdGlwbHlTY2FsYXIoZGVsdGFUKSk7XHJcbiAgICAgIHJldHVybiBuZXdCb2R5O1xyXG4gICAgfSk7XHJcbiAgICAvLyBhY2NlbCBhdCBuZXdYXHJcbiAgICByZXR1cm4gdGhpcy5mb3JjZS5nZXRGb3JjZXMobmV3Qm9kaWVzKVxyXG4gICAgICAubWFwKCh2LCBpKSA9PiB2LmRpdmlkZVNjYWxhcihib2RpZXNbaV0ubWFzcykpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0IGludGVybWVkaWF0ZSBwb3NpdGlvbiByYXRlIHZhbHVlcy5cclxuICAgKiBAcGFyYW0gYm9kaWVzIGN1cnJlbnQgYm9kaWVzLlxyXG4gICAqIEBwYXJhbSBib2RpZXNLIGludGVybWVkaWF0ZSBraW5lbWF0aWMgcmF0ZSB2YWx1ZXMgZm9yIGFsbCBib2RpZXMuXHJcbiAgICogQHBhcmFtIGtJbmQgaW5kZXggb2YgaW50ZXJtZWRpYXRlIGtpbmVtYXRpYyByYXRlIHZhbHVlIHRvIGJhc2UgdGhlIG5ldyBpbnRlcm1lZGlhdGUgdmFsdWUgb24uXHJcbiAgICogQHBhcmFtIGRlbHRhVCB0aW1lIHN0ZXAuXHJcbiAgICogQHJldHVybnMgbmV4dCBpbnRlcm1lZGlhdGUgcG9zaXRpb24gcmF0ZSB2YWx1ZXMgZm9yIGFsbCBib2RpZXMuXHJcbiAgICogQGhpZGRlblxyXG4gICAqL1xyXG4gIHByaXZhdGUgZ2V0SW50ZXJLWChcclxuICAgIGJvZGllczogQ2VsZXN0aWFsQm9keVtdLFxyXG4gICAgYm9kaWVzSzogUnVuZ2VLdXR0YVN0ZXBzW10sXHJcbiAgICBrSW5kOiBudW1iZXIsXHJcbiAgICBkZWx0YVQ6IG51bWJlcixcclxuICApOiBWZWN0b3IzW10ge1xyXG4gICAgLy8gdih0KSArIGsoa0luZCl2ICogZGVsdGFUXHJcbiAgICByZXR1cm4gYm9kaWVzLm1hcCgodiwgaSkgPT4gdi52ZWxvY2l0eS5jbG9uZSgpXHJcbiAgICAgIC5hZGQoYm9kaWVzS1tpXS5rdltrSW5kXS5jbG9uZSgpXHJcbiAgICAgICAgLm11bHRpcGx5U2NhbGFyKGRlbHRhVCkpKTtcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHR5cGUgeyBGb3JjZSB9IGZyb20gJy4vRm9yY2UnO1xyXG5pbXBvcnQgdHlwZSB7IFN0YXRlIH0gZnJvbSAnLi9TdGF0ZSc7XHJcblxyXG4vKipcclxuICogUmVwcmVzZW50cyBhIGZ1bmN0aW9uIG9iamVjdCB1c2VkIGZvciBzaW11bGF0aW5nIHRoZSBVbml2ZXJzZS4gU2hvdWxkIGVuY2Fwc3VsYXRlIHRoZSBudW1lcmljYWwgaW50ZWdyYXRpb24gbWV0aG9kIGFuZCBvdGhlciBuZWNlc3Nhcnkgc2ltdWxhdGlvbiBsb2dpYy4gQ2FuIHVzZSBhbiBleHRlcm5hbCBmb3JjZSBjYWxjdWxhdGlvbiBmdW5jdGlvbiBvYmplY3QgLSBzZWUge0BsaW5rIEZvcmNlfS5cclxuICogQGNhdGVnb3J5IEludGVyZmFjZXNcclxuICogQGNhdGVnb3J5IFNpbXVsYXRlRnVuY3Rpb25zXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIFNpbXVsYXRlRnVuY3Rpb24ge1xyXG4gIC8qKlxyXG4gICAqIFNpbXVsYXRlIGEgc3RlcCBpbiB0aGUgVW5pdmVyc2UgYnkgdXNpbmcgdGhlIHByZXZpb3VzIGFuZC9vciBjdXJyZW50IHN0YXRlIGFuZCBhIHRpbWUgc3RlcC5cclxuICAgKiBAcGFyYW0gZGVsdGFUIHRpbWUgc3RlcC5cclxuICAgKiBAcGFyYW0gY3VyclN0YXRlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIFVuaXZlcnNlLlxyXG4gICAqIEBwYXJhbSBwcmV2U3RhdGUgcHJldmlvdXMgc3RhdGUgb2YgdGhlIFVuaXZlcnNlLlxyXG4gICAqIEByZXR1cm5zIHRoZSBuZXh0IHN0YXRlIG9mIHRoZSBVbml2ZXJzZS5cclxuICAgKi9cclxuICBzaW11bGF0ZShkZWx0YVQ6IG51bWJlciwgY3VyclN0YXRlOiBTdGF0ZSwgcHJldlN0YXRlOiBTdGF0ZSk6IFN0YXRlXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBGdW5jdGlvbiBvYmplY3QgdGhhdCB1c2VzIHRoZSB1c2VyLWRlZmluZWQgbGFtYmRhIGZ1bmN0aW9uIHRvIHNpbXVsYXRlIHRoZSBVbml2ZXJzZS5cclxuICogQGNhdGVnb3J5IFNpbXVsYXRlRnVuY3Rpb25zXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgTGFtYmRhU2ltIGltcGxlbWVudHMgU2ltdWxhdGVGdW5jdGlvbiB7XHJcbiAgcmVhZG9ubHkgZm46IChkZWx0YVQ6IG51bWJlciwgY3VyclN0YXRlOiBTdGF0ZSwgcHJldlN0YXRlOiBTdGF0ZSkgPT4gU3RhdGU7XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZSBhIG5ldyBMYW1iZGFTaW0gd2l0aCB0aGUgcHJvdmlkZWQgbGFtYmRhIGZ1bmN0aW9uLlxyXG4gICAqIC0gVGhlIGxhbWJkYSBmdW5jdGlvbiBzaG91bGQgdGFrZSBpbiB0aGUgdGltZSBzdGVwLCB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgVW5pdmVyc2UsIGFuZCB0aGUgcHJldmlvdXMgc3RhdGUgb2YgdGhlIFVuaXZlcnNlLCBhbmQgcmV0dXJuIHRoZSBuZXh0IHN0YXRlIG9mIHRoZSBVbml2ZXJzZS5cclxuICAgKiAtIFRoZSBsYW1iZGEgZnVuY3Rpb24gc2hvdWxkIGNhbGwgb3IgY2FsY3VsYXRlIHRoZSBmb3JjZXMgYWN0aW9uIG9uIHRoZSBib2RpZXMgYnkgaXRzZWxmLlxyXG4gICAqIEBwYXJhbSBmbiBsYW1iZGEgZnVuY3Rpb24uXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IoZm46IChkZWx0YVQ6IG51bWJlciwgY3VyclN0YXRlOiBTdGF0ZSwgcHJldlN0YXRlOiBTdGF0ZSkgPT4gU3RhdGUpIHtcclxuICAgIHRoaXMuZm4gPSBmbjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNpbXVsYXRlIHRoZSBVbml2ZXJzZSB1c2luZyB0aGUgbGFtYmRhIGZ1bmN0aW9uLlxyXG4gICAqIEBwYXJhbSBkZWx0YVQgdGltZSBzdGVwLlxyXG4gICAqIEBwYXJhbSBjdXJyU3RhdGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgVW5pdmVyc2UuXHJcbiAgICogQHBhcmFtIHByZXZTdGF0ZSBwcmV2aW91cyBzdGF0ZSBvZiB0aGUgVW5pdmVyc2UuXHJcbiAgICogQHJldHVybnMgdGhlIG5leHQgc3RhdGUgb2YgdGhlIFVuaXZlcnNlLlxyXG4gICAqL1xyXG4gIHNpbXVsYXRlKGRlbHRhVDogbnVtYmVyLCBjdXJyU3RhdGU6IFN0YXRlLCBwcmV2U3RhdGU6IFN0YXRlKTogU3RhdGUge1xyXG4gICAgcmV0dXJuIHRoaXMuZm4oZGVsdGFULCBjdXJyU3RhdGUsIHByZXZTdGF0ZSk7XHJcbiAgfVxyXG59XHJcbiIsIi8qKlxuICogbGlsLWd1aVxuICogaHR0cHM6Ly9saWwtZ3VpLmdlb3JnZWFsd2F5cy5jb21cbiAqIEB2ZXJzaW9uIDAuMTkuMlxuICogQGF1dGhvciBHZW9yZ2UgTWljaGFlbCBCcm93ZXJcbiAqIEBsaWNlbnNlIE1JVFxuICovXG5cbi8qKlxuICogQmFzZSBjbGFzcyBmb3IgYWxsIGNvbnRyb2xsZXJzLlxuICovXG5jbGFzcyBDb250cm9sbGVyIHtcblxuXHRjb25zdHJ1Y3RvciggcGFyZW50LCBvYmplY3QsIHByb3BlcnR5LCBjbGFzc05hbWUsIGVsZW1lbnRUeXBlID0gJ2RpdicgKSB7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgR1VJIHRoYXQgY29udGFpbnMgdGhpcyBjb250cm9sbGVyLlxuXHRcdCAqIEB0eXBlIHtHVUl9XG5cdFx0ICovXG5cdFx0dGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgb2JqZWN0IHRoaXMgY29udHJvbGxlciB3aWxsIG1vZGlmeS5cblx0XHQgKiBAdHlwZSB7b2JqZWN0fVxuXHRcdCAqL1xuXHRcdHRoaXMub2JqZWN0ID0gb2JqZWN0O1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIGNvbnRyb2wuXG5cdFx0ICogQHR5cGUge3N0cmluZ31cblx0XHQgKi9cblx0XHR0aGlzLnByb3BlcnR5ID0gcHJvcGVydHk7XG5cblx0XHQvKipcblx0XHQgKiBVc2VkIHRvIGRldGVybWluZSBpZiB0aGUgY29udHJvbGxlciBpcyBkaXNhYmxlZC5cblx0XHQgKiBVc2UgYGNvbnRyb2xsZXIuZGlzYWJsZSggdHJ1ZXxmYWxzZSApYCB0byBtb2RpZnkgdGhpcyB2YWx1ZS5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKi9cblx0XHR0aGlzLl9kaXNhYmxlZCA9IGZhbHNlO1xuXG5cdFx0LyoqXG5cdFx0ICogVXNlZCB0byBkZXRlcm1pbmUgaWYgdGhlIENvbnRyb2xsZXIgaXMgaGlkZGVuLlxuXHRcdCAqIFVzZSBgY29udHJvbGxlci5zaG93KClgIG9yIGBjb250cm9sbGVyLmhpZGUoKWAgdG8gY2hhbmdlIHRoaXMuXG5cdFx0ICogQHR5cGUge2Jvb2xlYW59XG5cdFx0ICovXG5cdFx0dGhpcy5faGlkZGVuID0gZmFsc2U7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgdmFsdWUgb2YgYG9iamVjdFsgcHJvcGVydHkgXWAgd2hlbiB0aGUgY29udHJvbGxlciB3YXMgY3JlYXRlZC5cblx0XHQgKiBAdHlwZSB7YW55fVxuXHRcdCAqL1xuXHRcdHRoaXMuaW5pdGlhbFZhbHVlID0gdGhpcy5nZXRWYWx1ZSgpO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIG91dGVybW9zdCBjb250YWluZXIgRE9NIGVsZW1lbnQgZm9yIHRoaXMgY29udHJvbGxlci5cblx0XHQgKiBAdHlwZSB7SFRNTEVsZW1lbnR9XG5cdFx0ICovXG5cdFx0dGhpcy5kb21FbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggZWxlbWVudFR5cGUgKTtcblx0XHR0aGlzLmRvbUVsZW1lbnQuY2xhc3NMaXN0LmFkZCggJ2NvbnRyb2xsZXInICk7XG5cdFx0dGhpcy5kb21FbGVtZW50LmNsYXNzTGlzdC5hZGQoIGNsYXNzTmFtZSApO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIERPTSBlbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIGNvbnRyb2xsZXIncyBuYW1lLlxuXHRcdCAqIEB0eXBlIHtIVE1MRWxlbWVudH1cblx0XHQgKi9cblx0XHR0aGlzLiRuYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2RpdicgKTtcblx0XHR0aGlzLiRuYW1lLmNsYXNzTGlzdC5hZGQoICduYW1lJyApO1xuXG5cdFx0Q29udHJvbGxlci5uZXh0TmFtZUlEID0gQ29udHJvbGxlci5uZXh0TmFtZUlEIHx8IDA7XG5cdFx0dGhpcy4kbmFtZS5pZCA9IGBsaWwtZ3VpLW5hbWUtJHsrK0NvbnRyb2xsZXIubmV4dE5hbWVJRH1gO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIERPTSBlbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIGNvbnRyb2xsZXIncyBcIndpZGdldFwiICh3aGljaCBkaWZmZXJzIGJ5IGNvbnRyb2xsZXIgdHlwZSkuXG5cdFx0ICogQHR5cGUge0hUTUxFbGVtZW50fVxuXHRcdCAqL1xuXHRcdHRoaXMuJHdpZGdldCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoICdkaXYnICk7XG5cdFx0dGhpcy4kd2lkZ2V0LmNsYXNzTGlzdC5hZGQoICd3aWRnZXQnICk7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgRE9NIGVsZW1lbnQgdGhhdCByZWNlaXZlcyB0aGUgZGlzYWJsZWQgYXR0cmlidXRlIHdoZW4gdXNpbmcgZGlzYWJsZSgpLlxuXHRcdCAqIEB0eXBlIHtIVE1MRWxlbWVudH1cblx0XHQgKi9cblx0XHR0aGlzLiRkaXNhYmxlID0gdGhpcy4kd2lkZ2V0O1xuXG5cdFx0dGhpcy5kb21FbGVtZW50LmFwcGVuZENoaWxkKCB0aGlzLiRuYW1lICk7XG5cdFx0dGhpcy5kb21FbGVtZW50LmFwcGVuZENoaWxkKCB0aGlzLiR3aWRnZXQgKTtcblxuXHRcdC8vIERvbid0IGZpcmUgZ2xvYmFsIGtleSBldmVudHMgd2hpbGUgdHlwaW5nIGluIGEgY29udHJvbGxlclxuXHRcdHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCAna2V5ZG93bicsIGUgPT4gZS5zdG9wUHJvcGFnYXRpb24oKSApO1xuXHRcdHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCAna2V5dXAnLCBlID0+IGUuc3RvcFByb3BhZ2F0aW9uKCkgKTtcblxuXHRcdHRoaXMucGFyZW50LmNoaWxkcmVuLnB1c2goIHRoaXMgKTtcblx0XHR0aGlzLnBhcmVudC5jb250cm9sbGVycy5wdXNoKCB0aGlzICk7XG5cblx0XHR0aGlzLnBhcmVudC4kY2hpbGRyZW4uYXBwZW5kQ2hpbGQoIHRoaXMuZG9tRWxlbWVudCApO1xuXG5cdFx0dGhpcy5fbGlzdGVuQ2FsbGJhY2sgPSB0aGlzLl9saXN0ZW5DYWxsYmFjay5iaW5kKCB0aGlzICk7XG5cblx0XHR0aGlzLm5hbWUoIHByb3BlcnR5ICk7XG5cblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBuYW1lIG9mIHRoZSBjb250cm9sbGVyIGFuZCBpdHMgbGFiZWwgaW4gdGhlIEdVSS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcblx0ICogQHJldHVybnMge3RoaXN9XG5cdCAqL1xuXHRuYW1lKCBuYW1lICkge1xuXHRcdC8qKlxuXHRcdCAqIFRoZSBjb250cm9sbGVyJ3MgbmFtZS4gVXNlIGBjb250cm9sbGVyLm5hbWUoICdOYW1lJyApYCB0byBtb2RpZnkgdGhpcyB2YWx1ZS5cblx0XHQgKiBAdHlwZSB7c3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRoaXMuX25hbWUgPSBuYW1lO1xuXHRcdHRoaXMuJG5hbWUudGV4dENvbnRlbnQgPSBuYW1lO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBhc3MgYSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbmV2ZXIgdGhlIHZhbHVlIGlzIG1vZGlmaWVkIGJ5IHRoaXMgY29udHJvbGxlci5cblx0ICogVGhlIGZ1bmN0aW9uIHJlY2VpdmVzIHRoZSBuZXcgdmFsdWUgYXMgaXRzIGZpcnN0IHBhcmFtZXRlci4gVGhlIHZhbHVlIG9mIGB0aGlzYCB3aWxsIGJlIHRoZVxuXHQgKiBjb250cm9sbGVyLlxuXHQgKlxuXHQgKiBGb3IgZnVuY3Rpb24gY29udHJvbGxlcnMsIHRoZSBgb25DaGFuZ2VgIGNhbGxiYWNrIHdpbGwgYmUgZmlyZWQgb24gY2xpY2ssIGFmdGVyIHRoZSBmdW5jdGlvblxuXHQgKiBleGVjdXRlcy5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcblx0ICogQHJldHVybnMge3RoaXN9XG5cdCAqIEBleGFtcGxlXG5cdCAqIGNvbnN0IGNvbnRyb2xsZXIgPSBndWkuYWRkKCBvYmplY3QsICdwcm9wZXJ0eScgKTtcblx0ICpcblx0ICogY29udHJvbGxlci5vbkNoYW5nZSggZnVuY3Rpb24oIHYgKSB7XG5cdCAqIFx0Y29uc29sZS5sb2coICdUaGUgdmFsdWUgaXMgbm93ICcgKyB2ICk7XG5cdCAqIFx0Y29uc29sZS5hc3NlcnQoIHRoaXMgPT09IGNvbnRyb2xsZXIgKTtcblx0ICogfSApO1xuXHQgKi9cblx0b25DaGFuZ2UoIGNhbGxiYWNrICkge1xuXHRcdC8qKlxuXHRcdCAqIFVzZWQgdG8gYWNjZXNzIHRoZSBmdW5jdGlvbiBib3VuZCB0byBgb25DaGFuZ2VgIGV2ZW50cy4gRG9uJ3QgbW9kaWZ5IHRoaXMgdmFsdWUgZGlyZWN0bHkuXG5cdFx0ICogVXNlIHRoZSBgY29udHJvbGxlci5vbkNoYW5nZSggY2FsbGJhY2sgKWAgbWV0aG9kIGluc3RlYWQuXG5cdFx0ICogQHR5cGUge0Z1bmN0aW9ufVxuXHRcdCAqL1xuXHRcdHRoaXMuX29uQ2hhbmdlID0gY2FsbGJhY2s7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQ2FsbHMgdGhlIG9uQ2hhbmdlIG1ldGhvZHMgb2YgdGhpcyBjb250cm9sbGVyIGFuZCBpdHMgcGFyZW50IEdVSS5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0X2NhbGxPbkNoYW5nZSgpIHtcblxuXHRcdHRoaXMucGFyZW50Ll9jYWxsT25DaGFuZ2UoIHRoaXMgKTtcblxuXHRcdGlmICggdGhpcy5fb25DaGFuZ2UgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHRoaXMuX29uQ2hhbmdlLmNhbGwoIHRoaXMsIHRoaXMuZ2V0VmFsdWUoKSApO1xuXHRcdH1cblxuXHRcdHRoaXMuX2NoYW5nZWQgPSB0cnVlO1xuXG5cdH1cblxuXHQvKipcblx0ICogUGFzcyBhIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBhZnRlciB0aGlzIGNvbnRyb2xsZXIgaGFzIGJlZW4gbW9kaWZpZWQgYW5kIGxvc2VzIGZvY3VzLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuXHQgKiBAcmV0dXJucyB7dGhpc31cblx0ICogQGV4YW1wbGVcblx0ICogY29uc3QgY29udHJvbGxlciA9IGd1aS5hZGQoIG9iamVjdCwgJ3Byb3BlcnR5JyApO1xuXHQgKlxuXHQgKiBjb250cm9sbGVyLm9uRmluaXNoQ2hhbmdlKCBmdW5jdGlvbiggdiApIHtcblx0ICogXHRjb25zb2xlLmxvZyggJ0NoYW5nZXMgY29tcGxldGU6ICcgKyB2ICk7XG5cdCAqIFx0Y29uc29sZS5hc3NlcnQoIHRoaXMgPT09IGNvbnRyb2xsZXIgKTtcblx0ICogfSApO1xuXHQgKi9cblx0b25GaW5pc2hDaGFuZ2UoIGNhbGxiYWNrICkge1xuXHRcdC8qKlxuXHRcdCAqIFVzZWQgdG8gYWNjZXNzIHRoZSBmdW5jdGlvbiBib3VuZCB0byBgb25GaW5pc2hDaGFuZ2VgIGV2ZW50cy4gRG9uJ3QgbW9kaWZ5IHRoaXMgdmFsdWVcblx0XHQgKiBkaXJlY3RseS4gVXNlIHRoZSBgY29udHJvbGxlci5vbkZpbmlzaENoYW5nZSggY2FsbGJhY2sgKWAgbWV0aG9kIGluc3RlYWQuXG5cdFx0ICogQHR5cGUge0Z1bmN0aW9ufVxuXHRcdCAqL1xuXHRcdHRoaXMuX29uRmluaXNoQ2hhbmdlID0gY2FsbGJhY2s7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2hvdWxkIGJlIGNhbGxlZCBieSBDb250cm9sbGVyIHdoZW4gaXRzIHdpZGdldHMgbG9zZSBmb2N1cy5cblx0ICogQHByb3RlY3RlZFxuXHQgKi9cblx0X2NhbGxPbkZpbmlzaENoYW5nZSgpIHtcblxuXHRcdGlmICggdGhpcy5fY2hhbmdlZCApIHtcblxuXHRcdFx0dGhpcy5wYXJlbnQuX2NhbGxPbkZpbmlzaENoYW5nZSggdGhpcyApO1xuXG5cdFx0XHRpZiAoIHRoaXMuX29uRmluaXNoQ2hhbmdlICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHRoaXMuX29uRmluaXNoQ2hhbmdlLmNhbGwoIHRoaXMsIHRoaXMuZ2V0VmFsdWUoKSApO1xuXHRcdFx0fVxuXG5cdFx0fVxuXG5cdFx0dGhpcy5fY2hhbmdlZCA9IGZhbHNlO1xuXG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgY29udHJvbGxlciBiYWNrIHRvIGl0cyBpbml0aWFsIHZhbHVlLlxuXHQgKiBAcmV0dXJucyB7dGhpc31cblx0ICovXG5cdHJlc2V0KCkge1xuXHRcdHRoaXMuc2V0VmFsdWUoIHRoaXMuaW5pdGlhbFZhbHVlICk7XG5cdFx0dGhpcy5fY2FsbE9uRmluaXNoQ2hhbmdlKCk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogRW5hYmxlcyB0aGlzIGNvbnRyb2xsZXIuXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gZW5hYmxlZFxuXHQgKiBAcmV0dXJucyB7dGhpc31cblx0ICogQGV4YW1wbGVcblx0ICogY29udHJvbGxlci5lbmFibGUoKTtcblx0ICogY29udHJvbGxlci5lbmFibGUoIGZhbHNlICk7IC8vIGRpc2FibGVcblx0ICogY29udHJvbGxlci5lbmFibGUoIGNvbnRyb2xsZXIuX2Rpc2FibGVkICk7IC8vIHRvZ2dsZVxuXHQgKi9cblx0ZW5hYmxlKCBlbmFibGVkID0gdHJ1ZSApIHtcblx0XHRyZXR1cm4gdGhpcy5kaXNhYmxlKCAhZW5hYmxlZCApO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc2FibGVzIHRoaXMgY29udHJvbGxlci5cblx0ICogQHBhcmFtIHtib29sZWFufSBkaXNhYmxlZFxuXHQgKiBAcmV0dXJucyB7dGhpc31cblx0ICogQGV4YW1wbGVcblx0ICogY29udHJvbGxlci5kaXNhYmxlKCk7XG5cdCAqIGNvbnRyb2xsZXIuZGlzYWJsZSggZmFsc2UgKTsgLy8gZW5hYmxlXG5cdCAqIGNvbnRyb2xsZXIuZGlzYWJsZSggIWNvbnRyb2xsZXIuX2Rpc2FibGVkICk7IC8vIHRvZ2dsZVxuXHQgKi9cblx0ZGlzYWJsZSggZGlzYWJsZWQgPSB0cnVlICkge1xuXG5cdFx0aWYgKCBkaXNhYmxlZCA9PT0gdGhpcy5fZGlzYWJsZWQgKSByZXR1cm4gdGhpcztcblxuXHRcdHRoaXMuX2Rpc2FibGVkID0gZGlzYWJsZWQ7XG5cblx0XHR0aGlzLmRvbUVsZW1lbnQuY2xhc3NMaXN0LnRvZ2dsZSggJ2Rpc2FibGVkJywgZGlzYWJsZWQgKTtcblx0XHR0aGlzLiRkaXNhYmxlLnRvZ2dsZUF0dHJpYnV0ZSggJ2Rpc2FibGVkJywgZGlzYWJsZWQgKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXG5cdH1cblxuXHQvKipcblx0ICogU2hvd3MgdGhlIENvbnRyb2xsZXIgYWZ0ZXIgaXQncyBiZWVuIGhpZGRlbi5cblx0ICogQHBhcmFtIHtib29sZWFufSBzaG93XG5cdCAqIEByZXR1cm5zIHt0aGlzfVxuXHQgKiBAZXhhbXBsZVxuXHQgKiBjb250cm9sbGVyLnNob3coKTtcblx0ICogY29udHJvbGxlci5zaG93KCBmYWxzZSApOyAvLyBoaWRlXG5cdCAqIGNvbnRyb2xsZXIuc2hvdyggY29udHJvbGxlci5faGlkZGVuICk7IC8vIHRvZ2dsZVxuXHQgKi9cblx0c2hvdyggc2hvdyA9IHRydWUgKSB7XG5cblx0XHR0aGlzLl9oaWRkZW4gPSAhc2hvdztcblxuXHRcdHRoaXMuZG9tRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gdGhpcy5faGlkZGVuID8gJ25vbmUnIDogJyc7XG5cblx0XHRyZXR1cm4gdGhpcztcblxuXHR9XG5cblx0LyoqXG5cdCAqIEhpZGVzIHRoZSBDb250cm9sbGVyLlxuXHQgKiBAcmV0dXJucyB7dGhpc31cblx0ICovXG5cdGhpZGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuc2hvdyggZmFsc2UgKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGFuZ2VzIHRoaXMgY29udHJvbGxlciBpbnRvIGEgZHJvcGRvd24gb2Ygb3B0aW9ucy5cblx0ICpcblx0ICogQ2FsbGluZyB0aGlzIG1ldGhvZCBvbiBhbiBvcHRpb24gY29udHJvbGxlciB3aWxsIHNpbXBseSB1cGRhdGUgdGhlIG9wdGlvbnMuIEhvd2V2ZXIsIGlmIHRoaXNcblx0ICogY29udHJvbGxlciB3YXMgbm90IGFscmVhZHkgYW4gb3B0aW9uIGNvbnRyb2xsZXIsIG9sZCByZWZlcmVuY2VzIHRvIHRoaXMgY29udHJvbGxlciBhcmVcblx0ICogZGVzdHJveWVkLCBhbmQgYSBuZXcgY29udHJvbGxlciBpcyBhZGRlZCB0byB0aGUgZW5kIG9mIHRoZSBHVUkuXG5cdCAqIEBleGFtcGxlXG5cdCAqIC8vIHNhZmUgdXNhZ2Vcblx0ICpcblx0ICogZ3VpLmFkZCggb2JqLCAncHJvcDEnICkub3B0aW9ucyggWyAnYScsICdiJywgJ2MnIF0gKTtcblx0ICogZ3VpLmFkZCggb2JqLCAncHJvcDInICkub3B0aW9ucyggeyBCaWc6IDEwLCBTbWFsbDogMSB9ICk7XG5cdCAqIGd1aS5hZGQoIG9iaiwgJ3Byb3AzJyApO1xuXHQgKlxuXHQgKiAvLyBkYW5nZXJcblx0ICpcblx0ICogY29uc3QgY3RybDEgPSBndWkuYWRkKCBvYmosICdwcm9wMScgKTtcblx0ICogZ3VpLmFkZCggb2JqLCAncHJvcDInICk7XG5cdCAqXG5cdCAqIC8vIGNhbGxpbmcgb3B0aW9ucyBvdXQgb2Ygb3JkZXIgYWRkcyBhIG5ldyBjb250cm9sbGVyIHRvIHRoZSBlbmQuLi5cblx0ICogY29uc3QgY3RybDIgPSBjdHJsMS5vcHRpb25zKCBbICdhJywgJ2InLCAnYycgXSApO1xuXHQgKlxuXHQgKiAvLyAuLi5hbmQgY3RybDEgbm93IHJlZmVyZW5jZXMgYSBjb250cm9sbGVyIHRoYXQgZG9lc24ndCBleGlzdFxuXHQgKiBhc3NlcnQoIGN0cmwyICE9PSBjdHJsMSApXG5cdCAqIEBwYXJhbSB7b2JqZWN0fEFycmF5fSBvcHRpb25zXG5cdCAqIEByZXR1cm5zIHtDb250cm9sbGVyfVxuXHQgKi9cblx0b3B0aW9ucyggb3B0aW9ucyApIHtcblx0XHRjb25zdCBjb250cm9sbGVyID0gdGhpcy5wYXJlbnQuYWRkKCB0aGlzLm9iamVjdCwgdGhpcy5wcm9wZXJ0eSwgb3B0aW9ucyApO1xuXHRcdGNvbnRyb2xsZXIubmFtZSggdGhpcy5fbmFtZSApO1xuXHRcdHRoaXMuZGVzdHJveSgpO1xuXHRcdHJldHVybiBjb250cm9sbGVyO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIG1pbmltdW0gdmFsdWUuIE9ubHkgd29ya3Mgb24gbnVtYmVyIGNvbnRyb2xsZXJzLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gbWluXG5cdCAqIEByZXR1cm5zIHt0aGlzfVxuXHQgKi9cblx0bWluKCBtaW4gKSB7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgbWF4aW11bSB2YWx1ZS4gT25seSB3b3JrcyBvbiBudW1iZXIgY29udHJvbGxlcnMuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBtYXhcblx0ICogQHJldHVybnMge3RoaXN9XG5cdCAqL1xuXHRtYXgoIG1heCApIHtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBWYWx1ZXMgc2V0IGJ5IHRoaXMgY29udHJvbGxlciB3aWxsIGJlIHJvdW5kZWQgdG8gbXVsdGlwbGVzIG9mIGBzdGVwYC4gT25seSB3b3JrcyBvbiBudW1iZXJcblx0ICogY29udHJvbGxlcnMuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBzdGVwXG5cdCAqIEByZXR1cm5zIHt0aGlzfVxuXHQgKi9cblx0c3RlcCggc3RlcCApIHtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBSb3VuZHMgdGhlIGRpc3BsYXllZCB2YWx1ZSB0byBhIGZpeGVkIG51bWJlciBvZiBkZWNpbWFscywgd2l0aG91dCBhZmZlY3RpbmcgdGhlIGFjdHVhbCB2YWx1ZVxuXHQgKiBsaWtlIGBzdGVwKClgLiBPbmx5IHdvcmtzIG9uIG51bWJlciBjb250cm9sbGVycy5cblx0ICogQGV4YW1wbGVcblx0ICogZ3VpLmFkZCggb2JqZWN0LCAncHJvcGVydHknICkubGlzdGVuKCkuZGVjaW1hbHMoIDQgKTtcblx0ICogQHBhcmFtIHtudW1iZXJ9IGRlY2ltYWxzXG5cdCAqIEByZXR1cm5zIHt0aGlzfVxuXHQgKi9cblx0ZGVjaW1hbHMoIGRlY2ltYWxzICkge1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbGxzIGB1cGRhdGVEaXNwbGF5KClgIGV2ZXJ5IGFuaW1hdGlvbiBmcmFtZS4gUGFzcyBgZmFsc2VgIHRvIHN0b3AgbGlzdGVuaW5nLlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IGxpc3RlblxuXHQgKiBAcmV0dXJucyB7dGhpc31cblx0ICovXG5cdGxpc3RlbiggbGlzdGVuID0gdHJ1ZSApIHtcblxuXHRcdC8qKlxuXHRcdCAqIFVzZWQgdG8gZGV0ZXJtaW5lIGlmIHRoZSBjb250cm9sbGVyIGlzIGN1cnJlbnRseSBsaXN0ZW5pbmcuIERvbid0IG1vZGlmeSB0aGlzIHZhbHVlXG5cdFx0ICogZGlyZWN0bHkuIFVzZSB0aGUgYGNvbnRyb2xsZXIubGlzdGVuKCB0cnVlfGZhbHNlIClgIG1ldGhvZCBpbnN0ZWFkLlxuXHRcdCAqIEB0eXBlIHtib29sZWFufVxuXHRcdCAqL1xuXHRcdHRoaXMuX2xpc3RlbmluZyA9IGxpc3RlbjtcblxuXHRcdGlmICggdGhpcy5fbGlzdGVuQ2FsbGJhY2tJRCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0Y2FuY2VsQW5pbWF0aW9uRnJhbWUoIHRoaXMuX2xpc3RlbkNhbGxiYWNrSUQgKTtcblx0XHRcdHRoaXMuX2xpc3RlbkNhbGxiYWNrSUQgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLl9saXN0ZW5pbmcgKSB7XG5cdFx0XHR0aGlzLl9saXN0ZW5DYWxsYmFjaygpO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXG5cdH1cblxuXHRfbGlzdGVuQ2FsbGJhY2soKSB7XG5cblx0XHR0aGlzLl9saXN0ZW5DYWxsYmFja0lEID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCB0aGlzLl9saXN0ZW5DYWxsYmFjayApO1xuXG5cdFx0Ly8gVG8gcHJldmVudCBmcmFtZXJhdGUgbG9zcywgbWFrZSBzdXJlIHRoZSB2YWx1ZSBoYXMgY2hhbmdlZCBiZWZvcmUgdXBkYXRpbmcgdGhlIGRpc3BsYXkuXG5cdFx0Ly8gTm90ZTogc2F2ZSgpIGlzIHVzZWQgaGVyZSBpbnN0ZWFkIG9mIGdldFZhbHVlKCkgb25seSBiZWNhdXNlIG9mIENvbG9yQ29udHJvbGxlci4gVGhlICE9PSBvcGVyYXRvclxuXHRcdC8vIHdvbid0IHdvcmsgZm9yIGNvbG9yIG9iamVjdHMgb3IgYXJyYXlzLCBidXQgQ29sb3JDb250cm9sbGVyLnNhdmUoKSBhbHdheXMgcmV0dXJucyBhIHN0cmluZy5cblxuXHRcdGNvbnN0IGN1clZhbHVlID0gdGhpcy5zYXZlKCk7XG5cblx0XHRpZiAoIGN1clZhbHVlICE9PSB0aGlzLl9saXN0ZW5QcmV2VmFsdWUgKSB7XG5cdFx0XHR0aGlzLnVwZGF0ZURpc3BsYXkoKTtcblx0XHR9XG5cblx0XHR0aGlzLl9saXN0ZW5QcmV2VmFsdWUgPSBjdXJWYWx1ZTtcblxuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYG9iamVjdFsgcHJvcGVydHkgXWAuXG5cdCAqIEByZXR1cm5zIHthbnl9XG5cdCAqL1xuXHRnZXRWYWx1ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5vYmplY3RbIHRoaXMucHJvcGVydHkgXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB2YWx1ZSBvZiBgb2JqZWN0WyBwcm9wZXJ0eSBdYCwgaW52b2tlcyBhbnkgYG9uQ2hhbmdlYCBoYW5kbGVycyBhbmQgdXBkYXRlcyB0aGUgZGlzcGxheS5cblx0ICogQHBhcmFtIHthbnl9IHZhbHVlXG5cdCAqIEByZXR1cm5zIHt0aGlzfVxuXHQgKi9cblx0c2V0VmFsdWUoIHZhbHVlICkge1xuXG5cdFx0aWYgKCB0aGlzLmdldFZhbHVlKCkgIT09IHZhbHVlICkge1xuXG5cdFx0XHR0aGlzLm9iamVjdFsgdGhpcy5wcm9wZXJ0eSBdID0gdmFsdWU7XG5cdFx0XHR0aGlzLl9jYWxsT25DaGFuZ2UoKTtcblx0XHRcdHRoaXMudXBkYXRlRGlzcGxheSgpO1xuXG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXM7XG5cblx0fVxuXG5cdC8qKlxuXHQgKiBVcGRhdGVzIHRoZSBkaXNwbGF5IHRvIGtlZXAgaXQgaW4gc3luYyB3aXRoIHRoZSBjdXJyZW50IHZhbHVlLiBVc2VmdWwgZm9yIHVwZGF0aW5nIHlvdXJcblx0ICogY29udHJvbGxlcnMgd2hlbiB0aGVpciB2YWx1ZXMgaGF2ZSBiZWVuIG1vZGlmaWVkIG91dHNpZGUgb2YgdGhlIEdVSS5cblx0ICogQHJldHVybnMge3RoaXN9XG5cdCAqL1xuXHR1cGRhdGVEaXNwbGF5KCkge1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0bG9hZCggdmFsdWUgKSB7XG5cdFx0dGhpcy5zZXRWYWx1ZSggdmFsdWUgKTtcblx0XHR0aGlzLl9jYWxsT25GaW5pc2hDaGFuZ2UoKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdHNhdmUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0VmFsdWUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEZXN0cm95cyB0aGlzIGNvbnRyb2xsZXIgYW5kIHJlbW92ZXMgaXQgZnJvbSB0aGUgcGFyZW50IEdVSS5cblx0ICovXG5cdGRlc3Ryb3koKSB7XG5cdFx0dGhpcy5saXN0ZW4oIGZhbHNlICk7XG5cdFx0dGhpcy5wYXJlbnQuY2hpbGRyZW4uc3BsaWNlKCB0aGlzLnBhcmVudC5jaGlsZHJlbi5pbmRleE9mKCB0aGlzICksIDEgKTtcblx0XHR0aGlzLnBhcmVudC5jb250cm9sbGVycy5zcGxpY2UoIHRoaXMucGFyZW50LmNvbnRyb2xsZXJzLmluZGV4T2YoIHRoaXMgKSwgMSApO1xuXHRcdHRoaXMucGFyZW50LiRjaGlsZHJlbi5yZW1vdmVDaGlsZCggdGhpcy5kb21FbGVtZW50ICk7XG5cdH1cblxufVxuXG5jbGFzcyBCb29sZWFuQ29udHJvbGxlciBleHRlbmRzIENvbnRyb2xsZXIge1xuXG5cdGNvbnN0cnVjdG9yKCBwYXJlbnQsIG9iamVjdCwgcHJvcGVydHkgKSB7XG5cblx0XHRzdXBlciggcGFyZW50LCBvYmplY3QsIHByb3BlcnR5LCAnYm9vbGVhbicsICdsYWJlbCcgKTtcblxuXHRcdHRoaXMuJGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2lucHV0JyApO1xuXHRcdHRoaXMuJGlucHV0LnNldEF0dHJpYnV0ZSggJ3R5cGUnLCAnY2hlY2tib3gnICk7XG5cdFx0dGhpcy4kaW5wdXQuc2V0QXR0cmlidXRlKCAnYXJpYS1sYWJlbGxlZGJ5JywgdGhpcy4kbmFtZS5pZCApO1xuXG5cdFx0dGhpcy4kd2lkZ2V0LmFwcGVuZENoaWxkKCB0aGlzLiRpbnB1dCApO1xuXG5cdFx0dGhpcy4kaW5wdXQuYWRkRXZlbnRMaXN0ZW5lciggJ2NoYW5nZScsICgpID0+IHtcblx0XHRcdHRoaXMuc2V0VmFsdWUoIHRoaXMuJGlucHV0LmNoZWNrZWQgKTtcblx0XHRcdHRoaXMuX2NhbGxPbkZpbmlzaENoYW5nZSgpO1xuXHRcdH0gKTtcblxuXHRcdHRoaXMuJGRpc2FibGUgPSB0aGlzLiRpbnB1dDtcblxuXHRcdHRoaXMudXBkYXRlRGlzcGxheSgpO1xuXG5cdH1cblxuXHR1cGRhdGVEaXNwbGF5KCkge1xuXHRcdHRoaXMuJGlucHV0LmNoZWNrZWQgPSB0aGlzLmdldFZhbHVlKCk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxufVxuXG5mdW5jdGlvbiBub3JtYWxpemVDb2xvclN0cmluZyggc3RyaW5nICkge1xuXG5cdGxldCBtYXRjaCwgcmVzdWx0O1xuXG5cdGlmICggbWF0Y2ggPSBzdHJpbmcubWF0Y2goIC8oI3wweCk/KFthLWYwLTldezZ9KS9pICkgKSB7XG5cblx0XHRyZXN1bHQgPSBtYXRjaFsgMiBdO1xuXG5cdH0gZWxzZSBpZiAoIG1hdGNoID0gc3RyaW5nLm1hdGNoKCAvcmdiXFwoXFxzKihcXGQqKVxccyosXFxzKihcXGQqKVxccyosXFxzKihcXGQqKVxccypcXCkvICkgKSB7XG5cblx0XHRyZXN1bHQgPSBwYXJzZUludCggbWF0Y2hbIDEgXSApLnRvU3RyaW5nKCAxNiApLnBhZFN0YXJ0KCAyLCAwIClcblx0XHRcdCsgcGFyc2VJbnQoIG1hdGNoWyAyIF0gKS50b1N0cmluZyggMTYgKS5wYWRTdGFydCggMiwgMCApXG5cdFx0XHQrIHBhcnNlSW50KCBtYXRjaFsgMyBdICkudG9TdHJpbmcoIDE2ICkucGFkU3RhcnQoIDIsIDAgKTtcblxuXHR9IGVsc2UgaWYgKCBtYXRjaCA9IHN0cmluZy5tYXRjaCggL14jPyhbYS1mMC05XSkoW2EtZjAtOV0pKFthLWYwLTldKSQvaSApICkge1xuXG5cdFx0cmVzdWx0ID0gbWF0Y2hbIDEgXSArIG1hdGNoWyAxIF0gKyBtYXRjaFsgMiBdICsgbWF0Y2hbIDIgXSArIG1hdGNoWyAzIF0gKyBtYXRjaFsgMyBdO1xuXG5cdH1cblxuXHRpZiAoIHJlc3VsdCApIHtcblx0XHRyZXR1cm4gJyMnICsgcmVzdWx0O1xuXHR9XG5cblx0cmV0dXJuIGZhbHNlO1xuXG59XG5cbmNvbnN0IFNUUklORyA9IHtcblx0aXNQcmltaXRpdmU6IHRydWUsXG5cdG1hdGNoOiB2ID0+IHR5cGVvZiB2ID09PSAnc3RyaW5nJyxcblx0ZnJvbUhleFN0cmluZzogbm9ybWFsaXplQ29sb3JTdHJpbmcsXG5cdHRvSGV4U3RyaW5nOiBub3JtYWxpemVDb2xvclN0cmluZ1xufTtcblxuY29uc3QgSU5UID0ge1xuXHRpc1ByaW1pdGl2ZTogdHJ1ZSxcblx0bWF0Y2g6IHYgPT4gdHlwZW9mIHYgPT09ICdudW1iZXInLFxuXHRmcm9tSGV4U3RyaW5nOiBzdHJpbmcgPT4gcGFyc2VJbnQoIHN0cmluZy5zdWJzdHJpbmcoIDEgKSwgMTYgKSxcblx0dG9IZXhTdHJpbmc6IHZhbHVlID0+ICcjJyArIHZhbHVlLnRvU3RyaW5nKCAxNiApLnBhZFN0YXJ0KCA2LCAwIClcbn07XG5cbmNvbnN0IEFSUkFZID0ge1xuXHRpc1ByaW1pdGl2ZTogZmFsc2UsXG5cblx0Ly8gVGhlIGFycm93IGZ1bmN0aW9uIGlzIGhlcmUgdG8gYXBwZWFzZSB0cmVlIHNoYWtlcnMgbGlrZSBlc2J1aWxkIG9yIHdlYnBhY2suXG5cdC8vIFNlZSBodHRwczovL2VzYnVpbGQuZ2l0aHViLmlvL2FwaS8jdHJlZS1zaGFraW5nXG5cdG1hdGNoOiB2ID0+IEFycmF5LmlzQXJyYXkoIHYgKSxcblxuXHRmcm9tSGV4U3RyaW5nKCBzdHJpbmcsIHRhcmdldCwgcmdiU2NhbGUgPSAxICkge1xuXG5cdFx0Y29uc3QgaW50ID0gSU5ULmZyb21IZXhTdHJpbmcoIHN0cmluZyApO1xuXG5cdFx0dGFyZ2V0WyAwIF0gPSAoIGludCA+PiAxNiAmIDI1NSApIC8gMjU1ICogcmdiU2NhbGU7XG5cdFx0dGFyZ2V0WyAxIF0gPSAoIGludCA+PiA4ICYgMjU1ICkgLyAyNTUgKiByZ2JTY2FsZTtcblx0XHR0YXJnZXRbIDIgXSA9ICggaW50ICYgMjU1ICkgLyAyNTUgKiByZ2JTY2FsZTtcblxuXHR9LFxuXHR0b0hleFN0cmluZyggWyByLCBnLCBiIF0sIHJnYlNjYWxlID0gMSApIHtcblxuXHRcdHJnYlNjYWxlID0gMjU1IC8gcmdiU2NhbGU7XG5cblx0XHRjb25zdCBpbnQgPSAoIHIgKiByZ2JTY2FsZSApIDw8IDE2IF5cblx0XHRcdCggZyAqIHJnYlNjYWxlICkgPDwgOCBeXG5cdFx0XHQoIGIgKiByZ2JTY2FsZSApIDw8IDA7XG5cblx0XHRyZXR1cm4gSU5ULnRvSGV4U3RyaW5nKCBpbnQgKTtcblxuXHR9XG59O1xuXG5jb25zdCBPQkpFQ1QgPSB7XG5cdGlzUHJpbWl0aXZlOiBmYWxzZSxcblx0bWF0Y2g6IHYgPT4gT2JqZWN0KCB2ICkgPT09IHYsXG5cdGZyb21IZXhTdHJpbmcoIHN0cmluZywgdGFyZ2V0LCByZ2JTY2FsZSA9IDEgKSB7XG5cblx0XHRjb25zdCBpbnQgPSBJTlQuZnJvbUhleFN0cmluZyggc3RyaW5nICk7XG5cblx0XHR0YXJnZXQuciA9ICggaW50ID4+IDE2ICYgMjU1ICkgLyAyNTUgKiByZ2JTY2FsZTtcblx0XHR0YXJnZXQuZyA9ICggaW50ID4+IDggJiAyNTUgKSAvIDI1NSAqIHJnYlNjYWxlO1xuXHRcdHRhcmdldC5iID0gKCBpbnQgJiAyNTUgKSAvIDI1NSAqIHJnYlNjYWxlO1xuXG5cdH0sXG5cdHRvSGV4U3RyaW5nKCB7IHIsIGcsIGIgfSwgcmdiU2NhbGUgPSAxICkge1xuXG5cdFx0cmdiU2NhbGUgPSAyNTUgLyByZ2JTY2FsZTtcblxuXHRcdGNvbnN0IGludCA9ICggciAqIHJnYlNjYWxlICkgPDwgMTYgXlxuXHRcdFx0KCBnICogcmdiU2NhbGUgKSA8PCA4IF5cblx0XHRcdCggYiAqIHJnYlNjYWxlICkgPDwgMDtcblxuXHRcdHJldHVybiBJTlQudG9IZXhTdHJpbmcoIGludCApO1xuXG5cdH1cbn07XG5cbmNvbnN0IEZPUk1BVFMgPSBbIFNUUklORywgSU5ULCBBUlJBWSwgT0JKRUNUIF07XG5cbmZ1bmN0aW9uIGdldENvbG9yRm9ybWF0KCB2YWx1ZSApIHtcblx0cmV0dXJuIEZPUk1BVFMuZmluZCggZm9ybWF0ID0+IGZvcm1hdC5tYXRjaCggdmFsdWUgKSApO1xufVxuXG5jbGFzcyBDb2xvckNvbnRyb2xsZXIgZXh0ZW5kcyBDb250cm9sbGVyIHtcblxuXHRjb25zdHJ1Y3RvciggcGFyZW50LCBvYmplY3QsIHByb3BlcnR5LCByZ2JTY2FsZSApIHtcblxuXHRcdHN1cGVyKCBwYXJlbnQsIG9iamVjdCwgcHJvcGVydHksICdjb2xvcicgKTtcblxuXHRcdHRoaXMuJGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2lucHV0JyApO1xuXHRcdHRoaXMuJGlucHV0LnNldEF0dHJpYnV0ZSggJ3R5cGUnLCAnY29sb3InICk7XG5cdFx0dGhpcy4kaW5wdXQuc2V0QXR0cmlidXRlKCAndGFiaW5kZXgnLCAtMSApO1xuXHRcdHRoaXMuJGlucHV0LnNldEF0dHJpYnV0ZSggJ2FyaWEtbGFiZWxsZWRieScsIHRoaXMuJG5hbWUuaWQgKTtcblxuXHRcdHRoaXMuJHRleHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCAnaW5wdXQnICk7XG5cdFx0dGhpcy4kdGV4dC5zZXRBdHRyaWJ1dGUoICd0eXBlJywgJ3RleHQnICk7XG5cdFx0dGhpcy4kdGV4dC5zZXRBdHRyaWJ1dGUoICdzcGVsbGNoZWNrJywgJ2ZhbHNlJyApO1xuXHRcdHRoaXMuJHRleHQuc2V0QXR0cmlidXRlKCAnYXJpYS1sYWJlbGxlZGJ5JywgdGhpcy4kbmFtZS5pZCApO1xuXG5cdFx0dGhpcy4kZGlzcGxheSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoICdkaXYnICk7XG5cdFx0dGhpcy4kZGlzcGxheS5jbGFzc0xpc3QuYWRkKCAnZGlzcGxheScgKTtcblxuXHRcdHRoaXMuJGRpc3BsYXkuYXBwZW5kQ2hpbGQoIHRoaXMuJGlucHV0ICk7XG5cdFx0dGhpcy4kd2lkZ2V0LmFwcGVuZENoaWxkKCB0aGlzLiRkaXNwbGF5ICk7XG5cdFx0dGhpcy4kd2lkZ2V0LmFwcGVuZENoaWxkKCB0aGlzLiR0ZXh0ICk7XG5cblx0XHR0aGlzLl9mb3JtYXQgPSBnZXRDb2xvckZvcm1hdCggdGhpcy5pbml0aWFsVmFsdWUgKTtcblx0XHR0aGlzLl9yZ2JTY2FsZSA9IHJnYlNjYWxlO1xuXG5cdFx0dGhpcy5faW5pdGlhbFZhbHVlSGV4U3RyaW5nID0gdGhpcy5zYXZlKCk7XG5cdFx0dGhpcy5fdGV4dEZvY3VzZWQgPSBmYWxzZTtcblxuXHRcdHRoaXMuJGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoICdpbnB1dCcsICgpID0+IHtcblx0XHRcdHRoaXMuX3NldFZhbHVlRnJvbUhleFN0cmluZyggdGhpcy4kaW5wdXQudmFsdWUgKTtcblx0XHR9ICk7XG5cblx0XHR0aGlzLiRpbnB1dC5hZGRFdmVudExpc3RlbmVyKCAnYmx1cicsICgpID0+IHtcblx0XHRcdHRoaXMuX2NhbGxPbkZpbmlzaENoYW5nZSgpO1xuXHRcdH0gKTtcblxuXHRcdHRoaXMuJHRleHQuYWRkRXZlbnRMaXN0ZW5lciggJ2lucHV0JywgKCkgPT4ge1xuXHRcdFx0Y29uc3QgdHJ5UGFyc2UgPSBub3JtYWxpemVDb2xvclN0cmluZyggdGhpcy4kdGV4dC52YWx1ZSApO1xuXHRcdFx0aWYgKCB0cnlQYXJzZSApIHtcblx0XHRcdFx0dGhpcy5fc2V0VmFsdWVGcm9tSGV4U3RyaW5nKCB0cnlQYXJzZSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblxuXHRcdHRoaXMuJHRleHQuYWRkRXZlbnRMaXN0ZW5lciggJ2ZvY3VzJywgKCkgPT4ge1xuXHRcdFx0dGhpcy5fdGV4dEZvY3VzZWQgPSB0cnVlO1xuXHRcdFx0dGhpcy4kdGV4dC5zZWxlY3QoKTtcblx0XHR9ICk7XG5cblx0XHR0aGlzLiR0ZXh0LmFkZEV2ZW50TGlzdGVuZXIoICdibHVyJywgKCkgPT4ge1xuXHRcdFx0dGhpcy5fdGV4dEZvY3VzZWQgPSBmYWxzZTtcblx0XHRcdHRoaXMudXBkYXRlRGlzcGxheSgpO1xuXHRcdFx0dGhpcy5fY2FsbE9uRmluaXNoQ2hhbmdlKCk7XG5cdFx0fSApO1xuXG5cdFx0dGhpcy4kZGlzYWJsZSA9IHRoaXMuJHRleHQ7XG5cblx0XHR0aGlzLnVwZGF0ZURpc3BsYXkoKTtcblxuXHR9XG5cblx0cmVzZXQoKSB7XG5cdFx0dGhpcy5fc2V0VmFsdWVGcm9tSGV4U3RyaW5nKCB0aGlzLl9pbml0aWFsVmFsdWVIZXhTdHJpbmcgKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdF9zZXRWYWx1ZUZyb21IZXhTdHJpbmcoIHZhbHVlICkge1xuXG5cdFx0aWYgKCB0aGlzLl9mb3JtYXQuaXNQcmltaXRpdmUgKSB7XG5cblx0XHRcdGNvbnN0IG5ld1ZhbHVlID0gdGhpcy5fZm9ybWF0LmZyb21IZXhTdHJpbmcoIHZhbHVlICk7XG5cdFx0XHR0aGlzLnNldFZhbHVlKCBuZXdWYWx1ZSApO1xuXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0dGhpcy5fZm9ybWF0LmZyb21IZXhTdHJpbmcoIHZhbHVlLCB0aGlzLmdldFZhbHVlKCksIHRoaXMuX3JnYlNjYWxlICk7XG5cdFx0XHR0aGlzLl9jYWxsT25DaGFuZ2UoKTtcblx0XHRcdHRoaXMudXBkYXRlRGlzcGxheSgpO1xuXG5cdFx0fVxuXG5cdH1cblxuXHRzYXZlKCkge1xuXHRcdHJldHVybiB0aGlzLl9mb3JtYXQudG9IZXhTdHJpbmcoIHRoaXMuZ2V0VmFsdWUoKSwgdGhpcy5fcmdiU2NhbGUgKTtcblx0fVxuXG5cdGxvYWQoIHZhbHVlICkge1xuXHRcdHRoaXMuX3NldFZhbHVlRnJvbUhleFN0cmluZyggdmFsdWUgKTtcblx0XHR0aGlzLl9jYWxsT25GaW5pc2hDaGFuZ2UoKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdHVwZGF0ZURpc3BsYXkoKSB7XG5cdFx0dGhpcy4kaW5wdXQudmFsdWUgPSB0aGlzLl9mb3JtYXQudG9IZXhTdHJpbmcoIHRoaXMuZ2V0VmFsdWUoKSwgdGhpcy5fcmdiU2NhbGUgKTtcblx0XHRpZiAoICF0aGlzLl90ZXh0Rm9jdXNlZCApIHtcblx0XHRcdHRoaXMuJHRleHQudmFsdWUgPSB0aGlzLiRpbnB1dC52YWx1ZS5zdWJzdHJpbmcoIDEgKTtcblx0XHR9XG5cdFx0dGhpcy4kZGlzcGxheS5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLiRpbnB1dC52YWx1ZTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG59XG5cbmNsYXNzIEZ1bmN0aW9uQ29udHJvbGxlciBleHRlbmRzIENvbnRyb2xsZXIge1xuXG5cdGNvbnN0cnVjdG9yKCBwYXJlbnQsIG9iamVjdCwgcHJvcGVydHkgKSB7XG5cblx0XHRzdXBlciggcGFyZW50LCBvYmplY3QsIHByb3BlcnR5LCAnZnVuY3Rpb24nICk7XG5cblx0XHQvLyBCdXR0b25zIGFyZSB0aGUgb25seSBjYXNlIHdoZXJlIHdpZGdldCBjb250YWlucyBuYW1lXG5cdFx0dGhpcy4kYnV0dG9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2J1dHRvbicgKTtcblx0XHR0aGlzLiRidXR0b24uYXBwZW5kQ2hpbGQoIHRoaXMuJG5hbWUgKTtcblx0XHR0aGlzLiR3aWRnZXQuYXBwZW5kQ2hpbGQoIHRoaXMuJGJ1dHRvbiApO1xuXG5cdFx0dGhpcy4kYnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoICdjbGljaycsIGUgPT4ge1xuXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0dGhpcy5nZXRWYWx1ZSgpLmNhbGwoIHRoaXMub2JqZWN0ICk7XG5cdFx0XHR0aGlzLl9jYWxsT25DaGFuZ2UoKTtcblx0XHR9ICk7XG5cblx0XHQvLyBlbmFibGVzIDphY3RpdmUgcHNldWRvIGNsYXNzIG9uIG1vYmlsZVxuXHRcdHRoaXMuJGJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKCAndG91Y2hzdGFydCcsICgpID0+IHt9LCB7IHBhc3NpdmU6IHRydWUgfSApO1xuXG5cdFx0dGhpcy4kZGlzYWJsZSA9IHRoaXMuJGJ1dHRvbjtcblxuXHR9XG5cbn1cblxuY2xhc3MgTnVtYmVyQ29udHJvbGxlciBleHRlbmRzIENvbnRyb2xsZXIge1xuXG5cdGNvbnN0cnVjdG9yKCBwYXJlbnQsIG9iamVjdCwgcHJvcGVydHksIG1pbiwgbWF4LCBzdGVwICkge1xuXG5cdFx0c3VwZXIoIHBhcmVudCwgb2JqZWN0LCBwcm9wZXJ0eSwgJ251bWJlcicgKTtcblxuXHRcdHRoaXMuX2luaXRJbnB1dCgpO1xuXG5cdFx0dGhpcy5taW4oIG1pbiApO1xuXHRcdHRoaXMubWF4KCBtYXggKTtcblxuXHRcdGNvbnN0IHN0ZXBFeHBsaWNpdCA9IHN0ZXAgIT09IHVuZGVmaW5lZDtcblx0XHR0aGlzLnN0ZXAoIHN0ZXBFeHBsaWNpdCA/IHN0ZXAgOiB0aGlzLl9nZXRJbXBsaWNpdFN0ZXAoKSwgc3RlcEV4cGxpY2l0ICk7XG5cblx0XHR0aGlzLnVwZGF0ZURpc3BsYXkoKTtcblxuXHR9XG5cblx0ZGVjaW1hbHMoIGRlY2ltYWxzICkge1xuXHRcdHRoaXMuX2RlY2ltYWxzID0gZGVjaW1hbHM7XG5cdFx0dGhpcy51cGRhdGVEaXNwbGF5KCk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRtaW4oIG1pbiApIHtcblx0XHR0aGlzLl9taW4gPSBtaW47XG5cdFx0dGhpcy5fb25VcGRhdGVNaW5NYXgoKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdG1heCggbWF4ICkge1xuXHRcdHRoaXMuX21heCA9IG1heDtcblx0XHR0aGlzLl9vblVwZGF0ZU1pbk1heCgpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0c3RlcCggc3RlcCwgZXhwbGljaXQgPSB0cnVlICkge1xuXHRcdHRoaXMuX3N0ZXAgPSBzdGVwO1xuXHRcdHRoaXMuX3N0ZXBFeHBsaWNpdCA9IGV4cGxpY2l0O1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0dXBkYXRlRGlzcGxheSgpIHtcblxuXHRcdGNvbnN0IHZhbHVlID0gdGhpcy5nZXRWYWx1ZSgpO1xuXG5cdFx0aWYgKCB0aGlzLl9oYXNTbGlkZXIgKSB7XG5cblx0XHRcdGxldCBwZXJjZW50ID0gKCB2YWx1ZSAtIHRoaXMuX21pbiApIC8gKCB0aGlzLl9tYXggLSB0aGlzLl9taW4gKTtcblx0XHRcdHBlcmNlbnQgPSBNYXRoLm1heCggMCwgTWF0aC5taW4oIHBlcmNlbnQsIDEgKSApO1xuXG5cdFx0XHR0aGlzLiRmaWxsLnN0eWxlLndpZHRoID0gcGVyY2VudCAqIDEwMCArICclJztcblxuXHRcdH1cblxuXHRcdGlmICggIXRoaXMuX2lucHV0Rm9jdXNlZCApIHtcblx0XHRcdHRoaXMuJGlucHV0LnZhbHVlID0gdGhpcy5fZGVjaW1hbHMgPT09IHVuZGVmaW5lZCA/IHZhbHVlIDogdmFsdWUudG9GaXhlZCggdGhpcy5fZGVjaW1hbHMgKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblxuXHR9XG5cblx0X2luaXRJbnB1dCgpIHtcblxuXHRcdHRoaXMuJGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2lucHV0JyApO1xuXHRcdHRoaXMuJGlucHV0LnNldEF0dHJpYnV0ZSggJ3R5cGUnLCAndGV4dCcgKTtcblx0XHR0aGlzLiRpbnB1dC5zZXRBdHRyaWJ1dGUoICdhcmlhLWxhYmVsbGVkYnknLCB0aGlzLiRuYW1lLmlkICk7XG5cblx0XHQvLyBPbiB0b3VjaCBkZXZpY2VzIG9ubHksIHVzZSBpbnB1dFt0eXBlPW51bWJlcl0gdG8gZm9yY2UgYSBudW1lcmljIGtleWJvYXJkLlxuXHRcdC8vIElkZWFsbHkgd2UgY291bGQgdXNlIG9uZSBpbnB1dCB0eXBlIGV2ZXJ5d2hlcmUsIGJ1dCBbdHlwZT1udW1iZXJdIGhhcyBxdWlya3Ncblx0XHQvLyBvbiBkZXNrdG9wLCBhbmQgW2lucHV0bW9kZT1kZWNpbWFsXSBoYXMgcXVpcmtzIG9uIGlPUy5cblx0XHQvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2dlb3JnZWFsd2F5cy9saWwtZ3VpL3B1bGwvMTZcblxuXHRcdGNvbnN0IGlzVG91Y2ggPSB3aW5kb3cubWF0Y2hNZWRpYSggJyhwb2ludGVyOiBjb2Fyc2UpJyApLm1hdGNoZXM7XG5cblx0XHRpZiAoIGlzVG91Y2ggKSB7XG5cdFx0XHR0aGlzLiRpbnB1dC5zZXRBdHRyaWJ1dGUoICd0eXBlJywgJ251bWJlcicgKTtcblx0XHRcdHRoaXMuJGlucHV0LnNldEF0dHJpYnV0ZSggJ3N0ZXAnLCAnYW55JyApO1xuXHRcdH1cblxuXHRcdHRoaXMuJHdpZGdldC5hcHBlbmRDaGlsZCggdGhpcy4kaW5wdXQgKTtcblxuXHRcdHRoaXMuJGRpc2FibGUgPSB0aGlzLiRpbnB1dDtcblxuXHRcdGNvbnN0IG9uSW5wdXQgPSAoKSA9PiB7XG5cblx0XHRcdGxldCB2YWx1ZSA9IHBhcnNlRmxvYXQoIHRoaXMuJGlucHV0LnZhbHVlICk7XG5cblx0XHRcdGlmICggaXNOYU4oIHZhbHVlICkgKSByZXR1cm47XG5cblx0XHRcdGlmICggdGhpcy5fc3RlcEV4cGxpY2l0ICkge1xuXHRcdFx0XHR2YWx1ZSA9IHRoaXMuX3NuYXAoIHZhbHVlICk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuc2V0VmFsdWUoIHRoaXMuX2NsYW1wKCB2YWx1ZSApICk7XG5cblx0XHR9O1xuXG5cdFx0Ly8gS2V5cyAmIG1vdXNlIHdoZWVsXG5cdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0XHRjb25zdCBpbmNyZW1lbnQgPSBkZWx0YSA9PiB7XG5cblx0XHRcdGNvbnN0IHZhbHVlID0gcGFyc2VGbG9hdCggdGhpcy4kaW5wdXQudmFsdWUgKTtcblxuXHRcdFx0aWYgKCBpc05hTiggdmFsdWUgKSApIHJldHVybjtcblxuXHRcdFx0dGhpcy5fc25hcENsYW1wU2V0VmFsdWUoIHZhbHVlICsgZGVsdGEgKTtcblxuXHRcdFx0Ly8gRm9yY2UgdGhlIGlucHV0IHRvIHVwZGF0ZURpc3BsYXkgd2hlbiBpdCdzIGZvY3VzZWRcblx0XHRcdHRoaXMuJGlucHV0LnZhbHVlID0gdGhpcy5nZXRWYWx1ZSgpO1xuXG5cdFx0fTtcblxuXHRcdGNvbnN0IG9uS2V5RG93biA9IGUgPT4ge1xuXHRcdFx0Ly8gVXNpbmcgYGUua2V5YCBpbnN0ZWFkIG9mIGBlLmNvZGVgIGFsc28gY2F0Y2hlcyBOdW1wYWRFbnRlclxuXHRcdFx0aWYgKCBlLmtleSA9PT0gJ0VudGVyJyApIHtcblx0XHRcdFx0dGhpcy4kaW5wdXQuYmx1cigpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCBlLmNvZGUgPT09ICdBcnJvd1VwJyApIHtcblx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRpbmNyZW1lbnQoIHRoaXMuX3N0ZXAgKiB0aGlzLl9hcnJvd0tleU11bHRpcGxpZXIoIGUgKSApO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCBlLmNvZGUgPT09ICdBcnJvd0Rvd24nICkge1xuXHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdGluY3JlbWVudCggdGhpcy5fc3RlcCAqIHRoaXMuX2Fycm93S2V5TXVsdGlwbGllciggZSApICogLTEgKTtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0Y29uc3Qgb25XaGVlbCA9IGUgPT4ge1xuXHRcdFx0aWYgKCB0aGlzLl9pbnB1dEZvY3VzZWQgKSB7XG5cdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0aW5jcmVtZW50KCB0aGlzLl9zdGVwICogdGhpcy5fbm9ybWFsaXplTW91c2VXaGVlbCggZSApICk7XG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdC8vIFZlcnRpY2FsIGRyYWdcblx0XHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRcdGxldCB0ZXN0aW5nRm9yVmVydGljYWxEcmFnID0gZmFsc2UsXG5cdFx0XHRpbml0Q2xpZW50WCxcblx0XHRcdGluaXRDbGllbnRZLFxuXHRcdFx0cHJldkNsaWVudFksXG5cdFx0XHRpbml0VmFsdWUsXG5cdFx0XHRkcmFnRGVsdGE7XG5cblx0XHQvLyBPbmNlIHRoZSBtb3VzZSBpcyBkcmFnZ2VkIG1vcmUgdGhhbiBEUkFHX1RIUkVTSCBweCBvbiBhbnkgYXhpcywgd2UgZGVjaWRlXG5cdFx0Ly8gb24gdGhlIHVzZXIncyBpbnRlbnQ6IGhvcml6b250YWwgbWVhbnMgaGlnaGxpZ2h0LCB2ZXJ0aWNhbCBtZWFucyBkcmFnLlxuXHRcdGNvbnN0IERSQUdfVEhSRVNIID0gNTtcblxuXHRcdGNvbnN0IG9uTW91c2VEb3duID0gZSA9PiB7XG5cblx0XHRcdGluaXRDbGllbnRYID0gZS5jbGllbnRYO1xuXHRcdFx0aW5pdENsaWVudFkgPSBwcmV2Q2xpZW50WSA9IGUuY2xpZW50WTtcblx0XHRcdHRlc3RpbmdGb3JWZXJ0aWNhbERyYWcgPSB0cnVlO1xuXG5cdFx0XHRpbml0VmFsdWUgPSB0aGlzLmdldFZhbHVlKCk7XG5cdFx0XHRkcmFnRGVsdGEgPSAwO1xuXG5cdFx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lciggJ21vdXNlbW92ZScsIG9uTW91c2VNb3ZlICk7XG5cdFx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lciggJ21vdXNldXAnLCBvbk1vdXNlVXAgKTtcblxuXHRcdH07XG5cblx0XHRjb25zdCBvbk1vdXNlTW92ZSA9IGUgPT4ge1xuXG5cdFx0XHRpZiAoIHRlc3RpbmdGb3JWZXJ0aWNhbERyYWcgKSB7XG5cblx0XHRcdFx0Y29uc3QgZHggPSBlLmNsaWVudFggLSBpbml0Q2xpZW50WDtcblx0XHRcdFx0Y29uc3QgZHkgPSBlLmNsaWVudFkgLSBpbml0Q2xpZW50WTtcblxuXHRcdFx0XHRpZiAoIE1hdGguYWJzKCBkeSApID4gRFJBR19USFJFU0ggKSB7XG5cblx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0dGhpcy4kaW5wdXQuYmx1cigpO1xuXHRcdFx0XHRcdHRlc3RpbmdGb3JWZXJ0aWNhbERyYWcgPSBmYWxzZTtcblx0XHRcdFx0XHR0aGlzLl9zZXREcmFnZ2luZ1N0eWxlKCB0cnVlLCAndmVydGljYWwnICk7XG5cblx0XHRcdFx0fSBlbHNlIGlmICggTWF0aC5hYnMoIGR4ICkgPiBEUkFHX1RIUkVTSCApIHtcblxuXHRcdFx0XHRcdG9uTW91c2VVcCgpO1xuXG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXG5cdFx0XHQvLyBUaGlzIGlzbid0IGFuIGVsc2Ugc28gdGhhdCB0aGUgZmlyc3QgbW92ZSBjb3VudHMgdG93YXJkcyBkcmFnRGVsdGFcblx0XHRcdGlmICggIXRlc3RpbmdGb3JWZXJ0aWNhbERyYWcgKSB7XG5cblx0XHRcdFx0Y29uc3QgZHkgPSBlLmNsaWVudFkgLSBwcmV2Q2xpZW50WTtcblxuXHRcdFx0XHRkcmFnRGVsdGEgLT0gZHkgKiB0aGlzLl9zdGVwICogdGhpcy5fYXJyb3dLZXlNdWx0aXBsaWVyKCBlICk7XG5cblx0XHRcdFx0Ly8gQ2xhbXAgZHJhZ0RlbHRhIHNvIHdlIGRvbid0IGhhdmUgJ2RlYWQgc3BhY2UnIGFmdGVyIGRyYWdnaW5nIHBhc3QgYm91bmRzLlxuXHRcdFx0XHQvLyBXZSdyZSBva2F5IHdpdGggdGhlIGZhY3QgdGhhdCBib3VuZHMgY2FuIGJlIHVuZGVmaW5lZCBoZXJlLlxuXHRcdFx0XHRpZiAoIGluaXRWYWx1ZSArIGRyYWdEZWx0YSA+IHRoaXMuX21heCApIHtcblx0XHRcdFx0XHRkcmFnRGVsdGEgPSB0aGlzLl9tYXggLSBpbml0VmFsdWU7XG5cdFx0XHRcdH0gZWxzZSBpZiAoIGluaXRWYWx1ZSArIGRyYWdEZWx0YSA8IHRoaXMuX21pbiApIHtcblx0XHRcdFx0XHRkcmFnRGVsdGEgPSB0aGlzLl9taW4gLSBpbml0VmFsdWU7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aGlzLl9zbmFwQ2xhbXBTZXRWYWx1ZSggaW5pdFZhbHVlICsgZHJhZ0RlbHRhICk7XG5cblx0XHRcdH1cblxuXHRcdFx0cHJldkNsaWVudFkgPSBlLmNsaWVudFk7XG5cblx0XHR9O1xuXG5cdFx0Y29uc3Qgb25Nb3VzZVVwID0gKCkgPT4ge1xuXHRcdFx0dGhpcy5fc2V0RHJhZ2dpbmdTdHlsZSggZmFsc2UsICd2ZXJ0aWNhbCcgKTtcblx0XHRcdHRoaXMuX2NhbGxPbkZpbmlzaENoYW5nZSgpO1xuXHRcdFx0d2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoICdtb3VzZW1vdmUnLCBvbk1vdXNlTW92ZSApO1xuXHRcdFx0d2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoICdtb3VzZXVwJywgb25Nb3VzZVVwICk7XG5cdFx0fTtcblxuXHRcdC8vIEZvY3VzIHN0YXRlICYgb25GaW5pc2hDaGFuZ2Vcblx0XHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRcdGNvbnN0IG9uRm9jdXMgPSAoKSA9PiB7XG5cdFx0XHR0aGlzLl9pbnB1dEZvY3VzZWQgPSB0cnVlO1xuXHRcdH07XG5cblx0XHRjb25zdCBvbkJsdXIgPSAoKSA9PiB7XG5cdFx0XHR0aGlzLl9pbnB1dEZvY3VzZWQgPSBmYWxzZTtcblx0XHRcdHRoaXMudXBkYXRlRGlzcGxheSgpO1xuXHRcdFx0dGhpcy5fY2FsbE9uRmluaXNoQ2hhbmdlKCk7XG5cdFx0fTtcblxuXHRcdHRoaXMuJGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoICdpbnB1dCcsIG9uSW5wdXQgKTtcblx0XHR0aGlzLiRpbnB1dC5hZGRFdmVudExpc3RlbmVyKCAna2V5ZG93bicsIG9uS2V5RG93biApO1xuXHRcdHRoaXMuJGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoICd3aGVlbCcsIG9uV2hlZWwsIHsgcGFzc2l2ZTogZmFsc2UgfSApO1xuXHRcdHRoaXMuJGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoICdtb3VzZWRvd24nLCBvbk1vdXNlRG93biApO1xuXHRcdHRoaXMuJGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoICdmb2N1cycsIG9uRm9jdXMgKTtcblx0XHR0aGlzLiRpbnB1dC5hZGRFdmVudExpc3RlbmVyKCAnYmx1cicsIG9uQmx1ciApO1xuXG5cdH1cblxuXHRfaW5pdFNsaWRlcigpIHtcblxuXHRcdHRoaXMuX2hhc1NsaWRlciA9IHRydWU7XG5cblx0XHQvLyBCdWlsZCBET01cblx0XHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRcdHRoaXMuJHNsaWRlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoICdkaXYnICk7XG5cdFx0dGhpcy4kc2xpZGVyLmNsYXNzTGlzdC5hZGQoICdzbGlkZXInICk7XG5cblx0XHR0aGlzLiRmaWxsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2RpdicgKTtcblx0XHR0aGlzLiRmaWxsLmNsYXNzTGlzdC5hZGQoICdmaWxsJyApO1xuXG5cdFx0dGhpcy4kc2xpZGVyLmFwcGVuZENoaWxkKCB0aGlzLiRmaWxsICk7XG5cdFx0dGhpcy4kd2lkZ2V0Lmluc2VydEJlZm9yZSggdGhpcy4kc2xpZGVyLCB0aGlzLiRpbnB1dCApO1xuXG5cdFx0dGhpcy5kb21FbGVtZW50LmNsYXNzTGlzdC5hZGQoICdoYXNTbGlkZXInICk7XG5cblx0XHQvLyBNYXAgY2xpZW50WCB0byB2YWx1ZVxuXHRcdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdFx0Y29uc3QgbWFwID0gKCB2LCBhLCBiLCBjLCBkICkgPT4ge1xuXHRcdFx0cmV0dXJuICggdiAtIGEgKSAvICggYiAtIGEgKSAqICggZCAtIGMgKSArIGM7XG5cdFx0fTtcblxuXHRcdGNvbnN0IHNldFZhbHVlRnJvbVggPSBjbGllbnRYID0+IHtcblx0XHRcdGNvbnN0IHJlY3QgPSB0aGlzLiRzbGlkZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cdFx0XHRsZXQgdmFsdWUgPSBtYXAoIGNsaWVudFgsIHJlY3QubGVmdCwgcmVjdC5yaWdodCwgdGhpcy5fbWluLCB0aGlzLl9tYXggKTtcblx0XHRcdHRoaXMuX3NuYXBDbGFtcFNldFZhbHVlKCB2YWx1ZSApO1xuXHRcdH07XG5cblx0XHQvLyBNb3VzZSBkcmFnXG5cdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0XHRjb25zdCBtb3VzZURvd24gPSBlID0+IHtcblx0XHRcdHRoaXMuX3NldERyYWdnaW5nU3R5bGUoIHRydWUgKTtcblx0XHRcdHNldFZhbHVlRnJvbVgoIGUuY2xpZW50WCApO1xuXHRcdFx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoICdtb3VzZW1vdmUnLCBtb3VzZU1vdmUgKTtcblx0XHRcdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCAnbW91c2V1cCcsIG1vdXNlVXAgKTtcblx0XHR9O1xuXG5cdFx0Y29uc3QgbW91c2VNb3ZlID0gZSA9PiB7XG5cdFx0XHRzZXRWYWx1ZUZyb21YKCBlLmNsaWVudFggKTtcblx0XHR9O1xuXG5cdFx0Y29uc3QgbW91c2VVcCA9ICgpID0+IHtcblx0XHRcdHRoaXMuX2NhbGxPbkZpbmlzaENoYW5nZSgpO1xuXHRcdFx0dGhpcy5fc2V0RHJhZ2dpbmdTdHlsZSggZmFsc2UgKTtcblx0XHRcdHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCAnbW91c2Vtb3ZlJywgbW91c2VNb3ZlICk7XG5cdFx0XHR3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lciggJ21vdXNldXAnLCBtb3VzZVVwICk7XG5cdFx0fTtcblxuXHRcdC8vIFRvdWNoIGRyYWdcblx0XHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRcdGxldCB0ZXN0aW5nRm9yU2Nyb2xsID0gZmFsc2UsIHByZXZDbGllbnRYLCBwcmV2Q2xpZW50WTtcblxuXHRcdGNvbnN0IGJlZ2luVG91Y2hEcmFnID0gZSA9PiB7XG5cdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHR0aGlzLl9zZXREcmFnZ2luZ1N0eWxlKCB0cnVlICk7XG5cdFx0XHRzZXRWYWx1ZUZyb21YKCBlLnRvdWNoZXNbIDAgXS5jbGllbnRYICk7XG5cdFx0XHR0ZXN0aW5nRm9yU2Nyb2xsID0gZmFsc2U7XG5cdFx0fTtcblxuXHRcdGNvbnN0IG9uVG91Y2hTdGFydCA9IGUgPT4ge1xuXG5cdFx0XHRpZiAoIGUudG91Y2hlcy5sZW5ndGggPiAxICkgcmV0dXJuO1xuXG5cdFx0XHQvLyBJZiB3ZSdyZSBpbiBhIHNjcm9sbGFibGUgY29udGFpbmVyLCB3ZSBzaG91bGQgd2FpdCBmb3IgdGhlIGZpcnN0XG5cdFx0XHQvLyB0b3VjaG1vdmUgdG8gc2VlIGlmIHRoZSB1c2VyIGlzIHRyeWluZyB0byBzbGlkZSBvciBzY3JvbGwuXG5cdFx0XHRpZiAoIHRoaXMuX2hhc1Njcm9sbEJhciApIHtcblxuXHRcdFx0XHRwcmV2Q2xpZW50WCA9IGUudG91Y2hlc1sgMCBdLmNsaWVudFg7XG5cdFx0XHRcdHByZXZDbGllbnRZID0gZS50b3VjaGVzWyAwIF0uY2xpZW50WTtcblx0XHRcdFx0dGVzdGluZ0ZvclNjcm9sbCA9IHRydWU7XG5cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0Ly8gT3RoZXJ3aXNlLCB3ZSBjYW4gc2V0IHRoZSB2YWx1ZSBzdHJhaWdodCBhd2F5IG9uIHRvdWNoc3RhcnQuXG5cdFx0XHRcdGJlZ2luVG91Y2hEcmFnKCBlICk7XG5cblx0XHRcdH1cblxuXHRcdFx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoICd0b3VjaG1vdmUnLCBvblRvdWNoTW92ZSwgeyBwYXNzaXZlOiBmYWxzZSB9ICk7XG5cdFx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lciggJ3RvdWNoZW5kJywgb25Ub3VjaEVuZCApO1xuXG5cdFx0fTtcblxuXHRcdGNvbnN0IG9uVG91Y2hNb3ZlID0gZSA9PiB7XG5cblx0XHRcdGlmICggdGVzdGluZ0ZvclNjcm9sbCApIHtcblxuXHRcdFx0XHRjb25zdCBkeCA9IGUudG91Y2hlc1sgMCBdLmNsaWVudFggLSBwcmV2Q2xpZW50WDtcblx0XHRcdFx0Y29uc3QgZHkgPSBlLnRvdWNoZXNbIDAgXS5jbGllbnRZIC0gcHJldkNsaWVudFk7XG5cblx0XHRcdFx0aWYgKCBNYXRoLmFicyggZHggKSA+IE1hdGguYWJzKCBkeSApICkge1xuXG5cdFx0XHRcdFx0Ly8gV2UgbW92ZWQgaG9yaXpvbnRhbGx5LCBzZXQgdGhlIHZhbHVlIGFuZCBzdG9wIGNoZWNraW5nLlxuXHRcdFx0XHRcdGJlZ2luVG91Y2hEcmFnKCBlICk7XG5cblx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdC8vIFRoaXMgd2FzLCBpbiBmYWN0LCBhbiBhdHRlbXB0IHRvIHNjcm9sbC4gQWJvcnQuXG5cdFx0XHRcdFx0d2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoICd0b3VjaG1vdmUnLCBvblRvdWNoTW92ZSApO1xuXHRcdFx0XHRcdHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCAndG91Y2hlbmQnLCBvblRvdWNoRW5kICk7XG5cblx0XHRcdFx0fVxuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0c2V0VmFsdWVGcm9tWCggZS50b3VjaGVzWyAwIF0uY2xpZW50WCApO1xuXG5cdFx0XHR9XG5cblx0XHR9O1xuXG5cdFx0Y29uc3Qgb25Ub3VjaEVuZCA9ICgpID0+IHtcblx0XHRcdHRoaXMuX2NhbGxPbkZpbmlzaENoYW5nZSgpO1xuXHRcdFx0dGhpcy5fc2V0RHJhZ2dpbmdTdHlsZSggZmFsc2UgKTtcblx0XHRcdHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCAndG91Y2htb3ZlJywgb25Ub3VjaE1vdmUgKTtcblx0XHRcdHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCAndG91Y2hlbmQnLCBvblRvdWNoRW5kICk7XG5cdFx0fTtcblxuXHRcdC8vIE1vdXNlIHdoZWVsXG5cdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0XHQvLyBXZSBoYXZlIHRvIHVzZSBhIGRlYm91bmNlZCBmdW5jdGlvbiB0byBjYWxsIG9uRmluaXNoQ2hhbmdlIGJlY2F1c2Vcblx0XHQvLyB0aGVyZSdzIG5vIHdheSB0byB0ZWxsIHdoZW4gdGhlIHVzZXIgaXMgXCJkb25lXCIgbW91c2Utd2hlZWxpbmcuXG5cdFx0Y29uc3QgY2FsbE9uRmluaXNoQ2hhbmdlID0gdGhpcy5fY2FsbE9uRmluaXNoQ2hhbmdlLmJpbmQoIHRoaXMgKTtcblx0XHRjb25zdCBXSEVFTF9ERUJPVU5DRV9USU1FID0gNDAwO1xuXHRcdGxldCB3aGVlbEZpbmlzaENoYW5nZVRpbWVvdXQ7XG5cblx0XHRjb25zdCBvbldoZWVsID0gZSA9PiB7XG5cblx0XHRcdC8vIGlnbm9yZSB2ZXJ0aWNhbCB3aGVlbHMgaWYgdGhlcmUncyBhIHNjcm9sbGJhclxuXHRcdFx0Y29uc3QgaXNWZXJ0aWNhbCA9IE1hdGguYWJzKCBlLmRlbHRhWCApIDwgTWF0aC5hYnMoIGUuZGVsdGFZICk7XG5cdFx0XHRpZiAoIGlzVmVydGljYWwgJiYgdGhpcy5faGFzU2Nyb2xsQmFyICkgcmV0dXJuO1xuXG5cdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdC8vIHNldCB2YWx1ZVxuXHRcdFx0Y29uc3QgZGVsdGEgPSB0aGlzLl9ub3JtYWxpemVNb3VzZVdoZWVsKCBlICkgKiB0aGlzLl9zdGVwO1xuXHRcdFx0dGhpcy5fc25hcENsYW1wU2V0VmFsdWUoIHRoaXMuZ2V0VmFsdWUoKSArIGRlbHRhICk7XG5cblx0XHRcdC8vIGZvcmNlIHRoZSBpbnB1dCB0byB1cGRhdGVEaXNwbGF5IHdoZW4gaXQncyBmb2N1c2VkXG5cdFx0XHR0aGlzLiRpbnB1dC52YWx1ZSA9IHRoaXMuZ2V0VmFsdWUoKTtcblxuXHRcdFx0Ly8gZGVib3VuY2Ugb25GaW5pc2hDaGFuZ2Vcblx0XHRcdGNsZWFyVGltZW91dCggd2hlZWxGaW5pc2hDaGFuZ2VUaW1lb3V0ICk7XG5cdFx0XHR3aGVlbEZpbmlzaENoYW5nZVRpbWVvdXQgPSBzZXRUaW1lb3V0KCBjYWxsT25GaW5pc2hDaGFuZ2UsIFdIRUVMX0RFQk9VTkNFX1RJTUUgKTtcblxuXHRcdH07XG5cblx0XHR0aGlzLiRzbGlkZXIuYWRkRXZlbnRMaXN0ZW5lciggJ21vdXNlZG93bicsIG1vdXNlRG93biApO1xuXHRcdHRoaXMuJHNsaWRlci5hZGRFdmVudExpc3RlbmVyKCAndG91Y2hzdGFydCcsIG9uVG91Y2hTdGFydCwgeyBwYXNzaXZlOiBmYWxzZSB9ICk7XG5cdFx0dGhpcy4kc2xpZGVyLmFkZEV2ZW50TGlzdGVuZXIoICd3aGVlbCcsIG9uV2hlZWwsIHsgcGFzc2l2ZTogZmFsc2UgfSApO1xuXG5cdH1cblxuXHRfc2V0RHJhZ2dpbmdTdHlsZSggYWN0aXZlLCBheGlzID0gJ2hvcml6b250YWwnICkge1xuXHRcdGlmICggdGhpcy4kc2xpZGVyICkge1xuXHRcdFx0dGhpcy4kc2xpZGVyLmNsYXNzTGlzdC50b2dnbGUoICdhY3RpdmUnLCBhY3RpdmUgKTtcblx0XHR9XG5cdFx0ZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QudG9nZ2xlKCAnbGlsLWd1aS1kcmFnZ2luZycsIGFjdGl2ZSApO1xuXHRcdGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnRvZ2dsZSggYGxpbC1ndWktJHtheGlzfWAsIGFjdGl2ZSApO1xuXHR9XG5cblx0X2dldEltcGxpY2l0U3RlcCgpIHtcblxuXHRcdGlmICggdGhpcy5faGFzTWluICYmIHRoaXMuX2hhc01heCApIHtcblx0XHRcdHJldHVybiAoIHRoaXMuX21heCAtIHRoaXMuX21pbiApIC8gMTAwMDtcblx0XHR9XG5cblx0XHRyZXR1cm4gMC4xO1xuXG5cdH1cblxuXHRfb25VcGRhdGVNaW5NYXgoKSB7XG5cblx0XHRpZiAoICF0aGlzLl9oYXNTbGlkZXIgJiYgdGhpcy5faGFzTWluICYmIHRoaXMuX2hhc01heCApIHtcblxuXHRcdFx0Ly8gSWYgdGhpcyBpcyB0aGUgZmlyc3QgdGltZSB3ZSdyZSBoZWFyaW5nIGFib3V0IG1pbiBhbmQgbWF4XG5cdFx0XHQvLyBhbmQgd2UgaGF2ZW4ndCBleHBsaWNpdGx5IHN0YXRlZCB3aGF0IG91ciBzdGVwIGlzLCBsZXQnc1xuXHRcdFx0Ly8gdXBkYXRlIHRoYXQgdG9vLlxuXHRcdFx0aWYgKCAhdGhpcy5fc3RlcEV4cGxpY2l0ICkge1xuXHRcdFx0XHR0aGlzLnN0ZXAoIHRoaXMuX2dldEltcGxpY2l0U3RlcCgpLCBmYWxzZSApO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLl9pbml0U2xpZGVyKCk7XG5cdFx0XHR0aGlzLnVwZGF0ZURpc3BsYXkoKTtcblxuXHRcdH1cblxuXHR9XG5cblx0X25vcm1hbGl6ZU1vdXNlV2hlZWwoIGUgKSB7XG5cblx0XHRsZXQgeyBkZWx0YVgsIGRlbHRhWSB9ID0gZTtcblxuXHRcdC8vIFNhZmFyaSBhbmQgQ2hyb21lIHJlcG9ydCB3ZWlyZCBub24taW50ZWdyYWwgdmFsdWVzIGZvciBhIG5vdGNoZWQgd2hlZWwsXG5cdFx0Ly8gYnV0IHN0aWxsIGV4cG9zZSBhY3R1YWwgbGluZXMgc2Nyb2xsZWQgdmlhIHdoZWVsRGVsdGEuIE5vdGNoZWQgd2hlZWxzXG5cdFx0Ly8gc2hvdWxkIGJlaGF2ZSB0aGUgc2FtZSB3YXkgYXMgYXJyb3cga2V5cy5cblx0XHRpZiAoIE1hdGguZmxvb3IoIGUuZGVsdGFZICkgIT09IGUuZGVsdGFZICYmIGUud2hlZWxEZWx0YSApIHtcblx0XHRcdGRlbHRhWCA9IDA7XG5cdFx0XHRkZWx0YVkgPSAtZS53aGVlbERlbHRhIC8gMTIwO1xuXHRcdFx0ZGVsdGFZICo9IHRoaXMuX3N0ZXBFeHBsaWNpdCA/IDEgOiAxMDtcblx0XHR9XG5cblx0XHRjb25zdCB3aGVlbCA9IGRlbHRhWCArIC1kZWx0YVk7XG5cblx0XHRyZXR1cm4gd2hlZWw7XG5cblx0fVxuXG5cdF9hcnJvd0tleU11bHRpcGxpZXIoIGUgKSB7XG5cblx0XHRsZXQgbXVsdCA9IHRoaXMuX3N0ZXBFeHBsaWNpdCA/IDEgOiAxMDtcblxuXHRcdGlmICggZS5zaGlmdEtleSApIHtcblx0XHRcdG11bHQgKj0gMTA7XG5cdFx0fSBlbHNlIGlmICggZS5hbHRLZXkgKSB7XG5cdFx0XHRtdWx0IC89IDEwO1xuXHRcdH1cblxuXHRcdHJldHVybiBtdWx0O1xuXG5cdH1cblxuXHRfc25hcCggdmFsdWUgKSB7XG5cblx0XHQvLyBUaGlzIHdvdWxkIGJlIHRoZSBsb2dpY2FsIHdheSB0byBkbyB0aGluZ3MsIGJ1dCBmbG9hdGluZyBwb2ludCBlcnJvcnMuXG5cdFx0Ly8gcmV0dXJuIE1hdGgucm91bmQoIHZhbHVlIC8gdGhpcy5fc3RlcCApICogdGhpcy5fc3RlcDtcblxuXHRcdC8vIFVzaW5nIGludmVyc2Ugc3RlcCBzb2x2ZXMgYSBsb3Qgb2YgdGhlbSwgYnV0IG5vdCBhbGxcblx0XHQvLyBjb25zdCBpbnZlcnNlU3RlcCA9IDEgLyB0aGlzLl9zdGVwO1xuXHRcdC8vIHJldHVybiBNYXRoLnJvdW5kKCB2YWx1ZSAqIGludmVyc2VTdGVwICkgLyBpbnZlcnNlU3RlcDtcblxuXHRcdC8vIE5vdCBoYXBweSBhYm91dCB0aGlzLCBidXQgaGF2ZW4ndCBzZWVuIGl0IGJyZWFrLlxuXHRcdGNvbnN0IHIgPSBNYXRoLnJvdW5kKCB2YWx1ZSAvIHRoaXMuX3N0ZXAgKSAqIHRoaXMuX3N0ZXA7XG5cdFx0cmV0dXJuIHBhcnNlRmxvYXQoIHIudG9QcmVjaXNpb24oIDE1ICkgKTtcblxuXHR9XG5cblx0X2NsYW1wKCB2YWx1ZSApIHtcblx0XHQvLyBlaXRoZXIgY29uZGl0aW9uIGlzIGZhbHNlIGlmIG1pbiBvciBtYXggaXMgdW5kZWZpbmVkXG5cdFx0aWYgKCB2YWx1ZSA8IHRoaXMuX21pbiApIHZhbHVlID0gdGhpcy5fbWluO1xuXHRcdGlmICggdmFsdWUgPiB0aGlzLl9tYXggKSB2YWx1ZSA9IHRoaXMuX21heDtcblx0XHRyZXR1cm4gdmFsdWU7XG5cdH1cblxuXHRfc25hcENsYW1wU2V0VmFsdWUoIHZhbHVlICkge1xuXHRcdHRoaXMuc2V0VmFsdWUoIHRoaXMuX2NsYW1wKCB0aGlzLl9zbmFwKCB2YWx1ZSApICkgKTtcblx0fVxuXG5cdGdldCBfaGFzU2Nyb2xsQmFyKCkge1xuXHRcdGNvbnN0IHJvb3QgPSB0aGlzLnBhcmVudC5yb290LiRjaGlsZHJlbjtcblx0XHRyZXR1cm4gcm9vdC5zY3JvbGxIZWlnaHQgPiByb290LmNsaWVudEhlaWdodDtcblx0fVxuXG5cdGdldCBfaGFzTWluKCkge1xuXHRcdHJldHVybiB0aGlzLl9taW4gIT09IHVuZGVmaW5lZDtcblx0fVxuXG5cdGdldCBfaGFzTWF4KCkge1xuXHRcdHJldHVybiB0aGlzLl9tYXggIT09IHVuZGVmaW5lZDtcblx0fVxuXG59XG5cbmNsYXNzIE9wdGlvbkNvbnRyb2xsZXIgZXh0ZW5kcyBDb250cm9sbGVyIHtcblxuXHRjb25zdHJ1Y3RvciggcGFyZW50LCBvYmplY3QsIHByb3BlcnR5LCBvcHRpb25zICkge1xuXG5cdFx0c3VwZXIoIHBhcmVudCwgb2JqZWN0LCBwcm9wZXJ0eSwgJ29wdGlvbicgKTtcblxuXHRcdHRoaXMuJHNlbGVjdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoICdzZWxlY3QnICk7XG5cdFx0dGhpcy4kc2VsZWN0LnNldEF0dHJpYnV0ZSggJ2FyaWEtbGFiZWxsZWRieScsIHRoaXMuJG5hbWUuaWQgKTtcblxuXHRcdHRoaXMuJGRpc3BsYXkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCAnZGl2JyApO1xuXHRcdHRoaXMuJGRpc3BsYXkuY2xhc3NMaXN0LmFkZCggJ2Rpc3BsYXknICk7XG5cblx0XHR0aGlzLiRzZWxlY3QuYWRkRXZlbnRMaXN0ZW5lciggJ2NoYW5nZScsICgpID0+IHtcblx0XHRcdHRoaXMuc2V0VmFsdWUoIHRoaXMuX3ZhbHVlc1sgdGhpcy4kc2VsZWN0LnNlbGVjdGVkSW5kZXggXSApO1xuXHRcdFx0dGhpcy5fY2FsbE9uRmluaXNoQ2hhbmdlKCk7XG5cdFx0fSApO1xuXG5cdFx0dGhpcy4kc2VsZWN0LmFkZEV2ZW50TGlzdGVuZXIoICdmb2N1cycsICgpID0+IHtcblx0XHRcdHRoaXMuJGRpc3BsYXkuY2xhc3NMaXN0LmFkZCggJ2ZvY3VzJyApO1xuXHRcdH0gKTtcblxuXHRcdHRoaXMuJHNlbGVjdC5hZGRFdmVudExpc3RlbmVyKCAnYmx1cicsICgpID0+IHtcblx0XHRcdHRoaXMuJGRpc3BsYXkuY2xhc3NMaXN0LnJlbW92ZSggJ2ZvY3VzJyApO1xuXHRcdH0gKTtcblxuXHRcdHRoaXMuJHdpZGdldC5hcHBlbmRDaGlsZCggdGhpcy4kc2VsZWN0ICk7XG5cdFx0dGhpcy4kd2lkZ2V0LmFwcGVuZENoaWxkKCB0aGlzLiRkaXNwbGF5ICk7XG5cblx0XHR0aGlzLiRkaXNhYmxlID0gdGhpcy4kc2VsZWN0O1xuXG5cdFx0dGhpcy5vcHRpb25zKCBvcHRpb25zICk7XG5cblx0fVxuXG5cdG9wdGlvbnMoIG9wdGlvbnMgKSB7XG5cblx0XHR0aGlzLl92YWx1ZXMgPSBBcnJheS5pc0FycmF5KCBvcHRpb25zICkgPyBvcHRpb25zIDogT2JqZWN0LnZhbHVlcyggb3B0aW9ucyApO1xuXHRcdHRoaXMuX25hbWVzID0gQXJyYXkuaXNBcnJheSggb3B0aW9ucyApID8gb3B0aW9ucyA6IE9iamVjdC5rZXlzKCBvcHRpb25zICk7XG5cblx0XHR0aGlzLiRzZWxlY3QucmVwbGFjZUNoaWxkcmVuKCk7XG5cblx0XHR0aGlzLl9uYW1lcy5mb3JFYWNoKCBuYW1lID0+IHtcblx0XHRcdGNvbnN0ICRvcHRpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCAnb3B0aW9uJyApO1xuXHRcdFx0JG9wdGlvbi50ZXh0Q29udGVudCA9IG5hbWU7XG5cdFx0XHR0aGlzLiRzZWxlY3QuYXBwZW5kQ2hpbGQoICRvcHRpb24gKTtcblx0XHR9ICk7XG5cblx0XHR0aGlzLnVwZGF0ZURpc3BsYXkoKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXG5cdH1cblxuXHR1cGRhdGVEaXNwbGF5KCkge1xuXHRcdGNvbnN0IHZhbHVlID0gdGhpcy5nZXRWYWx1ZSgpO1xuXHRcdGNvbnN0IGluZGV4ID0gdGhpcy5fdmFsdWVzLmluZGV4T2YoIHZhbHVlICk7XG5cdFx0dGhpcy4kc2VsZWN0LnNlbGVjdGVkSW5kZXggPSBpbmRleDtcblx0XHR0aGlzLiRkaXNwbGF5LnRleHRDb250ZW50ID0gaW5kZXggPT09IC0xID8gdmFsdWUgOiB0aGlzLl9uYW1lc1sgaW5kZXggXTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG59XG5cbmNsYXNzIFN0cmluZ0NvbnRyb2xsZXIgZXh0ZW5kcyBDb250cm9sbGVyIHtcblxuXHRjb25zdHJ1Y3RvciggcGFyZW50LCBvYmplY3QsIHByb3BlcnR5ICkge1xuXG5cdFx0c3VwZXIoIHBhcmVudCwgb2JqZWN0LCBwcm9wZXJ0eSwgJ3N0cmluZycgKTtcblxuXHRcdHRoaXMuJGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2lucHV0JyApO1xuXHRcdHRoaXMuJGlucHV0LnNldEF0dHJpYnV0ZSggJ3R5cGUnLCAndGV4dCcgKTtcblx0XHR0aGlzLiRpbnB1dC5zZXRBdHRyaWJ1dGUoICdzcGVsbGNoZWNrJywgJ2ZhbHNlJyApO1xuXHRcdHRoaXMuJGlucHV0LnNldEF0dHJpYnV0ZSggJ2FyaWEtbGFiZWxsZWRieScsIHRoaXMuJG5hbWUuaWQgKTtcblxuXHRcdHRoaXMuJGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoICdpbnB1dCcsICgpID0+IHtcblx0XHRcdHRoaXMuc2V0VmFsdWUoIHRoaXMuJGlucHV0LnZhbHVlICk7XG5cdFx0fSApO1xuXG5cdFx0dGhpcy4kaW5wdXQuYWRkRXZlbnRMaXN0ZW5lciggJ2tleWRvd24nLCBlID0+IHtcblx0XHRcdGlmICggZS5jb2RlID09PSAnRW50ZXInICkge1xuXHRcdFx0XHR0aGlzLiRpbnB1dC5ibHVyKCk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXG5cdFx0dGhpcy4kaW5wdXQuYWRkRXZlbnRMaXN0ZW5lciggJ2JsdXInLCAoKSA9PiB7XG5cdFx0XHR0aGlzLl9jYWxsT25GaW5pc2hDaGFuZ2UoKTtcblx0XHR9ICk7XG5cblx0XHR0aGlzLiR3aWRnZXQuYXBwZW5kQ2hpbGQoIHRoaXMuJGlucHV0ICk7XG5cblx0XHR0aGlzLiRkaXNhYmxlID0gdGhpcy4kaW5wdXQ7XG5cblx0XHR0aGlzLnVwZGF0ZURpc3BsYXkoKTtcblxuXHR9XG5cblx0dXBkYXRlRGlzcGxheSgpIHtcblx0XHR0aGlzLiRpbnB1dC52YWx1ZSA9IHRoaXMuZ2V0VmFsdWUoKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG59XG5cbmNvbnN0IHN0eWxlc2hlZXQgPSBgLmxpbC1ndWkge1xuICBmb250LWZhbWlseTogdmFyKC0tZm9udC1mYW1pbHkpO1xuICBmb250LXNpemU6IHZhcigtLWZvbnQtc2l6ZSk7XG4gIGxpbmUtaGVpZ2h0OiAxO1xuICBmb250LXdlaWdodDogbm9ybWFsO1xuICBmb250LXN0eWxlOiBub3JtYWw7XG4gIHRleHQtYWxpZ246IGxlZnQ7XG4gIGNvbG9yOiB2YXIoLS10ZXh0LWNvbG9yKTtcbiAgdXNlci1zZWxlY3Q6IG5vbmU7XG4gIC13ZWJraXQtdXNlci1zZWxlY3Q6IG5vbmU7XG4gIHRvdWNoLWFjdGlvbjogbWFuaXB1bGF0aW9uO1xuICAtLWJhY2tncm91bmQtY29sb3I6ICMxZjFmMWY7XG4gIC0tdGV4dC1jb2xvcjogI2ViZWJlYjtcbiAgLS10aXRsZS1iYWNrZ3JvdW5kLWNvbG9yOiAjMTExMTExO1xuICAtLXRpdGxlLXRleHQtY29sb3I6ICNlYmViZWI7XG4gIC0td2lkZ2V0LWNvbG9yOiAjNDI0MjQyO1xuICAtLWhvdmVyLWNvbG9yOiAjNGY0ZjRmO1xuICAtLWZvY3VzLWNvbG9yOiAjNTk1OTU5O1xuICAtLW51bWJlci1jb2xvcjogIzJjYzlmZjtcbiAgLS1zdHJpbmctY29sb3I6ICNhMmRiM2M7XG4gIC0tZm9udC1zaXplOiAxMXB4O1xuICAtLWlucHV0LWZvbnQtc2l6ZTogMTFweDtcbiAgLS1mb250LWZhbWlseTogLWFwcGxlLXN5c3RlbSwgQmxpbmtNYWNTeXN0ZW1Gb250LCBcIlNlZ29lIFVJXCIsIFJvYm90bywgQXJpYWwsIHNhbnMtc2VyaWY7XG4gIC0tZm9udC1mYW1pbHktbW9ubzogTWVubG8sIE1vbmFjbywgQ29uc29sYXMsIFwiRHJvaWQgU2FucyBNb25vXCIsIG1vbm9zcGFjZTtcbiAgLS1wYWRkaW5nOiA0cHg7XG4gIC0tc3BhY2luZzogNHB4O1xuICAtLXdpZGdldC1oZWlnaHQ6IDIwcHg7XG4gIC0tdGl0bGUtaGVpZ2h0OiBjYWxjKHZhcigtLXdpZGdldC1oZWlnaHQpICsgdmFyKC0tc3BhY2luZykgKiAxLjI1KTtcbiAgLS1uYW1lLXdpZHRoOiA0NSU7XG4gIC0tc2xpZGVyLWtub2Itd2lkdGg6IDJweDtcbiAgLS1zbGlkZXItaW5wdXQtd2lkdGg6IDI3JTtcbiAgLS1jb2xvci1pbnB1dC13aWR0aDogMjclO1xuICAtLXNsaWRlci1pbnB1dC1taW4td2lkdGg6IDQ1cHg7XG4gIC0tY29sb3ItaW5wdXQtbWluLXdpZHRoOiA0NXB4O1xuICAtLWZvbGRlci1pbmRlbnQ6IDdweDtcbiAgLS13aWRnZXQtcGFkZGluZzogMCAwIDAgM3B4O1xuICAtLXdpZGdldC1ib3JkZXItcmFkaXVzOiAycHg7XG4gIC0tY2hlY2tib3gtc2l6ZTogY2FsYygwLjc1ICogdmFyKC0td2lkZ2V0LWhlaWdodCkpO1xuICAtLXNjcm9sbGJhci13aWR0aDogNXB4O1xufVxuLmxpbC1ndWksIC5saWwtZ3VpICoge1xuICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICBtYXJnaW46IDA7XG4gIHBhZGRpbmc6IDA7XG59XG4ubGlsLWd1aS5yb290IHtcbiAgd2lkdGg6IHZhcigtLXdpZHRoLCAyNDVweCk7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGJhY2tncm91bmQ6IHZhcigtLWJhY2tncm91bmQtY29sb3IpO1xufVxuLmxpbC1ndWkucm9vdCA+IC50aXRsZSB7XG4gIGJhY2tncm91bmQ6IHZhcigtLXRpdGxlLWJhY2tncm91bmQtY29sb3IpO1xuICBjb2xvcjogdmFyKC0tdGl0bGUtdGV4dC1jb2xvcik7XG59XG4ubGlsLWd1aS5yb290ID4gLmNoaWxkcmVuIHtcbiAgb3ZlcmZsb3cteDogaGlkZGVuO1xuICBvdmVyZmxvdy15OiBhdXRvO1xufVxuLmxpbC1ndWkucm9vdCA+IC5jaGlsZHJlbjo6LXdlYmtpdC1zY3JvbGxiYXIge1xuICB3aWR0aDogdmFyKC0tc2Nyb2xsYmFyLXdpZHRoKTtcbiAgaGVpZ2h0OiB2YXIoLS1zY3JvbGxiYXItd2lkdGgpO1xuICBiYWNrZ3JvdW5kOiB2YXIoLS1iYWNrZ3JvdW5kLWNvbG9yKTtcbn1cbi5saWwtZ3VpLnJvb3QgPiAuY2hpbGRyZW46Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iIHtcbiAgYm9yZGVyLXJhZGl1czogdmFyKC0tc2Nyb2xsYmFyLXdpZHRoKTtcbiAgYmFja2dyb3VuZDogdmFyKC0tZm9jdXMtY29sb3IpO1xufVxuQG1lZGlhIChwb2ludGVyOiBjb2Fyc2UpIHtcbiAgLmxpbC1ndWkuYWxsb3ctdG91Y2gtc3R5bGVzLCAubGlsLWd1aS5hbGxvdy10b3VjaC1zdHlsZXMgLmxpbC1ndWkge1xuICAgIC0td2lkZ2V0LWhlaWdodDogMjhweDtcbiAgICAtLXBhZGRpbmc6IDZweDtcbiAgICAtLXNwYWNpbmc6IDZweDtcbiAgICAtLWZvbnQtc2l6ZTogMTNweDtcbiAgICAtLWlucHV0LWZvbnQtc2l6ZTogMTZweDtcbiAgICAtLWZvbGRlci1pbmRlbnQ6IDEwcHg7XG4gICAgLS1zY3JvbGxiYXItd2lkdGg6IDdweDtcbiAgICAtLXNsaWRlci1pbnB1dC1taW4td2lkdGg6IDUwcHg7XG4gICAgLS1jb2xvci1pbnB1dC1taW4td2lkdGg6IDY1cHg7XG4gIH1cbn1cbi5saWwtZ3VpLmZvcmNlLXRvdWNoLXN0eWxlcywgLmxpbC1ndWkuZm9yY2UtdG91Y2gtc3R5bGVzIC5saWwtZ3VpIHtcbiAgLS13aWRnZXQtaGVpZ2h0OiAyOHB4O1xuICAtLXBhZGRpbmc6IDZweDtcbiAgLS1zcGFjaW5nOiA2cHg7XG4gIC0tZm9udC1zaXplOiAxM3B4O1xuICAtLWlucHV0LWZvbnQtc2l6ZTogMTZweDtcbiAgLS1mb2xkZXItaW5kZW50OiAxMHB4O1xuICAtLXNjcm9sbGJhci13aWR0aDogN3B4O1xuICAtLXNsaWRlci1pbnB1dC1taW4td2lkdGg6IDUwcHg7XG4gIC0tY29sb3ItaW5wdXQtbWluLXdpZHRoOiA2NXB4O1xufVxuLmxpbC1ndWkuYXV0b1BsYWNlIHtcbiAgbWF4LWhlaWdodDogMTAwJTtcbiAgcG9zaXRpb246IGZpeGVkO1xuICB0b3A6IDA7XG4gIHJpZ2h0OiAxNXB4O1xuICB6LWluZGV4OiAxMDAxO1xufVxuXG4ubGlsLWd1aSAuY29udHJvbGxlciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIHBhZGRpbmc6IDAgdmFyKC0tcGFkZGluZyk7XG4gIG1hcmdpbjogdmFyKC0tc3BhY2luZykgMDtcbn1cbi5saWwtZ3VpIC5jb250cm9sbGVyLmRpc2FibGVkIHtcbiAgb3BhY2l0eTogMC41O1xufVxuLmxpbC1ndWkgLmNvbnRyb2xsZXIuZGlzYWJsZWQsIC5saWwtZ3VpIC5jb250cm9sbGVyLmRpc2FibGVkICoge1xuICBwb2ludGVyLWV2ZW50czogbm9uZSAhaW1wb3J0YW50O1xufVxuLmxpbC1ndWkgLmNvbnRyb2xsZXIgPiAubmFtZSB7XG4gIG1pbi13aWR0aDogdmFyKC0tbmFtZS13aWR0aCk7XG4gIGZsZXgtc2hyaW5rOiAwO1xuICB3aGl0ZS1zcGFjZTogcHJlO1xuICBwYWRkaW5nLXJpZ2h0OiB2YXIoLS1zcGFjaW5nKTtcbiAgbGluZS1oZWlnaHQ6IHZhcigtLXdpZGdldC1oZWlnaHQpO1xufVxuLmxpbC1ndWkgLmNvbnRyb2xsZXIgLndpZGdldCB7XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgd2lkdGg6IDEwMCU7XG4gIG1pbi1oZWlnaHQ6IHZhcigtLXdpZGdldC1oZWlnaHQpO1xufVxuLmxpbC1ndWkgLmNvbnRyb2xsZXIuc3RyaW5nIGlucHV0IHtcbiAgY29sb3I6IHZhcigtLXN0cmluZy1jb2xvcik7XG59XG4ubGlsLWd1aSAuY29udHJvbGxlci5ib29sZWFuIHtcbiAgY3Vyc29yOiBwb2ludGVyO1xufVxuLmxpbC1ndWkgLmNvbnRyb2xsZXIuY29sb3IgLmRpc3BsYXkge1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiB2YXIoLS13aWRnZXQtaGVpZ2h0KTtcbiAgYm9yZGVyLXJhZGl1czogdmFyKC0td2lkZ2V0LWJvcmRlci1yYWRpdXMpO1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG59XG5AbWVkaWEgKGhvdmVyOiBob3Zlcikge1xuICAubGlsLWd1aSAuY29udHJvbGxlci5jb2xvciAuZGlzcGxheTpob3ZlcjpiZWZvcmUge1xuICAgIGNvbnRlbnQ6IFwiIFwiO1xuICAgIGRpc3BsYXk6IGJsb2NrO1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICBib3JkZXItcmFkaXVzOiB2YXIoLS13aWRnZXQtYm9yZGVyLXJhZGl1cyk7XG4gICAgYm9yZGVyOiAxcHggc29saWQgI2ZmZjk7XG4gICAgdG9wOiAwO1xuICAgIHJpZ2h0OiAwO1xuICAgIGJvdHRvbTogMDtcbiAgICBsZWZ0OiAwO1xuICB9XG59XG4ubGlsLWd1aSAuY29udHJvbGxlci5jb2xvciBpbnB1dFt0eXBlPWNvbG9yXSB7XG4gIG9wYWNpdHk6IDA7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG4gIGN1cnNvcjogcG9pbnRlcjtcbn1cbi5saWwtZ3VpIC5jb250cm9sbGVyLmNvbG9yIGlucHV0W3R5cGU9dGV4dF0ge1xuICBtYXJnaW4tbGVmdDogdmFyKC0tc3BhY2luZyk7XG4gIGZvbnQtZmFtaWx5OiB2YXIoLS1mb250LWZhbWlseS1tb25vKTtcbiAgbWluLXdpZHRoOiB2YXIoLS1jb2xvci1pbnB1dC1taW4td2lkdGgpO1xuICB3aWR0aDogdmFyKC0tY29sb3ItaW5wdXQtd2lkdGgpO1xuICBmbGV4LXNocmluazogMDtcbn1cbi5saWwtZ3VpIC5jb250cm9sbGVyLm9wdGlvbiBzZWxlY3Qge1xuICBvcGFjaXR5OiAwO1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHdpZHRoOiAxMDAlO1xuICBtYXgtd2lkdGg6IDEwMCU7XG59XG4ubGlsLWd1aSAuY29udHJvbGxlci5vcHRpb24gLmRpc3BsYXkge1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gIHBvaW50ZXItZXZlbnRzOiBub25lO1xuICBib3JkZXItcmFkaXVzOiB2YXIoLS13aWRnZXQtYm9yZGVyLXJhZGl1cyk7XG4gIGhlaWdodDogdmFyKC0td2lkZ2V0LWhlaWdodCk7XG4gIGxpbmUtaGVpZ2h0OiB2YXIoLS13aWRnZXQtaGVpZ2h0KTtcbiAgbWF4LXdpZHRoOiAxMDAlO1xuICBvdmVyZmxvdzogaGlkZGVuO1xuICB3b3JkLWJyZWFrOiBicmVhay1hbGw7XG4gIHBhZGRpbmctbGVmdDogMC41NWVtO1xuICBwYWRkaW5nLXJpZ2h0OiAxLjc1ZW07XG4gIGJhY2tncm91bmQ6IHZhcigtLXdpZGdldC1jb2xvcik7XG59XG5AbWVkaWEgKGhvdmVyOiBob3Zlcikge1xuICAubGlsLWd1aSAuY29udHJvbGxlci5vcHRpb24gLmRpc3BsYXkuZm9jdXMge1xuICAgIGJhY2tncm91bmQ6IHZhcigtLWZvY3VzLWNvbG9yKTtcbiAgfVxufVxuLmxpbC1ndWkgLmNvbnRyb2xsZXIub3B0aW9uIC5kaXNwbGF5LmFjdGl2ZSB7XG4gIGJhY2tncm91bmQ6IHZhcigtLWZvY3VzLWNvbG9yKTtcbn1cbi5saWwtZ3VpIC5jb250cm9sbGVyLm9wdGlvbiAuZGlzcGxheTphZnRlciB7XG4gIGZvbnQtZmFtaWx5OiBcImxpbC1ndWlcIjtcbiAgY29udGVudDogXCLihpVcIjtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICB0b3A6IDA7XG4gIHJpZ2h0OiAwO1xuICBib3R0b206IDA7XG4gIHBhZGRpbmctcmlnaHQ6IDAuMzc1ZW07XG59XG4ubGlsLWd1aSAuY29udHJvbGxlci5vcHRpb24gLndpZGdldCxcbi5saWwtZ3VpIC5jb250cm9sbGVyLm9wdGlvbiBzZWxlY3Qge1xuICBjdXJzb3I6IHBvaW50ZXI7XG59XG5AbWVkaWEgKGhvdmVyOiBob3Zlcikge1xuICAubGlsLWd1aSAuY29udHJvbGxlci5vcHRpb24gLndpZGdldDpob3ZlciAuZGlzcGxheSB7XG4gICAgYmFja2dyb3VuZDogdmFyKC0taG92ZXItY29sb3IpO1xuICB9XG59XG4ubGlsLWd1aSAuY29udHJvbGxlci5udW1iZXIgaW5wdXQge1xuICBjb2xvcjogdmFyKC0tbnVtYmVyLWNvbG9yKTtcbn1cbi5saWwtZ3VpIC5jb250cm9sbGVyLm51bWJlci5oYXNTbGlkZXIgaW5wdXQge1xuICBtYXJnaW4tbGVmdDogdmFyKC0tc3BhY2luZyk7XG4gIHdpZHRoOiB2YXIoLS1zbGlkZXItaW5wdXQtd2lkdGgpO1xuICBtaW4td2lkdGg6IHZhcigtLXNsaWRlci1pbnB1dC1taW4td2lkdGgpO1xuICBmbGV4LXNocmluazogMDtcbn1cbi5saWwtZ3VpIC5jb250cm9sbGVyLm51bWJlciAuc2xpZGVyIHtcbiAgd2lkdGg6IDEwMCU7XG4gIGhlaWdodDogdmFyKC0td2lkZ2V0LWhlaWdodCk7XG4gIGJhY2tncm91bmQ6IHZhcigtLXdpZGdldC1jb2xvcik7XG4gIGJvcmRlci1yYWRpdXM6IHZhcigtLXdpZGdldC1ib3JkZXItcmFkaXVzKTtcbiAgcGFkZGluZy1yaWdodDogdmFyKC0tc2xpZGVyLWtub2Itd2lkdGgpO1xuICBvdmVyZmxvdzogaGlkZGVuO1xuICBjdXJzb3I6IGV3LXJlc2l6ZTtcbiAgdG91Y2gtYWN0aW9uOiBwYW4teTtcbn1cbkBtZWRpYSAoaG92ZXI6IGhvdmVyKSB7XG4gIC5saWwtZ3VpIC5jb250cm9sbGVyLm51bWJlciAuc2xpZGVyOmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kOiB2YXIoLS1ob3Zlci1jb2xvcik7XG4gIH1cbn1cbi5saWwtZ3VpIC5jb250cm9sbGVyLm51bWJlciAuc2xpZGVyLmFjdGl2ZSB7XG4gIGJhY2tncm91bmQ6IHZhcigtLWZvY3VzLWNvbG9yKTtcbn1cbi5saWwtZ3VpIC5jb250cm9sbGVyLm51bWJlciAuc2xpZGVyLmFjdGl2ZSAuZmlsbCB7XG4gIG9wYWNpdHk6IDAuOTU7XG59XG4ubGlsLWd1aSAuY29udHJvbGxlci5udW1iZXIgLmZpbGwge1xuICBoZWlnaHQ6IDEwMCU7XG4gIGJvcmRlci1yaWdodDogdmFyKC0tc2xpZGVyLWtub2Itd2lkdGgpIHNvbGlkIHZhcigtLW51bWJlci1jb2xvcik7XG4gIGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xufVxuXG4ubGlsLWd1aS1kcmFnZ2luZyAubGlsLWd1aSB7XG4gIC0taG92ZXItY29sb3I6IHZhcigtLXdpZGdldC1jb2xvcik7XG59XG4ubGlsLWd1aS1kcmFnZ2luZyAqIHtcbiAgY3Vyc29yOiBldy1yZXNpemUgIWltcG9ydGFudDtcbn1cblxuLmxpbC1ndWktZHJhZ2dpbmcubGlsLWd1aS12ZXJ0aWNhbCAqIHtcbiAgY3Vyc29yOiBucy1yZXNpemUgIWltcG9ydGFudDtcbn1cblxuLmxpbC1ndWkgLnRpdGxlIHtcbiAgaGVpZ2h0OiB2YXIoLS10aXRsZS1oZWlnaHQpO1xuICBsaW5lLWhlaWdodDogY2FsYyh2YXIoLS10aXRsZS1oZWlnaHQpIC0gNHB4KTtcbiAgZm9udC13ZWlnaHQ6IDYwMDtcbiAgcGFkZGluZzogMCB2YXIoLS1wYWRkaW5nKTtcbiAgLXdlYmtpdC10YXAtaGlnaGxpZ2h0LWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBvdXRsaW5lOiBub25lO1xuICB0ZXh0LWRlY29yYXRpb24tc2tpcDogb2JqZWN0cztcbn1cbi5saWwtZ3VpIC50aXRsZTpiZWZvcmUge1xuICBmb250LWZhbWlseTogXCJsaWwtZ3VpXCI7XG4gIGNvbnRlbnQ6IFwi4pa+XCI7XG4gIHBhZGRpbmctcmlnaHQ6IDJweDtcbiAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xufVxuLmxpbC1ndWkgLnRpdGxlOmFjdGl2ZSB7XG4gIGJhY2tncm91bmQ6IHZhcigtLXRpdGxlLWJhY2tncm91bmQtY29sb3IpO1xuICBvcGFjaXR5OiAwLjc1O1xufVxuQG1lZGlhIChob3ZlcjogaG92ZXIpIHtcbiAgYm9keTpub3QoLmxpbC1ndWktZHJhZ2dpbmcpIC5saWwtZ3VpIC50aXRsZTpob3ZlciB7XG4gICAgYmFja2dyb3VuZDogdmFyKC0tdGl0bGUtYmFja2dyb3VuZC1jb2xvcik7XG4gICAgb3BhY2l0eTogMC44NTtcbiAgfVxuICAubGlsLWd1aSAudGl0bGU6Zm9jdXMge1xuICAgIHRleHQtZGVjb3JhdGlvbjogdW5kZXJsaW5lIHZhcigtLWZvY3VzLWNvbG9yKTtcbiAgfVxufVxuLmxpbC1ndWkucm9vdCA+IC50aXRsZTpmb2N1cyB7XG4gIHRleHQtZGVjb3JhdGlvbjogbm9uZSAhaW1wb3J0YW50O1xufVxuLmxpbC1ndWkuY2xvc2VkID4gLnRpdGxlOmJlZm9yZSB7XG4gIGNvbnRlbnQ6IFwi4pa4XCI7XG59XG4ubGlsLWd1aS5jbG9zZWQgPiAuY2hpbGRyZW4ge1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTdweCk7XG4gIG9wYWNpdHk6IDA7XG59XG4ubGlsLWd1aS5jbG9zZWQ6bm90KC50cmFuc2l0aW9uKSA+IC5jaGlsZHJlbiB7XG4gIGRpc3BsYXk6IG5vbmU7XG59XG4ubGlsLWd1aS50cmFuc2l0aW9uID4gLmNoaWxkcmVuIHtcbiAgdHJhbnNpdGlvbi1kdXJhdGlvbjogMzAwbXM7XG4gIHRyYW5zaXRpb24tcHJvcGVydHk6IGhlaWdodCwgb3BhY2l0eSwgdHJhbnNmb3JtO1xuICB0cmFuc2l0aW9uLXRpbWluZy1mdW5jdGlvbjogY3ViaWMtYmV6aWVyKDAuMiwgMC42LCAwLjM1LCAxKTtcbiAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG59XG4ubGlsLWd1aSAuY2hpbGRyZW46ZW1wdHk6YmVmb3JlIHtcbiAgY29udGVudDogXCJFbXB0eVwiO1xuICBwYWRkaW5nOiAwIHZhcigtLXBhZGRpbmcpO1xuICBtYXJnaW46IHZhcigtLXNwYWNpbmcpIDA7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICBoZWlnaHQ6IHZhcigtLXdpZGdldC1oZWlnaHQpO1xuICBmb250LXN0eWxlOiBpdGFsaWM7XG4gIGxpbmUtaGVpZ2h0OiB2YXIoLS13aWRnZXQtaGVpZ2h0KTtcbiAgb3BhY2l0eTogMC41O1xufVxuLmxpbC1ndWkucm9vdCA+IC5jaGlsZHJlbiA+IC5saWwtZ3VpID4gLnRpdGxlIHtcbiAgYm9yZGVyOiAwIHNvbGlkIHZhcigtLXdpZGdldC1jb2xvcik7XG4gIGJvcmRlci13aWR0aDogMXB4IDA7XG4gIHRyYW5zaXRpb246IGJvcmRlci1jb2xvciAzMDBtcztcbn1cbi5saWwtZ3VpLnJvb3QgPiAuY2hpbGRyZW4gPiAubGlsLWd1aS5jbG9zZWQgPiAudGl0bGUge1xuICBib3JkZXItYm90dG9tLWNvbG9yOiB0cmFuc3BhcmVudDtcbn1cbi5saWwtZ3VpICsgLmNvbnRyb2xsZXIge1xuICBib3JkZXItdG9wOiAxcHggc29saWQgdmFyKC0td2lkZ2V0LWNvbG9yKTtcbiAgbWFyZ2luLXRvcDogMDtcbiAgcGFkZGluZy10b3A6IHZhcigtLXNwYWNpbmcpO1xufVxuLmxpbC1ndWkgLmxpbC1ndWkgLmxpbC1ndWkgPiAudGl0bGUge1xuICBib3JkZXI6IG5vbmU7XG59XG4ubGlsLWd1aSAubGlsLWd1aSAubGlsLWd1aSA+IC5jaGlsZHJlbiB7XG4gIGJvcmRlcjogbm9uZTtcbiAgbWFyZ2luLWxlZnQ6IHZhcigtLWZvbGRlci1pbmRlbnQpO1xuICBib3JkZXItbGVmdDogMnB4IHNvbGlkIHZhcigtLXdpZGdldC1jb2xvcik7XG59XG4ubGlsLWd1aSAubGlsLWd1aSAuY29udHJvbGxlciB7XG4gIGJvcmRlcjogbm9uZTtcbn1cblxuLmxpbC1ndWkgbGFiZWwsIC5saWwtZ3VpIGlucHV0LCAubGlsLWd1aSBidXR0b24ge1xuICAtd2Via2l0LXRhcC1oaWdobGlnaHQtY29sb3I6IHRyYW5zcGFyZW50O1xufVxuLmxpbC1ndWkgaW5wdXQge1xuICBib3JkZXI6IDA7XG4gIG91dGxpbmU6IG5vbmU7XG4gIGZvbnQtZmFtaWx5OiB2YXIoLS1mb250LWZhbWlseSk7XG4gIGZvbnQtc2l6ZTogdmFyKC0taW5wdXQtZm9udC1zaXplKTtcbiAgYm9yZGVyLXJhZGl1czogdmFyKC0td2lkZ2V0LWJvcmRlci1yYWRpdXMpO1xuICBoZWlnaHQ6IHZhcigtLXdpZGdldC1oZWlnaHQpO1xuICBiYWNrZ3JvdW5kOiB2YXIoLS13aWRnZXQtY29sb3IpO1xuICBjb2xvcjogdmFyKC0tdGV4dC1jb2xvcik7XG4gIHdpZHRoOiAxMDAlO1xufVxuQG1lZGlhIChob3ZlcjogaG92ZXIpIHtcbiAgLmxpbC1ndWkgaW5wdXQ6aG92ZXIge1xuICAgIGJhY2tncm91bmQ6IHZhcigtLWhvdmVyLWNvbG9yKTtcbiAgfVxuICAubGlsLWd1aSBpbnB1dDphY3RpdmUge1xuICAgIGJhY2tncm91bmQ6IHZhcigtLWZvY3VzLWNvbG9yKTtcbiAgfVxufVxuLmxpbC1ndWkgaW5wdXQ6ZGlzYWJsZWQge1xuICBvcGFjaXR5OiAxO1xufVxuLmxpbC1ndWkgaW5wdXRbdHlwZT10ZXh0XSxcbi5saWwtZ3VpIGlucHV0W3R5cGU9bnVtYmVyXSB7XG4gIHBhZGRpbmc6IHZhcigtLXdpZGdldC1wYWRkaW5nKTtcbiAgLW1vei1hcHBlYXJhbmNlOiB0ZXh0ZmllbGQ7XG59XG4ubGlsLWd1aSBpbnB1dFt0eXBlPXRleHRdOmZvY3VzLFxuLmxpbC1ndWkgaW5wdXRbdHlwZT1udW1iZXJdOmZvY3VzIHtcbiAgYmFja2dyb3VuZDogdmFyKC0tZm9jdXMtY29sb3IpO1xufVxuLmxpbC1ndWkgaW5wdXRbdHlwZT1jaGVja2JveF0ge1xuICBhcHBlYXJhbmNlOiBub25lO1xuICB3aWR0aDogdmFyKC0tY2hlY2tib3gtc2l6ZSk7XG4gIGhlaWdodDogdmFyKC0tY2hlY2tib3gtc2l6ZSk7XG4gIGJvcmRlci1yYWRpdXM6IHZhcigtLXdpZGdldC1ib3JkZXItcmFkaXVzKTtcbiAgdGV4dC1hbGlnbjogY2VudGVyO1xuICBjdXJzb3I6IHBvaW50ZXI7XG59XG4ubGlsLWd1aSBpbnB1dFt0eXBlPWNoZWNrYm94XTpjaGVja2VkOmJlZm9yZSB7XG4gIGZvbnQtZmFtaWx5OiBcImxpbC1ndWlcIjtcbiAgY29udGVudDogXCLinJNcIjtcbiAgZm9udC1zaXplOiB2YXIoLS1jaGVja2JveC1zaXplKTtcbiAgbGluZS1oZWlnaHQ6IHZhcigtLWNoZWNrYm94LXNpemUpO1xufVxuQG1lZGlhIChob3ZlcjogaG92ZXIpIHtcbiAgLmxpbC1ndWkgaW5wdXRbdHlwZT1jaGVja2JveF06Zm9jdXMge1xuICAgIGJveC1zaGFkb3c6IGluc2V0IDAgMCAwIDFweCB2YXIoLS1mb2N1cy1jb2xvcik7XG4gIH1cbn1cbi5saWwtZ3VpIGJ1dHRvbiB7XG4gIG91dGxpbmU6IG5vbmU7XG4gIGN1cnNvcjogcG9pbnRlcjtcbiAgZm9udC1mYW1pbHk6IHZhcigtLWZvbnQtZmFtaWx5KTtcbiAgZm9udC1zaXplOiB2YXIoLS1mb250LXNpemUpO1xuICBjb2xvcjogdmFyKC0tdGV4dC1jb2xvcik7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IHZhcigtLXdpZGdldC1oZWlnaHQpO1xuICB0ZXh0LXRyYW5zZm9ybTogbm9uZTtcbiAgYmFja2dyb3VuZDogdmFyKC0td2lkZ2V0LWNvbG9yKTtcbiAgYm9yZGVyLXJhZGl1czogdmFyKC0td2lkZ2V0LWJvcmRlci1yYWRpdXMpO1xuICBib3JkZXI6IG5vbmU7XG59XG5AbWVkaWEgKGhvdmVyOiBob3Zlcikge1xuICAubGlsLWd1aSBidXR0b246aG92ZXIge1xuICAgIGJhY2tncm91bmQ6IHZhcigtLWhvdmVyLWNvbG9yKTtcbiAgfVxuICAubGlsLWd1aSBidXR0b246Zm9jdXMge1xuICAgIGJveC1zaGFkb3c6IGluc2V0IDAgMCAwIDFweCB2YXIoLS1mb2N1cy1jb2xvcik7XG4gIH1cbn1cbi5saWwtZ3VpIGJ1dHRvbjphY3RpdmUge1xuICBiYWNrZ3JvdW5kOiB2YXIoLS1mb2N1cy1jb2xvcik7XG59XG5cbkBmb250LWZhY2Uge1xuICBmb250LWZhbWlseTogXCJsaWwtZ3VpXCI7XG4gIHNyYzogdXJsKFwiZGF0YTphcHBsaWNhdGlvbi9mb250LXdvZmY7Y2hhcnNldD11dGYtODtiYXNlNjQsZDA5R1JnQUJBQUFBQUFVc0FBc0FBQUFBQ0p3QUFRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUJIVTFWQ0FBQUJDQUFBQUg0QUFBREFJbXdtWUU5VEx6SUFBQUdJQUFBQVB3QUFBR0JLcUg1U1kyMWhjQUFBQWNnQUFBRDBBQUFDcnVreXlKQm5iSGxtQUFBQ3ZBQUFBRjhBQUFDRUlacFdIMmhsWVdRQUFBTWNBQUFBSndBQUFEWmZjajJ6YUdobFlRQUFBMFFBQUFBWUFBQUFKQUM1QUhob2JYUjRBQUFEWEFBQUFCQUFBQUJNQVpBQUFHeHZZMkVBQUFOc0FBQUFGQUFBQUNnQ0VnSXliV0Y0Y0FBQUE0QUFBQUFlQUFBQUlBRWZBQkp1WVcxbEFBQURvQUFBQVNJQUFBSUs5U1VVL1hCdmMzUUFBQVRFQUFBQVpnQUFBSkNUY01jMmVKeFZqYkVPZ2pBVVJVK2hGUkJLMWRHUkwrQUxuQWlUb3lNTEV6RnBuUHovZUFzaHdTYTk3NTE3Yy9Nd3dKbWVCOWt3UGwrMGNmNSt1R1BaWHNxUHU0bnZaYWJjU1psZFo2a2Z5V25vbUZZL2VTY0txWk5XdXBLSk82a1hOM0s5dUNWb0w3aUluUHIxWDViYVhzM3RqdU1xQ3R6RXVhZ20vQUFselFnUEFBQjRuR05nWVJCbG5NREF5c0RBWU0vZ0JpVDVvTFFCQXd1REpBTURFd01yTXdOV0VKRG1tc0p3Z0NGZVhaZ2hCY2psWk1nRkN6T2lLT0lGQUI3MUJiOEFlSnkxa2pGdXdrQVFSWitEd1JBd0J0TlFSVUdLUThPZEtDQVdVaEFnS0xoSXVBc1ZTcFd6NUJia2ozZEVnWWlVSXN6cVdkcFplK1o3L3dCMW9DWW1Jb2JvaXdpTFQyV2pLbC9qc2NySGZHZy9wS2RNa3lrbEM1WnMyTEVmSFlwamNSb1B6bWU5TVdXbWszZFdiSzlPYmtXa2lrT2V0SjU1NGZXeW9Fc21kU2x0K3VSMHBDSlIzNGI2dC9UVmcxU1kzc1l2ZGY4dnVpS3JweWFEWERJU2llZ3AxN3A3NTc5R3AzcCsreTdIUEFpWTlwbVRpYmxqcnI4NXFTaWR0bGc0K2wyNUdMQ2FTOGU2clJ4TkJtc25FUnVuS2JhT09iUno3TjcyanU1dmRBallwQlhIZ0p5bE9BVnNNc2VEQVBFUDhMWW9VSGljWTJCaUFBRWZoaUFHSmdaV0JnWjdSbkZSZG5WSkVMQ1FsQlNSbEFUSk1vTFYyREs0Z2xTWXM2dWJxNXZiS3JKTFNiR3JnRW1vdkR1REpWaGUzVnpjWEZ3TkxDT0lMQi9DNEl1UTF4VG41RlBpbEJUajVGUG1CQUI0V3dvcUFIaWNZMkJrWUdBQTRzazFzUi9qK1cyK01uQXpwREJnQXlFTVFVQ1NnNEVKeEFFQXdVZ0ZIZ0I0bkdOZ1pHQmdTR0ZnZ0pNaERJd01xRUFZQUJ5SEFUSjRuR05nQUlJVU5Fd21BQUJsM0FHUmVKeGpZQUFDSVFZbEJpTUdKM3dRQUVjUUJFVjRuR05nWkdCZ0VHWmdZMkJpQUFFUXlRV0VEQXovd1h3R0FBc1BBVElBQUhpY1hkQk5Tc05BSEFYd2wzNWlBMFVRWFluTVNoZlM5R1BaQTdUN0xnSXUwM1NTcGt3ellUSXQxQk40QWsvZ0tUeUFlQ3hmdzM5alpranltemN2QXdtQVcvd2d3SFVFR0RiMzYralFRM0dYR290NzlMMjRqeENQNGdIekYvRUlyNGpFSWU3d3hoT0MzZzJUTVl5NFE3K0x1L1NIdUVkL2l2dDR3SmQ0d1B4YlBFS01YM0dJNStESkZHYVNuNHFOems4bWNiS1NSNnhkWGRoU3phT1pKR3RkYXBkNHZWUGJpNnJQK2NMN1RHWE9IdFhLbGw0YlkxWGw3RUduUHRwN1h5Mm4wMHp5S0xWSGZrSEJhNEljSjJvRDNjZ2dnV3Z0L1YvRmJEclVsRVVKaFRuLzBhelZXYk5UTnIwRW5zOGRlMXRjZUs5eFptZkIxQ1BqT21QSDRraXRtdk91YmNOcG1WVE4zb0ZKeWp6Q3ZubXJ3aEpUenF6Vmo5amlTWDkxMUZqZUFBQjRuRzNITVJLQ01CQkEwZjBnaWlLaTREVThrMFYyR1diSVpET2g0UG9XV3ZxNko1VjhJZjlOVk5RY2FEaHlvdVhNaFk0clBUY0c3andZbVhoS3E4V3orcDc2MmFOYWVZWG9tMm4zbTJkTFRWZ3NyQ2dGSjdPVG1Ja1lid0liQzZ2SUI3V21GZkFBQUE9PVwiKSBmb3JtYXQoXCJ3b2ZmXCIpO1xufWA7XG5cbmZ1bmN0aW9uIF9pbmplY3RTdHlsZXMoIGNzc0NvbnRlbnQgKSB7XG5cdGNvbnN0IGluamVjdGVkID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ3N0eWxlJyApO1xuXHRpbmplY3RlZC5pbm5lckhUTUwgPSBjc3NDb250ZW50O1xuXHRjb25zdCBiZWZvcmUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCAnaGVhZCBsaW5rW3JlbD1zdHlsZXNoZWV0XSwgaGVhZCBzdHlsZScgKTtcblx0aWYgKCBiZWZvcmUgKSB7XG5cdFx0ZG9jdW1lbnQuaGVhZC5pbnNlcnRCZWZvcmUoIGluamVjdGVkLCBiZWZvcmUgKTtcblx0fSBlbHNlIHtcblx0XHRkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKCBpbmplY3RlZCApO1xuXHR9XG59XG5cbmxldCBzdHlsZXNJbmplY3RlZCA9IGZhbHNlO1xuXG5jbGFzcyBHVUkge1xuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgcGFuZWwgdGhhdCBob2xkcyBjb250cm9sbGVycy5cblx0ICogQGV4YW1wbGVcblx0ICogbmV3IEdVSSgpO1xuXHQgKiBuZXcgR1VJKCB7IGNvbnRhaW5lcjogZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoICdjdXN0b20nICkgfSApO1xuXHQgKlxuXHQgKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMuYXV0b1BsYWNlPXRydWVdXG5cdCAqIEFkZHMgdGhlIEdVSSB0byBgZG9jdW1lbnQuYm9keWAgYW5kIGZpeGVzIGl0IHRvIHRoZSB0b3AgcmlnaHQgb2YgdGhlIHBhZ2UuXG5cdCAqXG5cdCAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IFtvcHRpb25zLmNvbnRhaW5lcl1cblx0ICogQWRkcyB0aGUgR1VJIHRvIHRoaXMgRE9NIGVsZW1lbnQuIE92ZXJyaWRlcyBgYXV0b1BsYWNlYC5cblx0ICpcblx0ICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLndpZHRoPTI0NV1cblx0ICogV2lkdGggb2YgdGhlIEdVSSBpbiBwaXhlbHMsIHVzdWFsbHkgc2V0IHdoZW4gbmFtZSBsYWJlbHMgYmVjb21lIHRvbyBsb25nLiBOb3RlIHRoYXQgeW91IGNhbiBtYWtlXG5cdCAqIG5hbWUgbGFiZWxzIHdpZGVyIGluIENTUyB3aXRoIGAubGls4oCRZ3VpIHsg4oCR4oCRbmFtZeKAkXdpZHRoOiA1NSUgfWAuXG5cdCAqXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy50aXRsZT1Db250cm9sc11cblx0ICogTmFtZSB0byBkaXNwbGF5IGluIHRoZSB0aXRsZSBiYXIuXG5cdCAqXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMuY2xvc2VGb2xkZXJzPWZhbHNlXVxuXHQgKiBQYXNzIGB0cnVlYCB0byBjbG9zZSBhbGwgZm9sZGVycyBpbiB0aGlzIEdVSSBieSBkZWZhdWx0LlxuXHQgKlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmluamVjdFN0eWxlcz10cnVlXVxuXHQgKiBJbmplY3RzIHRoZSBkZWZhdWx0IHN0eWxlc2hlZXQgaW50byB0aGUgcGFnZSBpZiB0aGlzIGlzIHRoZSBmaXJzdCBHVUkuXG5cdCAqIFBhc3MgYGZhbHNlYCB0byB1c2UgeW91ciBvd24gc3R5bGVzaGVldC5cblx0ICpcblx0ICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLnRvdWNoU3R5bGVzPXRydWVdXG5cdCAqIE1ha2VzIGNvbnRyb2xsZXJzIGxhcmdlciBvbiB0b3VjaCBkZXZpY2VzLiBQYXNzIGBmYWxzZWAgdG8gZGlzYWJsZSB0b3VjaCBzdHlsZXMuXG5cdCAqXG5cdCAqIEBwYXJhbSB7R1VJfSBbb3B0aW9ucy5wYXJlbnRdXG5cdCAqIEFkZHMgdGhpcyBHVUkgYXMgYSBjaGlsZCBpbiBhbm90aGVyIEdVSS4gVXN1YWxseSB0aGlzIGlzIGRvbmUgZm9yIHlvdSBieSBgYWRkRm9sZGVyKClgLlxuXHQgKlxuXHQgKi9cblx0Y29uc3RydWN0b3IoIHtcblx0XHRwYXJlbnQsXG5cdFx0YXV0b1BsYWNlID0gcGFyZW50ID09PSB1bmRlZmluZWQsXG5cdFx0Y29udGFpbmVyLFxuXHRcdHdpZHRoLFxuXHRcdHRpdGxlID0gJ0NvbnRyb2xzJyxcblx0XHRjbG9zZUZvbGRlcnMgPSBmYWxzZSxcblx0XHRpbmplY3RTdHlsZXMgPSB0cnVlLFxuXHRcdHRvdWNoU3R5bGVzID0gdHJ1ZVxuXHR9ID0ge30gKSB7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgR1VJIGNvbnRhaW5pbmcgdGhpcyBmb2xkZXIsIG9yIGB1bmRlZmluZWRgIGlmIHRoaXMgaXMgdGhlIHJvb3QgR1VJLlxuXHRcdCAqIEB0eXBlIHtHVUl9XG5cdFx0ICovXG5cdFx0dGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgdG9wIGxldmVsIEdVSSBjb250YWluaW5nIHRoaXMgZm9sZGVyLCBvciBgdGhpc2AgaWYgdGhpcyBpcyB0aGUgcm9vdCBHVUkuXG5cdFx0ICogQHR5cGUge0dVSX1cblx0XHQgKi9cblx0XHR0aGlzLnJvb3QgPSBwYXJlbnQgPyBwYXJlbnQucm9vdCA6IHRoaXM7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgbGlzdCBvZiBjb250cm9sbGVycyBhbmQgZm9sZGVycyBjb250YWluZWQgYnkgdGhpcyBHVUkuXG5cdFx0ICogQHR5cGUge0FycmF5PEdVSXxDb250cm9sbGVyPn1cblx0XHQgKi9cblx0XHR0aGlzLmNoaWxkcmVuID0gW107XG5cblx0XHQvKipcblx0XHQgKiBUaGUgbGlzdCBvZiBjb250cm9sbGVycyBjb250YWluZWQgYnkgdGhpcyBHVUkuXG5cdFx0ICogQHR5cGUge0FycmF5PENvbnRyb2xsZXI+fVxuXHRcdCAqL1xuXHRcdHRoaXMuY29udHJvbGxlcnMgPSBbXTtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBsaXN0IG9mIGZvbGRlcnMgY29udGFpbmVkIGJ5IHRoaXMgR1VJLlxuXHRcdCAqIEB0eXBlIHtBcnJheTxHVUk+fVxuXHRcdCAqL1xuXHRcdHRoaXMuZm9sZGVycyA9IFtdO1xuXG5cdFx0LyoqXG5cdFx0ICogVXNlZCB0byBkZXRlcm1pbmUgaWYgdGhlIEdVSSBpcyBjbG9zZWQuIFVzZSBgZ3VpLm9wZW4oKWAgb3IgYGd1aS5jbG9zZSgpYCB0byBjaGFuZ2UgdGhpcy5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKi9cblx0XHR0aGlzLl9jbG9zZWQgPSBmYWxzZTtcblxuXHRcdC8qKlxuXHRcdCAqIFVzZWQgdG8gZGV0ZXJtaW5lIGlmIHRoZSBHVUkgaXMgaGlkZGVuLiBVc2UgYGd1aS5zaG93KClgIG9yIGBndWkuaGlkZSgpYCB0byBjaGFuZ2UgdGhpcy5cblx0XHQgKiBAdHlwZSB7Ym9vbGVhbn1cblx0XHQgKi9cblx0XHR0aGlzLl9oaWRkZW4gPSBmYWxzZTtcblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBvdXRlcm1vc3QgY29udGFpbmVyIGVsZW1lbnQuXG5cdFx0ICogQHR5cGUge0hUTUxFbGVtZW50fVxuXHRcdCAqL1xuXHRcdHRoaXMuZG9tRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoICdkaXYnICk7XG5cdFx0dGhpcy5kb21FbGVtZW50LmNsYXNzTGlzdC5hZGQoICdsaWwtZ3VpJyApO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIERPTSBlbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIHRpdGxlLlxuXHRcdCAqIEB0eXBlIHtIVE1MRWxlbWVudH1cblx0XHQgKi9cblx0XHR0aGlzLiR0aXRsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoICdkaXYnICk7XG5cdFx0dGhpcy4kdGl0bGUuY2xhc3NMaXN0LmFkZCggJ3RpdGxlJyApO1xuXHRcdHRoaXMuJHRpdGxlLnNldEF0dHJpYnV0ZSggJ3JvbGUnLCAnYnV0dG9uJyApO1xuXHRcdHRoaXMuJHRpdGxlLnNldEF0dHJpYnV0ZSggJ2FyaWEtZXhwYW5kZWQnLCB0cnVlICk7XG5cdFx0dGhpcy4kdGl0bGUuc2V0QXR0cmlidXRlKCAndGFiaW5kZXgnLCAwICk7XG5cblx0XHR0aGlzLiR0aXRsZS5hZGRFdmVudExpc3RlbmVyKCAnY2xpY2snLCAoKSA9PiB0aGlzLm9wZW5BbmltYXRlZCggdGhpcy5fY2xvc2VkICkgKTtcblx0XHR0aGlzLiR0aXRsZS5hZGRFdmVudExpc3RlbmVyKCAna2V5ZG93bicsIGUgPT4ge1xuXHRcdFx0aWYgKCBlLmNvZGUgPT09ICdFbnRlcicgfHwgZS5jb2RlID09PSAnU3BhY2UnICkge1xuXHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdHRoaXMuJHRpdGxlLmNsaWNrKCk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXG5cdFx0Ly8gZW5hYmxlcyA6YWN0aXZlIHBzZXVkbyBjbGFzcyBvbiBtb2JpbGVcblx0XHR0aGlzLiR0aXRsZS5hZGRFdmVudExpc3RlbmVyKCAndG91Y2hzdGFydCcsICgpID0+IHt9LCB7IHBhc3NpdmU6IHRydWUgfSApO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIERPTSBlbGVtZW50IHRoYXQgY29udGFpbnMgY2hpbGRyZW4uXG5cdFx0ICogQHR5cGUge0hUTUxFbGVtZW50fVxuXHRcdCAqL1xuXHRcdHRoaXMuJGNoaWxkcmVuID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2RpdicgKTtcblx0XHR0aGlzLiRjaGlsZHJlbi5jbGFzc0xpc3QuYWRkKCAnY2hpbGRyZW4nICk7XG5cblx0XHR0aGlzLmRvbUVsZW1lbnQuYXBwZW5kQ2hpbGQoIHRoaXMuJHRpdGxlICk7XG5cdFx0dGhpcy5kb21FbGVtZW50LmFwcGVuZENoaWxkKCB0aGlzLiRjaGlsZHJlbiApO1xuXG5cdFx0dGhpcy50aXRsZSggdGl0bGUgKTtcblxuXHRcdGlmICggdGhpcy5wYXJlbnQgKSB7XG5cblx0XHRcdHRoaXMucGFyZW50LmNoaWxkcmVuLnB1c2goIHRoaXMgKTtcblx0XHRcdHRoaXMucGFyZW50LmZvbGRlcnMucHVzaCggdGhpcyApO1xuXG5cdFx0XHR0aGlzLnBhcmVudC4kY2hpbGRyZW4uYXBwZW5kQ2hpbGQoIHRoaXMuZG9tRWxlbWVudCApO1xuXG5cdFx0XHQvLyBTdG9wIHRoZSBjb25zdHJ1Y3RvciBlYXJseSwgZXZlcnl0aGluZyBvbndhcmQgb25seSBhcHBsaWVzIHRvIHJvb3QgR1VJJ3Ncblx0XHRcdHJldHVybjtcblxuXHRcdH1cblxuXHRcdHRoaXMuZG9tRWxlbWVudC5jbGFzc0xpc3QuYWRkKCAncm9vdCcgKTtcblxuXHRcdGlmICggdG91Y2hTdHlsZXMgKSB7XG5cdFx0XHR0aGlzLmRvbUVsZW1lbnQuY2xhc3NMaXN0LmFkZCggJ2FsbG93LXRvdWNoLXN0eWxlcycgKTtcblx0XHR9XG5cblx0XHQvLyBJbmplY3Qgc3R5bGVzaGVldCBpZiB3ZSBoYXZlbid0IGRvbmUgdGhhdCB5ZXRcblx0XHRpZiAoICFzdHlsZXNJbmplY3RlZCAmJiBpbmplY3RTdHlsZXMgKSB7XG5cdFx0XHRfaW5qZWN0U3R5bGVzKCBzdHlsZXNoZWV0ICk7XG5cdFx0XHRzdHlsZXNJbmplY3RlZCA9IHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKCBjb250YWluZXIgKSB7XG5cblx0XHRcdGNvbnRhaW5lci5hcHBlbmRDaGlsZCggdGhpcy5kb21FbGVtZW50ICk7XG5cblx0XHR9IGVsc2UgaWYgKCBhdXRvUGxhY2UgKSB7XG5cblx0XHRcdHRoaXMuZG9tRWxlbWVudC5jbGFzc0xpc3QuYWRkKCAnYXV0b1BsYWNlJyApO1xuXHRcdFx0ZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZCggdGhpcy5kb21FbGVtZW50ICk7XG5cblx0XHR9XG5cblx0XHRpZiAoIHdpZHRoICkge1xuXHRcdFx0dGhpcy5kb21FbGVtZW50LnN0eWxlLnNldFByb3BlcnR5KCAnLS13aWR0aCcsIHdpZHRoICsgJ3B4JyApO1xuXHRcdH1cblxuXHRcdHRoaXMuX2Nsb3NlRm9sZGVycyA9IGNsb3NlRm9sZGVycztcblxuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBjb250cm9sbGVyIHRvIHRoZSBHVUksIGluZmVycmluZyBjb250cm9sbGVyIHR5cGUgdXNpbmcgdGhlIGB0eXBlb2ZgIG9wZXJhdG9yLlxuXHQgKiBAZXhhbXBsZVxuXHQgKiBndWkuYWRkKCBvYmplY3QsICdwcm9wZXJ0eScgKTtcblx0ICogZ3VpLmFkZCggb2JqZWN0LCAnbnVtYmVyJywgMCwgMTAwLCAxICk7XG5cdCAqIGd1aS5hZGQoIG9iamVjdCwgJ29wdGlvbnMnLCBbIDEsIDIsIDMgXSApO1xuXHQgKlxuXHQgKiBAcGFyYW0ge29iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdGhlIGNvbnRyb2xsZXIgd2lsbCBtb2RpZnkuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSBOYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBjb250cm9sLlxuXHQgKiBAcGFyYW0ge251bWJlcnxvYmplY3R8QXJyYXl9IFskMV0gTWluaW11bSB2YWx1ZSBmb3IgbnVtYmVyIGNvbnRyb2xsZXJzLCBvciB0aGUgc2V0IG9mXG5cdCAqIHNlbGVjdGFibGUgdmFsdWVzIGZvciBhIGRyb3Bkb3duLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gW21heF0gTWF4aW11bSB2YWx1ZSBmb3IgbnVtYmVyIGNvbnRyb2xsZXJzLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gW3N0ZXBdIFN0ZXAgdmFsdWUgZm9yIG51bWJlciBjb250cm9sbGVycy5cblx0ICogQHJldHVybnMge0NvbnRyb2xsZXJ9XG5cdCAqL1xuXHRhZGQoIG9iamVjdCwgcHJvcGVydHksICQxLCBtYXgsIHN0ZXAgKSB7XG5cblx0XHRpZiAoIE9iamVjdCggJDEgKSA9PT0gJDEgKSB7XG5cblx0XHRcdHJldHVybiBuZXcgT3B0aW9uQ29udHJvbGxlciggdGhpcywgb2JqZWN0LCBwcm9wZXJ0eSwgJDEgKTtcblxuXHRcdH1cblxuXHRcdGNvbnN0IGluaXRpYWxWYWx1ZSA9IG9iamVjdFsgcHJvcGVydHkgXTtcblxuXHRcdHN3aXRjaCAoIHR5cGVvZiBpbml0aWFsVmFsdWUgKSB7XG5cblx0XHRcdGNhc2UgJ251bWJlcic6XG5cblx0XHRcdFx0cmV0dXJuIG5ldyBOdW1iZXJDb250cm9sbGVyKCB0aGlzLCBvYmplY3QsIHByb3BlcnR5LCAkMSwgbWF4LCBzdGVwICk7XG5cblx0XHRcdGNhc2UgJ2Jvb2xlYW4nOlxuXG5cdFx0XHRcdHJldHVybiBuZXcgQm9vbGVhbkNvbnRyb2xsZXIoIHRoaXMsIG9iamVjdCwgcHJvcGVydHkgKTtcblxuXHRcdFx0Y2FzZSAnc3RyaW5nJzpcblxuXHRcdFx0XHRyZXR1cm4gbmV3IFN0cmluZ0NvbnRyb2xsZXIoIHRoaXMsIG9iamVjdCwgcHJvcGVydHkgKTtcblxuXHRcdFx0Y2FzZSAnZnVuY3Rpb24nOlxuXG5cdFx0XHRcdHJldHVybiBuZXcgRnVuY3Rpb25Db250cm9sbGVyKCB0aGlzLCBvYmplY3QsIHByb3BlcnR5ICk7XG5cblx0XHR9XG5cblx0XHRjb25zb2xlLmVycm9yKCBgZ3VpLmFkZCBmYWlsZWRcblx0cHJvcGVydHk6YCwgcHJvcGVydHksIGBcblx0b2JqZWN0OmAsIG9iamVjdCwgYFxuXHR2YWx1ZTpgLCBpbml0aWFsVmFsdWUgKTtcblxuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBjb2xvciBjb250cm9sbGVyIHRvIHRoZSBHVUkuXG5cdCAqIEBleGFtcGxlXG5cdCAqIHBhcmFtcyA9IHtcblx0ICogXHRjc3NDb2xvcjogJyNmZjAwZmYnLFxuXHQgKiBcdHJnYkNvbG9yOiB7IHI6IDAsIGc6IDAuMiwgYjogMC40IH0sXG5cdCAqIFx0Y3VzdG9tUmFuZ2U6IFsgMCwgMTI3LCAyNTUgXSxcblx0ICogfTtcblx0ICpcblx0ICogZ3VpLmFkZENvbG9yKCBwYXJhbXMsICdjc3NDb2xvcicgKTtcblx0ICogZ3VpLmFkZENvbG9yKCBwYXJhbXMsICdyZ2JDb2xvcicgKTtcblx0ICogZ3VpLmFkZENvbG9yKCBwYXJhbXMsICdjdXN0b21SYW5nZScsIDI1NSApO1xuXHQgKlxuXHQgKiBAcGFyYW0ge29iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdGhlIGNvbnRyb2xsZXIgd2lsbCBtb2RpZnkuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSBOYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBjb250cm9sLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gcmdiU2NhbGUgTWF4aW11bSB2YWx1ZSBmb3IgYSBjb2xvciBjaGFubmVsIHdoZW4gdXNpbmcgYW4gUkdCIGNvbG9yLiBZb3UgbWF5XG5cdCAqIG5lZWQgdG8gc2V0IHRoaXMgdG8gMjU1IGlmIHlvdXIgY29sb3JzIGFyZSB0b28gYnJpZ2h0LlxuXHQgKiBAcmV0dXJucyB7Q29udHJvbGxlcn1cblx0ICovXG5cdGFkZENvbG9yKCBvYmplY3QsIHByb3BlcnR5LCByZ2JTY2FsZSA9IDEgKSB7XG5cdFx0cmV0dXJuIG5ldyBDb2xvckNvbnRyb2xsZXIoIHRoaXMsIG9iamVjdCwgcHJvcGVydHksIHJnYlNjYWxlICk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGZvbGRlciB0byB0aGUgR1VJLCB3aGljaCBpcyBqdXN0IGFub3RoZXIgR1VJLiBUaGlzIG1ldGhvZCByZXR1cm5zXG5cdCAqIHRoZSBuZXN0ZWQgR1VJIHNvIHlvdSBjYW4gYWRkIGNvbnRyb2xsZXJzIHRvIGl0LlxuXHQgKiBAZXhhbXBsZVxuXHQgKiBjb25zdCBmb2xkZXIgPSBndWkuYWRkRm9sZGVyKCAnUG9zaXRpb24nICk7XG5cdCAqIGZvbGRlci5hZGQoIHBvc2l0aW9uLCAneCcgKTtcblx0ICogZm9sZGVyLmFkZCggcG9zaXRpb24sICd5JyApO1xuXHQgKiBmb2xkZXIuYWRkKCBwb3NpdGlvbiwgJ3onICk7XG5cdCAqXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSB0aXRsZSBOYW1lIHRvIGRpc3BsYXkgaW4gdGhlIGZvbGRlcidzIHRpdGxlIGJhci5cblx0ICogQHJldHVybnMge0dVSX1cblx0ICovXG5cdGFkZEZvbGRlciggdGl0bGUgKSB7XG5cdFx0Y29uc3QgZm9sZGVyID0gbmV3IEdVSSggeyBwYXJlbnQ6IHRoaXMsIHRpdGxlIH0gKTtcblx0XHRpZiAoIHRoaXMucm9vdC5fY2xvc2VGb2xkZXJzICkgZm9sZGVyLmNsb3NlKCk7XG5cdFx0cmV0dXJuIGZvbGRlcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZWNhbGxzIHZhbHVlcyB0aGF0IHdlcmUgc2F2ZWQgd2l0aCBgZ3VpLnNhdmUoKWAuXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBvYmpcblx0ICogQHBhcmFtIHtib29sZWFufSByZWN1cnNpdmUgUGFzcyBmYWxzZSB0byBleGNsdWRlIGZvbGRlcnMgZGVzY2VuZGluZyBmcm9tIHRoaXMgR1VJLlxuXHQgKiBAcmV0dXJucyB7dGhpc31cblx0ICovXG5cdGxvYWQoIG9iaiwgcmVjdXJzaXZlID0gdHJ1ZSApIHtcblxuXHRcdGlmICggb2JqLmNvbnRyb2xsZXJzICkge1xuXG5cdFx0XHR0aGlzLmNvbnRyb2xsZXJzLmZvckVhY2goIGMgPT4ge1xuXG5cdFx0XHRcdGlmICggYyBpbnN0YW5jZW9mIEZ1bmN0aW9uQ29udHJvbGxlciApIHJldHVybjtcblxuXHRcdFx0XHRpZiAoIGMuX25hbWUgaW4gb2JqLmNvbnRyb2xsZXJzICkge1xuXHRcdFx0XHRcdGMubG9hZCggb2JqLmNvbnRyb2xsZXJzWyBjLl9uYW1lIF0gKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9ICk7XG5cblx0XHR9XG5cblx0XHRpZiAoIHJlY3Vyc2l2ZSAmJiBvYmouZm9sZGVycyApIHtcblxuXHRcdFx0dGhpcy5mb2xkZXJzLmZvckVhY2goIGYgPT4ge1xuXG5cdFx0XHRcdGlmICggZi5fdGl0bGUgaW4gb2JqLmZvbGRlcnMgKSB7XG5cdFx0XHRcdFx0Zi5sb2FkKCBvYmouZm9sZGVyc1sgZi5fdGl0bGUgXSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdH0gKTtcblxuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhbiBvYmplY3QgbWFwcGluZyBjb250cm9sbGVyIG5hbWVzIHRvIHZhbHVlcy4gVGhlIG9iamVjdCBjYW4gYmUgcGFzc2VkIHRvIGBndWkubG9hZCgpYCB0b1xuXHQgKiByZWNhbGwgdGhlc2UgdmFsdWVzLlxuXHQgKiBAZXhhbXBsZVxuXHQgKiB7XG5cdCAqIFx0Y29udHJvbGxlcnM6IHtcblx0ICogXHRcdHByb3AxOiAxLFxuXHQgKiBcdFx0cHJvcDI6ICd2YWx1ZScsXG5cdCAqIFx0XHQuLi5cblx0ICogXHR9LFxuXHQgKiBcdGZvbGRlcnM6IHtcblx0ICogXHRcdGZvbGRlck5hbWUxOiB7IGNvbnRyb2xsZXJzLCBmb2xkZXJzIH0sXG5cdCAqIFx0XHRmb2xkZXJOYW1lMjogeyBjb250cm9sbGVycywgZm9sZGVycyB9XG5cdCAqIFx0XHQuLi5cblx0ICogXHR9XG5cdCAqIH1cblx0ICpcblx0ICogQHBhcmFtIHtib29sZWFufSByZWN1cnNpdmUgUGFzcyBmYWxzZSB0byBleGNsdWRlIGZvbGRlcnMgZGVzY2VuZGluZyBmcm9tIHRoaXMgR1VJLlxuXHQgKiBAcmV0dXJucyB7b2JqZWN0fVxuXHQgKi9cblx0c2F2ZSggcmVjdXJzaXZlID0gdHJ1ZSApIHtcblxuXHRcdGNvbnN0IG9iaiA9IHtcblx0XHRcdGNvbnRyb2xsZXJzOiB7fSxcblx0XHRcdGZvbGRlcnM6IHt9XG5cdFx0fTtcblxuXHRcdHRoaXMuY29udHJvbGxlcnMuZm9yRWFjaCggYyA9PiB7XG5cblx0XHRcdGlmICggYyBpbnN0YW5jZW9mIEZ1bmN0aW9uQ29udHJvbGxlciApIHJldHVybjtcblxuXHRcdFx0aWYgKCBjLl9uYW1lIGluIG9iai5jb250cm9sbGVycyApIHtcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCBgQ2Fubm90IHNhdmUgR1VJIHdpdGggZHVwbGljYXRlIHByb3BlcnR5IFwiJHtjLl9uYW1lfVwiYCApO1xuXHRcdFx0fVxuXG5cdFx0XHRvYmouY29udHJvbGxlcnNbIGMuX25hbWUgXSA9IGMuc2F2ZSgpO1xuXG5cdFx0fSApO1xuXG5cdFx0aWYgKCByZWN1cnNpdmUgKSB7XG5cblx0XHRcdHRoaXMuZm9sZGVycy5mb3JFYWNoKCBmID0+IHtcblxuXHRcdFx0XHRpZiAoIGYuX3RpdGxlIGluIG9iai5mb2xkZXJzICkge1xuXHRcdFx0XHRcdHRocm93IG5ldyBFcnJvciggYENhbm5vdCBzYXZlIEdVSSB3aXRoIGR1cGxpY2F0ZSBmb2xkZXIgXCIke2YuX3RpdGxlfVwiYCApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0b2JqLmZvbGRlcnNbIGYuX3RpdGxlIF0gPSBmLnNhdmUoKTtcblxuXHRcdFx0fSApO1xuXG5cdFx0fVxuXG5cdFx0cmV0dXJuIG9iajtcblxuXHR9XG5cblx0LyoqXG5cdCAqIE9wZW5zIGEgR1VJIG9yIGZvbGRlci4gR1VJIGFuZCBmb2xkZXJzIGFyZSBvcGVuIGJ5IGRlZmF1bHQuXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gb3BlbiBQYXNzIGZhbHNlIHRvIGNsb3NlLlxuXHQgKiBAcmV0dXJucyB7dGhpc31cblx0ICogQGV4YW1wbGVcblx0ICogZ3VpLm9wZW4oKTsgLy8gb3BlblxuXHQgKiBndWkub3BlbiggZmFsc2UgKTsgLy8gY2xvc2Vcblx0ICogZ3VpLm9wZW4oIGd1aS5fY2xvc2VkICk7IC8vIHRvZ2dsZVxuXHQgKi9cblx0b3Blbiggb3BlbiA9IHRydWUgKSB7XG5cblx0XHR0aGlzLl9zZXRDbG9zZWQoICFvcGVuICk7XG5cblx0XHR0aGlzLiR0aXRsZS5zZXRBdHRyaWJ1dGUoICdhcmlhLWV4cGFuZGVkJywgIXRoaXMuX2Nsb3NlZCApO1xuXHRcdHRoaXMuZG9tRWxlbWVudC5jbGFzc0xpc3QudG9nZ2xlKCAnY2xvc2VkJywgdGhpcy5fY2xvc2VkICk7XG5cblx0XHRyZXR1cm4gdGhpcztcblxuXHR9XG5cblx0LyoqXG5cdCAqIENsb3NlcyB0aGUgR1VJLlxuXHQgKiBAcmV0dXJucyB7dGhpc31cblx0ICovXG5cdGNsb3NlKCkge1xuXHRcdHJldHVybiB0aGlzLm9wZW4oIGZhbHNlICk7XG5cdH1cblxuXHRfc2V0Q2xvc2VkKCBjbG9zZWQgKSB7XG5cdFx0aWYgKCB0aGlzLl9jbG9zZWQgPT09IGNsb3NlZCApIHJldHVybjtcblx0XHR0aGlzLl9jbG9zZWQgPSBjbG9zZWQ7XG5cdFx0dGhpcy5fY2FsbE9uT3BlbkNsb3NlKCB0aGlzICk7XG5cdH1cblxuXHQvKipcblx0ICogU2hvd3MgdGhlIEdVSSBhZnRlciBpdCdzIGJlZW4gaGlkZGVuLlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IHNob3dcblx0ICogQHJldHVybnMge3RoaXN9XG5cdCAqIEBleGFtcGxlXG5cdCAqIGd1aS5zaG93KCk7XG5cdCAqIGd1aS5zaG93KCBmYWxzZSApOyAvLyBoaWRlXG5cdCAqIGd1aS5zaG93KCBndWkuX2hpZGRlbiApOyAvLyB0b2dnbGVcblx0ICovXG5cdHNob3coIHNob3cgPSB0cnVlICkge1xuXG5cdFx0dGhpcy5faGlkZGVuID0gIXNob3c7XG5cblx0XHR0aGlzLmRvbUVsZW1lbnQuc3R5bGUuZGlzcGxheSA9IHRoaXMuX2hpZGRlbiA/ICdub25lJyA6ICcnO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cblx0fVxuXG5cdC8qKlxuXHQgKiBIaWRlcyB0aGUgR1VJLlxuXHQgKiBAcmV0dXJucyB7dGhpc31cblx0ICovXG5cdGhpZGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuc2hvdyggZmFsc2UgKTtcblx0fVxuXG5cdG9wZW5BbmltYXRlZCggb3BlbiA9IHRydWUgKSB7XG5cblx0XHQvLyBzZXQgc3RhdGUgaW1tZWRpYXRlbHlcblx0XHR0aGlzLl9zZXRDbG9zZWQoICFvcGVuICk7XG5cblx0XHR0aGlzLiR0aXRsZS5zZXRBdHRyaWJ1dGUoICdhcmlhLWV4cGFuZGVkJywgIXRoaXMuX2Nsb3NlZCApO1xuXG5cdFx0Ly8gd2FpdCBmb3IgbmV4dCBmcmFtZSB0byBtZWFzdXJlICRjaGlsZHJlblxuXHRcdHJlcXVlc3RBbmltYXRpb25GcmFtZSggKCkgPT4ge1xuXG5cdFx0XHQvLyBleHBsaWNpdGx5IHNldCBpbml0aWFsIGhlaWdodCBmb3IgdHJhbnNpdGlvblxuXHRcdFx0Y29uc3QgaW5pdGlhbEhlaWdodCA9IHRoaXMuJGNoaWxkcmVuLmNsaWVudEhlaWdodDtcblx0XHRcdHRoaXMuJGNoaWxkcmVuLnN0eWxlLmhlaWdodCA9IGluaXRpYWxIZWlnaHQgKyAncHgnO1xuXG5cdFx0XHR0aGlzLmRvbUVsZW1lbnQuY2xhc3NMaXN0LmFkZCggJ3RyYW5zaXRpb24nICk7XG5cblx0XHRcdGNvbnN0IG9uVHJhbnNpdGlvbkVuZCA9IGUgPT4ge1xuXHRcdFx0XHRpZiAoIGUudGFyZ2V0ICE9PSB0aGlzLiRjaGlsZHJlbiApIHJldHVybjtcblx0XHRcdFx0dGhpcy4kY2hpbGRyZW4uc3R5bGUuaGVpZ2h0ID0gJyc7XG5cdFx0XHRcdHRoaXMuZG9tRWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCAndHJhbnNpdGlvbicgKTtcblx0XHRcdFx0dGhpcy4kY2hpbGRyZW4ucmVtb3ZlRXZlbnRMaXN0ZW5lciggJ3RyYW5zaXRpb25lbmQnLCBvblRyYW5zaXRpb25FbmQgKTtcblx0XHRcdH07XG5cblx0XHRcdHRoaXMuJGNoaWxkcmVuLmFkZEV2ZW50TGlzdGVuZXIoICd0cmFuc2l0aW9uZW5kJywgb25UcmFuc2l0aW9uRW5kICk7XG5cblx0XHRcdC8vIHRvZG86IHRoaXMgaXMgd3JvbmcgaWYgY2hpbGRyZW4ncyBzY3JvbGxIZWlnaHQgbWFrZXMgZm9yIGEgZ3VpIHRhbGxlciB0aGFuIG1heEhlaWdodFxuXHRcdFx0Y29uc3QgdGFyZ2V0SGVpZ2h0ID0gIW9wZW4gPyAwIDogdGhpcy4kY2hpbGRyZW4uc2Nyb2xsSGVpZ2h0O1xuXG5cdFx0XHR0aGlzLmRvbUVsZW1lbnQuY2xhc3NMaXN0LnRvZ2dsZSggJ2Nsb3NlZCcsICFvcGVuICk7XG5cblx0XHRcdHJlcXVlc3RBbmltYXRpb25GcmFtZSggKCkgPT4ge1xuXHRcdFx0XHR0aGlzLiRjaGlsZHJlbi5zdHlsZS5oZWlnaHQgPSB0YXJnZXRIZWlnaHQgKyAncHgnO1xuXHRcdFx0fSApO1xuXG5cdFx0fSApO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cblx0fVxuXG5cdC8qKlxuXHQgKiBDaGFuZ2UgdGhlIHRpdGxlIG9mIHRoaXMgR1VJLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdGl0bGVcblx0ICogQHJldHVybnMge3RoaXN9XG5cdCAqL1xuXHR0aXRsZSggdGl0bGUgKSB7XG5cdFx0LyoqXG5cdFx0ICogQ3VycmVudCB0aXRsZSBvZiB0aGUgR1VJLiBVc2UgYGd1aS50aXRsZSggJ1RpdGxlJyApYCB0byBtb2RpZnkgdGhpcyB2YWx1ZS5cblx0XHQgKiBAdHlwZSB7c3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRoaXMuX3RpdGxlID0gdGl0bGU7XG5cdFx0dGhpcy4kdGl0bGUudGV4dENvbnRlbnQgPSB0aXRsZTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXNldHMgYWxsIGNvbnRyb2xsZXJzIHRvIHRoZWlyIGluaXRpYWwgdmFsdWVzLlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IHJlY3Vyc2l2ZSBQYXNzIGZhbHNlIHRvIGV4Y2x1ZGUgZm9sZGVycyBkZXNjZW5kaW5nIGZyb20gdGhpcyBHVUkuXG5cdCAqIEByZXR1cm5zIHt0aGlzfVxuXHQgKi9cblx0cmVzZXQoIHJlY3Vyc2l2ZSA9IHRydWUgKSB7XG5cdFx0Y29uc3QgY29udHJvbGxlcnMgPSByZWN1cnNpdmUgPyB0aGlzLmNvbnRyb2xsZXJzUmVjdXJzaXZlKCkgOiB0aGlzLmNvbnRyb2xsZXJzO1xuXHRcdGNvbnRyb2xsZXJzLmZvckVhY2goIGMgPT4gYy5yZXNldCgpICk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogUGFzcyBhIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuZXZlciBhIGNvbnRyb2xsZXIgaW4gdGhpcyBHVUkgY2hhbmdlcy5cblx0ICogQHBhcmFtIHtmdW5jdGlvbih7b2JqZWN0Om9iamVjdCwgcHJvcGVydHk6c3RyaW5nLCB2YWx1ZTphbnksIGNvbnRyb2xsZXI6Q29udHJvbGxlcn0pfSBjYWxsYmFja1xuXHQgKiBAcmV0dXJucyB7dGhpc31cblx0ICogQGV4YW1wbGVcblx0ICogZ3VpLm9uQ2hhbmdlKCBldmVudCA9PiB7XG5cdCAqIFx0ZXZlbnQub2JqZWN0ICAgICAvLyBvYmplY3QgdGhhdCB3YXMgbW9kaWZpZWRcblx0ICogXHRldmVudC5wcm9wZXJ0eSAgIC8vIHN0cmluZywgbmFtZSBvZiBwcm9wZXJ0eVxuXHQgKiBcdGV2ZW50LnZhbHVlICAgICAgLy8gbmV3IHZhbHVlIG9mIGNvbnRyb2xsZXJcblx0ICogXHRldmVudC5jb250cm9sbGVyIC8vIGNvbnRyb2xsZXIgdGhhdCB3YXMgbW9kaWZpZWRcblx0ICogfSApO1xuXHQgKi9cblx0b25DaGFuZ2UoIGNhbGxiYWNrICkge1xuXHRcdC8qKlxuXHRcdCAqIFVzZWQgdG8gYWNjZXNzIHRoZSBmdW5jdGlvbiBib3VuZCB0byBgb25DaGFuZ2VgIGV2ZW50cy4gRG9uJ3QgbW9kaWZ5IHRoaXMgdmFsdWVcblx0XHQgKiBkaXJlY3RseS4gVXNlIHRoZSBgZ3VpLm9uQ2hhbmdlKCBjYWxsYmFjayApYCBtZXRob2QgaW5zdGVhZC5cblx0XHQgKiBAdHlwZSB7RnVuY3Rpb259XG5cdFx0ICovXG5cdFx0dGhpcy5fb25DaGFuZ2UgPSBjYWxsYmFjaztcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdF9jYWxsT25DaGFuZ2UoIGNvbnRyb2xsZXIgKSB7XG5cblx0XHRpZiAoIHRoaXMucGFyZW50ICkge1xuXHRcdFx0dGhpcy5wYXJlbnQuX2NhbGxPbkNoYW5nZSggY29udHJvbGxlciApO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5fb25DaGFuZ2UgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHRoaXMuX29uQ2hhbmdlLmNhbGwoIHRoaXMsIHtcblx0XHRcdFx0b2JqZWN0OiBjb250cm9sbGVyLm9iamVjdCxcblx0XHRcdFx0cHJvcGVydHk6IGNvbnRyb2xsZXIucHJvcGVydHksXG5cdFx0XHRcdHZhbHVlOiBjb250cm9sbGVyLmdldFZhbHVlKCksXG5cdFx0XHRcdGNvbnRyb2xsZXJcblx0XHRcdH0gKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUGFzcyBhIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuZXZlciBhIGNvbnRyb2xsZXIgaW4gdGhpcyBHVUkgaGFzIGZpbmlzaGVkIGNoYW5naW5nLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKHtvYmplY3Q6b2JqZWN0LCBwcm9wZXJ0eTpzdHJpbmcsIHZhbHVlOmFueSwgY29udHJvbGxlcjpDb250cm9sbGVyfSl9IGNhbGxiYWNrXG5cdCAqIEByZXR1cm5zIHt0aGlzfVxuXHQgKiBAZXhhbXBsZVxuXHQgKiBndWkub25GaW5pc2hDaGFuZ2UoIGV2ZW50ID0+IHtcblx0ICogXHRldmVudC5vYmplY3QgICAgIC8vIG9iamVjdCB0aGF0IHdhcyBtb2RpZmllZFxuXHQgKiBcdGV2ZW50LnByb3BlcnR5ICAgLy8gc3RyaW5nLCBuYW1lIG9mIHByb3BlcnR5XG5cdCAqIFx0ZXZlbnQudmFsdWUgICAgICAvLyBuZXcgdmFsdWUgb2YgY29udHJvbGxlclxuXHQgKiBcdGV2ZW50LmNvbnRyb2xsZXIgLy8gY29udHJvbGxlciB0aGF0IHdhcyBtb2RpZmllZFxuXHQgKiB9ICk7XG5cdCAqL1xuXHRvbkZpbmlzaENoYW5nZSggY2FsbGJhY2sgKSB7XG5cdFx0LyoqXG5cdFx0ICogVXNlZCB0byBhY2Nlc3MgdGhlIGZ1bmN0aW9uIGJvdW5kIHRvIGBvbkZpbmlzaENoYW5nZWAgZXZlbnRzLiBEb24ndCBtb2RpZnkgdGhpcyB2YWx1ZVxuXHRcdCAqIGRpcmVjdGx5LiBVc2UgdGhlIGBndWkub25GaW5pc2hDaGFuZ2UoIGNhbGxiYWNrIClgIG1ldGhvZCBpbnN0ZWFkLlxuXHRcdCAqIEB0eXBlIHtGdW5jdGlvbn1cblx0XHQgKi9cblx0XHR0aGlzLl9vbkZpbmlzaENoYW5nZSA9IGNhbGxiYWNrO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0X2NhbGxPbkZpbmlzaENoYW5nZSggY29udHJvbGxlciApIHtcblxuXHRcdGlmICggdGhpcy5wYXJlbnQgKSB7XG5cdFx0XHR0aGlzLnBhcmVudC5fY2FsbE9uRmluaXNoQ2hhbmdlKCBjb250cm9sbGVyICk7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLl9vbkZpbmlzaENoYW5nZSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0dGhpcy5fb25GaW5pc2hDaGFuZ2UuY2FsbCggdGhpcywge1xuXHRcdFx0XHRvYmplY3Q6IGNvbnRyb2xsZXIub2JqZWN0LFxuXHRcdFx0XHRwcm9wZXJ0eTogY29udHJvbGxlci5wcm9wZXJ0eSxcblx0XHRcdFx0dmFsdWU6IGNvbnRyb2xsZXIuZ2V0VmFsdWUoKSxcblx0XHRcdFx0Y29udHJvbGxlclxuXHRcdFx0fSApO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBQYXNzIGEgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdGhpcyBHVUkgb3IgaXRzIGRlc2NlbmRhbnRzIGFyZSBvcGVuZWQgb3IgY2xvc2VkLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9uKEdVSSl9IGNhbGxiYWNrXG5cdCAqIEByZXR1cm5zIHt0aGlzfVxuXHQgKiBAZXhhbXBsZVxuXHQgKiBndWkub25PcGVuQ2xvc2UoIGNoYW5nZWRHVUkgPT4ge1xuXHQgKiBcdGNvbnNvbGUubG9nKCBjaGFuZ2VkR1VJLl9jbG9zZWQgKTtcblx0ICogfSApO1xuXHQgKi9cblx0b25PcGVuQ2xvc2UoIGNhbGxiYWNrICkge1xuXHRcdHRoaXMuX29uT3BlbkNsb3NlID0gY2FsbGJhY2s7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRfY2FsbE9uT3BlbkNsb3NlKCBjaGFuZ2VkR1VJICkge1xuXHRcdGlmICggdGhpcy5wYXJlbnQgKSB7XG5cdFx0XHR0aGlzLnBhcmVudC5fY2FsbE9uT3BlbkNsb3NlKCBjaGFuZ2VkR1VJICk7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLl9vbk9wZW5DbG9zZSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0dGhpcy5fb25PcGVuQ2xvc2UuY2FsbCggdGhpcywgY2hhbmdlZEdVSSApO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBEZXN0cm95cyBhbGwgRE9NIGVsZW1lbnRzIGFuZCBldmVudCBsaXN0ZW5lcnMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgR1VJLlxuXHQgKi9cblx0ZGVzdHJveSgpIHtcblxuXHRcdGlmICggdGhpcy5wYXJlbnQgKSB7XG5cdFx0XHR0aGlzLnBhcmVudC5jaGlsZHJlbi5zcGxpY2UoIHRoaXMucGFyZW50LmNoaWxkcmVuLmluZGV4T2YoIHRoaXMgKSwgMSApO1xuXHRcdFx0dGhpcy5wYXJlbnQuZm9sZGVycy5zcGxpY2UoIHRoaXMucGFyZW50LmZvbGRlcnMuaW5kZXhPZiggdGhpcyApLCAxICk7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmRvbUVsZW1lbnQucGFyZW50RWxlbWVudCApIHtcblx0XHRcdHRoaXMuZG9tRWxlbWVudC5wYXJlbnRFbGVtZW50LnJlbW92ZUNoaWxkKCB0aGlzLmRvbUVsZW1lbnQgKTtcblx0XHR9XG5cblx0XHRBcnJheS5mcm9tKCB0aGlzLmNoaWxkcmVuICkuZm9yRWFjaCggYyA9PiBjLmRlc3Ryb3koKSApO1xuXG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhbiBhcnJheSBvZiBjb250cm9sbGVycyBjb250YWluZWQgYnkgdGhpcyBHVUkgYW5kIGl0cyBkZXNjZW5kZW50cy5cblx0ICogQHJldHVybnMge0NvbnRyb2xsZXJbXX1cblx0ICovXG5cdGNvbnRyb2xsZXJzUmVjdXJzaXZlKCkge1xuXHRcdGxldCBjb250cm9sbGVycyA9IEFycmF5LmZyb20oIHRoaXMuY29udHJvbGxlcnMgKTtcblx0XHR0aGlzLmZvbGRlcnMuZm9yRWFjaCggZiA9PiB7XG5cdFx0XHRjb250cm9sbGVycyA9IGNvbnRyb2xsZXJzLmNvbmNhdCggZi5jb250cm9sbGVyc1JlY3Vyc2l2ZSgpICk7XG5cdFx0fSApO1xuXHRcdHJldHVybiBjb250cm9sbGVycztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGFuIGFycmF5IG9mIGZvbGRlcnMgY29udGFpbmVkIGJ5IHRoaXMgR1VJIGFuZCBpdHMgZGVzY2VuZGVudHMuXG5cdCAqIEByZXR1cm5zIHtHVUlbXX1cblx0ICovXG5cdGZvbGRlcnNSZWN1cnNpdmUoKSB7XG5cdFx0bGV0IGZvbGRlcnMgPSBBcnJheS5mcm9tKCB0aGlzLmZvbGRlcnMgKTtcblx0XHR0aGlzLmZvbGRlcnMuZm9yRWFjaCggZiA9PiB7XG5cdFx0XHRmb2xkZXJzID0gZm9sZGVycy5jb25jYXQoIGYuZm9sZGVyc1JlY3Vyc2l2ZSgpICk7XG5cdFx0fSApO1xuXHRcdHJldHVybiBmb2xkZXJzO1xuXHR9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgR1VJO1xuZXhwb3J0IHsgQm9vbGVhbkNvbnRyb2xsZXIsIENvbG9yQ29udHJvbGxlciwgQ29udHJvbGxlciwgRnVuY3Rpb25Db250cm9sbGVyLCBHVUksIE51bWJlckNvbnRyb2xsZXIsIE9wdGlvbkNvbnRyb2xsZXIsIFN0cmluZ0NvbnRyb2xsZXIgfTtcbiIsImltcG9ydCBHVUkgZnJvbSAnbGlsLWd1aSc7XHJcbmltcG9ydCBQbG90bHksIHsgdHlwZSBEYXRhLCB0eXBlIExheW91dCB9IGZyb20gJ3Bsb3RseS5qcy1kaXN0JztcclxuaW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnO1xyXG5pbXBvcnQgeyBPcmJpdENvbnRyb2xzLCBWaWV3SGVscGVyIH0gZnJvbSAndGhyZWUvZXhhbXBsZXMvanNtL0FkZG9ucyc7XHJcbmltcG9ydCBTdGF0cyBmcm9tICd0aHJlZS9leGFtcGxlcy9qc20vbGlicy9zdGF0cy5tb2R1bGUnO1xyXG5pbXBvcnQgeyB0eXBlIFNpbXVsYXRpb24gfSBmcm9tICcuLi9TaW11bGF0aW9uJztcclxuaW1wb3J0IHsgdHlwZSBTdGF0ZSB9IGZyb20gJy4uL1N0YXRlJztcclxuaW1wb3J0IHsgdHlwZSBVbml2ZXJzZSB9IGZyb20gJy4uL1VuaXZlcnNlJztcclxuaW1wb3J0IHsgdHlwZSBWaXN1YWxpemVyIH0gZnJvbSAnLi4vVmlzdWFsaXplcic7XHJcblxyXG5sZXQgYW5pbWF0aW9uSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xyXG5cclxuLyoqXHJcbiAqIENsaXBzIGEgbnVtYmVyIHRvIGEgbWluaW11bSBhbmQgbWF4aW11bSB2YWx1ZS5cclxuICogQHBhcmFtIHggbnVtYmVyIHRvIGNsaXAuXHJcbiAqIEBwYXJhbSBtaW4gbWluaW11bSB2YWx1ZS5cclxuICogQHBhcmFtIG1heCBtYXhpbXVtIHZhbHVlLlxyXG4gKiBAcmV0dXJucyBjbGlwcGVkIHZhbHVlLlxyXG4gKi9cclxuZnVuY3Rpb24gY2xpcE1pbk1heCh4OiBudW1iZXIsIG1pbjogbnVtYmVyLCBtYXg6IG51bWJlcik6IG51bWJlciB7XHJcbiAgaWYgKHggPCBtaW4pIHJldHVybiBtaW47XHJcbiAgaWYgKHggPiBtYXgpIHJldHVybiBtYXg7XHJcbiAgcmV0dXJuIHg7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDb250YWluZXIgb2JqZWN0IGZvciBib2R5IHRyYWlscyBpbiBhIDJEIHVuaXZlcnNlIGJhc2VkIGluIFBsb3RseS5cclxuICovXHJcbmNsYXNzIFBsb3RseVVuaXZlcnNlVHJhaWwge1xyXG4gIGRhdGE6IHtcclxuICAgIHg6IChudW1iZXIgfCBudWxsKVtdO1xyXG4gICAgeTogKG51bWJlciB8IG51bGwpW107XHJcbiAgICBtb2RlOiAnbWFya2Vycyc7XHJcbiAgICBtYXJrZXI6IHtcclxuICAgICAgc2l6ZTogbnVtYmVyO1xyXG4gICAgICBjb2xvcjogc3RyaW5nO1xyXG4gICAgfTtcclxuICB9ID0ge1xyXG4gICAgICB4OiBbXSxcclxuICAgICAgeTogW10sXHJcbiAgICAgIG1vZGU6ICdtYXJrZXJzJyxcclxuICAgICAgbWFya2VyOiB7XHJcbiAgICAgICAgc2l6ZTogMSxcclxuICAgICAgICBjb2xvcjogJ3doaXRlJyxcclxuICAgICAgfSxcclxuICAgIH07XHJcbiAgdHJhaWxMZW5ndGg6IG51bWJlcjtcclxuICBtYXhUcmFpbExlbmd0aDogbnVtYmVyO1xyXG4gIHRyYWlsSW5kOiBudW1iZXI7XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbnN0cnVjdG9yIGZvciBQbG90bHlVbml2ZXJzZVRyYWlsXHJcbiAgICogQHBhcmFtIG1heFRyYWlsTGVuZ3RoIG1heCBudW1iZXIgb2YgdHJhaWwgcG9pbnRzIHRvIGtlZXAuXHJcbiAgICogQHBhcmFtIGNvbG9yIGNvbG9yIG9mIHRoZSB0cmFpbC5cclxuICAgKi9cclxuICBjb25zdHJ1Y3RvcihtYXhUcmFpbExlbmd0aDogbnVtYmVyLCBjb2xvcjogc3RyaW5nKSB7XHJcbiAgICB0aGlzLmRhdGEubWFya2VyLmNvbG9yID0gY29sb3I7XHJcbiAgICB0aGlzLnRyYWlsTGVuZ3RoID0gMDtcclxuICAgIHRoaXMubWF4VHJhaWxMZW5ndGggPSBtYXhUcmFpbExlbmd0aDtcclxuICAgIHRoaXMudHJhaWxJbmQgPSAwO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQWRkIGEgdHJhaWwgcG9pbnQgdG8gdGhlIHRyYWlsIGRhdGEsIG9yIHJlcGxhY2UgYW4gZXhpc3RpbmcgdHJhaWwgcG9pbnQgaWYgdGhlIG1heCB0cmFpbCBsZW5ndGggaGFzIGJlZW4gcmVhY2hlZC5cclxuICAgKiBAcGFyYW0geCB4IHBvc2l0aW9uLlxyXG4gICAqIEBwYXJhbSB5IHkgcG9zaXRpb24uXHJcbiAgICovXHJcbiAgYWRkVHJhaWwoeDogbnVtYmVyLCB5OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnRyYWlsTGVuZ3RoIDwgdGhpcy5tYXhUcmFpbExlbmd0aCkge1xyXG4gICAgICB0aGlzLmRhdGEueC5wdXNoKHgpO1xyXG4gICAgICB0aGlzLmRhdGEueS5wdXNoKHkpO1xyXG4gICAgICB0aGlzLnRyYWlsTGVuZ3RoKys7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmRhdGEueFt0aGlzLnRyYWlsSW5kXSA9IHg7XHJcbiAgICAgIHRoaXMuZGF0YS55W3RoaXMudHJhaWxJbmRdID0geTtcclxuICAgICAgdGhpcy50cmFpbEluZCA9ICh0aGlzLnRyYWlsSW5kICsgMSkgJSB0aGlzLnRyYWlsTGVuZ3RoO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUG9wIGFsbCB0cmFpbCBwb2ludHMgZnJvbSB0aGUgdHJhaWwgZGF0YS5cclxuICAgKi9cclxuICBwb3BBbGxUcmFpbHMoKTogdm9pZCB7XHJcbiAgICB0aGlzLmRhdGEueCA9IFtdO1xyXG4gICAgdGhpcy5kYXRhLnkgPSBbXTtcclxuICAgIHRoaXMudHJhaWxMZW5ndGggPSAwO1xyXG4gICAgdGhpcy50cmFpbEluZCA9IDA7XHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogMkQgcmVhbC10aW1lIHZpc3VhbGl6ZXIgdXNpbmcgUGxvdGx5LlxyXG4gKiBAY2F0ZWdvcnkgVmlzdWFsaXplcnNcclxuICovXHJcbmV4cG9ydCBjbGFzcyBSZWFsVGltZVZpc3VhbGl6ZXIgaW1wbGVtZW50cyBWaXN1YWxpemVyIHtcclxuICBzaW11bGF0aW9uOiBTaW11bGF0aW9uO1xyXG4gIGRpdklkOiBzdHJpbmcgPSAnJztcclxuICB1bml2ZXJzZVRyYWlsczogUGxvdGx5VW5pdmVyc2VUcmFpbFtdID0gW107XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbnN0cnVjdG9yIGZvciBSZWFsVGltZVZpc3VhbGl6ZXJcclxuICAgKiBAcGFyYW0gc2ltdWxhdGlvbiBzaW11bGF0aW9uIG9iamVjdFxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKHNpbXVsYXRpb246IFNpbXVsYXRpb24pIHtcclxuICAgIHRoaXMuc2ltdWxhdGlvbiA9IHNpbXVsYXRpb247XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBZGRzIGRlZmF1bHQgY29udHJvbHMgdXNpbmcgbGlsLWd1aSB0byB0aGUgdmlzdWFsaXphdGlvbi5cclxuICAgKiBAcGFyYW0gcGFyZW50RWxlbWVudCBwYXJlbnQgZWxlbWVudCB0byBwbGFjZSB0aGUgY29udHJvbGxlciBkaXYgaW4uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhZGRDb250cm9scyhwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCkge1xyXG4gICAgY29uc3QgZ3VpID0gbmV3IEdVSSh7XHJcbiAgICAgIGNvbnRhaW5lcjogcGFyZW50RWxlbWVudCxcclxuICAgIH0pO1xyXG4gICAgZ3VpLmRvbUVsZW1lbnQuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xyXG4gICAgZ3VpLmRvbUVsZW1lbnQuc3R5bGUudG9wID0gJzAnO1xyXG4gICAgZ3VpLmRvbUVsZW1lbnQuc3R5bGUubGVmdCA9ICcwJztcclxuICAgIGd1aS5kb21FbGVtZW50LnN0eWxlLnpJbmRleCA9ICcxMDAwJztcclxuXHJcbiAgICBjb25zdCBjb25maWcgPSB0aGlzLnNpbXVsYXRpb24uY29udHJvbHM7XHJcbiAgICBndWkuYWRkKGNvbmZpZywgJ3NwZWVkJyk7XHJcbiAgICBndWkuYWRkKGNvbmZpZywgJ3Nob3dUcmFpbHMnKVxyXG4gICAgICAub25DaGFuZ2UoKHZhbHVlOiBib29sZWFuKSA9PiB7XHJcbiAgICAgICAgaWYgKHZhbHVlID09PSBmYWxzZSkge1xyXG4gICAgICAgICAgdGhpcy51bml2ZXJzZVRyYWlscy5mb3JFYWNoKCh1dCkgPT4gdXQucG9wQWxsVHJhaWxzKCkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25maWcuc2hvd1RyYWlscyA9IHZhbHVlO1xyXG4gICAgICB9KTtcclxuICAgIGNvbnN0IHNob3dVbml2ZXJzZUZvbGRlciA9IGd1aS5hZGRGb2xkZXIoJ1Nob3cgVW5pdmVyc2UnKTtcclxuICAgIHNob3dVbml2ZXJzZUZvbGRlci5vcGVuKGZhbHNlKTtcclxuICAgIHRoaXMuc2ltdWxhdGlvbi51bml2ZXJzZXMuZm9yRWFjaCgodSwgaSkgPT4ge1xyXG4gICAgICBzaG93VW5pdmVyc2VGb2xkZXJcclxuICAgICAgICAuYWRkKGNvbmZpZy5zaG93VW5pdmVyc2UsIHUubGFiZWwpXHJcbiAgICAgICAgLm9uQ2hhbmdlKCh2YWx1ZTogYm9vbGVhbikgPT4ge1xyXG4gICAgICAgICAgaWYgKHZhbHVlID09PSBmYWxzZSkge1xyXG4gICAgICAgICAgICB0aGlzLnVuaXZlcnNlVHJhaWxzW2ldLnBvcEFsbFRyYWlscygpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgY29uZmlnLnNob3dVbml2ZXJzZVt1LmxhYmVsXSA9IHZhbHVlO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTaW11bGF0ZSBhbmQgcGxheSB0aGUgdmlzdWFsaXphdGlvbi5cclxuICAgKiBAcGFyYW0gZGl2SWQgZGl2IGlkIHRvIHJlbmRlciB0aGUgdmlzdWFsaXphdGlvbiBpbi5cclxuICAgKiBAcGFyYW0gd2lkdGggd2lkdGggb2YgdGhlIHZpc3VhbGl6YXRpb24uXHJcbiAgICogQHBhcmFtIGhlaWdodCBoZWlnaHQgb2YgdGhlIHZpc3VhbGl6YXRpb24uXHJcbiAgICovXHJcbiAgc3RhcnQoZGl2SWQ6IHN0cmluZywgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmRpdklkICE9PSAnJykge1xyXG4gICAgICAvLyB0aHJvdyBuZXcgRXJyb3IoXHJcbiAgICAgIC8vICAgJ1NpbXVsYXRpb24gYWxyZWFkeSBwbGF5aW5nLiBTdG9wIHRoZSBjdXJyZW50IHBsYXl0aW1lIGJlZm9yZSBpbml0aWF0aW5nIGEgbmV3IG9uZS4nLFxyXG4gICAgICAvLyApO1xyXG4gICAgICBjb25zb2xlLmVycm9yKCdTaW11bGF0aW9uIGFscmVhZHkgcGxheWluZy4gU3RvcCB0aGUgY3VycmVudCBwbGF5dGltZSBiZWZvcmUgaW5pdGlhdGluZyBhIG5ldyBvbmUuJyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIHRoaXMuZGl2SWQgPSBkaXZJZDtcclxuICAgIGxldCBlbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZGl2SWQpO1xyXG4gICAgaWYgKGVsZW1lbnQgPT09IG51bGwpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgLy8gY29uc3Qgd2lkdGggPSBlbGVtZW50LmNsaWVudFdpZHRoO1xyXG4gICAgLy8gY29uc3QgaGVpZ2h0ID0gZWxlbWVudC5jbGllbnRIZWlnaHQ7XHJcbiAgICBsZXQgbWF4V2lkdGggPSAwO1xyXG4gICAgbGV0IG1heEhlaWdodCA9IDA7XHJcbiAgICB0aGlzLnNpbXVsYXRpb24udW5pdmVyc2VzLmZvckVhY2goKHUpID0+IHUuY3VyclN0YXRlLmJvZGllcy5mb3JFYWNoKChiKSA9PiB7XHJcbiAgICAgIG1heFdpZHRoID0gTWF0aC5tYXgobWF4V2lkdGgsIE1hdGguYWJzKGIucG9zaXRpb24ueCkpO1xyXG4gICAgICBtYXhIZWlnaHQgPSBNYXRoLm1heChtYXhIZWlnaHQsIE1hdGguYWJzKGIucG9zaXRpb24ueSkpO1xyXG4gICAgfSkpO1xyXG4gICAgY29uc3Qgc2NhbGUgPSAwLjUgKiBNYXRoLm1pbihoZWlnaHQgLyBtYXhIZWlnaHQsIHdpZHRoIC8gbWF4V2lkdGgpO1xyXG5cclxuICAgIGNvbnN0IGxheW91dDogUGFydGlhbDxMYXlvdXQ+ID0ge1xyXG4gICAgICBwYXBlcl9iZ2NvbG9yOiAnIzAwMDAwMCcsXHJcbiAgICAgIHBsb3RfYmdjb2xvcjogJyMwMDAwMDAnLFxyXG4gICAgICBmb250OiB7XHJcbiAgICAgICAgY29sb3I6ICcjYmZiZmJmJyxcclxuICAgICAgfSxcclxuICAgICAgeGF4aXM6IHtcclxuICAgICAgICBhdXRvcmFuZ2U6IGZhbHNlLFxyXG4gICAgICAgIHJhbmdlOiBbLSh3aWR0aCAvIDIpIC8gc2NhbGUsIHdpZHRoIC8gMiAvIHNjYWxlXSxcclxuICAgICAgfSxcclxuICAgICAgeWF4aXM6IHtcclxuICAgICAgICBhdXRvcmFuZ2U6IGZhbHNlLFxyXG4gICAgICAgIHJhbmdlOiBbLShoZWlnaHQgLyAyKSAvIHNjYWxlLCBoZWlnaHQgLyAyIC8gc2NhbGVdLFxyXG4gICAgICB9LFxyXG4gICAgICAvLyB1aXJldmlzaW9uOiAndHJ1ZScsXHJcbiAgICAgIHNob3dsZWdlbmQ6IGZhbHNlLFxyXG4gICAgfTtcclxuXHJcbiAgICBpZiAodGhpcy5zaW11bGF0aW9uLmNvbnRyb2xsZXIgPT09ICd1aScpIHtcclxuICAgICAgdGhpcy5hZGRDb250cm9scyhlbGVtZW50KTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgc3RhdHM6IFN0YXRzIHwgdW5kZWZpbmVkO1xyXG4gICAgaWYgKHRoaXMuc2ltdWxhdGlvbi5zaG93RGVidWdJbmZvKSB7XHJcbiAgICAgIHN0YXRzID0gbmV3IFN0YXRzKCk7XHJcbiAgICAgIHN0YXRzLmRvbS5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XHJcbiAgICAgIHN0YXRzLmRvbS5zdHlsZS5ib3R0b20gPSAnMHB4JztcclxuICAgICAgc3RhdHMuZG9tLnN0eWxlLnJlbW92ZVByb3BlcnR5KCd0b3AnKTtcclxuICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChzdGF0cy5kb20pO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGluaXRfZGF0YTogRGF0YVtdID0gdGhpcy5zaW11bGF0aW9uLnVuaXZlcnNlcy5mbGF0TWFwKFxyXG4gICAgICAodW5pOiBVbml2ZXJzZSk6IERhdGFbXSA9PiB7XHJcbiAgICAgICAgY29uc3QgY3VyclRyYWlsID0gbmV3IFBsb3RseVVuaXZlcnNlVHJhaWwoXHJcbiAgICAgICAgICB0aGlzLnNpbXVsYXRpb24uZ2V0TWF4VHJhaWxMZW5ndGgoKSxcclxuICAgICAgICAgIHR5cGVvZiB1bmkuY29sb3IgPT09ICdzdHJpbmcnID8gdW5pLmNvbG9yIDogdW5pLmNvbG9yWzBdLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgdGhpcy51bml2ZXJzZVRyYWlscy5wdXNoKGN1cnJUcmFpbCk7XHJcbiAgICAgICAgY29uc3QgY3VyckRhdGE6IERhdGEgPSB7XHJcbiAgICAgICAgICB4OiB1bmkuY3VyclN0YXRlLmJvZGllcy5tYXAoKGJvZHkpID0+IGJvZHkucG9zaXRpb24ueCksXHJcbiAgICAgICAgICB5OiB1bmkuY3VyclN0YXRlLmJvZGllcy5tYXAoKGJvZHkpID0+IGJvZHkucG9zaXRpb24ueSksXHJcbiAgICAgICAgICB0eXBlOiAnc2NhdHRlcicsXHJcbiAgICAgICAgICBtb2RlOiAnbWFya2VycycsXHJcbiAgICAgICAgICBtYXJrZXI6IHtcclxuICAgICAgICAgICAgY29sb3I6IHVuaS5jb2xvcixcclxuICAgICAgICAgICAgc2l6ZW1pbjogNixcclxuICAgICAgICAgICAgc2l6ZTogdW5pLmN1cnJTdGF0ZS5ib2RpZXMubWFwKChib2R5KSA9PiBNYXRoLm1pbigxMCwgYm9keS5tYXNzKSksXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH07XHJcbiAgICAgICAgaWYgKHRoaXMuc2ltdWxhdGlvbi5nZXRTaG93VHJhaWxzKCkpIHtcclxuICAgICAgICAgIHVuaS5jdXJyU3RhdGUuYm9kaWVzLmZvckVhY2goKGIpID0+IHtcclxuICAgICAgICAgICAgY3VyclRyYWlsLmFkZFRyYWlsKGIucG9zaXRpb24ueCwgYi5wb3NpdGlvbi55KTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgcmV0dXJuIFtjdXJyRGF0YSwgY3VyclRyYWlsLmRhdGFdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gW1xyXG4gICAgICAgICAgY3VyckRhdGEsXHJcbiAgICAgICAgICB7XHJcbiAgICAgICAgICAgIHg6IFtdLFxyXG4gICAgICAgICAgICB5OiBbXSxcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgXTtcclxuICAgICAgfSxcclxuICAgICk7XHJcblxyXG4gICAgUGxvdGx5Lm5ld1Bsb3QoZGl2SWQsIGluaXRfZGF0YSwgbGF5b3V0LCB7XHJcbiAgICAgIHNjcm9sbFpvb206IHRydWUsXHJcbiAgICAgIG1vZGVCYXJCdXR0b25zVG9SZW1vdmU6IFtcclxuICAgICAgICAnbGFzc28yZCcsXHJcbiAgICAgICAgJ3NlbGVjdDJkJyxcclxuICAgICAgICAndG9JbWFnZScsXHJcbiAgICAgICAgJ3Jlc2V0U2NhbGUyZCcsXHJcbiAgICAgIF0sXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCB0aW1lUGVyRnJhbWUgPSAxMDAwIC8gdGhpcy5zaW11bGF0aW9uLm1heEZyYW1lUmF0ZTtcclxuICAgIGlmIChhbmltYXRpb25JZCAhPT0gbnVsbCkgcmV0dXJuO1xyXG4gICAgbGV0IGxhc3RQYWludFRpbWVzdGFtcE1zID0gMDtcclxuICAgIGxldCBsYXN0U2ltVGltZXN0YW1wTXMgPSAwO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2ltdWxhdGUgYSBzdGVwIGluIHRoZSBzaW11bGF0aW9uXHJcbiAgICAgKiBAcGFyYW0gdGltZXN0YW1wTXMgY3VycmVudCB0aW1lc3RhbXAgaW4gbWlsbGlzZWNvbmRzLCBzb3VyY2VkIGZyb20gcmVxdWVzdEFuaW1hdGlvbkZyYW1lXHJcbiAgICAgKi9cclxuICAgIGNvbnN0IHN0ZXAgPSAodGltZXN0YW1wTXM6IG51bWJlcik6IHZvaWQgPT4ge1xyXG4gICAgICB0aGlzLnNpbXVsYXRpb24uc2ltdWxhdGVTdGVwKFxyXG4gICAgICAgICh0aGlzLnNpbXVsYXRpb24uY29udHJvbHMuc3BlZWRcclxuICAgICAgICAgICogTWF0aC5taW4odGltZXN0YW1wTXMgLSBsYXN0U2ltVGltZXN0YW1wTXMsIDMzLjMzKSlcclxuICAgICAgICAgIC8gMTAwMCxcclxuICAgICAgKTtcclxuICAgICAgbGFzdFNpbVRpbWVzdGFtcE1zID0gdGltZXN0YW1wTXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGFpbnQgdGhlIHZpc3VhbGl6YXRpb25cclxuICAgICAqIEBwYXJhbSB0aW1lc3RhbXBNcyBjdXJyZW50IHRpbWVzdGFtcCBpbiBtaWxsaXNlY29uZHMsIHByb3ZpZGVkIGJ5IHJlcXVlc3RBbmltYXRpb25GcmFtZVxyXG4gICAgICovXHJcbiAgICBjb25zdCBwYWludCA9ICh0aW1lc3RhbXBNczogbnVtYmVyKSA9PiB7XHJcbiAgICAgIGlmIChcclxuICAgICAgICB0aGlzLnNpbXVsYXRpb24uY29udHJvbHMuc3BlZWQgPT09IDBcclxuICAgICAgICB8fCB0aGlzLnNpbXVsYXRpb24uY29udHJvbHMucGF1c2VkXHJcbiAgICAgICkge1xyXG4gICAgICAgIGFuaW1hdGlvbklkID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHBhaW50KTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgc3RlcCh0aW1lc3RhbXBNcyk7XHJcblxyXG4gICAgICBpZiAoXHJcbiAgICAgICAgdGltZVBlckZyYW1lID4gMFxyXG4gICAgICAgICYmIHRpbWVzdGFtcE1zIC0gbGFzdFBhaW50VGltZXN0YW1wTXMgPCB0aW1lUGVyRnJhbWVcclxuICAgICAgKSB7XHJcbiAgICAgICAgYW5pbWF0aW9uSWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocGFpbnQpO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgICBsYXN0UGFpbnRUaW1lc3RhbXBNcyA9IHRpbWVzdGFtcE1zO1xyXG5cclxuICAgICAgY29uc3QgbmV3X2RhdGEgPSB0aGlzLnNpbXVsYXRpb24udW5pdmVyc2VzLmZsYXRNYXAoXHJcbiAgICAgICAgKHVuaTogVW5pdmVyc2UsIGk6IG51bWJlcik6IERhdGFbXSA9PiB7XHJcbiAgICAgICAgICBpZiAoIXRoaXMuc2ltdWxhdGlvbi5nZXRTaG93VW5pdmVyc2UodW5pLmxhYmVsKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gW1xyXG4gICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHg6IFtdLFxyXG4gICAgICAgICAgICAgICAgeTogW10sXHJcbiAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICB7fSxcclxuICAgICAgICAgICAgXTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGNvbnN0IGN1cnJEYXRhOiBEYXRhID0ge1xyXG4gICAgICAgICAgICB4OiB1bmkuY3VyclN0YXRlLmJvZGllcy5tYXAoKGJvZHkpID0+IGJvZHkucG9zaXRpb24ueCksXHJcbiAgICAgICAgICAgIHk6IHVuaS5jdXJyU3RhdGUuYm9kaWVzLm1hcCgoYm9keSkgPT4gYm9keS5wb3NpdGlvbi55KSxcclxuICAgICAgICAgICAgaG92ZXJ0ZXh0OiB1bmkuY3VyclN0YXRlLmJvZGllcy5tYXAoKGJvZHkpID0+IGJvZHkubGFiZWwpLFxyXG4gICAgICAgICAgICBtYXJrZXI6IHtcclxuICAgICAgICAgICAgICBzaXplOiB1bmkuY3VyclN0YXRlLmJvZGllcy5tYXAoKGJvZHkpID0+IE1hdGgubWluKDEwLCBib2R5Lm1hc3MpKSxcclxuICAgICAgICAgICAgICBjb2xvcjogdW5pLmNvbG9yLFxyXG4gICAgICAgICAgICAgIHNpemVtaW46IDYsXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIG1vZGU6ICdtYXJrZXJzJyxcclxuICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgbGV0IHRyYWlsRGF0YTogRGF0YSA9IHt9O1xyXG4gICAgICAgICAgaWYgKHRoaXMuc2ltdWxhdGlvbi5nZXRTaG93VHJhaWxzKCkpIHtcclxuICAgICAgICAgICAgY29uc3QgY3VyclRyYWlsID0gdGhpcy51bml2ZXJzZVRyYWlsc1tpXTtcclxuICAgICAgICAgICAgdW5pLmN1cnJTdGF0ZS5ib2RpZXMuZm9yRWFjaCgoYikgPT4ge1xyXG4gICAgICAgICAgICAgIGN1cnJUcmFpbC5hZGRUcmFpbChiLnBvc2l0aW9uLngsIGIucG9zaXRpb24ueSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB0cmFpbERhdGEgPSBjdXJyVHJhaWwuZGF0YTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHJldHVybiBbY3VyckRhdGEsIHRyYWlsRGF0YV07XHJcbiAgICAgICAgfSxcclxuICAgICAgKTtcclxuXHJcbiAgICAgIFBsb3RseS5yZWFjdChkaXZJZCwgbmV3X2RhdGEsIGxheW91dCk7XHJcbiAgICAgIGlmICh0aGlzLnNpbXVsYXRpb24uc2hvd0RlYnVnSW5mbyAmJiBzdGF0cykge1xyXG4gICAgICAgIHN0YXRzLnVwZGF0ZSgpO1xyXG4gICAgICB9XHJcbiAgICAgIGFuaW1hdGlvbklkID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHBhaW50KTtcclxuICAgIH07XHJcblxyXG4gICAgYW5pbWF0aW9uSWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocGFpbnQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU3RvcCB0aGUgc2ltdWxhdGlvbiBhbmQgdmlzdWFsaXphdGlvbi5cclxuICAgKi9cclxuICBzdG9wKCk6IHZvaWQge1xyXG4gICAgUGxvdGx5LnB1cmdlKHRoaXMuZGl2SWQpO1xyXG4gICAgdGhpcy5kaXZJZCA9ICcnO1xyXG4gICAgdGhpcy51bml2ZXJzZVRyYWlscy5mb3JFYWNoKCh1dCkgPT4ge1xyXG4gICAgICB1dC5wb3BBbGxUcmFpbHMoKTtcclxuICAgIH0pO1xyXG4gICAgdGhpcy51bml2ZXJzZVRyYWlscyA9IFtdO1xyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIENvbnRhaW5lciBvYmplY3QgZm9yIGJvZHkgdHJhaWxzIGluIGEgM0QgdW5pdmVyc2UgYmFzZWQgaW4gVGhyZWUuanMuXHJcbiAqL1xyXG5jbGFzcyBUaHJlZVVuaXZlcnNlVHJhaWwge1xyXG4gIC8qKlxyXG4gICAqIFNpbmd1bGFyIFBvaW50cyBvYmplY3QgY29udGFpbmluZyBhbGwgdHJhaWwgcG9pbnRzLlxyXG4gICAqL1xyXG4gIHRyYWlsczogVEhSRUUuUG9pbnRzO1xyXG4gIHRyYWlsSW5kOiBudW1iZXI7XHJcbiAgdHJhaWxMZW5ndGg6IG51bWJlcjtcclxuICBtYXhUcmFpbExlbmd0aDogbnVtYmVyO1xyXG5cclxuICAvKipcclxuICAgKiBDb25zdHJ1Y3RvciBmb3IgVGhyZWVVbml2ZXJzZVRyYWlsLlxyXG4gICAqIEBwYXJhbSBtYXhUcmFpbExlbmd0aCBtYXggbnVtYmVyIG9mIHRyYWlsIHBvaW50cyB0byBrZWVwLlxyXG4gICAqIEBwYXJhbSBjb2xvciBjb2xvciBvZiB0aGUgdHJhY2UgcG9pbnRzLlxyXG4gICAqIEBwYXJhbSBzY2VuZSBzY2VuZSB0byBhZGQgdHJhaWwgcG9pbnRzIG9iamVjdCB0by5cclxuICAgKiBAcGFyYW0gc2NhbGUgc2NhbGUgb2YgdGhlIHZpc3VhbGl6YXRpb25sLCB1c2VkIHRvIHNldCB0aGUgc2l6ZSBvZiB0aGUgdHJhaWwgcG9pbnQuXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBtYXhUcmFpbExlbmd0aDogbnVtYmVyLFxyXG4gICAgY29sb3I6IHN0cmluZyxcclxuICAgIHNjZW5lOiBUSFJFRS5TY2VuZSxcclxuICAgIHNjYWxlOiBudW1iZXIsXHJcbiAgKSB7XHJcbiAgICBjb25zdCBnZW9tZXRyeSA9IG5ldyBUSFJFRS5CdWZmZXJHZW9tZXRyeSgpO1xyXG4gICAgZ2VvbWV0cnkuc2V0QXR0cmlidXRlKFxyXG4gICAgICAncG9zaXRpb24nLFxyXG4gICAgICBuZXcgVEhSRUUuQnVmZmVyQXR0cmlidXRlKG5ldyBGbG9hdDMyQXJyYXkoMCksIDMpLFxyXG4gICAgKTtcclxuICAgIHRoaXMudHJhaWxzID0gbmV3IFRIUkVFLlBvaW50cyhcclxuICAgICAgZ2VvbWV0cnksXHJcbiAgICAgIG5ldyBUSFJFRS5Qb2ludHNNYXRlcmlhbCh7XHJcbiAgICAgICAgY29sb3IsXHJcbiAgICAgICAgc2l6ZTogMC4wMDUgKiBzY2FsZSxcclxuICAgICAgfSksXHJcbiAgICApO1xyXG4gICAgc2NlbmUuYWRkKHRoaXMudHJhaWxzKTtcclxuICAgIHRoaXMudHJhaWxJbmQgPSAwO1xyXG4gICAgdGhpcy50cmFpbExlbmd0aCA9IDA7XHJcbiAgICB0aGlzLm1heFRyYWlsTGVuZ3RoID0gbWF4VHJhaWxMZW5ndGg7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBZGQgYSB0cmFpbCBwb2ludCBhdCB0aGUgZ2l2ZW4gcG9zaXRpb24gdG8gdGhlIHNjZW5lLiBSZXBsYWNlIGFuIGV4aXN0aW5nIHRyYWlsIHBvaW50IGlmIHRoZSBtYXggdHJhaWwgbGVuZ3RoIGhhcyBiZWVuIHJlYWNoZWQuXHJcbiAgICogQHBhcmFtIHBvcyBwb3NpdGlvbiB0byBhZGQgdHJhY2UgcG9pbnQgYXQuXHJcbiAgICovXHJcbiAgYWRkVHJhaWwocG9zOiBUSFJFRS5WZWN0b3IzKSB7XHJcbiAgICBpZiAodGhpcy50cmFpbExlbmd0aCA8IHRoaXMubWF4VHJhaWxMZW5ndGgpIHtcclxuICAgICAgdGhpcy50cmFpbHMudmlzaWJsZSA9IHRydWU7XHJcbiAgICAgIHRoaXMudHJhaWxMZW5ndGgrKztcclxuICAgICAgY29uc3QgcG9zQXJyYXkgPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMudHJhaWxMZW5ndGggKiAzKTtcclxuICAgICAgcG9zQXJyYXkuc2V0KHRoaXMudHJhaWxzLmdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24uYXJyYXkpO1xyXG4gICAgICBwb3NBcnJheS5zZXQocG9zLnRvQXJyYXkoKSwgdGhpcy50cmFpbExlbmd0aCAqIDMgLSAzKTtcclxuICAgICAgdGhpcy50cmFpbHMuZ2VvbWV0cnkuc2V0QXR0cmlidXRlKFxyXG4gICAgICAgICdwb3NpdGlvbicsXHJcbiAgICAgICAgbmV3IFRIUkVFLkJ1ZmZlckF0dHJpYnV0ZShwb3NBcnJheSwgMyksXHJcbiAgICAgICk7XHJcbiAgICAgIHRoaXMudHJhaWxzLmdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24ubmVlZHNVcGRhdGUgPSB0cnVlO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy50cmFpbHMuZ2VvbWV0cnkuYXR0cmlidXRlcy5wb3NpdGlvbi5hcnJheS5zZXQoXHJcbiAgICAgICAgcG9zLnRvQXJyYXkoKSxcclxuICAgICAgICB0aGlzLnRyYWlsSW5kICogMyxcclxuICAgICAgKTtcclxuICAgICAgdGhpcy50cmFpbEluZCA9ICh0aGlzLnRyYWlsSW5kICsgMSkgJSB0aGlzLm1heFRyYWlsTGVuZ3RoO1xyXG4gICAgICB0aGlzLnRyYWlscy5nZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLm5lZWRzVXBkYXRlID0gdHJ1ZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFBvcCBhbGwgdHJhaWwgcG9pbnRzLlxyXG4gICAqL1xyXG4gIHBvcEFsbFRyYWlscygpOiB2b2lkIHtcclxuICAgIHRoaXMudHJhaWxzLnZpc2libGUgPSBmYWxzZTtcclxuICAgIHRoaXMudHJhaWxzLmdlb21ldHJ5LnNldEF0dHJpYnV0ZShcclxuICAgICAgJ3Bvc2l0aW9uJyxcclxuICAgICAgbmV3IFRIUkVFLkJ1ZmZlckF0dHJpYnV0ZShuZXcgRmxvYXQzMkFycmF5KDApLCAzKSxcclxuICAgICk7XHJcbiAgICB0aGlzLnRyYWlsSW5kID0gMDtcclxuICAgIHRoaXMudHJhaWxMZW5ndGggPSAwO1xyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIDNEIHJlYWwtdGltZSB2aXN1YWxpemVyIHVzaW5nIFRocmVlLmpzLlxyXG4gKiBAY2F0ZWdvcnkgVmlzdWFsaXplcnNcclxuICovXHJcbmV4cG9ydCBjbGFzcyBSZWFsVGltZVZpc3VhbGl6ZXIzRCBpbXBsZW1lbnRzIFZpc3VhbGl6ZXIge1xyXG4gIHNpbXVsYXRpb246IFNpbXVsYXRpb247XHJcbiAgc2NlbmU/OiBUSFJFRS5TY2VuZTtcclxuICB1bml2ZXJzZVRyYWlsczogVGhyZWVVbml2ZXJzZVRyYWlsW10gPSBbXTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ29uc3RydWN0b3IgZm9yIFJlYWxUaW1lVmlzdWFsaXplcjNELlxyXG4gICAqIEBwYXJhbSBzaW11bGF0aW9uIHNpbXVsYXRpb24gb2JqZWN0LlxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKHNpbXVsYXRpb246IFNpbXVsYXRpb24pIHtcclxuICAgIHRoaXMuc2ltdWxhdGlvbiA9IHNpbXVsYXRpb247XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBZGRzIGRlZmF1bHQgY29udHJvbHMgdG8gdGhlIHZpc3VhbGl6YXRpb24uXHJcbiAgICogQHBhcmFtIHBhcmVudEVsZW1lbnQgcGFyZW50IGVsZW1lbnQgdG8gcGxhY2UgdGhlIGNvbnRyb2xsZXIgZGl2IGluLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgYWRkQ29udHJvbHMocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpIHtcclxuICAgIGNvbnN0IGd1aSA9IG5ldyBHVUkoe1xyXG4gICAgICBjb250YWluZXI6IHBhcmVudEVsZW1lbnQsXHJcbiAgICB9KTtcclxuICAgIGd1aS5kb21FbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcclxuICAgIGd1aS5kb21FbGVtZW50LnN0eWxlLnRvcCA9ICcwJztcclxuICAgIGd1aS5kb21FbGVtZW50LnN0eWxlLmxlZnQgPSAnMCc7XHJcbiAgICBndWkuZG9tRWxlbWVudC5zdHlsZS56SW5kZXggPSAnMTAwMCc7XHJcblxyXG4gICAgY29uc3QgY29uZmlnID0gdGhpcy5zaW11bGF0aW9uLmNvbnRyb2xzO1xyXG4gICAgZ3VpLmFkZChjb25maWcsICdzcGVlZCcpO1xyXG4gICAgZ3VpLmFkZChjb25maWcsICdzaG93VHJhaWxzJylcclxuICAgICAgLm9uQ2hhbmdlKCh2YWx1ZTogYm9vbGVhbikgPT4ge1xyXG4gICAgICAgIGlmICh2YWx1ZSA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgIHRoaXMudW5pdmVyc2VUcmFpbHMuZm9yRWFjaCgodXQpID0+IHtcclxuICAgICAgICAgICAgdXQucG9wQWxsVHJhaWxzKCk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uZmlnLnNob3dUcmFpbHMgPSB2YWx1ZTtcclxuICAgICAgfSk7XHJcbiAgICBjb25zdCBzaG93VW5pdmVyc2VGb2xkZXIgPSBndWkuYWRkRm9sZGVyKCdTaG93IFVuaXZlcnNlJyk7XHJcbiAgICBzaG93VW5pdmVyc2VGb2xkZXIub3BlbihmYWxzZSk7XHJcbiAgICB0aGlzLnNpbXVsYXRpb24udW5pdmVyc2VzLmZvckVhY2goKHUsIGkpID0+IHtcclxuICAgICAgc2hvd1VuaXZlcnNlRm9sZGVyXHJcbiAgICAgICAgLmFkZChjb25maWcuc2hvd1VuaXZlcnNlLCB1LmxhYmVsKVxyXG4gICAgICAgIC5vbkNoYW5nZSgodmFsdWU6IGJvb2xlYW4pID0+IHtcclxuICAgICAgICAgIGlmICh2YWx1ZSA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgdGhpcy51bml2ZXJzZVRyYWlsc1tpXS5wb3BBbGxUcmFpbHMoKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGNvbmZpZy5zaG93VW5pdmVyc2VbdS5sYWJlbF0gPSB2YWx1ZTtcclxuICAgICAgICB9KTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2ltdWxhdGUgYW5kIHBsYXkgdGhlIHZpc3VhbGl6YXRpb25cclxuICAgKiBAcGFyYW0gZGl2SWQgZGl2IGlkIHRvIHJlbmRlciB0aGUgdmlzdWFsaXphdGlvbiBpblxyXG4gICAqIEBwYXJhbSB3aWR0aCB3aWR0aCBvZiB0aGUgdmlzdWFsaXphdGlvbi5cclxuICAgKiBAcGFyYW0gaGVpZ2h0IGhlaWdodCBvZiB0aGUgdmlzdWFsaXphdGlvbi5cclxuICAgKi9cclxuICBzdGFydChkaXZJZDogc3RyaW5nLCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcik6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuc2NlbmUgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAvLyB0aHJvdyBuZXcgRXJyb3IoXHJcbiAgICAgIC8vICAgJ1NpbXVsYXRpb24gYWxyZWFkeSBwbGF5aW5nLiBTdG9wIHRoZSBjdXJyZW50IHBsYXl0aW1lIGJlZm9yZSBpbml0aWF0aW5nIGEgbmV3IG9uZS4nLFxyXG4gICAgICAvLyApO1xyXG4gICAgICBjb25zb2xlLmVycm9yKCdTaW11bGF0aW9uIGFscmVhZHkgcGxheWluZy4gU3RvcCB0aGUgY3VycmVudCBwbGF5dGltZSBiZWZvcmUgaW5pdGlhdGluZyBhIG5ldyBvbmUuJyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGxldCBlbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZGl2SWQpO1xyXG4gICAgaWYgKGVsZW1lbnQgPT09IG51bGwpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgZWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9ICdyZWxhdGl2ZSc7XHJcbiAgICAvLyBjb25zdCB3aWR0aCA9IGVsZW1lbnQuY2xpZW50V2lkdGg7XHJcbiAgICAvLyBjb25zdCBoZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodDtcclxuICAgIGxldCBtYXhXaWR0aCA9IDA7XHJcbiAgICBsZXQgbWF4SGVpZ2h0ID0gMDtcclxuICAgIHRoaXMuc2ltdWxhdGlvbi51bml2ZXJzZXMuZm9yRWFjaCgodSkgPT4gdS5jdXJyU3RhdGUuYm9kaWVzLmZvckVhY2goKGIpID0+IHtcclxuICAgICAgbWF4V2lkdGggPSBNYXRoLm1heChtYXhXaWR0aCwgTWF0aC5hYnMoYi5wb3NpdGlvbi54KSk7XHJcbiAgICAgIG1heEhlaWdodCA9IE1hdGgubWF4KG1heEhlaWdodCwgTWF0aC5hYnMoYi5wb3NpdGlvbi55KSk7XHJcbiAgICB9KSk7XHJcbiAgICBjb25zdCBzY2FsZSA9IDAuNSAqIE1hdGgubWluKGhlaWdodCAvIG1heEhlaWdodCwgd2lkdGggLyBtYXhXaWR0aCk7XHJcblxyXG4gICAgdGhpcy5zY2VuZSA9IG5ldyBUSFJFRS5TY2VuZSgpO1xyXG5cclxuICAgIGNvbnN0IGNhbWVyYSA9IG5ldyBUSFJFRS5PcnRob2dyYXBoaWNDYW1lcmEoXHJcbiAgICAgIHdpZHRoIC8gLTIsXHJcbiAgICAgIHdpZHRoIC8gMixcclxuICAgICAgaGVpZ2h0IC8gMixcclxuICAgICAgaGVpZ2h0IC8gLTIsXHJcbiAgICAgIDAsXHJcbiAgICAgIDEwMDAwMDAwMDAwLFxyXG4gICAgKTtcclxuICAgIGNhbWVyYS5wb3NpdGlvbi5zZXQoMCwgMCwgTWF0aC5tYXgod2lkdGgsIGhlaWdodCkpO1xyXG5cclxuICAgIGNvbnN0IHJlbmRlcmVyID0gbmV3IFRIUkVFLldlYkdMUmVuZGVyZXIoKTtcclxuICAgIHJlbmRlcmVyLnNldFNpemUod2lkdGgsIGhlaWdodCk7XHJcbiAgICByZW5kZXJlci5hdXRvQ2xlYXIgPSBmYWxzZTtcclxuICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQocmVuZGVyZXIuZG9tRWxlbWVudCk7XHJcblxyXG4gICAgbGV0IHN0YXRzOiBTdGF0cyB8IHVuZGVmaW5lZDtcclxuICAgIGlmICh0aGlzLnNpbXVsYXRpb24uc2hvd0RlYnVnSW5mbykge1xyXG4gICAgICBzdGF0cyA9IG5ldyBTdGF0cygpO1xyXG4gICAgICBzdGF0cy5kb20uc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xyXG4gICAgICBzdGF0cy5kb20uc3R5bGUucmlnaHQgPSAnMHB4JztcclxuICAgICAgc3RhdHMuZG9tLnN0eWxlLnJlbW92ZVByb3BlcnR5KCdsZWZ0Jyk7XHJcbiAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoc3RhdHMuZG9tKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5zaW11bGF0aW9uLmNvbnRyb2xsZXIgPT09ICd1aScpIHtcclxuICAgICAgdGhpcy5hZGRDb250cm9scyhlbGVtZW50KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBjb25zdCBlYXJ0aERpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG4gICAgLy8gZWFydGhEaXYuY2xhc3NOYW1lID0gJ2xhYmVsJztcclxuICAgIC8vIGVhcnRoRGl2LnRleHRDb250ZW50ID0gJ0VhcnRoaGdramZkZ2hramZnaCc7XHJcbiAgICAvLyBlYXJ0aERpdi5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAndHJhbnNwYXJlbnQnO1xyXG4gICAgLy8gZWFydGhEaXYuc3R5bGUuY29sb3IgPSAnd2hpdGUnO1xyXG4gICAgLy8gZWFydGhEaXYuc3R5bGUuZm9udEZhbWlseSA9ICdzYW5zLXNlcmlmJztcclxuICAgIC8vIGVhcnRoRGl2LnN0eWxlLmJhY2tncm91bmQgPSAncmdiYSgwLCAwLCAwLCAwLjYpJztcclxuXHJcbiAgICAvLyBjb25zdCBlYXJ0aExhYmVsID0gbmV3IENTUzJET2JqZWN0KGVhcnRoRGl2KTtcclxuICAgIC8vIGVhcnRoTGFiZWwucG9zaXRpb24uc2V0KDAsIDAsIDApO1xyXG4gICAgLy8gZWFydGhMYWJlbC5jZW50ZXIuc2V0KDAsIDEpO1xyXG4gICAgLy8gLy8gYXJyWzBdLmFkZChlYXJ0aExhYmVsKTtcclxuICAgIC8vIGVhcnRoTGFiZWwubGF5ZXJzLnNldCgwKTtcclxuICAgIC8vIGNvbnN0IGxhYmVsUmVuZGVyZXIgPSBuZXcgQ1NTMkRSZW5kZXJlcigpO1xyXG4gICAgLy8gbGFiZWxSZW5kZXJlci5zZXRTaXplKHdpZHRoLCBoZWlnaHQpO1xyXG4gICAgLy8gbGFiZWxSZW5kZXJlci5kb21FbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcclxuICAgIC8vIGxhYmVsUmVuZGVyZXIuZG9tRWxlbWVudC5zdHlsZS50b3AgPSAnMHB4JztcclxuICAgIC8vIGVsZW1lbnQuYXBwZW5kQ2hpbGQobGFiZWxSZW5kZXJlci5kb21FbGVtZW50KTtcclxuXHJcbiAgICBjb25zdCBvcmJpdENvbnRyb2xzID0gbmV3IE9yYml0Q29udHJvbHMoY2FtZXJhLCByZW5kZXJlci5kb21FbGVtZW50KTtcclxuICAgIG9yYml0Q29udHJvbHMubGlzdGVuVG9LZXlFdmVudHMod2luZG93KTtcclxuICAgIG9yYml0Q29udHJvbHMudXBkYXRlKCk7XHJcblxyXG4gICAgY29uc3QgYXhlc0hlbHBlciA9IG5ldyBUSFJFRS5BeGVzSGVscGVyKHdpZHRoKTtcclxuICAgIHRoaXMuc2NlbmUuYWRkKGF4ZXNIZWxwZXIpO1xyXG4gICAgY29uc3Qgdmlld0hlbHBlciA9IG5ldyBWaWV3SGVscGVyKGNhbWVyYSwgcmVuZGVyZXIuZG9tRWxlbWVudCk7XHJcblxyXG4gICAgLy8gdmFyIG06IE1hcDxzdHJpbmcsIFRIUkVFLkxpbmVTZWdtZW50cz4gPSBuZXcgTWFwKCk7XHJcbiAgICBsZXQgYXJyOiBUSFJFRS5MaW5lU2VnbWVudHNbXSA9IFtdO1xyXG5cclxuICAgIHRoaXMuc2ltdWxhdGlvbi51bml2ZXJzZXMuZm9yRWFjaCgodSkgPT4ge1xyXG4gICAgICB0aGlzLnVuaXZlcnNlVHJhaWxzLnB1c2goXHJcbiAgICAgICAgbmV3IFRocmVlVW5pdmVyc2VUcmFpbChcclxuICAgICAgICAgIHRoaXMuc2ltdWxhdGlvbi5tYXhUcmFpbExlbmd0aCxcclxuICAgICAgICAgIHR5cGVvZiB1LmNvbG9yID09PSAnc3RyaW5nJyA/IHUuY29sb3IgOiB1LmNvbG9yWzBdLFxyXG4gICAgICAgICAgdGhpcy5zY2VuZSEsXHJcbiAgICAgICAgICBzY2FsZSxcclxuICAgICAgICApLFxyXG4gICAgICApO1xyXG4gICAgICB1LmN1cnJTdGF0ZS5ib2RpZXMuZm9yRWFjaCgoYikgPT4ge1xyXG4gICAgICAgIGNvbnN0IHNwaCA9IG5ldyBUSFJFRS5TcGhlcmVHZW9tZXRyeShcclxuICAgICAgICAgIGNsaXBNaW5NYXgoTWF0aC5sb2cyKGIubWFzcykgLSA3MCwgMTAsIDQwKSxcclxuICAgICAgICAgIDgsXHJcbiAgICAgICAgICA4LFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgY29uc3QgY3VyciA9IG5ldyBUSFJFRS5XaXJlZnJhbWVHZW9tZXRyeShzcGgpO1xyXG4gICAgICAgIGNvbnN0IGxpbmUgPSBuZXcgVEhSRUUuTGluZVNlZ21lbnRzKFxyXG4gICAgICAgICAgY3VycixcclxuICAgICAgICAgIG5ldyBUSFJFRS5MaW5lQmFzaWNNYXRlcmlhbCh7XHJcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcclxuICAgICAgICAgICAgY29sb3I6IG5ldyBUSFJFRS5Db2xvcih1LmNvbG9yKSxcclxuICAgICAgICAgIH0pLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgdGhpcy5zY2VuZSEuYWRkKGxpbmUpO1xyXG4gICAgICAgIGxpbmUucG9zaXRpb24uY29weShiLnBvc2l0aW9uLmNsb25lKClcclxuICAgICAgICAgIC5tdWx0aXBseVNjYWxhcihzY2FsZSkpO1xyXG4gICAgICAgIC8vIG0uc2V0KHUubGFiZWwgKyBcIiBcIiArIGIubGFiZWwsIGxpbmUpO1xyXG4gICAgICAgIGFyci5wdXNoKGxpbmUpO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gICAgLy8gYXJyWzBdLmFkZChlYXJ0aExhYmVsKVxyXG5cclxuICAgIGNvbnN0IHRpbWVQZXJGcmFtZSA9IDEwMDAgLyB0aGlzLnNpbXVsYXRpb24ubWF4RnJhbWVSYXRlO1xyXG4gICAgbGV0IGxhc3RTaW1UaW1lc3RhbXBNcyA9IHBlcmZvcm1hbmNlLm5vdygpO1xyXG4gICAgbGV0IGxhc3RQYWludCA9IHBlcmZvcm1hbmNlLm5vdygpO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2ltdWxhdGUgYSBzdGVwIGluIHRoZSBzaW11bGF0aW9uXHJcbiAgICAgKiBAcGFyYW0gdGltZXN0YW1wTXMgY3VycmVudCB0aW1lc3RhbXAgaW4gbWlsbGlzZWNvbmRzLCBzb3VyY2VkIGZyb20gcmVxdWVzdEFuaW1hdGlvbkZyYW1lXHJcbiAgICAgKi9cclxuICAgIGNvbnN0IHN0ZXAgPSAodGltZXN0YW1wTXM6IG51bWJlcikgPT4ge1xyXG4gICAgICB0aGlzLnNpbXVsYXRpb24uc2ltdWxhdGVTdGVwKFxyXG4gICAgICAgICh0aGlzLnNpbXVsYXRpb24uY29udHJvbHMuc3BlZWRcclxuICAgICAgICAgICogTWF0aC5taW4odGltZXN0YW1wTXMgLSBsYXN0U2ltVGltZXN0YW1wTXMsIDE2LjY3KSlcclxuICAgICAgICAgIC8gMTAwMCxcclxuICAgICAgKTtcclxuICAgICAgbGFzdFNpbVRpbWVzdGFtcE1zID0gdGltZXN0YW1wTXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGFpbnQgdGhlIHZpc3VhbGl6YXRpb25cclxuICAgICAqIEBwYXJhbSB0aW1lc3RhbXBNcyBjdXJyZW50IHRpbWVzdGFtcCBpbiBtaWxsaXNlY29uZHMsIHByb3ZpZGVkIGJ5IHJlcXVlc3RBbmltYXRpb25GcmFtZVxyXG4gICAgICovXHJcbiAgICBjb25zdCBwYWludCA9ICh0aW1lc3RhbXBNczogbnVtYmVyKSA9PiB7XHJcbiAgICAgIGlmIChcclxuICAgICAgICB0aGlzLnNpbXVsYXRpb24uY29udHJvbHMuc3BlZWQgPT09IDBcclxuICAgICAgICB8fCB0aGlzLnNpbXVsYXRpb24uY29udHJvbHMucGF1c2VkXHJcbiAgICAgICkge1xyXG4gICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZShwYWludCk7XHJcbiAgICAgICAgcmVuZGVyZXIuY2xlYXIoKTtcclxuICAgICAgICByZW5kZXJlci5yZW5kZXIodGhpcy5zY2VuZSEsIGNhbWVyYSk7XHJcbiAgICAgICAgdmlld0hlbHBlci5yZW5kZXIocmVuZGVyZXIpO1xyXG4gICAgICAgIC8vIGxhYmVsUmVuZGVyZXIucmVuZGVyKHNjZW5lLCBjYW1lcmEpO1xyXG4gICAgICAgIG9yYml0Q29udHJvbHMudXBkYXRlKCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIHN0ZXAodGltZXN0YW1wTXMpO1xyXG5cclxuICAgICAgaWYgKHRpbWVQZXJGcmFtZSA+IDAgJiYgdGltZXN0YW1wTXMgLSBsYXN0UGFpbnQgPCB0aW1lUGVyRnJhbWUpIHtcclxuICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocGFpbnQpO1xyXG4gICAgICAgIHJlbmRlcmVyLmNsZWFyKCk7XHJcbiAgICAgICAgcmVuZGVyZXIucmVuZGVyKHRoaXMuc2NlbmUhLCBjYW1lcmEpO1xyXG4gICAgICAgIHZpZXdIZWxwZXIucmVuZGVyKHJlbmRlcmVyKTtcclxuICAgICAgICAvLyBsYWJlbFJlbmRlcmVyLnJlbmRlcihzY2VuZSwgY2FtZXJhKTtcclxuICAgICAgICBvcmJpdENvbnRyb2xzLnVwZGF0ZSgpO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgbGFzdFBhaW50ID0gdGltZXN0YW1wTXM7XHJcbiAgICAgIGlmICh0aGlzLnNpbXVsYXRpb24uc2hvd0RlYnVnSW5mbyAmJiBzdGF0cykge1xyXG4gICAgICAgIHN0YXRzLnVwZGF0ZSgpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBsZXQgaW5kID0gMDtcclxuICAgICAgdGhpcy5zaW11bGF0aW9uLnVuaXZlcnNlcy5mb3JFYWNoKCh1LCBpKSA9PiB7XHJcbiAgICAgICAgaWYgKHRoaXMuc2ltdWxhdGlvbi5jb250cm9scy5zaG93VW5pdmVyc2VbdS5sYWJlbF0pIHtcclxuICAgICAgICAgIHUuY3VyclN0YXRlLmJvZGllcy5mb3JFYWNoKChiKSA9PiB7XHJcbiAgICAgICAgICAgIGFycltpbmRdLnZpc2libGUgPSB0cnVlO1xyXG4gICAgICAgICAgICBhcnJbaW5kXS5wb3NpdGlvbi5jb3B5KGIucG9zaXRpb24uY2xvbmUoKVxyXG4gICAgICAgICAgICAgIC5tdWx0aXBseVNjYWxhcihzY2FsZSkpO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5zaW11bGF0aW9uLmNvbnRyb2xzLnNob3dUcmFpbHMpIHtcclxuICAgICAgICAgICAgICB0aGlzLnVuaXZlcnNlVHJhaWxzW2ldLmFkZFRyYWlsKGFycltpbmRdLnBvc2l0aW9uKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpbmQrKztcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB1LmN1cnJTdGF0ZS5ib2RpZXMuZm9yRWFjaCgoYikgPT4ge1xyXG4gICAgICAgICAgICBhcnJbaW5kXS52aXNpYmxlID0gZmFsc2U7XHJcbiAgICAgICAgICAgIGluZCsrO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHBhaW50KTtcclxuICAgICAgcmVuZGVyZXIuY2xlYXIoKTtcclxuICAgICAgcmVuZGVyZXIucmVuZGVyKHRoaXMuc2NlbmUhLCBjYW1lcmEpO1xyXG4gICAgICB2aWV3SGVscGVyLnJlbmRlcihyZW5kZXJlcik7XHJcbiAgICAgIC8vIGxhYmVsUmVuZGVyZXIucmVuZGVyKHNjZW5lLCBjYW1lcmEpO1xyXG4gICAgICBvcmJpdENvbnRyb2xzLnVwZGF0ZSgpO1xyXG4gICAgfTtcclxuXHJcbiAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocGFpbnQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU3RvcCB0aGUgc2ltdWxhdGlvbiBhbmQgdmlzdWFsaXphdGlvbi5cclxuICAgKi9cclxuICBzdG9wKCk6IHZvaWQge1xyXG4gICAgdGhpcy5zY2VuZT8uY2xlYXIoKTtcclxuICAgIHRoaXMuc2NlbmUgPSB1bmRlZmluZWQ7XHJcbiAgICB0aGlzLnVuaXZlcnNlVHJhaWxzLmZvckVhY2goKHV0KSA9PiB7XHJcbiAgICAgIHV0LnBvcEFsbFRyYWlscygpO1xyXG4gICAgfSk7XHJcbiAgICB0aGlzLnVuaXZlcnNlVHJhaWxzID0gW107XHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogMkQgcmVjb3JkaW5nIHZpc3VhbGl6ZXIgdXNpbmcgUGxvdGx5LlxyXG4gKiBAY2F0ZWdvcnkgVmlzdWFsaXplcnNcclxuICovXHJcbmV4cG9ydCBjbGFzcyBSZWNvcmRpbmdWaXN1YWxpemVyIGltcGxlbWVudHMgVmlzdWFsaXplciB7XHJcbiAgc2ltdWxhdGlvbjogU2ltdWxhdGlvbjtcclxuICBkaXZJZDogc3RyaW5nID0gJyc7XHJcbiAgdW5pdmVyc2VUcmFpbHM6IFBsb3RseVVuaXZlcnNlVHJhaWxbXSA9IFtdO1xyXG5cclxuICAvKipcclxuICAgKiBDb25zdHJ1Y3RvciBmb3IgUmVhbFRpbWVWaXN1YWxpemVyXHJcbiAgICogQHBhcmFtIHNpbXVsYXRpb24gc2ltdWxhdGlvbiBvYmplY3RcclxuICAgKi9cclxuICBjb25zdHJ1Y3RvcihzaW11bGF0aW9uOiBTaW11bGF0aW9uKSB7XHJcbiAgICB0aGlzLnNpbXVsYXRpb24gPSBzaW11bGF0aW9uO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQWRkcyBkZWZhdWx0IGNvbnRyb2xzIHVzaW5nIGxpbC1ndWkgdG8gdGhlIHZpc3VhbGl6YXRpb24uXHJcbiAgICogQHBhcmFtIHBhcmVudEVsZW1lbnQgcGFyZW50IGVsZW1lbnQgdG8gcGxhY2UgdGhlIGNvbnRyb2xsZXIgZGl2IGluLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgYWRkQ29udHJvbHMocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcclxuICAgIGNvbnN0IGd1aSA9IG5ldyBHVUkoe1xyXG4gICAgICBjb250YWluZXI6IHBhcmVudEVsZW1lbnQsXHJcbiAgICB9KTtcclxuICAgIGd1aS5kb21FbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcclxuICAgIGd1aS5kb21FbGVtZW50LnN0eWxlLnRvcCA9ICcwJztcclxuICAgIGd1aS5kb21FbGVtZW50LnN0eWxlLmxlZnQgPSAnMCc7XHJcbiAgICBndWkuZG9tRWxlbWVudC5zdHlsZS56SW5kZXggPSAnMTAwMCc7XHJcblxyXG4gICAgY29uc3QgY29uZmlnID0gdGhpcy5zaW11bGF0aW9uLmNvbnRyb2xzO1xyXG4gICAgZ3VpLmFkZChjb25maWcsICdzcGVlZCcpO1xyXG4gICAgZ3VpLmFkZChjb25maWcsICdzaG93VHJhaWxzJylcclxuICAgICAgLm9uQ2hhbmdlKCh2YWx1ZTogYm9vbGVhbikgPT4ge1xyXG4gICAgICAgIGlmICh2YWx1ZSA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgIHRoaXMudW5pdmVyc2VUcmFpbHMuZm9yRWFjaCgodXQpID0+IHV0LnBvcEFsbFRyYWlscygpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uZmlnLnNob3dUcmFpbHMgPSB2YWx1ZTtcclxuICAgICAgfSk7XHJcbiAgICBjb25zdCBzaG93VW5pdmVyc2VGb2xkZXIgPSBndWkuYWRkRm9sZGVyKCdTaG93IFVuaXZlcnNlJyk7XHJcbiAgICBzaG93VW5pdmVyc2VGb2xkZXIub3BlbihmYWxzZSk7XHJcbiAgICB0aGlzLnNpbXVsYXRpb24udW5pdmVyc2VzLmZvckVhY2goKHUsIGkpID0+IHtcclxuICAgICAgc2hvd1VuaXZlcnNlRm9sZGVyXHJcbiAgICAgICAgLmFkZChjb25maWcuc2hvd1VuaXZlcnNlLCB1LmxhYmVsKVxyXG4gICAgICAgIC5vbkNoYW5nZSgodmFsdWU6IGJvb2xlYW4pID0+IHtcclxuICAgICAgICAgIGlmICh2YWx1ZSA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgdGhpcy51bml2ZXJzZVRyYWlsc1tpXS5wb3BBbGxUcmFpbHMoKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGNvbmZpZy5zaG93VW5pdmVyc2VbdS5sYWJlbF0gPSB2YWx1ZTtcclxuICAgICAgICB9KTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2ltdWxhdGUgYW5kIHBsYXkgdGhlIHZpc3VhbGl6YXRpb24uXHJcbiAgICogQHBhcmFtIGRpdklkIGRpdiBpZCB0byByZW5kZXIgdGhlIHZpc3VhbGl6YXRpb24gaW4uXHJcbiAgICogQHBhcmFtIHdpZHRoIHdpZHRoIG9mIHRoZSB2aXN1YWxpemF0aW9uLlxyXG4gICAqIEBwYXJhbSBoZWlnaHQgaGVpZ2h0IG9mIHRoZSB2aXN1YWxpemF0aW9uLlxyXG4gICAqIEBwYXJhbSByZWNvcmRGb3IgbnVtYmVyIG9mIHNlY29uZHMgdG8gcmVjb3JkIGZvci4uXHJcbiAgICovXHJcbiAgc3RhcnQoZGl2SWQ6IHN0cmluZywgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIHJlY29yZEZvcjogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5kaXZJZCAhPT0gJycpIHtcclxuICAgICAgLy8gdGhyb3cgbmV3IEVycm9yKFxyXG4gICAgICAvLyAgICdTaW11bGF0aW9uIGFscmVhZHkgcGxheWluZy4gU3RvcCB0aGUgY3VycmVudCBwbGF5dGltZSBiZWZvcmUgaW5pdGlhdGluZyBhIG5ldyBvbmUuJyxcclxuICAgICAgLy8gKTtcclxuICAgICAgY29uc29sZS5lcnJvcignU2ltdWxhdGlvbiBhbHJlYWR5IHBsYXlpbmcuIFN0b3AgdGhlIGN1cnJlbnQgcGxheXRpbWUgYmVmb3JlIGluaXRpYXRpbmcgYSBuZXcgb25lLicpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLmRpdklkID0gZGl2SWQ7XHJcbiAgICBsZXQgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGRpdklkKTtcclxuICAgIGlmIChlbGVtZW50ID09PSBudWxsKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIC8vIGNvbnN0IHdpZHRoID0gZWxlbWVudC5jbGllbnRXaWR0aDtcclxuICAgIC8vIGNvbnN0IGhlaWdodCA9IGVsZW1lbnQuY2xpZW50SGVpZ2h0O1xyXG4gICAgbGV0IG1heFdpZHRoID0gMDtcclxuICAgIGxldCBtYXhIZWlnaHQgPSAwO1xyXG4gICAgdGhpcy5zaW11bGF0aW9uLnVuaXZlcnNlcy5mb3JFYWNoKCh1KSA9PiB1LmN1cnJTdGF0ZS5ib2RpZXMuZm9yRWFjaCgoYikgPT4ge1xyXG4gICAgICBtYXhXaWR0aCA9IE1hdGgubWF4KG1heFdpZHRoLCBNYXRoLmFicyhiLnBvc2l0aW9uLngpKTtcclxuICAgICAgbWF4SGVpZ2h0ID0gTWF0aC5tYXgobWF4SGVpZ2h0LCBNYXRoLmFicyhiLnBvc2l0aW9uLnkpKTtcclxuICAgIH0pKTtcclxuICAgIGNvbnN0IHNjYWxlID0gMC41ICogTWF0aC5taW4oaGVpZ2h0IC8gbWF4SGVpZ2h0LCB3aWR0aCAvIG1heFdpZHRoKTtcclxuXHJcbiAgICBjb25zdCByZWNvcmRlZEZyYW1lczogU3RhdGVbXVtdID0gW107XHJcbiAgICBjb25zdCB0b3RhbEZyYW1lcyA9IHRoaXMuc2ltdWxhdGlvbi5tYXhGcmFtZVJhdGUgKiByZWNvcmRGb3I7XHJcbiAgICBsZXQgcGxheUluZCA9IDE7XHJcbiAgICB0aGlzLnNpbXVsYXRpb24udW5pdmVyc2VzLmZvckVhY2goKHUpID0+IHtcclxuICAgICAgcmVjb3JkZWRGcmFtZXMucHVzaChbdS5jdXJyU3RhdGUuY2xvbmUoKV0pO1xyXG4gICAgfSk7XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRvdGFsRnJhbWVzOyBpKyspIHtcclxuICAgICAgdGhpcy5zaW11bGF0aW9uLnNpbXVsYXRlU3RlcCgxIC8gdGhpcy5zaW11bGF0aW9uLm1heEZyYW1lUmF0ZSk7XHJcbiAgICAgIHRoaXMuc2ltdWxhdGlvbi51bml2ZXJzZXMuZm9yRWFjaCgodSwgaikgPT4ge1xyXG4gICAgICAgIHJlY29yZGVkRnJhbWVzW2pdLnB1c2godS5jdXJyU3RhdGUuY2xvbmUoKSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGxheW91dDogUGFydGlhbDxMYXlvdXQ+ID0ge1xyXG4gICAgICBwYXBlcl9iZ2NvbG9yOiAnIzAwMDAwMCcsXHJcbiAgICAgIHBsb3RfYmdjb2xvcjogJyMwMDAwMDAnLFxyXG4gICAgICBmb250OiB7XHJcbiAgICAgICAgY29sb3I6ICcjYmZiZmJmJyxcclxuICAgICAgfSxcclxuICAgICAgeGF4aXM6IHtcclxuICAgICAgICBhdXRvcmFuZ2U6IGZhbHNlLFxyXG4gICAgICAgIHJhbmdlOiBbLSh3aWR0aCAvIDIpIC8gc2NhbGUsIHdpZHRoIC8gMiAvIHNjYWxlXSxcclxuICAgICAgfSxcclxuICAgICAgeWF4aXM6IHtcclxuICAgICAgICBhdXRvcmFuZ2U6IGZhbHNlLFxyXG4gICAgICAgIHJhbmdlOiBbLShoZWlnaHQgLyAyKSAvIHNjYWxlLCBoZWlnaHQgLyAyIC8gc2NhbGVdLFxyXG4gICAgICB9LFxyXG4gICAgICAvLyB1aXJldmlzaW9uOiAndHJ1ZScsXHJcbiAgICAgIHNob3dsZWdlbmQ6IGZhbHNlLFxyXG4gICAgfTtcclxuXHJcbiAgICBpZiAodGhpcy5zaW11bGF0aW9uLmNvbnRyb2xsZXIgPT09ICd1aScpIHtcclxuICAgICAgdGhpcy5hZGRDb250cm9scyhlbGVtZW50KTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgc3RhdHM6IFN0YXRzIHwgdW5kZWZpbmVkO1xyXG4gICAgaWYgKHRoaXMuc2ltdWxhdGlvbi5zaG93RGVidWdJbmZvKSB7XHJcbiAgICAgIHN0YXRzID0gbmV3IFN0YXRzKCk7XHJcbiAgICAgIHN0YXRzLmRvbS5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XHJcbiAgICAgIHN0YXRzLmRvbS5zdHlsZS5ib3R0b20gPSAnMHB4JztcclxuICAgICAgc3RhdHMuZG9tLnN0eWxlLnJlbW92ZVByb3BlcnR5KCd0b3AnKTtcclxuICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChzdGF0cy5kb20pO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGluaXRfZGF0YTogRGF0YVtdID0gdGhpcy5zaW11bGF0aW9uLnVuaXZlcnNlcy5mbGF0TWFwKFxyXG4gICAgICAodW5pOiBVbml2ZXJzZSk6IERhdGFbXSA9PiB7XHJcbiAgICAgICAgY29uc3QgY3VyclRyYWlsID0gbmV3IFBsb3RseVVuaXZlcnNlVHJhaWwoXHJcbiAgICAgICAgICB0aGlzLnNpbXVsYXRpb24uZ2V0TWF4VHJhaWxMZW5ndGgoKSxcclxuICAgICAgICAgIHR5cGVvZiB1bmkuY29sb3IgPT09ICdzdHJpbmcnID8gdW5pLmNvbG9yIDogdW5pLmNvbG9yWzBdLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgdGhpcy51bml2ZXJzZVRyYWlscy5wdXNoKGN1cnJUcmFpbCk7XHJcbiAgICAgICAgY29uc3QgY3VyckRhdGE6IERhdGEgPSB7XHJcbiAgICAgICAgICB4OiB1bmkuY3VyclN0YXRlLmJvZGllcy5tYXAoKGJvZHkpID0+IGJvZHkucG9zaXRpb24ueCksXHJcbiAgICAgICAgICB5OiB1bmkuY3VyclN0YXRlLmJvZGllcy5tYXAoKGJvZHkpID0+IGJvZHkucG9zaXRpb24ueSksXHJcbiAgICAgICAgICB0eXBlOiAnc2NhdHRlcicsXHJcbiAgICAgICAgICBtb2RlOiAnbWFya2VycycsXHJcbiAgICAgICAgICBtYXJrZXI6IHtcclxuICAgICAgICAgICAgY29sb3I6IHVuaS5jb2xvcixcclxuICAgICAgICAgICAgc2l6ZW1pbjogNixcclxuICAgICAgICAgICAgc2l6ZTogdW5pLmN1cnJTdGF0ZS5ib2RpZXMubWFwKChib2R5KSA9PiBNYXRoLm1pbigxMCwgYm9keS5tYXNzKSksXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH07XHJcbiAgICAgICAgaWYgKHRoaXMuc2ltdWxhdGlvbi5nZXRTaG93VHJhaWxzKCkpIHtcclxuICAgICAgICAgIHVuaS5jdXJyU3RhdGUuYm9kaWVzLmZvckVhY2goKGIpID0+IHtcclxuICAgICAgICAgICAgY3VyclRyYWlsLmFkZFRyYWlsKGIucG9zaXRpb24ueCwgYi5wb3NpdGlvbi55KTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgcmV0dXJuIFtjdXJyRGF0YSwgY3VyclRyYWlsLmRhdGFdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gW1xyXG4gICAgICAgICAgY3VyckRhdGEsXHJcbiAgICAgICAgICB7XHJcbiAgICAgICAgICAgIHg6IFtdLFxyXG4gICAgICAgICAgICB5OiBbXSxcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgXTtcclxuICAgICAgfSxcclxuICAgICk7XHJcblxyXG4gICAgUGxvdGx5Lm5ld1Bsb3QoZGl2SWQsIGluaXRfZGF0YSwgbGF5b3V0LCB7XHJcbiAgICAgIHNjcm9sbFpvb206IHRydWUsXHJcbiAgICAgIG1vZGVCYXJCdXR0b25zVG9SZW1vdmU6IFtcclxuICAgICAgICAnem9vbTJkJyxcclxuICAgICAgICAnbGFzc28yZCcsXHJcbiAgICAgICAgJ3NlbGVjdDJkJyxcclxuICAgICAgICAndG9JbWFnZScsXHJcbiAgICAgICAgJ3Jlc2V0U2NhbGUyZCcsXHJcbiAgICAgIF0sXHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoYW5pbWF0aW9uSWQgIT09IG51bGwpIHJldHVybjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFBhaW50IHRoZSB2aXN1YWxpemF0aW9uXHJcbiAgICAgKiBAcGFyYW0gdGltZXN0YW1wTXMgY3VycmVudCB0aW1lc3RhbXAgaW4gbWlsbGlzZWNvbmRzLCBwcm92aWRlZCBieSByZXF1ZXN0QW5pbWF0aW9uRnJhbWVcclxuICAgICAqL1xyXG4gICAgY29uc3QgcGFpbnQgPSAodGltZXN0YW1wTXM6IG51bWJlcikgPT4ge1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgdGhpcy5zaW11bGF0aW9uLmNvbnRyb2xzLnNwZWVkID09PSAwXHJcbiAgICAgICAgfHwgdGhpcy5zaW11bGF0aW9uLmNvbnRyb2xzLnBhdXNlZFxyXG4gICAgICApIHtcclxuICAgICAgICBhbmltYXRpb25JZCA9IHJlcXVlc3RBbmltYXRpb25GcmFtZShwYWludCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCBjdXJyUGxheUluZCA9IE1hdGgucm91bmQocGxheUluZCk7XHJcbiAgICAgIGNvbnN0IG5ld19kYXRhID0gdGhpcy5zaW11bGF0aW9uLnVuaXZlcnNlcy5mbGF0TWFwKFxyXG4gICAgICAgICh1bmk6IFVuaXZlcnNlLCBpOiBudW1iZXIpOiBEYXRhW10gPT4ge1xyXG4gICAgICAgICAgaWYgKCF0aGlzLnNpbXVsYXRpb24uZ2V0U2hvd1VuaXZlcnNlKHVuaS5sYWJlbCkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIFtcclxuICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICB4OiBbXSxcclxuICAgICAgICAgICAgICAgIHk6IFtdLFxyXG4gICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAge30sXHJcbiAgICAgICAgICAgIF07XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBjb25zdCBjdXJyU3RhdGUgPSByZWNvcmRlZEZyYW1lc1tpXVtjdXJyUGxheUluZF07XHJcbiAgICAgICAgICBjb25zdCBjdXJyRGF0YTogRGF0YSA9IHtcclxuICAgICAgICAgICAgeDogY3VyclN0YXRlLmJvZGllcy5tYXAoKGJvZHkpID0+IGJvZHkucG9zaXRpb24ueCksXHJcbiAgICAgICAgICAgIHk6IGN1cnJTdGF0ZS5ib2RpZXMubWFwKChib2R5KSA9PiBib2R5LnBvc2l0aW9uLnkpLFxyXG4gICAgICAgICAgICBob3ZlcnRleHQ6IGN1cnJTdGF0ZS5ib2RpZXMubWFwKChib2R5KSA9PiBib2R5LmxhYmVsKSxcclxuICAgICAgICAgICAgbWFya2VyOiB7XHJcbiAgICAgICAgICAgICAgc2l6ZTogY3VyclN0YXRlLmJvZGllcy5tYXAoKGJvZHkpID0+IE1hdGgubWluKDEwLCBib2R5Lm1hc3MpKSxcclxuICAgICAgICAgICAgICBjb2xvcjogdW5pLmNvbG9yLFxyXG4gICAgICAgICAgICAgIHNpemVtaW46IDYsXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIG1vZGU6ICdtYXJrZXJzJyxcclxuICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgbGV0IHRyYWlsRGF0YTogRGF0YSA9IHt9O1xyXG4gICAgICAgICAgaWYgKHRoaXMuc2ltdWxhdGlvbi5nZXRTaG93VHJhaWxzKCkpIHtcclxuICAgICAgICAgICAgY29uc3QgY3VyclRyYWlsID0gdGhpcy51bml2ZXJzZVRyYWlsc1tpXTtcclxuICAgICAgICAgICAgY3VyclN0YXRlLmJvZGllcy5mb3JFYWNoKChiKTogdm9pZCA9PiB7XHJcbiAgICAgICAgICAgICAgY3VyclRyYWlsLmFkZFRyYWlsKGIucG9zaXRpb24ueCwgYi5wb3NpdGlvbi55KTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIHRyYWlsRGF0YSA9IGN1cnJUcmFpbC5kYXRhO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgcmV0dXJuIFtjdXJyRGF0YSwgdHJhaWxEYXRhXTtcclxuICAgICAgICB9LFxyXG4gICAgICApO1xyXG4gICAgICBQbG90bHkucmVhY3QoZGl2SWQsIG5ld19kYXRhLCBsYXlvdXQpO1xyXG5cclxuICAgICAgaWYgKHRoaXMuc2ltdWxhdGlvbi5zaG93RGVidWdJbmZvICYmIHN0YXRzKSB7XHJcbiAgICAgICAgc3RhdHMudXBkYXRlKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHBsYXlJbmQgPSBNYXRoLnJvdW5kKHBsYXlJbmQgKyB0aGlzLnNpbXVsYXRpb24uY29udHJvbHMuc3BlZWQpO1xyXG4gICAgICBpZiAocGxheUluZCA8IDApIHtcclxuICAgICAgICBpZiAodGhpcy5zaW11bGF0aW9uLmxvb3BlZCkge1xyXG4gICAgICAgICAgcGxheUluZCA9ICgocGxheUluZCAlIHRvdGFsRnJhbWVzKSArIHRvdGFsRnJhbWVzKSAlIHRvdGFsRnJhbWVzO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBwbGF5SW5kID0gMDtcclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSBpZiAocGxheUluZCA+PSB0b3RhbEZyYW1lcykge1xyXG4gICAgICAgIGlmICh0aGlzLnNpbXVsYXRpb24ubG9vcGVkKSB7XHJcbiAgICAgICAgICBwbGF5SW5kICU9IHRvdGFsRnJhbWVzO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBwbGF5SW5kID0gdG90YWxGcmFtZXMgLSAxO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBhbmltYXRpb25JZCA9IHJlcXVlc3RBbmltYXRpb25GcmFtZShwYWludCk7XHJcbiAgICB9O1xyXG5cclxuICAgIGFuaW1hdGlvbklkID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHBhaW50KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFN0b3AgdGhlIHNpbXVsYXRpb24gYW5kIHZpc3VhbGl6YXRpb24uXHJcbiAgICovXHJcbiAgc3RvcCgpOiB2b2lkIHtcclxuICAgIFBsb3RseS5wdXJnZSh0aGlzLmRpdklkKTtcclxuICAgIHRoaXMuZGl2SWQgPSAnJztcclxuICAgIHRoaXMudW5pdmVyc2VUcmFpbHMgPSBbXTtcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiAzRCByZWNvcmRpbmcgdmlzdWFsaXplciB1c2luZyBUaHJlZS5qcy5cclxuICogQGNhdGVnb3J5IFZpc3VhbGl6ZXJzXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgUmVjb3JkaW5nVmlzdWFsaXplcjNEIGltcGxlbWVudHMgVmlzdWFsaXplciB7XHJcbiAgc2ltdWxhdGlvbjogU2ltdWxhdGlvbjtcclxuICBzY2VuZT86IFRIUkVFLlNjZW5lO1xyXG4gIHVuaXZlcnNlVHJhaWxzOiBUaHJlZVVuaXZlcnNlVHJhaWxbXSA9IFtdO1xyXG5cclxuICAvKipcclxuICAgKiBDb25zdHJ1Y3RvciBmb3IgUmVhbFRpbWVWaXN1YWxpemVyM0QuXHJcbiAgICogQHBhcmFtIHNpbXVsYXRpb24gc2ltdWxhdGlvbiBvYmplY3QuXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3Ioc2ltdWxhdGlvbjogU2ltdWxhdGlvbikge1xyXG4gICAgdGhpcy5zaW11bGF0aW9uID0gc2ltdWxhdGlvbjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFkZHMgZGVmYXVsdCBjb250cm9scyB0byB0aGUgdmlzdWFsaXphdGlvbi5cclxuICAgKiBAcGFyYW0gcGFyZW50RWxlbWVudCBwYXJlbnQgZWxlbWVudCB0byBwbGFjZSB0aGUgY29udHJvbGxlciBkaXYgaW4uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhZGRDb250cm9scyhwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCkge1xyXG4gICAgY29uc3QgZ3VpID0gbmV3IEdVSSh7XHJcbiAgICAgIGNvbnRhaW5lcjogcGFyZW50RWxlbWVudCxcclxuICAgIH0pO1xyXG4gICAgZ3VpLmRvbUVsZW1lbnQuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xyXG4gICAgZ3VpLmRvbUVsZW1lbnQuc3R5bGUudG9wID0gJzAnO1xyXG4gICAgZ3VpLmRvbUVsZW1lbnQuc3R5bGUubGVmdCA9ICcwJztcclxuICAgIGd1aS5kb21FbGVtZW50LnN0eWxlLnpJbmRleCA9ICcxMDAwJztcclxuXHJcbiAgICBjb25zdCBjb25maWcgPSB0aGlzLnNpbXVsYXRpb24uY29udHJvbHM7XHJcbiAgICBndWkuYWRkKGNvbmZpZywgJ3NwZWVkJyk7XHJcbiAgICBndWkuYWRkKGNvbmZpZywgJ3Nob3dUcmFpbHMnKVxyXG4gICAgICAub25DaGFuZ2UoKHZhbHVlOiBib29sZWFuKSA9PiB7XHJcbiAgICAgICAgaWYgKHZhbHVlID09PSBmYWxzZSkge1xyXG4gICAgICAgICAgdGhpcy51bml2ZXJzZVRyYWlscy5mb3JFYWNoKCh1dCkgPT4ge1xyXG4gICAgICAgICAgICB1dC5wb3BBbGxUcmFpbHMoKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25maWcuc2hvd1RyYWlscyA9IHZhbHVlO1xyXG4gICAgICB9KTtcclxuICAgIGNvbnN0IHNob3dVbml2ZXJzZUZvbGRlciA9IGd1aS5hZGRGb2xkZXIoJ1Nob3cgVW5pdmVyc2UnKTtcclxuICAgIHNob3dVbml2ZXJzZUZvbGRlci5vcGVuKGZhbHNlKTtcclxuICAgIHRoaXMuc2ltdWxhdGlvbi51bml2ZXJzZXMuZm9yRWFjaCgodSwgaSkgPT4ge1xyXG4gICAgICBzaG93VW5pdmVyc2VGb2xkZXJcclxuICAgICAgICAuYWRkKGNvbmZpZy5zaG93VW5pdmVyc2UsIHUubGFiZWwpXHJcbiAgICAgICAgLm9uQ2hhbmdlKCh2YWx1ZTogYm9vbGVhbikgPT4ge1xyXG4gICAgICAgICAgaWYgKHZhbHVlID09PSBmYWxzZSkge1xyXG4gICAgICAgICAgICB0aGlzLnVuaXZlcnNlVHJhaWxzW2ldLnBvcEFsbFRyYWlscygpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgY29uZmlnLnNob3dVbml2ZXJzZVt1LmxhYmVsXSA9IHZhbHVlO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTaW11bGF0ZSBhbmQgcGxheSB0aGUgdmlzdWFsaXphdGlvblxyXG4gICAqIEBwYXJhbSBkaXZJZCBkaXYgaWQgdG8gcmVuZGVyIHRoZSB2aXN1YWxpemF0aW9uIGluLlxyXG4gICAqIEBwYXJhbSB3aWR0aCB3aWR0aCBvZiB0aGUgdmlzdWFsaXphdGlvbi5cclxuICAgKiBAcGFyYW0gaGVpZ2h0IGhlaWdodCBvZiB0aGUgdmlzdWFsaXphdGlvbi5cclxuICAgKiBAcGFyYW0gcmVjb3JkRm9yIG51bWJlciBvZiBzZWNvbmRzIHRvIHJlY29yZCBmb3IuXHJcbiAgICovXHJcbiAgc3RhcnQoZGl2SWQ6IHN0cmluZywgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIHJlY29yZEZvcjogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5zY2VuZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIC8vIHRocm93IG5ldyBFcnJvcihcclxuICAgICAgLy8gICAnU2ltdWxhdGlvbiBhbHJlYWR5IHBsYXlpbmcuIFN0b3AgdGhlIGN1cnJlbnQgcGxheXRpbWUgYmVmb3JlIGluaXRpYXRpbmcgYSBuZXcgb25lLicsXHJcbiAgICAgIC8vICk7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1NpbXVsYXRpb24gYWxyZWFkeSBwbGF5aW5nLiBTdG9wIHRoZSBjdXJyZW50IHBsYXl0aW1lIGJlZm9yZSBpbml0aWF0aW5nIGEgbmV3IG9uZS4nKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgbGV0IGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChkaXZJZCk7XHJcbiAgICBpZiAoZWxlbWVudCA9PT0gbnVsbCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICAvLyBjb25zdCB3aWR0aCA9IGVsZW1lbnQuY2xpZW50V2lkdGg7XHJcbiAgICAvLyBjb25zdCBoZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodDtcclxuICAgIGxldCBtYXhXaWR0aCA9IDA7XHJcbiAgICBsZXQgbWF4SGVpZ2h0ID0gMDtcclxuICAgIHRoaXMuc2ltdWxhdGlvbi51bml2ZXJzZXMuZm9yRWFjaCgodSkgPT4gdS5jdXJyU3RhdGUuYm9kaWVzLmZvckVhY2goKGIpID0+IHtcclxuICAgICAgbWF4V2lkdGggPSBNYXRoLm1heChtYXhXaWR0aCwgTWF0aC5hYnMoYi5wb3NpdGlvbi54KSk7XHJcbiAgICAgIG1heEhlaWdodCA9IE1hdGgubWF4KG1heEhlaWdodCwgTWF0aC5hYnMoYi5wb3NpdGlvbi55KSk7XHJcbiAgICB9KSk7XHJcbiAgICBjb25zdCBzY2FsZSA9IDAuNSAqIE1hdGgubWluKGhlaWdodCAvIG1heEhlaWdodCwgd2lkdGggLyBtYXhXaWR0aCk7XHJcblxyXG4gICAgdGhpcy5zY2VuZSA9IG5ldyBUSFJFRS5TY2VuZSgpO1xyXG5cclxuICAgIGNvbnN0IGNhbWVyYSA9IG5ldyBUSFJFRS5PcnRob2dyYXBoaWNDYW1lcmEoXHJcbiAgICAgIHdpZHRoIC8gLTIsXHJcbiAgICAgIHdpZHRoIC8gMixcclxuICAgICAgaGVpZ2h0IC8gMixcclxuICAgICAgaGVpZ2h0IC8gLTIsXHJcbiAgICAgIDAsXHJcbiAgICAgIDEwMDAwMDAwMDAwLFxyXG4gICAgKTtcclxuICAgIGNhbWVyYS5wb3NpdGlvbi5zZXQoMCwgMCwgTWF0aC5tYXgod2lkdGgsIGhlaWdodCkpO1xyXG5cclxuICAgIGNvbnN0IHJlbmRlcmVyID0gbmV3IFRIUkVFLldlYkdMUmVuZGVyZXIoKTtcclxuICAgIHJlbmRlcmVyLnNldFNpemUod2lkdGgsIGhlaWdodCk7XHJcbiAgICByZW5kZXJlci5hdXRvQ2xlYXIgPSBmYWxzZTtcclxuICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQocmVuZGVyZXIuZG9tRWxlbWVudCk7XHJcblxyXG4gICAgbGV0IHN0YXRzOiBTdGF0cyB8IHVuZGVmaW5lZDtcclxuICAgIGlmICh0aGlzLnNpbXVsYXRpb24uc2hvd0RlYnVnSW5mbykge1xyXG4gICAgICBzdGF0cyA9IG5ldyBTdGF0cygpO1xyXG4gICAgICBzdGF0cy5kb20uc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xyXG4gICAgICBzdGF0cy5kb20uc3R5bGUucmlnaHQgPSAnMHB4JztcclxuICAgICAgc3RhdHMuZG9tLnN0eWxlLnJlbW92ZVByb3BlcnR5KCdsZWZ0Jyk7XHJcbiAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoc3RhdHMuZG9tKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5zaW11bGF0aW9uLmNvbnRyb2xsZXIgPT09ICd1aScpIHtcclxuICAgICAgdGhpcy5hZGRDb250cm9scyhlbGVtZW50KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBjb25zdCBlYXJ0aERpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG4gICAgLy8gZWFydGhEaXYuY2xhc3NOYW1lID0gJ2xhYmVsJztcclxuICAgIC8vIGVhcnRoRGl2LnRleHRDb250ZW50ID0gJ0VhcnRoaGdramZkZ2hramZnaCc7XHJcbiAgICAvLyBlYXJ0aERpdi5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAndHJhbnNwYXJlbnQnO1xyXG4gICAgLy8gZWFydGhEaXYuc3R5bGUuY29sb3IgPSAnd2hpdGUnO1xyXG4gICAgLy8gZWFydGhEaXYuc3R5bGUuZm9udEZhbWlseSA9ICdzYW5zLXNlcmlmJztcclxuICAgIC8vIGVhcnRoRGl2LnN0eWxlLmJhY2tncm91bmQgPSAncmdiYSgwLCAwLCAwLCAwLjYpJztcclxuXHJcbiAgICAvLyBjb25zdCBlYXJ0aExhYmVsID0gbmV3IENTUzJET2JqZWN0KGVhcnRoRGl2KTtcclxuICAgIC8vIGVhcnRoTGFiZWwucG9zaXRpb24uc2V0KDAsIDAsIDApO1xyXG4gICAgLy8gZWFydGhMYWJlbC5jZW50ZXIuc2V0KDAsIDEpO1xyXG4gICAgLy8gLy8gYXJyWzBdLmFkZChlYXJ0aExhYmVsKTtcclxuICAgIC8vIGVhcnRoTGFiZWwubGF5ZXJzLnNldCgwKTtcclxuICAgIC8vIGNvbnN0IGxhYmVsUmVuZGVyZXIgPSBuZXcgQ1NTMkRSZW5kZXJlcigpO1xyXG4gICAgLy8gbGFiZWxSZW5kZXJlci5zZXRTaXplKHdpZHRoLCBoZWlnaHQpO1xyXG4gICAgLy8gbGFiZWxSZW5kZXJlci5kb21FbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcclxuICAgIC8vIGxhYmVsUmVuZGVyZXIuZG9tRWxlbWVudC5zdHlsZS50b3AgPSAnMHB4JztcclxuICAgIC8vIGVsZW1lbnQuYXBwZW5kQ2hpbGQobGFiZWxSZW5kZXJlci5kb21FbGVtZW50KTtcclxuXHJcbiAgICBjb25zdCBvcmJpdENvbnRyb2xzID0gbmV3IE9yYml0Q29udHJvbHMoY2FtZXJhLCByZW5kZXJlci5kb21FbGVtZW50KTtcclxuICAgIG9yYml0Q29udHJvbHMubGlzdGVuVG9LZXlFdmVudHMod2luZG93KTtcclxuICAgIG9yYml0Q29udHJvbHMudXBkYXRlKCk7XHJcblxyXG4gICAgY29uc3QgYXhlc0hlbHBlciA9IG5ldyBUSFJFRS5BeGVzSGVscGVyKHdpZHRoKTtcclxuICAgIHRoaXMuc2NlbmUuYWRkKGF4ZXNIZWxwZXIpO1xyXG4gICAgY29uc3Qgdmlld0hlbHBlciA9IG5ldyBWaWV3SGVscGVyKGNhbWVyYSwgcmVuZGVyZXIuZG9tRWxlbWVudCk7XHJcblxyXG4gICAgLy8gdmFyIG06IE1hcDxzdHJpbmcsIFRIUkVFLkxpbmVTZWdtZW50cz4gPSBuZXcgTWFwKCk7XHJcbiAgICBsZXQgYXJyOiBUSFJFRS5MaW5lU2VnbWVudHNbXSA9IFtdO1xyXG5cclxuICAgIHRoaXMuc2ltdWxhdGlvbi51bml2ZXJzZXMuZm9yRWFjaCgodSkgPT4ge1xyXG4gICAgICB0aGlzLnVuaXZlcnNlVHJhaWxzLnB1c2goXHJcbiAgICAgICAgbmV3IFRocmVlVW5pdmVyc2VUcmFpbChcclxuICAgICAgICAgIHRoaXMuc2ltdWxhdGlvbi5tYXhUcmFpbExlbmd0aCxcclxuICAgICAgICAgIHR5cGVvZiB1LmNvbG9yID09PSAnc3RyaW5nJyA/IHUuY29sb3IgOiB1LmNvbG9yWzBdLFxyXG4gICAgICAgICAgdGhpcy5zY2VuZSEsXHJcbiAgICAgICAgICBzY2FsZSxcclxuICAgICAgICApLFxyXG4gICAgICApO1xyXG4gICAgICB1LmN1cnJTdGF0ZS5ib2RpZXMuZm9yRWFjaCgoYikgPT4ge1xyXG4gICAgICAgIGNvbnN0IHNwaCA9IG5ldyBUSFJFRS5TcGhlcmVHZW9tZXRyeShcclxuICAgICAgICAgIGNsaXBNaW5NYXgoTWF0aC5sb2cyKGIubWFzcykgLSA3MCwgMTAsIDQwKSxcclxuICAgICAgICAgIDgsXHJcbiAgICAgICAgICA4LFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgY29uc3QgY3VyciA9IG5ldyBUSFJFRS5XaXJlZnJhbWVHZW9tZXRyeShzcGgpO1xyXG4gICAgICAgIGNvbnN0IGxpbmUgPSBuZXcgVEhSRUUuTGluZVNlZ21lbnRzKFxyXG4gICAgICAgICAgY3VycixcclxuICAgICAgICAgIG5ldyBUSFJFRS5MaW5lQmFzaWNNYXRlcmlhbCh7XHJcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcclxuICAgICAgICAgICAgY29sb3I6IG5ldyBUSFJFRS5Db2xvcih1LmNvbG9yKSxcclxuICAgICAgICAgIH0pLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgdGhpcy5zY2VuZSEuYWRkKGxpbmUpO1xyXG4gICAgICAgIGxpbmUucG9zaXRpb24uY29weShiLnBvc2l0aW9uLmNsb25lKClcclxuICAgICAgICAgIC5tdWx0aXBseVNjYWxhcihzY2FsZSkpO1xyXG4gICAgICAgIC8vIG0uc2V0KHUubGFiZWwgKyBcIiBcIiArIGIubGFiZWwsIGxpbmUpO1xyXG4gICAgICAgIGFyci5wdXNoKGxpbmUpO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gICAgLy8gYXJyWzBdLmFkZChlYXJ0aExhYmVsKVxyXG5cclxuICAgIGNvbnN0IHJlY29yZGVkRnJhbWVzOiBTdGF0ZVtdW10gPSBbXTtcclxuICAgIGNvbnN0IHRvdGFsRnJhbWVzID0gdGhpcy5zaW11bGF0aW9uLm1heEZyYW1lUmF0ZSAqIHJlY29yZEZvcjtcclxuICAgIGxldCBwbGF5SW5kID0gMTtcclxuICAgIHRoaXMuc2ltdWxhdGlvbi51bml2ZXJzZXMuZm9yRWFjaCgodSkgPT4ge1xyXG4gICAgICByZWNvcmRlZEZyYW1lcy5wdXNoKFt1LmN1cnJTdGF0ZS5jbG9uZSgpXSk7XHJcbiAgICB9KTtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdG90YWxGcmFtZXM7IGkrKykge1xyXG4gICAgICB0aGlzLnNpbXVsYXRpb24uc2ltdWxhdGVTdGVwKDEgLyB0aGlzLnNpbXVsYXRpb24ubWF4RnJhbWVSYXRlKTtcclxuICAgICAgdGhpcy5zaW11bGF0aW9uLnVuaXZlcnNlcy5mb3JFYWNoKCh1LCBqKSA9PiB7XHJcbiAgICAgICAgcmVjb3JkZWRGcmFtZXNbal0ucHVzaCh1LmN1cnJTdGF0ZS5jbG9uZSgpKTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBQYWludCB0aGUgdmlzdWFsaXphdGlvblxyXG4gICAgICogQHBhcmFtIHRpbWVzdGFtcE1zIGN1cnJlbnQgdGltZXN0YW1wIGluIG1pbGxpc2Vjb25kcywgcHJvdmlkZWQgYnkgcmVxdWVzdEFuaW1hdGlvbkZyYW1lXHJcbiAgICAgKi9cclxuICAgIGNvbnN0IHBhaW50ID0gKHRpbWVzdGFtcE1zOiBudW1iZXIpID0+IHtcclxuICAgICAgaWYgKFxyXG4gICAgICAgIHRoaXMuc2ltdWxhdGlvbi5jb250cm9scy5zcGVlZCA9PT0gMFxyXG4gICAgICAgIHx8IHRoaXMuc2ltdWxhdGlvbi5jb250cm9scy5wYXVzZWRcclxuICAgICAgKSB7XHJcbiAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHBhaW50KTtcclxuICAgICAgICByZW5kZXJlci5jbGVhcigpO1xyXG4gICAgICAgIHJlbmRlcmVyLnJlbmRlcih0aGlzLnNjZW5lISwgY2FtZXJhKTtcclxuICAgICAgICB2aWV3SGVscGVyLnJlbmRlcihyZW5kZXJlcik7XHJcbiAgICAgICAgLy8gbGFiZWxSZW5kZXJlci5yZW5kZXIoc2NlbmUsIGNhbWVyYSk7XHJcbiAgICAgICAgb3JiaXRDb250cm9scy51cGRhdGUoKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGxldCBpbmQgPSAwO1xyXG4gICAgICB0aGlzLnNpbXVsYXRpb24udW5pdmVyc2VzLmZvckVhY2goKHUsIGkpID0+IHtcclxuICAgICAgICBpZiAodGhpcy5zaW11bGF0aW9uLmNvbnRyb2xzLnNob3dVbml2ZXJzZVt1LmxhYmVsXSkge1xyXG4gICAgICAgICAgY29uc3QgY3VyclN0YXRlID0gcmVjb3JkZWRGcmFtZXNbaV1bcGxheUluZF07XHJcbiAgICAgICAgICBjdXJyU3RhdGUuYm9kaWVzLmZvckVhY2goKGIpID0+IHtcclxuICAgICAgICAgICAgYXJyW2luZF0udmlzaWJsZSA9IHRydWU7XHJcbiAgICAgICAgICAgIGFycltpbmRdLnBvc2l0aW9uLmNvcHkoYi5wb3NpdGlvbi5jbG9uZSgpXHJcbiAgICAgICAgICAgICAgLm11bHRpcGx5U2NhbGFyKHNjYWxlKSk7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLnNpbXVsYXRpb24uY29udHJvbHMuc2hvd1RyYWlscykge1xyXG4gICAgICAgICAgICAgIHRoaXMudW5pdmVyc2VUcmFpbHNbaV0uYWRkVHJhaWwoYXJyW2luZF0ucG9zaXRpb24pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGluZCsrO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHUuY3VyclN0YXRlLmJvZGllcy5mb3JFYWNoKCgpID0+IHtcclxuICAgICAgICAgICAgYXJyW2luZF0udmlzaWJsZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICBpbmQrKztcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICBpZiAodGhpcy5zaW11bGF0aW9uLnNob3dEZWJ1Z0luZm8gJiYgc3RhdHMpIHtcclxuICAgICAgICBzdGF0cy51cGRhdGUoKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgcGxheUluZCA9IE1hdGgucm91bmQocGxheUluZCArIHRoaXMuc2ltdWxhdGlvbi5jb250cm9scy5zcGVlZCk7XHJcbiAgICAgIGlmIChwbGF5SW5kIDwgMCkge1xyXG4gICAgICAgIGlmICh0aGlzLnNpbXVsYXRpb24ubG9vcGVkKSB7XHJcbiAgICAgICAgICBwbGF5SW5kID0gKChwbGF5SW5kICUgdG90YWxGcmFtZXMpICsgdG90YWxGcmFtZXMpICUgdG90YWxGcmFtZXM7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHBsYXlJbmQgPSAwO1xyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIGlmIChwbGF5SW5kID49IHRvdGFsRnJhbWVzKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuc2ltdWxhdGlvbi5sb29wZWQpIHtcclxuICAgICAgICAgIHBsYXlJbmQgJT0gdG90YWxGcmFtZXM7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHBsYXlJbmQgPSB0b3RhbEZyYW1lcyAtIDE7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocGFpbnQpO1xyXG4gICAgICByZW5kZXJlci5jbGVhcigpO1xyXG4gICAgICByZW5kZXJlci5yZW5kZXIodGhpcy5zY2VuZSEsIGNhbWVyYSk7XHJcbiAgICAgIHZpZXdIZWxwZXIucmVuZGVyKHJlbmRlcmVyKTtcclxuICAgICAgLy8gbGFiZWxSZW5kZXJlci5yZW5kZXIoc2NlbmUsIGNhbWVyYSk7XHJcbiAgICAgIG9yYml0Q29udHJvbHMudXBkYXRlKCk7XHJcbiAgICB9O1xyXG5cclxuICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZShwYWludCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTdG9wIHRoZSBzaW11bGF0aW9uIGFuZCB2aXN1YWxpemF0aW9uLlxyXG4gICAqL1xyXG4gIHN0b3AoKTogdm9pZCB7XHJcbiAgICB0aGlzLnNjZW5lPy5jbGVhcigpO1xyXG4gICAgdGhpcy5zY2VuZSA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMudW5pdmVyc2VUcmFpbHMuZm9yRWFjaCgodXQpID0+IHtcclxuICAgICAgdXQucG9wQWxsVHJhaWxzKCk7XHJcbiAgICB9KTtcclxuICAgIHRoaXMudW5pdmVyc2VUcmFpbHMgPSBbXTtcclxuICB9XHJcbn1cclxuIiwiLyogZXNsaW50LWRpc2FibGUganNkb2MvcmVxdWlyZS1wYXJhbSAqL1xyXG4vKiBlc2xpbnQtZGlzYWJsZSBqc2RvYy9jaGVjay1wYXJhbS1uYW1lcyAqL1xyXG5pbXBvcnQgeyB0eXBlIFVuaXZlcnNlIH0gZnJvbSAnLi9Vbml2ZXJzZSc7XHJcbmltcG9ydCB7IHR5cGUgVmlzdWFsaXplciB9IGZyb20gJy4vVmlzdWFsaXplcic7XHJcbmltcG9ydCB7XHJcbiAgUmVhbFRpbWVWaXN1YWxpemVyLFxyXG4gIFJlYWxUaW1lVmlzdWFsaXplcjNELFxyXG4gIFJlY29yZGluZ1Zpc3VhbGl6ZXIsXHJcbiAgUmVjb3JkaW5nVmlzdWFsaXplcjNELFxyXG59IGZyb20gJy4vbGlicmFyeS9WaXN1YWxpemVyJztcclxuXHJcbi8qKlxyXG4gKiBWaXN1YWxpemF0aW9uIHR5cGUuXHJcbiAqIEBjYXRlZ29yeSBUeXBlc1xyXG4gKi9cclxuZXhwb3J0IHR5cGUgVmlzVHlwZSA9ICcyRCcgfCAnM0QnO1xyXG4vKipcclxuICogQ29udHJvbGxlciB0eXBlLlxyXG4gKiAtICd1aScgZm9yIHVzZXIgaW50ZXJmYWNlIGNvbnRyb2wuXHJcbiAqIC0gJ2NvZGUnIGZvciBtYW51YWwgY29udHJvbCB2aWEgY29kZS5cclxuICogLSAnbm9uZScgZm9yIG5vIGNvbnRyb2wuXHJcbiAqIEBjYXRlZ29yeSBUeXBlc1xyXG4gKi9cclxuZXhwb3J0IHR5cGUgQ29udHJvbGxlclR5cGUgPSAndWknIHwgJ2NvZGUnIHwgJ25vbmUnO1xyXG5cclxuLyoqXHJcbiAqIEEgU2ltdWxhdGlvbiBvYmplY3QgdGhhdCBjb250YWlucyBVbml2ZXJzZXMgYW5kIGEgVmlzdWFsaXplci5cclxuICogQGNhdGVnb3J5IEJ1aWxkaW5nIGJsb2Nrc1xyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFNpbXVsYXRpb24ge1xyXG4gIC8qKlxyXG4gICAqIFZpc3VhbGl6YXRpb24gb2JqZWN0IHVzZWQgdG8gcmVuZGVyIHRoZSBzaW11bGF0aW9uLlxyXG4gICAqIEBoaWRkZW5cclxuICAgKi9cclxuICByZWFkb25seSB2aXN1YWxpemVyOiBWaXN1YWxpemVyO1xyXG4gIC8qKlxyXG4gICAqIEFycmF5IG9mIFVuaXZlcnNlcyB0aGF0IG1ha2UgdXAgdGhpcyBzaW11bGF0aW9uLiBBbGwgdW5pdmVyc2VzIGFyZSBzaW11bGF0ZWQgaW5kZXBlbmRlbnRseSBhbmQgdmlzdWFsaXplZCB0b2dldGhlci5cclxuICAgKiBAaGlkZGVuXHJcbiAgICovXHJcbiAgcmVhZG9ubHkgdW5pdmVyc2VzOiBVbml2ZXJzZVtdO1xyXG4gIC8qKlxyXG4gICAqIENvbnRyb2xsZXIgdHlwZSB1c2VkIHRvIGNvbnRyb2wgdGhlIHNpbXVsYXRpb24uXHJcbiAgICogQGhpZGRlblxyXG4gICAqL1xyXG4gIHJlYWRvbmx5IGNvbnRyb2xsZXI6IENvbnRyb2xsZXJUeXBlO1xyXG4gIC8qKlxyXG4gICAqIE1heGltdW0gZnJhbWUgcmF0ZSBvZiB0aGUgdmlzdWFsaXphdGlvbi5cclxuICAgKiBAaGlkZGVuXHJcbiAgICovXHJcbiAgbWF4RnJhbWVSYXRlOiBudW1iZXI7XHJcbiAgLyoqXHJcbiAgICogTWF4aW11bSB0cmFpbCBsZW5ndGggdXNlZCBpbiB0aGUgdmlzdWFsaXphdGlvbi5cclxuICAgKiBAaGlkZGVuXHJcbiAgICovXHJcbiAgbWF4VHJhaWxMZW5ndGg6IG51bWJlcjtcclxuICAvKipcclxuICAgKiBXaGV0aGVyIHRoZSBzaW11bGF0aW9uIGlzIGxvb3BlZCBpbiBjYXNlIG9mIGEgcmVjb3JkaW5nLlxyXG4gICAqIEBoaWRkZW5cclxuICAgKi9cclxuICBsb29wZWQ6IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbnRyb2xzIG9iamVjdCB1c2VkIHRvIGNvbnRyb2wgdGhlIHNpbXVsYXRpb24uXHJcbiAgICogQGhpZGRlblxyXG4gICAqL1xyXG4gIGNvbnRyb2xzOiB7XHJcbiAgICAvKipcclxuICAgICAqIFNwZWVkIG9mIHRoZSBzaW11bGF0aW9uIGFzIGEgc2NhbGUgb2Ygbm9ybWFsIHRpbWUuXHJcbiAgICAgKi9cclxuICAgIHNwZWVkOiBudW1iZXI7XHJcbiAgICAvKipcclxuICAgICAqIFRydWUgaWYgdGhlIHNpbXVsYXRpb24gaXMgcGF1c2VkLlxyXG4gICAgICovXHJcbiAgICBwYXVzZWQ6IGJvb2xlYW47XHJcbiAgICAvKipcclxuICAgICAqIFRydWUgaWYgdHJhaWxzIGFyZSBzaG93biBpbiB0aGUgdmlzdWFsaXphdGlvbi5cclxuICAgICAqL1xyXG4gICAgc2hvd1RyYWlsczogYm9vbGVhbjtcclxuICAgIC8qKlxyXG4gICAgICogT2JqZWN0IGNvbnRhaW5pbmcgd2hldGhlciBlYWNoIHVuaXZlcnNlIGlzIHNob3duIGluIHRoZSB2aXN1YWxpemF0aW9uLlxyXG4gICAgICovXHJcbiAgICBzaG93VW5pdmVyc2U6IHtcclxuICAgICAgW2tleTogc3RyaW5nXTogYm9vbGVhbjtcclxuICAgIH07XHJcbiAgfSA9IHtcclxuICAgICAgc3BlZWQ6IDEsXHJcbiAgICAgIHBhdXNlZDogdHJ1ZSxcclxuICAgICAgc2hvd1RyYWlsczogZmFsc2UsXHJcbiAgICAgIHNob3dVbml2ZXJzZToge30sXHJcbiAgICB9O1xyXG4gIC8qKlxyXG4gICAqIFRydWUgaWYgZGVidWcgaW5mbyBpcyBzaG93biBpbiB0aGUgdmlzdWFsaXphdGlvbi5cclxuICAgKiBAaGlkZGVuXHJcbiAgICovXHJcbiAgc2hvd0RlYnVnSW5mbzogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlIGEgbmV3IFNpbXVsYXRpb24gb2JqZWN0IHdpdGggdGhlIHByb3ZpZGVkIFVuaXZlcnNlcyBhbmQgdmlzdWFsaXphdGlvbiBjb25maWcuXHJcbiAgICogQHBhcmFtIHVuaXZlcnNlcyBhcnJheSBvZiBVbml2ZXJzZXMuXHJcbiAgICogQHBhcmFtIHZpc1R5cGUgdmlzdWFsaXphdGlvbiB0eXBlLlxyXG4gICAqIEBwYXJhbSByZWNvcmQgd2hldGhlciB0byByZWNvcmQgdGhlIHNpbXVsYXRpb24uXHJcbiAgICogQHBhcmFtIGxvb3BlZCB3aGV0aGVyIHRvIGxvb3AgdGhlIHJlY29yZGVkIHNpbXVsYXRpb24uXHJcbiAgICogQHBhcmFtIGNvbnRyb2xsZXIgY29udHJvbGxlciB0eXBlLlxyXG4gICAqIEBwYXJhbSBzaG93VHJhaWxzIHdoZXRoZXIgdG8gc2hvdyB0cmFpbHMgaW4gdGhlIHZpc3VhbGl6YXRpb24uXHJcbiAgICogQHBhcmFtIHNob3dEZWJ1Z0luZm8gd2hldGhlciB0byBzaG93IGRlYnVnIGluZm8gaW4gdGhlIHZpc3VhbGl6YXRpb24uXHJcbiAgICogQHBhcmFtIG1heEZyYW1lUmF0ZSBtYXhpbXVtIGZyYW1lIHJhdGUgb2YgdGhlIHZpc3VhbGl6YXRpb24uXHJcbiAgICogQHBhcmFtIG1heFRyYWlsTGVuZ3RoIG1heGltdW0gdHJhaWwgZm9yIGVhY2ggdW5pdmVyc2UuXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICB1bml2ZXJzZXM6IFVuaXZlcnNlIHwgVW5pdmVyc2VbXSxcclxuICAgIHtcclxuICAgICAgdmlzVHlwZSA9ICcyRCcsXHJcbiAgICAgIHJlY29yZCA9IGZhbHNlLFxyXG4gICAgICBsb29wZWQgPSB0cnVlLFxyXG4gICAgICBjb250cm9sbGVyID0gJ25vbmUnLFxyXG4gICAgICBzaG93VHJhaWxzID0gZmFsc2UsXHJcbiAgICAgIHNob3dEZWJ1Z0luZm8gPSBmYWxzZSxcclxuICAgICAgbWF4RnJhbWVSYXRlID0gLTEsXHJcbiAgICAgIG1heFRyYWlsTGVuZ3RoID0gMTAwLFxyXG4gICAgfToge1xyXG4gICAgICB2aXNUeXBlPzogVmlzVHlwZTtcclxuICAgICAgcmVjb3JkPzogYm9vbGVhbjtcclxuICAgICAgbG9vcGVkPzogYm9vbGVhbjtcclxuICAgICAgY29udHJvbGxlcj86IENvbnRyb2xsZXJUeXBlO1xyXG4gICAgICBzaG93VHJhaWxzPzogYm9vbGVhbjtcclxuICAgICAgc2hvd0RlYnVnSW5mbz86IGJvb2xlYW47XHJcbiAgICAgIG1heEZyYW1lUmF0ZT86IG51bWJlcjtcclxuICAgICAgbWF4VHJhaWxMZW5ndGg/OiBudW1iZXI7XHJcbiAgICB9LFxyXG4gICkge1xyXG4gICAgdGhpcy51bml2ZXJzZXMgPSBBcnJheS5pc0FycmF5KHVuaXZlcnNlcykgPyB1bml2ZXJzZXMgOiBbdW5pdmVyc2VzXTtcclxuICAgIGlmICh0aGlzLnVuaXZlcnNlcy5sZW5ndGggPiAxMCkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RvbyBtYW55IHVuaXZlcnNlcycpO1xyXG4gICAgfVxyXG4gICAgY29uc3QgdW5pcXVlTGFiZWxzID0gbmV3IFNldCh0aGlzLnVuaXZlcnNlcy5tYXAoKHUpID0+IHUubGFiZWwpKTtcclxuICAgIGlmICh1bmlxdWVMYWJlbHMuc2l6ZSAhPT0gdGhpcy51bml2ZXJzZXMubGVuZ3RoKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcignRHVwbGljYXRlIGxhYmVsIGluIHVuaXZlcnNlcycpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjtcclxuICAgIHRoaXMudW5pdmVyc2VzLmZvckVhY2goKHUpID0+IHtcclxuICAgICAgdGhpcy5jb250cm9scy5zaG93VW5pdmVyc2VbdS5sYWJlbF0gPSB0cnVlO1xyXG4gICAgfSk7XHJcbiAgICB0aGlzLmNvbnRyb2xzLnNob3dUcmFpbHMgPSBzaG93VHJhaWxzO1xyXG4gICAgdGhpcy5zaG93RGVidWdJbmZvID0gc2hvd0RlYnVnSW5mbztcclxuICAgIHRoaXMubWF4RnJhbWVSYXRlID0gbWF4RnJhbWVSYXRlO1xyXG4gICAgdGhpcy5tYXhUcmFpbExlbmd0aCA9IG1heFRyYWlsTGVuZ3RoO1xyXG4gICAgdGhpcy5sb29wZWQgPSBsb29wZWQ7XHJcbiAgICBpZiAocmVjb3JkKSB7XHJcbiAgICAgIC8vIGlmICh0aGlzLnVuaXZlcnNlcy5sZW5ndGggPiAxKSB7XHJcbiAgICAgIC8vICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IHJlY29yZCBtdWx0aXBsZSB1bml2ZXJzZXNcIik7XHJcbiAgICAgIC8vIH1cclxuICAgICAgdGhpcy5tYXhGcmFtZVJhdGUgPSA2MDtcclxuICAgICAgdGhpcy52aXN1YWxpemVyXHJcbiAgICAgICAgPSB2aXNUeXBlID09PSAnMkQnXHJcbiAgICAgICAgICA/IG5ldyBSZWNvcmRpbmdWaXN1YWxpemVyKHRoaXMpXHJcbiAgICAgICAgICA6IG5ldyBSZWNvcmRpbmdWaXN1YWxpemVyM0QodGhpcyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnZpc3VhbGl6ZXJcclxuICAgICAgICA9IHZpc1R5cGUgPT09ICcyRCdcclxuICAgICAgICAgID8gbmV3IFJlYWxUaW1lVmlzdWFsaXplcih0aGlzKVxyXG4gICAgICAgICAgOiBuZXcgUmVhbFRpbWVWaXN1YWxpemVyM0QodGhpcyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgdGhlIHNwZWVkIG9mIHRoZSBzaW11bGF0aW9uLlxyXG4gICAqIEByZXR1cm5zIHNwZWVkIG9mIHRoZSBzaW11bGF0aW9uIGFzIGEgc2NhbGUgb2Ygbm9ybWFsIHRpbWUuXHJcbiAgICovXHJcbiAgZ2V0U3BlZWQoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLmNvbnRyb2xzLnNwZWVkO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0IHRoZSBzcGVlZCBvZiB0aGUgc2ltdWxhdGlvbi4gT25seSB3b3JrcyBpZiB0aGUgY29udHJvbGxlciBpcyAnY29kZScuXHJcbiAgICogQHBhcmFtIHNwZWVkIHNwZWVkIG9mIHRoZSBzaW11bGF0aW9uIGFzIGEgc2NhbGUgb2Ygbm9ybWFsIHRpbWUuXHJcbiAgICovXHJcbiAgc2V0U3BlZWQoc3BlZWQ6IG51bWJlcikge1xyXG4gICAgaWYgKHRoaXMuY29udHJvbGxlciA9PT0gJ2NvZGUnKSB7XHJcbiAgICAgIHRoaXMuY29udHJvbHMuc3BlZWQgPSBzcGVlZDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCB3aGV0aGVyIHRoZSBzaW11bGF0aW9uIGlzIHBsYXlpbmcuXHJcbiAgICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgc2ltdWxhdGlvbiBpcyBwbGF5aW5nLlxyXG4gICAqL1xyXG4gIGlzUGxheWluZygpOiBib29sZWFuIHtcclxuICAgIHJldHVybiAhdGhpcy5jb250cm9scy5wYXVzZWQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQYXVzZSB0aGUgc2ltdWxhdGlvbi4gT25seSB3b3JrcyBpZiB0aGUgY29udHJvbGxlciBpcyAnY29kZScuXHJcbiAgICovXHJcbiAgcGF1c2UoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5jb250cm9sbGVyID09PSAnY29kZScpIHtcclxuICAgICAgdGhpcy5jb250cm9scy5wYXVzZWQgPSB0cnVlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVzdW1lIHRoZSBzaW11bGF0aW9uLiBPbmx5IHdvcmtzIGlmIHRoZSBjb250cm9sbGVyIGlzICdjb2RlJy5cclxuICAgKi9cclxuICByZXN1bWUoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5jb250cm9sbGVyID09PSAnY29kZScpIHtcclxuICAgICAgdGhpcy5jb250cm9scy5wYXVzZWQgPSBmYWxzZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCB3aGV0aGVyIHRyYWlscyBhcmUgc2hvd24gaW4gdGhlIHZpc3VhbGl6YXRpb24uXHJcbiAgICogQHJldHVybnMgdHJ1ZSBpZiB0cmFpbHMgYXJlIHNob3duLlxyXG4gICAqL1xyXG4gIGdldFNob3dUcmFpbHMoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5jb250cm9scy5zaG93VHJhaWxzO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0IHdoZXRoZXIgdG8gc2hvdyB0cmFpbHMgaW4gdGhlIHZpc3VhbGl6YXRpb24uIE9ubHkgd29ya3MgaWYgdGhlIGNvbnRyb2xsZXIgaXMgJ2NvZGUnLlxyXG4gICAqIEBwYXJhbSBzaG93VHJhaWxzIHRydWUgdG8gc2hvdyB0cmFpbHMuXHJcbiAgICovXHJcbiAgc2V0U2hvd1RyYWlscyhzaG93VHJhaWxzOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5jb250cm9sbGVyID09PSAnY29kZScpIHtcclxuICAgICAgdGhpcy5jb250cm9scy5zaG93VHJhaWxzID0gc2hvd1RyYWlscztcclxuICAgICAgaWYgKCFzaG93VHJhaWxzKSB7XHJcbiAgICAgICAgLy8gVE9ET1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUcnVlIGlmIHRoZSB1bml2ZXJzZSB3aXRoIHRoZSBnaXZlbiBsYWJlbCBpcyBzaG93bi5cclxuICAgKiBAcGFyYW0gbGFiZWwgdW5pdmVyc2UgbGFiZWwuXHJcbiAgICogQHJldHVybnMgd2hldGhlciB0aGUgdW5pdmVyc2UgaXMgc2hvd24uXHJcbiAgICovXHJcbiAgZ2V0U2hvd1VuaXZlcnNlKGxhYmVsOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLmNvbnRyb2xzLnNob3dVbml2ZXJzZVtsYWJlbF07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZXQgd2hldGhlciB0byBzaG93IHRoZSB1bml2ZXJzZSB3aXRoIHRoZSBnaXZlbiBsYWJlbC4gT25seSB3b3JrcyBpZiB0aGUgY29udHJvbGxlciBpcyAnY29kZScuXHJcbiAgICogQHBhcmFtIGxhYmVsIHVuaXZlcnNlIGxhYmVsLlxyXG4gICAqIEBwYXJhbSBzaG93IHRydWUgdG8gc2hvdyB0aGUgdW5pdmVyc2UuXHJcbiAgICovXHJcbiAgc2V0U2hvd1VuaXZlcnNlKGxhYmVsOiBzdHJpbmcsIHNob3c6IGJvb2xlYW4pIHtcclxuICAgIGlmICh0aGlzLmNvbnRyb2xsZXIgPT09ICdjb2RlJykge1xyXG4gICAgICB0aGlzLmNvbnRyb2xzLnNob3dVbml2ZXJzZVtsYWJlbF0gPSBzaG93O1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0IHRoZSBtYXhpbXVtIHRyYWlsIGxlbmd0aCB1c2VkIGluIHRoZSB2aXN1YWxpemF0aW9uLlxyXG4gICAqIEByZXR1cm5zIG1heGltdW0gdHJhaWwgbGVuZ3RoLlxyXG4gICAqL1xyXG4gIGdldE1heFRyYWlsTGVuZ3RoKCk6IG51bWJlciB7XHJcbiAgICByZXR1cm4gdGhpcy5tYXhUcmFpbExlbmd0aDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldCB0aGUgbWF4aW11bSB0cmFpbCBsZW5ndGggdXNlZCBpbiB0aGUgdmlzdWFsaXphdGlvbi4gQ2hhbmdlcyBvbmx5IGFwcGx5IG9uIHRoZSBuZXh0IFNpbXVsYXRpb24ucGxheSgpIGNhbGwuXHJcbiAgICogQHBhcmFtIG1heFRyYWlsTGVuZ3RoIG1heGltdW0gdHJhaWwgbGVuZ3RoLlxyXG4gICAqL1xyXG4gIHNldE1heFRyYWlsTGVuZ3RoKG1heFRyYWlsTGVuZ3RoOiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmNvbnRyb2xsZXIgPT09ICdjb2RlJykge1xyXG4gICAgICB0aGlzLm1heFRyYWlsTGVuZ3RoID0gbWF4VHJhaWxMZW5ndGg7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTaW11bGF0ZXMgYSBzaW5nbGUgc3RlcCBpbiB0aGlzIHNpbXVsYXRpb24uXHJcbiAgICogQHBhcmFtIGRlbHRhVCB0aW1lIHN0ZXAgdG8gc2ltdWxhdGUuXHJcbiAgICogQGhpZGRlblxyXG4gICAqL1xyXG4gIHNpbXVsYXRlU3RlcChkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy51bml2ZXJzZXMuZm9yRWFjaCgodW5pdmVyc2UpID0+IHtcclxuICAgICAgdW5pdmVyc2Uuc2ltdWxhdGVTdGVwKGRlbHRhVCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEluc2VydCB0aGUgc2ltdWxhdGlvbiB2aXN1YWxpemF0aW9uIGluIHRoZSBkaXYgd2l0aCB0aGUgZ2l2ZW4gaWQuXHJcbiAgICogQHBhcmFtIGRpdklkIGRpdiBpZC5cclxuICAgKiBAcGFyYW0gc3BlZWQgaW5pdGlhbCB0aW1lIHNjYWxlLlxyXG4gICAqIEBwYXJhbSBwYXVzZWQgd2hldGhlciB0byBzdGFydCB0aGUgc2ltdWxhdGlvbiBwYXVzZWQuXHJcbiAgICogQHBhcmFtIHJlY29yZEZvciBudW1iZXIgb2Ygc2Vjb25kcyB0byByZWNvcmQgZm9yLCBvbmx5IHVzZWQgaWYgaW4gcmVjb3JkIG1vZGUuXHJcbiAgICovXHJcbiAgc3RhcnQoXHJcbiAgICBkaXZJZDogc3RyaW5nLFxyXG4gICAgd2lkdGg6IG51bWJlcixcclxuICAgIGhlaWdodDogbnVtYmVyLFxyXG4gICAgc3BlZWQ6IG51bWJlciA9IDEsXHJcbiAgICBwYXVzZWQ6IGJvb2xlYW4gPSBmYWxzZSxcclxuICAgIHJlY29yZEZvcjogbnVtYmVyID0gMCxcclxuICApOiB2b2lkIHtcclxuICAgIGlmIChyZWNvcmRGb3IgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3JlY29yZEZvciBtdXN0IGJlIGRlZmluZWQgaWYgcmVjb3JkIGlzIHRydWUnKTtcclxuICAgIH1cclxuICAgIHRoaXMuY29udHJvbHMucGF1c2VkID0gcGF1c2VkO1xyXG4gICAgdGhpcy5jb250cm9scy5zcGVlZCA9IHNwZWVkO1xyXG4gICAgdGhpcy52aXN1YWxpemVyLnN0YXJ0KGRpdklkLCB3aWR0aCwgaGVpZ2h0LCByZWNvcmRGb3IpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU3RvcCBhbmQgY2xlYXIgdGhlIHNpbXVsYXRpb24uXHJcbiAgICovXHJcbiAgc3RvcCgpOiB2b2lkIHtcclxuICAgIHRoaXMudmlzdWFsaXplci5zdG9wKCk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IFZlY3RvcjMgfSBmcm9tICd0aHJlZSc7XHJcbmltcG9ydCB7IHR5cGUgU3RhdGUgfSBmcm9tICcuLi9TdGF0ZSc7XHJcbmltcG9ydCB7IHR5cGUgVHJhbnNmb3JtYXRpb24gfSBmcm9tICcuLi9UcmFuc2Zvcm1hdGlvbic7XHJcblxyXG4vKipcclxuICogRnJhbWUgb2YgcmVmZXJlbmNlIHRyYW5zZm9ybWF0aW9uIHRvIHRoZSBjZW50ZXIgb2YgdGhlIGZpcnN0IGJvZHkgaW4gdGhlIHN5c3RlbS5cclxuICogQGNhdGVnb3J5IFRyYW5zZm9ybWF0aW9uc1xyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEJvZHlDZW50ZXJUcmFuc2Zvcm1hdGlvbiBpbXBsZW1lbnRzIFRyYW5zZm9ybWF0aW9uIHtcclxuICAvKipcclxuICAgKiBUcmFuc2Zvcm0gdGhlIGZyYW1lIG9mIHJlZmVyZW5jZSB0byB0aGUgY2VudGVyIG9mIHRoZSBmaXJzdCBib2R5IGluIHRoZSBzeXN0ZW0uXHJcbiAgICogQHBhcmFtIHN0YXRlIHN0YXRlIHRvIHRyYW5zZm9ybS5cclxuICAgKiBAcmV0dXJucyB0cmFuc2Zvcm1lZCBzdGF0ZS5cclxuICAgKi9cclxuICB0cmFuc2Zvcm0oc3RhdGU6IFN0YXRlKTogU3RhdGUge1xyXG4gICAgY29uc3QgdHJhbnNmb3JtID0gc3RhdGUuYm9kaWVzWzBdLnBvc2l0aW9uLmNsb25lKCk7XHJcbiAgICBzdGF0ZS5ib2RpZXMuZm9yRWFjaCgoYikgPT4ge1xyXG4gICAgICBiLnBvc2l0aW9uLnN1Yih0cmFuc2Zvcm0pO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gc3RhdGU7XHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogRnJhbWUgb2YgcmVmZXJlbmNlIHRyYW5zZm9ybWF0aW9uIHRvIHRoZSBjZW50ZXIgb2YgbWFzcyBvZiB0aGUgc3lzdGVtLlxyXG4gKiBAY2F0ZWdvcnkgVHJhbnNmb3JtYXRpb25zXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgQ29NVHJhbnNmb3JtYXRpb24gaW1wbGVtZW50cyBUcmFuc2Zvcm1hdGlvbiB7XHJcbiAgLyoqXHJcbiAgICogVHJhbnNmb3JtIHRoZSBmcmFtZSBvZiByZWZlcmVuY2UgdG8gdGhlIGNlbnRlciBvZiBtYXNzIG9mIHRoZSBzeXN0ZW0uXHJcbiAgICogQHBhcmFtIHN0YXRlIHN0YXRlIHRvIHRyYW5zZm9ybS5cclxuICAgKiBAcmV0dXJucyB0cmFuc2Zvcm1lZCBzdGF0ZS5cclxuICAgKi9cclxuICB0cmFuc2Zvcm0oc3RhdGU6IFN0YXRlKTogU3RhdGUge1xyXG4gICAgbGV0IHRvdGFsTWFzcyA9IDA7XHJcbiAgICBsZXQgY29tID0gbmV3IFZlY3RvcjMoKTtcclxuICAgIHN0YXRlLmJvZGllcy5mb3JFYWNoKChiKSA9PiB7XHJcbiAgICAgIHRvdGFsTWFzcyArPSBiLm1hc3M7XHJcbiAgICAgIGNvbS5hZGQoYi5wb3NpdGlvbi5jbG9uZSgpXHJcbiAgICAgICAgLm11bHRpcGx5U2NhbGFyKGIubWFzcykpO1xyXG4gICAgfSk7XHJcbiAgICBjb20uZGl2aWRlU2NhbGFyKHRvdGFsTWFzcyk7XHJcbiAgICBzdGF0ZS5ib2RpZXMuZm9yRWFjaCgoYikgPT4ge1xyXG4gICAgICBiLnBvc2l0aW9uLnN1Yihjb20pO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gc3RhdGU7XHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogRnJhbWUgb2YgcmVmZXJlbmNlIHRyYW5zZm9ybWF0aW9uIGFyb3VuZCBhbiBheGlzIGJ5IGFuIGFuZ2xlLiBNYWtlcyBzZW5zZSB0byB0aGlzIHRyYW5zZm9ybWF0aW9uIG9ubHkgZHVyaW5nIGluaXRpYWxpemF0aW9uIG9mIHRoZSB1bml2ZXJzZSBhbmQgbm90IGF0IGV2ZXJ5IHRpbWUgc3RlcC5cclxuICogQGNhdGVnb3J5IFRyYW5zZm9ybWF0aW9uc1xyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFJvdGF0ZVRyYW5zZm9ybWF0aW9uIGltcGxlbWVudHMgVHJhbnNmb3JtYXRpb24ge1xyXG4gIHJlYWRvbmx5IGF4aXM6IFZlY3RvcjM7XHJcbiAgcmVhZG9ubHkgYW5nbGU6IG51bWJlcjtcclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlIGEgbmV3IFJvdGF0ZVRyYW5zZm9ybWVyLlxyXG4gICAqIEBwYXJhbSBheGlzIGF4aXMgdG8gcm90YXRlIGFyb3VuZC5cclxuICAgKiBAcGFyYW0gYW5nbGUgYW5nbGUgdG8gcm90YXRlIGJ5LlxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKGF4aXM6IFZlY3RvcjMsIGFuZ2xlOiBudW1iZXIpIHtcclxuICAgIHRoaXMuYXhpcyA9IGF4aXM7XHJcbiAgICB0aGlzLmFuZ2xlID0gYW5nbGU7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUcmFuc2Zvcm0gdGhlIGZyYW1lIG9mIHJlZmVyZW5jZSBhcm91bmQgYW4gYXhpcyBieSBhbiBhbmdsZS5cclxuICAgKiBAcGFyYW0gc3RhdGUgc3RhdGUgdG8gdHJhbnNmb3JtLlxyXG4gICAqIEByZXR1cm5zIHRyYW5zZm9ybWVkIHN0YXRlLlxyXG4gICAqL1xyXG4gIHRyYW5zZm9ybShzdGF0ZTogU3RhdGUpOiBTdGF0ZSB7XHJcbiAgICBzdGF0ZS5ib2RpZXMuZm9yRWFjaCgoYikgPT4ge1xyXG4gICAgICBiLnBvc2l0aW9uLmFwcGx5QXhpc0FuZ2xlKHRoaXMuYXhpcywgdGhpcy5hbmdsZSk7XHJcbiAgICAgIGIudmVsb2NpdHkuYXBwbHlBeGlzQW5nbGUodGhpcy5heGlzLCB0aGlzLmFuZ2xlKTtcclxuICAgICAgYi5hY2NlbGVyYXRpb24uYXBwbHlBeGlzQW5nbGUodGhpcy5heGlzLCB0aGlzLmFuZ2xlKTtcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIHN0YXRlO1xyXG4gIH1cclxufVxyXG5cclxuLy8gZXhwb3J0IGNsYXNzIFBpblRyYW5zZm9ybWVyIGltcGxlbWVudHMgVHJhbnNmb3JtZXIge1xyXG4vLyAgIHJlYWRvbmx5IGF4aXM6IFZlY3RvcjM7XHJcbi8vICAgcmVhZG9ubHkgaW5kZXg6IG51bWJlcjtcclxuXHJcbi8vICAgY29uc3RydWN0b3IoYXhpczogVmVjdG9yMywgaW5kZXg6IG51bWJlcikge1xyXG4vLyAgICAgdGhpcy5heGlzID0gYXhpcztcclxuLy8gICAgIHRoaXMuaW5kZXggPSBpbmRleFxyXG4vLyAgIH1cclxuXHJcbi8vICAgdHJhbnNmb3JtKHN0YXRlOiBTdGF0ZSk6IFN0YXRlIHtcclxuLy8gICAgIGNvbnN0IGFuZ2xlID0gc3RhdGUuYm9kaWVzW3RoaXMuaW5kZXhdLnBvc2l0aW9uLmNsb25lKCkuYW5nbGVUbyh0aGlzLmF4aXMpO1xyXG4vLyAgICAgY29uc3QgcGl2b3QgPSBzdGF0ZS5ib2RpZXNbdGhpcy5pbmRleF0ucG9zaXRpb24uY2xvbmUoKS5jcm9zcyh0aGlzLmF4aXMuY2xvbmUoKSkubm9ybWFsaXplKCk7XHJcbi8vICAgICBzdGF0ZS5ib2RpZXMuZm9yRWFjaCgoYikgPT4ge1xyXG4vLyAgICAgICBiLnBvc2l0aW9uLmFwcGx5QXhpc0FuZ2xlKHBpdm90LmNsb25lKCksIGFuZ2xlKTtcclxuLy8gICAgICAgYi52ZWxvY2l0eS5hcHBseUF4aXNBbmdsZShwaXZvdC5jbG9uZSgpLCBhbmdsZSk7XHJcbi8vICAgICAgIGIuYWNjZWxlcmF0aW9uLmFwcGx5QXhpc0FuZ2xlKHBpdm90LmNsb25lKCksIGFuZ2xlKTtcclxuLy8gICAgIH0pO1xyXG4vLyAgICAgcmV0dXJuIHN0YXRlO1xyXG4vLyAgIH1cclxuLy8gfVxyXG4iLCJpbXBvcnQgeyB0eXBlIFN0YXRlIH0gZnJvbSAnLi9TdGF0ZSc7XHJcblxyXG4vKipcclxuICogUmVwcmVzZW50cyBhIEZyYW1lIG9mIFJlZmVyZW5jZSB0cmFuc2Zvcm1hdGlvbi5cclxuICogQGNhdGVnb3J5IEludGVyZmFjZXNcclxuICogQGNhdGVnb3J5IFRyYW5zZm9ybWF0aW9uc1xyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBUcmFuc2Zvcm1hdGlvbiB7XHJcbiAgLyoqXHJcbiAgICogVHJhbnNmb3JtIHRoZSBzdGF0ZSB0byBhIG5ldyBmcmFtZSBvZiByZWZlcmVuY2UuXHJcbiAgICogQHBhcmFtIHN0YXRlIHN0YXRlIHRvIHRyYW5zZm9ybS5cclxuICAgKiBAcGFyYW0gZGVsdGFUIHRpbWUgc3RlcCB0YWtlbiB0byBnZXQgdG8gdGhpcyBzdGF0ZS4gT25seSBhcHBsaWNhYmxlIGZvciB0aW1lLWRlcGVuZGVudCB0cmFuc2Zvcm1hdGlvbnMuXHJcbiAgICogQHJldHVybnMgdHJhbnNmb3JtZWQgc3RhdGUuXHJcbiAgICovXHJcbiAgdHJhbnNmb3JtKHN0YXRlOiBTdGF0ZSwgZGVsdGFUOiBudW1iZXIpOiBTdGF0ZTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEEgRnJhbWUgb2YgUmVmZXJlbmNlIHRyYW5zZm9ybWF0aW9uIHRoYXQgdXNlcyB0aGUgdXNlci1kZWZpbmVkIGxhbWJkYSBmdW5jdGlvbi5cclxuICogQGNhdGVnb3J5IFRyYW5zZm9ybWF0aW9uc1xyXG4gKi9cclxuZXhwb3J0IGNsYXNzIExhbWJkYVRyYW5zZm9ybWF0aW9uIGltcGxlbWVudHMgVHJhbnNmb3JtYXRpb24ge1xyXG4gIHJlYWRvbmx5IGZuOiAoc3RhdGU6IFN0YXRlLCBkZWx0YVQ6IG51bWJlcikgPT4gU3RhdGU7XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZSBhIG5ldyBMYW1iZGFUcmFuc2Zvcm1lciB3aXRoIHRoZSBwcm92aWRlZCBsYW1iZGEgZnVuY3Rpb24uXHJcbiAgICogLSBMYW1iZGEgZnVuY3Rpb24gc2hvdWxkIHRha2UgaW4gdGhlIGN1cnJlbnQgc3RhdGUgYW5kIHRoZSB0aW1lIHN0ZXAgYW5kIHJldHVybiB0aGUgdHJhbnNmb3JtZWQgc3RhdGUuXHJcbiAgICogLSBUaGUgdGltZSBzdGVwIGlzIG9ubHkgYXBwbGljYWJsZSBmb3IgdGltZS1kZXBlbmRlbnQgdHJhbnNmb3JtYXRpb25zLlxyXG4gICAqIC0gVHJhbnNmb3JtZWQgc3RhdGUgc2hvdWxkIGNvbnRhaW4gdGhlIHNhbWUgbnVtYmVyIG9mIGJvZGllcyBhcyB0aGUgaW5wdXQgc3RhdGUsIGFuZCB0aGUgb3JkZXIgc2hvdWxkIGJlIHByZXNlcnZlZC5cclxuICAgKiBAcGFyYW0gZm4gbGFtYmRhIGZ1bmN0aW9uLlxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKGZuOiAoc3RhdGU6IFN0YXRlLCBkZWx0YVQ6IG51bWJlcikgPT4gU3RhdGUpIHtcclxuICAgIHRoaXMuZm4gPSBmbjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRyYW5zZm9ybSB0aGUgc3RhdGUncyBmcmFtZSBvZiByZWZlcmVuY2UgdXNpbmcgdGhlIGxhbWJkYSBmdW5jdGlvbi5cclxuICAgKiBAcGFyYW0gc3RhdGUgc3RhdGUgdG8gdHJhbnNmb3JtLlxyXG4gICAqIEBwYXJhbSBkZWx0YVQgdGltZSBzdGVwIHRha2VuIHRvIGdldCB0byB0aGlzIHN0YXRlLiBPbmx5IGFwcGxpY2FibGUgZm9yIHRpbWUtZGVwZW5kZW50IHRyYW5zZm9ybWF0aW9ucy5cclxuICAgKiBAcmV0dXJucyB0cmFuc2Zvcm1lZCBzdGF0ZS5cclxuICAgKi9cclxuICB0cmFuc2Zvcm0oc3RhdGU6IFN0YXRlLCBkZWx0YVQ6IG51bWJlcik6IFN0YXRlIHtcclxuICAgIHJldHVybiB0aGlzLmZuKHN0YXRlLCBkZWx0YVQpO1xyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyB0eXBlIFNpbXVsYXRlRnVuY3Rpb24gfSBmcm9tICcuL1NpbXVsYXRlRnVuY3Rpb24nO1xyXG5pbXBvcnQgeyB0eXBlIFN0YXRlIH0gZnJvbSAnLi9TdGF0ZSc7XHJcbmltcG9ydCB7IHR5cGUgVHJhbnNmb3JtYXRpb24gfSBmcm9tICcuL1RyYW5zZm9ybWF0aW9uJztcclxuXHJcbi8qKlxyXG4gKiBDb250YWluZXIgZm9yIGEgVW5pdmVyc2UncyBjb25maWd1cmF0aW9uLlxyXG4gKiBAY2F0ZWdvcnkgVHlwZXNcclxuICovXHJcbmV4cG9ydCB0eXBlIFVuaXZlcnNlQ29uZmlnID0ge1xyXG4gIC8qKlxyXG4gICAqIFByZXZpb3VzIHN0YXRlIG9mIHRoZSBVbml2ZXJzZS5cclxuICAgKi9cclxuICBwcmV2U3RhdGU6IFN0YXRlO1xyXG4gIC8qKlxyXG4gICAqIEN1cnJlbnQgc3RhdGUgb2YgdGhlIFVuaXZlcnNlLlxyXG4gICAqL1xyXG4gIGN1cnJTdGF0ZTogU3RhdGU7XHJcbiAgLyoqXHJcbiAgICogQ29sb3Igb2YgdGhlIGJvZGllcyBpbiB0aGUgVW5pdmVyc2UuIEEgc2luZ2xlIGNvbG9yIGFwcGxpZWQgdG8gYWxsIGJvZGllcyBvciBhbiBhcnJheSBvZiBjb2xvcnMgYXBwbGllZCB0byBlYWNoIGJvZHkgcmVzcGVjdGl2ZWx5LiBMZW5ndGggb2YgdGhlIGFycmF5IHNob3VsZCBtYXRjaCB0aGUgbnVtYmVyIG9mIGJvZGllcyBpbiB0aGUgc3RhdGUuXHJcbiAgICovXHJcbiAgY29sb3I6IHN0cmluZyB8IHN0cmluZ1tdO1xyXG4gIC8qKlxyXG4gICAqIExhYmVsIG9mIHRoZSBVbml2ZXJzZS5cclxuICAgKi9cclxuICBsYWJlbDogc3RyaW5nO1xyXG4gIC8qKlxyXG4gICAqIFNpbXVsYXRpb24gZnVuY3Rpb24gdXNlZCB0byBzaW11bGF0ZSB0aGUgVW5pdmVyc2UuXHJcbiAgICovXHJcbiAgc2ltRnVuYzogU2ltdWxhdGVGdW5jdGlvbjtcclxuICAvKipcclxuICAgKiBBcnJheSBvZiB0cmFuc2Zvcm1hdGlvbnMgdG8gYmUgYXBwbGllZCB0byB0aGUgVW5pdmVyc2UncyBzdGF0ZSBhZnRlciBzaW11bGF0aW9uIGFuZCBiZWZvcmUgdmlzdWFsaXphdGlvbi5cclxuICAgKi9cclxuICB0cmFuc2Zvcm1hdGlvbnM6IFRyYW5zZm9ybWF0aW9uW107XHJcbn07XHJcblxyXG4vKipcclxuICogQSBVbml2ZXJzZSBvYmplY3QgdGhhdCBjb250YWlucyBwcmV2aW91cyBhbmQgY3VycmVudCBzdGF0ZSBvZiB0aGUgdW5pdmVyc2UsIGEgc2ltdWxhdGlvbiBmdW5jdGlvbiwgZnJhbWUgb2YgcmVmZXJlbmNlIHRyYW5zZm9ybWF0aW9ucyBhbmQgb3RoZXIgbmVjZXNzYXJ5IGRhdGEuXHJcbiAqIEBjYXRlZ29yeSBCdWlsZGluZyBibG9ja3NcclxuICovXHJcbmV4cG9ydCBjbGFzcyBVbml2ZXJzZSB7XHJcbiAgcHJldlN0YXRlOiBTdGF0ZTtcclxuICBjdXJyU3RhdGU6IFN0YXRlO1xyXG4gIC8qKlxyXG4gICAqIENvbG9yIG9mIHRoZSBib2RpZXMgaW4gdGhlIFVuaXZlcnNlLiBBIHNpbmdsZSBjb2xvciBhcHBsaWVkIHRvIGFsbCBib2RpZXMgb3IgYW4gYXJyYXkgb2YgY29sb3JzIGFwcGxpZWQgdG8gZWFjaCBib2R5IHJlc3BlY3RpdmVseS4gSW5jYXNlIG9mIGFycmF5LCBsZW5ndGggc2hvdWxkIG1hdGNoIHRoZSBudW1iZXIgb2YgYm9kaWVzIGluIHRoZSBzdGF0ZS5cclxuICAgKi9cclxuICBjb2xvcjogc3RyaW5nIHwgc3RyaW5nW107XHJcbiAgLyoqXHJcbiAgICogTGFiZWwgb2YgdGhlIFVuaXZlcnNlLlxyXG4gICAqL1xyXG4gIGxhYmVsOiBzdHJpbmc7XHJcbiAgLyoqXHJcbiAgICogU2ltdWxhdGlvbiBmdW5jdGlvbiB1c2VkIHRvIHNpbXVsYXRlIHRoZSBVbml2ZXJzZS5cclxuICAgKi9cclxuICBzaW1GdW5jOiBTaW11bGF0ZUZ1bmN0aW9uO1xyXG4gIC8qKlxyXG4gICAqIEFycmF5IG9mIHRyYW5zZm9ybWF0aW9ucyB0byBiZSBhcHBsaWVkIHRvIHRoZSBVbml2ZXJzZSdzIHN0YXRlIGFmdGVyIHNpbXVsYXRpb24gYW5kIGJlZm9yZSB2aXN1YWxpemF0aW9uLlxyXG4gICAqL1xyXG4gIHRyYW5zZm9ybWF0aW9uczogVHJhbnNmb3JtYXRpb25bXTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlIGEgbmV3IFVuaXZlcnNlIHdpdGggdGhlIHByb3ZpZGVkIGNvbmZpZ3VyYXRpb24uXHJcbiAgICogQHBhcmFtIGNvbmZpZyBjb25maWd1cmF0aW9uIG9iamVjdC5cclxuICAgKi9cclxuICBjb25zdHJ1Y3Rvcihjb25maWc6IFBhcnRpYWw8VW5pdmVyc2VDb25maWc+KSB7XHJcbiAgICBpZiAoY29uZmlnLmN1cnJTdGF0ZSA9PT0gdW5kZWZpbmVkKSB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgQ3VycmVudCBTdGF0ZSBpbiBVbml2ZXJzZScpO1xyXG4gICAgaWYgKGNvbmZpZy5zaW1GdW5jID09PSB1bmRlZmluZWQpIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBTaW11bGF0aW9uIEZ1bmN0aW9uIGluIFVuaXZlcnNlJyk7XHJcbiAgICB0aGlzLmxhYmVsID0gY29uZmlnLmxhYmVsID09PSB1bmRlZmluZWQgPyAnVW5pdmVyc2UnIDogY29uZmlnLmxhYmVsO1xyXG4gICAgdGhpcy5wcmV2U3RhdGVcclxuICAgICAgPSBjb25maWcucHJldlN0YXRlID09PSB1bmRlZmluZWQgPyBjb25maWcuY3VyclN0YXRlIDogY29uZmlnLnByZXZTdGF0ZTtcclxuICAgIHRoaXMuY3VyclN0YXRlID0gY29uZmlnLmN1cnJTdGF0ZTtcclxuICAgIHRoaXMuY29sb3JcclxuICAgICAgPSBjb25maWcuY29sb3IgPT09IHVuZGVmaW5lZCA/ICdyZ2JhKDI1NSwgMjU1LCAyNTUsIDEpJyA6IGNvbmZpZy5jb2xvcjtcclxuICAgIHRoaXMuc2ltRnVuYyA9IGNvbmZpZy5zaW1GdW5jO1xyXG4gICAgdGhpcy50cmFuc2Zvcm1hdGlvbnNcclxuICAgICAgPSBjb25maWcudHJhbnNmb3JtYXRpb25zID09PSB1bmRlZmluZWRcclxuICAgICAgICA/IFtdXHJcbiAgICAgICAgOiBBcnJheS5pc0FycmF5KGNvbmZpZy50cmFuc2Zvcm1hdGlvbnMpXHJcbiAgICAgICAgICA/IGNvbmZpZy50cmFuc2Zvcm1hdGlvbnNcclxuICAgICAgICAgIDogW2NvbmZpZy50cmFuc2Zvcm1hdGlvbnNdO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2ltdWxhdGUgYSBzdGVwIGluIHRoZSBVbml2ZXJzZSB1c2luZyB0aGUgU2ltdWxhdGVGdW5jdGlvbiBhbmQgVHJhbnNmb3JtYXRpb25zLlxyXG4gICAqIEBwYXJhbSBkZWx0YVQgdGltZSBzdGVwIHRvIHNpbXVsYXRlLlxyXG4gICAqIEBoaWRkZW5cclxuICAgKi9cclxuICBzaW11bGF0ZVN0ZXAoZGVsdGFUOiBudW1iZXIpIHtcclxuICAgIGxldCBuZXdTdGF0ZSA9IHRoaXMuc2ltRnVuYy5zaW11bGF0ZShcclxuICAgICAgZGVsdGFULFxyXG4gICAgICB0aGlzLmN1cnJTdGF0ZSxcclxuICAgICAgdGhpcy5wcmV2U3RhdGUsXHJcbiAgICApO1xyXG4gICAgdGhpcy5wcmV2U3RhdGUgPSB0aGlzLmN1cnJTdGF0ZTtcclxuICAgIHRoaXMudHJhbnNmb3JtYXRpb25zLmZvckVhY2goKHQpID0+IHtcclxuICAgICAgbmV3U3RhdGUgPSB0LnRyYW5zZm9ybShuZXdTdGF0ZSwgZGVsdGFUKTtcclxuICAgIH0pO1xyXG4gICAgdGhpcy5jdXJyU3RhdGUgPSBuZXdTdGF0ZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIERlZXAgY29weSB0aGUgY3VycmVudCBVbml2ZXJzZS5cclxuICAgKiBAcmV0dXJucyBhIG5ldyBVbml2ZXJzZSBpbnN0YW5jZS5cclxuICAgKi9cclxuICBjbG9uZSgpOiBVbml2ZXJzZSB7XHJcbiAgICByZXR1cm4gbmV3IFVuaXZlcnNlKHtcclxuICAgICAgcHJldlN0YXRlOiB0aGlzLnByZXZTdGF0ZS5jbG9uZSgpLFxyXG4gICAgICBjdXJyU3RhdGU6IHRoaXMuY3VyclN0YXRlLmNsb25lKCksXHJcbiAgICAgIGNvbG9yOiB0aGlzLmNvbG9yLFxyXG4gICAgICBsYWJlbDogdGhpcy5sYWJlbCxcclxuICAgICAgc2ltRnVuYzogdGhpcy5zaW1GdW5jLFxyXG4gICAgICB0cmFuc2Zvcm1hdGlvbnM6IHRoaXMudHJhbnNmb3JtYXRpb25zLFxyXG4gICAgfSk7XHJcbiAgfVxyXG59XHJcbiJdLCJuYW1lcyI6WyJyb290IiwiZmFjdG9yeSIsImV4cG9ydHMiLCJtb2R1bGUiLCJyZXF1aXJlIiwiZGVmaW5lIiwiYW1kIiwidGhpcyIsIl9fV0VCUEFDS19FWFRFUk5BTF9NT0RVTEVfXzYwNF9fIiwiX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV9fOTI0X18iLCJfX1dFQlBBQ0tfRVhURVJOQUxfTU9EVUxFX185ODdfXyIsIl9fV0VCUEFDS19FWFRFUk5BTF9NT0RVTEVfXzY4Nl9fIiwiX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fIiwiX193ZWJwYWNrX3JlcXVpcmVfXyIsIm1vZHVsZUlkIiwiY2FjaGVkTW9kdWxlIiwidW5kZWZpbmVkIiwiX193ZWJwYWNrX21vZHVsZXNfXyIsIm4iLCJnZXR0ZXIiLCJfX2VzTW9kdWxlIiwiZCIsImEiLCJkZWZpbml0aW9uIiwia2V5IiwibyIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZW51bWVyYWJsZSIsImdldCIsIm9iaiIsInByb3AiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJyIiwiU3ltYm9sIiwidG9TdHJpbmdUYWciLCJ2YWx1ZSIsIkNlbGVzdGlhbEJvZHkiLCJjb25zdHJ1Y3RvciIsImxhYmVsIiwibWFzcyIsInBvc2l0aW9uIiwidmVsb2NpdHkiLCJhY2NlbGVyYXRpb24iLCJjbG9uZSIsIkdyYXZpdHkiLCJHIiwiZ2V0Rm9yY2VzIiwiYm9kaWVzIiwibGVuZ3RoIiwiYW5zIiwiaSIsInB1c2giLCJWZWN0b3IzIiwiaiIsImN1cnJGb3JjZSIsImNhbGNOZXd0b25pYW4iLCJhZGQiLCJzdWIiLCJiIiwiZGlzdFNxIiwiZGlzdGFuY2VUb1NxdWFyZWQiLCJmb3JjZVZhbCIsIm5vcm1hbGl6ZSIsIm11bHRpcGx5U2NhbGFyIiwiQ2VudHJpcGV0YWxGb3JjZSIsImNlbnRlciIsIm1hcCIsImJvZHkiLCJkaXJlY3Rpb25WZWN0b3IiLCJzZXRMZW5ndGgiLCJsZW5ndGhTcSIsIkNvbWJpbmVkRm9yY2UiLCJmb3JjZXMiLCJmb3JFYWNoIiwiZm9yY2UiLCJ2YWwiLCJpbmRleCIsIlN0YXRlIiwiVmVsb2NpdHlWZXJsZXRTaW0iLCJmb3JjZUNhbGN1bGF0b3IiLCJzaW11bGF0ZSIsImRlbHRhVCIsImN1cnJTdGF0ZSIsInVwZGF0ZWRCb2RpZXMiLCJ2IiwidXBkYXRlZEJvZHkiLCJjYWxjTmV3UG9zIiwibmV3Rm9yY2VzIiwibmV3QWNjZWwiLCJkaXZpZGVTY2FsYXIiLCJjdXJyUG9zIiwiY3VyclZlbCIsImN1cnJBY2NlbCIsIkV4cGxpY2l0RXVsZXJTaW0iLCJyYXRlVXBkYXRlIiwidXBkYXRlZEZvcmNlcyIsInByZXYiLCJyYXRlIiwiU2VtaUltcGxpY2l0RXVsZXJTaW0iLCJ1cGRhdGVkVmVsIiwiUnVuZ2VLdXR0YTRTaW0iLCJ3ZWlnaHRzIiwiRXJyb3IiLCJib2RpZXNLIiwia3YiLCJreCIsImsydiIsImdldEludGVyS1YiLCJrMngiLCJnZXRJbnRlcktYIiwiazN2IiwiazN4IiwiazR2IiwiazR4Iiwid2VpZ2h0ZWRYUmF0ZSIsIndlaWdodGVkVlJhdGUiLCJrckluZCIsIm5ld0JvZGllcyIsIm5ld0JvZHkiLCJrSW5kIiwiTGFtYmRhU2ltIiwiZm4iLCJwcmV2U3RhdGUiLCJDb250cm9sbGVyIiwicGFyZW50Iiwib2JqZWN0IiwicHJvcGVydHkiLCJjbGFzc05hbWUiLCJlbGVtZW50VHlwZSIsIl9kaXNhYmxlZCIsIl9oaWRkZW4iLCJpbml0aWFsVmFsdWUiLCJnZXRWYWx1ZSIsImRvbUVsZW1lbnQiLCJkb2N1bWVudCIsImNyZWF0ZUVsZW1lbnQiLCJjbGFzc0xpc3QiLCIkbmFtZSIsIm5leHROYW1lSUQiLCJpZCIsIiR3aWRnZXQiLCIkZGlzYWJsZSIsImFwcGVuZENoaWxkIiwiYWRkRXZlbnRMaXN0ZW5lciIsImUiLCJzdG9wUHJvcGFnYXRpb24iLCJjaGlsZHJlbiIsImNvbnRyb2xsZXJzIiwiJGNoaWxkcmVuIiwiX2xpc3RlbkNhbGxiYWNrIiwiYmluZCIsIm5hbWUiLCJfbmFtZSIsInRleHRDb250ZW50Iiwib25DaGFuZ2UiLCJjYWxsYmFjayIsIl9vbkNoYW5nZSIsIl9jYWxsT25DaGFuZ2UiLCJfY2hhbmdlZCIsIm9uRmluaXNoQ2hhbmdlIiwiX29uRmluaXNoQ2hhbmdlIiwiX2NhbGxPbkZpbmlzaENoYW5nZSIsInJlc2V0Iiwic2V0VmFsdWUiLCJlbmFibGUiLCJlbmFibGVkIiwiZGlzYWJsZSIsImRpc2FibGVkIiwidG9nZ2xlIiwidG9nZ2xlQXR0cmlidXRlIiwic2hvdyIsInN0eWxlIiwiZGlzcGxheSIsImhpZGUiLCJvcHRpb25zIiwiY29udHJvbGxlciIsImRlc3Ryb3kiLCJtaW4iLCJtYXgiLCJzdGVwIiwiZGVjaW1hbHMiLCJsaXN0ZW4iLCJfbGlzdGVuaW5nIiwiX2xpc3RlbkNhbGxiYWNrSUQiLCJjYW5jZWxBbmltYXRpb25GcmFtZSIsInJlcXVlc3RBbmltYXRpb25GcmFtZSIsImN1clZhbHVlIiwic2F2ZSIsIl9saXN0ZW5QcmV2VmFsdWUiLCJ1cGRhdGVEaXNwbGF5IiwibG9hZCIsInNwbGljZSIsImluZGV4T2YiLCJyZW1vdmVDaGlsZCIsIkJvb2xlYW5Db250cm9sbGVyIiwic3VwZXIiLCIkaW5wdXQiLCJzZXRBdHRyaWJ1dGUiLCJjaGVja2VkIiwibm9ybWFsaXplQ29sb3JTdHJpbmciLCJzdHJpbmciLCJtYXRjaCIsInJlc3VsdCIsInBhcnNlSW50IiwidG9TdHJpbmciLCJwYWRTdGFydCIsIklOVCIsImlzUHJpbWl0aXZlIiwiZnJvbUhleFN0cmluZyIsInN1YnN0cmluZyIsInRvSGV4U3RyaW5nIiwiQVJSQVkiLCJBcnJheSIsImlzQXJyYXkiLCJ0YXJnZXQiLCJyZ2JTY2FsZSIsImludCIsImciLCJPQkpFQ1QiLCJGT1JNQVRTIiwiQ29sb3JDb250cm9sbGVyIiwiJHRleHQiLCIkZGlzcGxheSIsIl9mb3JtYXQiLCJmaW5kIiwiZm9ybWF0IiwiX3JnYlNjYWxlIiwiX2luaXRpYWxWYWx1ZUhleFN0cmluZyIsIl90ZXh0Rm9jdXNlZCIsIl9zZXRWYWx1ZUZyb21IZXhTdHJpbmciLCJ0cnlQYXJzZSIsInNlbGVjdCIsIm5ld1ZhbHVlIiwiYmFja2dyb3VuZENvbG9yIiwiRnVuY3Rpb25Db250cm9sbGVyIiwiJGJ1dHRvbiIsInByZXZlbnREZWZhdWx0IiwicGFzc2l2ZSIsIk51bWJlckNvbnRyb2xsZXIiLCJfaW5pdElucHV0Iiwic3RlcEV4cGxpY2l0IiwiX2dldEltcGxpY2l0U3RlcCIsIl9kZWNpbWFscyIsIl9taW4iLCJfb25VcGRhdGVNaW5NYXgiLCJfbWF4IiwiZXhwbGljaXQiLCJfc3RlcCIsIl9zdGVwRXhwbGljaXQiLCJfaGFzU2xpZGVyIiwicGVyY2VudCIsIk1hdGgiLCIkZmlsbCIsIndpZHRoIiwiX2lucHV0Rm9jdXNlZCIsInRvRml4ZWQiLCJ3aW5kb3ciLCJtYXRjaE1lZGlhIiwibWF0Y2hlcyIsImluY3JlbWVudCIsImRlbHRhIiwicGFyc2VGbG9hdCIsImlzTmFOIiwiX3NuYXBDbGFtcFNldFZhbHVlIiwiaW5pdENsaWVudFgiLCJpbml0Q2xpZW50WSIsInByZXZDbGllbnRZIiwiaW5pdFZhbHVlIiwiZHJhZ0RlbHRhIiwidGVzdGluZ0ZvclZlcnRpY2FsRHJhZyIsIm9uTW91c2VNb3ZlIiwiZHgiLCJjbGllbnRYIiwiZHkiLCJjbGllbnRZIiwiYWJzIiwiYmx1ciIsIl9zZXREcmFnZ2luZ1N0eWxlIiwib25Nb3VzZVVwIiwiX2Fycm93S2V5TXVsdGlwbGllciIsInJlbW92ZUV2ZW50TGlzdGVuZXIiLCJfc25hcCIsIl9jbGFtcCIsImNvZGUiLCJfbm9ybWFsaXplTW91c2VXaGVlbCIsIl9pbml0U2xpZGVyIiwiJHNsaWRlciIsImluc2VydEJlZm9yZSIsInNldFZhbHVlRnJvbVgiLCJyZWN0IiwiZ2V0Qm91bmRpbmdDbGllbnRSZWN0IiwibGVmdCIsInJpZ2h0IiwiYyIsIm1vdXNlTW92ZSIsIm1vdXNlVXAiLCJwcmV2Q2xpZW50WCIsInRlc3RpbmdGb3JTY3JvbGwiLCJiZWdpblRvdWNoRHJhZyIsInRvdWNoZXMiLCJvblRvdWNoTW92ZSIsIm9uVG91Y2hFbmQiLCJjYWxsT25GaW5pc2hDaGFuZ2UiLCJ3aGVlbEZpbmlzaENoYW5nZVRpbWVvdXQiLCJfaGFzU2Nyb2xsQmFyIiwiZGVsdGFYIiwiZGVsdGFZIiwiY2xlYXJUaW1lb3V0Iiwic2V0VGltZW91dCIsImFjdGl2ZSIsImF4aXMiLCJfaGFzTWluIiwiX2hhc01heCIsImZsb29yIiwid2hlZWxEZWx0YSIsIm11bHQiLCJzaGlmdEtleSIsImFsdEtleSIsInJvdW5kIiwidG9QcmVjaXNpb24iLCJzY3JvbGxIZWlnaHQiLCJjbGllbnRIZWlnaHQiLCJPcHRpb25Db250cm9sbGVyIiwiJHNlbGVjdCIsIl92YWx1ZXMiLCJzZWxlY3RlZEluZGV4IiwicmVtb3ZlIiwidmFsdWVzIiwiX25hbWVzIiwia2V5cyIsInJlcGxhY2VDaGlsZHJlbiIsIiRvcHRpb24iLCJTdHJpbmdDb250cm9sbGVyIiwic3R5bGVzSW5qZWN0ZWQiLCJHVUkiLCJhdXRvUGxhY2UiLCJjb250YWluZXIiLCJ0aXRsZSIsImNsb3NlRm9sZGVycyIsImluamVjdFN0eWxlcyIsInRvdWNoU3R5bGVzIiwiZm9sZGVycyIsIl9jbG9zZWQiLCIkdGl0bGUiLCJvcGVuQW5pbWF0ZWQiLCJjbGljayIsImNzc0NvbnRlbnQiLCJpbmplY3RlZCIsImlubmVySFRNTCIsImJlZm9yZSIsInF1ZXJ5U2VsZWN0b3IiLCJoZWFkIiwiX2luamVjdFN0eWxlcyIsInNldFByb3BlcnR5IiwiX2Nsb3NlRm9sZGVycyIsIiQxIiwiY29uc29sZSIsImVycm9yIiwiYWRkQ29sb3IiLCJhZGRGb2xkZXIiLCJmb2xkZXIiLCJjbG9zZSIsInJlY3Vyc2l2ZSIsImYiLCJfdGl0bGUiLCJvcGVuIiwiX3NldENsb3NlZCIsImNsb3NlZCIsIl9jYWxsT25PcGVuQ2xvc2UiLCJpbml0aWFsSGVpZ2h0IiwiaGVpZ2h0Iiwib25UcmFuc2l0aW9uRW5kIiwidGFyZ2V0SGVpZ2h0IiwiY29udHJvbGxlcnNSZWN1cnNpdmUiLCJvbk9wZW5DbG9zZSIsIl9vbk9wZW5DbG9zZSIsImNoYW5nZWRHVUkiLCJwYXJlbnRFbGVtZW50IiwiZnJvbSIsImNvbmNhdCIsImZvbGRlcnNSZWN1cnNpdmUiLCJhbmltYXRpb25JZCIsImNsaXBNaW5NYXgiLCJ4IiwiUGxvdGx5VW5pdmVyc2VUcmFpbCIsIm1heFRyYWlsTGVuZ3RoIiwiY29sb3IiLCJkYXRhIiwieSIsIm1vZGUiLCJtYXJrZXIiLCJzaXplIiwidHJhaWxMZW5ndGgiLCJ0cmFpbEluZCIsImFkZFRyYWlsIiwicG9wQWxsVHJhaWxzIiwiUmVhbFRpbWVWaXN1YWxpemVyIiwic2ltdWxhdGlvbiIsImRpdklkIiwidW5pdmVyc2VUcmFpbHMiLCJhZGRDb250cm9scyIsImd1aSIsInRvcCIsInpJbmRleCIsImNvbmZpZyIsImNvbnRyb2xzIiwidXQiLCJzaG93VHJhaWxzIiwic2hvd1VuaXZlcnNlRm9sZGVyIiwidW5pdmVyc2VzIiwidSIsInNob3dVbml2ZXJzZSIsInN0YXJ0IiwiZWxlbWVudCIsImdldEVsZW1lbnRCeUlkIiwibWF4V2lkdGgiLCJtYXhIZWlnaHQiLCJzY2FsZSIsImxheW91dCIsInBhcGVyX2JnY29sb3IiLCJwbG90X2JnY29sb3IiLCJmb250IiwieGF4aXMiLCJhdXRvcmFuZ2UiLCJyYW5nZSIsInlheGlzIiwic2hvd2xlZ2VuZCIsInN0YXRzIiwic2hvd0RlYnVnSW5mbyIsImRvbSIsImJvdHRvbSIsInJlbW92ZVByb3BlcnR5IiwiaW5pdF9kYXRhIiwiZmxhdE1hcCIsInVuaSIsImN1cnJUcmFpbCIsImdldE1heFRyYWlsTGVuZ3RoIiwiY3VyckRhdGEiLCJ0eXBlIiwic2l6ZW1pbiIsImdldFNob3dUcmFpbHMiLCJzY3JvbGxab29tIiwibW9kZUJhckJ1dHRvbnNUb1JlbW92ZSIsInRpbWVQZXJGcmFtZSIsIm1heEZyYW1lUmF0ZSIsImxhc3RQYWludFRpbWVzdGFtcE1zIiwibGFzdFNpbVRpbWVzdGFtcE1zIiwidGltZXN0YW1wTXMiLCJzaW11bGF0ZVN0ZXAiLCJzcGVlZCIsInBhaW50IiwicGF1c2VkIiwibmV3X2RhdGEiLCJnZXRTaG93VW5pdmVyc2UiLCJob3ZlcnRleHQiLCJ0cmFpbERhdGEiLCJ1cGRhdGUiLCJzdG9wIiwiVGhyZWVVbml2ZXJzZVRyYWlsIiwic2NlbmUiLCJnZW9tZXRyeSIsIkZsb2F0MzJBcnJheSIsInRyYWlscyIsInBvcyIsInZpc2libGUiLCJwb3NBcnJheSIsInNldCIsImF0dHJpYnV0ZXMiLCJhcnJheSIsInRvQXJyYXkiLCJuZWVkc1VwZGF0ZSIsIlJlYWxUaW1lVmlzdWFsaXplcjNEIiwiY2FtZXJhIiwicmVuZGVyZXIiLCJzZXRTaXplIiwiYXV0b0NsZWFyIiwib3JiaXRDb250cm9scyIsIk9yYml0Q29udHJvbHMiLCJsaXN0ZW5Ub0tleUV2ZW50cyIsImF4ZXNIZWxwZXIiLCJ2aWV3SGVscGVyIiwiVmlld0hlbHBlciIsImFyciIsInNwaCIsImxvZzIiLCJjdXJyIiwibGluZSIsImNvcHkiLCJwZXJmb3JtYW5jZSIsIm5vdyIsImxhc3RQYWludCIsImNsZWFyIiwicmVuZGVyIiwiaW5kIiwiUmVjb3JkaW5nVmlzdWFsaXplciIsInJlY29yZEZvciIsInJlY29yZGVkRnJhbWVzIiwidG90YWxGcmFtZXMiLCJwbGF5SW5kIiwiY3VyclBsYXlJbmQiLCJsb29wZWQiLCJSZWNvcmRpbmdWaXN1YWxpemVyM0QiLCJTaW11bGF0aW9uIiwidmlzVHlwZSIsInJlY29yZCIsIlNldCIsInZpc3VhbGl6ZXIiLCJnZXRTcGVlZCIsInNldFNwZWVkIiwiaXNQbGF5aW5nIiwicGF1c2UiLCJyZXN1bWUiLCJzZXRTaG93VHJhaWxzIiwic2V0U2hvd1VuaXZlcnNlIiwic2V0TWF4VHJhaWxMZW5ndGgiLCJ1bml2ZXJzZSIsIkJvZHlDZW50ZXJUcmFuc2Zvcm1hdGlvbiIsInRyYW5zZm9ybSIsInN0YXRlIiwiQ29NVHJhbnNmb3JtYXRpb24iLCJ0b3RhbE1hc3MiLCJjb20iLCJSb3RhdGVUcmFuc2Zvcm1hdGlvbiIsImFuZ2xlIiwiYXBwbHlBeGlzQW5nbGUiLCJMYW1iZGFUcmFuc2Zvcm1hdGlvbiIsIlVuaXZlcnNlIiwic2ltRnVuYyIsInRyYW5zZm9ybWF0aW9ucyIsIm5ld1N0YXRlIiwidCJdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dist/index.js.LICENSE.txt b/dist/index.js.LICENSE.txt deleted file mode 100644 index 57bb07f..0000000 --- a/dist/index.js.LICENSE.txt +++ /dev/null @@ -1,7 +0,0 @@ -/** - * lil-gui - * https://lil-gui.georgealways.com - * @version 0.19.2 - * @author George Michael Brower - * @license MIT - */ diff --git a/dist/src/CelestialBody.js b/dist/src/CelestialBody.js new file mode 100644 index 0000000..c322895 --- /dev/null +++ b/dist/src/CelestialBody.js @@ -0,0 +1,32 @@ +/** + * Represents a celestial body with all of its kinematic properties. + * @category Building blocks + */ +export class CelestialBody { + /** + * Create a new CelestialBody with the provided information. + * @param label label of the body. + * @param mass mass of the body. + * @param position position of the body. + * @param velocity velocity of the body. + * @param acceleration acceleration of the body. + */ + constructor(label, mass, position, velocity, acceleration) { + this.label = label; + this.mass = mass; + this.position = position; + this.velocity = velocity; + this.acceleration = acceleration; + } + /** + * Deep copy the current CelestialBody with the updated kinematic properties. + * @param position new position. + * @param velocity new velocity. + * @param acceleration new acceleration. + * @returns a new CelestialBody instance with the updated properties. + */ + clone(position, velocity, acceleration) { + return new CelestialBody(this.label, this.mass, position === undefined ? this.position.clone() : position, velocity === undefined ? this.velocity.clone() : velocity, acceleration === undefined ? this.acceleration.clone() : acceleration); + } +} +//# sourceMappingURL=CelestialBody.js.map \ No newline at end of file diff --git a/dist/src/CelestialBody.js.map b/dist/src/CelestialBody.js.map new file mode 100644 index 0000000..e57d037 --- /dev/null +++ b/dist/src/CelestialBody.js.map @@ -0,0 +1 @@ +{"version":3,"file":"CelestialBody.js","sourceRoot":"","sources":["../../src/CelestialBody.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,OAAO,aAAa;IAsBxB;;;;;;;OAOG;IACH,YACE,KAAa,EACb,IAAY,EACZ,QAAiB,EACjB,QAAiB,EACjB,YAAqB;QAErB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,QAAkB,EACtB,QAAkB,EAClB,YAAsB;QACtB,OAAO,IAAI,aAAa,CACtB,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,IAAI,EACT,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,EACzD,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,EACzD,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,CACtE,CAAC;IACJ,CAAC;CACF"} \ No newline at end of file diff --git a/dist/src/Force.js b/dist/src/Force.js new file mode 100644 index 0000000..69d14e3 --- /dev/null +++ b/dist/src/Force.js @@ -0,0 +1,25 @@ +/** + * Function object that uses the user-defined lambda function to calculate the forces acting on the bodies. + * @category Forces + */ +export class LambdaForce { + /** + * Create a new LambdaForce with the provided lambda function. + * - Lambda function should take in an array of CelestialBodies and return an array of forces acting on the bodies. + * - arr[i] should represent the force acting on the ith body. + * - Length of the returned array should be equal to the length of the input array of CelestialBodies. + * @param fn lambda function. + */ + constructor(fn) { + this.fn = fn; + } + /** + * Get the forces acting on the bodies. + * @param bodies array of CelestialBodies. + * @returns array of forces acting on the bodies. + */ + getForces(bodies) { + return this.fn(bodies); + } +} +//# sourceMappingURL=Force.js.map \ No newline at end of file diff --git a/dist/src/Force.js.map b/dist/src/Force.js.map new file mode 100644 index 0000000..c245114 --- /dev/null +++ b/dist/src/Force.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Force.js","sourceRoot":"","sources":["../../src/Force.ts"],"names":[],"mappings":"AAYA;;;GAGG;AACH,MAAM,OAAO,WAAW;IAMtB;;;;;;OAMG;IACH,YAAY,EAA0C;QACpD,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;IAGD;;;;OAIG;IACH,SAAS,CAAC,MAAuB;QAC/B,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;CACF"} \ No newline at end of file diff --git a/dist/src/SimulateFunction.js b/dist/src/SimulateFunction.js new file mode 100644 index 0000000..fc94acf --- /dev/null +++ b/dist/src/SimulateFunction.js @@ -0,0 +1,26 @@ +/** + * Function object that uses the user-defined lambda function to simulate the Universe. + * @category SimulateFunctions + */ +export class LambdaSim { + /** + * Create a new LambdaSim with the provided lambda function. + * - The lambda function should take in the time step, the current state of the Universe, and the previous state of the Universe, and return the next state of the Universe. + * - The lambda function should call or calculate the forces action on the bodies by itself. + * @param fn lambda function. + */ + constructor(fn) { + this.fn = fn; + } + /** + * Simulate the Universe using the lambda function. + * @param deltaT time step. + * @param currState current state of the Universe. + * @param prevState previous state of the Universe. + * @returns the next state of the Universe. + */ + simulate(deltaT, currState, prevState) { + return this.fn(deltaT, currState, prevState); + } +} +//# sourceMappingURL=SimulateFunction.js.map \ No newline at end of file diff --git a/dist/src/SimulateFunction.js.map b/dist/src/SimulateFunction.js.map new file mode 100644 index 0000000..3deeede --- /dev/null +++ b/dist/src/SimulateFunction.js.map @@ -0,0 +1 @@ +{"version":3,"file":"SimulateFunction.js","sourceRoot":"","sources":["../../src/SimulateFunction.ts"],"names":[],"mappings":"AAmBA;;;GAGG;AACH,MAAM,OAAO,SAAS;IAGpB;;;;;OAKG;IACH,YAAY,EAAiE;QAC3E,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;IAED;;;;;;OAMG;IACH,QAAQ,CAAC,MAAc,EAAE,SAAgB,EAAE,SAAgB;QACzD,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAC/C,CAAC;CACF"} \ No newline at end of file diff --git a/dist/src/Simulation.js b/dist/src/Simulation.js new file mode 100644 index 0000000..0444a70 --- /dev/null +++ b/dist/src/Simulation.js @@ -0,0 +1,188 @@ +import { RealTimeVisualizer, RealTimeVisualizer3D, RecordingVisualizer, RecordingVisualizer3D, } from './library/Visualizer'; +/** + * A Simulation object that contains Universes and a Visualizer. + * @category Building blocks + */ +export class Simulation { + /** + * Create a new Simulation object with the provided Universes and visualization config. + * @param universes array of Universes. + * @param visType visualization type. + * @param record whether to record the simulation. + * @param looped whether to loop the recorded simulation. + * @param controller controller type. + * @param showTrails whether to show trails in the visualization. + * @param showDebugInfo whether to show debug info in the visualization. + * @param maxFrameRate maximum frame rate of the visualization. + * @param maxTrailLength maximum trail for each universe. + */ + constructor(universes, { visType = '2D', record = false, looped = true, controller = 'none', showTrails = false, showDebugInfo = false, maxFrameRate = -1, maxTrailLength = 100, }) { + /** + * Controls object used to control the simulation. + * @hidden + */ + this.controls = { + speed: 1, + paused: true, + showTrails: false, + showUniverse: {}, + }; + this.universes = Array.isArray(universes) ? universes : [universes]; + if (this.universes.length > 10) { + throw new Error('Too many universes'); + } + const uniqueLabels = new Set(this.universes.map((u) => u.label)); + if (uniqueLabels.size !== this.universes.length) { + throw new Error('Duplicate label in universes'); + } + this.controller = controller; + this.universes.forEach((u) => { + this.controls.showUniverse[u.label] = true; + }); + this.controls.showTrails = showTrails; + this.showDebugInfo = showDebugInfo; + this.maxFrameRate = maxFrameRate; + this.maxTrailLength = maxTrailLength; + this.looped = looped; + if (record) { + // if (this.universes.length > 1) { + // throw new Error("Cannot record multiple universes"); + // } + this.maxFrameRate = 60; + this.visualizer + = visType === '2D' + ? new RecordingVisualizer(this) + : new RecordingVisualizer3D(this); + } + else { + this.visualizer + = visType === '2D' + ? new RealTimeVisualizer(this) + : new RealTimeVisualizer3D(this); + } + } + /** + * Get the speed of the simulation. + * @returns speed of the simulation as a scale of normal time. + */ + getSpeed() { + return this.controls.speed; + } + /** + * Set the speed of the simulation. Only works if the controller is 'code'. + * @param speed speed of the simulation as a scale of normal time. + */ + setSpeed(speed) { + if (this.controller === 'code') { + this.controls.speed = speed; + } + } + /** + * Get whether the simulation is playing. + * @returns true if the simulation is playing. + */ + isPlaying() { + return !this.controls.paused; + } + /** + * Pause the simulation. Only works if the controller is 'code'. + */ + pause() { + if (this.controller === 'code') { + this.controls.paused = true; + } + } + /** + * Resume the simulation. Only works if the controller is 'code'. + */ + resume() { + if (this.controller === 'code') { + this.controls.paused = false; + } + } + /** + * Get whether trails are shown in the visualization. + * @returns true if trails are shown. + */ + getShowTrails() { + return this.controls.showTrails; + } + /** + * Set whether to show trails in the visualization. Only works if the controller is 'code'. + * @param showTrails true to show trails. + */ + setShowTrails(showTrails) { + if (this.controller === 'code') { + this.controls.showTrails = showTrails; + if (!showTrails) { + // TODO + } + } + } + /** + * True if the universe with the given label is shown. + * @param label universe label. + * @returns whether the universe is shown. + */ + getShowUniverse(label) { + return this.controls.showUniverse[label]; + } + /** + * Set whether to show the universe with the given label. Only works if the controller is 'code'. + * @param label universe label. + * @param show true to show the universe. + */ + setShowUniverse(label, show) { + if (this.controller === 'code') { + this.controls.showUniverse[label] = show; + } + } + /** + * Get the maximum trail length used in the visualization. + * @returns maximum trail length. + */ + getMaxTrailLength() { + return this.maxTrailLength; + } + /** + * Set the maximum trail length used in the visualization. Changes only apply on the next Simulation.play() call. + * @param maxTrailLength maximum trail length. + */ + setMaxTrailLength(maxTrailLength) { + if (this.controller === 'code') { + this.maxTrailLength = maxTrailLength; + } + } + /** + * Simulates a single step in this simulation. + * @param deltaT time step to simulate. + * @hidden + */ + simulateStep(deltaT) { + this.universes.forEach((universe) => { + universe.simulateStep(deltaT); + }); + } + /** + * Insert the simulation visualization in the div with the given id. + * @param divId div id. + * @param speed initial time scale. + * @param paused whether to start the simulation paused. + * @param recordFor number of seconds to record for, only used if in record mode. + */ + start(divId, width, height, speed = 1, paused = false, recordFor = 0) { + if (recordFor === undefined) { + throw new Error('recordFor must be defined if record is true'); + } + this.controls.paused = paused; + this.controls.speed = speed; + this.visualizer.start(divId, width, height, recordFor); + } + /** + * Stop and clear the simulation. + */ + stop() { + this.visualizer.stop(); + } +} +//# sourceMappingURL=Simulation.js.map \ No newline at end of file diff --git a/dist/src/Simulation.js.map b/dist/src/Simulation.js.map new file mode 100644 index 0000000..5302558 --- /dev/null +++ b/dist/src/Simulation.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Simulation.js","sourceRoot":"","sources":["../../src/Simulation.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/src/State.js b/dist/src/State.js new file mode 100644 index 0000000..20aa829 --- /dev/null +++ b/dist/src/State.js @@ -0,0 +1,21 @@ +/** + * Represents a Universe's state snapshot. + * @category Building blocks + */ +export class State { + /** + * Create a new State with the given celestial bodies. + * @param bodies array of celestial bodies. + */ + constructor(bodies) { + this.bodies = bodies; + } + /** + * Deep copy this state + * @returns a new State instance. + */ + clone() { + return new State(this.bodies.map((body) => body.clone())); + } +} +//# sourceMappingURL=State.js.map \ No newline at end of file diff --git a/dist/src/State.js.map b/dist/src/State.js.map new file mode 100644 index 0000000..7bd3eba --- /dev/null +++ b/dist/src/State.js.map @@ -0,0 +1 @@ +{"version":3,"file":"State.js","sourceRoot":"","sources":["../../src/State.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,OAAO,KAAK;IAMhB;;;OAGG;IACH,YAAY,MAAuB;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;CACF"} \ No newline at end of file diff --git a/dist/src/Transformation.js b/dist/src/Transformation.js new file mode 100644 index 0000000..30a7143 --- /dev/null +++ b/dist/src/Transformation.js @@ -0,0 +1,26 @@ +/** + * A Frame of Reference transformation that uses the user-defined lambda function. + * @category Transformations + */ +export class LambdaTransformation { + /** + * Create a new LambdaTransformer with the provided lambda function. + * - Lambda function should take in the current state and the time step and return the transformed state. + * - The time step is only applicable for time-dependent transformations. + * - Transformed state should contain the same number of bodies as the input state, and the order should be preserved. + * @param fn lambda function. + */ + constructor(fn) { + this.fn = fn; + } + /** + * Transform the state's frame of reference using the lambda function. + * @param state state to transform. + * @param deltaT time step taken to get to this state. Only applicable for time-dependent transformations. + * @returns transformed state. + */ + transform(state, deltaT) { + return this.fn(state, deltaT); + } +} +//# sourceMappingURL=Transformation.js.map \ No newline at end of file diff --git a/dist/src/Transformation.js.map b/dist/src/Transformation.js.map new file mode 100644 index 0000000..7577995 --- /dev/null +++ b/dist/src/Transformation.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Transformation.js","sourceRoot":"","sources":["../../src/Transformation.ts"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,MAAM,OAAO,oBAAoB;IAG/B;;;;;;OAMG;IACH,YAAY,EAA2C;QACrD,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,KAAY,EAAE,MAAc;QACpC,OAAO,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAChC,CAAC;CACF"} \ No newline at end of file diff --git a/dist/src/Universe.js b/dist/src/Universe.js new file mode 100644 index 0000000..f371dad --- /dev/null +++ b/dist/src/Universe.js @@ -0,0 +1,57 @@ +/** + * A Universe object that contains previous and current state of the universe, a simulation function, frame of reference transformations and other necessary data. + * @category Building blocks + */ +export class Universe { + /** + * Create a new Universe with the provided configuration. + * @param config configuration object. + */ + constructor(config) { + if (config.currState === undefined) + throw new Error('Missing Current State in Universe'); + if (config.simFunc === undefined) + throw new Error('Missing Simulation Function in Universe'); + this.label = config.label === undefined ? 'Universe' : config.label; + this.prevState + = config.prevState === undefined ? config.currState : config.prevState; + this.currState = config.currState; + this.color + = config.color === undefined ? 'rgba(255, 255, 255, 1)' : config.color; + this.simFunc = config.simFunc; + this.transformations + = config.transformations === undefined + ? [] + : Array.isArray(config.transformations) + ? config.transformations + : [config.transformations]; + } + /** + * Simulate a step in the Universe using the SimulateFunction and Transformations. + * @param deltaT time step to simulate. + * @hidden + */ + simulateStep(deltaT) { + let newState = this.simFunc.simulate(deltaT, this.currState, this.prevState); + this.prevState = this.currState; + this.transformations.forEach((t) => { + newState = t.transform(newState, deltaT); + }); + this.currState = newState; + } + /** + * Deep copy the current Universe. + * @returns a new Universe instance. + */ + clone() { + return new Universe({ + prevState: this.prevState.clone(), + currState: this.currState.clone(), + color: this.color, + label: this.label, + simFunc: this.simFunc, + transformations: this.transformations, + }); + } +} +//# sourceMappingURL=Universe.js.map \ No newline at end of file diff --git a/dist/src/Universe.js.map b/dist/src/Universe.js.map new file mode 100644 index 0000000..6801ab0 --- /dev/null +++ b/dist/src/Universe.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Universe.js","sourceRoot":"","sources":["../../src/Universe.ts"],"names":[],"mappings":"AAmCA;;;GAGG;AACH,MAAM,OAAO,QAAQ;IAoBnB;;;OAGG;IACH,YAAY,MAA+B;QACzC,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACzF,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7F,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QACpE,IAAI,CAAC,SAAS;cACV,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;QACzE,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,KAAK;cACN,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QACzE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,eAAe;cAChB,MAAM,CAAC,eAAe,KAAK,SAAS;gBACpC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC;oBACrC,CAAC,CAAC,MAAM,CAAC,eAAe;oBACxB,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,YAAY,CAAC,MAAc;QACzB,IAAI,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAClC,MAAM,EACN,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,SAAS,CACf,CAAC;QACF,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACjC,QAAQ,GAAG,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,OAAO,IAAI,QAAQ,CAAC;YAClB,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE;YACjC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE;YACjC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,eAAe,EAAE,IAAI,CAAC,eAAe;SACtC,CAAC,CAAC;IACL,CAAC;CACF"} \ No newline at end of file diff --git a/dist/src/Visualizer.js b/dist/src/Visualizer.js new file mode 100644 index 0000000..25785bb --- /dev/null +++ b/dist/src/Visualizer.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=Visualizer.js.map \ No newline at end of file diff --git a/dist/src/Visualizer.js.map b/dist/src/Visualizer.js.map new file mode 100644 index 0000000..71c014d --- /dev/null +++ b/dist/src/Visualizer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Visualizer.js","sourceRoot":"","sources":["../../src/Visualizer.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/src/index.js b/dist/src/index.js new file mode 100644 index 0000000..1ed6e96 --- /dev/null +++ b/dist/src/index.js @@ -0,0 +1,18 @@ +/** + * NBody is a JS/TS library for simulating and visualizing n-body systems. It provides interfaces and implementations of forces, frame of reference transformations, simulation control, and multiple modes and paradigms of visualization. + * @author Yeluri Ketan + */ +import { CelestialBody, } from './CelestialBody'; +import { LambdaForce } from './Force'; +import { CentripetalForce, CombinedForce, Gravity, } from './library/Force'; +import { ExplicitEulerSim, RungeKutta4Sim, SemiImplicitEulerSim, VelocityVerletSim, } from './library/SimulateFunction'; +import { LambdaSim } from './SimulateFunction'; +import { Simulation } from './Simulation'; +import { State } from './State'; +import { BodyCenterTransformation, CoMTransformation, RotateTransformation, } from './library/Transformation'; +import { LambdaTransformation } from './Transformation'; +import { Universe } from './Universe'; +import { RealTimeVisualizer, RealTimeVisualizer3D, RecordingVisualizer, RecordingVisualizer3D, } from './library/Visualizer'; +import { Vector3 } from 'three'; +export { BodyCenterTransformation, CelestialBody, CentripetalForce, CombinedForce, CoMTransformation, ExplicitEulerSim, Gravity, LambdaForce, LambdaSim, LambdaTransformation, RealTimeVisualizer, RealTimeVisualizer3D, RecordingVisualizer, RecordingVisualizer3D, RotateTransformation, RungeKutta4Sim, SemiImplicitEulerSim, Simulation, State, Universe, Vector3, VelocityVerletSim, }; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/src/index.js.map b/dist/src/index.js.map new file mode 100644 index 0000000..7e15b5c --- /dev/null +++ b/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,aAAa,GACd,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAc,MAAM,SAAS,CAAC;AAClD,OAAO,EACL,gBAAgB,EAAE,aAAa,EAAE,OAAO,GACzC,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,gBAAgB,EAAE,cAAc,EAChC,oBAAoB,EAAE,iBAAiB,GACxC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,SAAS,EAAyB,MAAM,oBAAoB,CAAC;AAEtE,OAAO,EAAE,UAAU,EAAqC,MAAM,cAAc,CAAC;AAE7E,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EAAE,oBAAoB,GACxC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAuB,MAAM,kBAAkB,CAAC;AAE7E,OAAO,EAAE,QAAQ,EAAuB,MAAM,YAAY,CAAC;AAE3D,OAAO,EACL,kBAAkB,EAAE,oBAAoB,EACxC,mBAAmB,EAAE,qBAAqB,GAC3C,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EACL,wBAAwB,EAAE,aAAa,EAAE,gBAAgB,EACzD,aAAa,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,oBAAoB,EAAE,kBAAkB,EAC7H,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EAAE,cAAc,EACpC,oBAAoB,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,iBAAiB,GAC9E,CAAC"} \ No newline at end of file diff --git a/dist/src/library/Force.js b/dist/src/library/Force.js new file mode 100644 index 0000000..aa9d3ad --- /dev/null +++ b/dist/src/library/Force.js @@ -0,0 +1,105 @@ +import { Vector3 } from 'three'; +/** + * Represents a [Newtonian Gravitational force](https://en.wikipedia.org/wiki/Newton%27s_law_of_universal_gravitation) object. + * @category Forces + */ +export class Gravity { + /** + * Create a new Gravity with the provided gravitational constant. + * @param G gravitational constant. + */ + constructor(G = 6.674e-11) { + this.G = G; + } + /** + * Calculate and return the forces acting on the bodies. arr[i] represents the force acting on the ith body as a result of all other bodies. + * @param bodies celestial bodies + * @returns forces + */ + getForces(bodies) { + let n = bodies.length; + let ans = []; + for (let i = 0; i < n; i++) { + ans.push(new Vector3(0, 0, 0)); + } + for (let i = 0; i < n; i++) { + for (let j = i + 1; j < n; j++) { + let currForce = this.calcNewtonian(bodies[i], bodies[j]); + ans[i].add(currForce); + ans[j].sub(currForce); + } + } + return ans; + } + /** + * Calculate the gravitational force acting on body a due to body b. + * @param a body a. + * @param b body b. + * @returns gravitational force of a on b. + * @hidden + */ + calcNewtonian(a, b) { + let distSq = a.position.distanceToSquared(b.position); + let forceVal = (this.G * a.mass * b.mass) / distSq; + return b.position + .clone() + .sub(a.position) + .normalize() + .multiplyScalar(forceVal); + } +} +/** + * Represents a [Centripetal force](https://en.wikipedia.org/wiki/Centripetal_force) object. To be used to calculate the force required to keep the bodies in circular motion around a given center. + * @category Forces + */ +export class CentripetalForce { + /** + * Create a new CentripetalForce with the provided center of force. + * @param center center of force. + */ + constructor(center = new Vector3(0, 0, 0)) { + this.center = center; + } + /** + * Calculate the force required to keep the bodies in circular motion around the center. arr[i] represents the centripetal force required for the ith body. + * @param bodies celestial bodies. + * @returns forces. + */ + getForces(bodies) { + // TODO: mv^2/r sin or cos thetha? + return bodies.map((body) => { + const directionVector = this.center.clone() + .sub(body.position); + return directionVector.setLength((body.mass * body.velocity.lengthSq()) / directionVector.length()); + }); + } +} +/** + * Represents a combined force object. To be used to additively combine multiple forces acting on a system of bodies. + * @category Forces + */ +export class CombinedForce { + /** + * Create a new CombinedForce with the provided forces. + * @param forces array of forces. + */ + constructor(forces) { + this.forces = forces; + } + /** + * Get the combined forces acting on the bodies. arr[i] represents the combined force acting on the ith body as a result of all force systems. + * @param bodies celestial bodies. + * @returns element-wise combined forces. + */ + getForces(bodies) { + const forceVal = bodies.map(() => new Vector3(0, 0, 0)); + this.forces.forEach((force) => { + force.getForces(bodies) + .forEach((val, index) => { + forceVal[index].add(val); + }); + }); + return forceVal; + } +} +//# sourceMappingURL=Force.js.map \ No newline at end of file diff --git a/dist/src/library/Force.js.map b/dist/src/library/Force.js.map new file mode 100644 index 0000000..f7ad36c --- /dev/null +++ b/dist/src/library/Force.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Force.js","sourceRoot":"","sources":["../../../src/library/Force.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/src/library/SimulateFunction.js b/dist/src/library/SimulateFunction.js new file mode 100644 index 0000000..9b2dce7 --- /dev/null +++ b/dist/src/library/SimulateFunction.js @@ -0,0 +1,339 @@ +import { Vector3 } from 'three'; +import { State } from '../State'; +// export class VerletSim implements SimulateFunction { +// forceCalculator: Force; +// prevDeltaT: number | undefined = undefined; +// constructor(forceCalculator: Force) { +// this.forceCalculator = forceCalculator; +// } +// private fromOneState( +// currState: State, +// deltaT: number, +// forces: Vector3[] +// ): State { +// let updatedBodies: CelestialBody[] = currState.bodies.map((body, index) => { +// const currAccel = forces[index].divideScalar(body.mass); +// const newPos = currAccel +// .clone() +// .multiplyScalar(deltaT / 2) +// .add(body.velocity) +// .multiplyScalar(deltaT) +// .add(body.position); +// return body.clone( +// newPos, +// this.verletVel(body.position, newPos, deltaT), +// currAccel +// ); +// }); +// this.prevDeltaT = deltaT; +// return new State(updatedBodies); +// } +// simulate(deltaT: number, currState: State, prevState?: State): State { +// if (deltaT <= 0) { +// return currState.clone(); +// } +// let forces = this.forceCalculator.getForces(currState.bodies); +// if (forces.length !== currState.bodies.length) { +// console.error(`forces length !== number of bodies`); +// return currState.clone(); +// } +// if (prevState === undefined) { +// return this.fromOneState(currState, deltaT, forces); +// } +// let updatedBodies: CelestialBody[] = currState.bodies.map((body, index) => { +// const currAccel = forces[index].divideScalar(body.mass); +// const newPos = this.verletPos( +// prevState.bodies[index].position, +// body.position, +// currAccel, +// deltaT +// ); +// return body.clone( +// newPos, +// this.verletVel(body.position, newPos, deltaT), +// currAccel +// ); +// }); +// this.prevDeltaT = deltaT; +// return new State(updatedBodies); +// } +// verletPos( +// oldPos: Vector3, +// currPos: Vector3, +// currAccel: Vector3, +// deltaT: number +// ): Vector3 { +// const prevDT = this.prevDeltaT === undefined ? deltaT : this.prevDeltaT; +// return currAccel +// .clone() +// .multiplyScalar((prevDT + deltaT) / 2) +// .add(currPos.clone().sub(oldPos).divideScalar(prevDT)) +// .multiplyScalar(deltaT) +// .add(currPos); +// } +// verletVel(currPos: Vector3, newPos: Vector3, deltaT: number): Vector3 { +// return newPos.clone().sub(currPos).divideScalar(deltaT); +// } +// } +/** + * Represents a simulation function object that uses the [Velocity Verlet integration method](https://en.wikipedia.org/wiki/Verlet_integration#Velocity_Verlet) to simulate the motion of bodies. + * @category SimulateFunctions + */ +export class VelocityVerletSim { + /** + * Create a new VelocityVerletSim with the provided force calculator, which is invoked on every simulation step. + * @param forceCalculator force calculator. + */ + constructor(forceCalculator) { + this.forceCalculator = forceCalculator; + } + /** + * Simulate a step in the Universe by using the previous and/or current state and a time step, using the Velocity Verlet integration method. + * @param deltaT time step. + * @param currState current state. + * @returns new state after the simulation step. + */ + simulate(deltaT, currState) { + if (deltaT <= 0) { + return currState.clone(); + } + // x(t + dt) = x(t) + (v(t) * dt) + (0.5 * a(t) * dt * dt) + let updatedBodies = currState.bodies.map((v) => { + let updatedBody = v.clone(); + updatedBody.position = this.calcNewPos(updatedBody.position, updatedBody.velocity, updatedBody.acceleration, deltaT); + return updatedBody; + }); + // a(t + dt) = accel at x(t + dt) + let newForces = this.forceCalculator.getForces(updatedBodies); + return new State(updatedBodies.map((b, i) => { + let newAccel = newForces[i].divideScalar(b.mass); + // v(t + dt) = v(t) + 0.5 * (a(t) + a(t + dt)) * dt + b.velocity.add(b.acceleration.add(newAccel) + .multiplyScalar(deltaT / 2)); + b.acceleration = newAccel; + return b; + })); + } + /** + * Calculate the new position of a body in the following way: + * + * newPos = currPos + currVel * deltaT + 0.5 * currAccel * deltaT^2. + * @param currPos current position. + * @param currVel current velocity. + * @param currAccel current acceleration. + * @param deltaT time step. + * @returns new position. + * @hidden + */ + calcNewPos(currPos, currVel, currAccel, deltaT) { + return currPos + .clone() + .add(currVel.clone() + .multiplyScalar(deltaT)) + .add(currAccel.clone() + .multiplyScalar(deltaT * deltaT * 0.5)); + } +} +/** + * Represents a simulation function object that uses the [Euler integration method](https://en.wikipedia.org/wiki/Euler_method) to simulate motions of bodies. + * @category SimulateFunctions + */ +export class ExplicitEulerSim { + /** + * Create a new ExplicitEulerSim with the provided force calculator, which is invoked on every simulation step. + * @param force force calculator. + */ + constructor(force) { + this.force = force; + } + /** + * Simulate a step in the Universe by using the current state and a time step, using the Euler integration method. + * @param deltaT time step. + * @param currState current state. + * @returns new state after the simulation step. + */ + simulate(deltaT, currState) { + const updatedBodies = currState.bodies.map((b) => b.clone( + // x(t + dt) = x(t) + v(t) * dt + this.rateUpdate(b.position, b.velocity, deltaT), + // v(t + dt) = v(t) + a(t) * dt + this.rateUpdate(b.velocity, b.acceleration, deltaT))); + const updatedForces = this.force.getForces(updatedBodies); + updatedBodies.forEach((b, i) => { + // a(t + dt) = accel at x(t + dt) + b.acceleration = updatedForces[i].divideScalar(b.mass); + }); + return new State(updatedBodies); + } + /** + * Update a vector quantity using the rate of change and a time step. + * @param prev previous value. + * @param rate rate of change. + * @param deltaT time step. + * @returns updated value. + * @hidden + */ + rateUpdate(prev, rate, deltaT) { + return rate.clone() + .multiplyScalar(deltaT) + .add(prev); + } +} +/** + * Represents a simulation function object that uses the [Semi-Implicit Euler integration method](https://en.wikipedia.org/wiki/Semi-implicit_Euler_method) to simulate the motion of bodies. + * @category SimulateFunctions + */ +export class SemiImplicitEulerSim { + /** + * Create a new SemiImplicitEulerSim with the provided force calculator, which is invoked on every simulation step. + * @param force force calculator. + */ + constructor(force) { + this.force = force; + } + /** + * Simulate a step in the Universe by using the current state and a time step, using the Semi-Implicit Euler integration method. + * @param deltaT time step. + * @param currState current state. + * @returns new state after the simulation step. + */ + simulate(deltaT, currState) { + const updatedBodies = currState.bodies.map((b) => { + // v(t + dt) = v(t) + a(t) * dt + const updatedVel = this.rateUpdate(b.velocity, b.acceleration, deltaT); + return b.clone( + // x(t + dt) = x(t) + v(t + dt) * dt + this.rateUpdate(b.position, updatedVel, deltaT), updatedVel); + }); + const updatedForces = this.force.getForces(updatedBodies); + updatedBodies.forEach((b, i) => { + // a(t + dt) = accel at x(t + dt) + b.acceleration = updatedForces[i].divideScalar(b.mass); + }); + return new State(updatedBodies); + } + /** + * Update a vector quantity using the rate of change and a time step. + * @param prev previous value. + * @param rate rate of change. + * @param deltaT time step. + * @returns updated value. + * @hidden + */ + rateUpdate(prev, rate, deltaT) { + return rate.clone() + .multiplyScalar(deltaT) + .add(prev); + } +} +/** + * Represents a simulation function object that uses the [Runge-Kutta 4 integration method](https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods) to simulate the motion of bodies. + * @category SimulateFunctions + */ +export class RungeKutta4Sim { + /** + * Create a new RungeKutta4Sim with the provided weights for average force calculator, which is invoked on every simulation step. + * @param force force calculator. + * @param weights weights for weighted average. + */ + constructor(force, weights) { + this.force = force; + if (weights.length !== 4) { + throw new Error('Weights for RK4 must be of length 4'); + } + this.weights = weights; + } + /** + * Simulate a step in the Universe by using the current state and a time step, using the Runge-Kutta 4 integration method. + * @param deltaT time step. + * @param currState current state. + * @returns new state after the simulation step. + */ + simulate(deltaT, currState) { + let bodiesK = currState.bodies.map((v) => ({ + // k1v = a(x(t)) + kv: [v.acceleration.clone()], + // k1r = v(t) + kx: [v.velocity.clone()], + })); + // k2v = a(x(t) + k1x * dt / 2) + const k2v = this.getInterKV(currState.bodies, bodiesK, 0, deltaT / 2); + // k2x = v(t) + k1v * dt / 2 + const k2x = this.getInterKX(currState.bodies, bodiesK, 0, deltaT / 2); + bodiesK.forEach((v, i) => { + v.kv.push(k2v[i]); + v.kx.push(k2x[i]); + }); + // k3v = a(x(t) + k2x * dt / 2) + const k3v = this.getInterKV(currState.bodies, bodiesK, 1, deltaT / 2); + // k3x = v(t) + k2v * dt / 2 + const k3x = this.getInterKX(currState.bodies, bodiesK, 1, deltaT / 2); + bodiesK.forEach((v, i) => { + v.kv.push(k3v[i]); + v.kx.push(k3x[i]); + }); + // k3v = a(x(t) + k3x * dt) + const k4v = this.getInterKV(currState.bodies, bodiesK, 2, deltaT); + // k4x = v(t) + k3v * dt + const k4x = this.getInterKX(currState.bodies, bodiesK, 2, deltaT); + bodiesK.forEach((v, i) => { + v.kv.push(k4v[i]); + v.kx.push(k4x[i]); + }); + const updatedBodies = currState.bodies.map((b, i) => { + const weightedXRate = new Vector3(); + const weightedVRate = new Vector3(); + bodiesK[i].kx.forEach((v, j) => { + weightedXRate.add(v.multiplyScalar(this.weights[j])); + }); + bodiesK[i].kv.forEach((v, j) => { + weightedVRate.add(v.multiplyScalar(this.weights[j])); + }); + return b.clone(weightedXRate.multiplyScalar(deltaT / 6) + .add(b.position), weightedVRate.multiplyScalar(deltaT / 6) + .add(b.velocity)); + }); + const updatedForces = this.force.getForces(updatedBodies); + updatedBodies.forEach((v, i) => { + v.acceleration = updatedForces[i].divideScalar(v.mass); + }); + return new State(updatedBodies); + } + /** + * Get intermediate velocity rate values. + * @param bodies current bodies. + * @param bodiesK intermediate kinematic rate values for all bodies. + * @param krInd index of intermediate kinematic rate value to base the new intermediate value on. + * @param deltaT time step. + * @returns next intermediate velocity rate values for all bodies. + * @hidden + */ + getInterKV(bodies, bodiesK, krInd, deltaT) { + // newX = x(t) + k(kInd)x * delta + let newBodies = bodies.map((v, i) => { + let newBody = v.clone(); + newBody.position.add(bodiesK[i].kx[krInd].clone() + .multiplyScalar(deltaT)); + return newBody; + }); + // accel at newX + return this.force.getForces(newBodies) + .map((v, i) => v.divideScalar(bodies[i].mass)); + } + /** + * Get intermediate position rate values. + * @param bodies current bodies. + * @param bodiesK intermediate kinematic rate values for all bodies. + * @param kInd index of intermediate kinematic rate value to base the new intermediate value on. + * @param deltaT time step. + * @returns next intermediate position rate values for all bodies. + * @hidden + */ + getInterKX(bodies, bodiesK, kInd, deltaT) { + // v(t) + k(kInd)v * deltaT + return bodies.map((v, i) => v.velocity.clone() + .add(bodiesK[i].kv[kInd].clone() + .multiplyScalar(deltaT))); + } +} +//# sourceMappingURL=SimulateFunction.js.map \ No newline at end of file diff --git a/dist/src/library/SimulateFunction.js.map b/dist/src/library/SimulateFunction.js.map new file mode 100644 index 0000000..a491a01 --- /dev/null +++ b/dist/src/library/SimulateFunction.js.map @@ -0,0 +1 @@ +{"version":3,"file":"SimulateFunction.js","sourceRoot":"","sources":["../../../src/library/SimulateFunction.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/src/library/Transformation.js b/dist/src/library/Transformation.js new file mode 100644 index 0000000..ea1384a --- /dev/null +++ b/dist/src/library/Transformation.js @@ -0,0 +1,91 @@ +import { Vector3 } from 'three'; +/** + * Frame of reference transformation to the center of the first body in the system. + * @category Transformations + */ +export class BodyCenterTransformation { + /** + * Transform the frame of reference to the center of the first body in the system. + * @param state state to transform. + * @returns transformed state. + */ + transform(state) { + const transform = state.bodies[0].position.clone(); + state.bodies.forEach((b) => { + b.position.sub(transform); + }); + return state; + } +} +/** + * Frame of reference transformation to the center of mass of the system. + * @category Transformations + */ +export class CoMTransformation { + /** + * Transform the frame of reference to the center of mass of the system. + * @param state state to transform. + * @returns transformed state. + */ + transform(state) { + let totalMass = 0; + let com = new Vector3(); + state.bodies.forEach((b) => { + totalMass += b.mass; + com.add(b.position.clone() + .multiplyScalar(b.mass)); + }); + com.divideScalar(totalMass); + state.bodies.forEach((b) => { + b.position.sub(com); + }); + return state; + } +} +/** + * Frame of reference transformation around an axis by an angle. Makes sense to this transformation only during initialization of the universe and not at every time step. + * @category Transformations + */ +export class RotateTransformation { + /** + * Create a new RotateTransformer. + * @param axis axis to rotate around. + * @param angle angle to rotate by. + */ + constructor(axis, angle) { + this.axis = axis; + this.angle = angle; + } + /** + * Transform the frame of reference around an axis by an angle. + * @param state state to transform. + * @returns transformed state. + */ + transform(state) { + state.bodies.forEach((b) => { + b.position.applyAxisAngle(this.axis, this.angle); + b.velocity.applyAxisAngle(this.axis, this.angle); + b.acceleration.applyAxisAngle(this.axis, this.angle); + }); + return state; + } +} +// export class PinTransformer implements Transformer { +// readonly axis: Vector3; +// readonly index: number; +// constructor(axis: Vector3, index: number) { +// this.axis = axis; +// this.index = index +// } +// transform(state: State): State { +// const angle = state.bodies[this.index].position.clone().angleTo(this.axis); +// const pivot = state.bodies[this.index].position.clone().cross(this.axis.clone()).normalize(); +// state.bodies.forEach((b) => { +// b.position.applyAxisAngle(pivot.clone(), angle); +// b.velocity.applyAxisAngle(pivot.clone(), angle); +// b.acceleration.applyAxisAngle(pivot.clone(), angle); +// }); +// return state; +// } +// } +//# sourceMappingURL=Transformation.js.map \ No newline at end of file diff --git a/dist/src/library/Transformation.js.map b/dist/src/library/Transformation.js.map new file mode 100644 index 0000000..61b9676 --- /dev/null +++ b/dist/src/library/Transformation.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Transformation.js","sourceRoot":"","sources":["../../../src/library/Transformation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAIhC;;;GAGG;AACH,MAAM,OAAO,wBAAwB;IACnC;;;;OAIG;IACH,SAAS,CAAC,KAAY;QACpB,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnD,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACzB,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IAC5B;;;;OAIG;IACH,SAAS,CAAC,KAAY;QACpB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,GAAG,GAAG,IAAI,OAAO,EAAE,CAAC;QACxB,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACzB,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC;YACpB,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE;iBACvB,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC5B,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACzB,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,oBAAoB;IAI/B;;;;OAIG;IACH,YAAY,IAAa,EAAE,KAAa;QACtC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,KAAY;QACpB,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACzB,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACjD,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACjD,CAAC,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED,uDAAuD;AACvD,4BAA4B;AAC5B,4BAA4B;AAE5B,gDAAgD;AAChD,wBAAwB;AACxB,yBAAyB;AACzB,MAAM;AAEN,qCAAqC;AACrC,kFAAkF;AAClF,oGAAoG;AACpG,oCAAoC;AACpC,yDAAyD;AACzD,yDAAyD;AACzD,6DAA6D;AAC7D,UAAU;AACV,oBAAoB;AACpB,MAAM;AACN,IAAI"} \ No newline at end of file diff --git a/dist/src/library/Visualizer.js b/dist/src/library/Visualizer.js new file mode 100644 index 0000000..01cfd2e --- /dev/null +++ b/dist/src/library/Visualizer.js @@ -0,0 +1,1035 @@ +import GUI from 'lil-gui'; +import Plotly from 'plotly.js-dist'; +import * as THREE from 'three'; +import { OrbitControls, ViewHelper } from 'three/examples/jsm/Addons'; +import Stats from 'three/examples/jsm/libs/stats.module'; +let animationId = null; +/** + * Clips a number to a minimum and maximum value. + * @param x number to clip. + * @param min minimum value. + * @param max maximum value. + * @returns clipped value. + */ +function clipMinMax(x, min, max) { + if (x < min) + return min; + if (x > max) + return max; + return x; +} +/** + * Container object for body trails in a 2D universe based in Plotly. + */ +class PlotlyUniverseTrail { + /** + * Constructor for PlotlyUniverseTrail + * @param maxTrailLength max number of trail points to keep. + * @param color color of the trail. + */ + constructor(maxTrailLength, color) { + this.data = { + x: [], + y: [], + mode: 'markers', + marker: { + size: 1, + color: 'white', + }, + }; + this.data.marker.color = color; + this.trailLength = 0; + this.maxTrailLength = maxTrailLength; + this.trailInd = 0; + } + /** + * Add a trail point to the trail data, or replace an existing trail point if the max trail length has been reached. + * @param x x position. + * @param y y position. + */ + addTrail(x, y) { + if (this.trailLength < this.maxTrailLength) { + this.data.x.push(x); + this.data.y.push(y); + this.trailLength++; + } + else { + this.data.x[this.trailInd] = x; + this.data.y[this.trailInd] = y; + this.trailInd = (this.trailInd + 1) % this.trailLength; + } + } + /** + * Pop all trail points from the trail data. + */ + popAllTrails() { + this.data.x = []; + this.data.y = []; + this.trailLength = 0; + this.trailInd = 0; + } +} +/** + * 2D real-time visualizer using Plotly. + * @category Visualizers + */ +export class RealTimeVisualizer { + /** + * Constructor for RealTimeVisualizer + * @param simulation simulation object + */ + constructor(simulation) { + this.divId = ''; + this.universeTrails = []; + this.simulation = simulation; + } + /** + * Adds default controls using lil-gui to the visualization. + * @param parentElement parent element to place the controller div in. + */ + addControls(parentElement) { + const gui = new GUI({ + container: parentElement, + }); + gui.domElement.style.position = 'absolute'; + gui.domElement.style.top = '0'; + gui.domElement.style.left = '0'; + gui.domElement.style.zIndex = '1000'; + const config = this.simulation.controls; + gui.add(config, 'speed'); + gui.add(config, 'showTrails') + .onChange((value) => { + if (value === false) { + this.universeTrails.forEach((ut) => ut.popAllTrails()); + } + config.showTrails = value; + }); + const showUniverseFolder = gui.addFolder('Show Universe'); + showUniverseFolder.open(false); + this.simulation.universes.forEach((u, i) => { + showUniverseFolder + .add(config.showUniverse, u.label) + .onChange((value) => { + if (value === false) { + this.universeTrails[i].popAllTrails(); + } + config.showUniverse[u.label] = value; + }); + }); + } + /** + * Simulate and play the visualization. + * @param divId div id to render the visualization in. + * @param width width of the visualization. + * @param height height of the visualization. + */ + start(divId, width, height) { + if (this.divId !== '') { + // throw new Error( + // 'Simulation already playing. Stop the current playtime before initiating a new one.', + // ); + console.error('Simulation already playing. Stop the current playtime before initiating a new one.'); + return; + } + this.divId = divId; + let element = document.getElementById(divId); + if (element === null) { + return; + } + // const width = element.clientWidth; + // const height = element.clientHeight; + let maxWidth = 0; + let maxHeight = 0; + this.simulation.universes.forEach((u) => u.currState.bodies.forEach((b) => { + maxWidth = Math.max(maxWidth, Math.abs(b.position.x)); + maxHeight = Math.max(maxHeight, Math.abs(b.position.y)); + })); + const scale = 0.5 * Math.min(height / maxHeight, width / maxWidth); + const layout = { + paper_bgcolor: '#000000', + plot_bgcolor: '#000000', + font: { + color: '#bfbfbf', + }, + xaxis: { + autorange: false, + range: [-(width / 2) / scale, width / 2 / scale], + }, + yaxis: { + autorange: false, + range: [-(height / 2) / scale, height / 2 / scale], + }, + // uirevision: 'true', + showlegend: false, + width, + height, + }; + if (this.simulation.controller === 'ui') { + this.addControls(element); + } + let stats; + if (this.simulation.showDebugInfo) { + stats = new Stats(); + stats.dom.style.position = 'absolute'; + stats.dom.style.bottom = '0px'; + stats.dom.style.removeProperty('top'); + element.appendChild(stats.dom); + } + const init_data = this.simulation.universes.flatMap((uni) => { + const currTrail = new PlotlyUniverseTrail(this.simulation.getMaxTrailLength(), typeof uni.color === 'string' ? uni.color : uni.color[0]); + this.universeTrails.push(currTrail); + const currData = { + x: uni.currState.bodies.map((body) => body.position.x), + y: uni.currState.bodies.map((body) => body.position.y), + type: 'scatter', + mode: 'markers', + marker: { + color: uni.color, + sizemin: 6, + size: uni.currState.bodies.map((body) => Math.min(10, body.mass)), + }, + }; + if (this.simulation.getShowTrails()) { + uni.currState.bodies.forEach((b) => { + currTrail.addTrail(b.position.x, b.position.y); + }); + return [currData, currTrail.data]; + } + return [ + currData, + { + x: [], + y: [], + }, + ]; + }); + Plotly.newPlot(divId, init_data, layout, { + scrollZoom: true, + modeBarButtonsToRemove: [ + 'lasso2d', + 'select2d', + 'toImage', + 'resetScale2d', + ], + }); + const timePerFrame = 1000 / this.simulation.maxFrameRate; + if (animationId !== null) + return; + let lastPaintTimestampMs = 0; + let lastSimTimestampMs = 0; + /** + * Simulate a step in the simulation + * @param timestampMs current timestamp in milliseconds, sourced from requestAnimationFrame + */ + const step = (timestampMs) => { + this.simulation.simulateStep((this.simulation.controls.speed + * Math.min(timestampMs - lastSimTimestampMs, 33.33)) + / 1000); + lastSimTimestampMs = timestampMs; + }; + /** + * Paint the visualization + * @param timestampMs current timestamp in milliseconds, provided by requestAnimationFrame + */ + const paint = (timestampMs) => { + if (this.simulation.controls.speed === 0 + || this.simulation.controls.paused) { + animationId = requestAnimationFrame(paint); + return; + } + step(timestampMs); + if (timePerFrame > 0 + && timestampMs - lastPaintTimestampMs < timePerFrame) { + animationId = requestAnimationFrame(paint); + return; + } + lastPaintTimestampMs = timestampMs; + const new_data = this.simulation.universes.flatMap((uni, i) => { + if (!this.simulation.getShowUniverse(uni.label)) { + return [ + { + x: [], + y: [], + }, + {}, + ]; + } + const currData = { + x: uni.currState.bodies.map((body) => body.position.x), + y: uni.currState.bodies.map((body) => body.position.y), + hovertext: uni.currState.bodies.map((body) => body.label), + marker: { + size: uni.currState.bodies.map((body) => Math.min(10, body.mass)), + color: uni.color, + sizemin: 6, + }, + mode: 'markers', + }; + let trailData = {}; + if (this.simulation.getShowTrails()) { + const currTrail = this.universeTrails[i]; + uni.currState.bodies.forEach((b) => { + currTrail.addTrail(b.position.x, b.position.y); + }); + trailData = currTrail.data; + } + return [currData, trailData]; + }); + Plotly.react(divId, new_data, layout); + if (this.simulation.showDebugInfo && stats) { + stats.update(); + } + animationId = requestAnimationFrame(paint); + }; + animationId = requestAnimationFrame(paint); + } + /** + * Stop the simulation and visualization. + */ + stop() { + Plotly.purge(this.divId); + this.divId = ''; + this.universeTrails.forEach((ut) => { + ut.popAllTrails(); + }); + this.universeTrails = []; + } +} +/** + * Container object for body trails in a 3D universe based in Three.js. + */ +class ThreeUniverseTrail { + /** + * Constructor for ThreeUniverseTrail. + * @param maxTrailLength max number of trail points to keep. + * @param color color of the trace points. + * @param scene scene to add trail points object to. + * @param scale scale of the visualizationl, used to set the size of the trail point. + */ + constructor(maxTrailLength, color, scene, scale) { + const geometry = new THREE.BufferGeometry(); + geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(0), 3)); + this.trails = new THREE.Points(geometry, new THREE.PointsMaterial({ + color, + size: 0.005 * scale, + })); + scene.add(this.trails); + this.trailInd = 0; + this.trailLength = 0; + this.maxTrailLength = maxTrailLength; + } + /** + * Add a trail point at the given position to the scene. Replace an existing trail point if the max trail length has been reached. + * @param pos position to add trace point at. + */ + addTrail(pos) { + if (this.trailLength < this.maxTrailLength) { + this.trails.visible = true; + this.trailLength++; + const posArray = new Float32Array(this.trailLength * 3); + posArray.set(this.trails.geometry.attributes.position.array); + posArray.set(pos.toArray(), this.trailLength * 3 - 3); + this.trails.geometry.setAttribute('position', new THREE.BufferAttribute(posArray, 3)); + this.trails.geometry.attributes.position.needsUpdate = true; + } + else { + this.trails.geometry.attributes.position.array.set(pos.toArray(), this.trailInd * 3); + this.trailInd = (this.trailInd + 1) % this.maxTrailLength; + this.trails.geometry.attributes.position.needsUpdate = true; + } + } + /** + * Pop all trail points. + */ + popAllTrails() { + this.trails.visible = false; + this.trails.geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(0), 3)); + this.trailInd = 0; + this.trailLength = 0; + } +} +/** + * 3D real-time visualizer using Three.js. + * @category Visualizers + */ +export class RealTimeVisualizer3D { + /** + * Constructor for RealTimeVisualizer3D. + * @param simulation simulation object. + */ + constructor(simulation) { + this.universeTrails = []; + this.simulation = simulation; + } + /** + * Adds default controls to the visualization. + * @param parentElement parent element to place the controller div in. + */ + addControls(parentElement) { + const gui = new GUI({ + container: parentElement, + }); + gui.domElement.style.position = 'absolute'; + gui.domElement.style.top = '0'; + gui.domElement.style.left = '0'; + gui.domElement.style.zIndex = '1000'; + const config = this.simulation.controls; + gui.add(config, 'speed'); + gui.add(config, 'showTrails') + .onChange((value) => { + if (value === false) { + this.universeTrails.forEach((ut) => { + ut.popAllTrails(); + }); + } + config.showTrails = value; + }); + const showUniverseFolder = gui.addFolder('Show Universe'); + showUniverseFolder.open(false); + this.simulation.universes.forEach((u, i) => { + showUniverseFolder + .add(config.showUniverse, u.label) + .onChange((value) => { + if (value === false) { + this.universeTrails[i].popAllTrails(); + } + config.showUniverse[u.label] = value; + }); + }); + } + /** + * Simulate and play the visualization + * @param divId div id to render the visualization in + * @param width width of the visualization. + * @param height height of the visualization. + */ + start(divId, width, height) { + if (this.scene !== undefined) { + // throw new Error( + // 'Simulation already playing. Stop the current playtime before initiating a new one.', + // ); + console.error('Simulation already playing. Stop the current playtime before initiating a new one.'); + return; + } + let element = document.getElementById(divId); + if (element === null) { + return; + } + element.style.position = 'relative'; + // const width = element.clientWidth; + // const height = element.clientHeight; + let maxWidth = 0; + let maxHeight = 0; + this.simulation.universes.forEach((u) => u.currState.bodies.forEach((b) => { + maxWidth = Math.max(maxWidth, Math.abs(b.position.x)); + maxHeight = Math.max(maxHeight, Math.abs(b.position.y)); + })); + const scale = 0.5 * Math.min(height / maxHeight, width / maxWidth); + this.scene = new THREE.Scene(); + const camera = new THREE.OrthographicCamera(width / -2, width / 2, height / 2, height / -2, 0, 10000000000); + camera.position.set(0, 0, Math.max(width, height)); + const renderer = new THREE.WebGLRenderer(); + renderer.setSize(width, height); + renderer.autoClear = false; + element.appendChild(renderer.domElement); + let stats; + if (this.simulation.showDebugInfo) { + stats = new Stats(); + stats.dom.style.position = 'absolute'; + stats.dom.style.right = '0px'; + stats.dom.style.removeProperty('left'); + element.appendChild(stats.dom); + } + if (this.simulation.controller === 'ui') { + this.addControls(element); + } + // const earthDiv = document.createElement('div'); + // earthDiv.className = 'label'; + // earthDiv.textContent = 'Earthhgkjfdghkjfgh'; + // earthDiv.style.backgroundColor = 'transparent'; + // earthDiv.style.color = 'white'; + // earthDiv.style.fontFamily = 'sans-serif'; + // earthDiv.style.background = 'rgba(0, 0, 0, 0.6)'; + // const earthLabel = new CSS2DObject(earthDiv); + // earthLabel.position.set(0, 0, 0); + // earthLabel.center.set(0, 1); + // // arr[0].add(earthLabel); + // earthLabel.layers.set(0); + // const labelRenderer = new CSS2DRenderer(); + // labelRenderer.setSize(width, height); + // labelRenderer.domElement.style.position = 'absolute'; + // labelRenderer.domElement.style.top = '0px'; + // element.appendChild(labelRenderer.domElement); + const orbitControls = new OrbitControls(camera, renderer.domElement); + orbitControls.listenToKeyEvents(window); + orbitControls.update(); + const axesHelper = new THREE.AxesHelper(width); + this.scene.add(axesHelper); + const viewHelper = new ViewHelper(camera, renderer.domElement); + // var m: Map = new Map(); + let arr = []; + this.simulation.universes.forEach((u) => { + this.universeTrails.push(new ThreeUniverseTrail(this.simulation.maxTrailLength, typeof u.color === 'string' ? u.color : u.color[0], this.scene, scale)); + u.currState.bodies.forEach((b) => { + const sph = new THREE.SphereGeometry(clipMinMax(Math.log2(b.mass) - 70, 10, 40), 8, 8); + const curr = new THREE.WireframeGeometry(sph); + const line = new THREE.LineSegments(curr, new THREE.LineBasicMaterial({ + // @ts-ignore + color: new THREE.Color(u.color), + })); + this.scene.add(line); + line.position.copy(b.position.clone() + .multiplyScalar(scale)); + // m.set(u.label + " " + b.label, line); + arr.push(line); + }); + }); + // arr[0].add(earthLabel) + const timePerFrame = 1000 / this.simulation.maxFrameRate; + let lastSimTimestampMs = performance.now(); + let lastPaint = performance.now(); + /** + * Simulate a step in the simulation + * @param timestampMs current timestamp in milliseconds, sourced from requestAnimationFrame + */ + const step = (timestampMs) => { + this.simulation.simulateStep((this.simulation.controls.speed + * Math.min(timestampMs - lastSimTimestampMs, 16.67)) + / 1000); + lastSimTimestampMs = timestampMs; + }; + /** + * Paint the visualization + * @param timestampMs current timestamp in milliseconds, provided by requestAnimationFrame + */ + const paint = (timestampMs) => { + if (this.simulation.controls.speed === 0 + || this.simulation.controls.paused) { + requestAnimationFrame(paint); + renderer.clear(); + renderer.render(this.scene, camera); + viewHelper.render(renderer); + // labelRenderer.render(scene, camera); + orbitControls.update(); + return; + } + step(timestampMs); + if (timePerFrame > 0 && timestampMs - lastPaint < timePerFrame) { + requestAnimationFrame(paint); + renderer.clear(); + renderer.render(this.scene, camera); + viewHelper.render(renderer); + // labelRenderer.render(scene, camera); + orbitControls.update(); + return; + } + lastPaint = timestampMs; + if (this.simulation.showDebugInfo && stats) { + stats.update(); + } + let ind = 0; + this.simulation.universes.forEach((u, i) => { + if (this.simulation.controls.showUniverse[u.label]) { + u.currState.bodies.forEach((b) => { + arr[ind].visible = true; + arr[ind].position.copy(b.position.clone() + .multiplyScalar(scale)); + if (this.simulation.controls.showTrails) { + this.universeTrails[i].addTrail(arr[ind].position); + } + ind++; + }); + } + else { + u.currState.bodies.forEach((b) => { + arr[ind].visible = false; + ind++; + }); + } + }); + requestAnimationFrame(paint); + renderer.clear(); + renderer.render(this.scene, camera); + viewHelper.render(renderer); + // labelRenderer.render(scene, camera); + orbitControls.update(); + }; + requestAnimationFrame(paint); + } + /** + * Stop the simulation and visualization. + */ + stop() { + var _a; + (_a = this.scene) === null || _a === void 0 ? void 0 : _a.clear(); + this.scene = undefined; + this.universeTrails.forEach((ut) => { + ut.popAllTrails(); + }); + this.universeTrails = []; + } +} +/** + * 2D recording visualizer using Plotly. + * @category Visualizers + */ +export class RecordingVisualizer { + /** + * Constructor for RealTimeVisualizer + * @param simulation simulation object + */ + constructor(simulation) { + this.divId = ''; + this.universeTrails = []; + this.simulation = simulation; + } + /** + * Adds default controls using lil-gui to the visualization. + * @param parentElement parent element to place the controller div in. + */ + addControls(parentElement) { + const gui = new GUI({ + container: parentElement, + }); + gui.domElement.style.position = 'absolute'; + gui.domElement.style.top = '0'; + gui.domElement.style.left = '0'; + gui.domElement.style.zIndex = '1000'; + const config = this.simulation.controls; + gui.add(config, 'speed'); + gui.add(config, 'showTrails') + .onChange((value) => { + if (value === false) { + this.universeTrails.forEach((ut) => ut.popAllTrails()); + } + config.showTrails = value; + }); + const showUniverseFolder = gui.addFolder('Show Universe'); + showUniverseFolder.open(false); + this.simulation.universes.forEach((u, i) => { + showUniverseFolder + .add(config.showUniverse, u.label) + .onChange((value) => { + if (value === false) { + this.universeTrails[i].popAllTrails(); + } + config.showUniverse[u.label] = value; + }); + }); + } + /** + * Simulate and play the visualization. + * @param divId div id to render the visualization in. + * @param width width of the visualization. + * @param height height of the visualization. + * @param recordFor number of seconds to record for.. + */ + start(divId, width, height, recordFor) { + if (this.divId !== '') { + // throw new Error( + // 'Simulation already playing. Stop the current playtime before initiating a new one.', + // ); + console.error('Simulation already playing. Stop the current playtime before initiating a new one.'); + return; + } + this.divId = divId; + let element = document.getElementById(divId); + if (element === null) { + return; + } + // const width = element.clientWidth; + // const height = element.clientHeight; + let maxWidth = 0; + let maxHeight = 0; + this.simulation.universes.forEach((u) => u.currState.bodies.forEach((b) => { + maxWidth = Math.max(maxWidth, Math.abs(b.position.x)); + maxHeight = Math.max(maxHeight, Math.abs(b.position.y)); + })); + const scale = 0.5 * Math.min(height / maxHeight, width / maxWidth); + const recordedFrames = []; + const totalFrames = this.simulation.maxFrameRate * recordFor; + let playInd = 1; + this.simulation.universes.forEach((u) => { + recordedFrames.push([u.currState.clone()]); + }); + for (let i = 0; i < totalFrames; i++) { + this.simulation.simulateStep(1 / this.simulation.maxFrameRate); + this.simulation.universes.forEach((u, j) => { + recordedFrames[j].push(u.currState.clone()); + }); + } + const layout = { + paper_bgcolor: '#000000', + plot_bgcolor: '#000000', + font: { + color: '#bfbfbf', + }, + xaxis: { + autorange: false, + range: [-(width / 2) / scale, width / 2 / scale], + }, + yaxis: { + autorange: false, + range: [-(height / 2) / scale, height / 2 / scale], + }, + // uirevision: 'true', + showlegend: false, + width, + height, + }; + if (this.simulation.controller === 'ui') { + this.addControls(element); + } + let stats; + if (this.simulation.showDebugInfo) { + stats = new Stats(); + stats.dom.style.position = 'absolute'; + stats.dom.style.bottom = '0px'; + stats.dom.style.removeProperty('top'); + element.appendChild(stats.dom); + } + const init_data = this.simulation.universes.flatMap((uni) => { + const currTrail = new PlotlyUniverseTrail(this.simulation.getMaxTrailLength(), typeof uni.color === 'string' ? uni.color : uni.color[0]); + this.universeTrails.push(currTrail); + const currData = { + x: uni.currState.bodies.map((body) => body.position.x), + y: uni.currState.bodies.map((body) => body.position.y), + type: 'scatter', + mode: 'markers', + marker: { + color: uni.color, + sizemin: 6, + size: uni.currState.bodies.map((body) => Math.min(10, body.mass)), + }, + }; + if (this.simulation.getShowTrails()) { + uni.currState.bodies.forEach((b) => { + currTrail.addTrail(b.position.x, b.position.y); + }); + return [currData, currTrail.data]; + } + return [ + currData, + { + x: [], + y: [], + }, + ]; + }); + Plotly.newPlot(divId, init_data, layout, { + scrollZoom: true, + modeBarButtonsToRemove: [ + 'zoom2d', + 'lasso2d', + 'select2d', + 'toImage', + 'resetScale2d', + ], + }); + if (animationId !== null) + return; + /** + * Paint the visualization + * @param timestampMs current timestamp in milliseconds, provided by requestAnimationFrame + */ + const paint = (timestampMs) => { + if (this.simulation.controls.speed === 0 + || this.simulation.controls.paused) { + animationId = requestAnimationFrame(paint); + return; + } + const currPlayInd = Math.round(playInd); + const new_data = this.simulation.universes.flatMap((uni, i) => { + if (!this.simulation.getShowUniverse(uni.label)) { + return [ + { + x: [], + y: [], + }, + {}, + ]; + } + const currState = recordedFrames[i][currPlayInd]; + const currData = { + x: currState.bodies.map((body) => body.position.x), + y: currState.bodies.map((body) => body.position.y), + hovertext: currState.bodies.map((body) => body.label), + marker: { + size: currState.bodies.map((body) => Math.min(10, body.mass)), + color: uni.color, + sizemin: 6, + }, + mode: 'markers', + }; + let trailData = {}; + if (this.simulation.getShowTrails()) { + const currTrail = this.universeTrails[i]; + currState.bodies.forEach((b) => { + currTrail.addTrail(b.position.x, b.position.y); + }); + trailData = currTrail.data; + } + return [currData, trailData]; + }); + Plotly.react(divId, new_data, layout); + if (this.simulation.showDebugInfo && stats) { + stats.update(); + } + playInd = Math.round(playInd + this.simulation.controls.speed); + if (playInd < 0) { + if (this.simulation.looped) { + playInd = ((playInd % totalFrames) + totalFrames) % totalFrames; + } + else { + playInd = 0; + } + } + else if (playInd >= totalFrames) { + if (this.simulation.looped) { + playInd %= totalFrames; + } + else { + playInd = totalFrames - 1; + } + } + animationId = requestAnimationFrame(paint); + }; + animationId = requestAnimationFrame(paint); + } + /** + * Stop the simulation and visualization. + */ + stop() { + Plotly.purge(this.divId); + this.divId = ''; + this.universeTrails = []; + } +} +/** + * 3D recording visualizer using Three.js. + * @category Visualizers + */ +export class RecordingVisualizer3D { + /** + * Constructor for RealTimeVisualizer3D. + * @param simulation simulation object. + */ + constructor(simulation) { + this.universeTrails = []; + this.simulation = simulation; + } + /** + * Adds default controls to the visualization. + * @param parentElement parent element to place the controller div in. + */ + addControls(parentElement) { + const gui = new GUI({ + container: parentElement, + }); + gui.domElement.style.position = 'absolute'; + gui.domElement.style.top = '0'; + gui.domElement.style.left = '0'; + gui.domElement.style.zIndex = '1000'; + const config = this.simulation.controls; + gui.add(config, 'speed'); + gui.add(config, 'showTrails') + .onChange((value) => { + if (value === false) { + this.universeTrails.forEach((ut) => { + ut.popAllTrails(); + }); + } + config.showTrails = value; + }); + const showUniverseFolder = gui.addFolder('Show Universe'); + showUniverseFolder.open(false); + this.simulation.universes.forEach((u, i) => { + showUniverseFolder + .add(config.showUniverse, u.label) + .onChange((value) => { + if (value === false) { + this.universeTrails[i].popAllTrails(); + } + config.showUniverse[u.label] = value; + }); + }); + } + /** + * Simulate and play the visualization + * @param divId div id to render the visualization in. + * @param width width of the visualization. + * @param height height of the visualization. + * @param recordFor number of seconds to record for. + */ + start(divId, width, height, recordFor) { + if (this.scene !== undefined) { + // throw new Error( + // 'Simulation already playing. Stop the current playtime before initiating a new one.', + // ); + console.error('Simulation already playing. Stop the current playtime before initiating a new one.'); + return; + } + let element = document.getElementById(divId); + if (element === null) { + return; + } + // const width = element.clientWidth; + // const height = element.clientHeight; + let maxWidth = 0; + let maxHeight = 0; + this.simulation.universes.forEach((u) => u.currState.bodies.forEach((b) => { + maxWidth = Math.max(maxWidth, Math.abs(b.position.x)); + maxHeight = Math.max(maxHeight, Math.abs(b.position.y)); + })); + const scale = 0.5 * Math.min(height / maxHeight, width / maxWidth); + this.scene = new THREE.Scene(); + const camera = new THREE.OrthographicCamera(width / -2, width / 2, height / 2, height / -2, 0, 10000000000); + camera.position.set(0, 0, Math.max(width, height)); + const renderer = new THREE.WebGLRenderer(); + renderer.setSize(width, height); + renderer.autoClear = false; + element.appendChild(renderer.domElement); + let stats; + if (this.simulation.showDebugInfo) { + stats = new Stats(); + stats.dom.style.position = 'absolute'; + stats.dom.style.right = '0px'; + stats.dom.style.removeProperty('left'); + element.appendChild(stats.dom); + } + if (this.simulation.controller === 'ui') { + this.addControls(element); + } + // const earthDiv = document.createElement('div'); + // earthDiv.className = 'label'; + // earthDiv.textContent = 'Earthhgkjfdghkjfgh'; + // earthDiv.style.backgroundColor = 'transparent'; + // earthDiv.style.color = 'white'; + // earthDiv.style.fontFamily = 'sans-serif'; + // earthDiv.style.background = 'rgba(0, 0, 0, 0.6)'; + // const earthLabel = new CSS2DObject(earthDiv); + // earthLabel.position.set(0, 0, 0); + // earthLabel.center.set(0, 1); + // // arr[0].add(earthLabel); + // earthLabel.layers.set(0); + // const labelRenderer = new CSS2DRenderer(); + // labelRenderer.setSize(width, height); + // labelRenderer.domElement.style.position = 'absolute'; + // labelRenderer.domElement.style.top = '0px'; + // element.appendChild(labelRenderer.domElement); + const orbitControls = new OrbitControls(camera, renderer.domElement); + orbitControls.listenToKeyEvents(window); + orbitControls.update(); + const axesHelper = new THREE.AxesHelper(width); + this.scene.add(axesHelper); + const viewHelper = new ViewHelper(camera, renderer.domElement); + // var m: Map = new Map(); + let arr = []; + this.simulation.universes.forEach((u) => { + this.universeTrails.push(new ThreeUniverseTrail(this.simulation.maxTrailLength, typeof u.color === 'string' ? u.color : u.color[0], this.scene, scale)); + u.currState.bodies.forEach((b) => { + const sph = new THREE.SphereGeometry(clipMinMax(Math.log2(b.mass) - 70, 10, 40), 8, 8); + const curr = new THREE.WireframeGeometry(sph); + const line = new THREE.LineSegments(curr, new THREE.LineBasicMaterial({ + // @ts-ignore + color: new THREE.Color(u.color), + })); + this.scene.add(line); + line.position.copy(b.position.clone() + .multiplyScalar(scale)); + // m.set(u.label + " " + b.label, line); + arr.push(line); + }); + }); + // arr[0].add(earthLabel) + const recordedFrames = []; + const totalFrames = this.simulation.maxFrameRate * recordFor; + let playInd = 1; + this.simulation.universes.forEach((u) => { + recordedFrames.push([u.currState.clone()]); + }); + for (let i = 0; i < totalFrames; i++) { + this.simulation.simulateStep(1 / this.simulation.maxFrameRate); + this.simulation.universes.forEach((u, j) => { + recordedFrames[j].push(u.currState.clone()); + }); + } + /** + * Paint the visualization + * @param timestampMs current timestamp in milliseconds, provided by requestAnimationFrame + */ + const paint = (timestampMs) => { + if (this.simulation.controls.speed === 0 + || this.simulation.controls.paused) { + requestAnimationFrame(paint); + renderer.clear(); + renderer.render(this.scene, camera); + viewHelper.render(renderer); + // labelRenderer.render(scene, camera); + orbitControls.update(); + return; + } + let ind = 0; + this.simulation.universes.forEach((u, i) => { + if (this.simulation.controls.showUniverse[u.label]) { + const currState = recordedFrames[i][playInd]; + currState.bodies.forEach((b) => { + arr[ind].visible = true; + arr[ind].position.copy(b.position.clone() + .multiplyScalar(scale)); + if (this.simulation.controls.showTrails) { + this.universeTrails[i].addTrail(arr[ind].position); + } + ind++; + }); + } + else { + u.currState.bodies.forEach(() => { + arr[ind].visible = false; + ind++; + }); + } + }); + if (this.simulation.showDebugInfo && stats) { + stats.update(); + } + playInd = Math.round(playInd + this.simulation.controls.speed); + if (playInd < 0) { + if (this.simulation.looped) { + playInd = ((playInd % totalFrames) + totalFrames) % totalFrames; + } + else { + playInd = 0; + } + } + else if (playInd >= totalFrames) { + if (this.simulation.looped) { + playInd %= totalFrames; + } + else { + playInd = totalFrames - 1; + } + } + requestAnimationFrame(paint); + renderer.clear(); + renderer.render(this.scene, camera); + viewHelper.render(renderer); + // labelRenderer.render(scene, camera); + orbitControls.update(); + }; + requestAnimationFrame(paint); + } + /** + * Stop the simulation and visualization. + */ + stop() { + var _a; + (_a = this.scene) === null || _a === void 0 ? void 0 : _a.clear(); + this.scene = undefined; + this.universeTrails.forEach((ut) => { + ut.popAllTrails(); + }); + this.universeTrails = []; + } +} +//# sourceMappingURL=Visualizer.js.map \ No newline at end of file diff --git a/dist/src/library/Visualizer.js.map b/dist/src/library/Visualizer.js.map new file mode 100644 index 0000000..4d59043 --- /dev/null +++ b/dist/src/library/Visualizer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Visualizer.js","sourceRoot":"","sources":["../../../src/library/Visualizer.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/src/plotly.js b/dist/src/plotly.js new file mode 100644 index 0000000..49893ec --- /dev/null +++ b/dist/src/plotly.js @@ -0,0 +1,31 @@ +/** + * + */ +export class SimulationPlot { + /** + * Create a new SimulationPlot with the provided draw function, data, simulation, and layout. + * @param plotlyDrawFn draw function. + * @param data data to draw. + * @param sim simulation. + * @param layout layout of the plot. + */ + constructor(plotlyDrawFn, data, sim, layout) { + /** + * Returns a string representation of the object. + * @returns string representation of the object. + */ + this.toReplString = () => ''; + /** + * Draw the plot in the provided div. + * @param divId div id. + */ + this.draw = (divId) => { + this.plotlyDrawFn(divId, this.data, this.sim, this.layout); + }; + this.plotlyDrawFn = plotlyDrawFn; + this.data = data; + this.sim = sim; + this.layout = layout; + } +} +//# sourceMappingURL=plotly.js.map \ No newline at end of file diff --git a/dist/src/plotly.js.map b/dist/src/plotly.js.map new file mode 100644 index 0000000..72e1dcc --- /dev/null +++ b/dist/src/plotly.js.map @@ -0,0 +1 @@ +{"version":3,"file":"plotly.js","sourceRoot":"","sources":["../../src/plotly.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,OAAO,cAAc;IAKzB;;;;;;OAMG;IACH,YACE,YAAiB,EACjB,IAAU,EACV,GAAe,EACf,MAAuB;QAOzB;;;WAGG;QACI,iBAAY,GAAG,GAAG,EAAE,CAAC,kBAAkB,CAAC;QAE/C;;;WAGG;QACI,SAAI,GAAG,CAAC,KAAa,EAAE,EAAE;YAC9B,IAAI,CAAC,YAAY,CACf,KAAK,EACL,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,GAAG,EACR,IAAI,CAAC,MAAM,CACZ,CAAC;QACJ,CAAC,CAAC;QAtBA,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CAmBF"} \ No newline at end of file diff --git a/dist/src/CelestialBody.d.ts b/dist/types/src/CelestialBody.d.ts similarity index 100% rename from dist/src/CelestialBody.d.ts rename to dist/types/src/CelestialBody.d.ts diff --git a/dist/src/Force.d.ts b/dist/types/src/Force.d.ts similarity index 100% rename from dist/src/Force.d.ts rename to dist/types/src/Force.d.ts diff --git a/dist/src/SimulateFunction.d.ts b/dist/types/src/SimulateFunction.d.ts similarity index 100% rename from dist/src/SimulateFunction.d.ts rename to dist/types/src/SimulateFunction.d.ts diff --git a/dist/src/Simulation.d.ts b/dist/types/src/Simulation.d.ts similarity index 100% rename from dist/src/Simulation.d.ts rename to dist/types/src/Simulation.d.ts diff --git a/dist/src/State.d.ts b/dist/types/src/State.d.ts similarity index 100% rename from dist/src/State.d.ts rename to dist/types/src/State.d.ts diff --git a/dist/src/Transformation.d.ts b/dist/types/src/Transformation.d.ts similarity index 100% rename from dist/src/Transformation.d.ts rename to dist/types/src/Transformation.d.ts diff --git a/dist/src/Universe.d.ts b/dist/types/src/Universe.d.ts similarity index 100% rename from dist/src/Universe.d.ts rename to dist/types/src/Universe.d.ts diff --git a/dist/src/Visualizer.d.ts b/dist/types/src/Visualizer.d.ts similarity index 100% rename from dist/src/Visualizer.d.ts rename to dist/types/src/Visualizer.d.ts diff --git a/dist/src/index.d.ts b/dist/types/src/index.d.ts similarity index 74% rename from dist/src/index.d.ts rename to dist/types/src/index.d.ts index 2c66886..4e74496 100644 --- a/dist/src/index.d.ts +++ b/dist/types/src/index.d.ts @@ -3,7 +3,7 @@ * @author Yeluri Ketan */ import { CelestialBody } from './CelestialBody'; -import { type Force } from './Force'; +import { LambdaForce, type Force } from './Force'; import { CentripetalForce, CombinedForce, Gravity } from './library/Force'; import { ExplicitEulerSim, RungeKutta4Sim, SemiImplicitEulerSim, VelocityVerletSim } from './library/SimulateFunction'; import { LambdaSim, type SimulateFunction } from './SimulateFunction'; @@ -14,4 +14,4 @@ import { LambdaTransformation, type Transformation } from './Transformation'; import { Universe, type UniverseConfig } from './Universe'; import { RealTimeVisualizer, RealTimeVisualizer3D, RecordingVisualizer, RecordingVisualizer3D } from './library/Visualizer'; import { Vector3 } from 'three'; -export { BodyCenterTransformation, CelestialBody, CentripetalForce, CombinedForce, CoMTransformation, ExplicitEulerSim, Gravity, LambdaSim, LambdaTransformation, RealTimeVisualizer, RealTimeVisualizer3D, RecordingVisualizer, RecordingVisualizer3D, RotateTransformation, RungeKutta4Sim, SemiImplicitEulerSim, Simulation, State, Universe, Vector3, VelocityVerletSim, type ControllerType, type Force, type SimulateFunction, type Transformation, type UniverseConfig, type VisType, }; +export { BodyCenterTransformation, CelestialBody, CentripetalForce, CombinedForce, CoMTransformation, ExplicitEulerSim, Gravity, LambdaForce, LambdaSim, LambdaTransformation, RealTimeVisualizer, RealTimeVisualizer3D, RecordingVisualizer, RecordingVisualizer3D, RotateTransformation, RungeKutta4Sim, SemiImplicitEulerSim, Simulation, State, Universe, Vector3, VelocityVerletSim, type ControllerType, type Force, type SimulateFunction, type Transformation, type UniverseConfig, type VisType, }; diff --git a/dist/src/library/Force.d.ts b/dist/types/src/library/Force.d.ts similarity index 100% rename from dist/src/library/Force.d.ts rename to dist/types/src/library/Force.d.ts diff --git a/dist/src/library/SimulateFunction.d.ts b/dist/types/src/library/SimulateFunction.d.ts similarity index 100% rename from dist/src/library/SimulateFunction.d.ts rename to dist/types/src/library/SimulateFunction.d.ts diff --git a/dist/src/library/Transformation.d.ts b/dist/types/src/library/Transformation.d.ts similarity index 100% rename from dist/src/library/Transformation.d.ts rename to dist/types/src/library/Transformation.d.ts diff --git a/dist/src/library/Visualizer.d.ts b/dist/types/src/library/Visualizer.d.ts similarity index 100% rename from dist/src/library/Visualizer.d.ts rename to dist/types/src/library/Visualizer.d.ts diff --git a/dist/src/plotly.d.ts b/dist/types/src/plotly.d.ts similarity index 100% rename from dist/src/plotly.d.ts rename to dist/types/src/plotly.d.ts diff --git a/docs/assets/navigation.js b/docs/assets/navigation.js index d3eac64..033ebc0 100644 --- a/docs/assets/navigation.js +++ b/docs/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAACq2WS1PbMBSF/0pHa0NKAm3xkvAYhnYDaTaMF4p8k9xBj4x0zSTt5L93TENiWw/DwNbnnE9Xjyv58S8jWBPL2UWFskS9+DKTRjw5ljGxRFla0Cx/3LvGIMERcnlhyg3L2IrTkuVMSO4cuEFLPl6SkixjT6hLlp8Mf2yzPecBVSU5odE+5KAlCcQJAuH6cyr3W+MzWBeIviqp9BQEGTvywzvBy2b/HSxn5MojdEewJrCaS7YtGtxbTWDnXEBs4a+NFY2ace8fvCjtcYdn3/y1hutKi/aKNyhdUwo4sVy7ubGKR3Ftiw9rzv1lAvEDp8niCojLzhIczlzbkdq+sVEz1FDGUE05xbmx/Bkp0AA7IZV9904Wib2MLdvVeiVRIF1VEuwDKr/SriNV8k+uZiUPYvZSKn9f6QXcVUT8NAhp68muB4W3qm9uIVe6q6URSJspWAkURHqWN9xuH+24ItpzsW2vr926H8DGevR1PjFnunt+9WE9S/+x6kOGXMnDZuonoI8acqWon3znTTar+JVnNFkjJdjadRiK6sygrXZG+Xr+/eRsGHjtxkbPcdFltdU+1hRdqKDd53C6aOcrLvEP2NjM74HLCSo4OAMb53mSh8Fzjy7fwhxdpqnC2PpnKV2oZ3onM1xqwOZzi23xD10a3TfbCQAA" \ No newline at end of file +window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAACq2WTU/bQBCG/0q1Z0NKAm3xkfAhRHuBNBfkw2Y9SUbsR7Q7Rkmr/PfKNCS298MguPp95/HM7szYj38ZwZpYzi4qlCXqxZeZNOLJsYyJJcrSgmb54941BgmOkMsLU25YxlaclixnQnLnwA1a8vGSlGQZe0Jdsvxk+GOb7TkPqCrJCY32IQctSSBOEAiuH6fifmt8BusCoa9KKnoKgowd+cE7wYvN/jtYzsiVR+iOYE1gNZdsWzS4t5rAzrmA2MFfGysaOePeP3hR2u8dnn3zzxquKy3aJ96gdE0p4MRy7ebGKh7FtS0+rFn7SwHxhtNkcQXEZecIDj3XdqSub2zUDDWUMVRTTnFuLH9GCgzATkjF/uRqVvJIBg0xxXh3NxSJfogd/dV6JVEgXVUS7AMqP9uuo7/sIGYvpeLvK72Au4qInwYhbT25OUDhreqrLeRKbwZpBNJmClYCBZGe5Q0b8qNTW0TnNnbt9equZwpsbM5f64k50xP4qw/rWfrbqg8ZciWbzdSfkT5qyJWifvLenGxW8bVpNFkjJdjadXgV1TGDttp5y9fz7ydnw8AXc2z0HBddVlvtY03RhRLaPQ5HF+34ikv8AzZW+T1wOUEFB2fg4jxPshk89+jyLczRZZoqjK1/uNKJeqZ3MsOpBmw+t9gW/wBFz1T7HwoAAA==" \ No newline at end of file diff --git a/docs/assets/search.js b/docs/assets/search.js index b3369ca..6aaa028 100644 --- a/docs/assets/search.js +++ b/docs/assets/search.js @@ -1 +1 @@ -window.searchData = "data:application/octet-stream;base64,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"; \ No newline at end of file +window.searchData = "data:application/octet-stream;base64,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"; \ No newline at end of file diff --git a/docs/classes/BodyCenterTransformation.html b/docs/classes/BodyCenterTransformation.html index b688e25..25ba4ce 100644 --- a/docs/classes/BodyCenterTransformation.html +++ b/docs/classes/BodyCenterTransformation.html @@ -1,7 +1,7 @@ BodyCenterTransformation | nbody

Class BodyCenterTransformation

Frame of reference transformation to the center of the first body in the system.

-

Implements

Constructors

Implements

Constructors

Methods

Constructors

Methods

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/CelestialBody.html b/docs/classes/CelestialBody.html index e86e342..f9178a5 100644 --- a/docs/classes/CelestialBody.html +++ b/docs/classes/CelestialBody.html @@ -1,5 +1,5 @@ CelestialBody | nbody

Class CelestialBody

Represents a celestial body with all of its kinematic properties.

-

Constructors

Constructors

Properties

acceleration label mass @@ -12,14 +12,14 @@
  • position: Vector3

    position of the body.

  • velocity: Vector3

    velocity of the body.

  • acceleration: Vector3

    acceleration of the body.

    -
  • Returns CelestialBody

    Properties

    acceleration: Vector3

    Acceleration vector of the body.

    -
    label: string

    Label of the body.

    -
    mass: number

    Mean mass of the body.

    -
    position: Vector3

    Position vector of the body.

    -
    velocity: Vector3

    Velocity vector of the body.

    -

    Methods

    • Deep copy the current CelestialBody with the updated kinematic properties.

      +

    Returns CelestialBody

    Properties

    acceleration: Vector3

    Acceleration vector of the body.

    +
    label: string

    Label of the body.

    +
    mass: number

    Mean mass of the body.

    +
    position: Vector3

    Position vector of the body.

    +
    velocity: Vector3

    Velocity vector of the body.

    +

    Methods

    • Deep copy the current CelestialBody with the updated kinematic properties.

      Parameters

      • Optional position: Vector3

        new position.

      • Optional velocity: Vector3

        new velocity.

      • Optional acceleration: Vector3

        new acceleration.

      Returns CelestialBody

      a new CelestialBody instance with the updated properties.

      -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/CentripetalForce.html b/docs/classes/CentripetalForce.html index 01c5551..9b348a4 100644 --- a/docs/classes/CentripetalForce.html +++ b/docs/classes/CentripetalForce.html @@ -1,11 +1,11 @@ CentripetalForce | nbody

    Class CentripetalForce

    Represents a Centripetal force object. To be used to calculate the force required to keep the bodies in circular motion around a given center.

    -

    Implements

    Constructors

    Implements

    Constructors

    Properties

    Methods

    Constructors

    Properties

    center: Vector3

    Center of force.

    -

    Methods

    • Calculate the force required to keep the bodies in circular motion around the center. arr[i] represents the centripetal force required for the ith body.

      +

    Returns CentripetalForce

    Properties

    center: Vector3

    Center of force.

    +

    Methods

    • Calculate the force required to keep the bodies in circular motion around the center. arr[i] represents the centripetal force required for the ith body.

      Parameters

      Returns Vector3[]

      forces.

      -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/CoMTransformation.html b/docs/classes/CoMTransformation.html index a24514e..ecdeec4 100644 --- a/docs/classes/CoMTransformation.html +++ b/docs/classes/CoMTransformation.html @@ -1,7 +1,7 @@ CoMTransformation | nbody

    Class CoMTransformation

    Frame of reference transformation to the center of mass of the system.

    -

    Implements

    Constructors

    Implements

    Constructors

    Methods

    Constructors

    Methods

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/CombinedForce.html b/docs/classes/CombinedForce.html index 0829071..19f1167 100644 --- a/docs/classes/CombinedForce.html +++ b/docs/classes/CombinedForce.html @@ -1,10 +1,10 @@ CombinedForce | nbody

    Class CombinedForce

    Represents a combined force object. To be used to additively combine multiple forces acting on a system of bodies.

    -

    Implements

    Constructors

    Implements

    Constructors

    Properties

    Methods

    Constructors

    Properties

    forces: Force[]

    Methods

    • Get the combined forces acting on the bodies. arr[i] represents the combined force acting on the ith body as a result of all force systems.

      +

    Returns CombinedForce

    Properties

    forces: Force[]

    Methods

    • Get the combined forces acting on the bodies. arr[i] represents the combined force acting on the ith body as a result of all force systems.

      Parameters

      Returns Vector3[]

      element-wise combined forces.

      -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/ExplicitEulerSim.html b/docs/classes/ExplicitEulerSim.html index 8d19f6a..5dd09fb 100644 --- a/docs/classes/ExplicitEulerSim.html +++ b/docs/classes/ExplicitEulerSim.html @@ -1,12 +1,12 @@ ExplicitEulerSim | nbody

    Class ExplicitEulerSim

    Represents a simulation function object that uses the Euler integration method to simulate motions of bodies.

    -

    Implements

    Constructors

    Implements

    Constructors

    Properties

    Methods

    Constructors

    Properties

    force: Force

    Force object to calculate forces on bodies in the Universe.

    -

    Methods

    • Simulate a step in the Universe by using the current state and a time step, using the Euler integration method.

      +

    Returns ExplicitEulerSim

    Properties

    force: Force

    Force object to calculate forces on bodies in the Universe.

    +

    Methods

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/Gravity.html b/docs/classes/Gravity.html index 58b90e3..928c57e 100644 --- a/docs/classes/Gravity.html +++ b/docs/classes/Gravity.html @@ -1,13 +1,13 @@ Gravity | nbody

    Class Gravity

    Represents a Newtonian Gravitational force object.

    -

    Implements

    Constructors

    Implements

    Constructors

    Properties

    G

    Methods

    Constructors

    • Create a new Gravity with the provided gravitational constant.

      Parameters

      • G: number = 6.674e-11

        gravitational constant.

        -

      Returns Gravity

    Properties

    G: number

    Gravitational constant.

    +

    Returns Gravity

    Properties

    G: number

    Gravitational constant.

    Default Value

    6.674e-11
     
    -

    Methods

    • Calculate and return the forces acting on the bodies. arr[i] represents the force acting on the ith body as a result of all other bodies.

      +

    Methods

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/LambdaForce.html b/docs/classes/LambdaForce.html new file mode 100644 index 0000000..a039183 --- /dev/null +++ b/docs/classes/LambdaForce.html @@ -0,0 +1,16 @@ +LambdaForce | nbody

    Class LambdaForce

    Function object that uses the user-defined lambda function to calculate the forces acting on the bodies.

    +

    Implements

    Constructors

    Properties

    fn +

    Methods

    Constructors

    • Create a new LambdaForce with the provided lambda function.

      +
        +
      • Lambda function should take in an array of CelestialBodies and return an array of forces acting on the bodies.
      • +
      • arr[i] should represent the force acting on the ith body.
      • +
      • Length of the returned array should be equal to the length of the input array of CelestialBodies.
      • +
      +

      Parameters

      Returns LambdaForce

    Properties

    fn: ((bodies) => Vector3[])

    Lambda function to calculate forces, provided by the user.

    +

    Type declaration

    Methods

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/LambdaSim.html b/docs/classes/LambdaSim.html index 619babc..98ff811 100644 --- a/docs/classes/LambdaSim.html +++ b/docs/classes/LambdaSim.html @@ -1,5 +1,5 @@ LambdaSim | nbody

    Class LambdaSim

    Function object that uses the user-defined lambda function to simulate the Universe.

    -

    Implements

    Constructors

    Implements

    Constructors

    Properties

    Methods

    Constructors

    • Create a new LambdaSim with the provided lambda function.

      @@ -8,9 +8,9 @@
    • The lambda function should call or calculate the forces action on the bodies by itself.

    Parameters

    • fn: ((deltaT, currState, prevState) => State)

      lambda function.

      -
        • (deltaT, currState, prevState): State
        • Parameters

          Returns State

    Returns LambdaSim

    Properties

    fn: ((deltaT, currState, prevState) => State)

    Type declaration

      • (deltaT, currState, prevState): State
      • Parameters

        Returns State

    Methods

    • Simulate the Universe using the lambda function.

      +
        • (deltaT, currState, prevState): State
        • Parameters

          Returns State

    Returns LambdaSim

    Properties

    fn: ((deltaT, currState, prevState) => State)

    Type declaration

      • (deltaT, currState, prevState): State
      • Parameters

        Returns State

    Methods

    • Simulate the Universe using the lambda function.

      Parameters

      • deltaT: number

        time step.

      • currState: State

        current state of the Universe.

      • prevState: State

        previous state of the Universe.

      Returns State

      the next state of the Universe.

      -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/LambdaTransformation.html b/docs/classes/LambdaTransformation.html index 9b16155..cbbfac5 100644 --- a/docs/classes/LambdaTransformation.html +++ b/docs/classes/LambdaTransformation.html @@ -1,5 +1,5 @@ LambdaTransformation | nbody

    Class LambdaTransformation

    A Frame of Reference transformation that uses the user-defined lambda function.

    -

    Implements

    Constructors

    Implements

    Constructors

    Properties

    Methods

    Constructors

    • Create a new LambdaTransformer with the provided lambda function.

      @@ -9,8 +9,8 @@
    • Transformed state should contain the same number of bodies as the input state, and the order should be preserved.

    Parameters

    • fn: ((state, deltaT) => State)

      lambda function.

      -

    Returns LambdaTransformation

    Properties

    fn: ((state, deltaT) => State)

    Type declaration

    Methods

    • Transform the state's frame of reference using the lambda function.

      +

    Returns LambdaTransformation

    Properties

    fn: ((state, deltaT) => State)

    Type declaration

    Methods

    • Transform the state's frame of reference using the lambda function.

      Parameters

      • state: State

        state to transform.

      • deltaT: number

        time step taken to get to this state. Only applicable for time-dependent transformations.

      Returns State

      transformed state.

      -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/RealTimeVisualizer.html b/docs/classes/RealTimeVisualizer.html index 3bbbfee..f2d749c 100644 --- a/docs/classes/RealTimeVisualizer.html +++ b/docs/classes/RealTimeVisualizer.html @@ -1,5 +1,5 @@ RealTimeVisualizer | nbody

    Class RealTimeVisualizer

    2D real-time visualizer using Plotly.

    -

    Implements

    • Visualizer

    Constructors

    Implements

    • Visualizer

    Constructors

    Properties

    divId simulation universeTrails @@ -8,11 +8,11 @@ stop

    Constructors

    Properties

    divId: string = ''
    simulation: Simulation
    universeTrails: PlotlyUniverseTrail[] = []

    Methods

    • Adds default controls using lil-gui to the visualization.

      +

    Returns RealTimeVisualizer

    Properties

    divId: string = ''
    simulation: Simulation
    universeTrails: PlotlyUniverseTrail[] = []

    Methods

    • Adds default controls using lil-gui to the visualization.

      Parameters

      • parentElement: HTMLElement

        parent element to place the controller div in.

        -

      Returns void

    • Simulate and play the visualization.

      +

    Returns void

    • Simulate and play the visualization.

      Parameters

      • divId: string

        div id to render the visualization in.

      • width: number

        width of the visualization.

      • height: number

        height of the visualization.

        -

      Returns void

    Generated using TypeDoc

    \ No newline at end of file +

    Returns void

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/RealTimeVisualizer3D.html b/docs/classes/RealTimeVisualizer3D.html index 75c0a42..ad82f40 100644 --- a/docs/classes/RealTimeVisualizer3D.html +++ b/docs/classes/RealTimeVisualizer3D.html @@ -1,5 +1,5 @@ RealTimeVisualizer3D | nbody

    Class RealTimeVisualizer3D

    3D real-time visualizer using Three.js.

    -

    Implements

    • Visualizer

    Constructors

    Implements

    • Visualizer

    Constructors

    Properties

    Constructors

    Properties

    scene?: Scene
    simulation: Simulation
    universeTrails: ThreeUniverseTrail[] = []

    Methods

    • Adds default controls to the visualization.

      +

    Returns RealTimeVisualizer3D

    Properties

    scene?: Scene
    simulation: Simulation
    universeTrails: ThreeUniverseTrail[] = []

    Methods

    • Adds default controls to the visualization.

      Parameters

      • parentElement: HTMLElement

        parent element to place the controller div in.

        -

      Returns void

    • Simulate and play the visualization

      +

    Returns void

    • Simulate and play the visualization

      Parameters

      • divId: string

        div id to render the visualization in

      • width: number

        width of the visualization.

      • height: number

        height of the visualization.

        -

      Returns void

    Generated using TypeDoc

    \ No newline at end of file +

    Returns void

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/RecordingVisualizer.html b/docs/classes/RecordingVisualizer.html index 5b2c89f..3f2cef6 100644 --- a/docs/classes/RecordingVisualizer.html +++ b/docs/classes/RecordingVisualizer.html @@ -1,5 +1,5 @@ RecordingVisualizer | nbody

    Class RecordingVisualizer

    2D recording visualizer using Plotly.

    -

    Implements

    • Visualizer

    Constructors

    Implements

    • Visualizer

    Constructors

    Properties

    divId simulation universeTrails @@ -8,12 +8,12 @@ stop

    Constructors

    Properties

    divId: string = ''
    simulation: Simulation
    universeTrails: PlotlyUniverseTrail[] = []

    Methods

    • Adds default controls using lil-gui to the visualization.

      +

    Returns RecordingVisualizer

    Properties

    divId: string = ''
    simulation: Simulation
    universeTrails: PlotlyUniverseTrail[] = []

    Methods

    • Adds default controls using lil-gui to the visualization.

      Parameters

      • parentElement: HTMLElement

        parent element to place the controller div in.

        -

      Returns void

    • Simulate and play the visualization.

      +

    Returns void

    • Simulate and play the visualization.

      Parameters

      • divId: string

        div id to render the visualization in.

      • width: number

        width of the visualization.

      • height: number

        height of the visualization.

      • recordFor: number

        number of seconds to record for..

        -

      Returns void

    Generated using TypeDoc

    \ No newline at end of file +

    Returns void

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/RecordingVisualizer3D.html b/docs/classes/RecordingVisualizer3D.html index f1ee977..7e456ad 100644 --- a/docs/classes/RecordingVisualizer3D.html +++ b/docs/classes/RecordingVisualizer3D.html @@ -1,5 +1,5 @@ RecordingVisualizer3D | nbody

    Class RecordingVisualizer3D

    3D recording visualizer using Three.js.

    -

    Implements

    • Visualizer

    Constructors

    Implements

    • Visualizer

    Constructors

    Properties

    Constructors

    Properties

    scene?: Scene
    simulation: Simulation
    universeTrails: ThreeUniverseTrail[] = []

    Methods

    • Adds default controls to the visualization.

      +

    Returns RecordingVisualizer3D

    Properties

    scene?: Scene
    simulation: Simulation
    universeTrails: ThreeUniverseTrail[] = []

    Methods

    • Adds default controls to the visualization.

      Parameters

      • parentElement: HTMLElement

        parent element to place the controller div in.

        -

      Returns void

    • Simulate and play the visualization

      +

    Returns void

    • Simulate and play the visualization

      Parameters

      • divId: string

        div id to render the visualization in.

      • width: number

        width of the visualization.

      • height: number

        height of the visualization.

      • recordFor: number

        number of seconds to record for.

        -

      Returns void

    Generated using TypeDoc

    \ No newline at end of file +

    Returns void

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/RotateTransformation.html b/docs/classes/RotateTransformation.html index d4f098f..44a2d1b 100644 --- a/docs/classes/RotateTransformation.html +++ b/docs/classes/RotateTransformation.html @@ -1,12 +1,12 @@ RotateTransformation | nbody

    Class RotateTransformation

    Frame of reference transformation around an axis by an angle. Makes sense to this transformation only during initialization of the universe and not at every time step.

    -

    Implements

    Constructors

    Implements

    Constructors

    Properties

    Methods

    Constructors

    Properties

    angle: number
    axis: Vector3

    Methods

    • Transform the frame of reference around an axis by an angle.

      +

    Returns RotateTransformation

    Properties

    angle: number
    axis: Vector3

    Methods

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/RungeKutta4Sim.html b/docs/classes/RungeKutta4Sim.html index 3b0efd3..baff168 100644 --- a/docs/classes/RungeKutta4Sim.html +++ b/docs/classes/RungeKutta4Sim.html @@ -1,15 +1,15 @@ RungeKutta4Sim | nbody

    Class RungeKutta4Sim

    Represents a simulation function object that uses the Runge-Kutta 4 integration method to simulate the motion of bodies.

    -

    Implements

    Constructors

    Implements

    Constructors

    Properties

    Methods

    Constructors

    Properties

    force: Force

    Force object to calculate forces on bodies in the Universe.

    -
    weights: number[]

    Weights for weighted average.

    -

    Methods

    • Simulate a step in the Universe by using the current state and a time step, using the Runge-Kutta 4 integration method.

      +

    Returns RungeKutta4Sim

    Properties

    force: Force

    Force object to calculate forces on bodies in the Universe.

    +
    weights: number[]

    Weights for weighted average.

    +

    Methods

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/SemiImplicitEulerSim.html b/docs/classes/SemiImplicitEulerSim.html index e023c00..98284a4 100644 --- a/docs/classes/SemiImplicitEulerSim.html +++ b/docs/classes/SemiImplicitEulerSim.html @@ -1,12 +1,12 @@ SemiImplicitEulerSim | nbody

    Class SemiImplicitEulerSim

    Represents a simulation function object that uses the Semi-Implicit Euler integration method to simulate the motion of bodies.

    -

    Implements

    Constructors

    Implements

    Constructors

    Properties

    Methods

    Constructors

    Properties

    force: Force

    Force object to calculate forces on bodies in the Universe.

    -

    Methods

    • Simulate a step in the Universe by using the current state and a time step, using the Semi-Implicit Euler integration method.

      +

    Returns SemiImplicitEulerSim

    Properties

    force: Force

    Force object to calculate forces on bodies in the Universe.

    +

    Methods

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/Simulation.html b/docs/classes/Simulation.html index 8d57734..b817a07 100644 --- a/docs/classes/Simulation.html +++ b/docs/classes/Simulation.html @@ -1,5 +1,5 @@ Simulation | nbody

    Class Simulation

    A Simulation object that contains Universes and a Visualizer.

    -

    Constructors

    Constructors

    Methods

    Constructors

    • Create a new Simulation object with the provided Universes and visualization config.

      Parameters

      • universes: Universe | Universe[]

        array of Universes.

        -
      • __namedParameters: {
            controller?: ControllerType;
            looped?: boolean;
            maxFrameRate?: number;
            maxTrailLength?: number;
            record?: boolean;
            showDebugInfo?: boolean;
            showTrails?: boolean;
            visType?: VisType;
        }
        • Optional controller?: ControllerType
        • Optional looped?: boolean
        • Optional maxFrameRate?: number
        • Optional maxTrailLength?: number
        • Optional record?: boolean
        • Optional showDebugInfo?: boolean
        • Optional showTrails?: boolean
        • Optional visType?: VisType

      Returns Simulation

    Methods

    • Get the maximum trail length used in the visualization.

      +
    • __namedParameters: {
          controller?: ControllerType;
          looped?: boolean;
          maxFrameRate?: number;
          maxTrailLength?: number;
          record?: boolean;
          showDebugInfo?: boolean;
          showTrails?: boolean;
          visType?: VisType;
      }
      • Optional controller?: ControllerType
      • Optional looped?: boolean
      • Optional maxFrameRate?: number
      • Optional maxTrailLength?: number
      • Optional record?: boolean
      • Optional showDebugInfo?: boolean
      • Optional showTrails?: boolean
      • Optional visType?: VisType

    Returns Simulation

    Methods

    • Get the maximum trail length used in the visualization.

      Returns number

      maximum trail length.

      -
    • Get whether trails are shown in the visualization.

      +
    • Get whether trails are shown in the visualization.

      Returns boolean

      true if trails are shown.

      -
    • True if the universe with the given label is shown.

      +
    • True if the universe with the given label is shown.

      Parameters

      • label: string

        universe label.

      Returns boolean

      whether the universe is shown.

      -
    • Get the speed of the simulation.

      Returns number

      speed of the simulation as a scale of normal time.

      -
    • Get whether the simulation is playing.

      Returns boolean

      true if the simulation is playing.

      -
    • Pause the simulation. Only works if the controller is 'code'.

      -

      Returns void

    • Resume the simulation. Only works if the controller is 'code'.

      -

      Returns void

    • Set the maximum trail length used in the visualization. Changes only apply on the next Simulation.play() call.

      +
    • Pause the simulation. Only works if the controller is 'code'.

      +

      Returns void

    • Resume the simulation. Only works if the controller is 'code'.

      +

      Returns void

    • Set the maximum trail length used in the visualization. Changes only apply on the next Simulation.play() call.

      Parameters

      • maxTrailLength: number

        maximum trail length.

        -

      Returns void

    • Set whether to show trails in the visualization. Only works if the controller is 'code'.

      +

    Returns void

    • Set whether to show trails in the visualization. Only works if the controller is 'code'.

      Parameters

      • showTrails: boolean

        true to show trails.

        -

      Returns void

    • Set whether to show the universe with the given label. Only works if the controller is 'code'.

      +

    Returns void

    • Set whether to show the universe with the given label. Only works if the controller is 'code'.

      Parameters

      • label: string

        universe label.

      • show: boolean

        true to show the universe.

        -

      Returns void

    • Set the speed of the simulation. Only works if the controller is 'code'.

      +

    Returns void

    • Set the speed of the simulation. Only works if the controller is 'code'.

      Parameters

      • speed: number

        speed of the simulation as a scale of normal time.

        -

      Returns void

    • Insert the simulation visualization in the div with the given id.

      +

    Returns void

    • Insert the simulation visualization in the div with the given id.

      Parameters

      • divId: string

        div id.

      • width: number
      • height: number
      • speed: number = 1

        initial time scale.

      • paused: boolean = false

        whether to start the simulation paused.

      • recordFor: number = 0

        number of seconds to record for, only used if in record mode.

        -

      Returns void

    Generated using TypeDoc

    \ No newline at end of file +

    Returns void

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/State.html b/docs/classes/State.html index 020b955..9d082a7 100644 --- a/docs/classes/State.html +++ b/docs/classes/State.html @@ -1,10 +1,10 @@ State | nbody

    Class State

    Represents a Universe's state snapshot.

    -

    Constructors

    Constructors

    Properties

    Methods

    Constructors

    Properties

    bodies: CelestialBody[]

    Array of celestial bodies that make up this state of the Universe.

    -

    Methods

    • Deep copy this state

      +

    Returns State

    Properties

    bodies: CelestialBody[]

    Array of celestial bodies that make up this state of the Universe.

    +

    Methods

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/Universe.html b/docs/classes/Universe.html index 5fa2c80..2a15817 100644 --- a/docs/classes/Universe.html +++ b/docs/classes/Universe.html @@ -1,5 +1,5 @@ Universe | nbody

    Class Universe

    A Universe object that contains previous and current state of the universe, a simulation function, frame of reference transformations and other necessary data.

    -

    Constructors

    Constructors

    Properties

    color currState label @@ -9,10 +9,10 @@

    Methods

    Constructors

    Properties

    color: string | string[]

    Color of the bodies in the Universe. A single color applied to all bodies or an array of colors applied to each body respectively. Incase of array, length should match the number of bodies in the state.

    -
    currState: State
    label: string

    Label of the Universe.

    -
    prevState: State

    Simulation function used to simulate the Universe.

    -
    transformations: Transformation[]

    Array of transformations to be applied to the Universe's state after simulation and before visualization.

    -

    Methods

    • Deep copy the current Universe.

      +

    Returns Universe

    Properties

    color: string | string[]

    Color of the bodies in the Universe. A single color applied to all bodies or an array of colors applied to each body respectively. Incase of array, length should match the number of bodies in the state.

    +
    currState: State
    label: string

    Label of the Universe.

    +
    prevState: State

    Simulation function used to simulate the Universe.

    +
    transformations: Transformation[]

    Array of transformations to be applied to the Universe's state after simulation and before visualization.

    +

    Methods

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/Vector3.html b/docs/classes/Vector3.html index 0bb5a71..18b0aed 100644 --- a/docs/classes/Vector3.html +++ b/docs/classes/Vector3.html @@ -1,8 +1,8 @@ -Vector3 | nbody

    Class Vector3

    3D vector. ( class Vector3 implements Vector )

    +Vector3 | nbody

    Class Vector3

    Example

    const a = new THREE.Vector3( 1, 0, 0 );
    const b = new THREE.Vector3( 0, 1, 0 );
    const c = new THREE.Vector3();
    c.crossVectors( a, b );
    -

    Implements

    • Vector

    Constructors

    Constructors

    • Parameters

      • Optional x: number
      • Optional y: number
      • Optional z: number

      Returns Vector3

    Properties

    isVector3: true
    x: number

    Default

    0
    +

    Constructors

    • Parameters

      • Optional x: number
      • Optional y: number
      • Optional z: number

      Returns Vector3

    Properties

    isVector3: true
    x: number

    Default

    0
     
    -
    y: number

    Default

    0
    +
    y: number

    Default

    0
     
    -
    z: number

    Default

    0
    +
    z: number

    Default

    0
     
    -

    Methods

    • Iterating through a Vector3 instance will yield its components (x, y, z) in the corresponding order.

      -

      Returns Iterator<number, any, undefined>

    • Adds v to this vector.

      -

      Parameters

      Returns this

    • Parameters

      • s: number

      Returns this

    • Parameters

      Returns this

    • Sets this vector to a + b.

      -

      Parameters

      Returns this

    • Parameters

      Returns number

    • Parameters

      Returns this

    • Parameters

      • euler: Euler

      Returns this

    • Parameters

      • m: Matrix3

      Returns this

    • Parameters

      • m: Matrix4

      Returns this

    • Parameters

      • m: Matrix3

      Returns this

    • Parameters

      • q: Quaternion

      Returns this

    • Returns this

    • Parameters

      Returns this

    • Parameters

      • min: number
      • max: number

      Returns this

    • Parameters

      • min: number
      • max: number

      Returns this

    • Clones this vector.

      -

      Returns this

    • Copies value of v to this vector.

      -

      Parameters

      Returns this

    • Sets this vector to cross product of itself and v.

      -

      Parameters

      Returns this

    • Sets this vector to cross product of a and b.

      -

      Parameters

      Returns this

    • Computes distance of this vector to v.

      -

      Parameters

      Returns number

    • Parameters

      Returns number

      Deprecated

      Use .manhattanDistanceTo() instead.

      -
    • Computes squared distance of this vector to v.

      -

      Parameters

      Returns number

    • Parameters

      Returns this

    • Divides this vector by scalar s. +

    Methods

    • Iterating through a Vector3 instance will yield its components (x, y, z) in the corresponding order.

      +

      Returns Iterator<number, any, undefined>

    • Adds v to this vector.

      +

      Parameters

      • v: Vector3Like

      Returns this

    • Parameters

      • s: number

      Returns this

    • Parameters

      Returns this

    • Sets this vector to a + b.

      +

      Parameters

      • a: Vector3Like
      • b: Vector3Like

      Returns this

    • Parameters

      Returns number

    • Parameters

      Returns this

    • Parameters

      • euler: Euler

      Returns this

    • Parameters

      • m: Matrix3

      Returns this

    • Parameters

      • m: Matrix4

      Returns this

    • Parameters

      • m: Matrix3

      Returns this

    • Parameters

      • q: QuaternionLike

      Returns this

    • Returns this

    • Parameters

      • min: Vector3Like
      • max: Vector3Like

      Returns this

    • Parameters

      • min: number
      • max: number

      Returns this

    • Parameters

      • min: number
      • max: number

      Returns this

    • Clones this vector.

      +

      Returns this

    • Copies value of v to this vector.

      +

      Parameters

      • v: Vector3Like

      Returns this

    • Sets this vector to cross product of itself and v.

      +

      Parameters

      • a: Vector3Like

      Returns this

    • Sets this vector to cross product of a and b.

      +

      Parameters

      • a: Vector3Like
      • b: Vector3Like

      Returns this

    • Computes distance of this vector to v.

      +

      Parameters

      • v: Vector3Like

      Returns number

    • Computes squared distance of this vector to v.

      +

      Parameters

      • v: Vector3Like

      Returns number

    • Parameters

      • v: Vector3Like

      Returns this

    • Divides this vector by scalar s. Set vector to ( 0, 0, 0 ) if s == 0.

      -

      Parameters

      • s: number

      Returns this

    • Computes dot product of this vector and v.

      -

      Parameters

      Returns number

    • Checks for strict equality of this vector and v.

      -

      Parameters

      Returns boolean

    • Returns this

    • Sets this vector's x, y and z value from the provided array or array-like.

      +

      Parameters

      • s: number

      Returns this

    • Computes dot product of this vector and v.

      +

      Parameters

      • v: Vector3Like

      Returns number

    • Checks for strict equality of this vector and v.

      +

      Parameters

      • v: Vector3Like

      Returns boolean

    • Returns this

    • Sets this vector's x, y and z value from the provided array or array-like.

      Parameters

      • array: number[] | ArrayLike<number>

        the source array or array-like.

      • Optional offset: number

        (optional) offset into the array. Default is 0.

        -

      Returns this

    • Parameters

      • attribute: BufferAttribute | InterleavedBufferAttribute
      • index: number

      Returns this

    • Parameters

      • index: number

      Returns number

    • Computes length of this vector.

      -

      Returns number

    • Computes squared length of this vector.

      -

      Returns number

    • Parameters

      Returns this

    • Parameters

      Returns this

    • Computes the Manhattan length (distance) from this vector to the given vector v

      +

    Returns this

    • Parameters

      • attribute: BufferAttribute | InterleavedBufferAttribute
      • index: number

      Returns this

    • Parameters

      • index: number

      Returns number

    • Computes length of this vector.

      +

      Returns number

    • Computes squared length of this vector.

      +

      Returns number

    • Parameters

      • v: Vector3Like
      • alpha: number

      Returns this

    • Parameters

      • v1: Vector3Like
      • v2: Vector3Like
      • alpha: number

      Returns this

    • Computes the Manhattan length (distance) from this vector to the given vector v

      see Taxicab Geometry

      -

      Parameters

      Returns number

    • Computes the Manhattan length of this vector.

      +

      Parameters

      • v: Vector3Like

      Returns number

    • Computes the Manhattan length of this vector.

      see Taxicab Geometry

      -

      Returns number

    • Parameters

      Returns this

    • Parameters

      Returns this

    • Parameters

      Returns this

    • Multiplies this vector by scalar s.

      -

      Parameters

      • s: number

      Returns this

    • Parameters

      Returns this

    • Inverts this vector.

      -

      Returns this

    • Normalizes this vector.

      -

      Returns this

    • Parameters

      • camera: Camera

      Returns this

    • Parameters

      Returns this

    • Parameters

      Returns this

    • Sets this vector's x, y and z from Math.random

      -

      Returns this

    • Returns this

    • Parameters

      Returns this

    • Returns this

    • Returns this

    • Sets value of this vector.

      -

      Parameters

      • x: number
      • y: number
      • z: number

      Returns this

    • Parameters

      • index: number
      • value: number

      Returns this

    • Sets this vector's x, y and z components from the r, g, and b components of the specified +

      Returns number

    • Parameters

      • v: Vector3Like

      Returns this

    • Parameters

      • v: Vector3Like

      Returns this

    • Parameters

      • v: Vector3Like

      Returns this

    • Multiplies this vector by scalar s.

      +

      Parameters

      • s: number

      Returns this

    • Parameters

      • a: Vector3Like
      • b: Vector3Like

      Returns this

    • Inverts this vector.

      +

      Returns this

    • Normalizes this vector.

      +

      Returns this

    • Parameters

      • camera: Camera

      Returns this

    • Parameters

      Returns this

    • Parameters

      Returns this

    • Sets this vector's x, y and z from Math.random

      +

      Returns this

    • Returns this

    • Parameters

      • vector: Vector3Like

      Returns this

    • Returns this

    • Returns this

    • Sets value of this vector.

      +

      Parameters

      • x: number
      • y: number
      • z: number

      Returns this

    • Parameters

      • index: number
      • value: number

      Returns this

    • Sets this vector's x, y and z components from the r, g, and b components of the specified Color | color.

      -

      Parameters

      • color: Color

      Returns this

    • Parameters

      • s: Cylindrical

      Returns this

    • Parameters

      • radius: number
      • theta: number
      • y: number

      Returns this

    • Sets this vector's x, y and z components from the x, y, and z components of the specified Euler Euler Angle.

      -

      Parameters

      • e: Euler

      Returns this

    • Parameters

      • matrix: Matrix3
      • index: number

      Returns this

    • Parameters

      • matrix: Matrix4
      • index: number

      Returns this

    • Parameters

      • m: Matrix4

      Returns this

    • Parameters

      • m: Matrix4

      Returns this

    • Parameters

      • s: Spherical

      Returns this

    • Parameters

      • r: number
      • phi: number
      • theta: number

      Returns this

    • Normalizes this vector and multiplies it by l.

      -

      Parameters

      • l: number

      Returns this

    • Sets all values of this vector.

      -

      Parameters

      • scalar: number

      Returns this

    • Sets x value of this vector.

      -

      Parameters

      • x: number

      Returns Vector3

    • Sets y value of this vector.

      -

      Parameters

      • y: number

      Returns Vector3

    • Sets z value of this vector.

      -

      Parameters

      • z: number

      Returns Vector3

    • Subtracts v from this vector.

      -

      Parameters

      Returns this

    • Parameters

      • s: number

      Returns this

    • Sets this vector to a - b.

      -

      Parameters

      Returns this

    • Returns an array [x, y, z], or copies x, y and z into the provided array.

      +

      Parameters

      • color: RGB

      Returns this

    • Parameters

      • s: Cylindrical

      Returns this

    • Parameters

      • radius: number
      • theta: number
      • y: number

      Returns this

    • Sets this vector's x, y and z components from the x, y, and z components of the specified Euler Euler Angle.

      +

      Parameters

      • e: Euler

      Returns this

    • Parameters

      • matrix: Matrix3
      • index: number

      Returns this

    • Parameters

      • matrix: Matrix4
      • index: number

      Returns this

    • Parameters

      • m: Matrix4

      Returns this

    • Parameters

      • m: Matrix4

      Returns this

    • Parameters

      • s: Spherical

      Returns this

    • Parameters

      • r: number
      • phi: number
      • theta: number

      Returns this

    • Normalizes this vector and multiplies it by l.

      +

      Parameters

      • l: number

      Returns this

    • Sets all values of this vector.

      +

      Parameters

      • scalar: number

      Returns this

    • Sets x value of this vector.

      +

      Parameters

      • x: number

      Returns this

    • Sets y value of this vector.

      +

      Parameters

      • y: number

      Returns this

    • Sets z value of this vector.

      +

      Parameters

      • z: number

      Returns this

    • Subtracts v from this vector.

      +

      Parameters

      • a: Vector3Like

      Returns this

    • Parameters

      • s: number

      Returns this

    • Sets this vector to a - b.

      +

      Parameters

      • a: Vector3Like
      • b: Vector3Like

      Returns this

    • Returns an array [x, y, z], or copies x, y and z into the provided array.

      Parameters

      • Optional array: number[]

        (optional) array to store the vector to. If this is not provided, a new array will be created.

      • Optional offset: number

        (optional) optional offset into the array.

      Returns number[]

      The created or provided array.

      -
    • Parameters

      • Optional array: Vector3Tuple
      • Optional offset: 0

      Returns Vector3Tuple

    • Copies x, y and z into the provided array-like.

      +
    • Parameters

      • Optional array: Vector3Tuple
      • Optional offset: 0

      Returns Vector3Tuple

    • Copies x, y and z into the provided array-like.

      Parameters

      • array: ArrayLike<number>

        array-like to store the vector to.

      • Optional offset: number

        (optional) optional offset into the array-like.

      Returns ArrayLike<number>

      The provided array-like.

      -
    • Parameters

      • m: Matrix4

      Returns this

    • Parameters

      • camera: Camera

      Returns this

    Generated using TypeDoc

    \ No newline at end of file +
    • Parameters

      • m: Matrix4

      Returns this

    • Parameters

      • camera: Camera

      Returns this

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/VelocityVerletSim.html b/docs/classes/VelocityVerletSim.html index 160d7d9..d2c2dd4 100644 --- a/docs/classes/VelocityVerletSim.html +++ b/docs/classes/VelocityVerletSim.html @@ -1,12 +1,12 @@ VelocityVerletSim | nbody

    Class VelocityVerletSim

    Represents a simulation function object that uses the Velocity Verlet integration method to simulate the motion of bodies.

    -

    Implements

    Constructors

    Implements

    Constructors

    Properties

    Methods

    Constructors

    Properties

    forceCalculator: Force

    Force object to calculate forces on bodies in the Universe.

    -

    Methods

    • Simulate a step in the Universe by using the previous and/or current state and a time step, using the Velocity Verlet integration method.

      +

    Returns VelocityVerletSim

    Properties

    forceCalculator: Force

    Force object to calculate forces on bodies in the Universe.

    +

    Methods

    • Simulate a step in the Universe by using the previous and/or current state and a time step, using the Velocity Verlet integration method.

      Parameters

      • deltaT: number

        time step.

      • currState: State

        current state.

      Returns State

      new state after the simulation step.

      -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/hierarchy.html b/docs/hierarchy.html index f0b150f..502d9dd 100644 --- a/docs/hierarchy.html +++ b/docs/hierarchy.html @@ -1 +1 @@ -nbody

    Generated using TypeDoc

    \ No newline at end of file +nbody

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/Force.html b/docs/interfaces/Force.html index d2147a1..c97de59 100644 --- a/docs/interfaces/Force.html +++ b/docs/interfaces/Force.html @@ -1,3 +1,3 @@ Force | nbody

    Interface Force

    Represents a force object used to calculate forces acting on the bodies in the Universe.

    -
    interface Force {
        getForces(bodies): Vector3[];
    }

    Implemented by

    Methods

    Methods

    Generated using TypeDoc

    \ No newline at end of file +
    interface Force {
        getForces(bodies): Vector3[];
    }

    Implemented by

    Methods

    Methods

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/SimulateFunction.html b/docs/interfaces/SimulateFunction.html index 9c22c99..e893ad9 100644 --- a/docs/interfaces/SimulateFunction.html +++ b/docs/interfaces/SimulateFunction.html @@ -1,8 +1,8 @@ SimulateFunction | nbody

    Interface SimulateFunction

    Represents a function object used for simulating the Universe. Should encapsulate the numerical integration method and other necessary simulation logic. Can use an external force calculation function object - see Force.

    -
    interface SimulateFunction {
        simulate(deltaT, currState, prevState): State;
    }

    Implemented by

    Methods

    interface SimulateFunction {
        simulate(deltaT, currState, prevState): State;
    }

    Implemented by

    Methods

    Methods

    • Simulate a step in the Universe by using the previous and/or current state and a time step.

      Parameters

      • deltaT: number

        time step.

      • currState: State

        current state of the Universe.

      • prevState: State

        previous state of the Universe.

      Returns State

      the next state of the Universe.

      -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/Transformation.html b/docs/interfaces/Transformation.html index 05a3a26..0c9f075 100644 --- a/docs/interfaces/Transformation.html +++ b/docs/interfaces/Transformation.html @@ -1,7 +1,7 @@ Transformation | nbody

    Interface Transformation

    Represents a Frame of Reference transformation.

    -
    interface Transformation {
        transform(state, deltaT): State;
    }

    Implemented by

    Methods

    interface Transformation {
        transform(state, deltaT): State;
    }

    Implemented by

    Methods

    Methods

    • Transform the state to a new frame of reference.

      Parameters

      • state: State

        state to transform.

      • deltaT: number

        time step taken to get to this state. Only applicable for time-dependent transformations.

      Returns State

      transformed state.

      -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules.html b/docs/modules.html index c1b3a24..2c8467f 100644 --- a/docs/modules.html +++ b/docs/modules.html @@ -9,6 +9,7 @@

    Forces

    SimulateFunctions

    ExplicitEulerSim LambdaSim diff --git a/docs/types/ControllerType.html b/docs/types/ControllerType.html index 2009b50..bb7861a 100644 --- a/docs/types/ControllerType.html +++ b/docs/types/ControllerType.html @@ -4,4 +4,4 @@
  • 'code' for manual control via code.
  • 'none' for no control.
  • -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/UniverseConfig.html b/docs/types/UniverseConfig.html index f88d808..5bd3fec 100644 --- a/docs/types/UniverseConfig.html +++ b/docs/types/UniverseConfig.html @@ -5,4 +5,4 @@
  • prevState: State

    Previous state of the Universe.

  • simFunc: SimulateFunction

    Simulation function used to simulate the Universe.

  • transformations: Transformation[]

    Array of transformations to be applied to the Universe's state after simulation and before visualization.

    -
  • Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/VisType.html b/docs/types/VisType.html index 3fdb648..aa8e69b 100644 --- a/docs/types/VisType.html +++ b/docs/types/VisType.html @@ -1,2 +1,2 @@ VisType | nbody

    Type alias VisType

    VisType: "2D" | "3D"

    Visualization type.

    -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/package.json b/package.json index 3cb5550..70357d1 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "nbody", - "version": "0.0.2", + "version": "0.0.3", "description": "Configure, simulate and visualize n-body interactions", - "main": "./dist/index.js", - "types": "./dist/src/index.d.ts", - "module": "./dist/index.js", + "main": "./dist/src/index.js", + "types": "./dist/types/src/index.d.ts", + "module": "./dist/src/index.js", "repository": "https://github.com/source-academy/nbody.git", "author": "Yeluri Ketan", "license": "Apache-2.0", @@ -29,8 +29,8 @@ "docs": "typedoc", "clean": "node scripts/clean.cjs", "test": "echo \"Error: no test specified\" && exit 1", - "build": "yarn lint && yarn clean && webpack && yarn docs", - "dev": "yarn clean && webpack && yarn unlink && yarn link" + "build": "yarn lint && yarn clean && tsc && yarn docs", + "dev": "yarn clean && tsc && yarn unlink && yarn link" }, "dependencies": { "lil-gui": "^0.19.2" @@ -39,7 +39,7 @@ "@types/eslint": "^8.4.10", "@types/plotly.js": "^2.29.2", "@types/plotly.js-dist": "npm:@types/plotly.js", - "@types/three": "^0.158.1", + "@types/three": "^0.163.0", "@typescript-eslint/eslint-plugin": "^6.6.0", "@typescript-eslint/parser": "^6.6.0", "eslint": "^8.57.0", @@ -54,17 +54,14 @@ "eslint-plugin-react-hooks": "^4.4.0", "eslint-plugin-simple-import-sort": "^8.0.0", "plotly.js-dist": "^2.30.1", - "three": "^0.158.0", - "ts-loader": "^9.5.1", + "three": "^0.163.0", "typedoc": "^0.25.12", - "typescript": "^5.4.2", - "webpack": "^5.90.3", - "webpack-cli": "^5.1.4" + "typescript": "^5.4.2" }, "peerDependencies": { "@types/plotly.js": "^2.29.2", - "@types/three": "^0.158.1", + "@types/three": "^0.163.0", "plotly.js-dist": "^2.30.1", - "three": "^0.158.0" + "three": "^0.163.0" } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 6b42ddb..7af5167 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,7 +6,7 @@ import { CelestialBody, } from './CelestialBody'; -import { type Force } from './Force'; +import { LambdaForce, type Force } from './Force'; import { CentripetalForce, CombinedForce, Gravity, } from './library/Force'; @@ -38,7 +38,7 @@ import { Vector3 } from 'three'; export { BodyCenterTransformation, CelestialBody, CentripetalForce, - CombinedForce, CoMTransformation, ExplicitEulerSim, Gravity, LambdaSim, LambdaTransformation, RealTimeVisualizer, + CombinedForce, CoMTransformation, ExplicitEulerSim, Gravity, LambdaForce, LambdaSim, LambdaTransformation, RealTimeVisualizer, RealTimeVisualizer3D, RecordingVisualizer, RecordingVisualizer3D, diff --git a/src/library/Visualizer.ts b/src/library/Visualizer.ts index 1ec1164..7ef9cd1 100644 --- a/src/library/Visualizer.ts +++ b/src/library/Visualizer.ts @@ -186,6 +186,8 @@ export class RealTimeVisualizer implements Visualizer { }, // uirevision: 'true', showlegend: false, + width, + height, }; if (this.simulation.controller === 'ui') { @@ -809,6 +811,8 @@ export class RecordingVisualizer implements Visualizer { }, // uirevision: 'true', showlegend: false, + width, + height, }; if (this.simulation.controller === 'ui') { diff --git a/tsconfig.json b/tsconfig.json index 3c07d77..27b41b1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,6 +3,7 @@ "allowJs": true, "allowSyntheticDefaultImports": true, "declaration": true, + "declarationDir": "./dist/types/", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, @@ -27,5 +28,6 @@ "src/.eslintrc.cjs", ".eslintrc.base.cjs", ".eslintrc.test.cjs", + "node_modules", ] } diff --git a/webpack.config.cjs b/webpack.config.cjs deleted file mode 100644 index 9607043..0000000 --- a/webpack.config.cjs +++ /dev/null @@ -1,41 +0,0 @@ -const path = require("path"); - -module.exports = { - entry: "./src/index.ts", - devtool: "inline-source-map", - mode: "production", - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - loader: "ts-loader", - options: { - configFile: path.resolve(__dirname, "tsconfig.json"), - }, - }, - ], - }, - resolve: { - extensions: [".tsx", ".ts", ".js"], - }, - output: { - filename: "index.js", - path: path.resolve(__dirname, "dist"), - globalObject: "this", - library: { - name: "nbody", - type: "umd", - }, - }, - optimization: { - usedExports: false, - }, - externals: { - three: "three", - "three/examples/jsm/Addons": "three/examples/jsm/Addons", - "three/examples/jsm/libs/stats.module": - "three/examples/jsm/libs/stats.module", - "plotly.js-dist": "plotly.js-dist", - }, -}; diff --git a/yarn.lock b/yarn.lock index bb08e54..3d2d48b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14,11 +14,6 @@ dependencies: regenerator-runtime "^0.14.0" -"@discoveryjs/json-ext@^0.5.0": - version "0.5.7" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" - integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== - "@es-joy/jsdoccomment@~0.42.0": version "0.42.0" resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.42.0.tgz#59e878708336aaee88c2b34c894f73dbf77ae2b0" @@ -79,46 +74,6 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" - integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/source-map@^0.3.3": - version "0.3.6" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" - integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -140,15 +95,12 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@types/eslint-scope@^3.7.3": - version "3.7.7" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" - integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== - dependencies: - "@types/eslint" "*" - "@types/estree" "*" +"@tweenjs/tween.js@~23.1.1": + version "23.1.1" + resolved "https://registry.yarnpkg.com/@tweenjs/tween.js/-/tween.js-23.1.1.tgz#0ae28ed9c635805557f78c2626464018d5f1b5e2" + integrity sha512-ZpboH7pCPPeyBWKf8c7TJswtCEQObFo3bOBYalm99NzZarATALYCo5OhbCa/n4RQyJyHfhkdx+hNrdL5ByFYDw== -"@types/eslint@*", "@types/eslint@^8.4.10": +"@types/eslint@^8.4.10": version "8.56.5" resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.5.tgz#94b88cab77588fcecdd0771a6d576fa1c0af9d02" integrity sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw== @@ -156,12 +108,12 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^1.0.5": +"@types/estree@*": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== -"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -171,13 +123,6 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/node@*": - version "20.11.28" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.28.tgz#4fd5b2daff2e580c12316e457473d68f15ee6f66" - integrity sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA== - dependencies: - undici-types "~5.26.4" - "@types/plotly.js-dist@npm:@types/plotly.js", "@types/plotly.js@^2.29.2": version "2.29.2" resolved "https://registry.yarnpkg.com/@types/plotly.js/-/plotly.js-2.29.2.tgz#e058cd17963c1658c2bd204b2b9b1b782cdf73d7" @@ -193,14 +138,15 @@ resolved "https://registry.yarnpkg.com/@types/stats.js/-/stats.js-0.17.3.tgz#705446e12ce0fad618557dd88236f51148b7a935" integrity sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ== -"@types/three@^0.158.1": - version "0.158.3" - resolved "https://registry.yarnpkg.com/@types/three/-/three-0.158.3.tgz#f53e26c50709c7f972934e4e8c1ca51add0cfa9f" - integrity sha512-6Qs1rUvLSbkJ4hlIe6/rdwIf61j1x2UKvGJg7s8KjswYsz1C1qDTs6voVXXB8kYaI0hgklgZgbZUupfL1l9xdA== +"@types/three@^0.163.0": + version "0.163.0" + resolved "https://registry.yarnpkg.com/@types/three/-/three-0.163.0.tgz#96f5440fcd39452d2c84dfe0c9b7a9cf0247b9e6" + integrity sha512-uIdDhsXRpQiBUkflBS/i1l3JX14fW6Ot9csed60nfbZNXHDTRsnV2xnTVwXcgbvTiboAR4IW+t+lTL5f1rqIqA== dependencies: + "@tweenjs/tween.js" "~23.1.1" "@types/stats.js" "*" "@types/webxr" "*" - fflate "~0.6.10" + fflate "~0.8.2" meshoptimizer "~0.18.1" "@types/webxr@*": @@ -347,173 +293,17 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.11.5": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" - integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - -"@webassemblyjs/floating-point-hex-parser@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" - integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== - -"@webassemblyjs/helper-api-error@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" - integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== - -"@webassemblyjs/helper-buffer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" - integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== - -"@webassemblyjs/helper-numbers@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" - integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.6" - "@webassemblyjs/helper-api-error" "1.11.6" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/helper-wasm-bytecode@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" - integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== - -"@webassemblyjs/helper-wasm-section@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" - integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.12.1" - -"@webassemblyjs/ieee754@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" - integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" - integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" - integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== - -"@webassemblyjs/wasm-edit@^1.11.5": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" - integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-opt" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - "@webassemblyjs/wast-printer" "1.12.1" - -"@webassemblyjs/wasm-gen@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" - integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wasm-opt@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" - integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - -"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.11.5": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" - integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-api-error" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wast-printer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" - integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@xtuc/long" "4.2.2" - -"@webpack-cli/configtest@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" - integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== - -"@webpack-cli/info@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" - integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== - -"@webpack-cli/serve@^2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" - integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -acorn-import-assertions@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== - acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: +acorn@^8.9.0: version "8.11.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== -ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -720,21 +510,6 @@ braces@^3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.21.10: - version "4.23.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" - integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== - dependencies: - caniuse-lite "^1.0.30001587" - electron-to-chromium "^1.4.668" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - builtin-modules@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" @@ -756,12 +531,7 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -caniuse-lite@^1.0.30001587: - version "1.0.30001599" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz#571cf4f3f1506df9bf41fcbb6d10d5d017817bce" - integrity sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA== - -chalk@^4.0.0, chalk@^4.1.0: +chalk@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -769,20 +539,6 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -795,21 +551,6 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^2.0.14: - version "2.0.20" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" - integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== - -commander@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" - integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - comment-parser@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.4.1.tgz#bdafead37961ac079be11eb7ec65c4d021eaf9cc" @@ -825,7 +566,7 @@ confusing-browser-globals@^1.0.10: resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -929,29 +670,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -electron-to-chromium@^1.4.668: - version "1.4.708" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.708.tgz#d54d3b47cb44ae6b190067439c42135456907893" - integrity sha512-iWgEEvREL4GTXXHKohhh33+6Y8XkPI5eHihDmm8zUk5Zo7HICEW+wI/j5kJ2tbuNUCXJ/sNXa03ajW635DiJXA== - emoji-regex@^9.2.2: version "9.2.2" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== -enhanced-resolve@^5.0.0, enhanced-resolve@^5.15.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787" - integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -envinfo@^7.7.3: - version "7.11.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.11.1.tgz#2ffef77591057081b0129a8fd8cf6118da1b94e1" - integrity sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg== - es-abstract@^1.22.1, es-abstract@^1.22.3: version "1.22.5" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.5.tgz#1417df4e97cc55f09bf7e58d1e614bc61cb8df46" @@ -1088,11 +811,6 @@ es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.17: iterator.prototype "^1.1.2" safe-array-concat "^1.1.2" -es-module-lexer@^1.2.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5" - integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w== - es-object-atoms@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" @@ -1125,11 +843,6 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -escalade@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== - escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -1289,7 +1002,7 @@ eslint-plugin-simple-import-sort@^8.0.0: resolved "https://registry.yarnpkg.com/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-8.0.0.tgz#9d9a2372b0606e999ea841b10458a370a6ccc160" integrity sha512-bXgJQ+lqhtQBCuWY/FUWdB27j4+lqcvXv5rUARkzbeWLwea+S5eBZEQrhnO+WgX3ZoJHVj0cn943iyXwByHHQw== -eslint-scope@5.1.1, eslint-scope@^5.1.1: +eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -1392,11 +1105,6 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -events@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1423,11 +1131,6 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== -fastest-levenshtein@^1.0.12: - version "1.0.16" - resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" - integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== - fastq@^1.6.0: version "1.17.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" @@ -1435,10 +1138,10 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -fflate@~0.6.10: - version "0.6.10" - resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.6.10.tgz#5f40f9659205936a2d18abf88b2e7781662b6d43" - integrity sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg== +fflate@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" + integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== file-entry-cache@^6.0.1: version "6.0.1" @@ -1454,14 +1157,6 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -find-up@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -1479,11 +1174,6 @@ flat-cache@^3.0.4: keyv "^4.5.3" rimraf "^3.0.2" -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - flatted@^3.2.9: version "3.3.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" @@ -1555,11 +1245,6 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - glob@^7.1.3, glob@^7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -1605,11 +1290,6 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - graphemer@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" @@ -1669,14 +1349,6 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -1704,11 +1376,6 @@ internal-slot@^1.0.5, internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" -interpret@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" - integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== - is-array-buffer@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" @@ -1825,13 +1492,6 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -1903,11 +1563,6 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== - iterator.prototype@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" @@ -1919,15 +1574,6 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" -jest-worker@^27.4.5: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - "js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -1950,11 +1596,6 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-even-better-errors@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -1994,11 +1635,6 @@ keyv@^4.5.3: dependencies: json-buffer "3.0.1" -kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - language-subtag-registry@^0.3.20: version "0.3.22" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" @@ -2024,18 +1660,6 @@ lil-gui@^0.19.2: resolved "https://registry.yarnpkg.com/lil-gui/-/lil-gui-0.19.2.tgz#774bf46f1f43ec5fec00884af46b8060786f97fc" integrity sha512-nU8j4ND702ouGfQZoaTN4dfXxacvGOAVK0DtmZBVcUYUAeYQXLQAjAN50igMHiba3T5jZyKEjXZU+Ntm1Qs6ZQ== -loader-runner@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" - integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -2072,11 +1696,6 @@ marked@^4.3.0: resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -2087,7 +1706,7 @@ meshoptimizer@~0.18.1: resolved "https://registry.yarnpkg.com/meshoptimizer/-/meshoptimizer-0.18.1.tgz#cdb90907f30a7b5b1190facd3b7ee6b7087797d8" integrity sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw== -micromatch@^4.0.0, micromatch@^4.0.4: +micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -2095,18 +1714,6 @@ micromatch@^4.0.0, micromatch@^4.0.4: braces "^3.0.2" picomatch "^2.3.1" -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.27: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - minimatch@9.0.3, minimatch@^9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" @@ -2141,16 +1748,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== - object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -2241,13 +1838,6 @@ optionator@^0.9.3: prelude-ls "^1.2.1" type-check "^0.4.0" -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" @@ -2255,13 +1845,6 @@ p-limit@^3.0.2: dependencies: yocto-queue "^0.1.0" -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -2269,11 +1852,6 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -2306,23 +1884,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - plotly.js-dist@^2.30.1: version "2.30.1" resolved "https://registry.yarnpkg.com/plotly.js-dist/-/plotly.js-dist-2.30.1.tgz#98ef3f6e5d5f34d53390c2e8ff5d2668bfcfb4d8" @@ -2357,25 +1923,11 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - react-is@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -rechoir@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" - integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== - dependencies: - resolve "^1.20.0" - reflect.getprototypeof@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" @@ -2404,24 +1956,12 @@ regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.2: es-errors "^1.3.0" set-function-name "^2.0.1" -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.4: +resolve@^1.22.0, resolve@^1.22.4: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -2468,11 +2008,6 @@ safe-array-concat@^1.1.0, safe-array-concat@^1.1.2: has-symbols "^1.0.3" isarray "^2.0.5" -safe-buffer@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - safe-regex-test@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" @@ -2482,34 +2017,18 @@ safe-regex-test@^1.0.3: es-errors "^1.3.0" is-regex "^1.1.4" -schema-utils@^3.1.1, schema-utils@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" - integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.4, semver@^7.3.7, semver@^7.5.4, semver@^7.6.0: +semver@^7.3.7, semver@^7.5.4, semver@^7.6.0: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== dependencies: lru-cache "^6.0.0" -serialize-javascript@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" - integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== - dependencies: - randombytes "^2.1.0" - set-function-length@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" @@ -2532,13 +2051,6 @@ set-function-name@^2.0.0, set-function-name@^2.0.1: functions-have-names "^1.2.3" has-property-descriptors "^1.0.2" -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -2576,24 +2088,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" - integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== - spdx-exceptions@^2.1.0: version "2.5.0" resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" @@ -2679,53 +2173,20 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -tapable@^2.1.1, tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -terser-webpack-plugin@^5.3.10: - version "5.3.10" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" - integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== - dependencies: - "@jridgewell/trace-mapping" "^0.3.20" - jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.1" - terser "^5.26.0" - -terser@^5.26.0: - version "5.29.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.29.2.tgz#c17d573ce1da1b30f21a877bffd5655dd86fdb35" - integrity sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw== - dependencies: - "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" - commander "^2.20.0" - source-map-support "~0.5.20" - text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -three@^0.158.0: - version "0.158.0" - resolved "https://registry.yarnpkg.com/three/-/three-0.158.0.tgz#03ddd5b60ce9c31be8fb69f27a6d9efd49908ac3" - integrity sha512-TALj4EOpdDPF1henk2Q+s17K61uEAAWQ7TJB68nr7FKxqwyDr3msOt5IWdbGm4TaWKjrtWS8DJJWe9JnvsWOhQ== +three@^0.163.0: + version "0.163.0" + resolved "https://registry.yarnpkg.com/three/-/three-0.163.0.tgz#cbfefbfd64a1353ab7cc8bf0fc396ddca1875a49" + integrity sha512-HlMgCb2TF/dTLRtknBnjUTsR8FsDqBY43itYop2+Zg822I+Kd0Ua2vs8CvfBVefXkBdNDrLMoRTGCIIpfCuDew== to-regex-range@^5.0.1: version "5.0.1" @@ -2739,17 +2200,6 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== -ts-loader@^9.5.1: - version "9.5.1" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.5.1.tgz#63d5912a86312f1fbe32cef0859fb8b2193d9b89" - integrity sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg== - dependencies: - chalk "^4.1.0" - enhanced-resolve "^5.0.0" - micromatch "^4.0.0" - semver "^7.3.4" - source-map "^0.7.4" - tsconfig-paths@^3.14.1, tsconfig-paths@^3.15.0: version "3.15.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" @@ -2853,19 +2303,6 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -2883,77 +2320,6 @@ vscode-textmate@^8.0.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d" integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg== -watchpack@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" - integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -webpack-cli@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" - integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== - dependencies: - "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^2.1.1" - "@webpack-cli/info" "^2.0.2" - "@webpack-cli/serve" "^2.0.5" - colorette "^2.0.14" - commander "^10.0.1" - cross-spawn "^7.0.3" - envinfo "^7.7.3" - fastest-levenshtein "^1.0.12" - import-local "^3.0.2" - interpret "^3.1.1" - rechoir "^0.8.0" - webpack-merge "^5.7.3" - -webpack-merge@^5.7.3: - version "5.10.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" - integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== - dependencies: - clone-deep "^4.0.1" - flat "^5.0.2" - wildcard "^2.0.0" - -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5.90.3: - version "5.90.3" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.90.3.tgz#37b8f74d3ded061ba789bb22b31e82eed75bd9ac" - integrity sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA== - dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^1.0.5" - "@webassemblyjs/ast" "^1.11.5" - "@webassemblyjs/wasm-edit" "^1.11.5" - "@webassemblyjs/wasm-parser" "^1.11.5" - acorn "^8.7.1" - acorn-import-assertions "^1.9.0" - browserslist "^4.21.10" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.15.0" - es-module-lexer "^1.2.1" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.2.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.3.10" - watchpack "^2.4.0" - webpack-sources "^3.2.3" - which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -3011,11 +2377,6 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -wildcard@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" - integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"