From 9b3e93891035dee16ba382d96894caa33d446780 Mon Sep 17 00:00:00 2001 From: darcyabjones Date: Thu, 19 Sep 2024 16:42:17 +0200 Subject: [PATCH 1/3] Added gridstack-extra to enable setting columns --- inst/htmlwidgets/gridstack.js | 6602 ++++++++++++++++++++++++++++++++- srcjs/widgets/gridstack.js | 1 + 2 files changed, 6601 insertions(+), 2 deletions(-) diff --git a/inst/htmlwidgets/gridstack.js b/inst/htmlwidgets/gridstack.js index 8ef696b..eeb4d38 100644 --- a/inst/htmlwidgets/gridstack.js +++ b/inst/htmlwidgets/gridstack.js @@ -1,2 +1,6600 @@ -/*! For license information please see gridstack.js.LICENSE.txt */ -(()=>{"use strict";var e={365:(e,t,i)=>{i.d(t,{A:()=>g});var s=i(601),o=i.n(s),n=i(314),r=i.n(n),a=i(417),l=i.n(a),d=new URL(i(487),i.b),h=r()(o()),c=l()(d);h.push([e.id,`.grid-stack{position:relative}.grid-stack-rtl{direction:ltr}.grid-stack-rtl>.grid-stack-item{direction:rtl}.grid-stack-placeholder>.placeholder-content{background-color:rgba(0,0,0,.1);margin:0;position:absolute;width:auto;z-index:0!important}.grid-stack>.grid-stack-item{position:absolute;padding:0}.grid-stack>.grid-stack-item>.grid-stack-item-content{margin:0;position:absolute;width:auto;overflow-x:hidden;overflow-y:auto}.grid-stack>.grid-stack-item.size-to-content:not(.size-to-content-max)>.grid-stack-item-content{overflow-y:hidden}.grid-stack-item>.ui-resizable-handle{position:absolute;font-size:.1px;display:block;-ms-touch-action:none;touch-action:none}.grid-stack-item.ui-resizable-autohide>.ui-resizable-handle,.grid-stack-item.ui-resizable-disabled>.ui-resizable-handle{display:none}.grid-stack-item>.ui-resizable-ne,.grid-stack-item>.ui-resizable-nw,.grid-stack-item>.ui-resizable-se,.grid-stack-item>.ui-resizable-sw{background-image:url(${c});background-repeat:no-repeat;background-position:center}.grid-stack-item>.ui-resizable-ne{transform:translate(0,10px) rotate(45deg)}.grid-stack-item>.ui-resizable-sw{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-nw{transform:translate(0,10px) rotate(-45deg)}.grid-stack-item>.ui-resizable-se{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-nw{cursor:nw-resize;width:20px;height:20px;top:0}.grid-stack-item>.ui-resizable-n{cursor:n-resize;height:10px;top:0;left:25px;right:25px}.grid-stack-item>.ui-resizable-ne{cursor:ne-resize;width:20px;height:20px;top:0}.grid-stack-item>.ui-resizable-e{cursor:e-resize;width:10px;top:15px;bottom:15px}.grid-stack-item>.ui-resizable-se{cursor:se-resize;width:20px;height:20px}.grid-stack-item>.ui-resizable-s{cursor:s-resize;height:10px;left:25px;bottom:0;right:25px}.grid-stack-item>.ui-resizable-sw{cursor:sw-resize;width:20px;height:20px}.grid-stack-item>.ui-resizable-w{cursor:w-resize;width:10px;top:15px;bottom:15px}.grid-stack-item.ui-draggable-dragging>.ui-resizable-handle{display:none!important}.grid-stack-item.ui-draggable-dragging{will-change:left,top;cursor:move}.grid-stack-item.ui-resizable-resizing{will-change:width,height}.ui-draggable-dragging,.ui-resizable-resizing{z-index:10000}.ui-draggable-dragging>.grid-stack-item-content,.ui-resizable-resizing>.grid-stack-item-content{box-shadow:1px 4px 6px rgba(0,0,0,.2);opacity:.8}.grid-stack-animate,.grid-stack-animate .grid-stack-item{transition:left .3s,top .3s,height .3s,width .3s}.grid-stack-animate .grid-stack-item.grid-stack-placeholder,.grid-stack-animate .grid-stack-item.ui-draggable-dragging,.grid-stack-animate .grid-stack-item.ui-resizable-resizing{transition:left 0s,top 0s,height 0s,width 0s}.grid-stack>.grid-stack-item[gs-y="0"]{top:0}.grid-stack>.grid-stack-item[gs-x="0"]{left:0}.gs-12>.grid-stack-item{width:8.333%}.gs-12>.grid-stack-item[gs-x="1"]{left:8.333%}.gs-12>.grid-stack-item[gs-w="2"]{width:16.667%}.gs-12>.grid-stack-item[gs-x="2"]{left:16.667%}.gs-12>.grid-stack-item[gs-w="3"]{width:25%}.gs-12>.grid-stack-item[gs-x="3"]{left:25%}.gs-12>.grid-stack-item[gs-w="4"]{width:33.333%}.gs-12>.grid-stack-item[gs-x="4"]{left:33.333%}.gs-12>.grid-stack-item[gs-w="5"]{width:41.667%}.gs-12>.grid-stack-item[gs-x="5"]{left:41.667%}.gs-12>.grid-stack-item[gs-w="6"]{width:50%}.gs-12>.grid-stack-item[gs-x="6"]{left:50%}.gs-12>.grid-stack-item[gs-w="7"]{width:58.333%}.gs-12>.grid-stack-item[gs-x="7"]{left:58.333%}.gs-12>.grid-stack-item[gs-w="8"]{width:66.667%}.gs-12>.grid-stack-item[gs-x="8"]{left:66.667%}.gs-12>.grid-stack-item[gs-w="9"]{width:75%}.gs-12>.grid-stack-item[gs-x="9"]{left:75%}.gs-12>.grid-stack-item[gs-w="10"]{width:83.333%}.gs-12>.grid-stack-item[gs-x="10"]{left:83.333%}.gs-12>.grid-stack-item[gs-w="11"]{width:91.667%}.gs-12>.grid-stack-item[gs-x="11"]{left:91.667%}.gs-12>.grid-stack-item[gs-w="12"]{width:100%}.gs-1>.grid-stack-item{width:100%}`,""]);const g=h},173:(e,t,i)=>{i.d(t,{A:()=>a});var s=i(601),o=i.n(s),n=i(314),r=i.n(n)()(o());r.push([e.id,"\n.grid-stack-edit {\n padding: 0.25rem;\n border-width: 1px;\n border-radius: 0.5rem;\n}\n\n.gs-item-example {\n border-radius: 8px;\n border: 1px solid red;\n background: #FFF;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: bold;\n}\n\n.gs-trash {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n}\n",""]);const a=r},314:e=>{e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var i="",s=void 0!==t[5];return t[4]&&(i+="@supports (".concat(t[4],") {")),t[2]&&(i+="@media ".concat(t[2]," {")),s&&(i+="@layer".concat(t[5].length>0?" ".concat(t[5]):""," {")),i+=e(t),s&&(i+="}"),t[2]&&(i+="}"),t[4]&&(i+="}"),i})).join("")},t.i=function(e,i,s,o,n){"string"==typeof e&&(e=[[null,e,void 0]]);var r={};if(s)for(var a=0;a0?" ".concat(h[5]):""," {").concat(h[1],"}")),h[5]=n),i&&(h[2]?(h[1]="@media ".concat(h[2]," {").concat(h[1],"}"),h[2]=i):h[2]=i),o&&(h[4]?(h[1]="@supports (".concat(h[4],") {").concat(h[1],"}"),h[4]=o):h[4]="".concat(o)),t.push(h))}},t}},417:e=>{e.exports=function(e,t){return t||(t={}),e?(e=String(e.__esModule?e.default:e),/^['"].*['"]$/.test(e)&&(e=e.slice(1,-1)),t.hash&&(e+=t.hash),/["'() \t\n]|(%20)/.test(e)||t.needQuotes?'"'.concat(e.replace(/"/g,'\\"').replace(/\n/g,"\\n"),'"'):e):e}},601:e=>{e.exports=function(e){return e[1]}},72:e=>{var t=[];function i(e){for(var i=-1,s=0;s{var t={};e.exports=function(e,i){var s=function(e){if(void 0===t[e]){var i=document.querySelector(e);if(window.HTMLIFrameElement&&i instanceof window.HTMLIFrameElement)try{i=i.contentDocument.head}catch(e){i=null}t[e]=i}return t[e]}(e);if(!s)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");s.appendChild(i)}},540:e=>{e.exports=function(e){var t=document.createElement("style");return e.setAttributes(t,e.attributes),e.insert(t,e.options),t}},56:(e,t,i)=>{e.exports=function(e){var t=i.nc;t&&e.setAttribute("nonce",t)}},825:e=>{e.exports=function(e){if("undefined"==typeof document)return{update:function(){},remove:function(){}};var t=e.insertStyleElement(e);return{update:function(i){!function(e,t,i){var s="";i.supports&&(s+="@supports (".concat(i.supports,") {")),i.media&&(s+="@media ".concat(i.media," {"));var o=void 0!==i.layer;o&&(s+="@layer".concat(i.layer.length>0?" ".concat(i.layer):""," {")),s+=i.css,o&&(s+="}"),i.media&&(s+="}"),i.supports&&(s+="}");var n=i.sourceMap;n&&"undefined"!=typeof btoa&&(s+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(n))))," */")),t.styleTagTransform(s,e,t.options)}(t,e,i)},remove:function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(t)}}}},113:e=>{e.exports=function(e,t){if(t.styleSheet)t.styleSheet.cssText=e;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(e))}}},487:e=>{e.exports='data:image/svg+xml;utf8,'}},t={};function i(s){var o=t[s];if(void 0!==o)return o.exports;var n=t[s]={id:s,exports:{}};return e[s](n,n.exports,i),n.exports}i.m=e,i.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return i.d(t,{a:t}),t},i.d=(e,t)=>{for(var s in t)i.o(t,s)&&!i.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})},i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),i.b=document.baseURI||self.location.href,i.nc=void 0,(()=>{HTMLWidgets;var e=i(72),t=i.n(e),s=i(825),o=i.n(s),n=i(659),r=i.n(n),a=i(56),l=i.n(a),d=i(540),h=i.n(d),c=i(113),g=i.n(c),u=i(365),p={};p.styleTagTransform=g(),p.setAttributes=l(),p.insert=r().bind(null,"head"),p.domAPI=o(),p.insertStyleElement=h(),t()(u.A,p),u.A&&u.A.locals&&u.A.locals;class m{static getElements(e,t=document){if("string"==typeof e){const i="getElementById"in t?t:void 0;if(i&&!isNaN(+e[0])){const t=i.getElementById(e);return t?[t]:[]}let s=t.querySelectorAll(e);return s.length||"."===e[0]||"#"===e[0]||(s=t.querySelectorAll("."+e),s.length||(s=t.querySelectorAll("#"+e))),Array.from(s)}return[e]}static getElement(e,t=document){if("string"==typeof e){const i="getElementById"in t?t:void 0;if(!e.length)return null;if(i&&"#"===e[0])return i.getElementById(e.substring(1));if("#"===e[0]||"."===e[0]||"["===e[0])return t.querySelector(e);if(i&&!isNaN(+e[0]))return i.getElementById(e);let s=t.querySelector(e);return i&&!s&&(s=i.getElementById(e)),s||(s=t.querySelector("."+e)),s}return e}static shouldSizeToContent(e,t=!1){return e?.grid&&(t?!0===e.sizeToContent||!0===e.grid.opts.sizeToContent&&void 0===e.sizeToContent:!!e.sizeToContent||e.grid.opts.sizeToContent&&!1!==e.sizeToContent)}static isIntercepted(e,t){return!(e.y>=t.y+t.h||e.y+e.h<=t.y||e.x+e.w<=t.x||e.x>=t.x+t.w)}static isTouching(e,t){return m.isIntercepted(e,{x:t.x-.5,y:t.y-.5,w:t.w+1,h:t.h+1})}static areaIntercept(e,t){let i=e.x>t.x?e.x:t.x,s=e.x+e.wt.y?e.y:t.y,n=e.y+e.h{let o=t*((e.y??i)-(s.y??i));return 0===o?t*((e.x??i)-(s.x??i)):o}))}static find(e,t){return t?e.find((e=>e.id===t)):void 0}static createStylesheet(e,t,i){let s=document.createElement("style");const o=i?.nonce;return o&&(s.nonce=o),s.setAttribute("type","text/css"),s.setAttribute("gs-style-id",e),s.styleSheet?s.styleSheet.cssText="":s.appendChild(document.createTextNode("")),t?t.insertBefore(s,t.firstChild):(t=document.getElementsByTagName("head")[0]).appendChild(s),s.sheet}static removeStylesheet(e,t){let i=(t||document).querySelector("STYLE[gs-style-id="+e+"]");i&&i.parentNode&&i.remove()}static addCSSRule(e,t,i){"function"==typeof e.addRule?e.addRule(t,i):"function"==typeof e.insertRule&&e.insertRule(`${t}{${i}}`)}static toBool(e){return"boolean"==typeof e?e:"string"==typeof e?!(""===(e=e.toLowerCase())||"no"===e||"false"===e||"0"===e):Boolean(e)}static toNumber(e){return null===e||0===e.length?void 0:Number(e)}static parseHeight(e){let t,i="px";if("string"==typeof e)if("auto"===e||""===e)t=0;else{let s=e.match(/^(-[0-9]+\.[0-9]+|[0-9]*\.[0-9]+|-[0-9]+|[0-9]+)(px|em|rem|vh|vw|%|cm|mm)?$/);if(!s)throw new Error(`Invalid height val = ${e}`);i=s[2]||"px",t=parseFloat(s[1])}else t=e;return{h:t,unit:i}}static defaults(e,...t){return t.forEach((t=>{for(const i in t){if(!t.hasOwnProperty(i))return;null===e[i]||void 0===e[i]?e[i]=t[i]:"object"==typeof t[i]&&"object"==typeof e[i]&&this.defaults(e[i],t[i])}})),e}static same(e,t){if("object"!=typeof e)return e==t;if(typeof e!=typeof t)return!1;if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const i in e)if(e[i]!==t[i])return!1;return!0}static copyPos(e,t,i=!1){return void 0!==t.x&&(e.x=t.x),void 0!==t.y&&(e.y=t.y),void 0!==t.w&&(e.w=t.w),void 0!==t.h&&(e.h=t.h),i&&(t.minW&&(e.minW=t.minW),t.minH&&(e.minH=t.minH),t.maxW&&(e.maxW=t.maxW),t.maxH&&(e.maxH=t.maxH)),e}static samePos(e,t){return e&&t&&e.x===t.x&&e.y===t.y&&(e.w||1)===(t.w||1)&&(e.h||1)===(t.h||1)}static sanitizeMinMax(e){e.minW||delete e.minW,e.minH||delete e.minH,e.maxW||delete e.maxW,e.maxH||delete e.maxH}static removeInternalAndSame(e,t){if("object"==typeof e&&"object"==typeof t)for(let i in e){let s=e[i];if("_"===i[0]||s===t[i])delete e[i];else if(s&&"object"==typeof s&&void 0!==t[i]){for(let e in s)s[e]!==t[i][e]&&"_"!==e[0]||delete s[e];Object.keys(s).length||delete e[i]}}}static removeInternalForSave(e,t=!0){for(let t in e)"_"!==t[0]&&null!==e[t]&&void 0!==e[t]||delete e[t];delete e.grid,t&&delete e.el,e.autoPosition||delete e.autoPosition,e.noResize||delete e.noResize,e.noMove||delete e.noMove,e.locked||delete e.locked,1!==e.w&&e.w!==e.minW||delete e.w,1!==e.h&&e.h!==e.minH||delete e.h}static throttle(e,t){let i=!1;return(...s)=>{i||(i=!0,setTimeout((()=>{e(...s),i=!1}),t))}}static removePositioningStyles(e){let t=e.style;t.position&&t.removeProperty("position"),t.left&&t.removeProperty("left"),t.top&&t.removeProperty("top"),t.width&&t.removeProperty("width"),t.height&&t.removeProperty("height")}static getScrollElement(e){if(!e)return document.scrollingElement||document.documentElement;const t=getComputedStyle(e);return/(auto|scroll)/.test(t.overflow+t.overflowY)?e:this.getScrollElement(e.parentElement)}static updateScrollPosition(e,t,i){let s=e.getBoundingClientRect(),o=window.innerHeight||document.documentElement.clientHeight;if(s.top<0||s.bottom>o){let n=s.bottom-o,r=s.top,a=this.getScrollElement(e);if(null!==a){let l=a.scrollTop;s.top<0&&i<0?e.offsetHeight>o?a.scrollTop+=i:a.scrollTop+=Math.abs(r)>Math.abs(i)?i:r:i>0&&(e.offsetHeight>o?a.scrollTop+=i:a.scrollTop+=n>i?i:n),t.top+=a.scrollTop-l}}}static updateScrollResize(e,t,i){const s=this.getScrollElement(t),o=s.clientHeight,n=s===this.getScrollElement()?0:s.getBoundingClientRect().top,r=e.clientY-n,a=r>o-i;re===s))&&(i[s]=m.cloneDeep(e[s]));return i}static cloneNode(e){const t=e.cloneNode(!0);return t.removeAttribute("id"),t}static appendTo(e,t){let i;i="string"==typeof t?m.getElement(t):t,i&&i.appendChild(e)}static addElStyles(e,t){if(t instanceof Object)for(const i in t)t.hasOwnProperty(i)&&(Array.isArray(t[i])?t[i].forEach((t=>{e.style[i]=t})):e.style[i]=t[i])}static initEvent(e,t){const i={type:t.type},s={button:0,which:0,buttons:1,bubbles:!0,cancelable:!0,target:t.target?t.target:e.target};return e.dataTransfer&&(i.dataTransfer=e.dataTransfer),["altKey","ctrlKey","metaKey","shiftKey"].forEach((t=>i[t]=e[t])),["pageX","pageY","clientX","clientY","screenX","screenY"].forEach((t=>i[t]=e[t])),{...i,...s}}static simulateMouseEvent(e,t,i){const s=document.createEvent("MouseEvents");s.initMouseEvent(t,!0,!0,window,1,e.screenX,e.screenY,e.clientX,e.clientY,e.ctrlKey,e.altKey,e.shiftKey,e.metaKey,0,e.target),(i||e.target).dispatchEvent(s)}static getValuesFromTransformedElement(e){const t=document.createElement("div");m.addElStyles(t,{opacity:"0",position:"fixed",top:"0px",left:"0px",width:"1px",height:"1px",zIndex:"-999999"}),e.appendChild(t);const i=t.getBoundingClientRect();return e.removeChild(t),t.remove(),{xScale:1/i.width,yScale:1/i.height,xOffset:i.left,yOffset:i.top}}}class f{constructor(e={}){this.addedNodes=[],this.removedNodes=[],this.column=e.column||12,this.maxRow=e.maxRow,this._float=e.float,this.nodes=e.nodes||[],this.onChange=e.onChange}batchUpdate(e=!0,t=!0){return!!this.batchMode===e||(this.batchMode=e,e?(this._prevFloat=this._float,this._float=!0,this.cleanNodes(),this.saveInitial()):(this._float=this._prevFloat,delete this._prevFloat,t&&this._packNodes(),this._notify())),this}_useEntireRowArea(e,t){return(!this.float||this.batchMode&&!this._prevFloat)&&!this._hasLocked&&(!e._moving||e._skipDown||t.y<=e.y)}_fixCollisions(e,t=e,i,s={}){if(this.sortNodes(-1),!(i=i||this.collide(e,t)))return!1;if(e._moving&&!s.nested&&!this.float&&this.swap(e,i))return!0;let o=t;this._useEntireRowArea(e,t)&&(o={x:0,w:this.column,y:t.y,h:t.h},i=this.collide(e,o,s.skip));let n=!1,r={nested:!0,pack:!1};for(;i=i||this.collide(e,o,s.skip);){let o;if(i.locked||e._moving&&!e._skipDown&&t.y>e.y&&!this.float&&(!this.collide(i,{...i,y:e.y},e)||!this.collide(i,{...i,y:t.y-i.h},e))?(e._skipDown=e._skipDown||t.y>e.y,o=this.moveNode(e,{...t,y:i.y+i.h,...r}),i.locked&&o?m.copyPos(t,e):!i.locked&&o&&s.pack&&(this._packNodes(),t.y=i.y+i.h,m.copyPos(e,t)),n=n||o):o=this.moveNode(i,{...i,y:t.y+t.h,skip:e,...r}),!o)return n;i=void 0}return n}collide(e,t=e,i){const s=e._id,o=i?._id;return this.nodes.find((e=>e._id!==s&&e._id!==o&&m.isIntercepted(e,t)))}collideAll(e,t=e,i){const s=e._id,o=i?._id;return this.nodes.filter((e=>e._id!==s&&e._id!==o&&m.isIntercepted(e,t)))}directionCollideCoverage(e,t,i){if(!t.rect||!e._rect)return;let s,o=e._rect,n={...t.rect};n.y>o.y?(n.h+=n.y-o.y,n.y=o.y):n.h+=o.y-n.y,n.x>o.x?(n.w+=n.x-o.x,n.x=o.x):n.w+=o.x-n.x;let r=.5;for(let e of i){if(e.locked||!e._rect)break;let t=e._rect,i=Number.MAX_VALUE,a=Number.MAX_VALUE;o.yt.y+t.h&&(i=(t.y+t.h-n.y)/t.h),o.xt.x+t.w&&(a=(t.x+t.w-n.x)/t.w);let l=Math.min(a,i);l>r&&(r=l,s=e)}return t.collide=s,s}cacheRects(e,t,i,s,o,n){return this.nodes.forEach((r=>r._rect={y:r.y*t+i,x:r.x*e+n,w:r.w*e-n-s,h:r.h*t-i-o})),this}swap(e,t){if(!t||t.locked||!e||e.locked)return!1;function i(){let i=t.x,s=t.y;return t.x=e.x,t.y=e.y,e.h!=t.h?(e.x=i,e.y=t.y+t.h):e.w!=t.w?(e.x=t.x+t.w,e.y=s):(e.x=i,e.y=s),e._dirty=t._dirty=!0,!0}let s;if(e.w===t.w&&e.h===t.h&&(e.x===t.x||e.y===t.y)&&(s=m.isTouching(e,t)))return i();if(!1!==s){if(e.w===t.w&&e.x===t.x&&(s||(s=m.isTouching(e,t)))){if(t.y{let o;t.locked||(t.autoPosition=!0,"list"===e&&i&&(o=s[i-1])),this.addNode(t,!1,o)})),s||delete this._inColumnResize,i||this.batchUpdate(!1),this}set float(e){this._float!==e&&(this._float=e||!1,e||this._packNodes()._notify())}get float(){return this._float||!1}sortNodes(e=1){return this.nodes=m.sort(this.nodes,e),this}_packNodes(){return this.batchMode||(this.sortNodes(),this.float?this.nodes.forEach((e=>{if(e._updating||void 0===e._orig||e.y===e._orig.y)return;let t=e.y;for(;t>e._orig.y;)--t,this.collide(e,{x:e.x,y:t,w:e.w,h:e.h})||(e._dirty=!0,e.y=t)})):this.nodes.forEach(((e,t)=>{if(!e.locked)for(;e.y>0;){let i=0===t?0:e.y-1;if(0!==t&&this.collide(e,{x:e.x,y:i,w:e.w,h:e.h}))break;e._dirty=e.y!==i,e.y=i}}))),this}prepareNode(e,t){e._id=e._id??f._idSeq++,void 0!==e.x&&void 0!==e.y&&null!==e.x&&null!==e.y||(e.autoPosition=!0);let i={x:0,y:0,w:1,h:1};return m.defaults(e,i),e.autoPosition||delete e.autoPosition,e.noResize||delete e.noResize,e.noMove||delete e.noMove,m.sanitizeMinMax(e),"string"==typeof e.x&&(e.x=Number(e.x)),"string"==typeof e.y&&(e.y=Number(e.y)),"string"==typeof e.w&&(e.w=Number(e.w)),"string"==typeof e.h&&(e.h=Number(e.h)),isNaN(e.x)&&(e.x=i.x,e.autoPosition=!0),isNaN(e.y)&&(e.y=i.y,e.autoPosition=!0),isNaN(e.w)&&(e.w=i.w),isNaN(e.h)&&(e.h=i.h),this.nodeBoundFix(e,t),e}nodeBoundFix(e,t){let i=e._orig||m.copyPos({},e);if(e.maxW&&(e.w=Math.min(e.w,e.maxW)),e.maxH&&(e.h=Math.min(e.h,e.maxH)),e.minW&&e.minW<=this.column&&(e.w=Math.max(e.w,e.minW)),e.minH&&(e.h=Math.max(e.h,e.minH)),(e.x||0)+(e.w||1)>this.column&&this.column<12&&!this._inColumnResize&&e._id&&-1===this.findCacheLayout(e,12)){let t={...e};t.autoPosition||void 0===t.x?(delete t.x,delete t.y):t.x=Math.min(11,t.x),t.w=Math.min(12,t.w||1),this.cacheOneLayout(t,12)}return e.w>this.column?e.w=this.column:e.w<1&&(e.w=1),this.maxRow&&e.h>this.maxRow?e.h=this.maxRow:e.h<1&&(e.h=1),e.x<0&&(e.x=0),e.y<0&&(e.y=0),e.x+e.w>this.column&&(t?e.w=this.column-e.x:e.x=this.column-e.w),this.maxRow&&e.y+e.h>this.maxRow&&(t?e.h=this.maxRow-e.y:e.y=this.maxRow-e.h),m.samePos(e,i)||(e._dirty=!0),this}getDirtyNodes(e){return e?this.nodes.filter((e=>e._dirty&&!m.samePos(e,e._orig))):this.nodes.filter((e=>e._dirty))}_notify(e){if(this.batchMode||!this.onChange)return this;let t=(e||[]).concat(this.getDirtyNodes());return this.onChange(t),this}cleanNodes(){return this.batchMode||this.nodes.forEach((e=>{delete e._dirty,delete e._lastTried})),this}saveInitial(){return this.nodes.forEach((e=>{e._orig=m.copyPos({},e),delete e._dirty})),this._hasLocked=this.nodes.some((e=>e.locked)),this}restoreInitial(){return this.nodes.forEach((e=>{m.samePos(e,e._orig)||(m.copyPos(e,e._orig),e._dirty=!0)})),this._notify(),this}findEmptyPosition(e,t=this.nodes,i=this.column,s){let o=!1;for(let n=s?s.y*i+(s.x+s.w):0;!o;++n){let s=n%i,r=Math.floor(n/i);if(s+e.w>i)continue;let a={x:s,y:r,w:e.w,h:e.h};t.find((e=>m.isIntercepted(a,e)))||(e.x===s&&e.y===r||(e._dirty=!0),e.x=s,e.y=r,delete e.autoPosition,o=!0)}return o}addNode(e,t=!1,i){let s;return this.nodes.find((t=>t._id===e._id))||(this._inColumnResize?this.nodeBoundFix(e):this.prepareNode(e),delete e._temporaryRemoved,delete e._removeDOM,e.autoPosition&&this.findEmptyPosition(e,this.nodes,this.column,i)&&(delete e.autoPosition,s=!0),this.nodes.push(e),t&&this.addedNodes.push(e),s||this._fixCollisions(e),this.batchMode||this._packNodes()._notify(),e)}removeNode(e,t=!0,i=!1){return this.nodes.find((t=>t._id===e._id))?(i&&this.removedNodes.push(e),t&&(e._removeDOM=!0),this.nodes=this.nodes.filter((t=>t._id!==e._id)),e._isAboutToRemove||this._packNodes(),this._notify([e]),this):this}removeAll(e=!0,t=!0){if(delete this._layouts,!this.nodes.length)return this;e&&this.nodes.forEach((e=>e._removeDOM=!0));const i=this.nodes;return this.removedNodes=t?i:[],this.nodes=[],this._notify(i)}moveNodeCheck(e,t){if(!this.changedPosConstrain(e,t))return!1;if(t.pack=!0,!this.maxRow)return this.moveNode(e,t);let i,s=new f({column:this.column,float:this.float,nodes:this.nodes.map((t=>t._id===e._id?(i={...t},i):{...t}))});if(!i)return!1;let o=s.moveNode(i,t)&&s.getRow()<=Math.max(this.getRow(),this.maxRow);if(!o&&!t.resizing&&t.collide){let i=t.collide.el.gridstackNode;if(this.swap(e,i))return this._notify(),!0}return!!o&&(s.nodes.filter((e=>e._dirty)).forEach((e=>{let t=this.nodes.find((t=>t._id===e._id));t&&(m.copyPos(t,e),t._dirty=!0)})),this._notify(),!0)}willItFit(e){if(delete e._willFitPos,!this.maxRow)return!0;let t=new f({column:this.column,float:this.float,nodes:this.nodes.map((e=>({...e})))}),i={...e};return this.cleanupNode(i),delete i.el,delete i._id,delete i.content,delete i.grid,t.addNode(i),t.getRow()<=this.maxRow&&(e._willFitPos=m.copyPos({},i),!0)}changedPosConstrain(e,t){return t.w=t.w||e.w,t.h=t.h||e.h,e.x!==t.x||e.y!==t.y||(e.maxW&&(t.w=Math.min(t.w,e.maxW)),e.maxH&&(t.h=Math.min(t.h,e.maxH)),e.minW&&(t.w=Math.max(t.w,e.minW)),e.minH&&(t.h=Math.max(t.h,e.minH)),e.w!==t.w||e.h!==t.h)}moveNode(e,t){if(!e||!t)return!1;let i;void 0!==t.pack||this.batchMode||(i=t.pack=!0),"number"!=typeof t.x&&(t.x=e.x),"number"!=typeof t.y&&(t.y=e.y),"number"!=typeof t.w&&(t.w=e.w),"number"!=typeof t.h&&(t.h=e.h);let s=e.w!==t.w||e.h!==t.h,o=m.copyPos({},e,!0);if(m.copyPos(o,t),this.nodeBoundFix(o,s),m.copyPos(t,o),!t.forceCollide&&m.samePos(e,t))return!1;let n=m.copyPos({},e),r=this.collideAll(e,o,t.skip),a=!0;if(r.length){let s=e._moving&&!t.nested,n=s?this.directionCollideCoverage(e,t,r):r[0];if(s&&n&&e.grid?.opts?.subGridDynamic&&!e.grid._isTemp){let i=m.areaIntercept(t.rect,n._rect),s=m.area(t.rect),o=m.area(n._rect);i/(s.8&&(n.grid.makeSubGrid(n.el,void 0,e),n=void 0)}n?a=!this._fixCollisions(e,o,n,t):(a=!1,i&&delete t.pack)}return a&&(e._dirty=!0,m.copyPos(e,o)),t.pack&&this._packNodes()._notify(),!m.samePos(e,n)}getRow(){return this.nodes.reduce(((e,t)=>Math.max(e,t.y+t.h)),0)}beginUpdate(e){return e._updating||(e._updating=!0,delete e._skipDown,this.batchMode||this.saveInitial()),this}endUpdate(){let e=this.nodes.find((e=>e._updating));return e&&(delete e._updating,delete e._skipDown),this}save(e=!0,t){let i=this._layouts?.length,s=i&&this.column!==i-1?this._layouts[i-1]:null,o=[];return this.sortNodes(),this.nodes.forEach((i=>{let n=s?.find((e=>e._id===i._id)),r={...i,...n||{}};m.removeInternalForSave(r,!e),t&&t(i,r),o.push(r)})),o}layoutsNodesChange(e){return!this._layouts||this._inColumnResize||this._layouts.forEach(((t,i)=>{if(!t||i===this.column)return this;if(i{if(!e._orig)return;let i=t.find((t=>t._id===e._id));i&&(i.y>=0&&e.y!==e._orig.y&&(i.y+=e.y-e._orig.y),e.x!==e._orig.x&&(i.x=Math.round(e.x*s)),e.w!==e._orig.w&&(i.w=Math.round(e.w*s)))}))}})),this}columnChanged(e,t,i="moveScale"){if(!this.nodes.length||!t||e===t)return this;if("none"===i)return this;const s="compact"===i||"list"===i;s&&this.sortNodes(1),te&&this._layouts){const i=this._layouts[t]||[];let r=this._layouts.length-1;!i.length&&e!==r&&this._layouts[r]?.length&&(e=r,this._layouts[r].forEach((e=>{let t=n.find((t=>t._id===e._id));t&&(s||e.autoPosition||(t.x=e.x??t.x,t.y=e.y??t.y),t.w=e.w??t.w,null!=e.x&&void 0!==e.y||(t.autoPosition=!0))}))),i.forEach((e=>{let t=n.findIndex((t=>t._id===e._id));if(-1!==t){const i=n[t];if(s)return void(i.w=e.w);(e.autoPosition||isNaN(e.x)||isNaN(e.y))&&this.findEmptyPosition(e,o),e.autoPosition||(i.x=e.x??i.x,i.y=e.y??i.y,i.w=e.w??i.w,o.push(i)),n.splice(t,1)}}))}if(s)this.compact(i,!1);else{if(n.length)if("function"==typeof i)i(t,e,o,n);else{let r=s?1:t/e,a="move"===i||"moveScale"===i,l="scale"===i||"moveScale"===i;n.forEach((i=>{i.x=1===t?0:a?Math.round(i.x*r):Math.min(i.x,t-1),i.w=1===t||1===e?1:l?Math.round(i.w*r)||1:Math.min(i.w,t),o.push(i)})),n=[]}o=m.sort(o,-1),this._inColumnResize=!0,this.nodes=[],o.forEach((e=>{this.addNode(e,!1),delete e._orig}))}return this.nodes.forEach((e=>delete e._orig)),this.batchUpdate(!1,!s),delete this._inColumnResize,this}cacheLayout(e,t,i=!1){let s=[];return e.forEach(((e,t)=>{if(void 0===e._id){const t=e.id?this.nodes.find((t=>t.id===e.id)):void 0;e._id=t?._id??f._idSeq++}s[t]={x:e.x,y:e.y,w:e.w,_id:e._id}})),this._layouts=i?[]:this._layouts||[],this._layouts[t]=s,this}cacheOneLayout(e,t){e._id=e._id??f._idSeq++;let i={x:e.x,y:e.y,w:e.w,_id:e._id};(e.autoPosition||void 0===e.x)&&(delete i.x,delete i.y,e.autoPosition&&(i.autoPosition=!0)),this._layouts=this._layouts||[],this._layouts[t]=this._layouts[t]||[];let s=this.findCacheLayout(e,t);return-1===s?this._layouts[t].push(i):this._layouts[t][s]=i,this}findCacheLayout(e,t){return this._layouts?.[t]?.findIndex((t=>t._id===e._id))??-1}removeNodeFromLayoutCache(e){if(this._layouts)for(let t=0;t0||navigator.msMaxTouchPoints>0);class w{}function E(e,t){if(e.touches.length>1)return;e.cancelable&&e.preventDefault();const i=e.changedTouches[0],s=document.createEvent("MouseEvents");s.initMouseEvent(t,!0,!0,window,1,i.screenX,i.screenY,i.clientX,i.clientY,!1,!1,!1,!1,0,null),e.target.dispatchEvent(s)}function x(e,t){e.cancelable&&e.preventDefault();const i=document.createEvent("MouseEvents");i.initMouseEvent(t,!0,!0,window,1,e.screenX,e.screenY,e.clientX,e.clientY,!1,!1,!1,!1,0,null),e.target.dispatchEvent(i)}function C(e){w.touchHandled||(w.touchHandled=!0,E(e,"mousedown"))}function k(e){w.touchHandled&&E(e,"mousemove")}function z(e){if(!w.touchHandled)return;w.pointerLeaveTimeout&&(window.clearTimeout(w.pointerLeaveTimeout),delete w.pointerLeaveTimeout);const t=!!_.dragElement;E(e,"mouseup"),t||E(e,"click"),w.touchHandled=!1}function R(e){"mouse"!==e.pointerType&&e.target.releasePointerCapture(e.pointerId)}function S(e){_.dragElement&&"mouse"!==e.pointerType&&x(e,"mouseenter")}function H(e){_.dragElement&&"mouse"!==e.pointerType&&(w.pointerLeaveTimeout=window.setTimeout((()=>{delete w.pointerLeaveTimeout,x(e,"mouseleave")}),10))}class T{constructor(e,t,i){this.host=e,this.dir=t,this.option=i,this.moving=!1,this._mouseDown=this._mouseDown.bind(this),this._mouseMove=this._mouseMove.bind(this),this._mouseUp=this._mouseUp.bind(this),this._init()}_init(){const e=this.el=document.createElement("div");return e.classList.add("ui-resizable-handle"),e.classList.add(`${T.prefix}${this.dir}`),e.style.zIndex="100",e.style.userSelect="none",this.host.appendChild(this.el),this.el.addEventListener("mousedown",this._mouseDown),b&&(this.el.addEventListener("touchstart",C),this.el.addEventListener("pointerdown",R)),this}destroy(){return this.moving&&this._mouseUp(this.mouseDownEvent),this.el.removeEventListener("mousedown",this._mouseDown),b&&(this.el.removeEventListener("touchstart",C),this.el.removeEventListener("pointerdown",R)),this.host.removeChild(this.el),delete this.el,delete this.host,this}_mouseDown(e){this.mouseDownEvent=e,document.addEventListener("mousemove",this._mouseMove,{capture:!0,passive:!0}),document.addEventListener("mouseup",this._mouseUp,!0),b&&(this.el.addEventListener("touchmove",k),this.el.addEventListener("touchend",z)),e.stopPropagation(),e.preventDefault()}_mouseMove(e){let t=this.mouseDownEvent;this.moving?this._triggerEvent("move",e):Math.abs(e.x-t.x)+Math.abs(e.y-t.y)>2&&(this.moving=!0,this._triggerEvent("start",this.mouseDownEvent),this._triggerEvent("move",e)),e.stopPropagation()}_mouseUp(e){this.moving&&this._triggerEvent("stop",e),document.removeEventListener("mousemove",this._mouseMove,!0),document.removeEventListener("mouseup",this._mouseUp,!0),b&&(this.el.removeEventListener("touchmove",k),this.el.removeEventListener("touchend",z)),delete this.moving,delete this.mouseDownEvent,e.stopPropagation(),e.preventDefault()}_triggerEvent(e,t){return this.option[e]&&this.option[e](t),this}}T.prefix="ui-resizable-";class D{constructor(){this._eventRegister={}}get disabled(){return this._disabled}on(e,t){this._eventRegister[e]=t}off(e){delete this._eventRegister[e]}enable(){this._disabled=!1}disable(){this._disabled=!0}destroy(){delete this._eventRegister}triggerEvent(e,t){if(!this.disabled&&this._eventRegister&&this._eventRegister[e])return this._eventRegister[e](t)}}class N extends D{constructor(e,t={}){super(),this.el=e,this.option=t,this.rectScale={x:1,y:1},this._ui=()=>{const e=this.el.parentElement.getBoundingClientRect(),t={width:this.originalRect.width,height:this.originalRect.height+this.scrolled,left:this.originalRect.left,top:this.originalRect.top-this.scrolled},i=this.temporalRect||t;return{position:{left:(i.left-e.left)*this.rectScale.x,top:(i.top-e.top)*this.rectScale.y},size:{width:i.width*this.rectScale.x,height:i.height*this.rectScale.y}}},this._mouseOver=this._mouseOver.bind(this),this._mouseOut=this._mouseOut.bind(this),this.enable(),this._setupAutoHide(this.option.autoHide),this._setupHandlers()}on(e,t){super.on(e,t)}off(e){super.off(e)}enable(){super.enable(),this.el.classList.remove("ui-resizable-disabled"),this._setupAutoHide(this.option.autoHide)}disable(){super.disable(),this.el.classList.add("ui-resizable-disabled"),this._setupAutoHide(!1)}destroy(){this._removeHandlers(),this._setupAutoHide(!1),delete this.el,super.destroy()}updateOption(e){let t=e.handles&&e.handles!==this.option.handles,i=e.autoHide&&e.autoHide!==this.option.autoHide;return Object.keys(e).forEach((t=>this.option[t]=e[t])),t&&(this._removeHandlers(),this._setupHandlers()),i&&this._setupAutoHide(this.option.autoHide),this}_setupAutoHide(e){return e?(this.el.classList.add("ui-resizable-autohide"),this.el.addEventListener("mouseover",this._mouseOver),this.el.addEventListener("mouseout",this._mouseOut)):(this.el.classList.remove("ui-resizable-autohide"),this.el.removeEventListener("mouseover",this._mouseOver),this.el.removeEventListener("mouseout",this._mouseOut),_.overResizeElement===this&&delete _.overResizeElement),this}_mouseOver(e){_.overResizeElement||_.dragElement||(_.overResizeElement=this,this.el.classList.remove("ui-resizable-autohide"))}_mouseOut(e){_.overResizeElement===this&&(delete _.overResizeElement,this.el.classList.add("ui-resizable-autohide"))}_setupHandlers(){return this.handlers=this.option.handles.split(",").map((e=>e.trim())).map((e=>new T(this.el,e,{start:e=>{this._resizeStart(e)},stop:e=>{this._resizeStop(e)},move:t=>{this._resizing(t,e)}}))),this}_resizeStart(e){this.sizeToContent=m.shouldSizeToContent(this.el.gridstackNode,!0),this.originalRect=this.el.getBoundingClientRect(),this.scrollEl=m.getScrollElement(this.el),this.scrollY=this.scrollEl.scrollTop,this.scrolled=0,this.startEvent=e,this._setupHelper(),this._applyChange();const t=m.initEvent(e,{type:"resizestart",target:this.el});return this.option.start&&this.option.start(t,this._ui()),this.el.classList.add("ui-resizable-resizing"),this.triggerEvent("resizestart",t),this}_resizing(e,t){this.scrolled=this.scrollEl.scrollTop-this.scrollY,this.temporalRect=this._getChange(e,t),this._applyChange();const i=m.initEvent(e,{type:"resize",target:this.el});return this.option.resize&&this.option.resize(i,this._ui()),this.triggerEvent("resize",i),this}_resizeStop(e){const t=m.initEvent(e,{type:"resizestop",target:this.el});return this.option.stop&&this.option.stop(t),this.el.classList.remove("ui-resizable-resizing"),this.triggerEvent("resizestop",t),this._cleanHelper(),delete this.startEvent,delete this.originalRect,delete this.temporalRect,delete this.scrollY,delete this.scrolled,this}_setupHelper(){this.elOriginStyleVal=N._originStyleProp.map((e=>this.el.style[e])),this.parentOriginStylePosition=this.el.parentElement.style.position;const e=this.el.parentElement,t=m.getValuesFromTransformedElement(e);return this.rectScale={x:t.xScale,y:t.yScale},getComputedStyle(this.el.parentElement).position.match(/static/)&&(this.el.parentElement.style.position="relative"),this.el.style.position="absolute",this.el.style.opacity="0.8",this}_cleanHelper(){return N._originStyleProp.forEach(((e,t)=>{this.el.style[e]=this.elOriginStyleVal[t]||null})),this.el.parentElement.style.position=this.parentOriginStylePosition||null,this}_getChange(e,t){const i=this.startEvent,s={width:this.originalRect.width,height:this.originalRect.height+this.scrolled,left:this.originalRect.left,top:this.originalRect.top-this.scrolled},o=e.clientX-i.clientX,n=this.sizeToContent?0:e.clientY-i.clientY;t.indexOf("e")>-1?s.width+=o:t.indexOf("w")>-1&&(s.width-=o,s.left+=o),t.indexOf("s")>-1?s.height+=n:t.indexOf("n")>-1&&(s.height-=n,s.top+=n);const r=this._constrainSize(s.width,s.height);return Math.round(s.width)!==Math.round(r.width)&&(t.indexOf("w")>-1&&(s.left+=s.width-r.width),s.width=r.width),Math.round(s.height)!==Math.round(r.height)&&(t.indexOf("n")>-1&&(s.top+=s.height-r.height),s.height=r.height),s}_constrainSize(e,t){const i=this.option.maxWidth||Number.MAX_SAFE_INTEGER,s=this.option.minWidth/this.rectScale.x||e,o=this.option.maxHeight||Number.MAX_SAFE_INTEGER,n=this.option.minHeight/this.rectScale.y||t;return{width:Math.min(i,Math.max(s,e)),height:Math.min(o,Math.max(n,t))}}_applyChange(){let e={left:0,top:0,width:0,height:0};if("absolute"===this.el.style.position){const t=this.el.parentElement,{left:i,top:s}=t.getBoundingClientRect();e={left:i,top:s,width:0,height:0}}return this.temporalRect?(Object.keys(this.temporalRect).forEach((t=>{const i=this.temporalRect[t],s="width"===t||"left"===t?this.rectScale.x:"height"===t||"top"===t?this.rectScale.y:1;this.el.style[t]=(i-e[t])*s+"px"})),this):this}_removeHandlers(){return this.handlers.forEach((e=>e.destroy())),delete this.handlers,this}}N._originStyleProp=["width","height","position","left","top","opacity","zIndex"];class M extends D{constructor(e,t={}){super(),this.el=e,this.option=t,this.dragTransform={xScale:1,yScale:1,xOffset:0,yOffset:0};let i=t.handle.substring(1);this.dragEl=e.classList.contains(i)?e:e.querySelector(t.handle)||e,this._mouseDown=this._mouseDown.bind(this),this._mouseMove=this._mouseMove.bind(this),this._mouseUp=this._mouseUp.bind(this),this.enable()}on(e,t){super.on(e,t)}off(e){super.off(e)}enable(){!1!==this.disabled&&(super.enable(),this.dragEl.addEventListener("mousedown",this._mouseDown),b&&(this.dragEl.addEventListener("touchstart",C),this.dragEl.addEventListener("pointerdown",R)),this.el.classList.remove("ui-draggable-disabled"))}disable(e=!1){!0!==this.disabled&&(super.disable(),this.dragEl.removeEventListener("mousedown",this._mouseDown),b&&(this.dragEl.removeEventListener("touchstart",C),this.dragEl.removeEventListener("pointerdown",R)),e||this.el.classList.add("ui-draggable-disabled"))}destroy(){this.dragTimeout&&window.clearTimeout(this.dragTimeout),delete this.dragTimeout,this.mouseDownEvent&&this._mouseUp(this.mouseDownEvent),this.disable(!0),delete this.el,delete this.helper,delete this.option,super.destroy()}updateOption(e){return Object.keys(e).forEach((t=>this.option[t]=e[t])),this}_mouseDown(e){if(!_.mouseHandled)return 0!==e.button||e.target.closest('input,textarea,button,select,option,[contenteditable="true"],.ui-resizable-handle')||this.option.cancel&&e.target.closest(this.option.cancel)||(this.mouseDownEvent=e,delete this.dragging,delete _.dragElement,delete _.dropElement,document.addEventListener("mousemove",this._mouseMove,{capture:!0,passive:!0}),document.addEventListener("mouseup",this._mouseUp,!0),b&&(this.dragEl.addEventListener("touchmove",k),this.dragEl.addEventListener("touchend",z)),e.preventDefault(),document.activeElement&&document.activeElement.blur(),_.mouseHandled=!0),!0}_callDrag(e){if(!this.dragging)return;const t=m.initEvent(e,{target:this.el,type:"drag"});this.option.drag&&this.option.drag(t,this.ui()),this.triggerEvent("drag",t)}_mouseMove(e){let t=this.mouseDownEvent;if(this.dragging)if(this._dragFollow(e),_.pauseDrag){const t=Number.isInteger(_.pauseDrag)?_.pauseDrag:100;this.dragTimeout&&window.clearTimeout(this.dragTimeout),this.dragTimeout=window.setTimeout((()=>this._callDrag(e)),t)}else this._callDrag(e);else if(Math.abs(e.x-t.x)+Math.abs(e.y-t.y)>3){this.dragging=!0,_.dragElement=this;let t=this.el.gridstackNode?.grid;t?_.dropElement=t.el.ddElement.ddDroppable:delete _.dropElement,this.helper=this._createHelper(e),this._setupHelperContainmentStyle(),this.dragTransform=m.getValuesFromTransformedElement(this.helperContainment),this.dragOffset=this._getDragOffset(e,this.el,this.helperContainment);const i=m.initEvent(e,{target:this.el,type:"dragstart"});this._setupHelperStyle(e),this.option.start&&this.option.start(i,this.ui()),this.triggerEvent("dragstart",i)}return!0}_mouseUp(e){if(document.removeEventListener("mousemove",this._mouseMove,!0),document.removeEventListener("mouseup",this._mouseUp,!0),b&&(this.dragEl.removeEventListener("touchmove",k,!0),this.dragEl.removeEventListener("touchend",z,!0)),this.dragging){delete this.dragging,_.dropElement?.el===this.el.parentElement&&delete _.dropElement,this.helperContainment.style.position=this.parentOriginStylePosition||null,this.helper===this.el?this._removeHelperStyle():this.helper.remove();const t=m.initEvent(e,{target:this.el,type:"dragstop"});this.option.stop&&this.option.stop(t),this.triggerEvent("dragstop",t),_.dropElement&&_.dropElement.drop(e)}delete this.helper,delete this.mouseDownEvent,delete _.dragElement,delete _.dropElement,delete _.mouseHandled,e.preventDefault()}_createHelper(e){let t=this.el;return"function"==typeof this.option.helper?t=this.option.helper(e):"clone"===this.option.helper&&(t=m.cloneNode(this.el)),document.body.contains(t)||m.appendTo(t,"parent"===this.option.appendTo?this.el.parentElement:this.option.appendTo),t===this.el&&(this.dragElementOriginStyle=M.originStyleProp.map((e=>this.el.style[e]))),t}_setupHelperStyle(e){this.helper.classList.add("ui-draggable-dragging");const t=this.helper.style;return t.pointerEvents="none",t.width=this.dragOffset.width+"px",t.height=this.dragOffset.height+"px",t.willChange="left, top",t.position="fixed",this._dragFollow(e),t.transition="none",setTimeout((()=>{this.helper&&(t.transition=null)}),0),this}_removeHelperStyle(){this.helper.classList.remove("ui-draggable-dragging");let e=this.helper?.gridstackNode;if(!e?._isAboutToRemove&&this.dragElementOriginStyle){let e=this.helper,t=this.dragElementOriginStyle.transition||null;e.style.transition=this.dragElementOriginStyle.transition="none",M.originStyleProp.forEach((t=>e.style[t]=this.dragElementOriginStyle[t]||null)),setTimeout((()=>e.style.transition=t),50)}return delete this.dragElementOriginStyle,this}_dragFollow(e){const t=this.helper.style,i=this.dragOffset;t.left=(e.clientX+i.offsetLeft-0)*this.dragTransform.xScale+"px",t.top=(e.clientY+i.offsetTop-0)*this.dragTransform.yScale+"px"}_setupHelperContainmentStyle(){return this.helperContainment=this.helper.parentElement,"fixed"!==this.helper.style.position&&(this.parentOriginStylePosition=this.helperContainment.style.position,getComputedStyle(this.helperContainment).position.match(/static/)&&(this.helperContainment.style.position="relative")),this}_getDragOffset(e,t,i){let s=0,o=0;i&&(s=this.dragTransform.xOffset,o=this.dragTransform.yOffset);const n=t.getBoundingClientRect();return{left:n.left,top:n.top,offsetLeft:-e.clientX+n.left-s,offsetTop:-e.clientY+n.top-o,width:n.width*this.dragTransform.xScale,height:n.height*this.dragTransform.yScale}}ui(){const e=this.el.parentElement.getBoundingClientRect(),t=this.helper.getBoundingClientRect();return{position:{top:(t.top-e.top)*this.dragTransform.yScale,left:(t.left-e.left)*this.dragTransform.xScale}}}}M.originStyleProp=["transition","pointerEvents","position","left","top","minWidth","willChange"];class L extends D{constructor(e,t={}){super(),this.el=e,this.option=t,this._mouseEnter=this._mouseEnter.bind(this),this._mouseLeave=this._mouseLeave.bind(this),this.enable(),this._setupAccept()}on(e,t){super.on(e,t)}off(e){super.off(e)}enable(){!1!==this.disabled&&(super.enable(),this.el.classList.add("ui-droppable"),this.el.classList.remove("ui-droppable-disabled"),this.el.addEventListener("mouseenter",this._mouseEnter),this.el.addEventListener("mouseleave",this._mouseLeave),b&&(this.el.addEventListener("pointerenter",S),this.el.addEventListener("pointerleave",H)))}disable(e=!1){!0!==this.disabled&&(super.disable(),this.el.classList.remove("ui-droppable"),e||this.el.classList.add("ui-droppable-disabled"),this.el.removeEventListener("mouseenter",this._mouseEnter),this.el.removeEventListener("mouseleave",this._mouseLeave),b&&(this.el.removeEventListener("pointerenter",S),this.el.removeEventListener("pointerleave",H)))}destroy(){this.disable(!0),this.el.classList.remove("ui-droppable"),this.el.classList.remove("ui-droppable-disabled"),super.destroy()}updateOption(e){return Object.keys(e).forEach((t=>this.option[t]=e[t])),this._setupAccept(),this}_mouseEnter(e){if(!_.dragElement)return;if(!this._canDrop(_.dragElement.el))return;e.preventDefault(),e.stopPropagation(),_.dropElement&&_.dropElement!==this&&_.dropElement._mouseLeave(e,!0),_.dropElement=this;const t=m.initEvent(e,{target:this.el,type:"dropover"});this.option.over&&this.option.over(t,this._ui(_.dragElement)),this.triggerEvent("dropover",t),this.el.classList.add("ui-droppable-over")}_mouseLeave(e,t=!1){if(!_.dragElement||_.dropElement!==this)return;e.preventDefault(),e.stopPropagation();const i=m.initEvent(e,{target:this.el,type:"dropout"});if(this.option.out&&this.option.out(i,this._ui(_.dragElement)),this.triggerEvent("dropout",i),_.dropElement===this&&(delete _.dropElement,!t)){let t,i=this.el.parentElement;for(;!t&&i;)t=i.ddElement?.ddDroppable,i=i.parentElement;t&&t._mouseEnter(e)}}drop(e){e.preventDefault();const t=m.initEvent(e,{target:this.el,type:"drop"});this.option.drop&&this.option.drop(t,this._ui(_.dragElement)),this.triggerEvent("drop",t)}_canDrop(e){return e&&(!this.accept||this.accept(e))}_setupAccept(){return this.option.accept?("string"==typeof this.option.accept?this.accept=e=>e.classList.contains(this.option.accept)||e.matches(this.option.accept):this.accept=this.option.accept,this):this}_ui(e){return{draggable:e.el,...e.ui()}}}class A{static init(e){return e.ddElement||(e.ddElement=new A(e)),e.ddElement}constructor(e){this.el=e}on(e,t){return this.ddDraggable&&["drag","dragstart","dragstop"].indexOf(e)>-1?this.ddDraggable.on(e,t):this.ddDroppable&&["drop","dropover","dropout"].indexOf(e)>-1?this.ddDroppable.on(e,t):this.ddResizable&&["resizestart","resize","resizestop"].indexOf(e)>-1&&this.ddResizable.on(e,t),this}off(e){return this.ddDraggable&&["drag","dragstart","dragstop"].indexOf(e)>-1?this.ddDraggable.off(e):this.ddDroppable&&["drop","dropover","dropout"].indexOf(e)>-1?this.ddDroppable.off(e):this.ddResizable&&["resizestart","resize","resizestop"].indexOf(e)>-1&&this.ddResizable.off(e),this}setupDraggable(e){return this.ddDraggable?this.ddDraggable.updateOption(e):this.ddDraggable=new M(this.el,e),this}cleanDraggable(){return this.ddDraggable&&(this.ddDraggable.destroy(),delete this.ddDraggable),this}setupResizable(e){return this.ddResizable?this.ddResizable.updateOption(e):this.ddResizable=new N(this.el,e),this}cleanResizable(){return this.ddResizable&&(this.ddResizable.destroy(),delete this.ddResizable),this}setupDroppable(e){return this.ddDroppable?this.ddDroppable.updateOption(e):this.ddDroppable=new L(this.el,e),this}cleanDroppable(){return this.ddDroppable&&(this.ddDroppable.destroy(),delete this.ddDroppable),this}}const O=new class{resizable(e,t,i,s){return this._getDDElements(e).forEach((e=>{if("disable"===t||"enable"===t)e.ddResizable&&e.ddResizable[t]();else if("destroy"===t)e.ddResizable&&e.cleanResizable();else if("option"===t)e.setupResizable({[i]:s});else{const i=e.el.gridstackNode.grid;let s=e.el.getAttribute("gs-resize-handles")||i.opts.resizable.handles||"e,s,se";"all"===s&&(s="n,e,s,w,se,sw,ne,nw");const o=!i.opts.alwaysShowResizeHandle;e.setupResizable({...i.opts.resizable,handles:s,autoHide:o,start:t.start,stop:t.stop,resize:t.resize})}})),this}draggable(e,t,i,s){return this._getDDElements(e).forEach((e=>{if("disable"===t||"enable"===t)e.ddDraggable&&e.ddDraggable[t]();else if("destroy"===t)e.ddDraggable&&e.cleanDraggable();else if("option"===t)e.setupDraggable({[i]:s});else{const i=e.el.gridstackNode.grid;e.setupDraggable({...i.opts.draggable,start:t.start,stop:t.stop,drag:t.drag})}})),this}dragIn(e,t){return this._getDDElements(e).forEach((e=>e.setupDraggable(t))),this}droppable(e,t,i,s){return"function"!=typeof t.accept||t._accept||(t._accept=t.accept,t.accept=e=>t._accept(e)),this._getDDElements(e).forEach((e=>{"disable"===t||"enable"===t?e.ddDroppable&&e.ddDroppable[t]():"destroy"===t?e.ddDroppable&&e.cleanDroppable():"option"===t?e.setupDroppable({[i]:s}):e.setupDroppable(t)})),this}isDroppable(e){return!(!(e&&e.ddElement&&e.ddElement.ddDroppable)||e.ddElement.ddDroppable.disabled)}isDraggable(e){return!(!(e&&e.ddElement&&e.ddElement.ddDraggable)||e.ddElement.ddDraggable.disabled)}isResizable(e){return!(!(e&&e.ddElement&&e.ddElement.ddResizable)||e.ddElement.ddResizable.disabled)}on(e,t,i){return this._getDDElements(e).forEach((e=>e.on(t,(e=>{i(e,_.dragElement?_.dragElement.el:e.target,_.dragElement?_.dragElement.helper:null)})))),this}off(e,t){return this._getDDElements(e).forEach((e=>e.off(t))),this}_getDDElements(e,t=!0){let i=m.getElements(e);if(!i.length)return[];let s=i.map((e=>e.ddElement||(t?A.init(e):null)));return t||s.filter((e=>e)),s}};class P{static init(e={},t=".grid-stack"){if("undefined"==typeof document)return null;let i=P.getGridElement(t);return i?(i.gridstack||(i.gridstack=new P(i,m.cloneDeep(e))),i.gridstack):("string"==typeof t?console.error('GridStack.initAll() no grid was found with selector "'+t+'" - element missing or wrong selector ?\nNote: ".grid-stack" is required for proper CSS styling and drag/drop, and is the default selector.'):console.error("GridStack.init() no grid element was passed."),null)}static initAll(e={},t=".grid-stack"){let i=[];return"undefined"==typeof document||(P.getGridElements(t).forEach((t=>{t.gridstack||(t.gridstack=new P(t,m.cloneDeep(e))),i.push(t.gridstack)})),0===i.length&&console.error('GridStack.initAll() no grid was found with selector "'+t+'" - element missing or wrong selector ?\nNote: ".grid-stack" is required for proper CSS styling and drag/drop, and is the default selector.')),i}static addGrid(e,t={}){if(!e)return null;let i=e;if(i.gridstack){const e=i.gridstack;return t&&(e.opts={...e.opts,...t}),void 0!==t.children&&e.load(t.children),e}if(!e.classList.contains("grid-stack")||P.addRemoveCB)if(P.addRemoveCB)i=P.addRemoveCB(e,t,!0,!0);else{let s=document.implementation.createHTMLDocument("");s.body.innerHTML=`
`,i=s.body.children[0],e.appendChild(i)}return P.init(t,i)}static registerEngine(e){P.engineClass=e}get placeholder(){if(!this._placeholder){let e=document.createElement("div");e.className="placeholder-content",this.opts.placeholderText&&(e.innerHTML=this.opts.placeholderText),this._placeholder=document.createElement("div"),this._placeholder.classList.add(this.opts.placeholderClass,v.itemClass,this.opts.itemClass),this.placeholder.appendChild(e)}return this._placeholder}constructor(e,t={}){this.el=e,this.opts=t,this._gsEventHandler={},this._extraDragRow=0,this.dragTransform={xScale:1,yScale:1,xOffset:0,yOffset:0},e.gridstack=this,t=t||{},e.classList.contains("grid-stack")||this.el.classList.add("grid-stack"),t.row&&(t.minRow=t.maxRow=t.row,delete t.row);let i=m.toNumber(e.getAttribute("gs-row"));"auto"===t.column&&delete t.column,void 0!==t.alwaysShowResizeHandle&&(t._alwaysShowResizeHandle=t.alwaysShowResizeHandle);let s=t.columnOpts?.breakpoints;const o=t;if(o.oneColumnModeDomSort&&(delete o.oneColumnModeDomSort,console.log("warning: Gridstack oneColumnModeDomSort no longer supported. Use GridStackOptions.columnOpts instead.")),o.oneColumnSize||!1===o.disableOneColumnMode){const e=o.oneColumnSize||768;delete o.oneColumnSize,delete o.disableOneColumnMode,t.columnOpts=t.columnOpts||{},s=t.columnOpts.breakpoints=t.columnOpts.breakpoints||[];let i=s.find((e=>1===e.c));i?i.w=e:(i={c:1,w:e},s.push(i,{c:12,w:e+1}))}const n=t.columnOpts;n&&(n.columnWidth||n.breakpoints?.length?n.columnMax=n.columnMax||12:(delete t.columnOpts,s=void 0)),s?.length>1&&s.sort(((e,t)=>(t.w||0)-(e.w||0)));let r={...m.cloneDeep(v),column:m.toNumber(e.getAttribute("gs-column"))||v.column,minRow:i||m.toNumber(e.getAttribute("gs-min-row"))||v.minRow,maxRow:i||m.toNumber(e.getAttribute("gs-max-row"))||v.maxRow,staticGrid:m.toBool(e.getAttribute("gs-static"))||v.staticGrid,draggable:{handle:(t.handleClass?"."+t.handleClass:t.handle?t.handle:"")||v.draggable.handle},removableOptions:{accept:t.itemClass||v.removableOptions.accept,decline:v.removableOptions.decline}};e.getAttribute("gs-animate")&&(r.animate=m.toBool(e.getAttribute("gs-animate"))),t=m.defaults(t,r),this._initMargin(),this.checkDynamicColumn(),this.el.classList.add("gs-"+t.column),"auto"===t.rtl&&(t.rtl="rtl"===e.style.direction),t.rtl&&this.el.classList.add("grid-stack-rtl");const a=this.el.parentElement?.parentElement;let l=a?.classList.contains(v.itemClass)?a.gridstackNode:void 0;l&&(l.subGrid=this,this.parentGridItem=l,this.el.classList.add("grid-stack-nested"),l.el.classList.add("grid-stack-sub-grid")),this._isAutoCellHeight="auto"===t.cellHeight,this._isAutoCellHeight||"initial"===t.cellHeight?this.cellHeight(void 0,!1):("number"==typeof t.cellHeight&&t.cellHeightUnit&&t.cellHeightUnit!==v.cellHeightUnit&&(t.cellHeight=t.cellHeight+t.cellHeightUnit,delete t.cellHeightUnit),this.cellHeight(t.cellHeight,!1)),"mobile"===t.alwaysShowResizeHandle&&(t.alwaysShowResizeHandle=b),this._styleSheetClass="gs-id-"+f._idSeq++,this.el.classList.add(this._styleSheetClass),this._setStaticClass();let d=t.engineClass||P.engineClass||f;if(this.engine=new d({column:this.getColumn(),float:t.float,maxRow:t.maxRow,onChange:e=>{let t=0;this.engine.nodes.forEach((e=>{t=Math.max(t,e.y+e.h)})),e.forEach((e=>{let t=e.el;t&&(e._removeDOM?(t&&t.remove(),delete e._removeDOM):this._writePosAttr(t,e))})),this._updateStyles(!1,t)}}),this._updateStyles(!1,0),t.auto&&(this.batchUpdate(),this.getGridItems().forEach((e=>this._prepareElement(e))),this.batchUpdate(!1)),t.children){let e=t.children;delete t.children,e.length&&this.load(e)}this.setAnimation(t.animate),t.subGridDynamic&&!_.pauseDrag&&(_.pauseDrag=!0),void 0!==t.draggable?.pause&&(_.pauseDrag=t.draggable.pause),this._setupRemoveDrop(),this._setupAcceptWidget(),this._updateResizeEvent()}addWidget(e,t){let i,s;if("string"==typeof e){let t=document.implementation.createHTMLDocument("");t.body.innerHTML=e,i=t.body.children[0]}else if(0===arguments.length||1===arguments.length&&(void 0!==(o=e).el||void 0!==o.x||void 0!==o.y||void 0!==o.w||void 0!==o.h||void 0!==o.content))if(s=t=e,s?.el)i=s.el;else if(P.addRemoveCB)i=P.addRemoveCB(this.el,t,!0,!1);else{let e=t?.content||"",s=document.implementation.createHTMLDocument("");s.body.innerHTML=`
${e}
`,i=s.body.children[0]}else i=e;var o;if(!i)return;if(s=i.gridstackNode,s&&i.parentElement===this.el&&this.engine.nodes.find((e=>e._id===s._id)))return i;let n=this._readAttr(i);return t=m.cloneDeep(t)||{},m.defaults(t,n),s=this.engine.prepareNode(t),this._writeAttr(i,t),this._insertNotAppend?this.el.prepend(i):this.el.appendChild(i),this.makeWidget(i,t),i}makeSubGrid(e,t,i,s=!0){let o,n=e.gridstackNode;if(n||(n=this.makeWidget(e).gridstackNode),n.subGrid?.el)return n.subGrid;let r,a=this;for(;a&&!o;)o=a.opts?.subGridOpts,a=a.parentGridItem?.grid;t=m.cloneDeep({...o||{},children:void 0,...t||n.subGridOpts||{}}),n.subGridOpts=t,"auto"===t.column&&(r=!0,t.column=Math.max(n.w||1,i?.w||1),delete t.columnOpts);let l,d,h=n.el.querySelector(".grid-stack-item-content");if(s){if(this._removeDD(n.el),d={...n,x:0,y:0},m.removeInternalForSave(d),delete d.subGridOpts,n.content&&(d.content=n.content,delete n.content),P.addRemoveCB)l=P.addRemoveCB(this.el,d,!0,!1);else{let e=document.implementation.createHTMLDocument("");e.body.innerHTML='
',l=e.body.children[0],l.appendChild(h),e.body.innerHTML='
',h=e.body.children[0],n.el.appendChild(h)}this._prepareDragDropByNode(n)}if(i){let e=r?t.column:n.w,s=n.h+i.h,o=n.el.style;o.transition="none",this.update(n.el,{w:e,h:s}),setTimeout((()=>o.transition=null))}let c=n.subGrid=P.addGrid(h,t);return i?._moving&&(c._isTemp=!0),r&&(c._autoColumn=!0),s&&c.addWidget(l,d),i&&(i._moving?window.setTimeout((()=>m.simulateMouseEvent(i._event,"mouseenter",c.el)),0):c.addWidget(n.el,n)),c}removeAsSubGrid(e){let t=this.parentGridItem?.grid;t&&(t.batchUpdate(),t.removeWidget(this.parentGridItem.el,!0,!0),this.engine.nodes.forEach((e=>{e.x+=this.parentGridItem.x,e.y+=this.parentGridItem.y,t.addWidget(e.el,e)})),t.batchUpdate(!1),this.parentGridItem&&delete this.parentGridItem.subGrid,delete this.parentGridItem,e&&window.setTimeout((()=>m.simulateMouseEvent(e._event,"mouseenter",t.el)),0))}save(e=!0,t=!1,i=P.saveCB){let s=this.engine.save(e,i);if(s.forEach((s=>{if(e&&s.el&&!s.subGrid&&!i){let e=s.el.querySelector(".grid-stack-item-content");s.content=e?e.innerHTML:void 0,s.content||delete s.content}else if(e||i||delete s.content,s.subGrid?.el){const o=s.subGrid.save(e,t,i);s.subGridOpts=t?o:{children:o},delete s.subGrid}delete s.el})),t){let e=m.cloneDeep(this.opts);e.marginBottom===e.marginTop&&e.marginRight===e.marginLeft&&e.marginTop===e.marginRight&&(e.margin=e.marginTop,delete e.marginTop,delete e.marginRight,delete e.marginBottom,delete e.marginLeft),e.rtl===("rtl"===this.el.style.direction)&&(e.rtl="auto"),this._isAutoCellHeight&&(e.cellHeight="auto"),this._autoColumn&&(e.column="auto");const t=e._alwaysShowResizeHandle;return delete e._alwaysShowResizeHandle,void 0!==t?e.alwaysShowResizeHandle=t:delete e.alwaysShowResizeHandle,m.removeInternalAndSame(e,v),e.children=s,e}return s}load(e,t=P.addRemoveCB||!0){e=m.cloneDeep(e);const i=this.getColumn();let s=e.filter((e=>(void 0===e.x||void 0===e.y)&&!m.find(this.engine.nodes,e.id)));s.length&&s.length!==e.length?e=e.filter((e=>!m.find(s,e.id))):s=[];const o=e.some((e=>void 0!==e.x||void 0!==e.y));o&&(e=m.sort(e,-1)),this._insertNotAppend=o,e.some((e=>(e.x||0)+(e.w||1)>i))&&(this._ignoreLayoutsNodeChange=!0,this.engine.cacheLayout(e,12,!0));const n=P.addRemoveCB;"function"==typeof t&&(P.addRemoveCB=t);let r=[];this.batchUpdate();const a=!this.engine.nodes.length;a&&this.setAnimation(!1),t&&[...this.engine.nodes].forEach((t=>{t.id&&(m.find(e,t.id)||(P.addRemoveCB&&P.addRemoveCB(this.el,t,!1,!1),r.push(t),this.removeWidget(t.el,!0,!1)))}));let l=[];return this.engine.nodes=this.engine.nodes.filter((t=>!m.find(e,t.id)||(l.push(t),!1))),e.forEach((e=>{let i=m.find(l,e.id);if(i){if(m.shouldSizeToContent(i)&&(e.h=i.h),this.engine.nodeBoundFix(e),(e.autoPosition||void 0===e.x||void 0===e.y)&&(e.w=e.w||i.w,e.h=e.h||i.h,this.engine.findEmptyPosition(e)),this.engine.nodes.push(i),m.samePos(i,e)&&this.moveNode(i,{...e,forceCollide:!0}),this.update(i.el,e),e.subGridOpts?.children){let t=i.el.querySelector(".grid-stack");t&&t.gridstack&&(t.gridstack.load(e.subGridOpts.children),this._insertNotAppend=!0)}}else t&&this.addWidget(e)})),t&&s.forEach((e=>this.addWidget(e))),this.engine.removedNodes=r,this.batchUpdate(!1),delete this._ignoreLayoutsNodeChange,delete this._insertNotAppend,n?P.addRemoveCB=n:delete P.addRemoveCB,a&&this.opts?.animate&&setTimeout((()=>{this.opts&&this.setAnimation(this.opts.animate)})),this}batchUpdate(e=!0){return this.engine.batchUpdate(e),e||(this._updateContainerHeight(),this._triggerRemoveEvent(),this._triggerAddEvent(),this._triggerChangeEvent()),this}getCellHeight(e=!1){if(this.opts.cellHeight&&"auto"!==this.opts.cellHeight&&(!e||!this.opts.cellHeightUnit||"px"===this.opts.cellHeightUnit))return this.opts.cellHeight;if("rem"===this.opts.cellHeightUnit)return this.opts.cellHeight*parseFloat(getComputedStyle(document.documentElement).fontSize);if("em"===this.opts.cellHeightUnit)return this.opts.cellHeight*parseFloat(getComputedStyle(this.el).fontSize);if("cm"===this.opts.cellHeightUnit)return this.opts.cellHeight*(96/2.54);if("mm"===this.opts.cellHeightUnit)return this.opts.cellHeight*(96/2.54)/10;let t=this.el.querySelector("."+this.opts.itemClass);if(t){let e=m.toNumber(t.getAttribute("gs-h"))||1;return Math.round(t.offsetHeight/e)}let i=parseInt(this.el.getAttribute("gs-current-row"));return i?Math.round(this.el.getBoundingClientRect().height/i):this.opts.cellHeight}cellHeight(e,t=!0){if(t&&void 0!==e&&this._isAutoCellHeight!==("auto"===e)&&(this._isAutoCellHeight="auto"===e,this._updateResizeEvent()),"initial"!==e&&"auto"!==e||(e=void 0),void 0===e){let t=-this.opts.marginRight-this.opts.marginLeft+this.opts.marginTop+this.opts.marginBottom;e=this.cellWidth()+t}let i=m.parseHeight(e);return this.opts.cellHeightUnit===i.unit&&this.opts.cellHeight===i.h||(this.opts.cellHeightUnit=i.unit,this.opts.cellHeight=i.h,this.resizeToContentCheck(),t&&this._updateStyles(!0)),this}cellWidth(){return this._widthOrContainer()/this.getColumn()}_widthOrContainer(e=!1){return e&&this.opts.columnOpts?.breakpointForWindow?window.innerWidth:this.el.clientWidth||this.el.parentElement.clientWidth||window.innerWidth}checkDynamicColumn(){const e=this.opts.columnOpts;if(!e||!e.columnWidth&&!e.breakpoints?.length)return!1;const t=this.getColumn();let i=t;const s=this._widthOrContainer(!0);if(e.columnWidth)i=Math.min(Math.round(s/e.columnWidth)||1,e.columnMax);else{i=e.columnMax;let o=0;for(;oe.c===i));return this.column(i,t?.layout||e.layout),!0}return!1}compact(e="compact",t=!0){return this.engine.compact(e,t),this._triggerChangeEvent(),this}column(e,t="moveScale"){if(!e||e<1||this.opts.column===e)return this;let i=this.getColumn();return this.opts.column=e,this.engine?(this.engine.column=e,this.el.classList.remove("gs-"+i),this.el.classList.add("gs-"+e),this.engine.columnChanged(i,e,t),this._isAutoCellHeight&&this.cellHeight(),this.resizeToContentCheck(!0),this._ignoreLayoutsNodeChange=!0,this._triggerChangeEvent(),delete this._ignoreLayoutsNodeChange,this):this}getColumn(){return this.opts.column}getGridItems(){return Array.from(this.el.children).filter((e=>e.matches("."+this.opts.itemClass)&&!e.matches("."+this.opts.placeholderClass)))}destroy(e=!0){if(this.el)return this.offAll(),this._updateResizeEvent(!0),this.setStatic(!0,!1),this.setAnimation(!1),e?this.el.parentNode.removeChild(this.el):(this.removeAll(e),this.el.classList.remove(this._styleSheetClass),this.el.removeAttribute("gs-current-row")),this._removeStylesheet(),this.parentGridItem&&delete this.parentGridItem.subGrid,delete this.parentGridItem,delete this.opts,delete this._placeholder,delete this.engine,delete this.el.gridstack,delete this.el,this}float(e){return this.opts.float!==e&&(this.opts.float=this.engine.float=e,this._triggerChangeEvent()),this}getFloat(){return this.engine.float}getCellFromPixel(e,t=!1){let i,s=this.el.getBoundingClientRect();i=t?{top:s.top+document.documentElement.scrollTop,left:s.left}:{top:this.el.offsetTop,left:this.el.offsetLeft};let o=e.left-i.left,n=e.top-i.top,r=s.width/this.getColumn(),a=s.height/parseInt(this.el.getAttribute("gs-current-row"));return{x:Math.floor(o/r),y:Math.floor(n/a)}}getRow(){return Math.max(this.engine.getRow(),this.opts.minRow)}isAreaEmpty(e,t,i,s){return this.engine.isAreaEmpty(e,t,i,s)}makeWidget(e,t){let i=P.getElement(e);this._prepareElement(i,!0,t);const s=i.gridstackNode;return this._updateContainerHeight(),s.subGridOpts&&this.makeSubGrid(i,s.subGridOpts,void 0,!1),1===this.opts.column&&(this._ignoreLayoutsNodeChange=!0),this._triggerAddEvent(),this._triggerChangeEvent(),delete this._ignoreLayoutsNodeChange,i}on(e,t){if(-1!==e.indexOf(" "))return e.split(" ").forEach((e=>this.on(e,t))),this;if("change"===e||"added"===e||"removed"===e||"enable"===e||"disable"===e){let i="enable"===e||"disable"===e;this._gsEventHandler[e]=i?e=>t(e):e=>t(e,e.detail),this.el.addEventListener(e,this._gsEventHandler[e])}else"drag"===e||"dragstart"===e||"dragstop"===e||"resizestart"===e||"resize"===e||"resizestop"===e||"dropped"===e||"resizecontent"===e?this._gsEventHandler[e]=t:console.error("GridStack.on("+e+") event not supported");return this}off(e){return-1!==e.indexOf(" ")?(e.split(" ").forEach((e=>this.off(e))),this):("change"!==e&&"added"!==e&&"removed"!==e&&"enable"!==e&&"disable"!==e||this._gsEventHandler[e]&&this.el.removeEventListener(e,this._gsEventHandler[e]),delete this._gsEventHandler[e],this)}offAll(){return Object.keys(this._gsEventHandler).forEach((e=>this.off(e))),this}removeWidget(e,t=!0,i=!0){return P.getElements(e).forEach((e=>{if(e.parentElement&&e.parentElement!==this.el)return;let s=e.gridstackNode;s||(s=this.engine.nodes.find((t=>e===t.el))),s&&(t&&P.addRemoveCB&&P.addRemoveCB(this.el,s,!1,!1),delete e.gridstackNode,this._removeDD(e),this.engine.removeNode(s,t,i),t&&e.parentElement&&e.remove())})),i&&(this._triggerRemoveEvent(),this._triggerChangeEvent()),this}removeAll(e=!0,t=!0){return this.engine.nodes.forEach((t=>{e&&P.addRemoveCB&&P.addRemoveCB(this.el,t,!1,!1),delete t.el.gridstackNode,this.opts.staticGrid||this._removeDD(t.el)})),this.engine.removeAll(e,t),t&&this._triggerRemoveEvent(),this}setAnimation(e){return e?this.el.classList.add("grid-stack-animate"):this.el.classList.remove("grid-stack-animate"),this}hasAnimationCSS(){return this.el.classList.contains("grid-stack-animate")}setStatic(e,t=!0,i=!0){return!!this.opts.staticGrid===e||(e?this.opts.staticGrid=!0:delete this.opts.staticGrid,this._setupRemoveDrop(),this._setupAcceptWidget(),this.engine.nodes.forEach((s=>{this._prepareDragDropByNode(s),s.subGrid&&i&&s.subGrid.setStatic(e,t,i)})),t&&this._setStaticClass()),this}update(e,t){if(arguments.length>2){console.warn("gridstack.ts: `update(el, x, y, w, h)` is deprecated. Use `update(el, {x, w, content, ...})`. It will be removed soon");let i=arguments,s=1;return t={x:i[s++],y:i[s++],w:i[s++],h:i[s++]},this.update(e,t)}return P.getElements(e).forEach((e=>{let i=e?.gridstackNode;if(!i)return;let s=m.cloneDeep(t);this.engine.nodeBoundFix(s),delete s.autoPosition,delete s.id;let o,n=["x","y","w","h"];if(n.some((e=>void 0!==s[e]&&s[e]!==i[e]))&&(o={},n.forEach((e=>{o[e]=void 0!==s[e]?s[e]:i[e],delete s[e]}))),!o&&(s.minW||s.minH||s.maxW||s.maxH)&&(o={}),void 0!==s.content){const t=e.querySelector(".grid-stack-item-content");t&&t.innerHTML!==s.content&&(t.innerHTML=s.content,i.subGrid?.el&&(t.appendChild(i.subGrid.el),i.subGrid.opts.styleInHead||i.subGrid._updateStyles(!0))),delete s.content}let r=!1,a=!1;for(const e in s)"_"!==e[0]&&i[e]!==s[e]&&(i[e]=s[e],r=!0,a=a||!this.opts.staticGrid&&("noResize"===e||"noMove"===e||"locked"===e));if(m.sanitizeMinMax(i),o){const e=void 0!==o.w&&o.w!==i.w;this.moveNode(i,o),this.resizeToContentCheck(e,i)}(o||r)&&this._writeAttr(e,i),a&&this._prepareDragDropByNode(i)})),this}moveNode(e,t){this.engine.cleanNodes().beginUpdate(e).moveNode(e,t),this._updateContainerHeight(),this._triggerChangeEvent(),this.engine.endUpdate()}resizeToContent(e){if(!e)return;if(e.classList.remove("size-to-content-max"),!e.clientHeight)return;const t=e.gridstackNode;if(!t)return;const i=t.grid;if(!i||e.parentElement!==i.el)return;const s=i.getCellHeight(!0);if(!s)return;let o,n=t.h?t.h*s:e.clientHeight;if(t.resizeToContentParent&&(o=e.querySelector(t.resizeToContentParent)),o||(o=e.querySelector(P.resizeToContentParent)),!o)return;const r=e.clientHeight-o.clientHeight,a=t.h?t.h*s-r:o.clientHeight;let l;if(t.subGrid)l=t.subGrid.getRow()*t.subGrid.getCellHeight(!0);else{const e=o.firstElementChild;if(!e)return void console.error(`Error: GridStack.resizeToContent() widget id:${t.id} '${P.resizeToContentParent}'.firstElementChild is null, make sure to have a div like container. Skipping sizing.`);l=e.getBoundingClientRect().height||a}if(a===l)return;n+=l-a;let d=Math.ceil(n/s);const h=Number.isInteger(t.sizeToContent)?t.sizeToContent:0;h&&d>h&&(d=h,e.classList.add("size-to-content-max")),t.minH&&dt.maxH&&(d=t.maxH),d!==t.h&&(i._ignoreLayoutsNodeChange=!0,i.moveNode(t,{h:d}),delete i._ignoreLayoutsNodeChange)}resizeToContentCBCheck(e){P.resizeToContentCB?P.resizeToContentCB(e):this.resizeToContent(e)}margin(e){if(!("string"==typeof e&&e.split(" ").length>1)){let t=m.parseHeight(e);if(this.opts.marginUnit===t.unit&&this.opts.margin===t.h)return}return this.opts.margin=e,this.opts.marginTop=this.opts.marginBottom=this.opts.marginLeft=this.opts.marginRight=void 0,this._initMargin(),this._updateStyles(!0),this}getMargin(){return this.opts.margin}willItFit(e){if(arguments.length>1){console.warn("gridstack.ts: `willItFit(x,y,w,h,autoPosition)` is deprecated. Use `willItFit({x, y,...})`. It will be removed soon");let e=arguments,t=0,i={x:e[t++],y:e[t++],w:e[t++],h:e[t++],autoPosition:e[t++]};return this.willItFit(i)}return this.engine.willItFit(e)}_triggerChangeEvent(){if(this.engine.batchMode)return this;let e=this.engine.getDirtyNodes(!0);return e&&e.length&&(this._ignoreLayoutsNodeChange||this.engine.layoutsNodesChange(e),this._triggerEvent("change",e)),this.engine.saveInitial(),this}_triggerAddEvent(){if(this.engine.batchMode)return this;if(this.engine.addedNodes?.length){this._ignoreLayoutsNodeChange||this.engine.layoutsNodesChange(this.engine.addedNodes),this.engine.addedNodes.forEach((e=>{delete e._dirty}));const e=[...this.engine.addedNodes];this.engine.addedNodes=[],this._triggerEvent("added",e)}return this}_triggerRemoveEvent(){if(this.engine.batchMode)return this;if(this.engine.removedNodes?.length){const e=[...this.engine.removedNodes];this.engine.removedNodes=[],this._triggerEvent("removed",e)}return this}_triggerEvent(e,t){let i=t?new CustomEvent(e,{bubbles:!1,detail:t}):new Event(e);return this.el.dispatchEvent(i),this}_removeStylesheet(){if(this._styles){const e=this.opts.styleInHead?void 0:this.el.parentNode;m.removeStylesheet(this._styleSheetClass,e),delete this._styles}return this}_updateStyles(e=!1,t){if(e&&this._removeStylesheet(),void 0===t&&(t=this.getRow()),this._updateContainerHeight(),0===this.opts.cellHeight)return this;let i=this.opts.cellHeight,s=this.opts.cellHeightUnit,o=`.${this._styleSheetClass} > .${this.opts.itemClass}`;if(!this._styles){const e=this.opts.styleInHead?void 0:this.el.parentNode;if(this._styles=m.createStylesheet(this._styleSheetClass,e,{nonce:this.opts.nonce}),!this._styles)return this;this._styles._max=0,m.addCSSRule(this._styles,o,`height: ${i}${s}`);let t=this.opts.marginTop+this.opts.marginUnit,n=this.opts.marginBottom+this.opts.marginUnit,r=this.opts.marginRight+this.opts.marginUnit,a=this.opts.marginLeft+this.opts.marginUnit,l=`${o} > .grid-stack-item-content`,d=`.${this._styleSheetClass} > .grid-stack-placeholder > .placeholder-content`;m.addCSSRule(this._styles,l,`top: ${t}; right: ${r}; bottom: ${n}; left: ${a};`),m.addCSSRule(this._styles,d,`top: ${t}; right: ${r}; bottom: ${n}; left: ${a};`),m.addCSSRule(this._styles,`${o} > .ui-resizable-n`,`top: ${t};`),m.addCSSRule(this._styles,`${o} > .ui-resizable-s`,`bottom: ${n}`),m.addCSSRule(this._styles,`${o} > .ui-resizable-ne`,`right: ${r}`),m.addCSSRule(this._styles,`${o} > .ui-resizable-e`,`right: ${r}`),m.addCSSRule(this._styles,`${o} > .ui-resizable-se`,`right: ${r}; bottom: ${n}`),m.addCSSRule(this._styles,`${o} > .ui-resizable-nw`,`left: ${a}`),m.addCSSRule(this._styles,`${o} > .ui-resizable-w`,`left: ${a}`),m.addCSSRule(this._styles,`${o} > .ui-resizable-sw`,`left: ${a}; bottom: ${n}`)}if((t=t||this._styles._max)>this._styles._max){let e=e=>i*e+s;for(let i=this._styles._max+1;i<=t;i++)m.addCSSRule(this._styles,`${o}[gs-y="${i}"]`,`top: ${e(i)}`),m.addCSSRule(this._styles,`${o}[gs-h="${i+1}"]`,`height: ${e(i+1)}`);this._styles._max=t}return this}_updateContainerHeight(){if(!this.engine||this.engine.batchMode)return this;const e=this.parentGridItem;let t=this.getRow()+this._extraDragRow;const i=this.opts.cellHeight,s=this.opts.cellHeightUnit;if(!i)return this;if(!e){const e=m.parseHeight(getComputedStyle(this.el).minHeight);if(e.h>0&&e.unit===s){const s=Math.floor(e.h/i);t1?e.setAttribute("gs-w",String(t.w)):e.removeAttribute("gs-w"),t.h>1?e.setAttribute("gs-h",String(t.h)):e.removeAttribute("gs-h"),this}_writeAttr(e,t){if(!t)return this;this._writePosAttr(e,t);let i={autoPosition:"gs-auto-position",noResize:"gs-no-resize",noMove:"gs-no-move",locked:"gs-locked",id:"gs-id"};for(const s in i)t[s]?e.setAttribute(i[s],String(t[s])):e.removeAttribute(i[s]);return this}_readAttr(e,t=!0){let i={};i.x=m.toNumber(e.getAttribute("gs-x")),i.y=m.toNumber(e.getAttribute("gs-y")),i.w=m.toNumber(e.getAttribute("gs-w")),i.h=m.toNumber(e.getAttribute("gs-h")),i.autoPosition=m.toBool(e.getAttribute("gs-auto-position")),i.noResize=m.toBool(e.getAttribute("gs-no-resize")),i.noMove=m.toBool(e.getAttribute("gs-no-move")),i.locked=m.toBool(e.getAttribute("gs-locked")),i.id=e.getAttribute("gs-id"),i.maxW=m.toNumber(e.getAttribute("gs-max-w")),i.minW=m.toNumber(e.getAttribute("gs-min-w")),i.maxH=m.toNumber(e.getAttribute("gs-max-h")),i.minH=m.toNumber(e.getAttribute("gs-min-h")),t&&(1===i.w&&e.removeAttribute("gs-w"),1===i.h&&e.removeAttribute("gs-h"),i.maxW&&e.removeAttribute("gs-max-w"),i.minW&&e.removeAttribute("gs-min-w"),i.maxH&&e.removeAttribute("gs-max-h"),i.minH&&e.removeAttribute("gs-min-h"));for(const e in i){if(!i.hasOwnProperty(e))return;i[e]||0===i[e]||delete i[e]}return i}_setStaticClass(){let e=["grid-stack-static"];return this.opts.staticGrid?(this.el.classList.add(...e),this.el.setAttribute("gs-static","true")):(this.el.classList.remove(...e),this.el.removeAttribute("gs-static")),this}onResize(){if(!this.el?.clientWidth)return;if(this.prevWidth===this.el.clientWidth)return;this.prevWidth=this.el.clientWidth,this.batchUpdate();let e=!1;return this._autoColumn&&this.parentGridItem?this.opts.column!==this.parentGridItem.w&&(this.column(this.parentGridItem.w,"none"),e=!0):e=this.checkDynamicColumn(),this._isAutoCellHeight&&this.cellHeight(),this.engine.nodes.forEach((e=>{e.subGrid&&e.subGrid.onResize()})),this._skipInitialResize||this.resizeToContentCheck(e),delete this._skipInitialResize,this.batchUpdate(!1),this}resizeToContentCheck(e=!1,t=void 0){if(this.engine){if(e&&this.hasAnimationCSS())return setTimeout((()=>this.resizeToContentCheck(!1,t)),310);if(t)m.shouldSizeToContent(t)&&this.resizeToContentCBCheck(t.el);else if(this.engine.nodes.some((e=>m.shouldSizeToContent(e)))){const e=[...this.engine.nodes];this.batchUpdate(),e.forEach((e=>{m.shouldSizeToContent(e)&&this.resizeToContentCBCheck(e.el)})),this.batchUpdate(!1)}this._gsEventHandler.resizecontent&&this._gsEventHandler.resizecontent(null,t?[t]:this.engine.nodes)}}_updateResizeEvent(e=!1){const t=!this.parentGridItem&&(this._isAutoCellHeight||this.opts.sizeToContent||this.opts.columnOpts||this.engine.nodes.find((e=>e.sizeToContent)));return e||!t||this.resizeObserver?!e&&t||!this.resizeObserver||(this.resizeObserver.disconnect(),delete this.resizeObserver,delete this._sizeThrottle):(this._sizeThrottle=m.throttle((()=>this.onResize()),this.opts.cellHeightThrottle),this.resizeObserver=new ResizeObserver((()=>this._sizeThrottle())),this.resizeObserver.observe(this.el),this._skipInitialResize=!0),this}static getElement(e=".grid-stack-item"){return m.getElement(e)}static getElements(e=".grid-stack-item"){return m.getElements(e)}static getGridElement(e){return P.getElement(e)}static getGridElements(e){return m.getElements(e)}_initMargin(){let e,t=0,i=[];return"string"==typeof this.opts.margin&&(i=this.opts.margin.split(" ")),2===i.length?(this.opts.marginTop=this.opts.marginBottom=i[0],this.opts.marginLeft=this.opts.marginRight=i[1]):4===i.length?(this.opts.marginTop=i[0],this.opts.marginRight=i[1],this.opts.marginBottom=i[2],this.opts.marginLeft=i[3]):(e=m.parseHeight(this.opts.margin),this.opts.marginUnit=e.unit,t=this.opts.margin=e.h),void 0===this.opts.marginTop?this.opts.marginTop=t:(e=m.parseHeight(this.opts.marginTop),this.opts.marginTop=e.h,delete this.opts.margin),void 0===this.opts.marginBottom?this.opts.marginBottom=t:(e=m.parseHeight(this.opts.marginBottom),this.opts.marginBottom=e.h,delete this.opts.margin),void 0===this.opts.marginRight?this.opts.marginRight=t:(e=m.parseHeight(this.opts.marginRight),this.opts.marginRight=e.h,delete this.opts.margin),void 0===this.opts.marginLeft?this.opts.marginLeft=t:(e=m.parseHeight(this.opts.marginLeft),this.opts.marginLeft=e.h,delete this.opts.margin),this.opts.marginUnit=e.unit,this.opts.marginTop===this.opts.marginBottom&&this.opts.marginLeft===this.opts.marginRight&&this.opts.marginTop===this.opts.marginRight&&(this.opts.margin=this.opts.marginTop),this}static getDD(){return O}static setupDragIn(e,t,i=document){void 0!==t?.pause&&(_.pauseDrag=t.pause),t={...y,...t||{}};let s="string"==typeof e?m.getElements(e,i):e;s.length&&s?.forEach((e=>{O.isDraggable(e)||O.dragIn(e,t)}))}movable(e,t){return this.opts.staticGrid||P.getElements(e).forEach((e=>{const i=e.gridstackNode;i&&(t?delete i.noMove:i.noMove=!0,this._prepareDragDropByNode(i))})),this}resizable(e,t){return this.opts.staticGrid||P.getElements(e).forEach((e=>{let i=e.gridstackNode;i&&(t?delete i.noResize:i.noResize=!0,this._prepareDragDropByNode(i))})),this}disable(e=!0){if(!this.opts.staticGrid)return this.enableMove(!1,e),this.enableResize(!1,e),this._triggerEvent("disable"),this}enable(e=!0){if(!this.opts.staticGrid)return this.enableMove(!0,e),this.enableResize(!0,e),this._triggerEvent("enable"),this}enableMove(e,t=!0){return this.opts.staticGrid||(e?delete this.opts.disableDrag:this.opts.disableDrag=!0,this.engine.nodes.forEach((i=>{this._prepareDragDropByNode(i),i.subGrid&&t&&i.subGrid.enableMove(e,t)}))),this}enableResize(e,t=!0){return this.opts.staticGrid||(e?delete this.opts.disableResize:this.opts.disableResize=!0,this.engine.nodes.forEach((i=>{this._prepareDragDropByNode(i),i.subGrid&&t&&i.subGrid.enableResize(e,t)}))),this}_removeDD(e){return O.draggable(e,"destroy").resizable(e,"destroy"),e.gridstackNode&&delete e.gridstackNode._initDD,delete e.ddElement,this}_setupAcceptWidget(){if(this.opts.staticGrid||!this.opts.acceptWidgets&&!this.opts.removable)return O.droppable(this.el,"destroy"),this;let e,t,i=(i,s,o)=>{let n=s.gridstackNode;if(!n)return;if(o=o||s,!n.grid?.el){o.style.transform=`scale(${1/this.dragTransform.xScale},${1/this.dragTransform.yScale})`;const e=o.getBoundingClientRect();o.style.left=e.x+(this.dragTransform.xScale-1)*(i.clientX-e.x)/this.dragTransform.xScale+"px",o.style.top=e.y+(this.dragTransform.yScale-1)*(i.clientY-e.y)/this.dragTransform.yScale+"px",o.style.transformOrigin="0px 0px"}let r=this.el.getBoundingClientRect(),{top:a,left:l}=o.getBoundingClientRect();l-=r.left,a-=r.top;let d={position:{top:a*this.dragTransform.xScale,left:l*this.dragTransform.yScale}};if(n._temporaryRemoved){if(n.x=Math.max(0,Math.round(l/t)),n.y=Math.max(0,Math.round(a/e)),delete n.autoPosition,this.engine.nodeBoundFix(n),!this.engine.willItFit(n)){if(n.autoPosition=!0,!this.engine.willItFit(n))return void O.off(s,"drag");n._willFitPos&&(m.copyPos(n,n._willFitPos),delete n._willFitPos)}this._onStartMoving(o,i,d,n,t,e)}else this._dragOrResize(o,i,d,n,t,e)};return O.droppable(this.el,{accept:e=>{let t=e.gridstackNode||this._readAttr(e,!1);if(t?.grid===this)return!0;if(!this.opts.acceptWidgets)return!1;let i=!0;if("function"==typeof this.opts.acceptWidgets)i=this.opts.acceptWidgets(e);else{let t=!0===this.opts.acceptWidgets?".grid-stack-item":this.opts.acceptWidgets;i=e.matches(t)}if(i&&t&&this.opts.maxRow){let e={w:t.w,h:t.h,minW:t.minW,minH:t.minH};i=this.engine.willItFit(e)}return i}}).on(this.el,"dropover",((s,o,n)=>{let r=o.gridstackNode;if(r?.grid===this&&!r._temporaryRemoved)return!1;r?.grid&&r.grid!==this&&!r._temporaryRemoved&&r.grid._leave(o,n),t=this.cellWidth(),e=this.getCellHeight(!0),r||(r=this._readAttr(o,!1)),r.grid||(r._isExternal=!0,o.gridstackNode=r),n=n||o;let a=r.w||Math.round(n.offsetWidth/t)||1,l=r.h||Math.round(n.offsetHeight/e)||1;return r.grid&&r.grid!==this?(o._gridstackNodeOrig||(o._gridstackNodeOrig=r),o.gridstackNode=r={...r,w:a,h:l,grid:this},delete r.x,delete r.y,this.engine.cleanupNode(r).nodeBoundFix(r),r._initDD=r._isExternal=r._temporaryRemoved=!0):(r.w=a,r.h=l,r._temporaryRemoved=!0),P._itemRemoving(r.el,!1),O.on(o,"drag",i),i(s,o,n),!1})).on(this.el,"dropout",((e,t,i)=>{let s=t.gridstackNode;return!!s&&(s.grid&&s.grid!==this||(this._leave(t,i),this._isTemp&&this.removeAsSubGrid(s)),!1)})).on(this.el,"drop",((e,t,i)=>{let s=t.gridstackNode;if(s?.grid===this&&!s._isExternal)return!1;const o=!!this.placeholder.parentElement;this.placeholder.remove();const n=o&&this.opts.animate;n&&this.setAnimation(!1);let r=t._gridstackNodeOrig;if(delete t._gridstackNodeOrig,o&&r?.grid&&r.grid!==this){let e=r.grid;e.engine.removeNodeFromLayoutCache(r),e.engine.removedNodes.push(r),e._triggerRemoveEvent()._triggerChangeEvent(),e.parentGridItem&&!e.engine.nodes.length&&e.opts.subGridDynamic&&e.removeAsSubGrid()}if(!s)return!1;if(o&&(this.engine.cleanupNode(s),s.grid=this),delete s.grid._isTemp,O.off(t,"drag"),i!==t?(i.remove(),t.gridstackNode=r,o&&(t=t.cloneNode(!0))):(t.remove(),this._removeDD(t)),!o)return!1;t.gridstackNode=s,s.el=t;let a=s.subGrid?.el?.gridstack;return m.copyPos(s,this._readAttr(this.placeholder)),m.removePositioningStyles(t),this.el.appendChild(t),this._prepareElement(t,!0,s),a&&(a.parentGridItem=s,a.opts.styleInHead||a._updateStyles(!0)),this._updateContainerHeight(),this.engine.addedNodes.push(s),this._triggerAddEvent(),this._triggerChangeEvent(),this.engine.endUpdate(),this._gsEventHandler.dropped&&this._gsEventHandler.dropped({...e,type:"dropped"},r&&r.grid?r:void 0,s),n&&setTimeout((()=>{this.opts&&this.setAnimation(this.opts.animate)})),!1})),this}static _itemRemoving(e,t){const i=e?e.gridstackNode:void 0;i?.grid&&!e.classList.contains(i.grid.opts.removableOptions.decline)&&(t?i._isAboutToRemove=!0:delete i._isAboutToRemove,t?e.classList.add("grid-stack-item-removing"):e.classList.remove("grid-stack-item-removing"))}_setupRemoveDrop(){if("string"!=typeof this.opts.removable)return this;let e=document.querySelector(this.opts.removable);return e?(this.opts.staticGrid||O.isDroppable(e)||O.droppable(e,this.opts.removableOptions).on(e,"dropover",((e,t)=>P._itemRemoving(t,!0))).on(e,"dropout",((e,t)=>P._itemRemoving(t,!1))),this):this}_prepareDragDropByNode(e){let t=e.el;const i=e.noMove||this.opts.disableDrag,s=e.noResize||this.opts.disableResize;if(this.opts.staticGrid||i&&s)return e._initDD&&(this._removeDD(t),delete e._initDD),t.classList.add("ui-draggable-disabled","ui-resizable-disabled"),this;if(!e._initDD){let i,s,o=(o,n)=>{this._gsEventHandler[o.type]&&this._gsEventHandler[o.type](o,o.target),i=this.cellWidth(),s=this.getCellHeight(!0),this._onStartMoving(t,o,n,e,i,s)},n=(o,n)=>{this._dragOrResize(t,o,n,e,i,s)},r=i=>{this.placeholder.remove(),delete e._moving,delete e._event,delete e._lastTried;const s=e.w!==e._orig.w;let o=i.target;if(o.gridstackNode&&o.gridstackNode.grid===this){if(e.el=o,e._isAboutToRemove){let s=t.gridstackNode.grid;s._gsEventHandler[i.type]&&s._gsEventHandler[i.type](i,o),s.engine.nodes.push(e),s.removeWidget(t,!0,!0)}else m.removePositioningStyles(o),e._temporaryRemoved?(m.copyPos(e,e._orig),this._writePosAttr(o,e),this.engine.addNode(e)):this._writePosAttr(o,e),this._gsEventHandler[i.type]&&this._gsEventHandler[i.type](i,o);this._extraDragRow=0,this._updateContainerHeight(),this._triggerChangeEvent(),this.engine.endUpdate(),"resizestop"===i.type&&(Number.isInteger(e.sizeToContent)&&(e.sizeToContent=e.h),this.resizeToContentCheck(s,e))}};O.draggable(t,{start:o,stop:r,drag:n}).resizable(t,{start:o,stop:r,resize:n}),e._initDD=!0}return O.draggable(t,i?"disable":"enable").resizable(t,s?"disable":"enable"),this}_onStartMoving(e,t,i,s,o,n){if(this.engine.cleanNodes().beginUpdate(s),this._writePosAttr(this.placeholder,s),this.el.appendChild(this.placeholder),s.grid?.el)this.dragTransform=m.getValuesFromTransformedElement(e);else if(this.placeholder&&this.placeholder.closest(".grid-stack")){const e=this.placeholder.closest(".grid-stack");this.dragTransform=m.getValuesFromTransformedElement(e)}else this.dragTransform={xScale:1,xOffset:0,yScale:1,yOffset:0};s.el=this.placeholder,s._lastUiPosition=i.position,s._prevYPix=i.position.top,s._moving="dragstart"===t.type,delete s._lastTried,"dropover"===t.type&&s._temporaryRemoved&&(this.engine.addNode(s),s._moving=!0),this.engine.cacheRects(o,n,this.opts.marginTop,this.opts.marginRight,this.opts.marginBottom,this.opts.marginLeft),"resizestart"===t.type&&(O.resizable(e,"option","minWidth",o*(s.minW||1)).resizable(e,"option","minHeight",n*(s.minH||1)),s.maxW&&O.resizable(e,"option","maxWidth",o*s.maxW),s.maxH&&O.resizable(e,"option","maxHeight",n*s.maxH))}_dragOrResize(e,t,i,s,o,n){let r,a={...s._orig},l=this.opts.marginLeft,d=this.opts.marginRight,h=this.opts.marginTop,c=this.opts.marginBottom,g=Math.round(.1*n),u=Math.round(.1*o);if(l=Math.min(l,u),d=Math.min(d,u),h=Math.min(h,g),c=Math.min(c,g),"drag"===t.type){if(s._temporaryRemoved)return;let t=i.position.top-s._prevYPix;s._prevYPix=i.position.top,!1!==this.opts.draggable.scroll&&m.updateScrollPosition(e,i.position,t);let r=i.position.left+(i.position.left>s._lastUiPosition.left?-d:l),g=i.position.top+(i.position.top>s._lastUiPosition.top?-c:h);a.x=Math.round(r/o),a.y=Math.round(g/n);let u=this._extraDragRow;if(this.engine.collide(s,a)){let e=this.getRow(),t=Math.max(0,a.y+s.h-e);this.opts.maxRow&&e+t>this.opts.maxRow&&(t=Math.max(0,this.opts.maxRow-e)),this._extraDragRow=t}else this._extraDragRow=0;if(this._extraDragRow!==u&&this._updateContainerHeight(),s.x===a.x&&s.y===a.y)return}else if("resize"===t.type){if(a.x<0)return;if(m.updateScrollResize(t,e,n),a.w=Math.round((i.size.width-l)/o),a.h=Math.round((i.size.height-h)/n),s.w===a.w&&s.h===a.h)return;if(s._lastTried&&s._lastTried.w===a.w&&s._lastTried.h===a.h)return;let d=i.position.left+l,c=i.position.top+h;a.x=Math.round(d/o),a.y=Math.round(c/n),r=!0}s._event=t,s._lastTried=a;let p={x:i.position.left+l,y:i.position.top+h,w:(i.size?i.size.width:s.w*o)-l-d,h:(i.size?i.size.height:s.h*n)-h-c};if(this.engine.moveNodeCheck(s,{...a,cellWidth:o,cellHeight:n,rect:p,resizing:r})){s._lastUiPosition=i.position,this.engine.cacheRects(o,n,h,d,c,l),delete s._skipDown,r&&s.subGrid&&s.subGrid.onResize(),this._extraDragRow=0,this._updateContainerHeight();let e=t.target;this._writePosAttr(e,s),this._gsEventHandler[t.type]&&this._gsEventHandler[t.type](t,e)}}_leave(e,t){let i=e.gridstackNode;i&&((t=t||e).style.transform="scale(1)",O.off(e,"drag"),i._temporaryRemoved||(i._temporaryRemoved=!0,this.engine.removeNode(i),i.el=i._isExternal&&t?t:e,!0===this.opts.removable&&P._itemRemoving(e,!0),e._gridstackNodeOrig?(e.gridstackNode=e._gridstackNodeOrig,delete e._gridstackNodeOrig):i._isExternal&&(delete i.el,delete e.gridstackNode,this.engine.restoreInitial())))}commit(){return this.batchUpdate(!1).prototype,this}}P.resizeToContentParent=".grid-stack-item-content",P.Utils=m,P.Engine=f,P.GDRev="10.1.2";var G=i(173),B={};function I(e){var t,i=HTMLWidgets.find("#"+e);return void 0!==i&&(t=i.getWidget()),t}B.styleTagTransform=g(),B.setAttributes=l(),B.insert=r().bind(null,"head"),B.domAPI=o(),B.insertStyleElement=h(),t()(G.A,B),G.A&&G.A.locals&&G.A.locals,HTMLWidgets.widget({name:"gridstack",type:"output",factory:function(e,t,i){var s;return{renderValue:function(t){if(e.classList.add("grid-stack"),e.classList.add("grid-stack-edit"),e.style.background=t.bg,e.innerHTML=t.html,(s=P.init(t.options,e)).on("resizestop",(function(e,t){window.dispatchEvent(new Event("resize"))})),HTMLWidgets.shinyMode){var i=$(e);Shiny.bindAll(i)}if(s.on("added",(function(e,t){HTMLWidgets.shinyMode&&t.forEach((function(e){var t=$(e);Shiny.bindAll(t)}))})),HTMLWidgets.shinyMode){var o=s.save(!0,!0);Shiny.setInputValue(e.id+"_layout",o),s.on("added removed change",(function(t,i){o=s.save(!0,!0),Shiny.setInputValue(e.id+"_layout",o)}))}},getWidget:function(){return s},resize:function(e,t){}}}}),HTMLWidgets.shinyMode&&(Shiny.addCustomMessageHandler("gridstackr-add-widget",(function(e){var t=I(e.id);void 0!==t&&t.addWidget(e.data.options)})),Shiny.addCustomMessageHandler("gridstackr-compact",(function(e){var t=I(e.id);void 0!==t&&t.compact(e.data)})),Shiny.addCustomMessageHandler("gridstackr-disable",(function(e){var t=I(e.id);void 0!==t&&t.disable()})),Shiny.addCustomMessageHandler("gridstackr-enable",(function(e){var t=I(e.id);void 0!==t&&t.enable()})),Shiny.addCustomMessageHandler("gridstackr-enable-move",(function(e){var t=I(e.id);void 0!==t&&t.enableMove(e.data.doEnable)})),Shiny.addCustomMessageHandler("gridstackr-enable-resize",(function(e){var t=I(e.id);void 0!==t&&t.enableResize(e.data.doEnable)})),Shiny.addCustomMessageHandler("gridstackr-remove-all",(function(e){var t=I(e.id);void 0!==t&&t.removeAll()})),Shiny.addCustomMessageHandler("gridstackr-remove-widget",(function(e){var t=I(e.id);if(void 0!==t){var i=document.getElementById(e.id).querySelector("div[gs-id='"+e.data.id+"']");t.removeWidget(i)}})))})()})(); \ No newline at end of file +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "./node_modules/css-loader/dist/cjs.js!./node_modules/gridstack/dist/gridstack-extra.min.css": +/*!***************************************************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js!./node_modules/gridstack/dist/gridstack-extra.min.css ***! + \***************************************************************************************************/ +/***/ ((module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../css-loader/dist/runtime/sourceMaps.js */ "./node_modules/css-loader/dist/runtime/sourceMaps.js"); +/* harmony import */ var _css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js"); +/* harmony import */ var _css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__); +// Imports + + +var ___CSS_LOADER_EXPORT___ = _css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default())); +// Module +___CSS_LOADER_EXPORT___.push([module.id, `.gs-2>.grid-stack-item{width:50%}.gs-2>.grid-stack-item[gs-x="1"]{left:50%}.gs-2>.grid-stack-item[gs-w="2"]{width:100%}.gs-3>.grid-stack-item{width:33.333%}.gs-3>.grid-stack-item[gs-x="1"]{left:33.333%}.gs-3>.grid-stack-item[gs-w="2"]{width:66.667%}.gs-3>.grid-stack-item[gs-x="2"]{left:66.667%}.gs-3>.grid-stack-item[gs-w="3"]{width:100%}.gs-4>.grid-stack-item{width:25%}.gs-4>.grid-stack-item[gs-x="1"]{left:25%}.gs-4>.grid-stack-item[gs-w="2"]{width:50%}.gs-4>.grid-stack-item[gs-x="2"]{left:50%}.gs-4>.grid-stack-item[gs-w="3"]{width:75%}.gs-4>.grid-stack-item[gs-x="3"]{left:75%}.gs-4>.grid-stack-item[gs-w="4"]{width:100%}.gs-5>.grid-stack-item{width:20%}.gs-5>.grid-stack-item[gs-x="1"]{left:20%}.gs-5>.grid-stack-item[gs-w="2"]{width:40%}.gs-5>.grid-stack-item[gs-x="2"]{left:40%}.gs-5>.grid-stack-item[gs-w="3"]{width:60%}.gs-5>.grid-stack-item[gs-x="3"]{left:60%}.gs-5>.grid-stack-item[gs-w="4"]{width:80%}.gs-5>.grid-stack-item[gs-x="4"]{left:80%}.gs-5>.grid-stack-item[gs-w="5"]{width:100%}.gs-6>.grid-stack-item{width:16.667%}.gs-6>.grid-stack-item[gs-x="1"]{left:16.667%}.gs-6>.grid-stack-item[gs-w="2"]{width:33.333%}.gs-6>.grid-stack-item[gs-x="2"]{left:33.333%}.gs-6>.grid-stack-item[gs-w="3"]{width:50%}.gs-6>.grid-stack-item[gs-x="3"]{left:50%}.gs-6>.grid-stack-item[gs-w="4"]{width:66.667%}.gs-6>.grid-stack-item[gs-x="4"]{left:66.667%}.gs-6>.grid-stack-item[gs-w="5"]{width:83.333%}.gs-6>.grid-stack-item[gs-x="5"]{left:83.333%}.gs-6>.grid-stack-item[gs-w="6"]{width:100%}.gs-7>.grid-stack-item{width:14.286%}.gs-7>.grid-stack-item[gs-x="1"]{left:14.286%}.gs-7>.grid-stack-item[gs-w="2"]{width:28.571%}.gs-7>.grid-stack-item[gs-x="2"]{left:28.571%}.gs-7>.grid-stack-item[gs-w="3"]{width:42.857%}.gs-7>.grid-stack-item[gs-x="3"]{left:42.857%}.gs-7>.grid-stack-item[gs-w="4"]{width:57.143%}.gs-7>.grid-stack-item[gs-x="4"]{left:57.143%}.gs-7>.grid-stack-item[gs-w="5"]{width:71.429%}.gs-7>.grid-stack-item[gs-x="5"]{left:71.429%}.gs-7>.grid-stack-item[gs-w="6"]{width:85.714%}.gs-7>.grid-stack-item[gs-x="6"]{left:85.714%}.gs-7>.grid-stack-item[gs-w="7"]{width:100%}.gs-8>.grid-stack-item{width:12.5%}.gs-8>.grid-stack-item[gs-x="1"]{left:12.5%}.gs-8>.grid-stack-item[gs-w="2"]{width:25%}.gs-8>.grid-stack-item[gs-x="2"]{left:25%}.gs-8>.grid-stack-item[gs-w="3"]{width:37.5%}.gs-8>.grid-stack-item[gs-x="3"]{left:37.5%}.gs-8>.grid-stack-item[gs-w="4"]{width:50%}.gs-8>.grid-stack-item[gs-x="4"]{left:50%}.gs-8>.grid-stack-item[gs-w="5"]{width:62.5%}.gs-8>.grid-stack-item[gs-x="5"]{left:62.5%}.gs-8>.grid-stack-item[gs-w="6"]{width:75%}.gs-8>.grid-stack-item[gs-x="6"]{left:75%}.gs-8>.grid-stack-item[gs-w="7"]{width:87.5%}.gs-8>.grid-stack-item[gs-x="7"]{left:87.5%}.gs-8>.grid-stack-item[gs-w="8"]{width:100%}.gs-9>.grid-stack-item{width:11.111%}.gs-9>.grid-stack-item[gs-x="1"]{left:11.111%}.gs-9>.grid-stack-item[gs-w="2"]{width:22.222%}.gs-9>.grid-stack-item[gs-x="2"]{left:22.222%}.gs-9>.grid-stack-item[gs-w="3"]{width:33.333%}.gs-9>.grid-stack-item[gs-x="3"]{left:33.333%}.gs-9>.grid-stack-item[gs-w="4"]{width:44.444%}.gs-9>.grid-stack-item[gs-x="4"]{left:44.444%}.gs-9>.grid-stack-item[gs-w="5"]{width:55.556%}.gs-9>.grid-stack-item[gs-x="5"]{left:55.556%}.gs-9>.grid-stack-item[gs-w="6"]{width:66.667%}.gs-9>.grid-stack-item[gs-x="6"]{left:66.667%}.gs-9>.grid-stack-item[gs-w="7"]{width:77.778%}.gs-9>.grid-stack-item[gs-x="7"]{left:77.778%}.gs-9>.grid-stack-item[gs-w="8"]{width:88.889%}.gs-9>.grid-stack-item[gs-x="8"]{left:88.889%}.gs-9>.grid-stack-item[gs-w="9"]{width:100%}.gs-10>.grid-stack-item{width:10%}.gs-10>.grid-stack-item[gs-x="1"]{left:10%}.gs-10>.grid-stack-item[gs-w="2"]{width:20%}.gs-10>.grid-stack-item[gs-x="2"]{left:20%}.gs-10>.grid-stack-item[gs-w="3"]{width:30%}.gs-10>.grid-stack-item[gs-x="3"]{left:30%}.gs-10>.grid-stack-item[gs-w="4"]{width:40%}.gs-10>.grid-stack-item[gs-x="4"]{left:40%}.gs-10>.grid-stack-item[gs-w="5"]{width:50%}.gs-10>.grid-stack-item[gs-x="5"]{left:50%}.gs-10>.grid-stack-item[gs-w="6"]{width:60%}.gs-10>.grid-stack-item[gs-x="6"]{left:60%}.gs-10>.grid-stack-item[gs-w="7"]{width:70%}.gs-10>.grid-stack-item[gs-x="7"]{left:70%}.gs-10>.grid-stack-item[gs-w="8"]{width:80%}.gs-10>.grid-stack-item[gs-x="8"]{left:80%}.gs-10>.grid-stack-item[gs-w="9"]{width:90%}.gs-10>.grid-stack-item[gs-x="9"]{left:90%}.gs-10>.grid-stack-item[gs-w="10"]{width:100%}.gs-11>.grid-stack-item{width:9.091%}.gs-11>.grid-stack-item[gs-x="1"]{left:9.091%}.gs-11>.grid-stack-item[gs-w="2"]{width:18.182%}.gs-11>.grid-stack-item[gs-x="2"]{left:18.182%}.gs-11>.grid-stack-item[gs-w="3"]{width:27.273%}.gs-11>.grid-stack-item[gs-x="3"]{left:27.273%}.gs-11>.grid-stack-item[gs-w="4"]{width:36.364%}.gs-11>.grid-stack-item[gs-x="4"]{left:36.364%}.gs-11>.grid-stack-item[gs-w="5"]{width:45.455%}.gs-11>.grid-stack-item[gs-x="5"]{left:45.455%}.gs-11>.grid-stack-item[gs-w="6"]{width:54.545%}.gs-11>.grid-stack-item[gs-x="6"]{left:54.545%}.gs-11>.grid-stack-item[gs-w="7"]{width:63.636%}.gs-11>.grid-stack-item[gs-x="7"]{left:63.636%}.gs-11>.grid-stack-item[gs-w="8"]{width:72.727%}.gs-11>.grid-stack-item[gs-x="8"]{left:72.727%}.gs-11>.grid-stack-item[gs-w="9"]{width:81.818%}.gs-11>.grid-stack-item[gs-x="9"]{left:81.818%}.gs-11>.grid-stack-item[gs-w="10"]{width:90.909%}.gs-11>.grid-stack-item[gs-x="10"]{left:90.909%}.gs-11>.grid-stack-item[gs-w="11"]{width:100%}`, "",{"version":3,"sources":["webpack://./node_modules/gridstack/dist/gridstack-extra.min.css"],"names":[],"mappings":"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","sourcesContent":[".gs-2>.grid-stack-item{width:50%}.gs-2>.grid-stack-item[gs-x=\"1\"]{left:50%}.gs-2>.grid-stack-item[gs-w=\"2\"]{width:100%}.gs-3>.grid-stack-item{width:33.333%}.gs-3>.grid-stack-item[gs-x=\"1\"]{left:33.333%}.gs-3>.grid-stack-item[gs-w=\"2\"]{width:66.667%}.gs-3>.grid-stack-item[gs-x=\"2\"]{left:66.667%}.gs-3>.grid-stack-item[gs-w=\"3\"]{width:100%}.gs-4>.grid-stack-item{width:25%}.gs-4>.grid-stack-item[gs-x=\"1\"]{left:25%}.gs-4>.grid-stack-item[gs-w=\"2\"]{width:50%}.gs-4>.grid-stack-item[gs-x=\"2\"]{left:50%}.gs-4>.grid-stack-item[gs-w=\"3\"]{width:75%}.gs-4>.grid-stack-item[gs-x=\"3\"]{left:75%}.gs-4>.grid-stack-item[gs-w=\"4\"]{width:100%}.gs-5>.grid-stack-item{width:20%}.gs-5>.grid-stack-item[gs-x=\"1\"]{left:20%}.gs-5>.grid-stack-item[gs-w=\"2\"]{width:40%}.gs-5>.grid-stack-item[gs-x=\"2\"]{left:40%}.gs-5>.grid-stack-item[gs-w=\"3\"]{width:60%}.gs-5>.grid-stack-item[gs-x=\"3\"]{left:60%}.gs-5>.grid-stack-item[gs-w=\"4\"]{width:80%}.gs-5>.grid-stack-item[gs-x=\"4\"]{left:80%}.gs-5>.grid-stack-item[gs-w=\"5\"]{width:100%}.gs-6>.grid-stack-item{width:16.667%}.gs-6>.grid-stack-item[gs-x=\"1\"]{left:16.667%}.gs-6>.grid-stack-item[gs-w=\"2\"]{width:33.333%}.gs-6>.grid-stack-item[gs-x=\"2\"]{left:33.333%}.gs-6>.grid-stack-item[gs-w=\"3\"]{width:50%}.gs-6>.grid-stack-item[gs-x=\"3\"]{left:50%}.gs-6>.grid-stack-item[gs-w=\"4\"]{width:66.667%}.gs-6>.grid-stack-item[gs-x=\"4\"]{left:66.667%}.gs-6>.grid-stack-item[gs-w=\"5\"]{width:83.333%}.gs-6>.grid-stack-item[gs-x=\"5\"]{left:83.333%}.gs-6>.grid-stack-item[gs-w=\"6\"]{width:100%}.gs-7>.grid-stack-item{width:14.286%}.gs-7>.grid-stack-item[gs-x=\"1\"]{left:14.286%}.gs-7>.grid-stack-item[gs-w=\"2\"]{width:28.571%}.gs-7>.grid-stack-item[gs-x=\"2\"]{left:28.571%}.gs-7>.grid-stack-item[gs-w=\"3\"]{width:42.857%}.gs-7>.grid-stack-item[gs-x=\"3\"]{left:42.857%}.gs-7>.grid-stack-item[gs-w=\"4\"]{width:57.143%}.gs-7>.grid-stack-item[gs-x=\"4\"]{left:57.143%}.gs-7>.grid-stack-item[gs-w=\"5\"]{width:71.429%}.gs-7>.grid-stack-item[gs-x=\"5\"]{left:71.429%}.gs-7>.grid-stack-item[gs-w=\"6\"]{width:85.714%}.gs-7>.grid-stack-item[gs-x=\"6\"]{left:85.714%}.gs-7>.grid-stack-item[gs-w=\"7\"]{width:100%}.gs-8>.grid-stack-item{width:12.5%}.gs-8>.grid-stack-item[gs-x=\"1\"]{left:12.5%}.gs-8>.grid-stack-item[gs-w=\"2\"]{width:25%}.gs-8>.grid-stack-item[gs-x=\"2\"]{left:25%}.gs-8>.grid-stack-item[gs-w=\"3\"]{width:37.5%}.gs-8>.grid-stack-item[gs-x=\"3\"]{left:37.5%}.gs-8>.grid-stack-item[gs-w=\"4\"]{width:50%}.gs-8>.grid-stack-item[gs-x=\"4\"]{left:50%}.gs-8>.grid-stack-item[gs-w=\"5\"]{width:62.5%}.gs-8>.grid-stack-item[gs-x=\"5\"]{left:62.5%}.gs-8>.grid-stack-item[gs-w=\"6\"]{width:75%}.gs-8>.grid-stack-item[gs-x=\"6\"]{left:75%}.gs-8>.grid-stack-item[gs-w=\"7\"]{width:87.5%}.gs-8>.grid-stack-item[gs-x=\"7\"]{left:87.5%}.gs-8>.grid-stack-item[gs-w=\"8\"]{width:100%}.gs-9>.grid-stack-item{width:11.111%}.gs-9>.grid-stack-item[gs-x=\"1\"]{left:11.111%}.gs-9>.grid-stack-item[gs-w=\"2\"]{width:22.222%}.gs-9>.grid-stack-item[gs-x=\"2\"]{left:22.222%}.gs-9>.grid-stack-item[gs-w=\"3\"]{width:33.333%}.gs-9>.grid-stack-item[gs-x=\"3\"]{left:33.333%}.gs-9>.grid-stack-item[gs-w=\"4\"]{width:44.444%}.gs-9>.grid-stack-item[gs-x=\"4\"]{left:44.444%}.gs-9>.grid-stack-item[gs-w=\"5\"]{width:55.556%}.gs-9>.grid-stack-item[gs-x=\"5\"]{left:55.556%}.gs-9>.grid-stack-item[gs-w=\"6\"]{width:66.667%}.gs-9>.grid-stack-item[gs-x=\"6\"]{left:66.667%}.gs-9>.grid-stack-item[gs-w=\"7\"]{width:77.778%}.gs-9>.grid-stack-item[gs-x=\"7\"]{left:77.778%}.gs-9>.grid-stack-item[gs-w=\"8\"]{width:88.889%}.gs-9>.grid-stack-item[gs-x=\"8\"]{left:88.889%}.gs-9>.grid-stack-item[gs-w=\"9\"]{width:100%}.gs-10>.grid-stack-item{width:10%}.gs-10>.grid-stack-item[gs-x=\"1\"]{left:10%}.gs-10>.grid-stack-item[gs-w=\"2\"]{width:20%}.gs-10>.grid-stack-item[gs-x=\"2\"]{left:20%}.gs-10>.grid-stack-item[gs-w=\"3\"]{width:30%}.gs-10>.grid-stack-item[gs-x=\"3\"]{left:30%}.gs-10>.grid-stack-item[gs-w=\"4\"]{width:40%}.gs-10>.grid-stack-item[gs-x=\"4\"]{left:40%}.gs-10>.grid-stack-item[gs-w=\"5\"]{width:50%}.gs-10>.grid-stack-item[gs-x=\"5\"]{left:50%}.gs-10>.grid-stack-item[gs-w=\"6\"]{width:60%}.gs-10>.grid-stack-item[gs-x=\"6\"]{left:60%}.gs-10>.grid-stack-item[gs-w=\"7\"]{width:70%}.gs-10>.grid-stack-item[gs-x=\"7\"]{left:70%}.gs-10>.grid-stack-item[gs-w=\"8\"]{width:80%}.gs-10>.grid-stack-item[gs-x=\"8\"]{left:80%}.gs-10>.grid-stack-item[gs-w=\"9\"]{width:90%}.gs-10>.grid-stack-item[gs-x=\"9\"]{left:90%}.gs-10>.grid-stack-item[gs-w=\"10\"]{width:100%}.gs-11>.grid-stack-item{width:9.091%}.gs-11>.grid-stack-item[gs-x=\"1\"]{left:9.091%}.gs-11>.grid-stack-item[gs-w=\"2\"]{width:18.182%}.gs-11>.grid-stack-item[gs-x=\"2\"]{left:18.182%}.gs-11>.grid-stack-item[gs-w=\"3\"]{width:27.273%}.gs-11>.grid-stack-item[gs-x=\"3\"]{left:27.273%}.gs-11>.grid-stack-item[gs-w=\"4\"]{width:36.364%}.gs-11>.grid-stack-item[gs-x=\"4\"]{left:36.364%}.gs-11>.grid-stack-item[gs-w=\"5\"]{width:45.455%}.gs-11>.grid-stack-item[gs-x=\"5\"]{left:45.455%}.gs-11>.grid-stack-item[gs-w=\"6\"]{width:54.545%}.gs-11>.grid-stack-item[gs-x=\"6\"]{left:54.545%}.gs-11>.grid-stack-item[gs-w=\"7\"]{width:63.636%}.gs-11>.grid-stack-item[gs-x=\"7\"]{left:63.636%}.gs-11>.grid-stack-item[gs-w=\"8\"]{width:72.727%}.gs-11>.grid-stack-item[gs-x=\"8\"]{left:72.727%}.gs-11>.grid-stack-item[gs-w=\"9\"]{width:81.818%}.gs-11>.grid-stack-item[gs-x=\"9\"]{left:81.818%}.gs-11>.grid-stack-item[gs-w=\"10\"]{width:90.909%}.gs-11>.grid-stack-item[gs-x=\"10\"]{left:90.909%}.gs-11>.grid-stack-item[gs-w=\"11\"]{width:100%}"],"sourceRoot":""}]); +// Exports +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___); + + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js!./node_modules/gridstack/dist/gridstack.min.css": +/*!*********************************************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js!./node_modules/gridstack/dist/gridstack.min.css ***! + \*********************************************************************************************/ +/***/ ((module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../css-loader/dist/runtime/sourceMaps.js */ "./node_modules/css-loader/dist/runtime/sourceMaps.js"); +/* harmony import */ var _css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js"); +/* harmony import */ var _css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var _css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../css-loader/dist/runtime/getUrl.js */ "./node_modules/css-loader/dist/runtime/getUrl.js"); +/* harmony import */ var _css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2__); +// Imports + + + +var ___CSS_LOADER_URL_IMPORT_0___ = new URL(/* asset import */ __webpack_require__(/*! data:image/svg+xml;utf8, */ "data:image/svg+xml;utf8,"), __webpack_require__.b); +var ___CSS_LOADER_EXPORT___ = _css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default())); +var ___CSS_LOADER_URL_REPLACEMENT_0___ = _css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2___default()(___CSS_LOADER_URL_IMPORT_0___); +// Module +___CSS_LOADER_EXPORT___.push([module.id, `.grid-stack{position:relative}.grid-stack-rtl{direction:ltr}.grid-stack-rtl>.grid-stack-item{direction:rtl}.grid-stack-placeholder>.placeholder-content{background-color:rgba(0,0,0,.1);margin:0;position:absolute;width:auto;z-index:0!important}.grid-stack>.grid-stack-item{position:absolute;padding:0}.grid-stack>.grid-stack-item>.grid-stack-item-content{margin:0;position:absolute;width:auto;overflow-x:hidden;overflow-y:auto}.grid-stack>.grid-stack-item.size-to-content:not(.size-to-content-max)>.grid-stack-item-content{overflow-y:hidden}.grid-stack-item>.ui-resizable-handle{position:absolute;font-size:.1px;display:block;-ms-touch-action:none;touch-action:none}.grid-stack-item.ui-resizable-autohide>.ui-resizable-handle,.grid-stack-item.ui-resizable-disabled>.ui-resizable-handle{display:none}.grid-stack-item>.ui-resizable-ne,.grid-stack-item>.ui-resizable-nw,.grid-stack-item>.ui-resizable-se,.grid-stack-item>.ui-resizable-sw{background-image:url(${___CSS_LOADER_URL_REPLACEMENT_0___});background-repeat:no-repeat;background-position:center}.grid-stack-item>.ui-resizable-ne{transform:translate(0,10px) rotate(45deg)}.grid-stack-item>.ui-resizable-sw{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-nw{transform:translate(0,10px) rotate(-45deg)}.grid-stack-item>.ui-resizable-se{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-nw{cursor:nw-resize;width:20px;height:20px;top:0}.grid-stack-item>.ui-resizable-n{cursor:n-resize;height:10px;top:0;left:25px;right:25px}.grid-stack-item>.ui-resizable-ne{cursor:ne-resize;width:20px;height:20px;top:0}.grid-stack-item>.ui-resizable-e{cursor:e-resize;width:10px;top:15px;bottom:15px}.grid-stack-item>.ui-resizable-se{cursor:se-resize;width:20px;height:20px}.grid-stack-item>.ui-resizable-s{cursor:s-resize;height:10px;left:25px;bottom:0;right:25px}.grid-stack-item>.ui-resizable-sw{cursor:sw-resize;width:20px;height:20px}.grid-stack-item>.ui-resizable-w{cursor:w-resize;width:10px;top:15px;bottom:15px}.grid-stack-item.ui-draggable-dragging>.ui-resizable-handle{display:none!important}.grid-stack-item.ui-draggable-dragging{will-change:left,top;cursor:move}.grid-stack-item.ui-resizable-resizing{will-change:width,height}.ui-draggable-dragging,.ui-resizable-resizing{z-index:10000}.ui-draggable-dragging>.grid-stack-item-content,.ui-resizable-resizing>.grid-stack-item-content{box-shadow:1px 4px 6px rgba(0,0,0,.2);opacity:.8}.grid-stack-animate,.grid-stack-animate .grid-stack-item{transition:left .3s,top .3s,height .3s,width .3s}.grid-stack-animate .grid-stack-item.grid-stack-placeholder,.grid-stack-animate .grid-stack-item.ui-draggable-dragging,.grid-stack-animate .grid-stack-item.ui-resizable-resizing{transition:left 0s,top 0s,height 0s,width 0s}.grid-stack>.grid-stack-item[gs-y="0"]{top:0}.grid-stack>.grid-stack-item[gs-x="0"]{left:0}.gs-12>.grid-stack-item{width:8.333%}.gs-12>.grid-stack-item[gs-x="1"]{left:8.333%}.gs-12>.grid-stack-item[gs-w="2"]{width:16.667%}.gs-12>.grid-stack-item[gs-x="2"]{left:16.667%}.gs-12>.grid-stack-item[gs-w="3"]{width:25%}.gs-12>.grid-stack-item[gs-x="3"]{left:25%}.gs-12>.grid-stack-item[gs-w="4"]{width:33.333%}.gs-12>.grid-stack-item[gs-x="4"]{left:33.333%}.gs-12>.grid-stack-item[gs-w="5"]{width:41.667%}.gs-12>.grid-stack-item[gs-x="5"]{left:41.667%}.gs-12>.grid-stack-item[gs-w="6"]{width:50%}.gs-12>.grid-stack-item[gs-x="6"]{left:50%}.gs-12>.grid-stack-item[gs-w="7"]{width:58.333%}.gs-12>.grid-stack-item[gs-x="7"]{left:58.333%}.gs-12>.grid-stack-item[gs-w="8"]{width:66.667%}.gs-12>.grid-stack-item[gs-x="8"]{left:66.667%}.gs-12>.grid-stack-item[gs-w="9"]{width:75%}.gs-12>.grid-stack-item[gs-x="9"]{left:75%}.gs-12>.grid-stack-item[gs-w="10"]{width:83.333%}.gs-12>.grid-stack-item[gs-x="10"]{left:83.333%}.gs-12>.grid-stack-item[gs-w="11"]{width:91.667%}.gs-12>.grid-stack-item[gs-x="11"]{left:91.667%}.gs-12>.grid-stack-item[gs-w="12"]{width:100%}.gs-1>.grid-stack-item{width:100%}`, "",{"version":3,"sources":["webpack://./node_modules/gridstack/dist/gridstack.min.css"],"names":[],"mappings":"AAAA,YAAY,iBAAiB,CAAC,gBAAgB,aAAa,CAAC,iCAAiC,aAAa,CAAC,6CAA6C,+BAA+B,CAAC,QAAQ,CAAC,iBAAiB,CAAC,UAAU,CAAC,mBAAmB,CAAC,6BAA6B,iBAAiB,CAAC,SAAS,CAAC,sDAAsD,QAAQ,CAAC,iBAAiB,CAAC,UAAU,CAAC,iBAAiB,CAAC,eAAe,CAAC,gGAAgG,iBAAiB,CAAC,sCAAsC,iBAAiB,CAAC,cAAc,CAAC,aAAa,CAAC,qBAAqB,CAAC,iBAAiB,CAAC,wHAAwH,YAAY,CAAC,wIAAwI,wDAAwP,CAAC,2BAA2B,CAAC,0BAA0B,CAAC,kCAAkC,yCAAyC,CAAC,kCAAkC,uBAAuB,CAAC,kCAAkC,0CAA0C,CAAC,kCAAkC,wBAAwB,CAAC,kCAAkC,gBAAgB,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,iCAAiC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,kCAAkC,gBAAgB,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,iCAAiC,eAAe,CAAC,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,kCAAkC,gBAAgB,CAAC,UAAU,CAAC,WAAW,CAAC,iCAAiC,eAAe,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,kCAAkC,gBAAgB,CAAC,UAAU,CAAC,WAAW,CAAC,iCAAiC,eAAe,CAAC,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,4DAA4D,sBAAsB,CAAC,uCAAuC,oBAAoB,CAAC,WAAW,CAAC,uCAAuC,wBAAwB,CAAC,8CAA8C,aAAa,CAAC,gGAAgG,qCAAqC,CAAC,UAAU,CAAC,yDAAyD,gDAAgD,CAAC,kLAAkL,4CAA4C,CAAC,uCAAuC,KAAK,CAAC,uCAAuC,MAAM,CAAC,wBAAwB,YAAY,CAAC,kCAAkC,WAAW,CAAC,kCAAkC,aAAa,CAAC,kCAAkC,YAAY,CAAC,kCAAkC,SAAS,CAAC,kCAAkC,QAAQ,CAAC,kCAAkC,aAAa,CAAC,kCAAkC,YAAY,CAAC,kCAAkC,aAAa,CAAC,kCAAkC,YAAY,CAAC,kCAAkC,SAAS,CAAC,kCAAkC,QAAQ,CAAC,kCAAkC,aAAa,CAAC,kCAAkC,YAAY,CAAC,kCAAkC,aAAa,CAAC,kCAAkC,YAAY,CAAC,kCAAkC,SAAS,CAAC,kCAAkC,QAAQ,CAAC,mCAAmC,aAAa,CAAC,mCAAmC,YAAY,CAAC,mCAAmC,aAAa,CAAC,mCAAmC,YAAY,CAAC,mCAAmC,UAAU,CAAC,uBAAuB,UAAU","sourcesContent":[".grid-stack{position:relative}.grid-stack-rtl{direction:ltr}.grid-stack-rtl>.grid-stack-item{direction:rtl}.grid-stack-placeholder>.placeholder-content{background-color:rgba(0,0,0,.1);margin:0;position:absolute;width:auto;z-index:0!important}.grid-stack>.grid-stack-item{position:absolute;padding:0}.grid-stack>.grid-stack-item>.grid-stack-item-content{margin:0;position:absolute;width:auto;overflow-x:hidden;overflow-y:auto}.grid-stack>.grid-stack-item.size-to-content:not(.size-to-content-max)>.grid-stack-item-content{overflow-y:hidden}.grid-stack-item>.ui-resizable-handle{position:absolute;font-size:.1px;display:block;-ms-touch-action:none;touch-action:none}.grid-stack-item.ui-resizable-autohide>.ui-resizable-handle,.grid-stack-item.ui-resizable-disabled>.ui-resizable-handle{display:none}.grid-stack-item>.ui-resizable-ne,.grid-stack-item>.ui-resizable-nw,.grid-stack-item>.ui-resizable-se,.grid-stack-item>.ui-resizable-sw{background-image:url('data:image/svg+xml;utf8,');background-repeat:no-repeat;background-position:center}.grid-stack-item>.ui-resizable-ne{transform:translate(0,10px) rotate(45deg)}.grid-stack-item>.ui-resizable-sw{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-nw{transform:translate(0,10px) rotate(-45deg)}.grid-stack-item>.ui-resizable-se{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-nw{cursor:nw-resize;width:20px;height:20px;top:0}.grid-stack-item>.ui-resizable-n{cursor:n-resize;height:10px;top:0;left:25px;right:25px}.grid-stack-item>.ui-resizable-ne{cursor:ne-resize;width:20px;height:20px;top:0}.grid-stack-item>.ui-resizable-e{cursor:e-resize;width:10px;top:15px;bottom:15px}.grid-stack-item>.ui-resizable-se{cursor:se-resize;width:20px;height:20px}.grid-stack-item>.ui-resizable-s{cursor:s-resize;height:10px;left:25px;bottom:0;right:25px}.grid-stack-item>.ui-resizable-sw{cursor:sw-resize;width:20px;height:20px}.grid-stack-item>.ui-resizable-w{cursor:w-resize;width:10px;top:15px;bottom:15px}.grid-stack-item.ui-draggable-dragging>.ui-resizable-handle{display:none!important}.grid-stack-item.ui-draggable-dragging{will-change:left,top;cursor:move}.grid-stack-item.ui-resizable-resizing{will-change:width,height}.ui-draggable-dragging,.ui-resizable-resizing{z-index:10000}.ui-draggable-dragging>.grid-stack-item-content,.ui-resizable-resizing>.grid-stack-item-content{box-shadow:1px 4px 6px rgba(0,0,0,.2);opacity:.8}.grid-stack-animate,.grid-stack-animate .grid-stack-item{transition:left .3s,top .3s,height .3s,width .3s}.grid-stack-animate .grid-stack-item.grid-stack-placeholder,.grid-stack-animate .grid-stack-item.ui-draggable-dragging,.grid-stack-animate .grid-stack-item.ui-resizable-resizing{transition:left 0s,top 0s,height 0s,width 0s}.grid-stack>.grid-stack-item[gs-y=\"0\"]{top:0}.grid-stack>.grid-stack-item[gs-x=\"0\"]{left:0}.gs-12>.grid-stack-item{width:8.333%}.gs-12>.grid-stack-item[gs-x=\"1\"]{left:8.333%}.gs-12>.grid-stack-item[gs-w=\"2\"]{width:16.667%}.gs-12>.grid-stack-item[gs-x=\"2\"]{left:16.667%}.gs-12>.grid-stack-item[gs-w=\"3\"]{width:25%}.gs-12>.grid-stack-item[gs-x=\"3\"]{left:25%}.gs-12>.grid-stack-item[gs-w=\"4\"]{width:33.333%}.gs-12>.grid-stack-item[gs-x=\"4\"]{left:33.333%}.gs-12>.grid-stack-item[gs-w=\"5\"]{width:41.667%}.gs-12>.grid-stack-item[gs-x=\"5\"]{left:41.667%}.gs-12>.grid-stack-item[gs-w=\"6\"]{width:50%}.gs-12>.grid-stack-item[gs-x=\"6\"]{left:50%}.gs-12>.grid-stack-item[gs-w=\"7\"]{width:58.333%}.gs-12>.grid-stack-item[gs-x=\"7\"]{left:58.333%}.gs-12>.grid-stack-item[gs-w=\"8\"]{width:66.667%}.gs-12>.grid-stack-item[gs-x=\"8\"]{left:66.667%}.gs-12>.grid-stack-item[gs-w=\"9\"]{width:75%}.gs-12>.grid-stack-item[gs-x=\"9\"]{left:75%}.gs-12>.grid-stack-item[gs-w=\"10\"]{width:83.333%}.gs-12>.grid-stack-item[gs-x=\"10\"]{left:83.333%}.gs-12>.grid-stack-item[gs-w=\"11\"]{width:91.667%}.gs-12>.grid-stack-item[gs-x=\"11\"]{left:91.667%}.gs-12>.grid-stack-item[gs-w=\"12\"]{width:100%}.gs-1>.grid-stack-item{width:100%}"],"sourceRoot":""}]); +// Exports +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___); + + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js!./srcjs/css/custom.css": +/*!********************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js!./srcjs/css/custom.css ***! + \********************************************************************/ +/***/ ((module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/sourceMaps.js */ "./node_modules/css-loader/dist/runtime/sourceMaps.js"); +/* harmony import */ var _node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js"); +/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__); +// Imports + + +var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default())); +// Module +___CSS_LOADER_EXPORT___.push([module.id, ` +.grid-stack-edit { + padding: 0.25rem; + border-width: 1px; + border-radius: 0.5rem; +} + +.gs-item-example { + border-radius: 8px; + border: 1px solid red; + background: #FFF; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-weight: bold; +} + +.gs-trash { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; +} +`, "",{"version":3,"sources":["webpack://./srcjs/css/custom.css"],"names":[],"mappings":";AACA;EACE,gBAAgB;EAChB,iBAAiB;EACjB,qBAAqB;AACvB;;AAEA;EACE,kBAAkB;EAClB,qBAAqB;EACrB,gBAAgB;EAChB,eAAe;EACf,aAAa;EACb,mBAAmB;EACnB,uBAAuB;EACvB,iBAAiB;AACnB;;AAEA;EACE,aAAa;EACb,mBAAmB;EACnB,uBAAuB;EACvB,sBAAsB;AACxB","sourcesContent":["\n.grid-stack-edit {\n padding: 0.25rem;\n border-width: 1px;\n border-radius: 0.5rem;\n}\n\n.gs-item-example {\n border-radius: 8px;\n border: 1px solid red;\n background: #FFF;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: bold;\n}\n\n.gs-trash {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n}\n"],"sourceRoot":""}]); +// Exports +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___); + + +/***/ }), + +/***/ "./node_modules/css-loader/dist/runtime/api.js": +/*!*****************************************************!*\ + !*** ./node_modules/css-loader/dist/runtime/api.js ***! + \*****************************************************/ +/***/ ((module) => { + + + +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +module.exports = function (cssWithMappingToString) { + var list = []; + + // return the list of modules as css string + list.toString = function toString() { + return this.map(function (item) { + var content = ""; + var needLayer = typeof item[5] !== "undefined"; + if (item[4]) { + content += "@supports (".concat(item[4], ") {"); + } + if (item[2]) { + content += "@media ".concat(item[2], " {"); + } + if (needLayer) { + content += "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {"); + } + content += cssWithMappingToString(item); + if (needLayer) { + content += "}"; + } + if (item[2]) { + content += "}"; + } + if (item[4]) { + content += "}"; + } + return content; + }).join(""); + }; + + // import a list of modules into the list + list.i = function i(modules, media, dedupe, supports, layer) { + if (typeof modules === "string") { + modules = [[null, modules, undefined]]; + } + var alreadyImportedModules = {}; + if (dedupe) { + for (var k = 0; k < this.length; k++) { + var id = this[k][0]; + if (id != null) { + alreadyImportedModules[id] = true; + } + } + } + for (var _k = 0; _k < modules.length; _k++) { + var item = [].concat(modules[_k]); + if (dedupe && alreadyImportedModules[item[0]]) { + continue; + } + if (typeof layer !== "undefined") { + if (typeof item[5] === "undefined") { + item[5] = layer; + } else { + item[1] = "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {").concat(item[1], "}"); + item[5] = layer; + } + } + if (media) { + if (!item[2]) { + item[2] = media; + } else { + item[1] = "@media ".concat(item[2], " {").concat(item[1], "}"); + item[2] = media; + } + } + if (supports) { + if (!item[4]) { + item[4] = "".concat(supports); + } else { + item[1] = "@supports (".concat(item[4], ") {").concat(item[1], "}"); + item[4] = supports; + } + } + list.push(item); + } + }; + return list; +}; + +/***/ }), + +/***/ "./node_modules/css-loader/dist/runtime/getUrl.js": +/*!********************************************************!*\ + !*** ./node_modules/css-loader/dist/runtime/getUrl.js ***! + \********************************************************/ +/***/ ((module) => { + + + +module.exports = function (url, options) { + if (!options) { + options = {}; + } + if (!url) { + return url; + } + url = String(url.__esModule ? url.default : url); + + // If url is already wrapped in quotes, remove them + if (/^['"].*['"]$/.test(url)) { + url = url.slice(1, -1); + } + if (options.hash) { + url += options.hash; + } + + // Should url be wrapped? + // See https://drafts.csswg.org/css-values-3/#urls + if (/["'() \t\n]|(%20)/.test(url) || options.needQuotes) { + return "\"".concat(url.replace(/"/g, '\\"').replace(/\n/g, "\\n"), "\""); + } + return url; +}; + +/***/ }), + +/***/ "./node_modules/css-loader/dist/runtime/sourceMaps.js": +/*!************************************************************!*\ + !*** ./node_modules/css-loader/dist/runtime/sourceMaps.js ***! + \************************************************************/ +/***/ ((module) => { + + + +module.exports = function (item) { + var content = item[1]; + var cssMapping = item[3]; + if (!cssMapping) { + return content; + } + if (typeof btoa === "function") { + var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(cssMapping)))); + var data = "sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(base64); + var sourceMapping = "/*# ".concat(data, " */"); + return [content].concat([sourceMapping]).join("\n"); + } + return [content].join("\n"); +}; + +/***/ }), + +/***/ "./node_modules/gridstack/dist/dd-base-impl.js": +/*!*****************************************************!*\ + !*** ./node_modules/gridstack/dist/dd-base-impl.js ***! + \*****************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ DDBaseImplement: () => (/* binding */ DDBaseImplement) +/* harmony export */ }); +/** + * dd-base-impl.ts 10.1.2 + * Copyright (c) 2021-2022 Alain Dumesny - see GridStack root license + */ +class DDBaseImplement { + constructor() { + /** @internal */ + this._eventRegister = {}; + } + /** returns the enable state, but you have to call enable()/disable() to change (as other things need to happen) */ + get disabled() { return this._disabled; } + on(event, callback) { + this._eventRegister[event] = callback; + } + off(event) { + delete this._eventRegister[event]; + } + enable() { + this._disabled = false; + } + disable() { + this._disabled = true; + } + destroy() { + delete this._eventRegister; + } + triggerEvent(eventName, event) { + if (!this.disabled && this._eventRegister && this._eventRegister[eventName]) + return this._eventRegister[eventName](event); + } +} +//# sourceMappingURL=dd-base-impl.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/dd-draggable.js": +/*!*****************************************************!*\ + !*** ./node_modules/gridstack/dist/dd-draggable.js ***! + \*****************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ DDDraggable: () => (/* binding */ DDDraggable) +/* harmony export */ }); +/* harmony import */ var _dd_manager__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./dd-manager */ "./node_modules/gridstack/dist/dd-manager.js"); +/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils */ "./node_modules/gridstack/dist/utils.js"); +/* harmony import */ var _dd_base_impl__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./dd-base-impl */ "./node_modules/gridstack/dist/dd-base-impl.js"); +/* harmony import */ var _dd_touch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./dd-touch */ "./node_modules/gridstack/dist/dd-touch.js"); +/** + * dd-draggable.ts 10.1.2 + * Copyright (c) 2021-2022 Alain Dumesny - see GridStack root license + */ + + + + +// make sure we are not clicking on known object that handles mouseDown +const skipMouseDown = 'input,textarea,button,select,option,[contenteditable="true"],.ui-resizable-handle'; +// let count = 0; // TEST +class DDDraggable extends _dd_base_impl__WEBPACK_IMPORTED_MODULE_2__.DDBaseImplement { + constructor(el, option = {}) { + super(); + this.el = el; + this.option = option; + /** @internal */ + this.dragTransform = { + xScale: 1, + yScale: 1, + xOffset: 0, + yOffset: 0 + }; + // get the element that is actually supposed to be dragged by + let handleName = option.handle.substring(1); + this.dragEl = el.classList.contains(handleName) ? el : el.querySelector(option.handle) || el; + // create var event binding so we can easily remove and still look like TS methods (unlike anonymous functions) + this._mouseDown = this._mouseDown.bind(this); + this._mouseMove = this._mouseMove.bind(this); + this._mouseUp = this._mouseUp.bind(this); + this.enable(); + } + on(event, callback) { + super.on(event, callback); + } + off(event) { + super.off(event); + } + enable() { + if (this.disabled === false) + return; + super.enable(); + this.dragEl.addEventListener('mousedown', this._mouseDown); + if (_dd_touch__WEBPACK_IMPORTED_MODULE_3__.isTouch) { + this.dragEl.addEventListener('touchstart', _dd_touch__WEBPACK_IMPORTED_MODULE_3__.touchstart); + this.dragEl.addEventListener('pointerdown', _dd_touch__WEBPACK_IMPORTED_MODULE_3__.pointerdown); + // this.dragEl.style.touchAction = 'none'; // not needed unlike pointerdown doc comment + } + this.el.classList.remove('ui-draggable-disabled'); + } + disable(forDestroy = false) { + if (this.disabled === true) + return; + super.disable(); + this.dragEl.removeEventListener('mousedown', this._mouseDown); + if (_dd_touch__WEBPACK_IMPORTED_MODULE_3__.isTouch) { + this.dragEl.removeEventListener('touchstart', _dd_touch__WEBPACK_IMPORTED_MODULE_3__.touchstart); + this.dragEl.removeEventListener('pointerdown', _dd_touch__WEBPACK_IMPORTED_MODULE_3__.pointerdown); + } + if (!forDestroy) + this.el.classList.add('ui-draggable-disabled'); + } + destroy() { + if (this.dragTimeout) + window.clearTimeout(this.dragTimeout); + delete this.dragTimeout; + if (this.mouseDownEvent) + this._mouseUp(this.mouseDownEvent); + this.disable(true); + delete this.el; + delete this.helper; + delete this.option; + super.destroy(); + } + updateOption(opts) { + Object.keys(opts).forEach(key => this.option[key] = opts[key]); + return this; + } + /** @internal call when mouse goes down before a dragstart happens */ + _mouseDown(e) { + // don't let more than one widget handle mouseStart + if (_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.mouseHandled) + return; + if (e.button !== 0) + return true; // only left click + // make sure we are not clicking on known object that handles mouseDown, or ones supplied by the user + if (e.target.closest(skipMouseDown)) + return true; + if (this.option.cancel) { + if (e.target.closest(this.option.cancel)) + return true; + } + // REMOVE: why would we get the event if it wasn't for us or child ? + // make sure we are clicking on a drag handle or child of it... + // Note: we don't need to check that's handle is an immediate child, as mouseHandled will prevent parents from also handling it (lowest wins) + // let className = this.option.handle.substring(1); + // let el = e.target as HTMLElement; + // while (el && !el.classList.contains(className)) { el = el.parentElement; } + // if (!el) return; + this.mouseDownEvent = e; + delete this.dragging; + delete _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dragElement; + delete _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement; + // document handler so we can continue receiving moves as the item is 'fixed' position, and capture=true so WE get a first crack + document.addEventListener('mousemove', this._mouseMove, { capture: true, passive: true }); // true=capture, not bubble + document.addEventListener('mouseup', this._mouseUp, true); + if (_dd_touch__WEBPACK_IMPORTED_MODULE_3__.isTouch) { + this.dragEl.addEventListener('touchmove', _dd_touch__WEBPACK_IMPORTED_MODULE_3__.touchmove); + this.dragEl.addEventListener('touchend', _dd_touch__WEBPACK_IMPORTED_MODULE_3__.touchend); + } + e.preventDefault(); + // preventDefault() prevents blur event which occurs just after mousedown event. + // if an editable content has focus, then blur must be call + if (document.activeElement) + document.activeElement.blur(); + _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.mouseHandled = true; + return true; + } + /** @internal method to call actual drag event */ + _callDrag(e) { + if (!this.dragging) + return; + const ev = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.initEvent(e, { target: this.el, type: 'drag' }); + if (this.option.drag) { + this.option.drag(ev, this.ui()); + } + this.triggerEvent('drag', ev); + } + /** @internal called when the main page (after successful mousedown) receives a move event to drag the item around the screen */ + _mouseMove(e) { + // console.log(`${count++} move ${e.x},${e.y}`) + let s = this.mouseDownEvent; + if (this.dragging) { + this._dragFollow(e); + // delay actual grid handling drag until we pause for a while if set + if (_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.pauseDrag) { + const pause = Number.isInteger(_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.pauseDrag) ? _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.pauseDrag : 100; + if (this.dragTimeout) + window.clearTimeout(this.dragTimeout); + this.dragTimeout = window.setTimeout(() => this._callDrag(e), pause); + } + else { + this._callDrag(e); + } + } + else if (Math.abs(e.x - s.x) + Math.abs(e.y - s.y) > 3) { + /** + * don't start unless we've moved at least 3 pixels + */ + this.dragging = true; + _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dragElement = this; + // if we're dragging an actual grid item, set the current drop as the grid (to detect enter/leave) + let grid = this.el.gridstackNode?.grid; + if (grid) { + _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement = grid.el.ddElement.ddDroppable; + } + else { + delete _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement; + } + this.helper = this._createHelper(e); + this._setupHelperContainmentStyle(); + this.dragTransform = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.getValuesFromTransformedElement(this.helperContainment); + this.dragOffset = this._getDragOffset(e, this.el, this.helperContainment); + const ev = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.initEvent(e, { target: this.el, type: 'dragstart' }); + this._setupHelperStyle(e); + if (this.option.start) { + this.option.start(ev, this.ui()); + } + this.triggerEvent('dragstart', ev); + } + // e.preventDefault(); // passive = true. OLD: was needed otherwise we get text sweep text selection as we drag around + return true; + } + /** @internal call when the mouse gets released to drop the item at current location */ + _mouseUp(e) { + document.removeEventListener('mousemove', this._mouseMove, true); + document.removeEventListener('mouseup', this._mouseUp, true); + if (_dd_touch__WEBPACK_IMPORTED_MODULE_3__.isTouch) { + this.dragEl.removeEventListener('touchmove', _dd_touch__WEBPACK_IMPORTED_MODULE_3__.touchmove, true); + this.dragEl.removeEventListener('touchend', _dd_touch__WEBPACK_IMPORTED_MODULE_3__.touchend, true); + } + if (this.dragging) { + delete this.dragging; + // reset the drop target if dragging over ourself (already parented, just moving during stop callback below) + if (_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement?.el === this.el.parentElement) { + delete _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement; + } + this.helperContainment.style.position = this.parentOriginStylePosition || null; + if (this.helper === this.el) { + this._removeHelperStyle(); + } + else { + this.helper.remove(); + } + const ev = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.initEvent(e, { target: this.el, type: 'dragstop' }); + if (this.option.stop) { + this.option.stop(ev); // NOTE: destroy() will be called when removing item, so expect NULL ptr after! + } + this.triggerEvent('dragstop', ev); + // call the droppable method to receive the item + if (_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement) { + _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement.drop(e); + } + } + delete this.helper; + delete this.mouseDownEvent; + delete _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dragElement; + delete _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement; + delete _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.mouseHandled; + e.preventDefault(); + } + /** @internal create a clone copy (or user defined method) of the original drag item if set */ + _createHelper(event) { + let helper = this.el; + if (typeof this.option.helper === 'function') { + helper = this.option.helper(event); + } + else if (this.option.helper === 'clone') { + helper = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.cloneNode(this.el); + } + if (!document.body.contains(helper)) { + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.appendTo(helper, this.option.appendTo === 'parent' ? this.el.parentElement : this.option.appendTo); + } + if (helper === this.el) { + this.dragElementOriginStyle = DDDraggable.originStyleProp.map(prop => this.el.style[prop]); + } + return helper; + } + /** @internal set the fix position of the dragged item */ + _setupHelperStyle(e) { + this.helper.classList.add('ui-draggable-dragging'); + // TODO: set all at once with style.cssText += ... ? https://stackoverflow.com/questions/3968593 + const style = this.helper.style; + style.pointerEvents = 'none'; // needed for over items to get enter/leave + // style.cursor = 'move'; // TODO: can't set with pointerEvents=none ! (done in CSS as well) + style.width = this.dragOffset.width + 'px'; + style.height = this.dragOffset.height + 'px'; + style.willChange = 'left, top'; + style.position = 'fixed'; // let us drag between grids by not clipping as parent .grid-stack is position: 'relative' + this._dragFollow(e); // now position it + style.transition = 'none'; // show up instantly + setTimeout(() => { + if (this.helper) { + style.transition = null; // recover animation + } + }, 0); + return this; + } + /** @internal restore back the original style before dragging */ + _removeHelperStyle() { + this.helper.classList.remove('ui-draggable-dragging'); + let node = this.helper?.gridstackNode; + // don't bother restoring styles if we're gonna remove anyway... + if (!node?._isAboutToRemove && this.dragElementOriginStyle) { + let helper = this.helper; + // don't animate, otherwise we animate offseted when switching back to 'absolute' from 'fixed'. + // TODO: this also removes resizing animation which doesn't have this issue, but others. + // Ideally both would animate ('move' would immediately restore 'absolute' and adjust coordinate to match, + // then trigger a delay (repaint) to restore to final dest with animate) but then we need to make sure 'resizestop' + // is called AFTER 'transitionend' event is received (see https://github.com/gridstack/gridstack.js/issues/2033) + let transition = this.dragElementOriginStyle['transition'] || null; + helper.style.transition = this.dragElementOriginStyle['transition'] = 'none'; // can't be NULL #1973 + DDDraggable.originStyleProp.forEach(prop => helper.style[prop] = this.dragElementOriginStyle[prop] || null); + setTimeout(() => helper.style.transition = transition, 50); // recover animation from saved vars after a pause (0 isn't enough #1973) + } + delete this.dragElementOriginStyle; + return this; + } + /** @internal updates the top/left position to follow the mouse */ + _dragFollow(e) { + let containmentRect = { left: 0, top: 0 }; + // if (this.helper.style.position === 'absolute') { // we use 'fixed' + // const { left, top } = this.helperContainment.getBoundingClientRect(); + // containmentRect = { left, top }; + // } + const style = this.helper.style; + const offset = this.dragOffset; + style.left = (e.clientX + offset.offsetLeft - containmentRect.left) * this.dragTransform.xScale + 'px'; + style.top = (e.clientY + offset.offsetTop - containmentRect.top) * this.dragTransform.yScale + 'px'; + } + /** @internal */ + _setupHelperContainmentStyle() { + this.helperContainment = this.helper.parentElement; + if (this.helper.style.position !== 'fixed') { + this.parentOriginStylePosition = this.helperContainment.style.position; + if (getComputedStyle(this.helperContainment).position.match(/static/)) { + this.helperContainment.style.position = 'relative'; + } + } + return this; + } + /** @internal */ + _getDragOffset(event, el, parent) { + // in case ancestor has transform/perspective css properties that change the viewpoint + let xformOffsetX = 0; + let xformOffsetY = 0; + if (parent) { + xformOffsetX = this.dragTransform.xOffset; + xformOffsetY = this.dragTransform.yOffset; + } + const targetOffset = el.getBoundingClientRect(); + return { + left: targetOffset.left, + top: targetOffset.top, + offsetLeft: -event.clientX + targetOffset.left - xformOffsetX, + offsetTop: -event.clientY + targetOffset.top - xformOffsetY, + width: targetOffset.width * this.dragTransform.xScale, + height: targetOffset.height * this.dragTransform.yScale + }; + } + /** @internal TODO: set to public as called by DDDroppable! */ + ui() { + const containmentEl = this.el.parentElement; + const containmentRect = containmentEl.getBoundingClientRect(); + const offset = this.helper.getBoundingClientRect(); + return { + position: { + top: (offset.top - containmentRect.top) * this.dragTransform.yScale, + left: (offset.left - containmentRect.left) * this.dragTransform.xScale + } + /* not used by GridStack for now... + helper: [this.helper], //The object arr representing the helper that's being dragged. + offset: { top: offset.top, left: offset.left } // Current offset position of the helper as { top, left } object. + */ + }; + } +} +/** @internal properties we change during dragging, and restore back */ +DDDraggable.originStyleProp = ['transition', 'pointerEvents', 'position', 'left', 'top', 'minWidth', 'willChange']; + +//# sourceMappingURL=dd-draggable.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/dd-droppable.js": +/*!*****************************************************!*\ + !*** ./node_modules/gridstack/dist/dd-droppable.js ***! + \*****************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ DDDroppable: () => (/* binding */ DDDroppable) +/* harmony export */ }); +/* harmony import */ var _dd_manager__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./dd-manager */ "./node_modules/gridstack/dist/dd-manager.js"); +/* harmony import */ var _dd_base_impl__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dd-base-impl */ "./node_modules/gridstack/dist/dd-base-impl.js"); +/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ "./node_modules/gridstack/dist/utils.js"); +/* harmony import */ var _dd_touch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./dd-touch */ "./node_modules/gridstack/dist/dd-touch.js"); +/** + * dd-droppable.ts 10.1.2 + * Copyright (c) 2021-2022 Alain Dumesny - see GridStack root license + */ + + + + +// let count = 0; // TEST +class DDDroppable extends _dd_base_impl__WEBPACK_IMPORTED_MODULE_1__.DDBaseImplement { + constructor(el, option = {}) { + super(); + this.el = el; + this.option = option; + // create var event binding so we can easily remove and still look like TS methods (unlike anonymous functions) + this._mouseEnter = this._mouseEnter.bind(this); + this._mouseLeave = this._mouseLeave.bind(this); + this.enable(); + this._setupAccept(); + } + on(event, callback) { + super.on(event, callback); + } + off(event) { + super.off(event); + } + enable() { + if (this.disabled === false) + return; + super.enable(); + this.el.classList.add('ui-droppable'); + this.el.classList.remove('ui-droppable-disabled'); + this.el.addEventListener('mouseenter', this._mouseEnter); + this.el.addEventListener('mouseleave', this._mouseLeave); + if (_dd_touch__WEBPACK_IMPORTED_MODULE_3__.isTouch) { + this.el.addEventListener('pointerenter', _dd_touch__WEBPACK_IMPORTED_MODULE_3__.pointerenter); + this.el.addEventListener('pointerleave', _dd_touch__WEBPACK_IMPORTED_MODULE_3__.pointerleave); + } + } + disable(forDestroy = false) { + if (this.disabled === true) + return; + super.disable(); + this.el.classList.remove('ui-droppable'); + if (!forDestroy) + this.el.classList.add('ui-droppable-disabled'); + this.el.removeEventListener('mouseenter', this._mouseEnter); + this.el.removeEventListener('mouseleave', this._mouseLeave); + if (_dd_touch__WEBPACK_IMPORTED_MODULE_3__.isTouch) { + this.el.removeEventListener('pointerenter', _dd_touch__WEBPACK_IMPORTED_MODULE_3__.pointerenter); + this.el.removeEventListener('pointerleave', _dd_touch__WEBPACK_IMPORTED_MODULE_3__.pointerleave); + } + } + destroy() { + this.disable(true); + this.el.classList.remove('ui-droppable'); + this.el.classList.remove('ui-droppable-disabled'); + super.destroy(); + } + updateOption(opts) { + Object.keys(opts).forEach(key => this.option[key] = opts[key]); + this._setupAccept(); + return this; + } + /** @internal called when the cursor enters our area - prepare for a possible drop and track leaving */ + _mouseEnter(e) { + // console.log(`${count++} Enter ${this.el.id || (this.el as GridHTMLElement).gridstack.opts.id}`); // TEST + if (!_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dragElement) + return; + if (!this._canDrop(_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dragElement.el)) + return; + e.preventDefault(); + e.stopPropagation(); + // make sure when we enter this, that the last one gets a leave FIRST to correctly cleanup as we don't always do + if (_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement && _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement !== this) { + _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement._mouseLeave(e, true); // calledByEnter = true + } + _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement = this; + const ev = _utils__WEBPACK_IMPORTED_MODULE_2__.Utils.initEvent(e, { target: this.el, type: 'dropover' }); + if (this.option.over) { + this.option.over(ev, this._ui(_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dragElement)); + } + this.triggerEvent('dropover', ev); + this.el.classList.add('ui-droppable-over'); + // console.log('tracking'); // TEST + } + /** @internal called when the item is leaving our area, stop tracking if we had moving item */ + _mouseLeave(e, calledByEnter = false) { + // console.log(`${count++} Leave ${this.el.id || (this.el as GridHTMLElement).gridstack.opts.id}`); // TEST + if (!_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dragElement || _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement !== this) + return; + e.preventDefault(); + e.stopPropagation(); + const ev = _utils__WEBPACK_IMPORTED_MODULE_2__.Utils.initEvent(e, { target: this.el, type: 'dropout' }); + if (this.option.out) { + this.option.out(ev, this._ui(_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dragElement)); + } + this.triggerEvent('dropout', ev); + if (_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement === this) { + delete _dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dropElement; + // console.log('not tracking'); // TEST + // if we're still over a parent droppable, send it an enter as we don't get one from leaving nested children + if (!calledByEnter) { + let parentDrop; + let parent = this.el.parentElement; + while (!parentDrop && parent) { + parentDrop = parent.ddElement?.ddDroppable; + parent = parent.parentElement; + } + if (parentDrop) { + parentDrop._mouseEnter(e); + } + } + } + } + /** item is being dropped on us - called by the drag mouseup handler - this calls the client drop event */ + drop(e) { + e.preventDefault(); + const ev = _utils__WEBPACK_IMPORTED_MODULE_2__.Utils.initEvent(e, { target: this.el, type: 'drop' }); + if (this.option.drop) { + this.option.drop(ev, this._ui(_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dragElement)); + } + this.triggerEvent('drop', ev); + } + /** @internal true if element matches the string/method accept option */ + _canDrop(el) { + return el && (!this.accept || this.accept(el)); + } + /** @internal */ + _setupAccept() { + if (!this.option.accept) + return this; + if (typeof this.option.accept === 'string') { + this.accept = (el) => el.classList.contains(this.option.accept) || el.matches(this.option.accept); + } + else { + this.accept = this.option.accept; + } + return this; + } + /** @internal */ + _ui(drag) { + return { + draggable: drag.el, + ...drag.ui() + }; + } +} +//# sourceMappingURL=dd-droppable.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/dd-element.js": +/*!***************************************************!*\ + !*** ./node_modules/gridstack/dist/dd-element.js ***! + \***************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ DDElement: () => (/* binding */ DDElement) +/* harmony export */ }); +/* harmony import */ var _dd_resizable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./dd-resizable */ "./node_modules/gridstack/dist/dd-resizable.js"); +/* harmony import */ var _dd_draggable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dd-draggable */ "./node_modules/gridstack/dist/dd-draggable.js"); +/* harmony import */ var _dd_droppable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./dd-droppable */ "./node_modules/gridstack/dist/dd-droppable.js"); +/** + * dd-elements.ts 10.1.2 + * Copyright (c) 2021 Alain Dumesny - see GridStack root license + */ + + + +class DDElement { + static init(el) { + if (!el.ddElement) { + el.ddElement = new DDElement(el); + } + return el.ddElement; + } + constructor(el) { + this.el = el; + } + on(eventName, callback) { + if (this.ddDraggable && ['drag', 'dragstart', 'dragstop'].indexOf(eventName) > -1) { + this.ddDraggable.on(eventName, callback); + } + else if (this.ddDroppable && ['drop', 'dropover', 'dropout'].indexOf(eventName) > -1) { + this.ddDroppable.on(eventName, callback); + } + else if (this.ddResizable && ['resizestart', 'resize', 'resizestop'].indexOf(eventName) > -1) { + this.ddResizable.on(eventName, callback); + } + return this; + } + off(eventName) { + if (this.ddDraggable && ['drag', 'dragstart', 'dragstop'].indexOf(eventName) > -1) { + this.ddDraggable.off(eventName); + } + else if (this.ddDroppable && ['drop', 'dropover', 'dropout'].indexOf(eventName) > -1) { + this.ddDroppable.off(eventName); + } + else if (this.ddResizable && ['resizestart', 'resize', 'resizestop'].indexOf(eventName) > -1) { + this.ddResizable.off(eventName); + } + return this; + } + setupDraggable(opts) { + if (!this.ddDraggable) { + this.ddDraggable = new _dd_draggable__WEBPACK_IMPORTED_MODULE_1__.DDDraggable(this.el, opts); + } + else { + this.ddDraggable.updateOption(opts); + } + return this; + } + cleanDraggable() { + if (this.ddDraggable) { + this.ddDraggable.destroy(); + delete this.ddDraggable; + } + return this; + } + setupResizable(opts) { + if (!this.ddResizable) { + this.ddResizable = new _dd_resizable__WEBPACK_IMPORTED_MODULE_0__.DDResizable(this.el, opts); + } + else { + this.ddResizable.updateOption(opts); + } + return this; + } + cleanResizable() { + if (this.ddResizable) { + this.ddResizable.destroy(); + delete this.ddResizable; + } + return this; + } + setupDroppable(opts) { + if (!this.ddDroppable) { + this.ddDroppable = new _dd_droppable__WEBPACK_IMPORTED_MODULE_2__.DDDroppable(this.el, opts); + } + else { + this.ddDroppable.updateOption(opts); + } + return this; + } + cleanDroppable() { + if (this.ddDroppable) { + this.ddDroppable.destroy(); + delete this.ddDroppable; + } + return this; + } +} +//# sourceMappingURL=dd-element.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/dd-gridstack.js": +/*!*****************************************************!*\ + !*** ./node_modules/gridstack/dist/dd-gridstack.js ***! + \*****************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ DDGridStack: () => (/* binding */ DDGridStack) +/* harmony export */ }); +/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ "./node_modules/gridstack/dist/utils.js"); +/* harmony import */ var _dd_manager__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dd-manager */ "./node_modules/gridstack/dist/dd-manager.js"); +/* harmony import */ var _dd_element__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./dd-element */ "./node_modules/gridstack/dist/dd-element.js"); +/** + * dd-gridstack.ts 10.1.2 + * Copyright (c) 2021 Alain Dumesny - see GridStack root license + */ + + + +// let count = 0; // TEST +/** + * HTML Native Mouse and Touch Events Drag and Drop functionality. + */ +class DDGridStack { + resizable(el, opts, key, value) { + this._getDDElements(el).forEach(dEl => { + if (opts === 'disable' || opts === 'enable') { + dEl.ddResizable && dEl.ddResizable[opts](); // can't create DD as it requires options for setupResizable() + } + else if (opts === 'destroy') { + dEl.ddResizable && dEl.cleanResizable(); + } + else if (opts === 'option') { + dEl.setupResizable({ [key]: value }); + } + else { + const n = dEl.el.gridstackNode; + const grid = n.grid; + let handles = dEl.el.getAttribute('gs-resize-handles') || grid.opts.resizable.handles || 'e,s,se'; + if (handles === 'all') + handles = 'n,e,s,w,se,sw,ne,nw'; + // NOTE: keep the resize handles as e,w don't have enough space (10px) to show resize corners anyway. limit during drag instead + // restrict vertical resize if height is done to match content anyway... odd to have it spring back + // if (Utils.shouldSizeToContent(n, true)) { + // const doE = handles.indexOf('e') !== -1; + // const doW = handles.indexOf('w') !== -1; + // handles = doE ? (doW ? 'e,w' : 'e') : (doW ? 'w' : ''); + // } + const autoHide = !grid.opts.alwaysShowResizeHandle; + dEl.setupResizable({ + ...grid.opts.resizable, + ...{ handles, autoHide }, + ...{ + start: opts.start, + stop: opts.stop, + resize: opts.resize + } + }); + } + }); + return this; + } + draggable(el, opts, key, value) { + this._getDDElements(el).forEach(dEl => { + if (opts === 'disable' || opts === 'enable') { + dEl.ddDraggable && dEl.ddDraggable[opts](); // can't create DD as it requires options for setupDraggable() + } + else if (opts === 'destroy') { + dEl.ddDraggable && dEl.cleanDraggable(); + } + else if (opts === 'option') { + dEl.setupDraggable({ [key]: value }); + } + else { + const grid = dEl.el.gridstackNode.grid; + dEl.setupDraggable({ + ...grid.opts.draggable, + ...{ + // containment: (grid.parentGridItem && !grid.opts.dragOut) ? grid.el.parentElement : (grid.opts.draggable.containment || null), + start: opts.start, + stop: opts.stop, + drag: opts.drag + } + }); + } + }); + return this; + } + dragIn(el, opts) { + this._getDDElements(el).forEach(dEl => dEl.setupDraggable(opts)); + return this; + } + droppable(el, opts, key, value) { + if (typeof opts.accept === 'function' && !opts._accept) { + opts._accept = opts.accept; + opts.accept = (el) => opts._accept(el); + } + this._getDDElements(el).forEach(dEl => { + if (opts === 'disable' || opts === 'enable') { + dEl.ddDroppable && dEl.ddDroppable[opts](); + } + else if (opts === 'destroy') { + if (dEl.ddDroppable) { // error to call destroy if not there + dEl.cleanDroppable(); + } + } + else if (opts === 'option') { + dEl.setupDroppable({ [key]: value }); + } + else { + dEl.setupDroppable(opts); + } + }); + return this; + } + /** true if element is droppable */ + isDroppable(el) { + return !!(el && el.ddElement && el.ddElement.ddDroppable && !el.ddElement.ddDroppable.disabled); + } + /** true if element is draggable */ + isDraggable(el) { + return !!(el && el.ddElement && el.ddElement.ddDraggable && !el.ddElement.ddDraggable.disabled); + } + /** true if element is draggable */ + isResizable(el) { + return !!(el && el.ddElement && el.ddElement.ddResizable && !el.ddElement.ddResizable.disabled); + } + on(el, name, callback) { + this._getDDElements(el).forEach(dEl => dEl.on(name, (event) => { + callback(event, _dd_manager__WEBPACK_IMPORTED_MODULE_1__.DDManager.dragElement ? _dd_manager__WEBPACK_IMPORTED_MODULE_1__.DDManager.dragElement.el : event.target, _dd_manager__WEBPACK_IMPORTED_MODULE_1__.DDManager.dragElement ? _dd_manager__WEBPACK_IMPORTED_MODULE_1__.DDManager.dragElement.helper : null); + })); + return this; + } + off(el, name) { + this._getDDElements(el).forEach(dEl => dEl.off(name)); + return this; + } + /** @internal returns a list of DD elements, creating them on the fly by default */ + _getDDElements(els, create = true) { + let hosts = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.getElements(els); + if (!hosts.length) + return []; + let list = hosts.map(e => e.ddElement || (create ? _dd_element__WEBPACK_IMPORTED_MODULE_2__.DDElement.init(e) : null)); + if (!create) { + list.filter(d => d); + } // remove nulls + return list; + } +} +//# sourceMappingURL=dd-gridstack.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/dd-manager.js": +/*!***************************************************!*\ + !*** ./node_modules/gridstack/dist/dd-manager.js ***! + \***************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ DDManager: () => (/* binding */ DDManager) +/* harmony export */ }); +/** + * dd-manager.ts 10.1.2 + * Copyright (c) 2021 Alain Dumesny - see GridStack root license + */ +/** + * globals that are shared across Drag & Drop instances + */ +class DDManager { +} +//# sourceMappingURL=dd-manager.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/dd-resizable-handle.js": +/*!************************************************************!*\ + !*** ./node_modules/gridstack/dist/dd-resizable-handle.js ***! + \************************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ DDResizableHandle: () => (/* binding */ DDResizableHandle) +/* harmony export */ }); +/* harmony import */ var _dd_touch__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./dd-touch */ "./node_modules/gridstack/dist/dd-touch.js"); +/** + * dd-resizable-handle.ts 10.1.2 + * Copyright (c) 2021-2022 Alain Dumesny - see GridStack root license + */ + +class DDResizableHandle { + constructor(host, dir, option) { + this.host = host; + this.dir = dir; + this.option = option; + /** @internal true after we've moved enough pixels to start a resize */ + this.moving = false; + // create var event binding so we can easily remove and still look like TS methods (unlike anonymous functions) + this._mouseDown = this._mouseDown.bind(this); + this._mouseMove = this._mouseMove.bind(this); + this._mouseUp = this._mouseUp.bind(this); + this._init(); + } + /** @internal */ + _init() { + const el = this.el = document.createElement('div'); + el.classList.add('ui-resizable-handle'); + el.classList.add(`${DDResizableHandle.prefix}${this.dir}`); + el.style.zIndex = '100'; + el.style.userSelect = 'none'; + this.host.appendChild(this.el); + this.el.addEventListener('mousedown', this._mouseDown); + if (_dd_touch__WEBPACK_IMPORTED_MODULE_0__.isTouch) { + this.el.addEventListener('touchstart', _dd_touch__WEBPACK_IMPORTED_MODULE_0__.touchstart); + this.el.addEventListener('pointerdown', _dd_touch__WEBPACK_IMPORTED_MODULE_0__.pointerdown); + // this.el.style.touchAction = 'none'; // not needed unlike pointerdown doc comment + } + return this; + } + /** call this when resize handle needs to be removed and cleaned up */ + destroy() { + if (this.moving) + this._mouseUp(this.mouseDownEvent); + this.el.removeEventListener('mousedown', this._mouseDown); + if (_dd_touch__WEBPACK_IMPORTED_MODULE_0__.isTouch) { + this.el.removeEventListener('touchstart', _dd_touch__WEBPACK_IMPORTED_MODULE_0__.touchstart); + this.el.removeEventListener('pointerdown', _dd_touch__WEBPACK_IMPORTED_MODULE_0__.pointerdown); + } + this.host.removeChild(this.el); + delete this.el; + delete this.host; + return this; + } + /** @internal called on mouse down on us: capture move on the entire document (mouse might not stay on us) until we release the mouse */ + _mouseDown(e) { + this.mouseDownEvent = e; + document.addEventListener('mousemove', this._mouseMove, { capture: true, passive: true }); // capture, not bubble + document.addEventListener('mouseup', this._mouseUp, true); + if (_dd_touch__WEBPACK_IMPORTED_MODULE_0__.isTouch) { + this.el.addEventListener('touchmove', _dd_touch__WEBPACK_IMPORTED_MODULE_0__.touchmove); + this.el.addEventListener('touchend', _dd_touch__WEBPACK_IMPORTED_MODULE_0__.touchend); + } + e.stopPropagation(); + e.preventDefault(); + } + /** @internal */ + _mouseMove(e) { + let s = this.mouseDownEvent; + if (this.moving) { + this._triggerEvent('move', e); + } + else if (Math.abs(e.x - s.x) + Math.abs(e.y - s.y) > 2) { + // don't start unless we've moved at least 3 pixels + this.moving = true; + this._triggerEvent('start', this.mouseDownEvent); + this._triggerEvent('move', e); + } + e.stopPropagation(); + // e.preventDefault(); passive = true + } + /** @internal */ + _mouseUp(e) { + if (this.moving) { + this._triggerEvent('stop', e); + } + document.removeEventListener('mousemove', this._mouseMove, true); + document.removeEventListener('mouseup', this._mouseUp, true); + if (_dd_touch__WEBPACK_IMPORTED_MODULE_0__.isTouch) { + this.el.removeEventListener('touchmove', _dd_touch__WEBPACK_IMPORTED_MODULE_0__.touchmove); + this.el.removeEventListener('touchend', _dd_touch__WEBPACK_IMPORTED_MODULE_0__.touchend); + } + delete this.moving; + delete this.mouseDownEvent; + e.stopPropagation(); + e.preventDefault(); + } + /** @internal */ + _triggerEvent(name, event) { + if (this.option[name]) + this.option[name](event); + return this; + } +} +/** @internal */ +DDResizableHandle.prefix = 'ui-resizable-'; + +//# sourceMappingURL=dd-resizable-handle.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/dd-resizable.js": +/*!*****************************************************!*\ + !*** ./node_modules/gridstack/dist/dd-resizable.js ***! + \*****************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ DDResizable: () => (/* binding */ DDResizable) +/* harmony export */ }); +/* harmony import */ var _dd_resizable_handle__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./dd-resizable-handle */ "./node_modules/gridstack/dist/dd-resizable-handle.js"); +/* harmony import */ var _dd_base_impl__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dd-base-impl */ "./node_modules/gridstack/dist/dd-base-impl.js"); +/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ "./node_modules/gridstack/dist/utils.js"); +/* harmony import */ var _dd_manager__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./dd-manager */ "./node_modules/gridstack/dist/dd-manager.js"); +/** + * dd-resizable.ts 10.1.2 + * Copyright (c) 2021-2022 Alain Dumesny - see GridStack root license + */ + + + + +class DDResizable extends _dd_base_impl__WEBPACK_IMPORTED_MODULE_1__.DDBaseImplement { + // have to be public else complains for HTMLElementExtendOpt ? + constructor(el, option = {}) { + super(); + this.el = el; + this.option = option; + /** @internal */ + this.rectScale = { x: 1, y: 1 }; + /** @internal */ + this._ui = () => { + const containmentEl = this.el.parentElement; + const containmentRect = containmentEl.getBoundingClientRect(); + const newRect = { + width: this.originalRect.width, + height: this.originalRect.height + this.scrolled, + left: this.originalRect.left, + top: this.originalRect.top - this.scrolled + }; + const rect = this.temporalRect || newRect; + return { + position: { + left: (rect.left - containmentRect.left) * this.rectScale.x, + top: (rect.top - containmentRect.top) * this.rectScale.y + }, + size: { + width: rect.width * this.rectScale.x, + height: rect.height * this.rectScale.y + } + /* Gridstack ONLY needs position set above... keep around in case. + element: [this.el], // The object representing the element to be resized + helper: [], // TODO: not support yet - The object representing the helper that's being resized + originalElement: [this.el],// we don't wrap here, so simplify as this.el //The object representing the original element before it is wrapped + originalPosition: { // The position represented as { left, top } before the resizable is resized + left: this.originalRect.left - containmentRect.left, + top: this.originalRect.top - containmentRect.top + }, + originalSize: { // The size represented as { width, height } before the resizable is resized + width: this.originalRect.width, + height: this.originalRect.height + } + */ + }; + }; + // create var event binding so we can easily remove and still look like TS methods (unlike anonymous functions) + this._mouseOver = this._mouseOver.bind(this); + this._mouseOut = this._mouseOut.bind(this); + this.enable(); + this._setupAutoHide(this.option.autoHide); + this._setupHandlers(); + } + on(event, callback) { + super.on(event, callback); + } + off(event) { + super.off(event); + } + enable() { + super.enable(); + this.el.classList.remove('ui-resizable-disabled'); + this._setupAutoHide(this.option.autoHide); + } + disable() { + super.disable(); + this.el.classList.add('ui-resizable-disabled'); + this._setupAutoHide(false); + } + destroy() { + this._removeHandlers(); + this._setupAutoHide(false); + delete this.el; + super.destroy(); + } + updateOption(opts) { + let updateHandles = (opts.handles && opts.handles !== this.option.handles); + let updateAutoHide = (opts.autoHide && opts.autoHide !== this.option.autoHide); + Object.keys(opts).forEach(key => this.option[key] = opts[key]); + if (updateHandles) { + this._removeHandlers(); + this._setupHandlers(); + } + if (updateAutoHide) { + this._setupAutoHide(this.option.autoHide); + } + return this; + } + /** @internal turns auto hide on/off */ + _setupAutoHide(auto) { + if (auto) { + this.el.classList.add('ui-resizable-autohide'); + // use mouseover and not mouseenter to get better performance and track for nested cases + this.el.addEventListener('mouseover', this._mouseOver); + this.el.addEventListener('mouseout', this._mouseOut); + } + else { + this.el.classList.remove('ui-resizable-autohide'); + this.el.removeEventListener('mouseover', this._mouseOver); + this.el.removeEventListener('mouseout', this._mouseOut); + if (_dd_manager__WEBPACK_IMPORTED_MODULE_3__.DDManager.overResizeElement === this) { + delete _dd_manager__WEBPACK_IMPORTED_MODULE_3__.DDManager.overResizeElement; + } + } + return this; + } + /** @internal */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _mouseOver(e) { + // console.log(`${count++} pre-enter ${(this.el as GridItemHTMLElement).gridstackNode._id}`) + // already over a child, ignore. Ideally we just call e.stopPropagation() but see https://github.com/gridstack/gridstack.js/issues/2018 + if (_dd_manager__WEBPACK_IMPORTED_MODULE_3__.DDManager.overResizeElement || _dd_manager__WEBPACK_IMPORTED_MODULE_3__.DDManager.dragElement) + return; + _dd_manager__WEBPACK_IMPORTED_MODULE_3__.DDManager.overResizeElement = this; + // console.log(`${count++} enter ${(this.el as GridItemHTMLElement).gridstackNode._id}`) + this.el.classList.remove('ui-resizable-autohide'); + } + /** @internal */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _mouseOut(e) { + // console.log(`${count++} pre-leave ${(this.el as GridItemHTMLElement).gridstackNode._id}`) + if (_dd_manager__WEBPACK_IMPORTED_MODULE_3__.DDManager.overResizeElement !== this) + return; + delete _dd_manager__WEBPACK_IMPORTED_MODULE_3__.DDManager.overResizeElement; + // console.log(`${count++} leave ${(this.el as GridItemHTMLElement).gridstackNode._id}`) + this.el.classList.add('ui-resizable-autohide'); + } + /** @internal */ + _setupHandlers() { + this.handlers = this.option.handles.split(',') + .map(dir => dir.trim()) + .map(dir => new _dd_resizable_handle__WEBPACK_IMPORTED_MODULE_0__.DDResizableHandle(this.el, dir, { + start: (event) => { + this._resizeStart(event); + }, + stop: (event) => { + this._resizeStop(event); + }, + move: (event) => { + this._resizing(event, dir); + } + })); + return this; + } + /** @internal */ + _resizeStart(event) { + this.sizeToContent = _utils__WEBPACK_IMPORTED_MODULE_2__.Utils.shouldSizeToContent(this.el.gridstackNode, true); // strick true only and not number + this.originalRect = this.el.getBoundingClientRect(); + this.scrollEl = _utils__WEBPACK_IMPORTED_MODULE_2__.Utils.getScrollElement(this.el); + this.scrollY = this.scrollEl.scrollTop; + this.scrolled = 0; + this.startEvent = event; + this._setupHelper(); + this._applyChange(); + const ev = _utils__WEBPACK_IMPORTED_MODULE_2__.Utils.initEvent(event, { type: 'resizestart', target: this.el }); + if (this.option.start) { + this.option.start(ev, this._ui()); + } + this.el.classList.add('ui-resizable-resizing'); + this.triggerEvent('resizestart', ev); + return this; + } + /** @internal */ + _resizing(event, dir) { + this.scrolled = this.scrollEl.scrollTop - this.scrollY; + this.temporalRect = this._getChange(event, dir); + this._applyChange(); + const ev = _utils__WEBPACK_IMPORTED_MODULE_2__.Utils.initEvent(event, { type: 'resize', target: this.el }); + if (this.option.resize) { + this.option.resize(ev, this._ui()); + } + this.triggerEvent('resize', ev); + return this; + } + /** @internal */ + _resizeStop(event) { + const ev = _utils__WEBPACK_IMPORTED_MODULE_2__.Utils.initEvent(event, { type: 'resizestop', target: this.el }); + if (this.option.stop) { + this.option.stop(ev); // Note: ui() not used by gridstack so don't pass + } + this.el.classList.remove('ui-resizable-resizing'); + this.triggerEvent('resizestop', ev); + this._cleanHelper(); + delete this.startEvent; + delete this.originalRect; + delete this.temporalRect; + delete this.scrollY; + delete this.scrolled; + return this; + } + /** @internal */ + _setupHelper() { + this.elOriginStyleVal = DDResizable._originStyleProp.map(prop => this.el.style[prop]); + this.parentOriginStylePosition = this.el.parentElement.style.position; + const parent = this.el.parentElement; + const dragTransform = _utils__WEBPACK_IMPORTED_MODULE_2__.Utils.getValuesFromTransformedElement(parent); + this.rectScale = { + x: dragTransform.xScale, + y: dragTransform.yScale + }; + if (getComputedStyle(this.el.parentElement).position.match(/static/)) { + this.el.parentElement.style.position = 'relative'; + } + this.el.style.position = 'absolute'; + this.el.style.opacity = '0.8'; + return this; + } + /** @internal */ + _cleanHelper() { + DDResizable._originStyleProp.forEach((prop, i) => { + this.el.style[prop] = this.elOriginStyleVal[i] || null; + }); + this.el.parentElement.style.position = this.parentOriginStylePosition || null; + return this; + } + /** @internal */ + _getChange(event, dir) { + const oEvent = this.startEvent; + const newRect = { + width: this.originalRect.width, + height: this.originalRect.height + this.scrolled, + left: this.originalRect.left, + top: this.originalRect.top - this.scrolled + }; + const offsetX = event.clientX - oEvent.clientX; + const offsetY = this.sizeToContent ? 0 : event.clientY - oEvent.clientY; // prevent vert resize + if (dir.indexOf('e') > -1) { + newRect.width += offsetX; + } + else if (dir.indexOf('w') > -1) { + newRect.width -= offsetX; + newRect.left += offsetX; + } + if (dir.indexOf('s') > -1) { + newRect.height += offsetY; + } + else if (dir.indexOf('n') > -1) { + newRect.height -= offsetY; + newRect.top += offsetY; + } + const constrain = this._constrainSize(newRect.width, newRect.height); + if (Math.round(newRect.width) !== Math.round(constrain.width)) { // round to ignore slight round-off errors + if (dir.indexOf('w') > -1) { + newRect.left += newRect.width - constrain.width; + } + newRect.width = constrain.width; + } + if (Math.round(newRect.height) !== Math.round(constrain.height)) { + if (dir.indexOf('n') > -1) { + newRect.top += newRect.height - constrain.height; + } + newRect.height = constrain.height; + } + return newRect; + } + /** @internal constrain the size to the set min/max values */ + _constrainSize(oWidth, oHeight) { + const maxWidth = this.option.maxWidth || Number.MAX_SAFE_INTEGER; + const minWidth = this.option.minWidth / this.rectScale.x || oWidth; + const maxHeight = this.option.maxHeight || Number.MAX_SAFE_INTEGER; + const minHeight = this.option.minHeight / this.rectScale.y || oHeight; + const width = Math.min(maxWidth, Math.max(minWidth, oWidth)); + const height = Math.min(maxHeight, Math.max(minHeight, oHeight)); + return { width, height }; + } + /** @internal */ + _applyChange() { + let containmentRect = { left: 0, top: 0, width: 0, height: 0 }; + if (this.el.style.position === 'absolute') { + const containmentEl = this.el.parentElement; + const { left, top } = containmentEl.getBoundingClientRect(); + containmentRect = { left, top, width: 0, height: 0 }; + } + if (!this.temporalRect) + return this; + Object.keys(this.temporalRect).forEach(key => { + const value = this.temporalRect[key]; + const scaleReciprocal = key === 'width' || key === 'left' ? this.rectScale.x : key === 'height' || key === 'top' ? this.rectScale.y : 1; + this.el.style[key] = (value - containmentRect[key]) * scaleReciprocal + 'px'; + }); + return this; + } + /** @internal */ + _removeHandlers() { + this.handlers.forEach(handle => handle.destroy()); + delete this.handlers; + return this; + } +} +/** @internal */ +DDResizable._originStyleProp = ['width', 'height', 'position', 'left', 'top', 'opacity', 'zIndex']; + +//# sourceMappingURL=dd-resizable.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/dd-touch.js": +/*!*************************************************!*\ + !*** ./node_modules/gridstack/dist/dd-touch.js ***! + \*************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ isTouch: () => (/* binding */ isTouch), +/* harmony export */ pointerdown: () => (/* binding */ pointerdown), +/* harmony export */ pointerenter: () => (/* binding */ pointerenter), +/* harmony export */ pointerleave: () => (/* binding */ pointerleave), +/* harmony export */ touchend: () => (/* binding */ touchend), +/* harmony export */ touchmove: () => (/* binding */ touchmove), +/* harmony export */ touchstart: () => (/* binding */ touchstart) +/* harmony export */ }); +/* harmony import */ var _dd_manager__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./dd-manager */ "./node_modules/gridstack/dist/dd-manager.js"); +/** + * touch.ts 10.1.2 + * Copyright (c) 2021 Alain Dumesny - see GridStack root license + */ + +/** + * Detect touch support - Windows Surface devices and other touch devices + * should we use this instead ? (what we had for always showing resize handles) + * /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) + */ +const isTouch = typeof window !== 'undefined' && typeof document !== 'undefined' && + ('ontouchstart' in document + || 'ontouchstart' in window + // || !!window.TouchEvent // true on Windows 10 Chrome desktop so don't use this + // eslint-disable-next-line @typescript-eslint/no-explicit-any + || (window.DocumentTouch && document instanceof window.DocumentTouch) + || navigator.maxTouchPoints > 0 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + || navigator.msMaxTouchPoints > 0); +// interface TouchCoord {x: number, y: number}; +class DDTouch { +} +/** +* Get the x,y position of a touch event +*/ +// function getTouchCoords(e: TouchEvent): TouchCoord { +// return { +// x: e.changedTouches[0].pageX, +// y: e.changedTouches[0].pageY +// }; +// } +/** + * Simulate a mouse event based on a corresponding touch event + * @param {Object} e A touch event + * @param {String} simulatedType The corresponding mouse event + */ +function simulateMouseEvent(e, simulatedType) { + // Ignore multi-touch events + if (e.touches.length > 1) + return; + // Prevent "Ignored attempt to cancel a touchmove event with cancelable=false" errors + if (e.cancelable) + e.preventDefault(); + const touch = e.changedTouches[0], simulatedEvent = document.createEvent('MouseEvents'); + // Initialize the simulated mouse event using the touch event's coordinates + simulatedEvent.initMouseEvent(simulatedType, // type + true, // bubbles + true, // cancelable + window, // view + 1, // detail + touch.screenX, // screenX + touch.screenY, // screenY + touch.clientX, // clientX + touch.clientY, // clientY + false, // ctrlKey + false, // altKey + false, // shiftKey + false, // metaKey + 0, // button + null // relatedTarget + ); + // Dispatch the simulated event to the target element + e.target.dispatchEvent(simulatedEvent); +} +/** + * Simulate a mouse event based on a corresponding Pointer event + * @param {Object} e A pointer event + * @param {String} simulatedType The corresponding mouse event + */ +function simulatePointerMouseEvent(e, simulatedType) { + // Prevent "Ignored attempt to cancel a touchmove event with cancelable=false" errors + if (e.cancelable) + e.preventDefault(); + const simulatedEvent = document.createEvent('MouseEvents'); + // Initialize the simulated mouse event using the touch event's coordinates + simulatedEvent.initMouseEvent(simulatedType, // type + true, // bubbles + true, // cancelable + window, // view + 1, // detail + e.screenX, // screenX + e.screenY, // screenY + e.clientX, // clientX + e.clientY, // clientY + false, // ctrlKey + false, // altKey + false, // shiftKey + false, // metaKey + 0, // button + null // relatedTarget + ); + // Dispatch the simulated event to the target element + e.target.dispatchEvent(simulatedEvent); +} +/** + * Handle the touchstart events + * @param {Object} e The widget element's touchstart event + */ +function touchstart(e) { + // Ignore the event if another widget is already being handled + if (DDTouch.touchHandled) + return; + DDTouch.touchHandled = true; + // Simulate the mouse events + // simulateMouseEvent(e, 'mouseover'); + // simulateMouseEvent(e, 'mousemove'); + simulateMouseEvent(e, 'mousedown'); +} +/** + * Handle the touchmove events + * @param {Object} e The document's touchmove event + */ +function touchmove(e) { + // Ignore event if not handled by us + if (!DDTouch.touchHandled) + return; + simulateMouseEvent(e, 'mousemove'); +} +/** + * Handle the touchend events + * @param {Object} e The document's touchend event + */ +function touchend(e) { + // Ignore event if not handled + if (!DDTouch.touchHandled) + return; + // cancel delayed leave event when we release on ourself which happens BEFORE we get this! + if (DDTouch.pointerLeaveTimeout) { + window.clearTimeout(DDTouch.pointerLeaveTimeout); + delete DDTouch.pointerLeaveTimeout; + } + const wasDragging = !!_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dragElement; + // Simulate the mouseup event + simulateMouseEvent(e, 'mouseup'); + // simulateMouseEvent(event, 'mouseout'); + // If the touch interaction did not move, it should trigger a click + if (!wasDragging) { + simulateMouseEvent(e, 'click'); + } + // Unset the flag to allow other widgets to inherit the touch event + DDTouch.touchHandled = false; +} +/** + * Note we don't get touchenter/touchleave (which are deprecated) + * see https://stackoverflow.com/questions/27908339/js-touch-equivalent-for-mouseenter + * so instead of PointerEvent to still get enter/leave and send the matching mouse event. + */ +function pointerdown(e) { + // console.log("pointer down") + if (e.pointerType === 'mouse') + return; + e.target.releasePointerCapture(e.pointerId); // <- Important! +} +function pointerenter(e) { + // ignore the initial one we get on pointerdown on ourself + if (!_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dragElement) { + // console.log('pointerenter ignored'); + return; + } + // console.log('pointerenter'); + if (e.pointerType === 'mouse') + return; + simulatePointerMouseEvent(e, 'mouseenter'); +} +function pointerleave(e) { + // ignore the leave on ourself we get before releasing the mouse over ourself + // by delaying sending the event and having the up event cancel us + if (!_dd_manager__WEBPACK_IMPORTED_MODULE_0__.DDManager.dragElement) { + // console.log('pointerleave ignored'); + return; + } + if (e.pointerType === 'mouse') + return; + DDTouch.pointerLeaveTimeout = window.setTimeout(() => { + delete DDTouch.pointerLeaveTimeout; + // console.log('pointerleave delayed'); + simulatePointerMouseEvent(e, 'mouseleave'); + }, 10); +} +//# sourceMappingURL=dd-touch.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/gridstack-engine.js": +/*!*********************************************************!*\ + !*** ./node_modules/gridstack/dist/gridstack-engine.js ***! + \*********************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ GridStackEngine: () => (/* binding */ GridStackEngine) +/* harmony export */ }); +/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ "./node_modules/gridstack/dist/utils.js"); +/** + * gridstack-engine.ts 10.1.2 + * Copyright (c) 2021-2022 Alain Dumesny - see GridStack root license + */ + +/** + * Defines the GridStack engine that does most no DOM grid manipulation. + * See GridStack methods and vars for descriptions. + * + * NOTE: values should not be modified directly - call the main GridStack API instead + */ +class GridStackEngine { + constructor(opts = {}) { + this.addedNodes = []; + this.removedNodes = []; + this.column = opts.column || 12; + this.maxRow = opts.maxRow; + this._float = opts.float; + this.nodes = opts.nodes || []; + this.onChange = opts.onChange; + } + batchUpdate(flag = true, doPack = true) { + if (!!this.batchMode === flag) + return this; + this.batchMode = flag; + if (flag) { + this._prevFloat = this._float; + this._float = true; // let things go anywhere for now... will restore and possibly reposition later + this.cleanNodes(); + this.saveInitial(); // since begin update (which is called multiple times) won't do this + } + else { + this._float = this._prevFloat; + delete this._prevFloat; + if (doPack) + this._packNodes(); + this._notify(); + } + return this; + } + // use entire row for hitting area (will use bottom reverse sorted first) if we not actively moving DOWN and didn't already skip + _useEntireRowArea(node, nn) { + return (!this.float || this.batchMode && !this._prevFloat) && !this._hasLocked && (!node._moving || node._skipDown || nn.y <= node.y); + } + /** @internal fix collision on given 'node', going to given new location 'nn', with optional 'collide' node already found. + * return true if we moved. */ + _fixCollisions(node, nn = node, collide, opt = {}) { + this.sortNodes(-1); // from last to first, so recursive collision move items in the right order + collide = collide || this.collide(node, nn); // REAL area collide for swap and skip if none... + if (!collide) + return false; + // swap check: if we're actively moving in gravity mode, see if we collide with an object the same size + if (node._moving && !opt.nested && !this.float) { + if (this.swap(node, collide)) + return true; + } + // during while() collisions MAKE SURE to check entire row so larger items don't leap frog small ones (push them all down starting last in grid) + let area = nn; + if (this._useEntireRowArea(node, nn)) { + area = { x: 0, w: this.column, y: nn.y, h: nn.h }; + collide = this.collide(node, area, opt.skip); // force new hit + } + let didMove = false; + let newOpt = { nested: true, pack: false }; + while (collide = collide || this.collide(node, area, opt.skip)) { // could collide with more than 1 item... so repeat for each + let moved; + // if colliding with a locked item OR moving down with top gravity (and collide could move up) -> skip past the collide, + // but remember that skip down so we only do this once (and push others otherwise). + if (collide.locked || node._moving && !node._skipDown && nn.y > node.y && !this.float && + // can take space we had, or before where we're going + (!this.collide(collide, { ...collide, y: node.y }, node) || !this.collide(collide, { ...collide, y: nn.y - collide.h }, node))) { + node._skipDown = (node._skipDown || nn.y > node.y); + moved = this.moveNode(node, { ...nn, y: collide.y + collide.h, ...newOpt }); + if (collide.locked && moved) { + _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.copyPos(nn, node); // moving after lock become our new desired location + } + else if (!collide.locked && moved && opt.pack) { + // we moved after and will pack: do it now and keep the original drop location, but past the old collide to see what else we might push way + this._packNodes(); + nn.y = collide.y + collide.h; + _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.copyPos(node, nn); + } + didMove = didMove || moved; + } + else { + // move collide down *after* where we will be, ignoring where we are now (don't collide with us) + moved = this.moveNode(collide, { ...collide, y: nn.y + nn.h, skip: node, ...newOpt }); + } + if (!moved) { + return didMove; + } // break inf loop if we couldn't move after all (ex: maxRow, fixed) + collide = undefined; + } + return didMove; + } + /** return the nodes that intercept the given node. Optionally a different area can be used, as well as a second node to skip */ + collide(skip, area = skip, skip2) { + const skipId = skip._id; + const skip2Id = skip2?._id; + return this.nodes.find(n => n._id !== skipId && n._id !== skip2Id && _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.isIntercepted(n, area)); + } + collideAll(skip, area = skip, skip2) { + const skipId = skip._id; + const skip2Id = skip2?._id; + return this.nodes.filter(n => n._id !== skipId && n._id !== skip2Id && _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.isIntercepted(n, area)); + } + /** does a pixel coverage collision based on where we started, returning the node that has the most coverage that is >50% mid line */ + directionCollideCoverage(node, o, collides) { + if (!o.rect || !node._rect) + return; + let r0 = node._rect; // where started + let r = { ...o.rect }; // where we are + // update dragged rect to show where it's coming from (above or below, etc...) + if (r.y > r0.y) { + r.h += r.y - r0.y; + r.y = r0.y; + } + else { + r.h += r0.y - r.y; + } + if (r.x > r0.x) { + r.w += r.x - r0.x; + r.x = r0.x; + } + else { + r.w += r0.x - r.x; + } + let collide; + let overMax = 0.5; // need >50% + for (let n of collides) { + if (n.locked || !n._rect) { + break; + } + let r2 = n._rect; // overlapping target + let yOver = Number.MAX_VALUE, xOver = Number.MAX_VALUE; + // depending on which side we started from, compute the overlap % of coverage + // (ex: from above/below we only compute the max horizontal line coverage) + if (r0.y < r2.y) { // from above + yOver = ((r.y + r.h) - r2.y) / r2.h; + } + else if (r0.y + r0.h > r2.y + r2.h) { // from below + yOver = ((r2.y + r2.h) - r.y) / r2.h; + } + if (r0.x < r2.x) { // from the left + xOver = ((r.x + r.w) - r2.x) / r2.w; + } + else if (r0.x + r0.w > r2.x + r2.w) { // from the right + xOver = ((r2.x + r2.w) - r.x) / r2.w; + } + let over = Math.min(xOver, yOver); + if (over > overMax) { + overMax = over; + collide = n; + } + } + o.collide = collide; // save it so we don't have to find it again + return collide; + } + /** does a pixel coverage returning the node that has the most coverage by area */ + /* + protected collideCoverage(r: GridStackPosition, collides: GridStackNode[]): {collide: GridStackNode, over: number} { + let collide: GridStackNode; + let overMax = 0; + collides.forEach(n => { + if (n.locked || !n._rect) return; + let over = Utils.areaIntercept(r, n._rect); + if (over > overMax) { + overMax = over; + collide = n; + } + }); + return {collide, over: overMax}; + } + */ + /** called to cache the nodes pixel rectangles used for collision detection during drag */ + cacheRects(w, h, top, right, bottom, left) { + this.nodes.forEach(n => n._rect = { + y: n.y * h + top, + x: n.x * w + left, + w: n.w * w - left - right, + h: n.h * h - top - bottom + }); + return this; + } + /** called to possibly swap between 2 nodes (same size or column, not locked, touching), returning true if successful */ + swap(a, b) { + if (!b || b.locked || !a || a.locked) + return false; + function _doSwap() { + let x = b.x, y = b.y; + b.x = a.x; + b.y = a.y; // b -> a position + if (a.h != b.h) { + a.x = x; + a.y = b.y + b.h; // a -> goes after b + } + else if (a.w != b.w) { + a.x = b.x + b.w; + a.y = y; // a -> goes after b + } + else { + a.x = x; + a.y = y; // a -> old b position + } + a._dirty = b._dirty = true; + return true; + } + let touching; // remember if we called it (vs undefined) + // same size and same row or column, and touching + if (a.w === b.w && a.h === b.h && (a.x === b.x || a.y === b.y) && (touching = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.isTouching(a, b))) + return _doSwap(); + if (touching === false) + return; // IFF ran test and fail, bail out + // check for taking same columns (but different height) and touching + if (a.w === b.w && a.x === b.x && (touching || (touching = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.isTouching(a, b)))) { + if (b.y < a.y) { + let t = a; + a = b; + b = t; + } // swap a <-> b vars so a is first + return _doSwap(); + } + if (touching === false) + return; + // check if taking same row (but different width) and touching + if (a.h === b.h && a.y === b.y && (touching || (touching = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.isTouching(a, b)))) { + if (b.x < a.x) { + let t = a; + a = b; + b = t; + } // swap a <-> b vars so a is first + return _doSwap(); + } + return false; + } + isAreaEmpty(x, y, w, h) { + let nn = { x: x || 0, y: y || 0, w: w || 1, h: h || 1 }; + return !this.collide(nn); + } + /** re-layout grid items to reclaim any empty space - optionally keeping the sort order exactly the same ('list' mode) vs truly finding an empty spaces */ + compact(layout = 'compact', doSort = true) { + if (this.nodes.length === 0) + return this; + if (doSort) + this.sortNodes(); + const wasBatch = this.batchMode; + if (!wasBatch) + this.batchUpdate(); + const wasColumnResize = this._inColumnResize; + if (!wasColumnResize) + this._inColumnResize = true; // faster addNode() + let copyNodes = this.nodes; + this.nodes = []; // pretend we have no nodes to conflict layout to start with... + copyNodes.forEach((n, index, list) => { + let after; + if (!n.locked) { + n.autoPosition = true; + if (layout === 'list' && index) + after = list[index - 1]; + } + this.addNode(n, false, after); // 'false' for add event trigger + }); + if (!wasColumnResize) + delete this._inColumnResize; + if (!wasBatch) + this.batchUpdate(false); + return this; + } + /** enable/disable floating widgets (default: `false`) See [example](http://gridstackjs.com/demo/float.html) */ + set float(val) { + if (this._float === val) + return; + this._float = val || false; + if (!val) { + this._packNodes()._notify(); + } + } + /** float getter method */ + get float() { return this._float || false; } + /** sort the nodes array from first to last, or reverse. Called during collision/placement to force an order */ + sortNodes(dir = 1) { + this.nodes = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.sort(this.nodes, dir); + return this; + } + /** @internal called to top gravity pack the items back OR revert back to original Y positions when floating */ + _packNodes() { + if (this.batchMode) { + return this; + } + this.sortNodes(); // first to last + if (this.float) { + // restore original Y pos + this.nodes.forEach(n => { + if (n._updating || n._orig === undefined || n.y === n._orig.y) + return; + let newY = n.y; + while (newY > n._orig.y) { + --newY; + let collide = this.collide(n, { x: n.x, y: newY, w: n.w, h: n.h }); + if (!collide) { + n._dirty = true; + n.y = newY; + } + } + }); + } + else { + // top gravity pack + this.nodes.forEach((n, i) => { + if (n.locked) + return; + while (n.y > 0) { + let newY = i === 0 ? 0 : n.y - 1; + let canBeMoved = i === 0 || !this.collide(n, { x: n.x, y: newY, w: n.w, h: n.h }); + if (!canBeMoved) + break; + // Note: must be dirty (from last position) for GridStack::OnChange CB to update positions + // and move items back. The user 'change' CB should detect changes from the original + // starting position instead. + n._dirty = (n.y !== newY); + n.y = newY; + } + }); + } + return this; + } + /** + * given a random node, makes sure it's coordinates/values are valid in the current grid + * @param node to adjust + * @param resizing if out of bound, resize down or move into the grid to fit ? + */ + prepareNode(node, resizing) { + node._id = node._id ?? GridStackEngine._idSeq++; + // if we're missing position, have the grid position us automatically (before we set them to 0,0) + if (node.x === undefined || node.y === undefined || node.x === null || node.y === null) { + node.autoPosition = true; + } + // assign defaults for missing required fields + let defaults = { x: 0, y: 0, w: 1, h: 1 }; + _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.defaults(node, defaults); + if (!node.autoPosition) { + delete node.autoPosition; + } + if (!node.noResize) { + delete node.noResize; + } + if (!node.noMove) { + delete node.noMove; + } + _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.sanitizeMinMax(node); + // check for NaN (in case messed up strings were passed. can't do parseInt() || defaults.x above as 0 is valid #) + if (typeof node.x == 'string') { + node.x = Number(node.x); + } + if (typeof node.y == 'string') { + node.y = Number(node.y); + } + if (typeof node.w == 'string') { + node.w = Number(node.w); + } + if (typeof node.h == 'string') { + node.h = Number(node.h); + } + if (isNaN(node.x)) { + node.x = defaults.x; + node.autoPosition = true; + } + if (isNaN(node.y)) { + node.y = defaults.y; + node.autoPosition = true; + } + if (isNaN(node.w)) { + node.w = defaults.w; + } + if (isNaN(node.h)) { + node.h = defaults.h; + } + this.nodeBoundFix(node, resizing); + return node; + } + /** part2 of preparing a node to fit inside our grid - checks for x,y,w from grid dimensions */ + nodeBoundFix(node, resizing) { + let before = node._orig || _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.copyPos({}, node); + if (node.maxW) { + node.w = Math.min(node.w, node.maxW); + } + if (node.maxH) { + node.h = Math.min(node.h, node.maxH); + } + if (node.minW && node.minW <= this.column) { + node.w = Math.max(node.w, node.minW); + } + if (node.minH) { + node.h = Math.max(node.h, node.minH); + } + // if user loaded a larger than allowed widget for current # of columns, + // remember it's position & width so we can restore back (1 -> 12 column) #1655 #1985 + // IFF we're not in the middle of column resizing! + const saveOrig = (node.x || 0) + (node.w || 1) > this.column; + if (saveOrig && this.column < 12 && !this._inColumnResize && node._id && this.findCacheLayout(node, 12) === -1) { + let copy = { ...node }; // need _id + positions + if (copy.autoPosition || copy.x === undefined) { + delete copy.x; + delete copy.y; + } + else + copy.x = Math.min(11, copy.x); + copy.w = Math.min(12, copy.w || 1); + this.cacheOneLayout(copy, 12); + } + if (node.w > this.column) { + node.w = this.column; + } + else if (node.w < 1) { + node.w = 1; + } + if (this.maxRow && node.h > this.maxRow) { + node.h = this.maxRow; + } + else if (node.h < 1) { + node.h = 1; + } + if (node.x < 0) { + node.x = 0; + } + if (node.y < 0) { + node.y = 0; + } + if (node.x + node.w > this.column) { + if (resizing) { + node.w = this.column - node.x; + } + else { + node.x = this.column - node.w; + } + } + if (this.maxRow && node.y + node.h > this.maxRow) { + if (resizing) { + node.h = this.maxRow - node.y; + } + else { + node.y = this.maxRow - node.h; + } + } + if (!_utils__WEBPACK_IMPORTED_MODULE_0__.Utils.samePos(node, before)) { + node._dirty = true; + } + return this; + } + /** returns a list of modified nodes from their original values */ + getDirtyNodes(verify) { + // compare original x,y,w,h instead as _dirty can be a temporary state + if (verify) { + return this.nodes.filter(n => n._dirty && !_utils__WEBPACK_IMPORTED_MODULE_0__.Utils.samePos(n, n._orig)); + } + return this.nodes.filter(n => n._dirty); + } + /** @internal call this to call onChange callback with dirty nodes so DOM can be updated */ + _notify(removedNodes) { + if (this.batchMode || !this.onChange) + return this; + let dirtyNodes = (removedNodes || []).concat(this.getDirtyNodes()); + this.onChange(dirtyNodes); + return this; + } + /** @internal remove dirty and last tried info */ + cleanNodes() { + if (this.batchMode) + return this; + this.nodes.forEach(n => { + delete n._dirty; + delete n._lastTried; + }); + return this; + } + /** @internal called to save initial position/size to track real dirty state. + * Note: should be called right after we call change event (so next API is can detect changes) + * as well as right before we start move/resize/enter (so we can restore items to prev values) */ + saveInitial() { + this.nodes.forEach(n => { + n._orig = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.copyPos({}, n); + delete n._dirty; + }); + this._hasLocked = this.nodes.some(n => n.locked); + return this; + } + /** @internal restore all the nodes back to initial values (called when we leave) */ + restoreInitial() { + this.nodes.forEach(n => { + if (_utils__WEBPACK_IMPORTED_MODULE_0__.Utils.samePos(n, n._orig)) + return; + _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.copyPos(n, n._orig); + n._dirty = true; + }); + this._notify(); + return this; + } + /** find the first available empty spot for the given node width/height, updating the x,y attributes. return true if found. + * optionally you can pass your own existing node list and column count, otherwise defaults to that engine data. + * Optionally pass a widget to start search AFTER, meaning the order will remain the same but possibly have empty slots we skipped + */ + findEmptyPosition(node, nodeList = this.nodes, column = this.column, after) { + let start = after ? after.y * column + (after.x + after.w) : 0; + let found = false; + for (let i = start; !found; ++i) { + let x = i % column; + let y = Math.floor(i / column); + if (x + node.w > column) { + continue; + } + let box = { x, y, w: node.w, h: node.h }; + if (!nodeList.find(n => _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.isIntercepted(box, n))) { + if (node.x !== x || node.y !== y) + node._dirty = true; + node.x = x; + node.y = y; + delete node.autoPosition; + found = true; + } + } + return found; + } + /** call to add the given node to our list, fixing collision and re-packing */ + addNode(node, triggerAddEvent = false, after) { + let dup = this.nodes.find(n => n._id === node._id); + if (dup) + return dup; // prevent inserting twice! return it instead. + // skip prepareNode if we're in middle of column resize (not new) but do check for bounds! + this._inColumnResize ? this.nodeBoundFix(node) : this.prepareNode(node); + delete node._temporaryRemoved; + delete node._removeDOM; + let skipCollision; + if (node.autoPosition && this.findEmptyPosition(node, this.nodes, this.column, after)) { + delete node.autoPosition; // found our slot + skipCollision = true; + } + this.nodes.push(node); + if (triggerAddEvent) { + this.addedNodes.push(node); + } + if (!skipCollision) + this._fixCollisions(node); + if (!this.batchMode) { + this._packNodes()._notify(); + } + return node; + } + removeNode(node, removeDOM = true, triggerEvent = false) { + if (!this.nodes.find(n => n._id === node._id)) { + // TEST console.log(`Error: GridStackEngine.removeNode() node._id=${node._id} not found!`) + return this; + } + if (triggerEvent) { // we wait until final drop to manually track removed items (rather than during drag) + this.removedNodes.push(node); + } + if (removeDOM) + node._removeDOM = true; // let CB remove actual HTML (used to set _id to null, but then we loose layout info) + // don't use 'faster' .splice(findIndex(),1) in case node isn't in our list, or in multiple times. + this.nodes = this.nodes.filter(n => n._id !== node._id); + if (!node._isAboutToRemove) + this._packNodes(); // if dragged out, no need to relayout as already done... + this._notify([node]); + return this; + } + removeAll(removeDOM = true, triggerEvent = true) { + delete this._layouts; + if (!this.nodes.length) + return this; + removeDOM && this.nodes.forEach(n => n._removeDOM = true); // let CB remove actual HTML (used to set _id to null, but then we loose layout info) + const removedNodes = this.nodes; + this.removedNodes = triggerEvent ? removedNodes : []; + this.nodes = []; + return this._notify(removedNodes); + } + /** checks if item can be moved (layout constrain) vs moveNode(), returning true if was able to move. + * In more complicated cases (maxRow) it will attempt at moving the item and fixing + * others in a clone first, then apply those changes if still within specs. */ + moveNodeCheck(node, o) { + // if (node.locked) return false; + if (!this.changedPosConstrain(node, o)) + return false; + o.pack = true; + // simpler case: move item directly... + if (!this.maxRow) { + return this.moveNode(node, o); + } + // complex case: create a clone with NO maxRow (will check for out of bounds at the end) + let clonedNode; + let clone = new GridStackEngine({ + column: this.column, + float: this.float, + nodes: this.nodes.map(n => { + if (n._id === node._id) { + clonedNode = { ...n }; + return clonedNode; + } + return { ...n }; + }) + }); + if (!clonedNode) + return false; + // check if we're covering 50% collision and could move, while still being under maxRow or at least not making it worse + // (case where widget was somehow added past our max #2449) + let canMove = clone.moveNode(clonedNode, o) && clone.getRow() <= Math.max(this.getRow(), this.maxRow); + // else check if we can force a swap (float=true, or different shapes) on non-resize + if (!canMove && !o.resizing && o.collide) { + let collide = o.collide.el.gridstackNode; // find the source node the clone collided with at 50% + if (this.swap(node, collide)) { // swaps and mark dirty + this._notify(); + return true; + } + } + if (!canMove) + return false; + // if clone was able to move, copy those mods over to us now instead of caller trying to do this all over! + // Note: we can't use the list directly as elements and other parts point to actual node, so copy content + clone.nodes.filter(n => n._dirty).forEach(c => { + let n = this.nodes.find(a => a._id === c._id); + if (!n) + return; + _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.copyPos(n, c); + n._dirty = true; + }); + this._notify(); + return true; + } + /** return true if can fit in grid height constrain only (always true if no maxRow) */ + willItFit(node) { + delete node._willFitPos; + if (!this.maxRow) + return true; + // create a clone with NO maxRow and check if still within size + let clone = new GridStackEngine({ + column: this.column, + float: this.float, + nodes: this.nodes.map(n => { return { ...n }; }) + }); + let n = { ...node }; // clone node so we don't mod any settings on it but have full autoPosition and min/max as well! #1687 + this.cleanupNode(n); + delete n.el; + delete n._id; + delete n.content; + delete n.grid; + clone.addNode(n); + if (clone.getRow() <= this.maxRow) { + node._willFitPos = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.copyPos({}, n); + return true; + } + return false; + } + /** true if x,y or w,h are different after clamping to min/max */ + changedPosConstrain(node, p) { + // first make sure w,h are set for caller + p.w = p.w || node.w; + p.h = p.h || node.h; + if (node.x !== p.x || node.y !== p.y) + return true; + // check constrained w,h + if (node.maxW) { + p.w = Math.min(p.w, node.maxW); + } + if (node.maxH) { + p.h = Math.min(p.h, node.maxH); + } + if (node.minW) { + p.w = Math.max(p.w, node.minW); + } + if (node.minH) { + p.h = Math.max(p.h, node.minH); + } + return (node.w !== p.w || node.h !== p.h); + } + /** return true if the passed in node was actually moved (checks for no-op and locked) */ + moveNode(node, o) { + if (!node || /*node.locked ||*/ !o) + return false; + let wasUndefinedPack; + if (o.pack === undefined && !this.batchMode) { + wasUndefinedPack = o.pack = true; + } + // constrain the passed in values and check if we're still changing our node + if (typeof o.x !== 'number') { + o.x = node.x; + } + if (typeof o.y !== 'number') { + o.y = node.y; + } + if (typeof o.w !== 'number') { + o.w = node.w; + } + if (typeof o.h !== 'number') { + o.h = node.h; + } + let resizing = (node.w !== o.w || node.h !== o.h); + let nn = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.copyPos({}, node, true); // get min/max out first, then opt positions next + _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.copyPos(nn, o); + this.nodeBoundFix(nn, resizing); + _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.copyPos(o, nn); + if (!o.forceCollide && _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.samePos(node, o)) + return false; + let prevPos = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.copyPos({}, node); + // check if we will need to fix collision at our new location + let collides = this.collideAll(node, nn, o.skip); + let needToMove = true; + if (collides.length) { + let activeDrag = node._moving && !o.nested; + // check to make sure we actually collided over 50% surface area while dragging + let collide = activeDrag ? this.directionCollideCoverage(node, o, collides) : collides[0]; + // if we're enabling creation of sub-grids on the fly, see if we're covering 80% of either one, if we didn't already do that + if (activeDrag && collide && node.grid?.opts?.subGridDynamic && !node.grid._isTemp) { + let over = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.areaIntercept(o.rect, collide._rect); + let a1 = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.area(o.rect); + let a2 = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.area(collide._rect); + let perc = over / (a1 < a2 ? a1 : a2); + if (perc > .8) { + collide.grid.makeSubGrid(collide.el, undefined, node); + collide = undefined; + } + } + if (collide) { + needToMove = !this._fixCollisions(node, nn, collide, o); // check if already moved... + } + else { + needToMove = false; // we didn't cover >50% for a move, skip... + if (wasUndefinedPack) + delete o.pack; + } + } + // now move (to the original ask vs the collision version which might differ) and repack things + if (needToMove) { + node._dirty = true; + _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.copyPos(node, nn); + } + if (o.pack) { + this._packNodes() + ._notify(); + } + return !_utils__WEBPACK_IMPORTED_MODULE_0__.Utils.samePos(node, prevPos); // pack might have moved things back + } + getRow() { + return this.nodes.reduce((row, n) => Math.max(row, n.y + n.h), 0); + } + beginUpdate(node) { + if (!node._updating) { + node._updating = true; + delete node._skipDown; + if (!this.batchMode) + this.saveInitial(); + } + return this; + } + endUpdate() { + let n = this.nodes.find(n => n._updating); + if (n) { + delete n._updating; + delete n._skipDown; + } + return this; + } + /** saves a copy of the largest column layout (eg 12 even when rendering oneColumnMode) so we don't loose orig layout, + * returning a list of widgets for serialization */ + save(saveElement = true, saveCB) { + // use the highest layout for any saved info so we can have full detail on reload #1849 + let len = this._layouts?.length; + let layout = len && this.column !== (len - 1) ? this._layouts[len - 1] : null; + let list = []; + this.sortNodes(); + this.nodes.forEach(n => { + let wl = layout?.find(l => l._id === n._id); + // use layout info fields instead if set + let w = { ...n, ...(wl || {}) }; + _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.removeInternalForSave(w, !saveElement); + if (saveCB) + saveCB(n, w); + list.push(w); + }); + return list; + } + /** @internal called whenever a node is added or moved - updates the cached layouts */ + layoutsNodesChange(nodes) { + if (!this._layouts || this._inColumnResize) + return this; + // remove smaller layouts - we will re-generate those on the fly... larger ones need to update + this._layouts.forEach((layout, column) => { + if (!layout || column === this.column) + return this; + if (column < this.column) { + this._layouts[column] = undefined; + } + else { + // we save the original x,y,w (h isn't cached) to see what actually changed to propagate better. + // NOTE: we don't need to check against out of bound scaling/moving as that will be done when using those cache values. #1785 + let ratio = column / this.column; + nodes.forEach(node => { + if (!node._orig) + return; // didn't change (newly added ?) + let n = layout.find(l => l._id === node._id); + if (!n) + return; // no cache for new nodes. Will use those values. + // Y changed, push down same amount + // TODO: detect doing item 'swaps' will help instead of move (especially in 1 column mode) + if (n.y >= 0 && node.y !== node._orig.y) { + n.y += (node.y - node._orig.y); + } + // X changed, scale from new position + if (node.x !== node._orig.x) { + n.x = Math.round(node.x * ratio); + } + // width changed, scale from new width + if (node.w !== node._orig.w) { + n.w = Math.round(node.w * ratio); + } + // ...height always carries over from cache + }); + } + }); + return this; + } + /** + * @internal Called to scale the widget width & position up/down based on the column change. + * Note we store previous layouts (especially original ones) to make it possible to go + * from say 12 -> 1 -> 12 and get back to where we were. + * + * @param prevColumn previous number of columns + * @param column new column number + * @param layout specify the type of re-layout that will happen (position, size, etc...). + * Note: items will never be outside of the current column boundaries. default (moveScale). Ignored for 1 column + */ + columnChanged(prevColumn, column, layout = 'moveScale') { + if (!this.nodes.length || !column || prevColumn === column) + return this; + // in this mode no layout is done whatsoever, up to the caller to handle it + if (layout === 'none') + return this; + // simpler shortcuts layouts + const doCompact = layout === 'compact' || layout === 'list'; + if (doCompact) { + this.sortNodes(1); // sort with original layout once and only once (new column will affect order otherwise) + } + // cache the current layout in case they want to go back (like 12 -> 1 -> 12) as it requires original data IFF we're sizing down (see below) + if (column < prevColumn) + this.cacheLayout(this.nodes, prevColumn); + this.batchUpdate(); // do this EARLY as it will call saveInitial() so we can detect where we started for _dirty and collision + let newNodes = []; + let nodes = doCompact ? this.nodes : _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.sort(this.nodes, -1); // current column reverse sorting so we can insert last to front (limit collision) + // see if we have cached previous layout IFF we are going up in size (restore) otherwise always + // generate next size down from where we are (looks more natural as you gradually size down). + if (column > prevColumn && this._layouts) { + const cacheNodes = this._layouts[column] || []; + // ...if not, start with the largest layout (if not already there) as down-scaling is more accurate + // by pretending we came from that larger column by assigning those values as starting point + let lastIndex = this._layouts.length - 1; + if (!cacheNodes.length && prevColumn !== lastIndex && this._layouts[lastIndex]?.length) { + prevColumn = lastIndex; + this._layouts[lastIndex].forEach(cacheNode => { + let n = nodes.find(n => n._id === cacheNode._id); + if (n) { + // still current, use cache info positions + if (!doCompact && !cacheNode.autoPosition) { + n.x = cacheNode.x ?? n.x; + n.y = cacheNode.y ?? n.y; + } + n.w = cacheNode.w ?? n.w; + if (cacheNode.x == undefined || cacheNode.y === undefined) + n.autoPosition = true; + } + }); + } + // if we found cache re-use those nodes that are still current + cacheNodes.forEach(cacheNode => { + let j = nodes.findIndex(n => n._id === cacheNode._id); + if (j !== -1) { + const n = nodes[j]; + // still current, use cache info positions + if (doCompact) { + n.w = cacheNode.w; // only w is used, and don't trim the list + return; + } + if (cacheNode.autoPosition || isNaN(cacheNode.x) || isNaN(cacheNode.y)) { + this.findEmptyPosition(cacheNode, newNodes); + } + if (!cacheNode.autoPosition) { + n.x = cacheNode.x ?? n.x; + n.y = cacheNode.y ?? n.y; + n.w = cacheNode.w ?? n.w; + newNodes.push(n); + } + nodes.splice(j, 1); + } + }); + } + // much simpler layout that just compacts + if (doCompact) { + this.compact(layout, false); + } + else { + // ...and add any extra non-cached ones + if (nodes.length) { + if (typeof layout === 'function') { + layout(column, prevColumn, newNodes, nodes); + } + else { + let ratio = doCompact ? 1 : column / prevColumn; + let move = (layout === 'move' || layout === 'moveScale'); + let scale = (layout === 'scale' || layout === 'moveScale'); + nodes.forEach(node => { + // NOTE: x + w could be outside of the grid, but addNode() below will handle that + node.x = (column === 1 ? 0 : (move ? Math.round(node.x * ratio) : Math.min(node.x, column - 1))); + node.w = ((column === 1 || prevColumn === 1) ? 1 : scale ? (Math.round(node.w * ratio) || 1) : (Math.min(node.w, column))); + newNodes.push(node); + }); + nodes = []; + } + } + // finally re-layout them in reverse order (to get correct placement) + newNodes = _utils__WEBPACK_IMPORTED_MODULE_0__.Utils.sort(newNodes, -1); + this._inColumnResize = true; // prevent cache update + this.nodes = []; // pretend we have no nodes to start with (add() will use same structures) to simplify layout + newNodes.forEach(node => { + this.addNode(node, false); // 'false' for add event trigger + delete node._orig; // make sure the commit doesn't try to restore things back to original + }); + } + this.nodes.forEach(n => delete n._orig); // clear _orig before batch=false so it doesn't handle float=true restore + this.batchUpdate(false, !doCompact); + delete this._inColumnResize; + return this; + } + /** + * call to cache the given layout internally to the given location so we can restore back when column changes size + * @param nodes list of nodes + * @param column corresponding column index to save it under + * @param clear if true, will force other caches to be removed (default false) + */ + cacheLayout(nodes, column, clear = false) { + let copy = []; + nodes.forEach((n, i) => { + // make sure we have an id in case this is new layout, else re-use id already set + if (n._id === undefined) { + const existing = n.id ? this.nodes.find(n2 => n2.id === n.id) : undefined; // find existing node using users id + n._id = existing?._id ?? GridStackEngine._idSeq++; + } + copy[i] = { x: n.x, y: n.y, w: n.w, _id: n._id }; // only thing we change is x,y,w and id to find it back + }); + this._layouts = clear ? [] : this._layouts || []; // use array to find larger quick + this._layouts[column] = copy; + return this; + } + /** + * call to cache the given node layout internally to the given location so we can restore back when column changes size + * @param node single node to cache + * @param column corresponding column index to save it under + */ + cacheOneLayout(n, column) { + n._id = n._id ?? GridStackEngine._idSeq++; + let l = { x: n.x, y: n.y, w: n.w, _id: n._id }; + if (n.autoPosition || n.x === undefined) { + delete l.x; + delete l.y; + if (n.autoPosition) + l.autoPosition = true; + } + this._layouts = this._layouts || []; + this._layouts[column] = this._layouts[column] || []; + let index = this.findCacheLayout(n, column); + if (index === -1) + this._layouts[column].push(l); + else + this._layouts[column][index] = l; + return this; + } + findCacheLayout(n, column) { + return this._layouts?.[column]?.findIndex(l => l._id === n._id) ?? -1; + } + removeNodeFromLayoutCache(n) { + if (!this._layouts) { + return; + } + for (let i = 0; i < this._layouts.length; i++) { + let index = this.findCacheLayout(n, i); + if (index !== -1) { + this._layouts[i].splice(index, 1); + } + } + } + /** called to remove all internal values but the _id */ + cleanupNode(node) { + for (let prop in node) { + if (prop[0] === '_' && prop !== '_id') + delete node[prop]; + } + return this; + } +} +/** @internal unique global internal _id counter */ +GridStackEngine._idSeq = 0; + +//# sourceMappingURL=gridstack-engine.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/gridstack.js": +/*!**************************************************!*\ + !*** ./node_modules/gridstack/dist/gridstack.js ***! + \**************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ DDGridStack: () => (/* reexport safe */ _dd_gridstack__WEBPACK_IMPORTED_MODULE_3__.DDGridStack), +/* harmony export */ GridStack: () => (/* binding */ GridStack), +/* harmony export */ GridStackEngine: () => (/* reexport safe */ _gridstack_engine__WEBPACK_IMPORTED_MODULE_0__.GridStackEngine), +/* harmony export */ Utils: () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_1__.Utils), +/* harmony export */ dragInDefaultOptions: () => (/* reexport safe */ _types__WEBPACK_IMPORTED_MODULE_2__.dragInDefaultOptions), +/* harmony export */ gridDefaults: () => (/* reexport safe */ _types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults), +/* harmony export */ obsolete: () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_1__.obsolete), +/* harmony export */ obsoleteAttr: () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_1__.obsoleteAttr), +/* harmony export */ obsoleteOpts: () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_1__.obsoleteOpts), +/* harmony export */ obsoleteOptsDel: () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_1__.obsoleteOptsDel) +/* harmony export */ }); +/* harmony import */ var _gridstack_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./gridstack-engine */ "./node_modules/gridstack/dist/gridstack-engine.js"); +/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils */ "./node_modules/gridstack/dist/utils.js"); +/* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./types */ "./node_modules/gridstack/dist/types.js"); +/* harmony import */ var _dd_gridstack__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./dd-gridstack */ "./node_modules/gridstack/dist/dd-gridstack.js"); +/* harmony import */ var _dd_touch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./dd-touch */ "./node_modules/gridstack/dist/dd-touch.js"); +/* harmony import */ var _dd_manager__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./dd-manager */ "./node_modules/gridstack/dist/dd-manager.js"); +/*! + * GridStack 10.1.2 + * https://gridstackjs.com/ + * + * Copyright (c) 2021-2022 Alain Dumesny + * see root license https://github.com/gridstack/gridstack.js/tree/master/LICENSE + */ + + + +/* + * and include D&D by default + * TODO: while we could generate a gridstack-static.js at smaller size - saves about 31k (41k -> 72k) + * I don't know how to generate the DD only code at the remaining 31k to delay load as code depends on Gridstack.ts + * also it caused loading issues in prod - see https://github.com/gridstack/gridstack.js/issues/2039 + */ + + + +const dd = new _dd_gridstack__WEBPACK_IMPORTED_MODULE_3__.DDGridStack; +// export all dependent file as well to make it easier for users to just import the main file + + + + +/** + * Main gridstack class - you will need to call `GridStack.init()` first to initialize your grid. + * Note: your grid elements MUST have the following classes for the CSS layout to work: + * @example + *
+ *
+ *
Item 1
+ *
+ *
+ */ +class GridStack { + /** + * initializing the HTML element, or selector string, into a grid will return the grid. Calling it again will + * simply return the existing instance (ignore any passed options). There is also an initAll() version that support + * multiple grids initialization at once. Or you can use addGrid() to create the entire grid from JSON. + * @param options grid options (optional) + * @param elOrString element or CSS selector (first one used) to convert to a grid (default to '.grid-stack' class selector) + * + * @example + * let grid = GridStack.init(); + * + * Note: the HTMLElement (of type GridHTMLElement) will store a `gridstack: GridStack` value that can be retrieve later + * let grid = document.querySelector('.grid-stack').gridstack; + */ + static init(options = {}, elOrString = '.grid-stack') { + if (typeof document === 'undefined') + return null; // temp workaround SSR + let el = GridStack.getGridElement(elOrString); + if (!el) { + if (typeof elOrString === 'string') { + console.error('GridStack.initAll() no grid was found with selector "' + elOrString + '" - element missing or wrong selector ?' + + '\nNote: ".grid-stack" is required for proper CSS styling and drag/drop, and is the default selector.'); + } + else { + console.error('GridStack.init() no grid element was passed.'); + } + return null; + } + if (!el.gridstack) { + el.gridstack = new GridStack(el, _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.cloneDeep(options)); + } + return el.gridstack; + } + /** + * Will initialize a list of elements (given a selector) and return an array of grids. + * @param options grid options (optional) + * @param selector elements selector to convert to grids (default to '.grid-stack' class selector) + * + * @example + * let grids = GridStack.initAll(); + * grids.forEach(...) + */ + static initAll(options = {}, selector = '.grid-stack') { + let grids = []; + if (typeof document === 'undefined') + return grids; // temp workaround SSR + GridStack.getGridElements(selector).forEach(el => { + if (!el.gridstack) { + el.gridstack = new GridStack(el, _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.cloneDeep(options)); + } + grids.push(el.gridstack); + }); + if (grids.length === 0) { + console.error('GridStack.initAll() no grid was found with selector "' + selector + '" - element missing or wrong selector ?' + + '\nNote: ".grid-stack" is required for proper CSS styling and drag/drop, and is the default selector.'); + } + return grids; + } + /** + * call to create a grid with the given options, including loading any children from JSON structure. This will call GridStack.init(), then + * grid.load() on any passed children (recursively). Great alternative to calling init() if you want entire grid to come from + * JSON serialized data, including options. + * @param parent HTML element parent to the grid + * @param opt grids options used to initialize the grid, and list of children + */ + static addGrid(parent, opt = {}) { + if (!parent) + return null; + let el = parent; + if (el.gridstack) { + // already a grid - set option and load data + const grid = el.gridstack; + if (opt) + grid.opts = { ...grid.opts, ...opt }; + if (opt.children !== undefined) + grid.load(opt.children); + return grid; + } + // create the grid element, but check if the passed 'parent' already has grid styling and should be used instead + const parentIsGrid = parent.classList.contains('grid-stack'); + if (!parentIsGrid || GridStack.addRemoveCB) { + if (GridStack.addRemoveCB) { + el = GridStack.addRemoveCB(parent, opt, true, true); + } + else { + let doc = document.implementation.createHTMLDocument(''); // IE needs a param + doc.body.innerHTML = `
`; + el = doc.body.children[0]; + parent.appendChild(el); + } + } + // create grid class and load any children + let grid = GridStack.init(opt, el); + return grid; + } + /** call this method to register your engine instead of the default one. + * See instead `GridStackOptions.engineClass` if you only need to + * replace just one instance. + */ + static registerEngine(engineClass) { + GridStack.engineClass = engineClass; + } + /** @internal create placeholder DIV as needed */ + get placeholder() { + if (!this._placeholder) { + let placeholderChild = document.createElement('div'); // child so padding match item-content + placeholderChild.className = 'placeholder-content'; + if (this.opts.placeholderText) { + placeholderChild.innerHTML = this.opts.placeholderText; + } + this._placeholder = document.createElement('div'); + this._placeholder.classList.add(this.opts.placeholderClass, _types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults.itemClass, this.opts.itemClass); + this.placeholder.appendChild(placeholderChild); + } + return this._placeholder; + } + /** + * Construct a grid item from the given element and options + * @param el the HTML element tied to this grid after it's been initialized + * @param opts grid options - public for classes to access, but use methods to modify! + */ + constructor(el, opts = {}) { + this.el = el; + this.opts = opts; + /** @internal */ + this._gsEventHandler = {}; + /** @internal extra row added when dragging at the bottom of the grid */ + this._extraDragRow = 0; + /** @internal meant to store the scale of the active grid */ + this.dragTransform = { xScale: 1, yScale: 1, xOffset: 0, yOffset: 0 }; + el.gridstack = this; + opts = opts || {}; // handles null/undefined/0 + if (!el.classList.contains('grid-stack')) { + this.el.classList.add('grid-stack'); + } + // if row property exists, replace minRow and maxRow instead + if (opts.row) { + opts.minRow = opts.maxRow = opts.row; + delete opts.row; + } + let rowAttr = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-row')); + // flag only valid in sub-grids (handled by parent, not here) + if (opts.column === 'auto') { + delete opts.column; + } + // save original setting so we can restore on save + if (opts.alwaysShowResizeHandle !== undefined) { + opts._alwaysShowResizeHandle = opts.alwaysShowResizeHandle; + } + let bk = opts.columnOpts?.breakpoints; + // LEGACY: oneColumnMode stuff changed in v10.x - check if user explicitly set something to convert over + const oldOpts = opts; + if (oldOpts.oneColumnModeDomSort) { + delete oldOpts.oneColumnModeDomSort; + console.log('warning: Gridstack oneColumnModeDomSort no longer supported. Use GridStackOptions.columnOpts instead.'); + } + if (oldOpts.oneColumnSize || oldOpts.disableOneColumnMode === false) { + const oneSize = oldOpts.oneColumnSize || 768; + delete oldOpts.oneColumnSize; + delete oldOpts.disableOneColumnMode; + opts.columnOpts = opts.columnOpts || {}; + bk = opts.columnOpts.breakpoints = opts.columnOpts.breakpoints || []; + let oneColumn = bk.find(b => b.c === 1); + if (!oneColumn) { + oneColumn = { c: 1, w: oneSize }; + bk.push(oneColumn, { c: 12, w: oneSize + 1 }); + } + else + oneColumn.w = oneSize; + } + //...end LEGACY + // cleanup responsive opts (must have columnWidth | breakpoints) then sort breakpoints by size (so we can match during resize) + const resp = opts.columnOpts; + if (resp) { + if (!resp.columnWidth && !resp.breakpoints?.length) { + delete opts.columnOpts; + bk = undefined; + } + else { + resp.columnMax = resp.columnMax || 12; + } + } + if (bk?.length > 1) + bk.sort((a, b) => (b.w || 0) - (a.w || 0)); + // elements DOM attributes override any passed options (like CSS style) - merge the two together + let defaults = { + ..._utils__WEBPACK_IMPORTED_MODULE_1__.Utils.cloneDeep(_types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults), + column: _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-column')) || _types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults.column, + minRow: rowAttr ? rowAttr : _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-min-row')) || _types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults.minRow, + maxRow: rowAttr ? rowAttr : _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-max-row')) || _types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults.maxRow, + staticGrid: _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toBool(el.getAttribute('gs-static')) || _types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults.staticGrid, + draggable: { + handle: (opts.handleClass ? '.' + opts.handleClass : (opts.handle ? opts.handle : '')) || _types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults.draggable.handle, + }, + removableOptions: { + accept: opts.itemClass || _types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults.removableOptions.accept, + decline: _types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults.removableOptions.decline + }, + }; + if (el.getAttribute('gs-animate')) { // default to true, but if set to false use that instead + defaults.animate = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toBool(el.getAttribute('gs-animate')); + } + opts = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.defaults(opts, defaults); + this._initMargin(); // part of settings defaults... + // Now check if we're loading into 1 column mode FIRST so we don't do un-necessary work (like cellHeight = width / 12 then go 1 column) + this.checkDynamicColumn(); + this.el.classList.add('gs-' + opts.column); + if (opts.rtl === 'auto') { + opts.rtl = (el.style.direction === 'rtl'); + } + if (opts.rtl) { + this.el.classList.add('grid-stack-rtl'); + } + // check if we're been nested, and if so update our style and keep pointer around (used during save) + const grandParent = this.el.parentElement?.parentElement; + let parentGridItem = grandParent?.classList.contains(_types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults.itemClass) ? grandParent.gridstackNode : undefined; + if (parentGridItem) { + parentGridItem.subGrid = this; + this.parentGridItem = parentGridItem; + this.el.classList.add('grid-stack-nested'); + parentGridItem.el.classList.add('grid-stack-sub-grid'); + } + this._isAutoCellHeight = (opts.cellHeight === 'auto'); + if (this._isAutoCellHeight || opts.cellHeight === 'initial') { + // make the cell content square initially (will use resize/column event to keep it square) + this.cellHeight(undefined, false); + } + else { + // append unit if any are set + if (typeof opts.cellHeight == 'number' && opts.cellHeightUnit && opts.cellHeightUnit !== _types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults.cellHeightUnit) { + opts.cellHeight = opts.cellHeight + opts.cellHeightUnit; + delete opts.cellHeightUnit; + } + this.cellHeight(opts.cellHeight, false); + } + // see if we need to adjust auto-hide + if (opts.alwaysShowResizeHandle === 'mobile') { + opts.alwaysShowResizeHandle = _dd_touch__WEBPACK_IMPORTED_MODULE_4__.isTouch; + } + this._styleSheetClass = 'gs-id-' + _gridstack_engine__WEBPACK_IMPORTED_MODULE_0__.GridStackEngine._idSeq++; + this.el.classList.add(this._styleSheetClass); + this._setStaticClass(); + let engineClass = opts.engineClass || GridStack.engineClass || _gridstack_engine__WEBPACK_IMPORTED_MODULE_0__.GridStackEngine; + this.engine = new engineClass({ + column: this.getColumn(), + float: opts.float, + maxRow: opts.maxRow, + onChange: (cbNodes) => { + let maxH = 0; + this.engine.nodes.forEach(n => { maxH = Math.max(maxH, n.y + n.h); }); + cbNodes.forEach(n => { + let el = n.el; + if (!el) + return; + if (n._removeDOM) { + if (el) + el.remove(); + delete n._removeDOM; + } + else { + this._writePosAttr(el, n); + } + }); + this._updateStyles(false, maxH); // false = don't recreate, just append if need be + } + }); + // create initial global styles BEFORE loading children so resizeToContent margin can be calculated correctly + this._updateStyles(false, 0); + if (opts.auto) { + this.batchUpdate(); // prevent in between re-layout #1535 TODO: this only set float=true, need to prevent collision check... + this.getGridItems().forEach(el => this._prepareElement(el)); + this.batchUpdate(false); + } + // load any passed in children as well, which overrides any DOM layout done above + if (opts.children) { + let children = opts.children; + delete opts.children; + if (children.length) + this.load(children); // don't load empty + } + // if (this.engine.nodes.length) this._updateStyles(); // update based on # of children. done in engine onChange CB + this.setAnimation(opts.animate); + // dynamic grids require pausing during drag to detect over to nest vs push + if (opts.subGridDynamic && !_dd_manager__WEBPACK_IMPORTED_MODULE_5__.DDManager.pauseDrag) + _dd_manager__WEBPACK_IMPORTED_MODULE_5__.DDManager.pauseDrag = true; + if (opts.draggable?.pause !== undefined) + _dd_manager__WEBPACK_IMPORTED_MODULE_5__.DDManager.pauseDrag = opts.draggable.pause; + this._setupRemoveDrop(); + this._setupAcceptWidget(); + this._updateResizeEvent(); + } + /** + * add a new widget and returns it. + * + * Widget will be always placed even if result height is more than actual grid height. + * You need to use `willItFit()` before calling addWidget for additional check. + * See also `makeWidget()`. + * + * @example + * let grid = GridStack.init(); + * grid.addWidget({w: 3, content: 'hello'}); + * grid.addWidget('
hello
', {w: 3}); + * + * @param el GridStackWidget (which can have content string as well), html element, or string definition to add + * @param options widget position/size options (optional, and ignore if first param is already option) - see GridStackWidget + */ + addWidget(els, options) { + function isGridStackWidget(w) { + return w.el !== undefined || w.x !== undefined || w.y !== undefined || w.w !== undefined || w.h !== undefined || w.content !== undefined ? true : false; + } + let el; + let node; + if (typeof els === 'string') { + let doc = document.implementation.createHTMLDocument(''); // IE needs a param + doc.body.innerHTML = els; + el = doc.body.children[0]; + } + else if (arguments.length === 0 || arguments.length === 1 && isGridStackWidget(els)) { + node = options = els; + if (node?.el) { + el = node.el; // re-use element stored in the node + } + else if (GridStack.addRemoveCB) { + el = GridStack.addRemoveCB(this.el, options, true, false); + } + else { + let content = options?.content || ''; + let doc = document.implementation.createHTMLDocument(''); // IE needs a param + doc.body.innerHTML = `
${content}
`; + el = doc.body.children[0]; + } + } + else { + el = els; + } + if (!el) + return; + // if the caller ended up initializing the widget in addRemoveCB, or we stared with one already, skip the rest + node = el.gridstackNode; + if (node && el.parentElement === this.el && this.engine.nodes.find(n => n._id === node._id)) + return el; + // Tempting to initialize the passed in opt with default and valid values, but this break knockout demos + // as the actual value are filled in when _prepareElement() calls el.getAttribute('gs-xyz') before adding the node. + // So make sure we load any DOM attributes that are not specified in passed in options (which override) + let domAttr = this._readAttr(el); + options = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.cloneDeep(options) || {}; // make a copy before we modify in case caller re-uses it + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.defaults(options, domAttr); + node = this.engine.prepareNode(options); + this._writeAttr(el, options); + if (this._insertNotAppend) { + this.el.prepend(el); + } + else { + this.el.appendChild(el); + } + this.makeWidget(el, options); + return el; + } + /** + * Convert an existing gridItem element into a sub-grid with the given (optional) options, else inherit them + * from the parent's subGrid options. + * @param el gridItem element to convert + * @param ops (optional) sub-grid options, else default to node, then parent settings, else defaults + * @param nodeToAdd (optional) node to add to the newly created sub grid (used when dragging over existing regular item) + * @param saveContent if true (default) the html inside .grid-stack-content will be saved to child widget + * @returns newly created grid + */ + makeSubGrid(el, ops, nodeToAdd, saveContent = true) { + let node = el.gridstackNode; + if (!node) { + node = this.makeWidget(el).gridstackNode; + } + if (node.subGrid?.el) + return node.subGrid; // already done + // find the template subGrid stored on a parent as fallback... + let subGridTemplate; // eslint-disable-next-line @typescript-eslint/no-this-alias + let grid = this; + while (grid && !subGridTemplate) { + subGridTemplate = grid.opts?.subGridOpts; + grid = grid.parentGridItem?.grid; + } + //... and set the create options + ops = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.cloneDeep({ ...(subGridTemplate || {}), children: undefined, ...(ops || node.subGridOpts || {}) }); + node.subGridOpts = ops; + // if column special case it set, remember that flag and set default + let autoColumn; + if (ops.column === 'auto') { + autoColumn = true; + ops.column = Math.max(node.w || 1, nodeToAdd?.w || 1); + delete ops.columnOpts; // driven by parent + } + // if we're converting an existing full item, move over the content to be the first sub item in the new grid + let content = node.el.querySelector('.grid-stack-item-content'); + let newItem; + let newItemOpt; + if (saveContent) { + this._removeDD(node.el); // remove D&D since it's set on content div + newItemOpt = { ...node, x: 0, y: 0 }; + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.removeInternalForSave(newItemOpt); + delete newItemOpt.subGridOpts; + if (node.content) { + newItemOpt.content = node.content; + delete node.content; + } + if (GridStack.addRemoveCB) { + newItem = GridStack.addRemoveCB(this.el, newItemOpt, true, false); + } + else { + let doc = document.implementation.createHTMLDocument(''); // IE needs a param + doc.body.innerHTML = `
`; + newItem = doc.body.children[0]; + newItem.appendChild(content); + doc.body.innerHTML = `
`; + content = doc.body.children[0]; + node.el.appendChild(content); + } + this._prepareDragDropByNode(node); // ... and restore original D&D + } + // if we're adding an additional item, make the container large enough to have them both + if (nodeToAdd) { + let w = autoColumn ? ops.column : node.w; + let h = node.h + nodeToAdd.h; + let style = node.el.style; + style.transition = 'none'; // show up instantly so we don't see scrollbar with nodeToAdd + this.update(node.el, { w, h }); + setTimeout(() => style.transition = null); // recover animation + } + let subGrid = node.subGrid = GridStack.addGrid(content, ops); + if (nodeToAdd?._moving) + subGrid._isTemp = true; // prevent re-nesting as we add over + if (autoColumn) + subGrid._autoColumn = true; + // add the original content back as a child of hte newly created grid + if (saveContent) { + subGrid.addWidget(newItem, newItemOpt); + } + // now add any additional node + if (nodeToAdd) { + if (nodeToAdd._moving) { + // create an artificial event even for the just created grid to receive this item + window.setTimeout(() => _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.simulateMouseEvent(nodeToAdd._event, 'mouseenter', subGrid.el), 0); + } + else { + subGrid.addWidget(node.el, node); + } + } + return subGrid; + } + /** + * called when an item was converted into a nested grid to accommodate a dragged over item, but then item leaves - return back + * to the original grid-item. Also called to remove empty sub-grids when last item is dragged out (since re-creating is simple) + */ + removeAsSubGrid(nodeThatRemoved) { + let pGrid = this.parentGridItem?.grid; + if (!pGrid) + return; + pGrid.batchUpdate(); + pGrid.removeWidget(this.parentGridItem.el, true, true); + this.engine.nodes.forEach(n => { + // migrate any children over and offsetting by our location + n.x += this.parentGridItem.x; + n.y += this.parentGridItem.y; + pGrid.addWidget(n.el, n); + }); + pGrid.batchUpdate(false); + if (this.parentGridItem) + delete this.parentGridItem.subGrid; + delete this.parentGridItem; + // create an artificial event for the original grid now that this one is gone (got a leave, but won't get enter) + if (nodeThatRemoved) { + window.setTimeout(() => _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.simulateMouseEvent(nodeThatRemoved._event, 'mouseenter', pGrid.el), 0); + } + } + /** + * saves the current layout returning a list of widgets for serialization which might include any nested grids. + * @param saveContent if true (default) the latest html inside .grid-stack-content will be saved to GridStackWidget.content field, else it will + * be removed. + * @param saveGridOpt if true (default false), save the grid options itself, so you can call the new GridStack.addGrid() + * to recreate everything from scratch. GridStackOptions.children would then contain the widget list instead. + * @param saveCB callback for each node -> widget, so application can insert additional data to be saved into the widget data structure. + * @returns list of widgets or full grid option, including .children list of widgets + */ + save(saveContent = true, saveGridOpt = false, saveCB = GridStack.saveCB) { + // return copied GridStackWidget (with optionally .el) we can modify at will... + let list = this.engine.save(saveContent, saveCB); + // check for HTML content and nested grids + list.forEach(n => { + if (saveContent && n.el && !n.subGrid && !saveCB) { // sub-grid are saved differently, not plain content + let sub = n.el.querySelector('.grid-stack-item-content'); + n.content = sub ? sub.innerHTML : undefined; + if (!n.content) + delete n.content; + } + else { + if (!saveContent && !saveCB) { + delete n.content; + } + // check for nested grid + if (n.subGrid?.el) { + const listOrOpt = n.subGrid.save(saveContent, saveGridOpt, saveCB); + n.subGridOpts = (saveGridOpt ? listOrOpt : { children: listOrOpt }); + delete n.subGrid; + } + } + delete n.el; + }); + // check if save entire grid options (needed for recursive) + children... + if (saveGridOpt) { + let o = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.cloneDeep(this.opts); + // delete default values that will be recreated on launch + if (o.marginBottom === o.marginTop && o.marginRight === o.marginLeft && o.marginTop === o.marginRight) { + o.margin = o.marginTop; + delete o.marginTop; + delete o.marginRight; + delete o.marginBottom; + delete o.marginLeft; + } + if (o.rtl === (this.el.style.direction === 'rtl')) { + o.rtl = 'auto'; + } + if (this._isAutoCellHeight) { + o.cellHeight = 'auto'; + } + if (this._autoColumn) { + o.column = 'auto'; + } + const origShow = o._alwaysShowResizeHandle; + delete o._alwaysShowResizeHandle; + if (origShow !== undefined) { + o.alwaysShowResizeHandle = origShow; + } + else { + delete o.alwaysShowResizeHandle; + } + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.removeInternalAndSame(o, _types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults); + o.children = list; + return o; + } + return list; + } + /** + * load the widgets from a list. This will call update() on each (matching by id) or add/remove widgets that are not there. + * + * @param layout list of widgets definition to update/create + * @param addAndRemove boolean (default true) or callback method can be passed to control if and how missing widgets can be added/removed, giving + * the user control of insertion. + * + * @example + * see http://gridstackjs.com/demo/serialization.html + */ + load(items, addRemove = GridStack.addRemoveCB || true) { + items = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.cloneDeep(items); // so we can mod + const column = this.getColumn(); + // if we have a mix of new items without coordinates and existing items, separate them out so they can be added after #2639 + let addAfter = items.filter(n => (n.x === undefined || n.y === undefined) && !_utils__WEBPACK_IMPORTED_MODULE_1__.Utils.find(this.engine.nodes, n.id)); + if (addAfter.length && addAfter.length !== items.length) { + items = items.filter(n => !_utils__WEBPACK_IMPORTED_MODULE_1__.Utils.find(addAfter, n.id)); + } + else + addAfter = []; + // if passed list has coordinates, use them (insert from end to beginning for conflict resolution) else keep widget order + const haveCoord = items.some(w => w.x !== undefined || w.y !== undefined); + if (haveCoord) + items = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.sort(items, -1); + this._insertNotAppend = haveCoord; // if we create in reverse order... + // if we're loading a layout into for example 1 column and items don't fit, make sure to save + // the original wanted layout so we can scale back up correctly #1471 + if (items.some(n => ((n.x || 0) + (n.w || 1)) > column)) { + this._ignoreLayoutsNodeChange = true; // skip layout update + this.engine.cacheLayout(items, 12, true); // TODO: 12 is arbitrary. use max value in layout ? + } + // if given a different callback, temporally set it as global option so creating will use it + const prevCB = GridStack.addRemoveCB; + if (typeof (addRemove) === 'function') + GridStack.addRemoveCB = addRemove; + let removed = []; + this.batchUpdate(); + // if we are blank (loading into empty like startup) temp remove animation + const noAnim = !this.engine.nodes.length; + if (noAnim) + this.setAnimation(false); + // see if any items are missing from new layout and need to be removed first + if (addRemove) { + let copyNodes = [...this.engine.nodes]; // don't loop through array you modify + copyNodes.forEach(n => { + if (!n.id) + return; + let item = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.find(items, n.id); + if (!item) { + if (GridStack.addRemoveCB) + GridStack.addRemoveCB(this.el, n, false, false); + removed.push(n); // batch keep track + this.removeWidget(n.el, true, false); + } + }); + } + // now add/update the widgets - starting with removing items in the new layout we will reposition + // to reduce collision and add no-coord ones at next available spot + let updateNodes = []; + this.engine.nodes = this.engine.nodes.filter(n => { + if (_utils__WEBPACK_IMPORTED_MODULE_1__.Utils.find(items, n.id)) { + updateNodes.push(n); + return false; + } // remove if found from list + return true; + }); + items.forEach(w => { + let item = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.find(updateNodes, w.id); + if (item) { + // if item sizes to content, re-use the exiting height so it's a better guess at the final size (same if width doesn't change) + if (_utils__WEBPACK_IMPORTED_MODULE_1__.Utils.shouldSizeToContent(item)) + w.h = item.h; + // check if missing coord, in which case find next empty slot with new (or old if missing) sizes + this.engine.nodeBoundFix(w); + if (w.autoPosition || w.x === undefined || w.y === undefined) { + w.w = w.w || item.w; + w.h = w.h || item.h; + this.engine.findEmptyPosition(w); + } + // add back to current list BUT force a collision check if it 'appears' we didn't change to make sure we don't overlap others now + this.engine.nodes.push(item); + if (_utils__WEBPACK_IMPORTED_MODULE_1__.Utils.samePos(item, w)) { + this.moveNode(item, { ...w, forceCollide: true }); + } + this.update(item.el, w); + if (w.subGridOpts?.children) { // update any sub grid as well + let sub = item.el.querySelector('.grid-stack'); + if (sub && sub.gridstack) { + sub.gridstack.load(w.subGridOpts.children); // TODO: support updating grid options ? + this._insertNotAppend = true; // got reset by above call + } + } + } + else if (addRemove) { + this.addWidget(w); + } + }); + // finally append any separate ones that didn't have explicit coordinates last so they can find next empty spot + if (addRemove) { + addAfter.forEach(w => this.addWidget(w)); + } + this.engine.removedNodes = removed; + this.batchUpdate(false); + // after commit, clear that flag + delete this._ignoreLayoutsNodeChange; + delete this._insertNotAppend; + prevCB ? GridStack.addRemoveCB = prevCB : delete GridStack.addRemoveCB; + // delay adding animation back, but check to make sure grid (opt) is still around + if (noAnim && this.opts?.animate) + setTimeout(() => { if (this.opts) + this.setAnimation(this.opts.animate); }); + return this; + } + /** + * use before calling a bunch of `addWidget()` to prevent un-necessary relayouts in between (more efficient) + * and get a single event callback. You will see no changes until `batchUpdate(false)` is called. + */ + batchUpdate(flag = true) { + this.engine.batchUpdate(flag); + if (!flag) { + this._updateContainerHeight(); + this._triggerRemoveEvent(); + this._triggerAddEvent(); + this._triggerChangeEvent(); + } + return this; + } + /** + * Gets current cell height. + */ + getCellHeight(forcePixel = false) { + if (this.opts.cellHeight && this.opts.cellHeight !== 'auto' && + (!forcePixel || !this.opts.cellHeightUnit || this.opts.cellHeightUnit === 'px')) { + return this.opts.cellHeight; + } + // do rem/em/cm/mm to px conversion + if (this.opts.cellHeightUnit === 'rem') { + return this.opts.cellHeight * parseFloat(getComputedStyle(document.documentElement).fontSize); + } + if (this.opts.cellHeightUnit === 'em') { + return this.opts.cellHeight * parseFloat(getComputedStyle(this.el).fontSize); + } + if (this.opts.cellHeightUnit === 'cm') { + // 1cm = 96px/2.54. See https://www.w3.org/TR/css-values-3/#absolute-lengths + return this.opts.cellHeight * (96 / 2.54); + } + if (this.opts.cellHeightUnit === 'mm') { + return this.opts.cellHeight * (96 / 2.54) / 10; + } + // else get first cell height + let el = this.el.querySelector('.' + this.opts.itemClass); + if (el) { + let h = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-h')) || 1; // since we don't write 1 anymore + return Math.round(el.offsetHeight / h); + } + // else do entire grid and # of rows (but doesn't work if min-height is the actual constrain) + let rows = parseInt(this.el.getAttribute('gs-current-row')); + return rows ? Math.round(this.el.getBoundingClientRect().height / rows) : this.opts.cellHeight; + } + /** + * Update current cell height - see `GridStackOptions.cellHeight` for format. + * This method rebuilds an internal CSS style sheet. + * Note: You can expect performance issues if call this method too often. + * + * @param val the cell height. If not passed (undefined), cells content will be made square (match width minus margin), + * if pass 0 the CSS will be generated by the application instead. + * @param update (Optional) if false, styles will not be updated + * + * @example + * grid.cellHeight(100); // same as 100px + * grid.cellHeight('70px'); + * grid.cellHeight(grid.cellWidth() * 1.2); + */ + cellHeight(val, update = true) { + // if not called internally, check if we're changing mode + if (update && val !== undefined) { + if (this._isAutoCellHeight !== (val === 'auto')) { + this._isAutoCellHeight = (val === 'auto'); + this._updateResizeEvent(); + } + } + if (val === 'initial' || val === 'auto') { + val = undefined; + } + // make item content be square + if (val === undefined) { + let marginDiff = -this.opts.marginRight - this.opts.marginLeft + + this.opts.marginTop + this.opts.marginBottom; + val = this.cellWidth() + marginDiff; + } + let data = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.parseHeight(val); + if (this.opts.cellHeightUnit === data.unit && this.opts.cellHeight === data.h) { + return this; + } + this.opts.cellHeightUnit = data.unit; + this.opts.cellHeight = data.h; + this.resizeToContentCheck(); + if (update) { + this._updateStyles(true); // true = force re-create for current # of rows + } + return this; + } + /** Gets current cell width. */ + cellWidth() { + return this._widthOrContainer() / this.getColumn(); + } + /** return our expected width (or parent) , and optionally of window for dynamic column check */ + _widthOrContainer(forBreakpoint = false) { + // use `offsetWidth` or `clientWidth` (no scrollbar) ? + // https://stackoverflow.com/questions/21064101/understanding-offsetwidth-clientwidth-scrollwidth-and-height-respectively + return forBreakpoint && this.opts.columnOpts?.breakpointForWindow ? window.innerWidth : (this.el.clientWidth || this.el.parentElement.clientWidth || window.innerWidth); + } + /** checks for dynamic column count for our current size, returning true if changed */ + checkDynamicColumn() { + const resp = this.opts.columnOpts; + if (!resp || (!resp.columnWidth && !resp.breakpoints?.length)) + return false; + const column = this.getColumn(); + let newColumn = column; + const w = this._widthOrContainer(true); + if (resp.columnWidth) { + newColumn = Math.min(Math.round(w / resp.columnWidth) || 1, resp.columnMax); + } + else { + // find the closest breakpoint (already sorted big to small) that matches + newColumn = resp.columnMax; + let i = 0; + while (i < resp.breakpoints.length && w <= resp.breakpoints[i].w) { + newColumn = resp.breakpoints[i++].c || column; + } + } + if (newColumn !== column) { + const bk = resp.breakpoints?.find(b => b.c === newColumn); + this.column(newColumn, bk?.layout || resp.layout); + return true; + } + return false; + } + /** + * re-layout grid items to reclaim any empty space. Options are: + * 'list' keep the widget left->right order the same, even if that means leaving an empty slot if things don't fit + * 'compact' might re-order items to fill any empty space + * + * doSort - 'false' to let you do your own sorting ahead in case you need to control a different order. (default to sort) + */ + compact(layout = 'compact', doSort = true) { + this.engine.compact(layout, doSort); + this._triggerChangeEvent(); + return this; + } + /** + * set the number of columns in the grid. Will update existing widgets to conform to new number of columns, + * as well as cache the original layout so you can revert back to previous positions without loss. + * Requires `gridstack-extra.css` or `gridstack-extra.min.css` for [2-11], + * else you will need to generate correct CSS (see https://github.com/gridstack/gridstack.js#change-grid-columns) + * @param column - Integer > 0 (default 12). + * @param layout specify the type of re-layout that will happen (position, size, etc...). + * Note: items will never be outside of the current column boundaries. default ('moveScale'). Ignored for 1 column + */ + column(column, layout = 'moveScale') { + if (!column || column < 1 || this.opts.column === column) + return this; + let oldColumn = this.getColumn(); + this.opts.column = column; + if (!this.engine) + return this; // called in constructor, noting else to do + this.engine.column = column; + this.el.classList.remove('gs-' + oldColumn); + this.el.classList.add('gs-' + column); + // update the items now, checking if we have a custom children layout + /*const newChildren = this.opts.columnOpts?.breakpoints?.find(r => r.c === column)?.children; + if (newChildren) this.load(newChildren); + else*/ this.engine.columnChanged(oldColumn, column, layout); + if (this._isAutoCellHeight) + this.cellHeight(); + this.resizeToContentCheck(true); // wait for width resizing + // and trigger our event last... + this._ignoreLayoutsNodeChange = true; // skip layout update + this._triggerChangeEvent(); + delete this._ignoreLayoutsNodeChange; + return this; + } + /** + * get the number of columns in the grid (default 12) + */ + getColumn() { return this.opts.column; } + /** returns an array of grid HTML elements (no placeholder) - used to iterate through our children in DOM order */ + getGridItems() { + return Array.from(this.el.children) + .filter((el) => el.matches('.' + this.opts.itemClass) && !el.matches('.' + this.opts.placeholderClass)); + } + /** + * Destroys a grid instance. DO NOT CALL any methods or access any vars after this as it will free up members. + * @param removeDOM if `false` grid and items HTML elements will not be removed from the DOM (Optional. Default `true`). + */ + destroy(removeDOM = true) { + if (!this.el) + return; // prevent multiple calls + this.offAll(); + this._updateResizeEvent(true); + this.setStatic(true, false); // permanently removes DD but don't set CSS class (we're going away) + this.setAnimation(false); + if (!removeDOM) { + this.removeAll(removeDOM); + this.el.classList.remove(this._styleSheetClass); + this.el.removeAttribute('gs-current-row'); + } + else { + this.el.parentNode.removeChild(this.el); + } + this._removeStylesheet(); + if (this.parentGridItem) + delete this.parentGridItem.subGrid; + delete this.parentGridItem; + delete this.opts; + delete this._placeholder; + delete this.engine; + delete this.el.gridstack; // remove circular dependency that would prevent a freeing + delete this.el; + return this; + } + /** + * enable/disable floating widgets (default: `false`) See [example](http://gridstackjs.com/demo/float.html) + */ + float(val) { + if (this.opts.float !== val) { + this.opts.float = this.engine.float = val; + this._triggerChangeEvent(); + } + return this; + } + /** + * get the current float mode + */ + getFloat() { + return this.engine.float; + } + /** + * Get the position of the cell under a pixel on screen. + * @param position the position of the pixel to resolve in + * absolute coordinates, as an object with top and left properties + * @param useDocRelative if true, value will be based on document position vs parent position (Optional. Default false). + * Useful when grid is within `position: relative` element + * + * Returns an object with properties `x` and `y` i.e. the column and row in the grid. + */ + getCellFromPixel(position, useDocRelative = false) { + let box = this.el.getBoundingClientRect(); + // console.log(`getBoundingClientRect left: ${box.left} top: ${box.top} w: ${box.w} h: ${box.h}`) + let containerPos; + if (useDocRelative) { + containerPos = { top: box.top + document.documentElement.scrollTop, left: box.left }; + // console.log(`getCellFromPixel scrollTop: ${document.documentElement.scrollTop}`) + } + else { + containerPos = { top: this.el.offsetTop, left: this.el.offsetLeft }; + // console.log(`getCellFromPixel offsetTop: ${containerPos.left} offsetLeft: ${containerPos.top}`) + } + let relativeLeft = position.left - containerPos.left; + let relativeTop = position.top - containerPos.top; + let columnWidth = (box.width / this.getColumn()); + let rowHeight = (box.height / parseInt(this.el.getAttribute('gs-current-row'))); + return { x: Math.floor(relativeLeft / columnWidth), y: Math.floor(relativeTop / rowHeight) }; + } + /** returns the current number of rows, which will be at least `minRow` if set */ + getRow() { + return Math.max(this.engine.getRow(), this.opts.minRow); + } + /** + * Checks if specified area is empty. + * @param x the position x. + * @param y the position y. + * @param w the width of to check + * @param h the height of to check + */ + isAreaEmpty(x, y, w, h) { + return this.engine.isAreaEmpty(x, y, w, h); + } + /** + * If you add elements to your grid by hand (or have some framework creating DOM), you have to tell gridstack afterwards to make them widgets. + * If you want gridstack to add the elements for you, use `addWidget()` instead. + * Makes the given element a widget and returns it. + * @param els widget or single selector to convert. + * @param options widget definition to use instead of reading attributes or using default sizing values + * + * @example + * let grid = GridStack.init(); + * grid.el.appendChild('
'); + * grid.el.appendChild('
'); + * grid.makeWidget('1'); + * grid.makeWidget('2', {w:2, content: 'hello'}); + */ + makeWidget(els, options) { + let el = GridStack.getElement(els); + this._prepareElement(el, true, options); + const node = el.gridstackNode; + this._updateContainerHeight(); + // see if there is a sub-grid to create + if (node.subGridOpts) { + this.makeSubGrid(el, node.subGridOpts, undefined, false); // node.subGrid will be used as option in method, no need to pass + } + // if we're adding an item into 1 column make sure + // we don't override the larger 12 column layout that was already saved. #1985 + if (this.opts.column === 1) { + this._ignoreLayoutsNodeChange = true; + } + this._triggerAddEvent(); + this._triggerChangeEvent(); + delete this._ignoreLayoutsNodeChange; + return el; + } + on(name, callback) { + // check for array of names being passed instead + if (name.indexOf(' ') !== -1) { + let names = name.split(' '); + names.forEach(name => this.on(name, callback)); + return this; + } + // native CustomEvent handlers - cash the generic handlers so we can easily remove + if (name === 'change' || name === 'added' || name === 'removed' || name === 'enable' || name === 'disable') { + let noData = (name === 'enable' || name === 'disable'); + if (noData) { + this._gsEventHandler[name] = (event) => callback(event); + } + else { + this._gsEventHandler[name] = (event) => callback(event, event.detail); + } + this.el.addEventListener(name, this._gsEventHandler[name]); + } + else if (name === 'drag' || name === 'dragstart' || name === 'dragstop' || name === 'resizestart' || name === 'resize' + || name === 'resizestop' || name === 'dropped' || name === 'resizecontent') { + // drag&drop stop events NEED to be call them AFTER we update node attributes so handle them ourself. + // do same for start event to make it easier... + this._gsEventHandler[name] = callback; + } + else { + console.error('GridStack.on(' + name + ') event not supported'); + } + return this; + } + /** + * unsubscribe from the 'on' event GridStackEvent + * @param name of the event (see possible values) or list of names space separated + */ + off(name) { + // check for array of names being passed instead + if (name.indexOf(' ') !== -1) { + let names = name.split(' '); + names.forEach(name => this.off(name)); + return this; + } + if (name === 'change' || name === 'added' || name === 'removed' || name === 'enable' || name === 'disable') { + // remove native CustomEvent handlers + if (this._gsEventHandler[name]) { + this.el.removeEventListener(name, this._gsEventHandler[name]); + } + } + delete this._gsEventHandler[name]; + return this; + } + /** remove all event handlers */ + offAll() { + Object.keys(this._gsEventHandler).forEach((key) => this.off(key)); + return this; + } + /** + * Removes widget from the grid. + * @param el widget or selector to modify + * @param removeDOM if `false` DOM element won't be removed from the tree (Default? true). + * @param triggerEvent if `false` (quiet mode) element will not be added to removed list and no 'removed' callbacks will be called (Default? true). + */ + removeWidget(els, removeDOM = true, triggerEvent = true) { + GridStack.getElements(els).forEach(el => { + if (el.parentElement && el.parentElement !== this.el) + return; // not our child! + let node = el.gridstackNode; + // For Meteor support: https://github.com/gridstack/gridstack.js/pull/272 + if (!node) { + node = this.engine.nodes.find(n => el === n.el); + } + if (!node) + return; + if (removeDOM && GridStack.addRemoveCB) { + GridStack.addRemoveCB(this.el, node, false, false); + } + // remove our DOM data (circular link) and drag&drop permanently + delete el.gridstackNode; + this._removeDD(el); + this.engine.removeNode(node, removeDOM, triggerEvent); + if (removeDOM && el.parentElement) { + el.remove(); // in batch mode engine.removeNode doesn't call back to remove DOM + } + }); + if (triggerEvent) { + this._triggerRemoveEvent(); + this._triggerChangeEvent(); + } + return this; + } + /** + * Removes all widgets from the grid. + * @param removeDOM if `false` DOM elements won't be removed from the tree (Default? `true`). + * @param triggerEvent if `false` (quiet mode) element will not be added to removed list and no 'removed' callbacks will be called (Default? true). + */ + removeAll(removeDOM = true, triggerEvent = true) { + // always remove our DOM data (circular link) before list gets emptied and drag&drop permanently + this.engine.nodes.forEach(n => { + if (removeDOM && GridStack.addRemoveCB) { + GridStack.addRemoveCB(this.el, n, false, false); + } + delete n.el.gridstackNode; + if (!this.opts.staticGrid) + this._removeDD(n.el); + }); + this.engine.removeAll(removeDOM, triggerEvent); + if (triggerEvent) + this._triggerRemoveEvent(); + return this; + } + /** + * Toggle the grid animation state. Toggles the `grid-stack-animate` class. + * @param doAnimate if true the grid will animate. + */ + setAnimation(doAnimate) { + if (doAnimate) { + this.el.classList.add('grid-stack-animate'); + } + else { + this.el.classList.remove('grid-stack-animate'); + } + return this; + } + /** @internal */ + hasAnimationCSS() { return this.el.classList.contains('grid-stack-animate'); } + /** + * Toggle the grid static state, which permanently removes/add Drag&Drop support, unlike disable()/enable() that just turns it off/on. + * Also toggle the grid-stack-static class. + * @param val if true the grid become static. + * @param updateClass true (default) if css class gets updated + * @param recurse true (default) if sub-grids also get updated + */ + setStatic(val, updateClass = true, recurse = true) { + if (!!this.opts.staticGrid === val) + return this; + val ? this.opts.staticGrid = true : delete this.opts.staticGrid; + this._setupRemoveDrop(); + this._setupAcceptWidget(); + this.engine.nodes.forEach(n => { + this._prepareDragDropByNode(n); // either delete or init Drag&drop + if (n.subGrid && recurse) + n.subGrid.setStatic(val, updateClass, recurse); + }); + if (updateClass) { + this._setStaticClass(); + } + return this; + } + /** + * Updates widget position/size and other info. Note: if you need to call this on all nodes, use load() instead which will update what changed. + * @param els widget or selector of objects to modify (note: setting the same x,y for multiple items will be indeterministic and likely unwanted) + * @param opt new widget options (x,y,w,h, etc..). Only those set will be updated. + */ + update(els, opt) { + // support legacy call for now ? + if (arguments.length > 2) { + console.warn('gridstack.ts: `update(el, x, y, w, h)` is deprecated. Use `update(el, {x, w, content, ...})`. It will be removed soon'); + // eslint-disable-next-line prefer-rest-params + let a = arguments, i = 1; + opt = { x: a[i++], y: a[i++], w: a[i++], h: a[i++] }; + return this.update(els, opt); + } + GridStack.getElements(els).forEach(el => { + let n = el?.gridstackNode; + if (!n) + return; + let w = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.cloneDeep(opt); // make a copy we can modify in case they re-use it or multiple items + this.engine.nodeBoundFix(w); + delete w.autoPosition; + delete w.id; + // move/resize widget if anything changed + let keys = ['x', 'y', 'w', 'h']; + let m; + if (keys.some(k => w[k] !== undefined && w[k] !== n[k])) { + m = {}; + keys.forEach(k => { + m[k] = (w[k] !== undefined) ? w[k] : n[k]; + delete w[k]; + }); + } + // for a move as well IFF there is any min/max fields set + if (!m && (w.minW || w.minH || w.maxW || w.maxH)) { + m = {}; // will use node position but validate values + } + // check for content changing + if (w.content !== undefined) { + const itemContent = el.querySelector('.grid-stack-item-content'); + if (itemContent && itemContent.innerHTML !== w.content) { + itemContent.innerHTML = w.content; + // restore any sub-grid back + if (n.subGrid?.el) { + itemContent.appendChild(n.subGrid.el); + if (!n.subGrid.opts.styleInHead) + n.subGrid._updateStyles(true); // force create + } + } + delete w.content; + } + // any remaining fields are assigned, but check for dragging changes, resize constrain + let changed = false; + let ddChanged = false; + for (const key in w) { + if (key[0] !== '_' && n[key] !== w[key]) { + n[key] = w[key]; + changed = true; + ddChanged = ddChanged || (!this.opts.staticGrid && (key === 'noResize' || key === 'noMove' || key === 'locked')); + } + } + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.sanitizeMinMax(n); + // finally move the widget and update attr + if (m) { + const widthChanged = (m.w !== undefined && m.w !== n.w); + this.moveNode(n, m); + this.resizeToContentCheck(widthChanged, n); // wait for animation if we changed width + } + if (m || changed) { + this._writeAttr(el, n); + } + if (ddChanged) { + this._prepareDragDropByNode(n); + } + }); + return this; + } + moveNode(n, m) { + this.engine.cleanNodes() + .beginUpdate(n) + .moveNode(n, m); + this._updateContainerHeight(); + this._triggerChangeEvent(); + this.engine.endUpdate(); + } + /** + * Updates widget height to match the content height to avoid v-scrollbar or dead space. + * Note: this assumes only 1 child under resizeToContentParent='.grid-stack-item-content' (sized to gridItem minus padding) that is at the entire content size wanted. + * @param el grid item element + * @param useNodeH set to true if GridStackNode.h should be used instead of actual container height when we don't need to wait for animation to finish to get actual DOM heights + */ + resizeToContent(el) { + if (!el) + return; + el.classList.remove('size-to-content-max'); + if (!el.clientHeight) + return; // 0 when hidden, skip + const n = el.gridstackNode; + if (!n) + return; + const grid = n.grid; + if (!grid || el.parentElement !== grid.el) + return; // skip if we are not inside a grid + const cell = grid.getCellHeight(true); + if (!cell) + return; + let height = n.h ? n.h * cell : el.clientHeight; // getBoundingClientRect().height seem to flicker back and forth + let item; + if (n.resizeToContentParent) + item = el.querySelector(n.resizeToContentParent); + if (!item) + item = el.querySelector(GridStack.resizeToContentParent); + if (!item) + return; + const padding = el.clientHeight - item.clientHeight; // full - available height to our child (minus border, padding...) + const itemH = n.h ? n.h * cell - padding : item.clientHeight; // calculated to what cellHeight is or will become (rather than actual to prevent waiting for animation to finish) + let wantedH; + if (n.subGrid) { + // sub-grid - use their actual row count * their cell height + wantedH = n.subGrid.getRow() * n.subGrid.getCellHeight(true); + } + else { + // NOTE: clientHeight & getBoundingClientRect() is undefined for text and other leaf nodes. use
container! + const child = item.firstElementChild; + if (!child) { + console.error(`Error: GridStack.resizeToContent() widget id:${n.id} '${GridStack.resizeToContentParent}'.firstElementChild is null, make sure to have a div like container. Skipping sizing.`); + return; + } + wantedH = child.getBoundingClientRect().height || itemH; + } + if (itemH === wantedH) + return; + height += wantedH - itemH; + let h = Math.ceil(height / cell); + // check for min/max and special sizing + const softMax = Number.isInteger(n.sizeToContent) ? n.sizeToContent : 0; + if (softMax && h > softMax) { + h = softMax; + el.classList.add('size-to-content-max'); // get v-scroll back + } + if (n.minH && h < n.minH) + h = n.minH; + else if (n.maxH && h > n.maxH) + h = n.maxH; + if (h !== n.h) { + grid._ignoreLayoutsNodeChange = true; + grid.moveNode(n, { h }); + delete grid._ignoreLayoutsNodeChange; + } + } + /** call the user resize (so they can do extra work) else our build in version */ + resizeToContentCBCheck(el) { + if (GridStack.resizeToContentCB) + GridStack.resizeToContentCB(el); + else + this.resizeToContent(el); + } + /** + * Updates the margins which will set all 4 sides at once - see `GridStackOptions.margin` for format options (CSS string format of 1,2,4 values or single number). + * @param value margin value + */ + margin(value) { + let isMultiValue = (typeof value === 'string' && value.split(' ').length > 1); + // check if we can skip re-creating our CSS file... won't check if multi values (too much hassle) + if (!isMultiValue) { + let data = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.parseHeight(value); + if (this.opts.marginUnit === data.unit && this.opts.margin === data.h) + return; + } + // re-use existing margin handling + this.opts.margin = value; + this.opts.marginTop = this.opts.marginBottom = this.opts.marginLeft = this.opts.marginRight = undefined; + this._initMargin(); + this._updateStyles(true); // true = force re-create + return this; + } + /** returns current margin number value (undefined if 4 sides don't match) */ + getMargin() { return this.opts.margin; } + /** + * Returns true if the height of the grid will be less than the vertical + * constraint. Always returns true if grid doesn't have height constraint. + * @param node contains x,y,w,h,auto-position options + * + * @example + * if (grid.willItFit(newWidget)) { + * grid.addWidget(newWidget); + * } else { + * alert('Not enough free space to place the widget'); + * } + */ + willItFit(node) { + // support legacy call for now + if (arguments.length > 1) { + console.warn('gridstack.ts: `willItFit(x,y,w,h,autoPosition)` is deprecated. Use `willItFit({x, y,...})`. It will be removed soon'); + // eslint-disable-next-line prefer-rest-params + let a = arguments, i = 0, w = { x: a[i++], y: a[i++], w: a[i++], h: a[i++], autoPosition: a[i++] }; + return this.willItFit(w); + } + return this.engine.willItFit(node); + } + /** @internal */ + _triggerChangeEvent() { + if (this.engine.batchMode) + return this; + let elements = this.engine.getDirtyNodes(true); // verify they really changed + if (elements && elements.length) { + if (!this._ignoreLayoutsNodeChange) { + this.engine.layoutsNodesChange(elements); + } + this._triggerEvent('change', elements); + } + this.engine.saveInitial(); // we called, now reset initial values & dirty flags + return this; + } + /** @internal */ + _triggerAddEvent() { + if (this.engine.batchMode) + return this; + if (this.engine.addedNodes?.length) { + if (!this._ignoreLayoutsNodeChange) { + this.engine.layoutsNodesChange(this.engine.addedNodes); + } + // prevent added nodes from also triggering 'change' event (which is called next) + this.engine.addedNodes.forEach(n => { delete n._dirty; }); + const addedNodes = [...this.engine.addedNodes]; + this.engine.addedNodes = []; + this._triggerEvent('added', addedNodes); + } + return this; + } + /** @internal */ + _triggerRemoveEvent() { + if (this.engine.batchMode) + return this; + if (this.engine.removedNodes?.length) { + const removedNodes = [...this.engine.removedNodes]; + this.engine.removedNodes = []; + this._triggerEvent('removed', removedNodes); + } + return this; + } + /** @internal */ + _triggerEvent(type, data) { + let event = data ? new CustomEvent(type, { bubbles: false, detail: data }) : new Event(type); + this.el.dispatchEvent(event); + return this; + } + /** @internal called to delete the current dynamic style sheet used for our layout */ + _removeStylesheet() { + if (this._styles) { + const styleLocation = this.opts.styleInHead ? undefined : this.el.parentNode; + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.removeStylesheet(this._styleSheetClass, styleLocation); + delete this._styles; + } + return this; + } + /** @internal updated/create the CSS styles for row based layout and initial margin setting */ + _updateStyles(forceUpdate = false, maxH) { + // call to delete existing one if we change cellHeight / margin + if (forceUpdate) { + this._removeStylesheet(); + } + if (maxH === undefined) + maxH = this.getRow(); + this._updateContainerHeight(); + // if user is telling us they will handle the CSS themselves by setting heights to 0. Do we need this opts really ?? + if (this.opts.cellHeight === 0) { + return this; + } + let cellHeight = this.opts.cellHeight; + let cellHeightUnit = this.opts.cellHeightUnit; + let prefix = `.${this._styleSheetClass} > .${this.opts.itemClass}`; + // create one as needed + if (!this._styles) { + // insert style to parent (instead of 'head' by default) to support WebComponent + const styleLocation = this.opts.styleInHead ? undefined : this.el.parentNode; + this._styles = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.createStylesheet(this._styleSheetClass, styleLocation, { + nonce: this.opts.nonce, + }); + if (!this._styles) + return this; + this._styles._max = 0; + // these are done once only + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, prefix, `height: ${cellHeight}${cellHeightUnit}`); + // content margins + let top = this.opts.marginTop + this.opts.marginUnit; + let bottom = this.opts.marginBottom + this.opts.marginUnit; + let right = this.opts.marginRight + this.opts.marginUnit; + let left = this.opts.marginLeft + this.opts.marginUnit; + let content = `${prefix} > .grid-stack-item-content`; + let placeholder = `.${this._styleSheetClass} > .grid-stack-placeholder > .placeholder-content`; + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, content, `top: ${top}; right: ${right}; bottom: ${bottom}; left: ${left};`); + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, placeholder, `top: ${top}; right: ${right}; bottom: ${bottom}; left: ${left};`); + // resize handles offset (to match margin) + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-n`, `top: ${top};`); + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-s`, `bottom: ${bottom}`); + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-ne`, `right: ${right}`); + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-e`, `right: ${right}`); + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-se`, `right: ${right}; bottom: ${bottom}`); + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-nw`, `left: ${left}`); + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-w`, `left: ${left}`); + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-sw`, `left: ${left}; bottom: ${bottom}`); + } + // now update the height specific fields + maxH = maxH || this._styles._max; + if (maxH > this._styles._max) { + let getHeight = (rows) => (cellHeight * rows) + cellHeightUnit; + for (let i = this._styles._max + 1; i <= maxH; i++) { // start at 1 + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, `${prefix}[gs-y="${i}"]`, `top: ${getHeight(i)}`); + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.addCSSRule(this._styles, `${prefix}[gs-h="${i + 1}"]`, `height: ${getHeight(i + 1)}`); // start at 2 + } + this._styles._max = maxH; + } + return this; + } + /** @internal */ + _updateContainerHeight() { + if (!this.engine || this.engine.batchMode) + return this; + const parent = this.parentGridItem; + let row = this.getRow() + this._extraDragRow; // this checks for minRow already + const cellHeight = this.opts.cellHeight; + const unit = this.opts.cellHeightUnit; + if (!cellHeight) + return this; + // check for css min height (non nested grid). TODO: support mismatch, say: min % while unit is px. + if (!parent) { + const cssMinHeight = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.parseHeight(getComputedStyle(this.el)['minHeight']); + if (cssMinHeight.h > 0 && cssMinHeight.unit === unit) { + const minRow = Math.floor(cssMinHeight.h / cellHeight); + if (row < minRow) { + row = minRow; + } + } + } + this.el.setAttribute('gs-current-row', String(row)); + this.el.style.removeProperty('min-height'); + this.el.style.removeProperty('height'); + if (row) { + // nested grids have 'insert:0' to fill the space of parent by default, but we may be taller so use min-height for possible scrollbars + this.el.style[parent ? 'minHeight' : 'height'] = row * cellHeight + unit; + } + // if we're a nested grid inside an sizeToContent item, tell it to resize itself too + if (parent && !parent.grid.engine.batchMode && _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.shouldSizeToContent(parent)) { + parent.grid.resizeToContentCBCheck(parent.el); + } + return this; + } + /** @internal */ + _prepareElement(el, triggerAddEvent = false, node) { + node = node || this._readAttr(el); + el.gridstackNode = node; + node.el = el; + node.grid = this; + node = this.engine.addNode(node, triggerAddEvent); + // write the dom sizes and class + this._writeAttr(el, node); + el.classList.add(_types__WEBPACK_IMPORTED_MODULE_2__.gridDefaults.itemClass, this.opts.itemClass); + const sizeToContent = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.shouldSizeToContent(node); + sizeToContent ? el.classList.add('size-to-content') : el.classList.remove('size-to-content'); + if (sizeToContent) + this.resizeToContentCheck(false, node); + this._prepareDragDropByNode(node); + return this; + } + /** @internal call to write position x,y,w,h attributes back to element */ + _writePosAttr(el, n) { + if (n.x !== undefined && n.x !== null) { + el.setAttribute('gs-x', String(n.x)); + } + if (n.y !== undefined && n.y !== null) { + el.setAttribute('gs-y', String(n.y)); + } + n.w > 1 ? el.setAttribute('gs-w', String(n.w)) : el.removeAttribute('gs-w'); + n.h > 1 ? el.setAttribute('gs-h', String(n.h)) : el.removeAttribute('gs-h'); + return this; + } + /** @internal call to write any default attributes back to element */ + _writeAttr(el, node) { + if (!node) + return this; + this._writePosAttr(el, node); + let attrs /*: GridStackWidget but strings */ = { + autoPosition: 'gs-auto-position', + noResize: 'gs-no-resize', + noMove: 'gs-no-move', + locked: 'gs-locked', + id: 'gs-id', + }; + for (const key in attrs) { + if (node[key]) { // 0 is valid for x,y only but done above already and not in list anyway + el.setAttribute(attrs[key], String(node[key])); + } + else { + el.removeAttribute(attrs[key]); + } + } + return this; + } + /** @internal call to read any default attributes from element */ + _readAttr(el, clearDefaultAttr = true) { + let n = {}; + n.x = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-x')); + n.y = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-y')); + n.w = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-w')); + n.h = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-h')); + n.autoPosition = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toBool(el.getAttribute('gs-auto-position')); + n.noResize = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toBool(el.getAttribute('gs-no-resize')); + n.noMove = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toBool(el.getAttribute('gs-no-move')); + n.locked = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toBool(el.getAttribute('gs-locked')); + n.id = el.getAttribute('gs-id'); + // read but never written out + n.maxW = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-max-w')); + n.minW = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-min-w')); + n.maxH = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-max-h')); + n.minH = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.toNumber(el.getAttribute('gs-min-h')); + // v8.x optimization to reduce un-needed attr that don't render or are default CSS + if (clearDefaultAttr) { + if (n.w === 1) + el.removeAttribute('gs-w'); + if (n.h === 1) + el.removeAttribute('gs-h'); + if (n.maxW) + el.removeAttribute('gs-max-w'); + if (n.minW) + el.removeAttribute('gs-min-w'); + if (n.maxH) + el.removeAttribute('gs-max-h'); + if (n.minH) + el.removeAttribute('gs-min-h'); + } + // remove any key not found (null or false which is default) + for (const key in n) { + if (!n.hasOwnProperty(key)) + return; + if (!n[key] && n[key] !== 0) { // 0 can be valid value (x,y only really) + delete n[key]; + } + } + return n; + } + /** @internal */ + _setStaticClass() { + let classes = ['grid-stack-static']; + if (this.opts.staticGrid) { + this.el.classList.add(...classes); + this.el.setAttribute('gs-static', 'true'); + } + else { + this.el.classList.remove(...classes); + this.el.removeAttribute('gs-static'); + } + return this; + } + /** + * called when we are being resized - check if the one Column Mode needs to be turned on/off + * and remember the prev columns we used, or get our count from parent, as well as check for cellHeight==='auto' (square) + * or `sizeToContent` gridItem options. + */ + onResize() { + if (!this.el?.clientWidth) + return; // return if we're gone or no size yet (will get called again) + if (this.prevWidth === this.el.clientWidth) + return; // no-op + this.prevWidth = this.el.clientWidth; + // console.log('onResize ', this.el.clientWidth); + this.batchUpdate(); + // see if we're nested and take our column count from our parent.... + let columnChanged = false; + if (this._autoColumn && this.parentGridItem) { + if (this.opts.column !== this.parentGridItem.w) { + this.column(this.parentGridItem.w, 'none'); + columnChanged = true; + } + } + else { + // else check for dynamic column + columnChanged = this.checkDynamicColumn(); + } + // make the cells content square again + if (this._isAutoCellHeight) + this.cellHeight(); + // update any nested grids, or items size + this.engine.nodes.forEach(n => { + if (n.subGrid) + n.subGrid.onResize(); + }); + if (!this._skipInitialResize) + this.resizeToContentCheck(columnChanged); // wait for anim of column changed (DOM reflow before we can size correctly) + delete this._skipInitialResize; + this.batchUpdate(false); + return this; + } + /** resizes content for given node (or all) if shouldSizeToContent() is true */ + resizeToContentCheck(delay = false, n = undefined) { + if (!this.engine) + return; // we've been deleted in between! + // update any gridItem height with sizeToContent, but wait for DOM $animation_speed to settle if we changed column count + // TODO: is there a way to know what the final (post animation) size of the content will be so we can animate the column width and height together rather than sequentially ? + if (delay && this.hasAnimationCSS()) + return setTimeout(() => this.resizeToContentCheck(false, n), 300 + 10); + if (n) { + if (_utils__WEBPACK_IMPORTED_MODULE_1__.Utils.shouldSizeToContent(n)) + this.resizeToContentCBCheck(n.el); + } + else if (this.engine.nodes.some(n => _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.shouldSizeToContent(n))) { + const nodes = [...this.engine.nodes]; // in case order changes while resizing one + this.batchUpdate(); + nodes.forEach(n => { + if (_utils__WEBPACK_IMPORTED_MODULE_1__.Utils.shouldSizeToContent(n)) + this.resizeToContentCBCheck(n.el); + }); + this.batchUpdate(false); + } + // call this regardless of shouldSizeToContent because widget might need to stretch to take available space after a resize + if (this._gsEventHandler['resizecontent']) + this._gsEventHandler['resizecontent'](null, n ? [n] : this.engine.nodes); + } + /** add or remove the grid element size event handler */ + _updateResizeEvent(forceRemove = false) { + // only add event if we're not nested (parent will call us) and we're auto sizing cells or supporting dynamic column (i.e. doing work) + // or supporting new sizeToContent option. + const trackSize = !this.parentGridItem && (this._isAutoCellHeight || this.opts.sizeToContent || this.opts.columnOpts + || this.engine.nodes.find(n => n.sizeToContent)); + if (!forceRemove && trackSize && !this.resizeObserver) { + this._sizeThrottle = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.throttle(() => this.onResize(), this.opts.cellHeightThrottle); + this.resizeObserver = new ResizeObserver(() => this._sizeThrottle()); + this.resizeObserver.observe(this.el); + this._skipInitialResize = true; // makeWidget will originally have called on startup + } + else if ((forceRemove || !trackSize) && this.resizeObserver) { + this.resizeObserver.disconnect(); + delete this.resizeObserver; + delete this._sizeThrottle; + } + return this; + } + /** @internal convert a potential selector into actual element */ + static getElement(els = '.grid-stack-item') { return _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.getElement(els); } + /** @internal */ + static getElements(els = '.grid-stack-item') { return _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.getElements(els); } + /** @internal */ + static getGridElement(els) { return GridStack.getElement(els); } + /** @internal */ + static getGridElements(els) { return _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.getElements(els); } + /** @internal initialize margin top/bottom/left/right and units */ + _initMargin() { + let data; + let margin = 0; + // support passing multiple values like CSS (ex: '5px 10px 0 20px') + let margins = []; + if (typeof this.opts.margin === 'string') { + margins = this.opts.margin.split(' '); + } + if (margins.length === 2) { // top/bot, left/right like CSS + this.opts.marginTop = this.opts.marginBottom = margins[0]; + this.opts.marginLeft = this.opts.marginRight = margins[1]; + } + else if (margins.length === 4) { // Clockwise like CSS + this.opts.marginTop = margins[0]; + this.opts.marginRight = margins[1]; + this.opts.marginBottom = margins[2]; + this.opts.marginLeft = margins[3]; + } + else { + data = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.parseHeight(this.opts.margin); + this.opts.marginUnit = data.unit; + margin = this.opts.margin = data.h; + } + // see if top/bottom/left/right need to be set as well + if (this.opts.marginTop === undefined) { + this.opts.marginTop = margin; + } + else { + data = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.parseHeight(this.opts.marginTop); + this.opts.marginTop = data.h; + delete this.opts.margin; + } + if (this.opts.marginBottom === undefined) { + this.opts.marginBottom = margin; + } + else { + data = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.parseHeight(this.opts.marginBottom); + this.opts.marginBottom = data.h; + delete this.opts.margin; + } + if (this.opts.marginRight === undefined) { + this.opts.marginRight = margin; + } + else { + data = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.parseHeight(this.opts.marginRight); + this.opts.marginRight = data.h; + delete this.opts.margin; + } + if (this.opts.marginLeft === undefined) { + this.opts.marginLeft = margin; + } + else { + data = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.parseHeight(this.opts.marginLeft); + this.opts.marginLeft = data.h; + delete this.opts.margin; + } + this.opts.marginUnit = data.unit; // in case side were spelled out, use those units instead... + if (this.opts.marginTop === this.opts.marginBottom && this.opts.marginLeft === this.opts.marginRight && this.opts.marginTop === this.opts.marginRight) { + this.opts.margin = this.opts.marginTop; // makes it easier to check for no-ops in setMargin() + } + return this; + } + /* =========================================================================================== + * drag&drop methods that used to be stubbed out and implemented in dd-gridstack.ts + * but caused loading issues in prod - see https://github.com/gridstack/gridstack.js/issues/2039 + * =========================================================================================== + */ + /** get the global (but static to this code) DD implementation */ + static getDD() { + return dd; + } + /** + * call to setup dragging in from the outside (say toolbar), by specifying the class selection and options. + * Called during GridStack.init() as options, but can also be called directly (last param are used) in case the toolbar + * is dynamically create and needs to be set later. + * @param dragIn string selector (ex: '.sidebar .grid-stack-item') or list of dom elements + * @param dragInOptions options - see DDDragInOpt. (default: {handle: '.grid-stack-item-content', appendTo: 'body'} + * @param root optional root which defaults to document (for shadow dom pas the parent HTMLDocument) + */ + static setupDragIn(dragIn, dragInOptions, root = document) { + if (dragInOptions?.pause !== undefined) { + _dd_manager__WEBPACK_IMPORTED_MODULE_5__.DDManager.pauseDrag = dragInOptions.pause; + } + dragInOptions = { ..._types__WEBPACK_IMPORTED_MODULE_2__.dragInDefaultOptions, ...(dragInOptions || {}) }; + let els = (typeof dragIn === 'string') ? _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.getElements(dragIn, root) : dragIn; + if (els.length) + els?.forEach(el => { + if (!dd.isDraggable(el)) + dd.dragIn(el, dragInOptions); + }); + } + /** + * Enables/Disables dragging by the user of specific grid element. If you want all items, and have it affect future items, use enableMove() instead. No-op for static grids. + * IF you are looking to prevent an item from moving (due to being pushed around by another during collision) use locked property instead. + * @param els widget or selector to modify. + * @param val if true widget will be draggable, assuming the parent grid isn't noMove or static. + */ + movable(els, val) { + if (this.opts.staticGrid) + return this; // can't move a static grid! + GridStack.getElements(els).forEach(el => { + const n = el.gridstackNode; + if (!n) + return; + val ? delete n.noMove : n.noMove = true; + this._prepareDragDropByNode(n); // init DD if need be, and adjust + }); + return this; + } + /** + * Enables/Disables user resizing of specific grid element. If you want all items, and have it affect future items, use enableResize() instead. No-op for static grids. + * @param els widget or selector to modify + * @param val if true widget will be resizable, assuming the parent grid isn't noResize or static. + */ + resizable(els, val) { + if (this.opts.staticGrid) + return this; // can't resize a static grid! + GridStack.getElements(els).forEach(el => { + let n = el.gridstackNode; + if (!n) + return; + val ? delete n.noResize : n.noResize = true; + this._prepareDragDropByNode(n); // init DD if need be, and adjust + }); + return this; + } + /** + * Temporarily disables widgets moving/resizing. + * If you want a more permanent way (which freezes up resources) use `setStatic(true)` instead. + * Note: no-op for static grid + * This is a shortcut for: + * @example + * grid.enableMove(false); + * grid.enableResize(false); + * @param recurse true (default) if sub-grids also get updated + */ + disable(recurse = true) { + if (this.opts.staticGrid) + return; + this.enableMove(false, recurse); + this.enableResize(false, recurse); + this._triggerEvent('disable'); + return this; + } + /** + * Re-enables widgets moving/resizing - see disable(). + * Note: no-op for static grid. + * This is a shortcut for: + * @example + * grid.enableMove(true); + * grid.enableResize(true); + * @param recurse true (default) if sub-grids also get updated + */ + enable(recurse = true) { + if (this.opts.staticGrid) + return; + this.enableMove(true, recurse); + this.enableResize(true, recurse); + this._triggerEvent('enable'); + return this; + } + /** + * Enables/disables widget moving. No-op for static grids, and locally defined items still overrule + * @param recurse true (default) if sub-grids also get updated + */ + enableMove(doEnable, recurse = true) { + if (this.opts.staticGrid) + return this; // can't move a static grid! + doEnable ? delete this.opts.disableDrag : this.opts.disableDrag = true; // FIRST before we update children as grid overrides #1658 + this.engine.nodes.forEach(n => { + this._prepareDragDropByNode(n); + if (n.subGrid && recurse) + n.subGrid.enableMove(doEnable, recurse); + }); + return this; + } + /** + * Enables/disables widget resizing. No-op for static grids. + * @param recurse true (default) if sub-grids also get updated + */ + enableResize(doEnable, recurse = true) { + if (this.opts.staticGrid) + return this; // can't size a static grid! + doEnable ? delete this.opts.disableResize : this.opts.disableResize = true; // FIRST before we update children as grid overrides #1658 + this.engine.nodes.forEach(n => { + this._prepareDragDropByNode(n); + if (n.subGrid && recurse) + n.subGrid.enableResize(doEnable, recurse); + }); + return this; + } + /** @internal removes any drag&drop present (called during destroy) */ + _removeDD(el) { + dd.draggable(el, 'destroy').resizable(el, 'destroy'); + if (el.gridstackNode) { + delete el.gridstackNode._initDD; // reset our DD init flag + } + delete el.ddElement; + return this; + } + /** @internal called to add drag over to support widgets being added externally */ + _setupAcceptWidget() { + // check if we need to disable things + if (this.opts.staticGrid || (!this.opts.acceptWidgets && !this.opts.removable)) { + dd.droppable(this.el, 'destroy'); + return this; + } + // vars shared across all methods + let cellHeight, cellWidth; + let onDrag = (event, el, helper) => { + let node = el.gridstackNode; + if (!node) + return; + helper = helper || el; + // if the element is being dragged from outside, scale it down to match the grid's scale + // and slightly adjust its position relative to the mouse + if (!node.grid?.el) { + // this scales the helper down + helper.style.transform = `scale(${1 / this.dragTransform.xScale},${1 / this.dragTransform.yScale})`; + // this makes it so that the helper is well positioned relative to the mouse after scaling + const helperRect = helper.getBoundingClientRect(); + helper.style.left = helperRect.x + (this.dragTransform.xScale - 1) * (event.clientX - helperRect.x) / this.dragTransform.xScale + 'px'; + helper.style.top = helperRect.y + (this.dragTransform.yScale - 1) * (event.clientY - helperRect.y) / this.dragTransform.yScale + 'px'; + helper.style.transformOrigin = `0px 0px`; + } + let parent = this.el.getBoundingClientRect(); + let { top, left } = helper.getBoundingClientRect(); + left -= parent.left; + top -= parent.top; + let ui = { + position: { + top: top * this.dragTransform.xScale, + left: left * this.dragTransform.yScale + } + }; + if (node._temporaryRemoved) { + node.x = Math.max(0, Math.round(left / cellWidth)); + node.y = Math.max(0, Math.round(top / cellHeight)); + delete node.autoPosition; + this.engine.nodeBoundFix(node); + // don't accept *initial* location if doesn't fit #1419 (locked drop region, or can't grow), but maybe try if it will go somewhere + if (!this.engine.willItFit(node)) { + node.autoPosition = true; // ignore x,y and try for any slot... + if (!this.engine.willItFit(node)) { + dd.off(el, 'drag'); // stop calling us + return; // full grid or can't grow + } + if (node._willFitPos) { + // use the auto position instead #1687 + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.copyPos(node, node._willFitPos); + delete node._willFitPos; + } + } + // re-use the existing node dragging method + this._onStartMoving(helper, event, ui, node, cellWidth, cellHeight); + } + else { + // re-use the existing node dragging that does so much of the collision detection + this._dragOrResize(helper, event, ui, node, cellWidth, cellHeight); + } + }; + dd.droppable(this.el, { + accept: (el) => { + let node = el.gridstackNode || this._readAttr(el, false); + // set accept drop to true on ourself (which we ignore) so we don't get "can't drop" icon in HTML5 mode while moving + if (node?.grid === this) + return true; + if (!this.opts.acceptWidgets) + return false; + // check for accept method or class matching + let canAccept = true; + if (typeof this.opts.acceptWidgets === 'function') { + canAccept = this.opts.acceptWidgets(el); + } + else { + let selector = (this.opts.acceptWidgets === true ? '.grid-stack-item' : this.opts.acceptWidgets); + canAccept = el.matches(selector); + } + // finally check to make sure we actually have space left #1571 #2633 + if (canAccept && node && this.opts.maxRow) { + let n = { w: node.w, h: node.h, minW: node.minW, minH: node.minH }; // only width/height matters and autoPosition + canAccept = this.engine.willItFit(n); + } + return canAccept; + } + }) + /** + * entering our grid area + */ + .on(this.el, 'dropover', (event, el, helper) => { + // console.log(`over ${this.el.gridstack.opts.id} ${count++}`); // TEST + let node = el.gridstackNode; + // ignore drop enter on ourself (unless we temporarily removed) which happens on a simple drag of our item + if (node?.grid === this && !node._temporaryRemoved) { + // delete node._added; // reset this to track placeholder again in case we were over other grid #1484 (dropout doesn't always clear) + return false; // prevent parent from receiving msg (which may be a grid as well) + } + // fix #1578 when dragging fast, we may not get a leave on the previous grid so force one now + if (node?.grid && node.grid !== this && !node._temporaryRemoved) { + // console.log('dropover without leave'); // TEST + let otherGrid = node.grid; + otherGrid._leave(el, helper); + } + // cache cell dimensions (which don't change), position can animate if we removed an item in otherGrid that affects us... + cellWidth = this.cellWidth(); + cellHeight = this.getCellHeight(true); + // load any element attributes if we don't have a node + if (!node) { + node = this._readAttr(el, false); // don't wipe external (e.g. drag toolbar) attr #2354 + } + if (!node.grid) { + node._isExternal = true; + el.gridstackNode = node; + } + // calculate the grid size based on element outer size + helper = helper || el; + let w = node.w || Math.round(helper.offsetWidth / cellWidth) || 1; + let h = node.h || Math.round(helper.offsetHeight / cellHeight) || 1; + // if the item came from another grid, make a copy and save the original info in case we go back there + if (node.grid && node.grid !== this) { + // copy the node original values (min/max/id/etc...) but override width/height/other flags which are this grid specific + // console.log('dropover cloning node'); // TEST + if (!el._gridstackNodeOrig) + el._gridstackNodeOrig = node; // shouldn't have multiple nested! + el.gridstackNode = node = { ...node, w, h, grid: this }; + delete node.x; + delete node.y; + this.engine.cleanupNode(node) + .nodeBoundFix(node); + // restore some internal fields we need after clearing them all + node._initDD = + node._isExternal = // DOM needs to be re-parented on a drop + node._temporaryRemoved = true; // so it can be inserted onDrag below + } + else { + node.w = w; + node.h = h; + node._temporaryRemoved = true; // so we can insert it + } + // clear any marked for complete removal (Note: don't check _isAboutToRemove as that is cleared above - just do it) + GridStack._itemRemoving(node.el, false); + dd.on(el, 'drag', onDrag); + // make sure this is called at least once when going fast #1578 + onDrag(event, el, helper); + return false; // prevent parent from receiving msg (which may be a grid as well) + }) + /** + * Leaving our grid area... + */ + .on(this.el, 'dropout', (event, el, helper) => { + // console.log(`out ${this.el.gridstack.opts.id} ${count++}`); // TEST + let node = el.gridstackNode; + if (!node) + return false; + // fix #1578 when dragging fast, we might get leave after other grid gets enter (which calls us to clean) + // so skip this one if we're not the active grid really.. + if (!node.grid || node.grid === this) { + this._leave(el, helper); + // if we were created as temporary nested grid, go back to before state + if (this._isTemp) { + this.removeAsSubGrid(node); + } + } + return false; // prevent parent from receiving msg (which may be grid as well) + }) + /** + * end - releasing the mouse + */ + .on(this.el, 'drop', (event, el, helper) => { + let node = el.gridstackNode; + // ignore drop on ourself from ourself that didn't come from the outside - dragend will handle the simple move instead + if (node?.grid === this && !node._isExternal) + return false; + const wasAdded = !!this.placeholder.parentElement; // skip items not actually added to us because of constrains, but do cleanup #1419 + this.placeholder.remove(); + // disable animation when replacing a placeholder (already positioned) with actual content + const noAnim = wasAdded && this.opts.animate; + if (noAnim) + this.setAnimation(false); + // notify previous grid of removal + // console.log('drop delete _gridstackNodeOrig') // TEST + let origNode = el._gridstackNodeOrig; + delete el._gridstackNodeOrig; + if (wasAdded && origNode?.grid && origNode.grid !== this) { + let oGrid = origNode.grid; + oGrid.engine.removeNodeFromLayoutCache(origNode); + oGrid.engine.removedNodes.push(origNode); + oGrid._triggerRemoveEvent()._triggerChangeEvent(); + // if it's an empty sub-grid that got auto-created, nuke it + if (oGrid.parentGridItem && !oGrid.engine.nodes.length && oGrid.opts.subGridDynamic) { + oGrid.removeAsSubGrid(); + } + } + if (!node) + return false; + // use existing placeholder node as it's already in our list with drop location + if (wasAdded) { + this.engine.cleanupNode(node); // removes all internal _xyz values + node.grid = this; + } + delete node.grid._isTemp; + dd.off(el, 'drag'); + // if we made a copy ('helper' which is temp) of the original node then insert a copy, else we move the original node (#1102) + // as the helper will be nuked by jquery-ui otherwise. TODO: update old code path + if (helper !== el) { + helper.remove(); + el.gridstackNode = origNode; // original item (left behind) is re-stored to pre dragging as the node now has drop info + if (wasAdded) { + el = el.cloneNode(true); + } + } + else { + el.remove(); // reduce flicker as we change depth here, and size further down + this._removeDD(el); + } + if (!wasAdded) + return false; + el.gridstackNode = node; + node.el = el; + let subGrid = node.subGrid?.el?.gridstack; // set when actual sub-grid present + // @ts-ignore + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.copyPos(node, this._readAttr(this.placeholder)); // placeholder values as moving VERY fast can throw things off #1578 + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.removePositioningStyles(el); // @ts-ignore + this.el.appendChild(el); // @ts-ignore // TODO: now would be ideal time to _removeHelperStyle() overriding floating styles (native only) + this._prepareElement(el, true, node); + if (subGrid) { + subGrid.parentGridItem = node; + if (!subGrid.opts.styleInHead) + subGrid._updateStyles(true); // re-create sub-grid styles now that we've moved + } + this._updateContainerHeight(); + this.engine.addedNodes.push(node); // @ts-ignore + this._triggerAddEvent(); // @ts-ignore + this._triggerChangeEvent(); + this.engine.endUpdate(); + if (this._gsEventHandler['dropped']) { + this._gsEventHandler['dropped']({ ...event, type: 'dropped' }, origNode && origNode.grid ? origNode : undefined, node); + } + // delay adding animation back, but check to make sure grid (opt) is still around + if (noAnim) + setTimeout(() => { if (this.opts) + this.setAnimation(this.opts.animate); }); + return false; // prevent parent from receiving msg (which may be grid as well) + }); + return this; + } + /** @internal mark item for removal */ + static _itemRemoving(el, remove) { + const node = el ? el.gridstackNode : undefined; + if (!node?.grid || el.classList.contains(node.grid.opts.removableOptions.decline)) + return; + remove ? node._isAboutToRemove = true : delete node._isAboutToRemove; + remove ? el.classList.add('grid-stack-item-removing') : el.classList.remove('grid-stack-item-removing'); + } + /** @internal called to setup a trash drop zone if the user specifies it */ + _setupRemoveDrop() { + if (typeof this.opts.removable !== 'string') + return this; + let trashEl = document.querySelector(this.opts.removable); + if (!trashEl) + return this; + // only register ONE static drop-over/dropout callback for the 'trash', and it will + // update the passed in item and parent grid because the '.trash' is a shared resource anyway, + // and Native DD only has 1 event CB (having a list and technically a per grid removableOptions complicates things greatly) + if (!this.opts.staticGrid && !dd.isDroppable(trashEl)) { + dd.droppable(trashEl, this.opts.removableOptions) + .on(trashEl, 'dropover', (event, el) => GridStack._itemRemoving(el, true)) + .on(trashEl, 'dropout', (event, el) => GridStack._itemRemoving(el, false)); + } + return this; + } + /** @internal prepares the element for drag&drop */ + _prepareDragDropByNode(node) { + let el = node.el; + const noMove = node.noMove || this.opts.disableDrag; + const noResize = node.noResize || this.opts.disableResize; + // check for disabled grid first + if (this.opts.staticGrid || (noMove && noResize)) { + if (node._initDD) { + this._removeDD(el); // nukes everything instead of just disable, will add some styles back next + delete node._initDD; + } + el.classList.add('ui-draggable-disabled', 'ui-resizable-disabled'); // add styles one might depend on #1435 + return this; + } + if (!node._initDD) { + // variables used/cashed between the 3 start/move/end methods, in addition to node passed above + let cellWidth; + let cellHeight; + /** called when item starts moving/resizing */ + let onStartMoving = (event, ui) => { + // trigger any 'dragstart' / 'resizestart' manually + if (this._gsEventHandler[event.type]) { + this._gsEventHandler[event.type](event, event.target); + } + cellWidth = this.cellWidth(); + cellHeight = this.getCellHeight(true); // force pixels for calculations + this._onStartMoving(el, event, ui, node, cellWidth, cellHeight); + }; + /** called when item is being dragged/resized */ + let dragOrResize = (event, ui) => { + this._dragOrResize(el, event, ui, node, cellWidth, cellHeight); + }; + /** called when the item stops moving/resizing */ + let onEndMoving = (event) => { + this.placeholder.remove(); + delete node._moving; + delete node._event; + delete node._lastTried; + const widthChanged = node.w !== node._orig.w; + // if the item has moved to another grid, we're done here + let target = event.target; + if (!target.gridstackNode || target.gridstackNode.grid !== this) + return; + node.el = target; + if (node._isAboutToRemove) { + let grid = el.gridstackNode.grid; + if (grid._gsEventHandler[event.type]) { + grid._gsEventHandler[event.type](event, target); + } + grid.engine.nodes.push(node); // temp add it back so we can proper remove it next + grid.removeWidget(el, true, true); + } + else { + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.removePositioningStyles(target); + if (node._temporaryRemoved) { + // got removed - restore item back to before dragging position + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.copyPos(node, node._orig); // @ts-ignore + this._writePosAttr(target, node); + this.engine.addNode(node); + } + else { + // move to new placeholder location + this._writePosAttr(target, node); + } + if (this._gsEventHandler[event.type]) { + this._gsEventHandler[event.type](event, target); + } + } + // @ts-ignore + this._extraDragRow = 0; // @ts-ignore + this._updateContainerHeight(); // @ts-ignore + this._triggerChangeEvent(); + this.engine.endUpdate(); + if (event.type === 'resizestop') { + if (Number.isInteger(node.sizeToContent)) + node.sizeToContent = node.h; // new soft limit + this.resizeToContentCheck(widthChanged, node); // wait for width animation if changed + } + }; + dd.draggable(el, { + start: onStartMoving, + stop: onEndMoving, + drag: dragOrResize + }).resizable(el, { + start: onStartMoving, + stop: onEndMoving, + resize: dragOrResize + }); + node._initDD = true; // we've set DD support now + } + // finally fine tune move vs resize by disabling any part... + dd.draggable(el, noMove ? 'disable' : 'enable') + .resizable(el, noResize ? 'disable' : 'enable'); + return this; + } + /** @internal handles actual drag/resize start */ + _onStartMoving(el, event, ui, node, cellWidth, cellHeight) { + this.engine.cleanNodes() + .beginUpdate(node); + // @ts-ignore + this._writePosAttr(this.placeholder, node); + this.el.appendChild(this.placeholder); + // console.log('_onStartMoving placeholder') // TEST + // if the element is inside a grid, it has already been scaled + // we can use that as a scale reference + if (node.grid?.el) { + this.dragTransform = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.getValuesFromTransformedElement(el); + } + // if the element is being dragged from outside (not from any grid) + // we use the grid as the transformation reference, since the helper is not subject to transformation + else if (this.placeholder && this.placeholder.closest('.grid-stack')) { + const gridEl = this.placeholder.closest('.grid-stack'); + this.dragTransform = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.getValuesFromTransformedElement(gridEl); + } + // Fallback + else { + this.dragTransform = { + xScale: 1, + xOffset: 0, + yScale: 1, + yOffset: 0, + }; + } + node.el = this.placeholder; + node._lastUiPosition = ui.position; + node._prevYPix = ui.position.top; + node._moving = (event.type === 'dragstart'); // 'dropover' are not initially moving so they can go exactly where they enter (will push stuff out of the way) + delete node._lastTried; + if (event.type === 'dropover' && node._temporaryRemoved) { + // console.log('engine.addNode x=' + node.x); // TEST + this.engine.addNode(node); // will add, fix collisions, update attr and clear _temporaryRemoved + node._moving = true; // AFTER, mark as moving object (wanted fix location before) + } + // set the min/max resize info + this.engine.cacheRects(cellWidth, cellHeight, this.opts.marginTop, this.opts.marginRight, this.opts.marginBottom, this.opts.marginLeft); + if (event.type === 'resizestart') { + dd.resizable(el, 'option', 'minWidth', cellWidth * (node.minW || 1)) + .resizable(el, 'option', 'minHeight', cellHeight * (node.minH || 1)); + if (node.maxW) { + dd.resizable(el, 'option', 'maxWidth', cellWidth * node.maxW); + } + if (node.maxH) { + dd.resizable(el, 'option', 'maxHeight', cellHeight * node.maxH); + } + } + } + /** @internal handles actual drag/resize */ + _dragOrResize(el, event, ui, node, cellWidth, cellHeight) { + let p = { ...node._orig }; // could be undefined (_isExternal) which is ok (drag only set x,y and w,h will default to node value) + let resizing; + let mLeft = this.opts.marginLeft, mRight = this.opts.marginRight, mTop = this.opts.marginTop, mBottom = this.opts.marginBottom; + // if margins (which are used to pass mid point by) are large relative to cell height/width, reduce them down #1855 + let mHeight = Math.round(cellHeight * 0.1), mWidth = Math.round(cellWidth * 0.1); + mLeft = Math.min(mLeft, mWidth); + mRight = Math.min(mRight, mWidth); + mTop = Math.min(mTop, mHeight); + mBottom = Math.min(mBottom, mHeight); + if (event.type === 'drag') { + if (node._temporaryRemoved) + return; // handled by dropover + let distance = ui.position.top - node._prevYPix; + node._prevYPix = ui.position.top; + if (this.opts.draggable.scroll !== false) { + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.updateScrollPosition(el, ui.position, distance); + } + // get new position taking into account the margin in the direction we are moving! (need to pass mid point by margin) + let left = ui.position.left + (ui.position.left > node._lastUiPosition.left ? -mRight : mLeft); + let top = ui.position.top + (ui.position.top > node._lastUiPosition.top ? -mBottom : mTop); + p.x = Math.round(left / cellWidth); + p.y = Math.round(top / cellHeight); + // @ts-ignore// if we're at the bottom hitting something else, grow the grid so cursor doesn't leave when trying to place below others + let prev = this._extraDragRow; + if (this.engine.collide(node, p)) { + let row = this.getRow(); + let extra = Math.max(0, (p.y + node.h) - row); + if (this.opts.maxRow && row + extra > this.opts.maxRow) { + extra = Math.max(0, this.opts.maxRow - row); + } // @ts-ignore + this._extraDragRow = extra; // @ts-ignore + } + else + this._extraDragRow = 0; // @ts-ignore + if (this._extraDragRow !== prev) + this._updateContainerHeight(); + if (node.x === p.x && node.y === p.y) + return; // skip same + // DON'T skip one we tried as we might have failed because of coverage <50% before + // if (node._lastTried && node._lastTried.x === x && node._lastTried.y === y) return; + } + else if (event.type === 'resize') { + if (p.x < 0) + return; + // Scrolling page if needed + _utils__WEBPACK_IMPORTED_MODULE_1__.Utils.updateScrollResize(event, el, cellHeight); + // get new size + p.w = Math.round((ui.size.width - mLeft) / cellWidth); + p.h = Math.round((ui.size.height - mTop) / cellHeight); + if (node.w === p.w && node.h === p.h) + return; + if (node._lastTried && node._lastTried.w === p.w && node._lastTried.h === p.h) + return; // skip one we tried (but failed) + // if we size on left/top side this might move us, so get possible new position as well + let left = ui.position.left + mLeft; + let top = ui.position.top + mTop; + p.x = Math.round(left / cellWidth); + p.y = Math.round(top / cellHeight); + resizing = true; + } + node._event = event; + node._lastTried = p; // set as last tried (will nuke if we go there) + let rect = { + x: ui.position.left + mLeft, + y: ui.position.top + mTop, + w: (ui.size ? ui.size.width : node.w * cellWidth) - mLeft - mRight, + h: (ui.size ? ui.size.height : node.h * cellHeight) - mTop - mBottom + }; + if (this.engine.moveNodeCheck(node, { ...p, cellWidth, cellHeight, rect, resizing })) { + node._lastUiPosition = ui.position; + this.engine.cacheRects(cellWidth, cellHeight, mTop, mRight, mBottom, mLeft); + delete node._skipDown; + if (resizing && node.subGrid) + node.subGrid.onResize(); + this._extraDragRow = 0; // @ts-ignore + this._updateContainerHeight(); + let target = event.target; // @ts-ignore + this._writePosAttr(target, node); + if (this._gsEventHandler[event.type]) { + this._gsEventHandler[event.type](event, target); + } + } + } + /** @internal called when item leaving our area by either cursor dropout event + * or shape is outside our boundaries. remove it from us, and mark temporary if this was + * our item to start with else restore prev node values from prev grid it came from. + */ + _leave(el, helper) { + let node = el.gridstackNode; + if (!node) + return; + helper = helper || el; + // restore the scale of the helper on leave + helper.style.transform = 'scale(1)'; + dd.off(el, 'drag'); // no need to track while being outside + // this gets called when cursor leaves and shape is outside, so only do this once + if (node._temporaryRemoved) + return; + node._temporaryRemoved = true; + this.engine.removeNode(node); // remove placeholder as well, otherwise it's a sign node is not in our list, which is a bigger issue + node.el = node._isExternal && helper ? helper : el; // point back to real item being dragged + if (this.opts.removable === true) { // boolean vs a class string + // item leaving us and we are supposed to remove on leave (no need to drag onto trash) mark it so + GridStack._itemRemoving(el, true); + } + // finally if item originally came from another grid, but left us, restore things back to prev info + if (el._gridstackNodeOrig) { + // console.log('leave delete _gridstackNodeOrig') // TEST + el.gridstackNode = el._gridstackNodeOrig; + delete el._gridstackNodeOrig; + } + else if (node._isExternal) { + // item came from outside (like a toolbar) so nuke any node info + delete node.el; + delete el.gridstackNode; + // and restore all nodes back to original + this.engine.restoreInitial(); + } + } + // legacy method removed + commit() { (0,_utils__WEBPACK_IMPORTED_MODULE_1__.obsolete)(this, this.batchUpdate(false), 'commit', 'batchUpdate', '5.2'); return this; } +} +/** parent class for sizing content. defaults to '.grid-stack-item-content' */ +GridStack.resizeToContentParent = '.grid-stack-item-content'; +/** scoping so users can call GridStack.Utils.sort() for example */ +GridStack.Utils = _utils__WEBPACK_IMPORTED_MODULE_1__.Utils; +/** scoping so users can call new GridStack.Engine(12) for example */ +GridStack.Engine = _gridstack_engine__WEBPACK_IMPORTED_MODULE_0__.GridStackEngine; +GridStack.GDRev = '10.1.2'; + +//# sourceMappingURL=gridstack.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/types.js": +/*!**********************************************!*\ + !*** ./node_modules/gridstack/dist/types.js ***! + \**********************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ dragInDefaultOptions: () => (/* binding */ dragInDefaultOptions), +/* harmony export */ gridDefaults: () => (/* binding */ gridDefaults) +/* harmony export */ }); +/** + * types.ts 10.1.2 + * Copyright (c) 2021 Alain Dumesny - see GridStack root license + */ +// default values for grid options - used during init and when saving out +const gridDefaults = { + alwaysShowResizeHandle: 'mobile', + animate: true, + auto: true, + cellHeight: 'auto', + cellHeightThrottle: 100, + cellHeightUnit: 'px', + column: 12, + draggable: { handle: '.grid-stack-item-content', appendTo: 'body', scroll: true }, + handle: '.grid-stack-item-content', + itemClass: 'grid-stack-item', + margin: 10, + marginUnit: 'px', + maxRow: 0, + minRow: 0, + placeholderClass: 'grid-stack-placeholder', + placeholderText: '', + removableOptions: { accept: 'grid-stack-item', decline: 'grid-stack-non-removable' }, + resizable: { handles: 'se' }, + rtl: 'auto', + // **** same as not being set **** + // disableDrag: false, + // disableResize: false, + // float: false, + // handleClass: null, + // removable: false, + // staticGrid: false, + // styleInHead: false, + //removable +}; +/** default dragIn options */ +const dragInDefaultOptions = { + handle: '.grid-stack-item-content', + appendTo: 'body', + // revert: 'invalid', + // scroll: false, +}; +//# sourceMappingURL=types.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/utils.js": +/*!**********************************************!*\ + !*** ./node_modules/gridstack/dist/utils.js ***! + \**********************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ Utils: () => (/* binding */ Utils), +/* harmony export */ obsolete: () => (/* binding */ obsolete), +/* harmony export */ obsoleteAttr: () => (/* binding */ obsoleteAttr), +/* harmony export */ obsoleteOpts: () => (/* binding */ obsoleteOpts), +/* harmony export */ obsoleteOptsDel: () => (/* binding */ obsoleteOptsDel) +/* harmony export */ }); +/** + * utils.ts 10.1.2 + * Copyright (c) 2021 Alain Dumesny - see GridStack root license + */ +/** checks for obsolete method names */ +// eslint-disable-next-line +function obsolete(self, f, oldName, newName, rev) { + let wrapper = (...args) => { + console.warn('gridstack.js: Function `' + oldName + '` is deprecated in ' + rev + ' and has been replaced ' + + 'with `' + newName + '`. It will be **removed** in a future release'); + return f.apply(self, args); + }; + wrapper.prototype = f.prototype; + return wrapper; +} +/** checks for obsolete grid options (can be used for any fields, but msg is about options) */ +function obsoleteOpts(opts, oldName, newName, rev) { + if (opts[oldName] !== undefined) { + opts[newName] = opts[oldName]; + console.warn('gridstack.js: Option `' + oldName + '` is deprecated in ' + rev + ' and has been replaced with `' + + newName + '`. It will be **removed** in a future release'); + } +} +/** checks for obsolete grid options which are gone */ +function obsoleteOptsDel(opts, oldName, rev, info) { + if (opts[oldName] !== undefined) { + console.warn('gridstack.js: Option `' + oldName + '` is deprecated in ' + rev + info); + } +} +/** checks for obsolete Jquery element attributes */ +function obsoleteAttr(el, oldName, newName, rev) { + let oldAttr = el.getAttribute(oldName); + if (oldAttr !== null) { + el.setAttribute(newName, oldAttr); + console.warn('gridstack.js: attribute `' + oldName + '`=' + oldAttr + ' is deprecated on this object in ' + rev + ' and has been replaced with `' + + newName + '`. It will be **removed** in a future release'); + } +} +/** + * Utility methods + */ +class Utils { + /** convert a potential selector into actual list of html elements. optional root which defaults to document (for shadow dom) */ + static getElements(els, root = document) { + if (typeof els === 'string') { + const doc = ('getElementById' in root) ? root : undefined; + // Note: very common for people use to id='1,2,3' which is only legal as HTML5 id, but not CSS selectors + // so if we start with a number, assume it's an id and just return that one item... + // see https://github.com/gridstack/gridstack.js/issues/2234#issuecomment-1523796562 + if (doc && !isNaN(+els[0])) { // start with digit + const el = doc.getElementById(els); + return el ? [el] : []; + } + let list = root.querySelectorAll(els); + if (!list.length && els[0] !== '.' && els[0] !== '#') { + list = root.querySelectorAll('.' + els); + if (!list.length) { + list = root.querySelectorAll('#' + els); + } + } + return Array.from(list); + } + return [els]; + } + /** convert a potential selector into actual single element. optional root which defaults to document (for shadow dom) */ + static getElement(els, root = document) { + if (typeof els === 'string') { + const doc = ('getElementById' in root) ? root : undefined; + if (!els.length) + return null; + if (doc && els[0] === '#') { + return doc.getElementById(els.substring(1)); + } + if (els[0] === '#' || els[0] === '.' || els[0] === '[') { + return root.querySelector(els); + } + // if we start with a digit, assume it's an id (error calling querySelector('#1')) as class are not valid CSS + if (doc && !isNaN(+els[0])) { // start with digit + return doc.getElementById(els); + } + // finally try string, then id, then class + let el = root.querySelector(els); + if (doc && !el) { + el = doc.getElementById(els); + } + if (!el) { + el = root.querySelector('.' + els); + } + return el; + } + return els; + } + /** true if we should resize to content. strict=true when only 'sizeToContent:true' and not a number which lets user adjust */ + static shouldSizeToContent(n, strict = false) { + return n?.grid && (strict ? + (n.sizeToContent === true || (n.grid.opts.sizeToContent === true && n.sizeToContent === undefined)) : + (!!n.sizeToContent || (n.grid.opts.sizeToContent && n.sizeToContent !== false))); + } + /** returns true if a and b overlap */ + static isIntercepted(a, b) { + return !(a.y >= b.y + b.h || a.y + a.h <= b.y || a.x + a.w <= b.x || a.x >= b.x + b.w); + } + /** returns true if a and b touch edges or corners */ + static isTouching(a, b) { + return Utils.isIntercepted(a, { x: b.x - 0.5, y: b.y - 0.5, w: b.w + 1, h: b.h + 1 }); + } + /** returns the area a and b overlap */ + static areaIntercept(a, b) { + let x0 = (a.x > b.x) ? a.x : b.x; + let x1 = (a.x + a.w < b.x + b.w) ? a.x + a.w : b.x + b.w; + if (x1 <= x0) + return 0; // no overlap + let y0 = (a.y > b.y) ? a.y : b.y; + let y1 = (a.y + a.h < b.y + b.h) ? a.y + a.h : b.y + b.h; + if (y1 <= y0) + return 0; // no overlap + return (x1 - x0) * (y1 - y0); + } + /** returns the area */ + static area(a) { + return a.w * a.h; + } + /** + * Sorts array of nodes + * @param nodes array to sort + * @param dir 1 for ascending, -1 for descending (optional) + **/ + static sort(nodes, dir = 1) { + const und = 10000; + return nodes.sort((a, b) => { + let diffY = dir * ((a.y ?? und) - (b.y ?? und)); + if (diffY === 0) + return dir * ((a.x ?? und) - (b.x ?? und)); + return diffY; + }); + } + /** find an item by id */ + static find(nodes, id) { + return id ? nodes.find(n => n.id === id) : undefined; + } + /** + * creates a style sheet with style id under given parent + * @param id will set the 'gs-style-id' attribute to that id + * @param parent to insert the stylesheet as first child, + * if none supplied it will be appended to the document head instead. + */ + static createStylesheet(id, parent, options) { + let style = document.createElement('style'); + const nonce = options?.nonce; + if (nonce) + style.nonce = nonce; + style.setAttribute('type', 'text/css'); + style.setAttribute('gs-style-id', id); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (style.styleSheet) { // TODO: only CSSImportRule have that and different beast ?? + // eslint-disable-next-line @typescript-eslint/no-explicit-any + style.styleSheet.cssText = ''; + } + else { + style.appendChild(document.createTextNode('')); // WebKit hack + } + if (!parent) { + // default to head + parent = document.getElementsByTagName('head')[0]; + parent.appendChild(style); + } + else { + parent.insertBefore(style, parent.firstChild); + } + return style.sheet; + } + /** removed the given stylesheet id */ + static removeStylesheet(id, parent) { + const target = parent || document; + let el = target.querySelector('STYLE[gs-style-id=' + id + ']'); + if (el && el.parentNode) + el.remove(); + } + /** inserts a CSS rule */ + static addCSSRule(sheet, selector, rules) { + if (typeof sheet.addRule === 'function') { + sheet.addRule(selector, rules); + } + else if (typeof sheet.insertRule === 'function') { + sheet.insertRule(`${selector}{${rules}}`); + } + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + static toBool(v) { + if (typeof v === 'boolean') { + return v; + } + if (typeof v === 'string') { + v = v.toLowerCase(); + return !(v === '' || v === 'no' || v === 'false' || v === '0'); + } + return Boolean(v); + } + static toNumber(value) { + return (value === null || value.length === 0) ? undefined : Number(value); + } + static parseHeight(val) { + let h; + let unit = 'px'; + if (typeof val === 'string') { + if (val === 'auto' || val === '') + h = 0; + else { + let match = val.match(/^(-[0-9]+\.[0-9]+|[0-9]*\.[0-9]+|-[0-9]+|[0-9]+)(px|em|rem|vh|vw|%|cm|mm)?$/); + if (!match) { + throw new Error(`Invalid height val = ${val}`); + } + unit = match[2] || 'px'; + h = parseFloat(match[1]); + } + } + else { + h = val; + } + return { h, unit }; + } + /** copies unset fields in target to use the given default sources values */ + // eslint-disable-next-line + static defaults(target, ...sources) { + sources.forEach(source => { + for (const key in source) { + if (!source.hasOwnProperty(key)) + return; + if (target[key] === null || target[key] === undefined) { + target[key] = source[key]; + } + else if (typeof source[key] === 'object' && typeof target[key] === 'object') { + // property is an object, recursively add it's field over... #1373 + this.defaults(target[key], source[key]); + } + } + }); + return target; + } + /** given 2 objects return true if they have the same values. Checks for Object {} having same fields and values (just 1 level down) */ + static same(a, b) { + if (typeof a !== 'object') + return a == b; + if (typeof a !== typeof b) + return false; + // else we have object, check just 1 level deep for being same things... + if (Object.keys(a).length !== Object.keys(b).length) + return false; + for (const key in a) { + if (a[key] !== b[key]) + return false; + } + return true; + } + /** copies over b size & position (GridStackPosition), and optionally min/max as well */ + static copyPos(a, b, doMinMax = false) { + if (b.x !== undefined) + a.x = b.x; + if (b.y !== undefined) + a.y = b.y; + if (b.w !== undefined) + a.w = b.w; + if (b.h !== undefined) + a.h = b.h; + if (doMinMax) { + if (b.minW) + a.minW = b.minW; + if (b.minH) + a.minH = b.minH; + if (b.maxW) + a.maxW = b.maxW; + if (b.maxH) + a.maxH = b.maxH; + } + return a; + } + /** true if a and b has same size & position */ + static samePos(a, b) { + return a && b && a.x === b.x && a.y === b.y && (a.w || 1) === (b.w || 1) && (a.h || 1) === (b.h || 1); + } + /** given a node, makes sure it's min/max are valid */ + static sanitizeMinMax(node) { + // remove 0, undefine, null + if (!node.minW) { + delete node.minW; + } + if (!node.minH) { + delete node.minH; + } + if (!node.maxW) { + delete node.maxW; + } + if (!node.maxH) { + delete node.maxH; + } + } + /** removes field from the first object if same as the second objects (like diffing) and internal '_' for saving */ + static removeInternalAndSame(a, b) { + if (typeof a !== 'object' || typeof b !== 'object') + return; + for (let key in a) { + let val = a[key]; + if (key[0] === '_' || val === b[key]) { + delete a[key]; + } + else if (val && typeof val === 'object' && b[key] !== undefined) { + for (let i in val) { + if (val[i] === b[key][i] || i[0] === '_') { + delete val[i]; + } + } + if (!Object.keys(val).length) { + delete a[key]; + } + } + } + } + /** removes internal fields '_' and default values for saving */ + static removeInternalForSave(n, removeEl = true) { + for (let key in n) { + if (key[0] === '_' || n[key] === null || n[key] === undefined) + delete n[key]; + } + delete n.grid; + if (removeEl) + delete n.el; + // delete default values (will be re-created on read) + if (!n.autoPosition) + delete n.autoPosition; + if (!n.noResize) + delete n.noResize; + if (!n.noMove) + delete n.noMove; + if (!n.locked) + delete n.locked; + if (n.w === 1 || n.w === n.minW) + delete n.w; + if (n.h === 1 || n.h === n.minH) + delete n.h; + } + /** return the closest parent (or itself) matching the given class */ + // static closestUpByClass(el: HTMLElement, name: string): HTMLElement { + // while (el) { + // if (el.classList.contains(name)) return el; + // el = el.parentElement + // } + // return null; + // } + /** delay calling the given function for given delay, preventing new calls from happening while waiting */ + static throttle(func, delay) { + let isWaiting = false; + return (...args) => { + if (!isWaiting) { + isWaiting = true; + setTimeout(() => { func(...args); isWaiting = false; }, delay); + } + }; + } + static removePositioningStyles(el) { + let style = el.style; + if (style.position) { + style.removeProperty('position'); + } + if (style.left) { + style.removeProperty('left'); + } + if (style.top) { + style.removeProperty('top'); + } + if (style.width) { + style.removeProperty('width'); + } + if (style.height) { + style.removeProperty('height'); + } + } + /** @internal returns the passed element if scrollable, else the closest parent that will, up to the entire document scrolling element */ + static getScrollElement(el) { + if (!el) + return document.scrollingElement || document.documentElement; // IE support + const style = getComputedStyle(el); + const overflowRegex = /(auto|scroll)/; + if (overflowRegex.test(style.overflow + style.overflowY)) { + return el; + } + else { + return this.getScrollElement(el.parentElement); + } + } + /** @internal */ + static updateScrollPosition(el, position, distance) { + // is widget in view? + let rect = el.getBoundingClientRect(); + let innerHeightOrClientHeight = (window.innerHeight || document.documentElement.clientHeight); + if (rect.top < 0 || + rect.bottom > innerHeightOrClientHeight) { + // set scrollTop of first parent that scrolls + // if parent is larger than el, set as low as possible + // to get entire widget on screen + let offsetDiffDown = rect.bottom - innerHeightOrClientHeight; + let offsetDiffUp = rect.top; + let scrollEl = this.getScrollElement(el); + if (scrollEl !== null) { + let prevScroll = scrollEl.scrollTop; + if (rect.top < 0 && distance < 0) { + // moving up + if (el.offsetHeight > innerHeightOrClientHeight) { + scrollEl.scrollTop += distance; + } + else { + scrollEl.scrollTop += Math.abs(offsetDiffUp) > Math.abs(distance) ? distance : offsetDiffUp; + } + } + else if (distance > 0) { + // moving down + if (el.offsetHeight > innerHeightOrClientHeight) { + scrollEl.scrollTop += distance; + } + else { + scrollEl.scrollTop += offsetDiffDown > distance ? distance : offsetDiffDown; + } + } + // move widget y by amount scrolled + position.top += scrollEl.scrollTop - prevScroll; + } + } + } + /** + * @internal Function used to scroll the page. + * + * @param event `MouseEvent` that triggers the resize + * @param el `HTMLElement` that's being resized + * @param distance Distance from the V edges to start scrolling + */ + static updateScrollResize(event, el, distance) { + const scrollEl = this.getScrollElement(el); + const height = scrollEl.clientHeight; + // #1727 event.clientY is relative to viewport, so must compare this against position of scrollEl getBoundingClientRect().top + // #1745 Special situation if scrollEl is document 'html': here browser spec states that + // clientHeight is height of viewport, but getBoundingClientRect() is rectangle of html element; + // this discrepancy arises because in reality scrollbar is attached to viewport, not html element itself. + const offsetTop = (scrollEl === this.getScrollElement()) ? 0 : scrollEl.getBoundingClientRect().top; + const pointerPosY = event.clientY - offsetTop; + const top = pointerPosY < distance; + const bottom = pointerPosY > height - distance; + if (top) { + // This also can be done with a timeout to keep scrolling while the mouse is + // in the scrolling zone. (will have smoother behavior) + scrollEl.scrollBy({ behavior: 'smooth', top: pointerPosY - distance }); + } + else if (bottom) { + scrollEl.scrollBy({ behavior: 'smooth', top: distance - (height - pointerPosY) }); + } + } + /** single level clone, returning a new object with same top fields. This will share sub objects and arrays */ + static clone(obj) { + if (obj === null || obj === undefined || typeof (obj) !== 'object') { + return obj; + } + // return Object.assign({}, obj); + if (obj instanceof Array) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return [...obj]; + } + return { ...obj }; + } + /** + * Recursive clone version that returns a full copy, checking for nested objects and arrays ONLY. + * Note: this will use as-is any key starting with double __ (and not copy inside) some lib have circular dependencies. + */ + static cloneDeep(obj) { + // list of fields we will skip during cloneDeep (nested objects, other internal) + const skipFields = ['parentGrid', 'el', 'grid', 'subGrid', 'engine']; + // return JSON.parse(JSON.stringify(obj)); // doesn't work with date format ? + const ret = Utils.clone(obj); + for (const key in ret) { + // NOTE: we don't support function/circular dependencies so skip those properties for now... + if (ret.hasOwnProperty(key) && typeof (ret[key]) === 'object' && key.substring(0, 2) !== '__' && !skipFields.find(k => k === key)) { + ret[key] = Utils.cloneDeep(obj[key]); + } + } + return ret; + } + /** deep clone the given HTML node, removing teh unique id field */ + static cloneNode(el) { + const node = el.cloneNode(true); + node.removeAttribute('id'); + return node; + } + static appendTo(el, parent) { + let parentNode; + if (typeof parent === 'string') { + parentNode = Utils.getElement(parent); + } + else { + parentNode = parent; + } + if (parentNode) { + parentNode.appendChild(el); + } + } + // public static setPositionRelative(el: HTMLElement): void { + // if (!(/^(?:r|a|f)/).test(getComputedStyle(el).position)) { + // el.style.position = "relative"; + // } + // } + static addElStyles(el, styles) { + if (styles instanceof Object) { + for (const s in styles) { + if (styles.hasOwnProperty(s)) { + if (Array.isArray(styles[s])) { + // support fallback value + styles[s].forEach(val => { + el.style[s] = val; + }); + } + else { + el.style[s] = styles[s]; + } + } + } + } + } + static initEvent(e, info) { + const evt = { type: info.type }; + const obj = { + button: 0, + which: 0, + buttons: 1, + bubbles: true, + cancelable: true, + target: info.target ? info.target : e.target + }; + // don't check for `instanceof DragEvent` as Safari use MouseEvent #1540 + if (e.dataTransfer) { + evt['dataTransfer'] = e.dataTransfer; // workaround 'readonly' field. + } + ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'].forEach(p => evt[p] = e[p]); // keys + ['pageX', 'pageY', 'clientX', 'clientY', 'screenX', 'screenY'].forEach(p => evt[p] = e[p]); // point info + return { ...evt, ...obj }; + } + /** copies the MouseEvent properties and sends it as another event to the given target */ + static simulateMouseEvent(e, simulatedType, target) { + const simulatedEvent = document.createEvent('MouseEvents'); + simulatedEvent.initMouseEvent(simulatedType, // type + true, // bubbles + true, // cancelable + window, // view + 1, // detail + e.screenX, // screenX + e.screenY, // screenY + e.clientX, // clientX + e.clientY, // clientY + e.ctrlKey, // ctrlKey + e.altKey, // altKey + e.shiftKey, // shiftKey + e.metaKey, // metaKey + 0, // button + e.target // relatedTarget + ); + (target || e.target).dispatchEvent(simulatedEvent); + } + /** + * defines an element that is used to get the offset and scale from grid transforms + * returns the scale and offsets from said element + */ + static getValuesFromTransformedElement(parent) { + const transformReference = document.createElement('div'); + Utils.addElStyles(transformReference, { + opacity: '0', + position: 'fixed', + top: 0 + 'px', + left: 0 + 'px', + width: '1px', + height: '1px', + zIndex: '-999999', + }); + parent.appendChild(transformReference); + const transformValues = transformReference.getBoundingClientRect(); + parent.removeChild(transformReference); + transformReference.remove(); + return { + xScale: 1 / transformValues.width, + yScale: 1 / transformValues.height, + xOffset: transformValues.left, + yOffset: transformValues.top, + }; + } +} +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ "./node_modules/gridstack/dist/gridstack-extra.min.css": +/*!*************************************************************!*\ + !*** ./node_modules/gridstack/dist/gridstack-extra.min.css ***! + \*************************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !../../style-loader/dist/runtime/injectStylesIntoStyleTag.js */ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js"); +/* harmony import */ var _style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !../../style-loader/dist/runtime/styleDomAPI.js */ "./node_modules/style-loader/dist/runtime/styleDomAPI.js"); +/* harmony import */ var _style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var _style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../style-loader/dist/runtime/insertBySelector.js */ "./node_modules/style-loader/dist/runtime/insertBySelector.js"); +/* harmony import */ var _style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! !../../style-loader/dist/runtime/setAttributesWithoutAttributes.js */ "./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js"); +/* harmony import */ var _style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! !../../style-loader/dist/runtime/insertStyleElement.js */ "./node_modules/style-loader/dist/runtime/insertStyleElement.js"); +/* harmony import */ var _style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__); +/* harmony import */ var _style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! !../../style-loader/dist/runtime/styleTagTransform.js */ "./node_modules/style-loader/dist/runtime/styleTagTransform.js"); +/* harmony import */ var _style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__); +/* harmony import */ var _css_loader_dist_cjs_js_gridstack_extra_min_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../../css-loader/dist/cjs.js!./gridstack-extra.min.css */ "./node_modules/css-loader/dist/cjs.js!./node_modules/gridstack/dist/gridstack-extra.min.css"); + + + + + + + + + + + +var options = {}; + +options.styleTagTransform = (_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default()); +options.setAttributes = (_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default()); +options.insert = _style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, "head"); +options.domAPI = (_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default()); +options.insertStyleElement = (_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default()); + +var update = _style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_css_loader_dist_cjs_js_gridstack_extra_min_css__WEBPACK_IMPORTED_MODULE_6__["default"], options); + + + + + /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_css_loader_dist_cjs_js_gridstack_extra_min_css__WEBPACK_IMPORTED_MODULE_6__["default"] && _css_loader_dist_cjs_js_gridstack_extra_min_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals ? _css_loader_dist_cjs_js_gridstack_extra_min_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals : undefined); + + +/***/ }), + +/***/ "./node_modules/gridstack/dist/gridstack.min.css": +/*!*******************************************************!*\ + !*** ./node_modules/gridstack/dist/gridstack.min.css ***! + \*******************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !../../style-loader/dist/runtime/injectStylesIntoStyleTag.js */ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js"); +/* harmony import */ var _style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !../../style-loader/dist/runtime/styleDomAPI.js */ "./node_modules/style-loader/dist/runtime/styleDomAPI.js"); +/* harmony import */ var _style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var _style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../style-loader/dist/runtime/insertBySelector.js */ "./node_modules/style-loader/dist/runtime/insertBySelector.js"); +/* harmony import */ var _style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! !../../style-loader/dist/runtime/setAttributesWithoutAttributes.js */ "./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js"); +/* harmony import */ var _style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! !../../style-loader/dist/runtime/insertStyleElement.js */ "./node_modules/style-loader/dist/runtime/insertStyleElement.js"); +/* harmony import */ var _style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__); +/* harmony import */ var _style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! !../../style-loader/dist/runtime/styleTagTransform.js */ "./node_modules/style-loader/dist/runtime/styleTagTransform.js"); +/* harmony import */ var _style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__); +/* harmony import */ var _css_loader_dist_cjs_js_gridstack_min_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../../css-loader/dist/cjs.js!./gridstack.min.css */ "./node_modules/css-loader/dist/cjs.js!./node_modules/gridstack/dist/gridstack.min.css"); + + + + + + + + + + + +var options = {}; + +options.styleTagTransform = (_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default()); +options.setAttributes = (_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default()); +options.insert = _style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, "head"); +options.domAPI = (_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default()); +options.insertStyleElement = (_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default()); + +var update = _style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_css_loader_dist_cjs_js_gridstack_min_css__WEBPACK_IMPORTED_MODULE_6__["default"], options); + + + + + /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_css_loader_dist_cjs_js_gridstack_min_css__WEBPACK_IMPORTED_MODULE_6__["default"] && _css_loader_dist_cjs_js_gridstack_min_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals ? _css_loader_dist_cjs_js_gridstack_min_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals : undefined); + + +/***/ }), + +/***/ "./srcjs/css/custom.css": +/*!******************************!*\ + !*** ./srcjs/css/custom.css ***! + \******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js"); +/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/styleDomAPI.js */ "./node_modules/style-loader/dist/runtime/styleDomAPI.js"); +/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/insertBySelector.js */ "./node_modules/style-loader/dist/runtime/insertBySelector.js"); +/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js */ "./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js"); +/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/insertStyleElement.js */ "./node_modules/style-loader/dist/runtime/insertStyleElement.js"); +/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__); +/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/styleTagTransform.js */ "./node_modules/style-loader/dist/runtime/styleTagTransform.js"); +/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__); +/* harmony import */ var _node_modules_css_loader_dist_cjs_js_custom_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../../node_modules/css-loader/dist/cjs.js!./custom.css */ "./node_modules/css-loader/dist/cjs.js!./srcjs/css/custom.css"); + + + + + + + + + + + +var options = {}; + +options.styleTagTransform = (_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default()); +options.setAttributes = (_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default()); +options.insert = _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, "head"); +options.domAPI = (_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default()); +options.insertStyleElement = (_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default()); + +var update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_node_modules_css_loader_dist_cjs_js_custom_css__WEBPACK_IMPORTED_MODULE_6__["default"], options); + + + + + /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_custom_css__WEBPACK_IMPORTED_MODULE_6__["default"] && _node_modules_css_loader_dist_cjs_js_custom_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals ? _node_modules_css_loader_dist_cjs_js_custom_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals : undefined); + + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js": +/*!****************************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js ***! + \****************************************************************************/ +/***/ ((module) => { + + + +var stylesInDOM = []; +function getIndexByIdentifier(identifier) { + var result = -1; + for (var i = 0; i < stylesInDOM.length; i++) { + if (stylesInDOM[i].identifier === identifier) { + result = i; + break; + } + } + return result; +} +function modulesToDom(list, options) { + var idCountMap = {}; + var identifiers = []; + for (var i = 0; i < list.length; i++) { + var item = list[i]; + var id = options.base ? item[0] + options.base : item[0]; + var count = idCountMap[id] || 0; + var identifier = "".concat(id, " ").concat(count); + idCountMap[id] = count + 1; + var indexByIdentifier = getIndexByIdentifier(identifier); + var obj = { + css: item[1], + media: item[2], + sourceMap: item[3], + supports: item[4], + layer: item[5] + }; + if (indexByIdentifier !== -1) { + stylesInDOM[indexByIdentifier].references++; + stylesInDOM[indexByIdentifier].updater(obj); + } else { + var updater = addElementStyle(obj, options); + options.byIndex = i; + stylesInDOM.splice(i, 0, { + identifier: identifier, + updater: updater, + references: 1 + }); + } + identifiers.push(identifier); + } + return identifiers; +} +function addElementStyle(obj, options) { + var api = options.domAPI(options); + api.update(obj); + var updater = function updater(newObj) { + if (newObj) { + if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap && newObj.supports === obj.supports && newObj.layer === obj.layer) { + return; + } + api.update(obj = newObj); + } else { + api.remove(); + } + }; + return updater; +} +module.exports = function (list, options) { + options = options || {}; + list = list || []; + var lastIdentifiers = modulesToDom(list, options); + return function update(newList) { + newList = newList || []; + for (var i = 0; i < lastIdentifiers.length; i++) { + var identifier = lastIdentifiers[i]; + var index = getIndexByIdentifier(identifier); + stylesInDOM[index].references--; + } + var newLastIdentifiers = modulesToDom(newList, options); + for (var _i = 0; _i < lastIdentifiers.length; _i++) { + var _identifier = lastIdentifiers[_i]; + var _index = getIndexByIdentifier(_identifier); + if (stylesInDOM[_index].references === 0) { + stylesInDOM[_index].updater(); + stylesInDOM.splice(_index, 1); + } + } + lastIdentifiers = newLastIdentifiers; + }; +}; + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/insertBySelector.js": +/*!********************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/insertBySelector.js ***! + \********************************************************************/ +/***/ ((module) => { + + + +var memo = {}; + +/* istanbul ignore next */ +function getTarget(target) { + if (typeof memo[target] === "undefined") { + var styleTarget = document.querySelector(target); + + // Special case to return head of iframe instead of iframe itself + if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) { + try { + // This will throw an exception if access to iframe is blocked + // due to cross-origin restrictions + styleTarget = styleTarget.contentDocument.head; + } catch (e) { + // istanbul ignore next + styleTarget = null; + } + } + memo[target] = styleTarget; + } + return memo[target]; +} + +/* istanbul ignore next */ +function insertBySelector(insert, style) { + var target = getTarget(insert); + if (!target) { + throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid."); + } + target.appendChild(style); +} +module.exports = insertBySelector; + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/insertStyleElement.js": +/*!**********************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/insertStyleElement.js ***! + \**********************************************************************/ +/***/ ((module) => { + + + +/* istanbul ignore next */ +function insertStyleElement(options) { + var element = document.createElement("style"); + options.setAttributes(element, options.attributes); + options.insert(element, options.options); + return element; +} +module.exports = insertStyleElement; + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js": +/*!**********************************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js ***! + \**********************************************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + + + +/* istanbul ignore next */ +function setAttributesWithoutAttributes(styleElement) { + var nonce = true ? __webpack_require__.nc : 0; + if (nonce) { + styleElement.setAttribute("nonce", nonce); + } +} +module.exports = setAttributesWithoutAttributes; + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/styleDomAPI.js": +/*!***************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/styleDomAPI.js ***! + \***************************************************************/ +/***/ ((module) => { + + + +/* istanbul ignore next */ +function apply(styleElement, options, obj) { + var css = ""; + if (obj.supports) { + css += "@supports (".concat(obj.supports, ") {"); + } + if (obj.media) { + css += "@media ".concat(obj.media, " {"); + } + var needLayer = typeof obj.layer !== "undefined"; + if (needLayer) { + css += "@layer".concat(obj.layer.length > 0 ? " ".concat(obj.layer) : "", " {"); + } + css += obj.css; + if (needLayer) { + css += "}"; + } + if (obj.media) { + css += "}"; + } + if (obj.supports) { + css += "}"; + } + var sourceMap = obj.sourceMap; + if (sourceMap && typeof btoa !== "undefined") { + css += "\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), " */"); + } + + // For old IE + /* istanbul ignore if */ + options.styleTagTransform(css, styleElement, options.options); +} +function removeStyleElement(styleElement) { + // istanbul ignore if + if (styleElement.parentNode === null) { + return false; + } + styleElement.parentNode.removeChild(styleElement); +} + +/* istanbul ignore next */ +function domAPI(options) { + if (typeof document === "undefined") { + return { + update: function update() {}, + remove: function remove() {} + }; + } + var styleElement = options.insertStyleElement(options); + return { + update: function update(obj) { + apply(styleElement, options, obj); + }, + remove: function remove() { + removeStyleElement(styleElement); + } + }; +} +module.exports = domAPI; + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/styleTagTransform.js": +/*!*********************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/styleTagTransform.js ***! + \*********************************************************************/ +/***/ ((module) => { + + + +/* istanbul ignore next */ +function styleTagTransform(css, styleElement) { + if (styleElement.styleSheet) { + styleElement.styleSheet.cssText = css; + } else { + while (styleElement.firstChild) { + styleElement.removeChild(styleElement.firstChild); + } + styleElement.appendChild(document.createTextNode(css)); + } +} +module.exports = styleTagTransform; + +/***/ }), + +/***/ "./srcjs/modules/utils.js": +/*!********************************!*\ + !*** ./srcjs/modules/utils.js ***! + \********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getWidget: () => (/* binding */ getWidget) +/* harmony export */ }); + +// From Friss tuto (https://github.com/FrissAnalytics/shinyJsTutorials/blob/master/tutorials/tutorial_03.Rmd) +function getWidget(id) { + var htmlWidgetsObj = HTMLWidgets.find("#" + id); + var widgetObj; + if (typeof htmlWidgetsObj !== "undefined") { + widgetObj = htmlWidgetsObj.getWidget(); + } + return widgetObj; +} + + +/***/ }), + +/***/ "data:image/svg+xml;utf8,": +/*!****************************************************************************************************************************************************************************************************************************************!*\ + !*** data:image/svg+xml;utf8, ***! + \****************************************************************************************************************************************************************************************************************************************/ +/***/ ((module) => { + +module.exports = "data:image/svg+xml;utf8,"; + +/***/ }), + +/***/ "widgets": +/*!******************************!*\ + !*** external "HTMLWidgets" ***! + \******************************/ +/***/ ((module) => { + +module.exports = HTMLWidgets; + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ id: moduleId, +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = __webpack_modules__; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/jsonp chunk loading */ +/******/ (() => { +/******/ __webpack_require__.b = document.baseURI || self.location.href; +/******/ +/******/ // object to store loaded and loading chunks +/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched +/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded +/******/ var installedChunks = { +/******/ "gridstack": 0 +/******/ }; +/******/ +/******/ // no chunk on demand loading +/******/ +/******/ // no prefetching +/******/ +/******/ // no preloaded +/******/ +/******/ // no HMR +/******/ +/******/ // no HMR manifest +/******/ +/******/ // no on chunks loaded +/******/ +/******/ // no jsonp function +/******/ })(); +/******/ +/******/ /* webpack/runtime/nonce */ +/******/ (() => { +/******/ __webpack_require__.nc = undefined; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!************************************!*\ + !*** ./srcjs/widgets/gridstack.js ***! + \************************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var widgets__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! widgets */ "widgets"); +/* harmony import */ var widgets__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(widgets__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var gridstack_dist_gridstack_min_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gridstack/dist/gridstack.min.css */ "./node_modules/gridstack/dist/gridstack.min.css"); +/* harmony import */ var gridstack_dist_gridstack_extra_min_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! gridstack/dist/gridstack-extra.min.css */ "./node_modules/gridstack/dist/gridstack-extra.min.css"); +/* harmony import */ var gridstack__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! gridstack */ "./node_modules/gridstack/dist/gridstack.js"); +/* harmony import */ var _css_custom_css__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../css/custom.css */ "./srcjs/css/custom.css"); +/* harmony import */ var _modules_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../modules/utils */ "./srcjs/modules/utils.js"); + + + + + + + +HTMLWidgets.widget({ + + name: "gridstack", + + type: "output", + + factory: function(el, width, height) { + + var grid; + + return { + + renderValue: function(x) { + + el.classList.add("grid-stack"); + el.classList.add("grid-stack-edit"); + el.style.background = x.bg; + el.innerHTML = x.html; + + grid = gridstack__WEBPACK_IMPORTED_MODULE_3__.GridStack.init(x.options, el); + grid.on("resizestop", function(event, el) { + window.dispatchEvent(new Event("resize")); + }); + if (HTMLWidgets.shinyMode) { + var $all = $(el); + Shiny.bindAll($all); + } + grid.on("added", function(event, items) { + if (HTMLWidgets.shinyMode) { + items.forEach(function(item) { + var $item = $(item); + Shiny.bindAll($item); + }); + } + }); + + if (HTMLWidgets.shinyMode) { + var serializedFull = grid.save(true, true); + Shiny.setInputValue(el.id + "_layout", serializedFull); + grid.on("added removed change", function(event, items) { + serializedFull = grid.save(true, true); + Shiny.setInputValue(el.id + "_layout", serializedFull); + }); + } + + }, + + getWidget: function() { + return grid; + }, + + resize: function(width, height) { + + // TODO: code to re-render the widget with a new size + + } + + }; + } +}); + + +if (HTMLWidgets.shinyMode) { + + // add a widget + Shiny.addCustomMessageHandler("gridstackr-add-widget", function(obj) { + var grid = _modules_utils__WEBPACK_IMPORTED_MODULE_5__.getWidget(obj.id); + if (typeof grid != "undefined") { + grid.addWidget(obj.data.options); + } + }); + + // compact layout + Shiny.addCustomMessageHandler("gridstackr-compact", function(obj) { + var grid = _modules_utils__WEBPACK_IMPORTED_MODULE_5__.getWidget(obj.id); + if (typeof grid != "undefined") { + grid.compact(obj.data); + } + }); + + // disable + Shiny.addCustomMessageHandler("gridstackr-disable", function(obj) { + var grid = _modules_utils__WEBPACK_IMPORTED_MODULE_5__.getWidget(obj.id); + if (typeof grid != "undefined") { + grid.disable(); + } + }); + + // enable + Shiny.addCustomMessageHandler("gridstackr-enable", function(obj) { + var grid = _modules_utils__WEBPACK_IMPORTED_MODULE_5__.getWidget(obj.id); + if (typeof grid != "undefined") { + grid.enable(); + } + }); + + // enableMove + Shiny.addCustomMessageHandler("gridstackr-enable-move", function(obj) { + var grid = _modules_utils__WEBPACK_IMPORTED_MODULE_5__.getWidget(obj.id); + if (typeof grid != "undefined") { + grid.enableMove(obj.data.doEnable); + } + }); + + // enableResize + Shiny.addCustomMessageHandler("gridstackr-enable-resize", function(obj) { + var grid = _modules_utils__WEBPACK_IMPORTED_MODULE_5__.getWidget(obj.id); + if (typeof grid != "undefined") { + grid.enableResize(obj.data.doEnable); + } + }); + + // removeAll + Shiny.addCustomMessageHandler("gridstackr-remove-all", function(obj) { + var grid = _modules_utils__WEBPACK_IMPORTED_MODULE_5__.getWidget(obj.id); + if (typeof grid != "undefined") { + grid.removeAll(); + } + }); + + // removeWidget + Shiny.addCustomMessageHandler("gridstackr-remove-widget", function(obj) { + var grid = _modules_utils__WEBPACK_IMPORTED_MODULE_5__.getWidget(obj.id); + if (typeof grid != "undefined") { + var container = document.getElementById(obj.id); + var el = container.querySelector("div[gs-id='" + obj.data.id + "']"); + grid.removeWidget(el) + } + }); + +} + + + + +})(); + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZHN0YWNrLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQ2dHO0FBQ2pCO0FBQy9FLDhCQUE4QixzRUFBMkIsQ0FBQywrRUFBcUM7QUFDL0Y7QUFDQSxpRUFBaUUsVUFBVSxpQ0FBaUMsU0FBUyxpQ0FBaUMsV0FBVyx1QkFBdUIsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsV0FBVyx1QkFBdUIsVUFBVSxpQ0FBaUMsU0FBUyxpQ0FBaUMsVUFBVSxpQ0FBaUMsU0FBUyxpQ0FBaUMsVUFBVSxpQ0FBaUMsU0FBUyxpQ0FBaUMsV0FBVyx1QkFBdUIsVUFBVSxpQ0FBaUMsU0FBUyxpQ0FBaUMsVUFBVSxpQ0FBaUMsU0FBUyxpQ0FBaUMsVUFBVSxpQ0FBaUMsU0FBUyxpQ0FBaUMsVUFBVSxpQ0FBaUMsU0FBUyxpQ0FBaUMsV0FBVyx1QkFBdUIsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsVUFBVSxpQ0FBaUMsU0FBUyxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsV0FBVyx1QkFBdUIsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsV0FBVyx1QkFBdUIsWUFBWSxpQ0FBaUMsV0FBVyxpQ0FBaUMsVUFBVSxpQ0FBaUMsU0FBUyxpQ0FBaUMsWUFBWSxpQ0FBaUMsV0FBVyxpQ0FBaUMsVUFBVSxpQ0FBaUMsU0FBUyxpQ0FBaUMsWUFBWSxpQ0FBaUMsV0FBVyxpQ0FBaUMsVUFBVSxpQ0FBaUMsU0FBUyxpQ0FBaUMsWUFBWSxpQ0FBaUMsV0FBVyxpQ0FBaUMsV0FBVyx1QkFBdUIsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsY0FBYyxpQ0FBaUMsYUFBYSxpQ0FBaUMsV0FBVyx3QkFBd0IsVUFBVSxrQ0FBa0MsU0FBUyxrQ0FBa0MsVUFBVSxrQ0FBa0MsU0FBUyxrQ0FBa0MsVUFBVSxrQ0FBa0MsU0FBUyxrQ0FBa0MsVUFBVSxrQ0FBa0MsU0FBUyxrQ0FBa0MsVUFBVSxrQ0FBa0MsU0FBUyxrQ0FBa0MsVUFBVSxrQ0FBa0MsU0FBUyxrQ0FBa0MsVUFBVSxrQ0FBa0MsU0FBUyxrQ0FBa0MsVUFBVSxrQ0FBa0MsU0FBUyxrQ0FBa0MsVUFBVSxrQ0FBa0MsU0FBUyxtQ0FBbUMsV0FBVyx3QkFBd0IsYUFBYSxrQ0FBa0MsWUFBWSxrQ0FBa0MsY0FBYyxrQ0FBa0MsYUFBYSxrQ0FBa0MsY0FBYyxrQ0FBa0MsYUFBYSxrQ0FBa0MsY0FBYyxrQ0FBa0MsYUFBYSxrQ0FBa0MsY0FBYyxrQ0FBa0MsYUFBYSxrQ0FBa0MsY0FBYyxrQ0FBa0MsYUFBYSxrQ0FBa0MsY0FBYyxrQ0FBa0MsYUFBYSxrQ0FBa0MsY0FBYyxrQ0FBa0MsYUFBYSxrQ0FBa0MsY0FBYyxrQ0FBa0MsYUFBYSxtQ0FBbUMsY0FBYyxtQ0FBbUMsYUFBYSxtQ0FBbUMsV0FBVyxPQUFPLG9wRUFBb3BFLFVBQVUsbUNBQW1DLFNBQVMsbUNBQW1DLFdBQVcsdUJBQXVCLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLFdBQVcsdUJBQXVCLFVBQVUsbUNBQW1DLFNBQVMsbUNBQW1DLFVBQVUsbUNBQW1DLFNBQVMsbUNBQW1DLFVBQVUsbUNBQW1DLFNBQVMsbUNBQW1DLFdBQVcsdUJBQXVCLFVBQVUsbUNBQW1DLFNBQVMsbUNBQW1DLFVBQVUsbUNBQW1DLFNBQVMsbUNBQW1DLFVBQVUsbUNBQW1DLFNBQVMsbUNBQW1DLFVBQVUsbUNBQW1DLFNBQVMsbUNBQW1DLFdBQVcsdUJBQXVCLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLFVBQVUsbUNBQW1DLFNBQVMsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLFdBQVcsdUJBQXVCLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLFdBQVcsdUJBQXVCLFlBQVksbUNBQW1DLFdBQVcsbUNBQW1DLFVBQVUsbUNBQW1DLFNBQVMsbUNBQW1DLFlBQVksbUNBQW1DLFdBQVcsbUNBQW1DLFVBQVUsbUNBQW1DLFNBQVMsbUNBQW1DLFlBQVksbUNBQW1DLFdBQVcsbUNBQW1DLFVBQVUsbUNBQW1DLFNBQVMsbUNBQW1DLFlBQVksbUNBQW1DLFdBQVcsbUNBQW1DLFdBQVcsdUJBQXVCLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLGNBQWMsbUNBQW1DLGFBQWEsbUNBQW1DLFdBQVcsd0JBQXdCLFVBQVUsb0NBQW9DLFNBQVMsb0NBQW9DLFVBQVUsb0NBQW9DLFNBQVMsb0NBQW9DLFVBQVUsb0NBQW9DLFNBQVMsb0NBQW9DLFVBQVUsb0NBQW9DLFNBQVMsb0NBQW9DLFVBQVUsb0NBQW9DLFNBQVMsb0NBQW9DLFVBQVUsb0NBQW9DLFNBQVMsb0NBQW9DLFVBQVUsb0NBQW9DLFNBQVMs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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsZUFBZSxvQkFBb0I7QUFDdEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEVBQTBFO0FBQzFFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDQWlCO0FBQ3lCO0FBQ007QUFDVjtBQUNYO0FBQ2U7O0FBRTFDOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGVBQWUsZ0RBQVM7QUFDeEI7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDs7QUFFQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDs7QUFFQTtBQUNBO0FBQ0EsZUFBZSxxREFBZTtBQUM5QjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxlQUFlLHFEQUFlO0FBQzlCO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLGVBQWUscURBQWU7QUFDOUI7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsZUFBZSxxREFBZTtBQUM5QjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxlQUFlLHFEQUFlO0FBQzlCO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLGVBQWUscURBQWU7QUFDOUI7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsZUFBZSxxREFBZTtBQUM5QjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxlQUFlLHFEQUFlO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci8uL25vZGVfbW9kdWxlcy9ncmlkc3RhY2svZGlzdC9ncmlkc3RhY2stZXh0cmEubWluLmNzcyIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyLy4vbm9kZV9tb2R1bGVzL2dyaWRzdGFjay9kaXN0L2dyaWRzdGFjay5taW4uY3NzIiwid2VicGFjazovL2dyaWRzdGFja3IvLi9zcmNqcy9jc3MvY3VzdG9tLmNzcyIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyLy4vbm9kZV9tb2R1bGVzL2Nzcy1sb2FkZXIvZGlzdC9ydW50aW1lL2FwaS5qcyIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyLy4vbm9kZV9tb2R1bGVzL2Nzcy1sb2FkZXIvZGlzdC9ydW50aW1lL2dldFVybC5qcyIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyLy4vbm9kZV9tb2R1bGVzL2Nzcy1sb2FkZXIvZGlzdC9ydW50aW1lL3NvdXJjZU1hcHMuanMiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci8uL25vZGVfbW9kdWxlcy9ncmlkc3RhY2svZGlzdC9kZC1iYXNlLWltcGwuanMiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci8uL25vZGVfbW9kdWxlcy9ncmlkc3RhY2svZGlzdC9kZC1kcmFnZ2FibGUuanMiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci8uL25vZGVfbW9kdWxlcy9ncmlkc3RhY2svZGlzdC9kZC1kcm9wcGFibGUuanMiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci8uL25vZGVfbW9kdWxlcy9ncmlkc3RhY2svZGlzdC9kZC1lbGVtZW50LmpzIiwid2VicGFjazovL2dyaWRzdGFja3IvLi9ub2RlX21vZHVsZXMvZ3JpZHN0YWNrL2Rpc3QvZGQtZ3JpZHN0YWNrLmpzIiwid2VicGFjazovL2dyaWRzdGFja3IvLi9ub2RlX21vZHVsZXMvZ3JpZHN0YWNrL2Rpc3QvZGQtbWFuYWdlci5qcyIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyLy4vbm9kZV9tb2R1bGVzL2dyaWRzdGFjay9kaXN0L2RkLXJlc2l6YWJsZS1oYW5kbGUuanMiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci8uL25vZGVfbW9kdWxlcy9ncmlkc3RhY2svZGlzdC9kZC1yZXNpemFibGUuanMiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci8uL25vZGVfbW9kdWxlcy9ncmlkc3RhY2svZGlzdC9kZC10b3VjaC5qcyIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyLy4vbm9kZV9tb2R1bGVzL2dyaWRzdGFjay9kaXN0L2dyaWRzdGFjay1lbmdpbmUuanMiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci8uL25vZGVfbW9kdWxlcy9ncmlkc3RhY2svZGlzdC9ncmlkc3RhY2suanMiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci8uL25vZGVfbW9kdWxlcy9ncmlkc3RhY2svZGlzdC90eXBlcy5qcyIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyLy4vbm9kZV9tb2R1bGVzL2dyaWRzdGFjay9kaXN0L3V0aWxzLmpzIiwid2VicGFjazovL2dyaWRzdGFja3IvLi9ub2RlX21vZHVsZXMvZ3JpZHN0YWNrL2Rpc3QvZ3JpZHN0YWNrLWV4dHJhLm1pbi5jc3M/OWQyZiIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyLy4vbm9kZV9tb2R1bGVzL2dyaWRzdGFjay9kaXN0L2dyaWRzdGFjay5taW4uY3NzP2EyZGIiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci8uL3NyY2pzL2Nzcy9jdXN0b20uY3NzP2QzOTAiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci8uL25vZGVfbW9kdWxlcy9zdHlsZS1sb2FkZXIvZGlzdC9ydW50aW1lL2luamVjdFN0eWxlc0ludG9TdHlsZVRhZy5qcyIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyLy4vbm9kZV9tb2R1bGVzL3N0eWxlLWxvYWRlci9kaXN0L3J1bnRpbWUvaW5zZXJ0QnlTZWxlY3Rvci5qcyIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyLy4vbm9kZV9tb2R1bGVzL3N0eWxlLWxvYWRlci9kaXN0L3J1bnRpbWUvaW5zZXJ0U3R5bGVFbGVtZW50LmpzIiwid2VicGFjazovL2dyaWRzdGFja3IvLi9ub2RlX21vZHVsZXMvc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9zZXRBdHRyaWJ1dGVzV2l0aG91dEF0dHJpYnV0ZXMuanMiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci8uL25vZGVfbW9kdWxlcy9zdHlsZS1sb2FkZXIvZGlzdC9ydW50aW1lL3N0eWxlRG9tQVBJLmpzIiwid2VicGFjazovL2dyaWRzdGFja3IvLi9ub2RlX21vZHVsZXMvc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9zdHlsZVRhZ1RyYW5zZm9ybS5qcyIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyLy4vc3JjanMvbW9kdWxlcy91dGlscy5qcyIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyL2V4dGVybmFsIHZhciBcIkhUTUxXaWRnZXRzXCIiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyL3dlYnBhY2svcnVudGltZS9jb21wYXQgZ2V0IGRlZmF1bHQgZXhwb3J0Iiwid2VicGFjazovL2dyaWRzdGFja3Ivd2VicGFjay9ydW50aW1lL2RlZmluZSBwcm9wZXJ0eSBnZXR0ZXJzIiwid2VicGFjazovL2dyaWRzdGFja3Ivd2VicGFjay9ydW50aW1lL2hhc093blByb3BlcnR5IHNob3J0aGFuZCIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyL3dlYnBhY2svcnVudGltZS9tYWtlIG5hbWVzcGFjZSBvYmplY3QiLCJ3ZWJwYWNrOi8vZ3JpZHN0YWNrci93ZWJwYWNrL3J1bnRpbWUvanNvbnAgY2h1bmsgbG9hZGluZyIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyL3dlYnBhY2svcnVudGltZS9ub25jZSIsIndlYnBhY2s6Ly9ncmlkc3RhY2tyLy4vc3JjanMvd2lkZ2V0cy9ncmlkc3RhY2suanMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gSW1wb3J0c1xuaW1wb3J0IF9fX0NTU19MT0FERVJfQVBJX1NPVVJDRU1BUF9JTVBPUlRfX18gZnJvbSBcIi4uLy4uL2Nzcy1sb2FkZXIvZGlzdC9ydW50aW1lL3NvdXJjZU1hcHMuanNcIjtcbmltcG9ydCBfX19DU1NfTE9BREVSX0FQSV9JTVBPUlRfX18gZnJvbSBcIi4uLy4uL2Nzcy1sb2FkZXIvZGlzdC9ydW50aW1lL2FwaS5qc1wiO1xudmFyIF9fX0NTU19MT0FERVJfRVhQT1JUX19fID0gX19fQ1NTX0xPQURFUl9BUElfSU1QT1JUX19fKF9fX0NTU19MT0FERVJfQVBJX1NPVVJDRU1BUF9JTVBPUlRfX18pO1xuLy8gTW9kdWxlXG5fX19DU1NfTE9BREVSX0VYUE9SVF9fXy5wdXNoKFttb2R1bGUuaWQsIGAuZ3MtMj4uZ3JpZC1zdGFjay1pdGVte3dpZHRoOjUwJX0uZ3MtMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIxXCJde2xlZnQ6NTAlfS5ncy0yPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjJcIl17d2lkdGg6MTAwJX0uZ3MtMz4uZ3JpZC1zdGFjay1pdGVte3dpZHRoOjMzLjMzMyV9LmdzLTM+LmdyaWQtc3RhY2staXRlbVtncy14PVwiMVwiXXtsZWZ0OjMzLjMzMyV9LmdzLTM+LmdyaWQtc3RhY2staXRlbVtncy13PVwiMlwiXXt3aWR0aDo2Ni42NjclfS5ncy0zPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjJcIl17bGVmdDo2Ni42NjclfS5ncy0zPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjNcIl17d2lkdGg6MTAwJX0uZ3MtND4uZ3JpZC1zdGFjay1pdGVte3dpZHRoOjI1JX0uZ3MtND4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIxXCJde2xlZnQ6MjUlfS5ncy00Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjJcIl17d2lkdGg6NTAlfS5ncy00Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjJcIl17bGVmdDo1MCV9LmdzLTQ+LmdyaWQtc3RhY2staXRlbVtncy13PVwiM1wiXXt3aWR0aDo3NSV9LmdzLTQ+LmdyaWQtc3RhY2staXRlbVtncy14PVwiM1wiXXtsZWZ0Ojc1JX0uZ3MtND4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI0XCJde3dpZHRoOjEwMCV9LmdzLTU+LmdyaWQtc3RhY2staXRlbXt3aWR0aDoyMCV9LmdzLTU+LmdyaWQtc3RhY2staXRlbVtncy14PVwiMVwiXXtsZWZ0OjIwJX0uZ3MtNT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCIyXCJde3dpZHRoOjQwJX0uZ3MtNT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIyXCJde2xlZnQ6NDAlfS5ncy01Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjNcIl17d2lkdGg6NjAlfS5ncy01Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjNcIl17bGVmdDo2MCV9LmdzLTU+LmdyaWQtc3RhY2staXRlbVtncy13PVwiNFwiXXt3aWR0aDo4MCV9LmdzLTU+LmdyaWQtc3RhY2staXRlbVtncy14PVwiNFwiXXtsZWZ0OjgwJX0uZ3MtNT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI1XCJde3dpZHRoOjEwMCV9LmdzLTY+LmdyaWQtc3RhY2staXRlbXt3aWR0aDoxNi42NjclfS5ncy02Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjFcIl17bGVmdDoxNi42NjclfS5ncy02Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjJcIl17d2lkdGg6MzMuMzMzJX0uZ3MtNj4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIyXCJde2xlZnQ6MzMuMzMzJX0uZ3MtNj4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCIzXCJde3dpZHRoOjUwJX0uZ3MtNj4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIzXCJde2xlZnQ6NTAlfS5ncy02Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjRcIl17d2lkdGg6NjYuNjY3JX0uZ3MtNj4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCI0XCJde2xlZnQ6NjYuNjY3JX0uZ3MtNj4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI1XCJde3dpZHRoOjgzLjMzMyV9LmdzLTY+LmdyaWQtc3RhY2staXRlbVtncy14PVwiNVwiXXtsZWZ0OjgzLjMzMyV9LmdzLTY+LmdyaWQtc3RhY2staXRlbVtncy13PVwiNlwiXXt3aWR0aDoxMDAlfS5ncy03Pi5ncmlkLXN0YWNrLWl0ZW17d2lkdGg6MTQuMjg2JX0uZ3MtNz4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIxXCJde2xlZnQ6MTQuMjg2JX0uZ3MtNz4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCIyXCJde3dpZHRoOjI4LjU3MSV9LmdzLTc+LmdyaWQtc3RhY2staXRlbVtncy14PVwiMlwiXXtsZWZ0OjI4LjU3MSV9LmdzLTc+LmdyaWQtc3RhY2staXRlbVtncy13PVwiM1wiXXt3aWR0aDo0Mi44NTclfS5ncy03Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjNcIl17bGVmdDo0Mi44NTclfS5ncy03Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjRcIl17d2lkdGg6NTcuMTQzJX0uZ3MtNz4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCI0XCJde2xlZnQ6NTcuMTQzJX0uZ3MtNz4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI1XCJde3dpZHRoOjcxLjQyOSV9LmdzLTc+LmdyaWQtc3RhY2staXRlbVtncy14PVwiNVwiXXtsZWZ0OjcxLjQyOSV9LmdzLTc+LmdyaWQtc3RhY2staXRlbVtncy13PVwiNlwiXXt3aWR0aDo4NS43MTQlfS5ncy03Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjZcIl17bGVmdDo4NS43MTQlfS5ncy03Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjdcIl17d2lkdGg6MTAwJX0uZ3MtOD4uZ3JpZC1zdGFjay1pdGVte3dpZHRoOjEyLjUlfS5ncy04Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjFcIl17bGVmdDoxMi41JX0uZ3MtOD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCIyXCJde3dpZHRoOjI1JX0uZ3MtOD4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIyXCJde2xlZnQ6MjUlfS5ncy04Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjNcIl17d2lkdGg6MzcuNSV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy14PVwiM1wiXXtsZWZ0OjM3LjUlfS5ncy04Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjRcIl17d2lkdGg6NTAlfS5ncy04Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjRcIl17bGVmdDo1MCV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy13PVwiNVwiXXt3aWR0aDo2Mi41JX0uZ3MtOD4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCI1XCJde2xlZnQ6NjIuNSV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy13PVwiNlwiXXt3aWR0aDo3NSV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy14PVwiNlwiXXtsZWZ0Ojc1JX0uZ3MtOD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI3XCJde3dpZHRoOjg3LjUlfS5ncy04Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjdcIl17bGVmdDo4Ny41JX0uZ3MtOD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI4XCJde3dpZHRoOjEwMCV9LmdzLTk+LmdyaWQtc3RhY2staXRlbXt3aWR0aDoxMS4xMTElfS5ncy05Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjFcIl17bGVmdDoxMS4xMTElfS5ncy05Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjJcIl17d2lkdGg6MjIuMjIyJX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIyXCJde2xlZnQ6MjIuMjIyJX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCIzXCJde3dpZHRoOjMzLjMzMyV9LmdzLTk+LmdyaWQtc3RhY2staXRlbVtncy14PVwiM1wiXXtsZWZ0OjMzLjMzMyV9LmdzLTk+LmdyaWQtc3RhY2staXRlbVtncy13PVwiNFwiXXt3aWR0aDo0NC40NDQlfS5ncy05Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjRcIl17bGVmdDo0NC40NDQlfS5ncy05Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjVcIl17d2lkdGg6NTUuNTU2JX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCI1XCJde2xlZnQ6NTUuNTU2JX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI2XCJde3dpZHRoOjY2LjY2NyV9LmdzLTk+LmdyaWQtc3RhY2staXRlbVtncy14PVwiNlwiXXtsZWZ0OjY2LjY2NyV9LmdzLTk+LmdyaWQtc3RhY2staXRlbVtncy13PVwiN1wiXXt3aWR0aDo3Ny43NzglfS5ncy05Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjdcIl17bGVmdDo3Ny43NzglfS5ncy05Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjhcIl17d2lkdGg6ODguODg5JX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCI4XCJde2xlZnQ6ODguODg5JX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI5XCJde3dpZHRoOjEwMCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW17d2lkdGg6MTAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIxXCJde2xlZnQ6MTAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCIyXCJde3dpZHRoOjIwJX0uZ3MtMTA+LmdyaWQtc3RhY2staXRlbVtncy14PVwiMlwiXXtsZWZ0OjIwJX0uZ3MtMTA+LmdyaWQtc3RhY2staXRlbVtncy13PVwiM1wiXXt3aWR0aDozMCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjNcIl17bGVmdDozMCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjRcIl17d2lkdGg6NDAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCI0XCJde2xlZnQ6NDAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI1XCJde3dpZHRoOjUwJX0uZ3MtMTA+LmdyaWQtc3RhY2staXRlbVtncy14PVwiNVwiXXtsZWZ0OjUwJX0uZ3MtMTA+LmdyaWQtc3RhY2staXRlbVtncy13PVwiNlwiXXt3aWR0aDo2MCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjZcIl17bGVmdDo2MCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjdcIl17d2lkdGg6NzAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCI3XCJde2xlZnQ6NzAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI4XCJde3dpZHRoOjgwJX0uZ3MtMTA+LmdyaWQtc3RhY2staXRlbVtncy14PVwiOFwiXXtsZWZ0OjgwJX0uZ3MtMTA+LmdyaWQtc3RhY2staXRlbVtncy13PVwiOVwiXXt3aWR0aDo5MCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjlcIl17bGVmdDo5MCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjEwXCJde3dpZHRoOjEwMCV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW17d2lkdGg6OS4wOTElfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIxXCJde2xlZnQ6OS4wOTElfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCIyXCJde3dpZHRoOjE4LjE4MiV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjJcIl17bGVmdDoxOC4xODIlfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCIzXCJde3dpZHRoOjI3LjI3MyV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjNcIl17bGVmdDoyNy4yNzMlfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI0XCJde3dpZHRoOjM2LjM2NCV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjRcIl17bGVmdDozNi4zNjQlfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI1XCJde3dpZHRoOjQ1LjQ1NSV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjVcIl17bGVmdDo0NS40NTUlfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI2XCJde3dpZHRoOjU0LjU0NSV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjZcIl17bGVmdDo1NC41NDUlfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI3XCJde3dpZHRoOjYzLjYzNiV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjdcIl17bGVmdDo2My42MzYlfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI4XCJde3dpZHRoOjcyLjcyNyV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjhcIl17bGVmdDo3Mi43MjclfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI5XCJde3dpZHRoOjgxLjgxOCV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjlcIl17bGVmdDo4MS44MTglfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCIxMFwiXXt3aWR0aDo5MC45MDklfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIxMFwiXXtsZWZ0OjkwLjkwOSV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjExXCJde3dpZHRoOjEwMCV9YCwgXCJcIix7XCJ2ZXJzaW9uXCI6MyxcInNvdXJjZXNcIjpbXCJ3ZWJwYWNrOi8vLi9ub2RlX21vZHVsZXMvZ3JpZHN0YWNrL2Rpc3QvZ3JpZHN0YWNrLWV4dHJhLm1pbi5jc3NcIl0sXCJuYW1lc1wiOltdLFwibWFwcGluZ3NcIjpcIkFBQUEsdUJBQXVCLFNBQVMsQ0FBQyxpQ0FBaUMsUUFBUSxDQUFDLGlDQUFpQyxVQUFVLENBQUMsdUJBQXVCLGFBQWEsQ0FBQyxpQ0FBaUMsWUFBWSxDQUFDLGlDQUFpQyxhQUFhLENBQUMsaUNBQWlDLFlBQVksQ0FBQyxpQ0FBaUMsVUFBVSxDQUFDLHVCQUF1QixTQUFTLENBQUMsaUNBQWlDLFFBQVEsQ0FBQyxpQ0FBaUMsU0FBUyxDQUFDLGlDQUFpQyxRQUFRLENBQUMsaUNBQWlDLFNBQVMsQ0FBQyxpQ0FBaUMsUUFBUSxDQUFDLGlDQUFpQyxVQUFVLENBQUMsdUJBQXVCLFNBQVMsQ0FBQyxpQ0FBaUMsUUFBUSxDQUFDLGlDQUFpQyxTQUFTLENBQUMsaUNBQWlDLFFBQVEsQ0FBQyxpQ0FBaUMsU0FBUyxDQUFDLGlDQUFpQyxRQUFRLENBQUMsaUNBQWlDLFNBQVMsQ0FBQyxpQ0FBaUMsUUFBUSxDQUFDLGlDQUFpQyxVQUFVLENBQUMsdUJBQXVCLGFBQWEsQ0FBQyxpQ0FBaUMsWUFBWSxDQUFDLGlDQUFpQyxhQUFhLENBQUMsaUNBQWlDLFlBQVksQ0FBQyxpQ0FBaUMsU0FBUyxDQUFDLGlDQUFpQyxRQUFRLENBQUMsaUNBQWlDLGFBQWEsQ0FBQyxpQ0FBaUMsWUFBWSxDQUFDLGlDQUFpQyxhQUFhLENBQUMsaUNBQWlDLFlBQVksQ0FBQyxpQ0FBaUMsVUFBVSxDQUFDLHVCQUF1QixhQUFhLENBQUMsaUNBQWlDLFlBQVksQ0FBQyxpQ0FBaUMsYUFBYSxDQUFDLGlDQUFpQyxZQUFZLENBQUMsaUNBQWlDLGFBQWEsQ0FBQyxpQ0FBaUMsWUFBWSxDQUFDLGlDQUFpQyxhQUFhLENBQUMsaUNBQWlDLFlBQVksQ0FBQyxpQ0FBaUMsYUFBYSxDQUFDLGlDQUFpQyxZQUFZLENBQUMsaUNBQWlDLGFBQWEsQ0FBQyxpQ0FBaUMsWUFBWSxDQUFDLGlDQUFpQyxVQUFVLENBQUMsdUJBQXVCLFdBQVcsQ0FBQyxpQ0FBaUMsVUFBVSxDQUFDLGlDQUFpQyxTQUFTLENBQUMsaUNBQWlDLFFBQVEsQ0FBQyxpQ0FBaUMsV0FBVyxDQUFDLGlDQUFpQyxVQUFVLENBQUMsaUNBQWlDLFNBQVMsQ0FBQyxpQ0FBaUMsUUFBUSxDQUFDLGlDQUFpQyxXQUFXLENBQUMsaUNBQWlDLFVBQVUsQ0FBQyxpQ0FBaUMsU0FBUyxDQUFDLGlDQUFpQyxRQUFRLENBQUMsaUNBQWlDLFdBQVcsQ0FBQyxpQ0FBaUMsVUFBVSxDQUFDLGlDQUFpQyxVQUFVLENBQUMsdUJBQXVCLGFBQWEsQ0FBQyxpQ0FBaUMsWUFBWSxDQUFDLGlDQUFpQyxhQUFhLENBQUMsaUNBQWlDLFlBQVksQ0FBQyxpQ0FBaUMsYUFBYSxDQUFDLGlDQUFpQyxZQUFZLENBQUMsaUNBQWlDLGFBQWEsQ0FBQyxpQ0FBaUMsWUFBWSxDQUFDLGlDQUFpQyxhQUFhLENBQUMsaUNBQWlDLFlBQVksQ0FBQyxpQ0FBaUMsYUFBYSxDQUFDLGlDQUFpQyxZQUFZLENBQUMsaUNBQWlDLGFBQWEsQ0FBQyxpQ0FBaUMsWUFBWSxDQUFDLGlDQUFpQyxhQUFhLENBQUMsaUNBQWlDLFlBQVksQ0FBQyxpQ0FBaUMsVUFBVSxDQUFDLHdCQUF3QixTQUFTLENBQUMsa0NBQWtDLFFBQVEsQ0FBQyxrQ0FBa0MsU0FBUyxDQUFDLGtDQUFrQyxRQUFRLENBQUMsa0NBQWtDLFNBQVMsQ0FBQyxrQ0FBa0MsUUFBUSxDQUFDLGtDQUFrQyxTQUFTLENBQUMsa0NBQWtDLFFBQVEsQ0FBQyxrQ0FBa0MsU0FBUyxDQUFDLGtDQUFrQyxRQUFRLENBQUMsa0NBQWtDLFNBQVMsQ0FBQyxrQ0FBa0MsUUFBUSxDQUFDLGtDQUFrQyxTQUFTLENBQUMsa0NBQWtDLFFBQVEsQ0FBQyxrQ0FBa0MsU0FBUyxDQUFDLGtDQUFrQyxRQUFRLENBQUMsa0NBQWtDLFNBQVMsQ0FBQyxrQ0FBa0MsUUFBUSxDQUFDLG1DQUFtQyxVQUFVLENBQUMsd0JBQXdCLFlBQVksQ0FBQyxrQ0FBa0MsV0FBVyxDQUFDLGtDQUFrQyxhQUFhLENBQUMsa0NBQWtDLFlBQVksQ0FBQyxrQ0FBa0MsYUFBYSxDQUFDLGtDQUFrQyxZQUFZLENBQUMsa0NBQWtDLGFBQWEsQ0FBQyxrQ0FBa0MsWUFBWSxDQUFDLGtDQUFrQyxhQUFhLENBQUMsa0NBQWtDLFlBQVksQ0FBQyxrQ0FBa0MsYUFBYSxDQUFDLGtDQUFrQyxZQUFZLENBQUMsa0NBQWtDLGFBQWEsQ0FBQyxrQ0FBa0MsWUFBWSxDQUFDLGtDQUFrQyxhQUFhLENBQUMsa0NBQWtDLFlBQVksQ0FBQyxrQ0FBa0MsYUFBYSxDQUFDLGtDQUFrQyxZQUFZLENBQUMsbUNBQW1DLGFBQWEsQ0FBQyxtQ0FBbUMsWUFBWSxDQUFDLG1DQUFtQyxVQUFVXCIsXCJzb3VyY2VzQ29udGVudFwiOltcIi5ncy0yPi5ncmlkLXN0YWNrLWl0ZW17d2lkdGg6NTAlfS5ncy0yPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiMVxcXCJde2xlZnQ6NTAlfS5ncy0yPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiMlxcXCJde3dpZHRoOjEwMCV9LmdzLTM+LmdyaWQtc3RhY2staXRlbXt3aWR0aDozMy4zMzMlfS5ncy0zPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiMVxcXCJde2xlZnQ6MzMuMzMzJX0uZ3MtMz4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjJcXFwiXXt3aWR0aDo2Ni42NjclfS5ncy0zPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiMlxcXCJde2xlZnQ6NjYuNjY3JX0uZ3MtMz4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjNcXFwiXXt3aWR0aDoxMDAlfS5ncy00Pi5ncmlkLXN0YWNrLWl0ZW17d2lkdGg6MjUlfS5ncy00Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiMVxcXCJde2xlZnQ6MjUlfS5ncy00Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiMlxcXCJde3dpZHRoOjUwJX0uZ3MtND4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjJcXFwiXXtsZWZ0OjUwJX0uZ3MtND4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjNcXFwiXXt3aWR0aDo3NSV9LmdzLTQ+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCIzXFxcIl17bGVmdDo3NSV9LmdzLTQ+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI0XFxcIl17d2lkdGg6MTAwJX0uZ3MtNT4uZ3JpZC1zdGFjay1pdGVte3dpZHRoOjIwJX0uZ3MtNT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjFcXFwiXXtsZWZ0OjIwJX0uZ3MtNT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjJcXFwiXXt3aWR0aDo0MCV9LmdzLTU+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCIyXFxcIl17bGVmdDo0MCV9LmdzLTU+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCIzXFxcIl17d2lkdGg6NjAlfS5ncy01Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiM1xcXCJde2xlZnQ6NjAlfS5ncy01Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiNFxcXCJde3dpZHRoOjgwJX0uZ3MtNT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjRcXFwiXXtsZWZ0OjgwJX0uZ3MtNT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjVcXFwiXXt3aWR0aDoxMDAlfS5ncy02Pi5ncmlkLXN0YWNrLWl0ZW17d2lkdGg6MTYuNjY3JX0uZ3MtNj4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjFcXFwiXXtsZWZ0OjE2LjY2NyV9LmdzLTY+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCIyXFxcIl17d2lkdGg6MzMuMzMzJX0uZ3MtNj4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjJcXFwiXXtsZWZ0OjMzLjMzMyV9LmdzLTY+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCIzXFxcIl17d2lkdGg6NTAlfS5ncy02Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiM1xcXCJde2xlZnQ6NTAlfS5ncy02Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiNFxcXCJde3dpZHRoOjY2LjY2NyV9LmdzLTY+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCI0XFxcIl17bGVmdDo2Ni42NjclfS5ncy02Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiNVxcXCJde3dpZHRoOjgzLjMzMyV9LmdzLTY+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCI1XFxcIl17bGVmdDo4My4zMzMlfS5ncy02Pi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiNlxcXCJde3dpZHRoOjEwMCV9LmdzLTc+LmdyaWQtc3RhY2staXRlbXt3aWR0aDoxNC4yODYlfS5ncy03Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiMVxcXCJde2xlZnQ6MTQuMjg2JX0uZ3MtNz4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjJcXFwiXXt3aWR0aDoyOC41NzElfS5ncy03Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiMlxcXCJde2xlZnQ6MjguNTcxJX0uZ3MtNz4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjNcXFwiXXt3aWR0aDo0Mi44NTclfS5ncy03Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiM1xcXCJde2xlZnQ6NDIuODU3JX0uZ3MtNz4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjRcXFwiXXt3aWR0aDo1Ny4xNDMlfS5ncy03Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiNFxcXCJde2xlZnQ6NTcuMTQzJX0uZ3MtNz4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjVcXFwiXXt3aWR0aDo3MS40MjklfS5ncy03Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiNVxcXCJde2xlZnQ6NzEuNDI5JX0uZ3MtNz4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjZcXFwiXXt3aWR0aDo4NS43MTQlfS5ncy03Pi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiNlxcXCJde2xlZnQ6ODUuNzE0JX0uZ3MtNz4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjdcXFwiXXt3aWR0aDoxMDAlfS5ncy04Pi5ncmlkLXN0YWNrLWl0ZW17d2lkdGg6MTIuNSV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCIxXFxcIl17bGVmdDoxMi41JX0uZ3MtOD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjJcXFwiXXt3aWR0aDoyNSV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCIyXFxcIl17bGVmdDoyNSV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCIzXFxcIl17d2lkdGg6MzcuNSV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCIzXFxcIl17bGVmdDozNy41JX0uZ3MtOD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjRcXFwiXXt3aWR0aDo1MCV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCI0XFxcIl17bGVmdDo1MCV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI1XFxcIl17d2lkdGg6NjIuNSV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCI1XFxcIl17bGVmdDo2Mi41JX0uZ3MtOD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjZcXFwiXXt3aWR0aDo3NSV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCI2XFxcIl17bGVmdDo3NSV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI3XFxcIl17d2lkdGg6ODcuNSV9LmdzLTg+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCI3XFxcIl17bGVmdDo4Ny41JX0uZ3MtOD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjhcXFwiXXt3aWR0aDoxMDAlfS5ncy05Pi5ncmlkLXN0YWNrLWl0ZW17d2lkdGg6MTEuMTExJX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjFcXFwiXXtsZWZ0OjExLjExMSV9LmdzLTk+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCIyXFxcIl17d2lkdGg6MjIuMjIyJX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjJcXFwiXXtsZWZ0OjIyLjIyMiV9LmdzLTk+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCIzXFxcIl17d2lkdGg6MzMuMzMzJX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjNcXFwiXXtsZWZ0OjMzLjMzMyV9LmdzLTk+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI0XFxcIl17d2lkdGg6NDQuNDQ0JX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjRcXFwiXXtsZWZ0OjQ0LjQ0NCV9LmdzLTk+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI1XFxcIl17d2lkdGg6NTUuNTU2JX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjVcXFwiXXtsZWZ0OjU1LjU1NiV9LmdzLTk+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI2XFxcIl17d2lkdGg6NjYuNjY3JX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjZcXFwiXXtsZWZ0OjY2LjY2NyV9LmdzLTk+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI3XFxcIl17d2lkdGg6NzcuNzc4JX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjdcXFwiXXtsZWZ0Ojc3Ljc3OCV9LmdzLTk+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI4XFxcIl17d2lkdGg6ODguODg5JX0uZ3MtOT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjhcXFwiXXtsZWZ0Ojg4Ljg4OSV9LmdzLTk+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI5XFxcIl17d2lkdGg6MTAwJX0uZ3MtMTA+LmdyaWQtc3RhY2staXRlbXt3aWR0aDoxMCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiMVxcXCJde2xlZnQ6MTAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjJcXFwiXXt3aWR0aDoyMCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiMlxcXCJde2xlZnQ6MjAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjNcXFwiXXt3aWR0aDozMCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiM1xcXCJde2xlZnQ6MzAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjRcXFwiXXt3aWR0aDo0MCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiNFxcXCJde2xlZnQ6NDAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjVcXFwiXXt3aWR0aDo1MCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiNVxcXCJde2xlZnQ6NTAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjZcXFwiXXt3aWR0aDo2MCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiNlxcXCJde2xlZnQ6NjAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjdcXFwiXXt3aWR0aDo3MCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiN1xcXCJde2xlZnQ6NzAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjhcXFwiXXt3aWR0aDo4MCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiOFxcXCJde2xlZnQ6ODAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjlcXFwiXXt3aWR0aDo5MCV9LmdzLTEwPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiOVxcXCJde2xlZnQ6OTAlfS5ncy0xMD4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjEwXFxcIl17d2lkdGg6MTAwJX0uZ3MtMTE+LmdyaWQtc3RhY2staXRlbXt3aWR0aDo5LjA5MSV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiMVxcXCJde2xlZnQ6OS4wOTElfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjJcXFwiXXt3aWR0aDoxOC4xODIlfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjJcXFwiXXtsZWZ0OjE4LjE4MiV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiM1xcXCJde3dpZHRoOjI3LjI3MyV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiM1xcXCJde2xlZnQ6MjcuMjczJX0uZ3MtMTE+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI0XFxcIl17d2lkdGg6MzYuMzY0JX0uZ3MtMTE+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCI0XFxcIl17bGVmdDozNi4zNjQlfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjVcXFwiXXt3aWR0aDo0NS40NTUlfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjVcXFwiXXtsZWZ0OjQ1LjQ1NSV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiNlxcXCJde3dpZHRoOjU0LjU0NSV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiNlxcXCJde2xlZnQ6NTQuNTQ1JX0uZ3MtMTE+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI3XFxcIl17d2lkdGg6NjMuNjM2JX0uZ3MtMTE+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCI3XFxcIl17bGVmdDo2My42MzYlfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjhcXFwiXXt3aWR0aDo3Mi43MjclfS5ncy0xMT4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjhcXFwiXXtsZWZ0OjcyLjcyNyV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiOVxcXCJde3dpZHRoOjgxLjgxOCV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiOVxcXCJde2xlZnQ6ODEuODE4JX0uZ3MtMTE+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCIxMFxcXCJde3dpZHRoOjkwLjkwOSV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiMTBcXFwiXXtsZWZ0OjkwLjkwOSV9LmdzLTExPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiMTFcXFwiXXt3aWR0aDoxMDAlfVwiXSxcInNvdXJjZVJvb3RcIjpcIlwifV0pO1xuLy8gRXhwb3J0c1xuZXhwb3J0IGRlZmF1bHQgX19fQ1NTX0xPQURFUl9FWFBPUlRfX187XG4iLCIvLyBJbXBvcnRzXG5pbXBvcnQgX19fQ1NTX0xPQURFUl9BUElfU09VUkNFTUFQX0lNUE9SVF9fXyBmcm9tIFwiLi4vLi4vY3NzLWxvYWRlci9kaXN0L3J1bnRpbWUvc291cmNlTWFwcy5qc1wiO1xuaW1wb3J0IF9fX0NTU19MT0FERVJfQVBJX0lNUE9SVF9fXyBmcm9tIFwiLi4vLi4vY3NzLWxvYWRlci9kaXN0L3J1bnRpbWUvYXBpLmpzXCI7XG5pbXBvcnQgX19fQ1NTX0xPQURFUl9HRVRfVVJMX0lNUE9SVF9fXyBmcm9tIFwiLi4vLi4vY3NzLWxvYWRlci9kaXN0L3J1bnRpbWUvZ2V0VXJsLmpzXCI7XG52YXIgX19fQ1NTX0xPQURFUl9VUkxfSU1QT1JUXzBfX18gPSBuZXcgVVJMKFwiZGF0YTppbWFnZS9zdmcreG1sO3V0ZjgsPHN2ZyB4bWxucz1cXFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcXFwiIGZpbGw9XFxcIm5vbmVcXFwiIHN0cm9rZT1cXFwiJTIzNjY2XFxcIiBzdHJva2UtbGluZWNhcD1cXFwicm91bmRcXFwiIHN0cm9rZS1saW5lam9pbj1cXFwicm91bmRcXFwiIHN0cm9rZS13aWR0aD1cXFwiMlxcXCIgdmlld0JveD1cXFwiMCAwIDIwIDIwXFxcIj48cGF0aCBkPVxcXCJtMTAgMyAyIDJIOGwyLTJ2MTRsLTItMmg0bC0yIDJcXFwiLz48L3N2Zz5cIiwgaW1wb3J0Lm1ldGEudXJsKTtcbnZhciBfX19DU1NfTE9BREVSX0VYUE9SVF9fXyA9IF9fX0NTU19MT0FERVJfQVBJX0lNUE9SVF9fXyhfX19DU1NfTE9BREVSX0FQSV9TT1VSQ0VNQVBfSU1QT1JUX19fKTtcbnZhciBfX19DU1NfTE9BREVSX1VSTF9SRVBMQUNFTUVOVF8wX19fID0gX19fQ1NTX0xPQURFUl9HRVRfVVJMX0lNUE9SVF9fXyhfX19DU1NfTE9BREVSX1VSTF9JTVBPUlRfMF9fXyk7XG4vLyBNb2R1bGVcbl9fX0NTU19MT0FERVJfRVhQT1JUX19fLnB1c2goW21vZHVsZS5pZCwgYC5ncmlkLXN0YWNre3Bvc2l0aW9uOnJlbGF0aXZlfS5ncmlkLXN0YWNrLXJ0bHtkaXJlY3Rpb246bHRyfS5ncmlkLXN0YWNrLXJ0bD4uZ3JpZC1zdGFjay1pdGVte2RpcmVjdGlvbjpydGx9LmdyaWQtc3RhY2stcGxhY2Vob2xkZXI+LnBsYWNlaG9sZGVyLWNvbnRlbnR7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDAsMCwwLC4xKTttYXJnaW46MDtwb3NpdGlvbjphYnNvbHV0ZTt3aWR0aDphdXRvO3otaW5kZXg6MCFpbXBvcnRhbnR9LmdyaWQtc3RhY2s+LmdyaWQtc3RhY2staXRlbXtwb3NpdGlvbjphYnNvbHV0ZTtwYWRkaW5nOjB9LmdyaWQtc3RhY2s+LmdyaWQtc3RhY2staXRlbT4uZ3JpZC1zdGFjay1pdGVtLWNvbnRlbnR7bWFyZ2luOjA7cG9zaXRpb246YWJzb2x1dGU7d2lkdGg6YXV0bztvdmVyZmxvdy14OmhpZGRlbjtvdmVyZmxvdy15OmF1dG99LmdyaWQtc3RhY2s+LmdyaWQtc3RhY2staXRlbS5zaXplLXRvLWNvbnRlbnQ6bm90KC5zaXplLXRvLWNvbnRlbnQtbWF4KT4uZ3JpZC1zdGFjay1pdGVtLWNvbnRlbnR7b3ZlcmZsb3cteTpoaWRkZW59LmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLWhhbmRsZXtwb3NpdGlvbjphYnNvbHV0ZTtmb250LXNpemU6LjFweDtkaXNwbGF5OmJsb2NrOy1tcy10b3VjaC1hY3Rpb246bm9uZTt0b3VjaC1hY3Rpb246bm9uZX0uZ3JpZC1zdGFjay1pdGVtLnVpLXJlc2l6YWJsZS1hdXRvaGlkZT4udWktcmVzaXphYmxlLWhhbmRsZSwuZ3JpZC1zdGFjay1pdGVtLnVpLXJlc2l6YWJsZS1kaXNhYmxlZD4udWktcmVzaXphYmxlLWhhbmRsZXtkaXNwbGF5Om5vbmV9LmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLW5lLC5ncmlkLXN0YWNrLWl0ZW0+LnVpLXJlc2l6YWJsZS1udywuZ3JpZC1zdGFjay1pdGVtPi51aS1yZXNpemFibGUtc2UsLmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLXN3e2JhY2tncm91bmQtaW1hZ2U6dXJsKCR7X19fQ1NTX0xPQURFUl9VUkxfUkVQTEFDRU1FTlRfMF9fX30pO2JhY2tncm91bmQtcmVwZWF0Om5vLXJlcGVhdDtiYWNrZ3JvdW5kLXBvc2l0aW9uOmNlbnRlcn0uZ3JpZC1zdGFjay1pdGVtPi51aS1yZXNpemFibGUtbmV7dHJhbnNmb3JtOnRyYW5zbGF0ZSgwLDEwcHgpIHJvdGF0ZSg0NWRlZyl9LmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLXN3e3RyYW5zZm9ybTpyb3RhdGUoNDVkZWcpfS5ncmlkLXN0YWNrLWl0ZW0+LnVpLXJlc2l6YWJsZS1ud3t0cmFuc2Zvcm06dHJhbnNsYXRlKDAsMTBweCkgcm90YXRlKC00NWRlZyl9LmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLXNle3RyYW5zZm9ybTpyb3RhdGUoLTQ1ZGVnKX0uZ3JpZC1zdGFjay1pdGVtPi51aS1yZXNpemFibGUtbnd7Y3Vyc29yOm53LXJlc2l6ZTt3aWR0aDoyMHB4O2hlaWdodDoyMHB4O3RvcDowfS5ncmlkLXN0YWNrLWl0ZW0+LnVpLXJlc2l6YWJsZS1ue2N1cnNvcjpuLXJlc2l6ZTtoZWlnaHQ6MTBweDt0b3A6MDtsZWZ0OjI1cHg7cmlnaHQ6MjVweH0uZ3JpZC1zdGFjay1pdGVtPi51aS1yZXNpemFibGUtbmV7Y3Vyc29yOm5lLXJlc2l6ZTt3aWR0aDoyMHB4O2hlaWdodDoyMHB4O3RvcDowfS5ncmlkLXN0YWNrLWl0ZW0+LnVpLXJlc2l6YWJsZS1le2N1cnNvcjplLXJlc2l6ZTt3aWR0aDoxMHB4O3RvcDoxNXB4O2JvdHRvbToxNXB4fS5ncmlkLXN0YWNrLWl0ZW0+LnVpLXJlc2l6YWJsZS1zZXtjdXJzb3I6c2UtcmVzaXplO3dpZHRoOjIwcHg7aGVpZ2h0OjIwcHh9LmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLXN7Y3Vyc29yOnMtcmVzaXplO2hlaWdodDoxMHB4O2xlZnQ6MjVweDtib3R0b206MDtyaWdodDoyNXB4fS5ncmlkLXN0YWNrLWl0ZW0+LnVpLXJlc2l6YWJsZS1zd3tjdXJzb3I6c3ctcmVzaXplO3dpZHRoOjIwcHg7aGVpZ2h0OjIwcHh9LmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLXd7Y3Vyc29yOnctcmVzaXplO3dpZHRoOjEwcHg7dG9wOjE1cHg7Ym90dG9tOjE1cHh9LmdyaWQtc3RhY2staXRlbS51aS1kcmFnZ2FibGUtZHJhZ2dpbmc+LnVpLXJlc2l6YWJsZS1oYW5kbGV7ZGlzcGxheTpub25lIWltcG9ydGFudH0uZ3JpZC1zdGFjay1pdGVtLnVpLWRyYWdnYWJsZS1kcmFnZ2luZ3t3aWxsLWNoYW5nZTpsZWZ0LHRvcDtjdXJzb3I6bW92ZX0uZ3JpZC1zdGFjay1pdGVtLnVpLXJlc2l6YWJsZS1yZXNpemluZ3t3aWxsLWNoYW5nZTp3aWR0aCxoZWlnaHR9LnVpLWRyYWdnYWJsZS1kcmFnZ2luZywudWktcmVzaXphYmxlLXJlc2l6aW5ne3otaW5kZXg6MTAwMDB9LnVpLWRyYWdnYWJsZS1kcmFnZ2luZz4uZ3JpZC1zdGFjay1pdGVtLWNvbnRlbnQsLnVpLXJlc2l6YWJsZS1yZXNpemluZz4uZ3JpZC1zdGFjay1pdGVtLWNvbnRlbnR7Ym94LXNoYWRvdzoxcHggNHB4IDZweCByZ2JhKDAsMCwwLC4yKTtvcGFjaXR5Oi44fS5ncmlkLXN0YWNrLWFuaW1hdGUsLmdyaWQtc3RhY2stYW5pbWF0ZSAuZ3JpZC1zdGFjay1pdGVte3RyYW5zaXRpb246bGVmdCAuM3MsdG9wIC4zcyxoZWlnaHQgLjNzLHdpZHRoIC4zc30uZ3JpZC1zdGFjay1hbmltYXRlIC5ncmlkLXN0YWNrLWl0ZW0uZ3JpZC1zdGFjay1wbGFjZWhvbGRlciwuZ3JpZC1zdGFjay1hbmltYXRlIC5ncmlkLXN0YWNrLWl0ZW0udWktZHJhZ2dhYmxlLWRyYWdnaW5nLC5ncmlkLXN0YWNrLWFuaW1hdGUgLmdyaWQtc3RhY2staXRlbS51aS1yZXNpemFibGUtcmVzaXppbmd7dHJhbnNpdGlvbjpsZWZ0IDBzLHRvcCAwcyxoZWlnaHQgMHMsd2lkdGggMHN9LmdyaWQtc3RhY2s+LmdyaWQtc3RhY2staXRlbVtncy15PVwiMFwiXXt0b3A6MH0uZ3JpZC1zdGFjaz4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIwXCJde2xlZnQ6MH0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbXt3aWR0aDo4LjMzMyV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjFcIl17bGVmdDo4LjMzMyV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjJcIl17d2lkdGg6MTYuNjY3JX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy14PVwiMlwiXXtsZWZ0OjE2LjY2NyV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjNcIl17d2lkdGg6MjUlfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCIzXCJde2xlZnQ6MjUlfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI0XCJde3dpZHRoOjMzLjMzMyV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjRcIl17bGVmdDozMy4zMzMlfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI1XCJde3dpZHRoOjQxLjY2NyV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjVcIl17bGVmdDo0MS42NjclfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCI2XCJde3dpZHRoOjUwJX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy14PVwiNlwiXXtsZWZ0OjUwJX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy13PVwiN1wiXXt3aWR0aDo1OC4zMzMlfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCI3XCJde2xlZnQ6NTguMzMzJX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy13PVwiOFwiXXt3aWR0aDo2Ni42NjclfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XCI4XCJde2xlZnQ6NjYuNjY3JX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy13PVwiOVwiXXt3aWR0aDo3NSV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjlcIl17bGVmdDo3NSV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cIjEwXCJde3dpZHRoOjgzLjMzMyV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cIjEwXCJde2xlZnQ6ODMuMzMzJX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy13PVwiMTFcIl17d2lkdGg6OTEuNjY3JX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy14PVwiMTFcIl17bGVmdDo5MS42NjclfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XCIxMlwiXXt3aWR0aDoxMDAlfS5ncy0xPi5ncmlkLXN0YWNrLWl0ZW17d2lkdGg6MTAwJX1gLCBcIlwiLHtcInZlcnNpb25cIjozLFwic291cmNlc1wiOltcIndlYnBhY2s6Ly8uL25vZGVfbW9kdWxlcy9ncmlkc3RhY2svZGlzdC9ncmlkc3RhY2subWluLmNzc1wiXSxcIm5hbWVzXCI6W10sXCJtYXBwaW5nc1wiOlwiQUFBQSxZQUFZLGlCQUFpQixDQUFDLGdCQUFnQixhQUFhLENBQUMsaUNBQWlDLGFBQWEsQ0FBQyw2Q0FBNkMsK0JBQStCLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxtQkFBbUIsQ0FBQyw2QkFBNkIsaUJBQWlCLENBQUMsU0FBUyxDQUFDLHNEQUFzRCxRQUFRLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDLGVBQWUsQ0FBQyxnR0FBZ0csaUJBQWlCLENBQUMsc0NBQXNDLGlCQUFpQixDQUFDLGNBQWMsQ0FBQyxhQUFhLENBQUMscUJBQXFCLENBQUMsaUJBQWlCLENBQUMsd0hBQXdILFlBQVksQ0FBQyx3SUFBd0ksd0RBQXdQLENBQUMsMkJBQTJCLENBQUMsMEJBQTBCLENBQUMsa0NBQWtDLHlDQUF5QyxDQUFDLGtDQUFrQyx1QkFBdUIsQ0FBQyxrQ0FBa0MsMENBQTBDLENBQUMsa0NBQWtDLHdCQUF3QixDQUFDLGtDQUFrQyxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxpQ0FBaUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxrQ0FBa0MsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsaUNBQWlDLGVBQWUsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxrQ0FBa0MsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxpQ0FBaUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxrQ0FBa0MsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxpQ0FBaUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLDREQUE0RCxzQkFBc0IsQ0FBQyx1Q0FBdUMsb0JBQW9CLENBQUMsV0FBVyxDQUFDLHVDQUF1Qyx3QkFBd0IsQ0FBQyw4Q0FBOEMsYUFBYSxDQUFDLGdHQUFnRyxxQ0FBcUMsQ0FBQyxVQUFVLENBQUMseURBQXlELGdEQUFnRCxDQUFDLGtMQUFrTCw0Q0FBNEMsQ0FBQyx1Q0FBdUMsS0FBSyxDQUFDLHVDQUF1QyxNQUFNLENBQUMsd0JBQXdCLFlBQVksQ0FBQyxrQ0FBa0MsV0FBVyxDQUFDLGtDQUFrQyxhQUFhLENBQUMsa0NBQWtDLFlBQVksQ0FBQyxrQ0FBa0MsU0FBUyxDQUFDLGtDQUFrQyxRQUFRLENBQUMsa0NBQWtDLGFBQWEsQ0FBQyxrQ0FBa0MsWUFBWSxDQUFDLGtDQUFrQyxhQUFhLENBQUMsa0NBQWtDLFlBQVksQ0FBQyxrQ0FBa0MsU0FBUyxDQUFDLGtDQUFrQyxRQUFRLENBQUMsa0NBQWtDLGFBQWEsQ0FBQyxrQ0FBa0MsWUFBWSxDQUFDLGtDQUFrQyxhQUFhLENBQUMsa0NBQWtDLFlBQVksQ0FBQyxrQ0FBa0MsU0FBUyxDQUFDLGtDQUFrQyxRQUFRLENBQUMsbUNBQW1DLGFBQWEsQ0FBQyxtQ0FBbUMsWUFBWSxDQUFDLG1DQUFtQyxhQUFhLENBQUMsbUNBQW1DLFlBQVksQ0FBQyxtQ0FBbUMsVUFBVSxDQUFDLHVCQUF1QixVQUFVXCIsXCJzb3VyY2VzQ29udGVudFwiOltcIi5ncmlkLXN0YWNre3Bvc2l0aW9uOnJlbGF0aXZlfS5ncmlkLXN0YWNrLXJ0bHtkaXJlY3Rpb246bHRyfS5ncmlkLXN0YWNrLXJ0bD4uZ3JpZC1zdGFjay1pdGVte2RpcmVjdGlvbjpydGx9LmdyaWQtc3RhY2stcGxhY2Vob2xkZXI+LnBsYWNlaG9sZGVyLWNvbnRlbnR7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDAsMCwwLC4xKTttYXJnaW46MDtwb3NpdGlvbjphYnNvbHV0ZTt3aWR0aDphdXRvO3otaW5kZXg6MCFpbXBvcnRhbnR9LmdyaWQtc3RhY2s+LmdyaWQtc3RhY2staXRlbXtwb3NpdGlvbjphYnNvbHV0ZTtwYWRkaW5nOjB9LmdyaWQtc3RhY2s+LmdyaWQtc3RhY2staXRlbT4uZ3JpZC1zdGFjay1pdGVtLWNvbnRlbnR7bWFyZ2luOjA7cG9zaXRpb246YWJzb2x1dGU7d2lkdGg6YXV0bztvdmVyZmxvdy14OmhpZGRlbjtvdmVyZmxvdy15OmF1dG99LmdyaWQtc3RhY2s+LmdyaWQtc3RhY2staXRlbS5zaXplLXRvLWNvbnRlbnQ6bm90KC5zaXplLXRvLWNvbnRlbnQtbWF4KT4uZ3JpZC1zdGFjay1pdGVtLWNvbnRlbnR7b3ZlcmZsb3cteTpoaWRkZW59LmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLWhhbmRsZXtwb3NpdGlvbjphYnNvbHV0ZTtmb250LXNpemU6LjFweDtkaXNwbGF5OmJsb2NrOy1tcy10b3VjaC1hY3Rpb246bm9uZTt0b3VjaC1hY3Rpb246bm9uZX0uZ3JpZC1zdGFjay1pdGVtLnVpLXJlc2l6YWJsZS1hdXRvaGlkZT4udWktcmVzaXphYmxlLWhhbmRsZSwuZ3JpZC1zdGFjay1pdGVtLnVpLXJlc2l6YWJsZS1kaXNhYmxlZD4udWktcmVzaXphYmxlLWhhbmRsZXtkaXNwbGF5Om5vbmV9LmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLW5lLC5ncmlkLXN0YWNrLWl0ZW0+LnVpLXJlc2l6YWJsZS1udywuZ3JpZC1zdGFjay1pdGVtPi51aS1yZXNpemFibGUtc2UsLmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLXN3e2JhY2tncm91bmQtaW1hZ2U6dXJsKCdkYXRhOmltYWdlL3N2Zyt4bWw7dXRmOCw8c3ZnIHhtbG5zPVxcXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1xcXCIgZmlsbD1cXFwibm9uZVxcXCIgc3Ryb2tlPVxcXCIlMjM2NjZcXFwiIHN0cm9rZS1saW5lY2FwPVxcXCJyb3VuZFxcXCIgc3Ryb2tlLWxpbmVqb2luPVxcXCJyb3VuZFxcXCIgc3Ryb2tlLXdpZHRoPVxcXCIyXFxcIiB2aWV3Qm94PVxcXCIwIDAgMjAgMjBcXFwiPjxwYXRoIGQ9XFxcIm0xMCAzIDIgMkg4bDItMnYxNGwtMi0yaDRsLTIgMlxcXCIvPjwvc3ZnPicpO2JhY2tncm91bmQtcmVwZWF0Om5vLXJlcGVhdDtiYWNrZ3JvdW5kLXBvc2l0aW9uOmNlbnRlcn0uZ3JpZC1zdGFjay1pdGVtPi51aS1yZXNpemFibGUtbmV7dHJhbnNmb3JtOnRyYW5zbGF0ZSgwLDEwcHgpIHJvdGF0ZSg0NWRlZyl9LmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLXN3e3RyYW5zZm9ybTpyb3RhdGUoNDVkZWcpfS5ncmlkLXN0YWNrLWl0ZW0+LnVpLXJlc2l6YWJsZS1ud3t0cmFuc2Zvcm06dHJhbnNsYXRlKDAsMTBweCkgcm90YXRlKC00NWRlZyl9LmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLXNle3RyYW5zZm9ybTpyb3RhdGUoLTQ1ZGVnKX0uZ3JpZC1zdGFjay1pdGVtPi51aS1yZXNpemFibGUtbnd7Y3Vyc29yOm53LXJlc2l6ZTt3aWR0aDoyMHB4O2hlaWdodDoyMHB4O3RvcDowfS5ncmlkLXN0YWNrLWl0ZW0+LnVpLXJlc2l6YWJsZS1ue2N1cnNvcjpuLXJlc2l6ZTtoZWlnaHQ6MTBweDt0b3A6MDtsZWZ0OjI1cHg7cmlnaHQ6MjVweH0uZ3JpZC1zdGFjay1pdGVtPi51aS1yZXNpemFibGUtbmV7Y3Vyc29yOm5lLXJlc2l6ZTt3aWR0aDoyMHB4O2hlaWdodDoyMHB4O3RvcDowfS5ncmlkLXN0YWNrLWl0ZW0+LnVpLXJlc2l6YWJsZS1le2N1cnNvcjplLXJlc2l6ZTt3aWR0aDoxMHB4O3RvcDoxNXB4O2JvdHRvbToxNXB4fS5ncmlkLXN0YWNrLWl0ZW0+LnVpLXJlc2l6YWJsZS1zZXtjdXJzb3I6c2UtcmVzaXplO3dpZHRoOjIwcHg7aGVpZ2h0OjIwcHh9LmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLXN7Y3Vyc29yOnMtcmVzaXplO2hlaWdodDoxMHB4O2xlZnQ6MjVweDtib3R0b206MDtyaWdodDoyNXB4fS5ncmlkLXN0YWNrLWl0ZW0+LnVpLXJlc2l6YWJsZS1zd3tjdXJzb3I6c3ctcmVzaXplO3dpZHRoOjIwcHg7aGVpZ2h0OjIwcHh9LmdyaWQtc3RhY2staXRlbT4udWktcmVzaXphYmxlLXd7Y3Vyc29yOnctcmVzaXplO3dpZHRoOjEwcHg7dG9wOjE1cHg7Ym90dG9tOjE1cHh9LmdyaWQtc3RhY2staXRlbS51aS1kcmFnZ2FibGUtZHJhZ2dpbmc+LnVpLXJlc2l6YWJsZS1oYW5kbGV7ZGlzcGxheTpub25lIWltcG9ydGFudH0uZ3JpZC1zdGFjay1pdGVtLnVpLWRyYWdnYWJsZS1kcmFnZ2luZ3t3aWxsLWNoYW5nZTpsZWZ0LHRvcDtjdXJzb3I6bW92ZX0uZ3JpZC1zdGFjay1pdGVtLnVpLXJlc2l6YWJsZS1yZXNpemluZ3t3aWxsLWNoYW5nZTp3aWR0aCxoZWlnaHR9LnVpLWRyYWdnYWJsZS1kcmFnZ2luZywudWktcmVzaXphYmxlLXJlc2l6aW5ne3otaW5kZXg6MTAwMDB9LnVpLWRyYWdnYWJsZS1kcmFnZ2luZz4uZ3JpZC1zdGFjay1pdGVtLWNvbnRlbnQsLnVpLXJlc2l6YWJsZS1yZXNpemluZz4uZ3JpZC1zdGFjay1pdGVtLWNvbnRlbnR7Ym94LXNoYWRvdzoxcHggNHB4IDZweCByZ2JhKDAsMCwwLC4yKTtvcGFjaXR5Oi44fS5ncmlkLXN0YWNrLWFuaW1hdGUsLmdyaWQtc3RhY2stYW5pbWF0ZSAuZ3JpZC1zdGFjay1pdGVte3RyYW5zaXRpb246bGVmdCAuM3MsdG9wIC4zcyxoZWlnaHQgLjNzLHdpZHRoIC4zc30uZ3JpZC1zdGFjay1hbmltYXRlIC5ncmlkLXN0YWNrLWl0ZW0uZ3JpZC1zdGFjay1wbGFjZWhvbGRlciwuZ3JpZC1zdGFjay1hbmltYXRlIC5ncmlkLXN0YWNrLWl0ZW0udWktZHJhZ2dhYmxlLWRyYWdnaW5nLC5ncmlkLXN0YWNrLWFuaW1hdGUgLmdyaWQtc3RhY2staXRlbS51aS1yZXNpemFibGUtcmVzaXppbmd7dHJhbnNpdGlvbjpsZWZ0IDBzLHRvcCAwcyxoZWlnaHQgMHMsd2lkdGggMHN9LmdyaWQtc3RhY2s+LmdyaWQtc3RhY2staXRlbVtncy15PVxcXCIwXFxcIl17dG9wOjB9LmdyaWQtc3RhY2s+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCIwXFxcIl17bGVmdDowfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVte3dpZHRoOjguMzMzJX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCIxXFxcIl17bGVmdDo4LjMzMyV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiMlxcXCJde3dpZHRoOjE2LjY2NyV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiMlxcXCJde2xlZnQ6MTYuNjY3JX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCIzXFxcIl17d2lkdGg6MjUlfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjNcXFwiXXtsZWZ0OjI1JX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI0XFxcIl17d2lkdGg6MzMuMzMzJX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCI0XFxcIl17bGVmdDozMy4zMzMlfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjVcXFwiXXt3aWR0aDo0MS42NjclfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXg9XFxcIjVcXFwiXXtsZWZ0OjQxLjY2NyV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiNlxcXCJde3dpZHRoOjUwJX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCI2XFxcIl17bGVmdDo1MCV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiN1xcXCJde3dpZHRoOjU4LjMzMyV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiN1xcXCJde2xlZnQ6NTguMzMzJX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCI4XFxcIl17d2lkdGg6NjYuNjY3JX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCI4XFxcIl17bGVmdDo2Ni42NjclfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjlcXFwiXXt3aWR0aDo3NSV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiOVxcXCJde2xlZnQ6NzUlfS5ncy0xMj4uZ3JpZC1zdGFjay1pdGVtW2dzLXc9XFxcIjEwXFxcIl17d2lkdGg6ODMuMzMzJX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy14PVxcXCIxMFxcXCJde2xlZnQ6ODMuMzMzJX0uZ3MtMTI+LmdyaWQtc3RhY2staXRlbVtncy13PVxcXCIxMVxcXCJde3dpZHRoOjkxLjY2NyV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3MteD1cXFwiMTFcXFwiXXtsZWZ0OjkxLjY2NyV9LmdzLTEyPi5ncmlkLXN0YWNrLWl0ZW1bZ3Mtdz1cXFwiMTJcXFwiXXt3aWR0aDoxMDAlfS5ncy0xPi5ncmlkLXN0YWNrLWl0ZW17d2lkdGg6MTAwJX1cIl0sXCJzb3VyY2VSb290XCI6XCJcIn1dKTtcbi8vIEV4cG9ydHNcbmV4cG9ydCBkZWZhdWx0IF9fX0NTU19MT0FERVJfRVhQT1JUX19fO1xuIiwiLy8gSW1wb3J0c1xuaW1wb3J0IF9fX0NTU19MT0FERVJfQVBJX1NPVVJDRU1BUF9JTVBPUlRfX18gZnJvbSBcIi4uLy4uL25vZGVfbW9kdWxlcy9jc3MtbG9hZGVyL2Rpc3QvcnVudGltZS9zb3VyY2VNYXBzLmpzXCI7XG5pbXBvcnQgX19fQ1NTX0xPQURFUl9BUElfSU1QT1JUX19fIGZyb20gXCIuLi8uLi9ub2RlX21vZHVsZXMvY3NzLWxvYWRlci9kaXN0L3J1bnRpbWUvYXBpLmpzXCI7XG52YXIgX19fQ1NTX0xPQURFUl9FWFBPUlRfX18gPSBfX19DU1NfTE9BREVSX0FQSV9JTVBPUlRfX18oX19fQ1NTX0xPQURFUl9BUElfU09VUkNFTUFQX0lNUE9SVF9fXyk7XG4vLyBNb2R1bGVcbl9fX0NTU19MT0FERVJfRVhQT1JUX19fLnB1c2goW21vZHVsZS5pZCwgYFxuLmdyaWQtc3RhY2stZWRpdCB7XG4gIHBhZGRpbmc6IDAuMjVyZW07XG4gIGJvcmRlci13aWR0aDogMXB4O1xuICBib3JkZXItcmFkaXVzOiAwLjVyZW07XG59XG5cbi5ncy1pdGVtLWV4YW1wbGUge1xuICBib3JkZXItcmFkaXVzOiA4cHg7XG4gIGJvcmRlcjogMXB4IHNvbGlkIHJlZDtcbiAgYmFja2dyb3VuZDogI0ZGRjtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG5cbi5ncy10cmFzaCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xufVxuYCwgXCJcIix7XCJ2ZXJzaW9uXCI6MyxcInNvdXJjZXNcIjpbXCJ3ZWJwYWNrOi8vLi9zcmNqcy9jc3MvY3VzdG9tLmNzc1wiXSxcIm5hbWVzXCI6W10sXCJtYXBwaW5nc1wiOlwiO0FBQ0E7RUFDRSxnQkFBZ0I7RUFDaEIsaUJBQWlCO0VBQ2pCLHFCQUFxQjtBQUN2Qjs7QUFFQTtFQUNFLGtCQUFrQjtFQUNsQixxQkFBcUI7RUFDckIsZ0JBQWdCO0VBQ2hCLGVBQWU7RUFDZixhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLHVCQUF1QjtFQUN2QixpQkFBaUI7QUFDbkI7O0FBRUE7RUFDRSxhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLHVCQUF1QjtFQUN2QixzQkFBc0I7QUFDeEJcIixcInNvdXJjZXNDb250ZW50XCI6W1wiXFxuLmdyaWQtc3RhY2stZWRpdCB7XFxuICBwYWRkaW5nOiAwLjI1cmVtO1xcbiAgYm9yZGVyLXdpZHRoOiAxcHg7XFxuICBib3JkZXItcmFkaXVzOiAwLjVyZW07XFxufVxcblxcbi5ncy1pdGVtLWV4YW1wbGUge1xcbiAgYm9yZGVyLXJhZGl1czogOHB4O1xcbiAgYm9yZGVyOiAxcHggc29saWQgcmVkO1xcbiAgYmFja2dyb3VuZDogI0ZGRjtcXG4gIGN1cnNvcjogcG9pbnRlcjtcXG4gIGRpc3BsYXk6IGZsZXg7XFxuICBhbGlnbi1pdGVtczogY2VudGVyO1xcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XFxuICBmb250LXdlaWdodDogYm9sZDtcXG59XFxuXFxuLmdzLXRyYXNoIHtcXG4gIGRpc3BsYXk6IGZsZXg7XFxuICBhbGlnbi1pdGVtczogY2VudGVyO1xcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XFxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xcbn1cXG5cIl0sXCJzb3VyY2VSb290XCI6XCJcIn1dKTtcbi8vIEV4cG9ydHNcbmV4cG9ydCBkZWZhdWx0IF9fX0NTU19MT0FERVJfRVhQT1JUX19fO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbi8qXG4gIE1JVCBMaWNlbnNlIGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwXG4gIEF1dGhvciBUb2JpYXMgS29wcGVycyBAc29rcmFcbiovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjc3NXaXRoTWFwcGluZ1RvU3RyaW5nKSB7XG4gIHZhciBsaXN0ID0gW107XG5cbiAgLy8gcmV0dXJuIHRoZSBsaXN0IG9mIG1vZHVsZXMgYXMgY3NzIHN0cmluZ1xuICBsaXN0LnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMubWFwKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICB2YXIgY29udGVudCA9IFwiXCI7XG4gICAgICB2YXIgbmVlZExheWVyID0gdHlwZW9mIGl0ZW1bNV0gIT09IFwidW5kZWZpbmVkXCI7XG4gICAgICBpZiAoaXRlbVs0XSkge1xuICAgICAgICBjb250ZW50ICs9IFwiQHN1cHBvcnRzIChcIi5jb25jYXQoaXRlbVs0XSwgXCIpIHtcIik7XG4gICAgICB9XG4gICAgICBpZiAoaXRlbVsyXSkge1xuICAgICAgICBjb250ZW50ICs9IFwiQG1lZGlhIFwiLmNvbmNhdChpdGVtWzJdLCBcIiB7XCIpO1xuICAgICAgfVxuICAgICAgaWYgKG5lZWRMYXllcikge1xuICAgICAgICBjb250ZW50ICs9IFwiQGxheWVyXCIuY29uY2F0KGl0ZW1bNV0ubGVuZ3RoID4gMCA/IFwiIFwiLmNvbmNhdChpdGVtWzVdKSA6IFwiXCIsIFwiIHtcIik7XG4gICAgICB9XG4gICAgICBjb250ZW50ICs9IGNzc1dpdGhNYXBwaW5nVG9TdHJpbmcoaXRlbSk7XG4gICAgICBpZiAobmVlZExheWVyKSB7XG4gICAgICAgIGNvbnRlbnQgKz0gXCJ9XCI7XG4gICAgICB9XG4gICAgICBpZiAoaXRlbVsyXSkge1xuICAgICAgICBjb250ZW50ICs9IFwifVwiO1xuICAgICAgfVxuICAgICAgaWYgKGl0ZW1bNF0pIHtcbiAgICAgICAgY29udGVudCArPSBcIn1cIjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjb250ZW50O1xuICAgIH0pLmpvaW4oXCJcIik7XG4gIH07XG5cbiAgLy8gaW1wb3J0IGEgbGlzdCBvZiBtb2R1bGVzIGludG8gdGhlIGxpc3RcbiAgbGlzdC5pID0gZnVuY3Rpb24gaShtb2R1bGVzLCBtZWRpYSwgZGVkdXBlLCBzdXBwb3J0cywgbGF5ZXIpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZXMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIG1vZHVsZXMgPSBbW251bGwsIG1vZHVsZXMsIHVuZGVmaW5lZF1dO1xuICAgIH1cbiAgICB2YXIgYWxyZWFkeUltcG9ydGVkTW9kdWxlcyA9IHt9O1xuICAgIGlmIChkZWR1cGUpIHtcbiAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgdGhpcy5sZW5ndGg7IGsrKykge1xuICAgICAgICB2YXIgaWQgPSB0aGlzW2tdWzBdO1xuICAgICAgICBpZiAoaWQgIT0gbnVsbCkge1xuICAgICAgICAgIGFscmVhZHlJbXBvcnRlZE1vZHVsZXNbaWRdID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHZhciBfayA9IDA7IF9rIDwgbW9kdWxlcy5sZW5ndGg7IF9rKyspIHtcbiAgICAgIHZhciBpdGVtID0gW10uY29uY2F0KG1vZHVsZXNbX2tdKTtcbiAgICAgIGlmIChkZWR1cGUgJiYgYWxyZWFkeUltcG9ydGVkTW9kdWxlc1tpdGVtWzBdXSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgbGF5ZXIgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBpdGVtWzVdID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgaXRlbVs1XSA9IGxheWVyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGl0ZW1bMV0gPSBcIkBsYXllclwiLmNvbmNhdChpdGVtWzVdLmxlbmd0aCA+IDAgPyBcIiBcIi5jb25jYXQoaXRlbVs1XSkgOiBcIlwiLCBcIiB7XCIpLmNvbmNhdChpdGVtWzFdLCBcIn1cIik7XG4gICAgICAgICAgaXRlbVs1XSA9IGxheWVyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobWVkaWEpIHtcbiAgICAgICAgaWYgKCFpdGVtWzJdKSB7XG4gICAgICAgICAgaXRlbVsyXSA9IG1lZGlhO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGl0ZW1bMV0gPSBcIkBtZWRpYSBcIi5jb25jYXQoaXRlbVsyXSwgXCIge1wiKS5jb25jYXQoaXRlbVsxXSwgXCJ9XCIpO1xuICAgICAgICAgIGl0ZW1bMl0gPSBtZWRpYTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHN1cHBvcnRzKSB7XG4gICAgICAgIGlmICghaXRlbVs0XSkge1xuICAgICAgICAgIGl0ZW1bNF0gPSBcIlwiLmNvbmNhdChzdXBwb3J0cyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaXRlbVsxXSA9IFwiQHN1cHBvcnRzIChcIi5jb25jYXQoaXRlbVs0XSwgXCIpIHtcIikuY29uY2F0KGl0ZW1bMV0sIFwifVwiKTtcbiAgICAgICAgICBpdGVtWzRdID0gc3VwcG9ydHM7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGxpc3QucHVzaChpdGVtKTtcbiAgICB9XG4gIH07XG4gIHJldHVybiBsaXN0O1xufTsiLCJcInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodXJsLCBvcHRpb25zKSB7XG4gIGlmICghb3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSB7fTtcbiAgfVxuICBpZiAoIXVybCkge1xuICAgIHJldHVybiB1cmw7XG4gIH1cbiAgdXJsID0gU3RyaW5nKHVybC5fX2VzTW9kdWxlID8gdXJsLmRlZmF1bHQgOiB1cmwpO1xuXG4gIC8vIElmIHVybCBpcyBhbHJlYWR5IHdyYXBwZWQgaW4gcXVvdGVzLCByZW1vdmUgdGhlbVxuICBpZiAoL15bJ1wiXS4qWydcIl0kLy50ZXN0KHVybCkpIHtcbiAgICB1cmwgPSB1cmwuc2xpY2UoMSwgLTEpO1xuICB9XG4gIGlmIChvcHRpb25zLmhhc2gpIHtcbiAgICB1cmwgKz0gb3B0aW9ucy5oYXNoO1xuICB9XG5cbiAgLy8gU2hvdWxkIHVybCBiZSB3cmFwcGVkP1xuICAvLyBTZWUgaHR0cHM6Ly9kcmFmdHMuY3Nzd2cub3JnL2Nzcy12YWx1ZXMtMy8jdXJsc1xuICBpZiAoL1tcIicoKSBcXHRcXG5dfCglMjApLy50ZXN0KHVybCkgfHwgb3B0aW9ucy5uZWVkUXVvdGVzKSB7XG4gICAgcmV0dXJuIFwiXFxcIlwiLmNvbmNhdCh1cmwucmVwbGFjZSgvXCIvZywgJ1xcXFxcIicpLnJlcGxhY2UoL1xcbi9nLCBcIlxcXFxuXCIpLCBcIlxcXCJcIik7XG4gIH1cbiAgcmV0dXJuIHVybDtcbn07IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0ZW0pIHtcbiAgdmFyIGNvbnRlbnQgPSBpdGVtWzFdO1xuICB2YXIgY3NzTWFwcGluZyA9IGl0ZW1bM107XG4gIGlmICghY3NzTWFwcGluZykge1xuICAgIHJldHVybiBjb250ZW50O1xuICB9XG4gIGlmICh0eXBlb2YgYnRvYSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgdmFyIGJhc2U2NCA9IGJ0b2EodW5lc2NhcGUoZW5jb2RlVVJJQ29tcG9uZW50KEpTT04uc3RyaW5naWZ5KGNzc01hcHBpbmcpKSkpO1xuICAgIHZhciBkYXRhID0gXCJzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtjaGFyc2V0PXV0Zi04O2Jhc2U2NCxcIi5jb25jYXQoYmFzZTY0KTtcbiAgICB2YXIgc291cmNlTWFwcGluZyA9IFwiLyojIFwiLmNvbmNhdChkYXRhLCBcIiAqL1wiKTtcbiAgICByZXR1cm4gW2NvbnRlbnRdLmNvbmNhdChbc291cmNlTWFwcGluZ10pLmpvaW4oXCJcXG5cIik7XG4gIH1cbiAgcmV0dXJuIFtjb250ZW50XS5qb2luKFwiXFxuXCIpO1xufTsiLCIvKipcbiAqIGRkLWJhc2UtaW1wbC50cyAxMC4xLjJcbiAqIENvcHlyaWdodCAoYykgMjAyMS0yMDIyIEFsYWluIER1bWVzbnkgLSBzZWUgR3JpZFN0YWNrIHJvb3QgbGljZW5zZVxuICovXG5leHBvcnQgY2xhc3MgRERCYXNlSW1wbGVtZW50IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgICAgICB0aGlzLl9ldmVudFJlZ2lzdGVyID0ge307XG4gICAgfVxuICAgIC8qKiByZXR1cm5zIHRoZSBlbmFibGUgc3RhdGUsIGJ1dCB5b3UgaGF2ZSB0byBjYWxsIGVuYWJsZSgpL2Rpc2FibGUoKSB0byBjaGFuZ2UgKGFzIG90aGVyIHRoaW5ncyBuZWVkIHRvIGhhcHBlbikgKi9cbiAgICBnZXQgZGlzYWJsZWQoKSB7IHJldHVybiB0aGlzLl9kaXNhYmxlZDsgfVxuICAgIG9uKGV2ZW50LCBjYWxsYmFjaykge1xuICAgICAgICB0aGlzLl9ldmVudFJlZ2lzdGVyW2V2ZW50XSA9IGNhbGxiYWNrO1xuICAgIH1cbiAgICBvZmYoZXZlbnQpIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50UmVnaXN0ZXJbZXZlbnRdO1xuICAgIH1cbiAgICBlbmFibGUoKSB7XG4gICAgICAgIHRoaXMuX2Rpc2FibGVkID0gZmFsc2U7XG4gICAgfVxuICAgIGRpc2FibGUoKSB7XG4gICAgICAgIHRoaXMuX2Rpc2FibGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgZGVzdHJveSgpIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50UmVnaXN0ZXI7XG4gICAgfVxuICAgIHRyaWdnZXJFdmVudChldmVudE5hbWUsIGV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5kaXNhYmxlZCAmJiB0aGlzLl9ldmVudFJlZ2lzdGVyICYmIHRoaXMuX2V2ZW50UmVnaXN0ZXJbZXZlbnROYW1lXSlcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9ldmVudFJlZ2lzdGVyW2V2ZW50TmFtZV0oZXZlbnQpO1xuICAgIH1cbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRkLWJhc2UtaW1wbC5qcy5tYXAiLCIvKipcbiAqIGRkLWRyYWdnYWJsZS50cyAxMC4xLjJcbiAqIENvcHlyaWdodCAoYykgMjAyMS0yMDIyIEFsYWluIER1bWVzbnkgLSBzZWUgR3JpZFN0YWNrIHJvb3QgbGljZW5zZVxuICovXG5pbXBvcnQgeyBERE1hbmFnZXIgfSBmcm9tICcuL2RkLW1hbmFnZXInO1xuaW1wb3J0IHsgVXRpbHMgfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7IEREQmFzZUltcGxlbWVudCB9IGZyb20gJy4vZGQtYmFzZS1pbXBsJztcbmltcG9ydCB7IGlzVG91Y2gsIHRvdWNoZW5kLCB0b3VjaG1vdmUsIHRvdWNoc3RhcnQsIHBvaW50ZXJkb3duIH0gZnJvbSAnLi9kZC10b3VjaCc7XG4vLyBtYWtlIHN1cmUgd2UgYXJlIG5vdCBjbGlja2luZyBvbiBrbm93biBvYmplY3QgdGhhdCBoYW5kbGVzIG1vdXNlRG93blxuY29uc3Qgc2tpcE1vdXNlRG93biA9ICdpbnB1dCx0ZXh0YXJlYSxidXR0b24sc2VsZWN0LG9wdGlvbixbY29udGVudGVkaXRhYmxlPVwidHJ1ZVwiXSwudWktcmVzaXphYmxlLWhhbmRsZSc7XG4vLyBsZXQgY291bnQgPSAwOyAvLyBURVNUXG5jbGFzcyBERERyYWdnYWJsZSBleHRlbmRzIEREQmFzZUltcGxlbWVudCB7XG4gICAgY29uc3RydWN0b3IoZWwsIG9wdGlvbiA9IHt9KSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuZWwgPSBlbDtcbiAgICAgICAgdGhpcy5vcHRpb24gPSBvcHRpb247XG4gICAgICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICAgICAgdGhpcy5kcmFnVHJhbnNmb3JtID0ge1xuICAgICAgICAgICAgeFNjYWxlOiAxLFxuICAgICAgICAgICAgeVNjYWxlOiAxLFxuICAgICAgICAgICAgeE9mZnNldDogMCxcbiAgICAgICAgICAgIHlPZmZzZXQ6IDBcbiAgICAgICAgfTtcbiAgICAgICAgLy8gZ2V0IHRoZSBlbGVtZW50IHRoYXQgaXMgYWN0dWFsbHkgc3VwcG9zZWQgdG8gYmUgZHJhZ2dlZCBieVxuICAgICAgICBsZXQgaGFuZGxlTmFtZSA9IG9wdGlvbi5oYW5kbGUuc3Vic3RyaW5nKDEpO1xuICAgICAgICB0aGlzLmRyYWdFbCA9IGVsLmNsYXNzTGlzdC5jb250YWlucyhoYW5kbGVOYW1lKSA/IGVsIDogZWwucXVlcnlTZWxlY3RvcihvcHRpb24uaGFuZGxlKSB8fCBlbDtcbiAgICAgICAgLy8gY3JlYXRlIHZhciBldmVudCBiaW5kaW5nIHNvIHdlIGNhbiBlYXNpbHkgcmVtb3ZlIGFuZCBzdGlsbCBsb29rIGxpa2UgVFMgbWV0aG9kcyAodW5saWtlIGFub255bW91cyBmdW5jdGlvbnMpXG4gICAgICAgIHRoaXMuX21vdXNlRG93biA9IHRoaXMuX21vdXNlRG93bi5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLl9tb3VzZU1vdmUgPSB0aGlzLl9tb3VzZU1vdmUuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5fbW91c2VVcCA9IHRoaXMuX21vdXNlVXAuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5lbmFibGUoKTtcbiAgICB9XG4gICAgb24oZXZlbnQsIGNhbGxiYWNrKSB7XG4gICAgICAgIHN1cGVyLm9uKGV2ZW50LCBjYWxsYmFjayk7XG4gICAgfVxuICAgIG9mZihldmVudCkge1xuICAgICAgICBzdXBlci5vZmYoZXZlbnQpO1xuICAgIH1cbiAgICBlbmFibGUoKSB7XG4gICAgICAgIGlmICh0aGlzLmRpc2FibGVkID09PSBmYWxzZSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgc3VwZXIuZW5hYmxlKCk7XG4gICAgICAgIHRoaXMuZHJhZ0VsLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX21vdXNlRG93bik7XG4gICAgICAgIGlmIChpc1RvdWNoKSB7XG4gICAgICAgICAgICB0aGlzLmRyYWdFbC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdG91Y2hzdGFydCk7XG4gICAgICAgICAgICB0aGlzLmRyYWdFbC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVyZG93bicsIHBvaW50ZXJkb3duKTtcbiAgICAgICAgICAgIC8vIHRoaXMuZHJhZ0VsLnN0eWxlLnRvdWNoQWN0aW9uID0gJ25vbmUnOyAvLyBub3QgbmVlZGVkIHVubGlrZSBwb2ludGVyZG93biBkb2MgY29tbWVudFxuICAgICAgICB9XG4gICAgICAgIHRoaXMuZWwuY2xhc3NMaXN0LnJlbW92ZSgndWktZHJhZ2dhYmxlLWRpc2FibGVkJyk7XG4gICAgfVxuICAgIGRpc2FibGUoZm9yRGVzdHJveSA9IGZhbHNlKSB7XG4gICAgICAgIGlmICh0aGlzLmRpc2FibGVkID09PSB0cnVlKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBzdXBlci5kaXNhYmxlKCk7XG4gICAgICAgIHRoaXMuZHJhZ0VsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX21vdXNlRG93bik7XG4gICAgICAgIGlmIChpc1RvdWNoKSB7XG4gICAgICAgICAgICB0aGlzLmRyYWdFbC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdG91Y2hzdGFydCk7XG4gICAgICAgICAgICB0aGlzLmRyYWdFbC5yZW1vdmVFdmVudExpc3RlbmVyKCdwb2ludGVyZG93bicsIHBvaW50ZXJkb3duKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWZvckRlc3Ryb3kpXG4gICAgICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5hZGQoJ3VpLWRyYWdnYWJsZS1kaXNhYmxlZCcpO1xuICAgIH1cbiAgICBkZXN0cm95KCkge1xuICAgICAgICBpZiAodGhpcy5kcmFnVGltZW91dClcbiAgICAgICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy5kcmFnVGltZW91dCk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmRyYWdUaW1lb3V0O1xuICAgICAgICBpZiAodGhpcy5tb3VzZURvd25FdmVudClcbiAgICAgICAgICAgIHRoaXMuX21vdXNlVXAodGhpcy5tb3VzZURvd25FdmVudCk7XG4gICAgICAgIHRoaXMuZGlzYWJsZSh0cnVlKTtcbiAgICAgICAgZGVsZXRlIHRoaXMuZWw7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmhlbHBlcjtcbiAgICAgICAgZGVsZXRlIHRoaXMub3B0aW9uO1xuICAgICAgICBzdXBlci5kZXN0cm95KCk7XG4gICAgfVxuICAgIHVwZGF0ZU9wdGlvbihvcHRzKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKG9wdHMpLmZvckVhY2goa2V5ID0+IHRoaXMub3B0aW9uW2tleV0gPSBvcHRzW2tleV0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCBjYWxsIHdoZW4gbW91c2UgZ29lcyBkb3duIGJlZm9yZSBhIGRyYWdzdGFydCBoYXBwZW5zICovXG4gICAgX21vdXNlRG93bihlKSB7XG4gICAgICAgIC8vIGRvbid0IGxldCBtb3JlIHRoYW4gb25lIHdpZGdldCBoYW5kbGUgbW91c2VTdGFydFxuICAgICAgICBpZiAoRERNYW5hZ2VyLm1vdXNlSGFuZGxlZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgaWYgKGUuYnV0dG9uICE9PSAwKVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7IC8vIG9ubHkgbGVmdCBjbGlja1xuICAgICAgICAvLyBtYWtlIHN1cmUgd2UgYXJlIG5vdCBjbGlja2luZyBvbiBrbm93biBvYmplY3QgdGhhdCBoYW5kbGVzIG1vdXNlRG93biwgb3Igb25lcyBzdXBwbGllZCBieSB0aGUgdXNlclxuICAgICAgICBpZiAoZS50YXJnZXQuY2xvc2VzdChza2lwTW91c2VEb3duKSlcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICBpZiAodGhpcy5vcHRpb24uY2FuY2VsKSB7XG4gICAgICAgICAgICBpZiAoZS50YXJnZXQuY2xvc2VzdCh0aGlzLm9wdGlvbi5jYW5jZWwpKVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJFTU9WRTogd2h5IHdvdWxkIHdlIGdldCB0aGUgZXZlbnQgaWYgaXQgd2Fzbid0IGZvciB1cyBvciBjaGlsZCA/XG4gICAgICAgIC8vIG1ha2Ugc3VyZSB3ZSBhcmUgY2xpY2tpbmcgb24gYSBkcmFnIGhhbmRsZSBvciBjaGlsZCBvZiBpdC4uLlxuICAgICAgICAvLyBOb3RlOiB3ZSBkb24ndCBuZWVkIHRvIGNoZWNrIHRoYXQncyBoYW5kbGUgaXMgYW4gaW1tZWRpYXRlIGNoaWxkLCBhcyBtb3VzZUhhbmRsZWQgd2lsbCBwcmV2ZW50IHBhcmVudHMgZnJvbSBhbHNvIGhhbmRsaW5nIGl0IChsb3dlc3Qgd2lucylcbiAgICAgICAgLy8gbGV0IGNsYXNzTmFtZSA9IHRoaXMub3B0aW9uLmhhbmRsZS5zdWJzdHJpbmcoMSk7XG4gICAgICAgIC8vIGxldCBlbCA9IGUudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgICAgICAvLyB3aGlsZSAoZWwgJiYgIWVsLmNsYXNzTGlzdC5jb250YWlucyhjbGFzc05hbWUpKSB7IGVsID0gZWwucGFyZW50RWxlbWVudDsgfVxuICAgICAgICAvLyBpZiAoIWVsKSByZXR1cm47XG4gICAgICAgIHRoaXMubW91c2VEb3duRXZlbnQgPSBlO1xuICAgICAgICBkZWxldGUgdGhpcy5kcmFnZ2luZztcbiAgICAgICAgZGVsZXRlIERETWFuYWdlci5kcmFnRWxlbWVudDtcbiAgICAgICAgZGVsZXRlIERETWFuYWdlci5kcm9wRWxlbWVudDtcbiAgICAgICAgLy8gZG9jdW1lbnQgaGFuZGxlciBzbyB3ZSBjYW4gY29udGludWUgcmVjZWl2aW5nIG1vdmVzIGFzIHRoZSBpdGVtIGlzICdmaXhlZCcgcG9zaXRpb24sIGFuZCBjYXB0dXJlPXRydWUgc28gV0UgZ2V0IGEgZmlyc3QgY3JhY2tcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fbW91c2VNb3ZlLCB7IGNhcHR1cmU6IHRydWUsIHBhc3NpdmU6IHRydWUgfSk7IC8vIHRydWU9Y2FwdHVyZSwgbm90IGJ1YmJsZVxuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fbW91c2VVcCwgdHJ1ZSk7XG4gICAgICAgIGlmIChpc1RvdWNoKSB7XG4gICAgICAgICAgICB0aGlzLmRyYWdFbC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0b3VjaG1vdmUpO1xuICAgICAgICAgICAgdGhpcy5kcmFnRWwuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0b3VjaGVuZCk7XG4gICAgICAgIH1cbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAvLyBwcmV2ZW50RGVmYXVsdCgpIHByZXZlbnRzIGJsdXIgZXZlbnQgd2hpY2ggb2NjdXJzIGp1c3QgYWZ0ZXIgbW91c2Vkb3duIGV2ZW50LlxuICAgICAgICAvLyBpZiBhbiBlZGl0YWJsZSBjb250ZW50IGhhcyBmb2N1cywgdGhlbiBibHVyIG11c3QgYmUgY2FsbFxuICAgICAgICBpZiAoZG9jdW1lbnQuYWN0aXZlRWxlbWVudClcbiAgICAgICAgICAgIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQuYmx1cigpO1xuICAgICAgICBERE1hbmFnZXIubW91c2VIYW5kbGVkID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgbWV0aG9kIHRvIGNhbGwgYWN0dWFsIGRyYWcgZXZlbnQgKi9cbiAgICBfY2FsbERyYWcoZSkge1xuICAgICAgICBpZiAoIXRoaXMuZHJhZ2dpbmcpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IGV2ID0gVXRpbHMuaW5pdEV2ZW50KGUsIHsgdGFyZ2V0OiB0aGlzLmVsLCB0eXBlOiAnZHJhZycgfSk7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbi5kcmFnKSB7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbi5kcmFnKGV2LCB0aGlzLnVpKCkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudHJpZ2dlckV2ZW50KCdkcmFnJywgZXYpO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsIGNhbGxlZCB3aGVuIHRoZSBtYWluIHBhZ2UgKGFmdGVyIHN1Y2Nlc3NmdWwgbW91c2Vkb3duKSByZWNlaXZlcyBhIG1vdmUgZXZlbnQgdG8gZHJhZyB0aGUgaXRlbSBhcm91bmQgdGhlIHNjcmVlbiAqL1xuICAgIF9tb3VzZU1vdmUoZSkge1xuICAgICAgICAvLyBjb25zb2xlLmxvZyhgJHtjb3VudCsrfSBtb3ZlICR7ZS54fSwke2UueX1gKVxuICAgICAgICBsZXQgcyA9IHRoaXMubW91c2VEb3duRXZlbnQ7XG4gICAgICAgIGlmICh0aGlzLmRyYWdnaW5nKSB7XG4gICAgICAgICAgICB0aGlzLl9kcmFnRm9sbG93KGUpO1xuICAgICAgICAgICAgLy8gZGVsYXkgYWN0dWFsIGdyaWQgaGFuZGxpbmcgZHJhZyB1bnRpbCB3ZSBwYXVzZSBmb3IgYSB3aGlsZSBpZiBzZXRcbiAgICAgICAgICAgIGlmIChERE1hbmFnZXIucGF1c2VEcmFnKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGF1c2UgPSBOdW1iZXIuaXNJbnRlZ2VyKERETWFuYWdlci5wYXVzZURyYWcpID8gRERNYW5hZ2VyLnBhdXNlRHJhZyA6IDEwMDtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kcmFnVGltZW91dClcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmNsZWFyVGltZW91dCh0aGlzLmRyYWdUaW1lb3V0KTtcbiAgICAgICAgICAgICAgICB0aGlzLmRyYWdUaW1lb3V0ID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4gdGhpcy5fY2FsbERyYWcoZSksIHBhdXNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX2NhbGxEcmFnKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKE1hdGguYWJzKGUueCAtIHMueCkgKyBNYXRoLmFicyhlLnkgLSBzLnkpID4gMykge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBkb24ndCBzdGFydCB1bmxlc3Mgd2UndmUgbW92ZWQgYXQgbGVhc3QgMyBwaXhlbHNcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdGhpcy5kcmFnZ2luZyA9IHRydWU7XG4gICAgICAgICAgICBERE1hbmFnZXIuZHJhZ0VsZW1lbnQgPSB0aGlzO1xuICAgICAgICAgICAgLy8gaWYgd2UncmUgZHJhZ2dpbmcgYW4gYWN0dWFsIGdyaWQgaXRlbSwgc2V0IHRoZSBjdXJyZW50IGRyb3AgYXMgdGhlIGdyaWQgKHRvIGRldGVjdCBlbnRlci9sZWF2ZSlcbiAgICAgICAgICAgIGxldCBncmlkID0gdGhpcy5lbC5ncmlkc3RhY2tOb2RlPy5ncmlkO1xuICAgICAgICAgICAgaWYgKGdyaWQpIHtcbiAgICAgICAgICAgICAgICBERE1hbmFnZXIuZHJvcEVsZW1lbnQgPSBncmlkLmVsLmRkRWxlbWVudC5kZERyb3BwYWJsZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBERE1hbmFnZXIuZHJvcEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmhlbHBlciA9IHRoaXMuX2NyZWF0ZUhlbHBlcihlKTtcbiAgICAgICAgICAgIHRoaXMuX3NldHVwSGVscGVyQ29udGFpbm1lbnRTdHlsZSgpO1xuICAgICAgICAgICAgdGhpcy5kcmFnVHJhbnNmb3JtID0gVXRpbHMuZ2V0VmFsdWVzRnJvbVRyYW5zZm9ybWVkRWxlbWVudCh0aGlzLmhlbHBlckNvbnRhaW5tZW50KTtcbiAgICAgICAgICAgIHRoaXMuZHJhZ09mZnNldCA9IHRoaXMuX2dldERyYWdPZmZzZXQoZSwgdGhpcy5lbCwgdGhpcy5oZWxwZXJDb250YWlubWVudCk7XG4gICAgICAgICAgICBjb25zdCBldiA9IFV0aWxzLmluaXRFdmVudChlLCB7IHRhcmdldDogdGhpcy5lbCwgdHlwZTogJ2RyYWdzdGFydCcgfSk7XG4gICAgICAgICAgICB0aGlzLl9zZXR1cEhlbHBlclN0eWxlKGUpO1xuICAgICAgICAgICAgaWYgKHRoaXMub3B0aW9uLnN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcHRpb24uc3RhcnQoZXYsIHRoaXMudWkoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnRyaWdnZXJFdmVudCgnZHJhZ3N0YXJ0JywgZXYpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGUucHJldmVudERlZmF1bHQoKTsgLy8gcGFzc2l2ZSA9IHRydWUuIE9MRDogd2FzIG5lZWRlZCBvdGhlcndpc2Ugd2UgZ2V0IHRleHQgc3dlZXAgdGV4dCBzZWxlY3Rpb24gYXMgd2UgZHJhZyBhcm91bmRcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgY2FsbCB3aGVuIHRoZSBtb3VzZSBnZXRzIHJlbGVhc2VkIHRvIGRyb3AgdGhlIGl0ZW0gYXQgY3VycmVudCBsb2NhdGlvbiAqL1xuICAgIF9tb3VzZVVwKGUpIHtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fbW91c2VNb3ZlLCB0cnVlKTtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX21vdXNlVXAsIHRydWUpO1xuICAgICAgICBpZiAoaXNUb3VjaCkge1xuICAgICAgICAgICAgdGhpcy5kcmFnRWwucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdG91Y2htb3ZlLCB0cnVlKTtcbiAgICAgICAgICAgIHRoaXMuZHJhZ0VsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdG91Y2hlbmQsIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmRyYWdnaW5nKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5kcmFnZ2luZztcbiAgICAgICAgICAgIC8vIHJlc2V0IHRoZSBkcm9wIHRhcmdldCBpZiBkcmFnZ2luZyBvdmVyIG91cnNlbGYgKGFscmVhZHkgcGFyZW50ZWQsIGp1c3QgbW92aW5nIGR1cmluZyBzdG9wIGNhbGxiYWNrIGJlbG93KVxuICAgICAgICAgICAgaWYgKERETWFuYWdlci5kcm9wRWxlbWVudD8uZWwgPT09IHRoaXMuZWwucGFyZW50RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBERE1hbmFnZXIuZHJvcEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmhlbHBlckNvbnRhaW5tZW50LnN0eWxlLnBvc2l0aW9uID0gdGhpcy5wYXJlbnRPcmlnaW5TdHlsZVBvc2l0aW9uIHx8IG51bGw7XG4gICAgICAgICAgICBpZiAodGhpcy5oZWxwZXIgPT09IHRoaXMuZWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVIZWxwZXJTdHlsZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oZWxwZXIucmVtb3ZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBldiA9IFV0aWxzLmluaXRFdmVudChlLCB7IHRhcmdldDogdGhpcy5lbCwgdHlwZTogJ2RyYWdzdG9wJyB9KTtcbiAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbi5zdG9wKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcHRpb24uc3RvcChldik7IC8vIE5PVEU6IGRlc3Ryb3koKSB3aWxsIGJlIGNhbGxlZCB3aGVuIHJlbW92aW5nIGl0ZW0sIHNvIGV4cGVjdCBOVUxMIHB0ciBhZnRlciFcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudHJpZ2dlckV2ZW50KCdkcmFnc3RvcCcsIGV2KTtcbiAgICAgICAgICAgIC8vIGNhbGwgdGhlIGRyb3BwYWJsZSBtZXRob2QgdG8gcmVjZWl2ZSB0aGUgaXRlbVxuICAgICAgICAgICAgaWYgKERETWFuYWdlci5kcm9wRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIERETWFuYWdlci5kcm9wRWxlbWVudC5kcm9wKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGRlbGV0ZSB0aGlzLmhlbHBlcjtcbiAgICAgICAgZGVsZXRlIHRoaXMubW91c2VEb3duRXZlbnQ7XG4gICAgICAgIGRlbGV0ZSBERE1hbmFnZXIuZHJhZ0VsZW1lbnQ7XG4gICAgICAgIGRlbGV0ZSBERE1hbmFnZXIuZHJvcEVsZW1lbnQ7XG4gICAgICAgIGRlbGV0ZSBERE1hbmFnZXIubW91c2VIYW5kbGVkO1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgY3JlYXRlIGEgY2xvbmUgY29weSAob3IgdXNlciBkZWZpbmVkIG1ldGhvZCkgb2YgdGhlIG9yaWdpbmFsIGRyYWcgaXRlbSBpZiBzZXQgKi9cbiAgICBfY3JlYXRlSGVscGVyKGV2ZW50KSB7XG4gICAgICAgIGxldCBoZWxwZXIgPSB0aGlzLmVsO1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMub3B0aW9uLmhlbHBlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgaGVscGVyID0gdGhpcy5vcHRpb24uaGVscGVyKGV2ZW50KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLm9wdGlvbi5oZWxwZXIgPT09ICdjbG9uZScpIHtcbiAgICAgICAgICAgIGhlbHBlciA9IFV0aWxzLmNsb25lTm9kZSh0aGlzLmVsKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWRvY3VtZW50LmJvZHkuY29udGFpbnMoaGVscGVyKSkge1xuICAgICAgICAgICAgVXRpbHMuYXBwZW5kVG8oaGVscGVyLCB0aGlzLm9wdGlvbi5hcHBlbmRUbyA9PT0gJ3BhcmVudCcgPyB0aGlzLmVsLnBhcmVudEVsZW1lbnQgOiB0aGlzLm9wdGlvbi5hcHBlbmRUbyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhlbHBlciA9PT0gdGhpcy5lbCkge1xuICAgICAgICAgICAgdGhpcy5kcmFnRWxlbWVudE9yaWdpblN0eWxlID0gREREcmFnZ2FibGUub3JpZ2luU3R5bGVQcm9wLm1hcChwcm9wID0+IHRoaXMuZWwuc3R5bGVbcHJvcF0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBoZWxwZXI7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgc2V0IHRoZSBmaXggcG9zaXRpb24gb2YgdGhlIGRyYWdnZWQgaXRlbSAqL1xuICAgIF9zZXR1cEhlbHBlclN0eWxlKGUpIHtcbiAgICAgICAgdGhpcy5oZWxwZXIuY2xhc3NMaXN0LmFkZCgndWktZHJhZ2dhYmxlLWRyYWdnaW5nJyk7XG4gICAgICAgIC8vIFRPRE86IHNldCBhbGwgYXQgb25jZSB3aXRoIHN0eWxlLmNzc1RleHQgKz0gLi4uID8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzk2ODU5M1xuICAgICAgICBjb25zdCBzdHlsZSA9IHRoaXMuaGVscGVyLnN0eWxlO1xuICAgICAgICBzdHlsZS5wb2ludGVyRXZlbnRzID0gJ25vbmUnOyAvLyBuZWVkZWQgZm9yIG92ZXIgaXRlbXMgdG8gZ2V0IGVudGVyL2xlYXZlXG4gICAgICAgIC8vIHN0eWxlLmN1cnNvciA9ICdtb3ZlJzsgLy8gIFRPRE86IGNhbid0IHNldCB3aXRoIHBvaW50ZXJFdmVudHM9bm9uZSAhIChkb25lIGluIENTUyBhcyB3ZWxsKVxuICAgICAgICBzdHlsZS53aWR0aCA9IHRoaXMuZHJhZ09mZnNldC53aWR0aCArICdweCc7XG4gICAgICAgIHN0eWxlLmhlaWdodCA9IHRoaXMuZHJhZ09mZnNldC5oZWlnaHQgKyAncHgnO1xuICAgICAgICBzdHlsZS53aWxsQ2hhbmdlID0gJ2xlZnQsIHRvcCc7XG4gICAgICAgIHN0eWxlLnBvc2l0aW9uID0gJ2ZpeGVkJzsgLy8gbGV0IHVzIGRyYWcgYmV0d2VlbiBncmlkcyBieSBub3QgY2xpcHBpbmcgYXMgcGFyZW50IC5ncmlkLXN0YWNrIGlzIHBvc2l0aW9uOiAncmVsYXRpdmUnXG4gICAgICAgIHRoaXMuX2RyYWdGb2xsb3coZSk7IC8vIG5vdyBwb3NpdGlvbiBpdFxuICAgICAgICBzdHlsZS50cmFuc2l0aW9uID0gJ25vbmUnOyAvLyBzaG93IHVwIGluc3RhbnRseVxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmhlbHBlcikge1xuICAgICAgICAgICAgICAgIHN0eWxlLnRyYW5zaXRpb24gPSBudWxsOyAvLyByZWNvdmVyIGFuaW1hdGlvblxuICAgICAgICAgICAgfVxuICAgICAgICB9LCAwKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgcmVzdG9yZSBiYWNrIHRoZSBvcmlnaW5hbCBzdHlsZSBiZWZvcmUgZHJhZ2dpbmcgKi9cbiAgICBfcmVtb3ZlSGVscGVyU3R5bGUoKSB7XG4gICAgICAgIHRoaXMuaGVscGVyLmNsYXNzTGlzdC5yZW1vdmUoJ3VpLWRyYWdnYWJsZS1kcmFnZ2luZycpO1xuICAgICAgICBsZXQgbm9kZSA9IHRoaXMuaGVscGVyPy5ncmlkc3RhY2tOb2RlO1xuICAgICAgICAvLyBkb24ndCBib3RoZXIgcmVzdG9yaW5nIHN0eWxlcyBpZiB3ZSdyZSBnb25uYSByZW1vdmUgYW55d2F5Li4uXG4gICAgICAgIGlmICghbm9kZT8uX2lzQWJvdXRUb1JlbW92ZSAmJiB0aGlzLmRyYWdFbGVtZW50T3JpZ2luU3R5bGUpIHtcbiAgICAgICAgICAgIGxldCBoZWxwZXIgPSB0aGlzLmhlbHBlcjtcbiAgICAgICAgICAgIC8vIGRvbid0IGFuaW1hdGUsIG90aGVyd2lzZSB3ZSBhbmltYXRlIG9mZnNldGVkIHdoZW4gc3dpdGNoaW5nIGJhY2sgdG8gJ2Fic29sdXRlJyBmcm9tICdmaXhlZCcuXG4gICAgICAgICAgICAvLyBUT0RPOiB0aGlzIGFsc28gcmVtb3ZlcyByZXNpemluZyBhbmltYXRpb24gd2hpY2ggZG9lc24ndCBoYXZlIHRoaXMgaXNzdWUsIGJ1dCBvdGhlcnMuXG4gICAgICAgICAgICAvLyBJZGVhbGx5IGJvdGggd291bGQgYW5pbWF0ZSAoJ21vdmUnIHdvdWxkIGltbWVkaWF0ZWx5IHJlc3RvcmUgJ2Fic29sdXRlJyBhbmQgYWRqdXN0IGNvb3JkaW5hdGUgdG8gbWF0Y2gsXG4gICAgICAgICAgICAvLyB0aGVuIHRyaWdnZXIgYSBkZWxheSAocmVwYWludCkgdG8gcmVzdG9yZSB0byBmaW5hbCBkZXN0IHdpdGggYW5pbWF0ZSkgYnV0IHRoZW4gd2UgbmVlZCB0byBtYWtlIHN1cmUgJ3Jlc2l6ZXN0b3AnXG4gICAgICAgICAgICAvLyBpcyBjYWxsZWQgQUZURVIgJ3RyYW5zaXRpb25lbmQnIGV2ZW50IGlzIHJlY2VpdmVkIChzZWUgaHR0cHM6Ly9naXRodWIuY29tL2dyaWRzdGFjay9ncmlkc3RhY2suanMvaXNzdWVzLzIwMzMpXG4gICAgICAgICAgICBsZXQgdHJhbnNpdGlvbiA9IHRoaXMuZHJhZ0VsZW1lbnRPcmlnaW5TdHlsZVsndHJhbnNpdGlvbiddIHx8IG51bGw7XG4gICAgICAgICAgICBoZWxwZXIuc3R5bGUudHJhbnNpdGlvbiA9IHRoaXMuZHJhZ0VsZW1lbnRPcmlnaW5TdHlsZVsndHJhbnNpdGlvbiddID0gJ25vbmUnOyAvLyBjYW4ndCBiZSBOVUxMICMxOTczXG4gICAgICAgICAgICBERERyYWdnYWJsZS5vcmlnaW5TdHlsZVByb3AuZm9yRWFjaChwcm9wID0+IGhlbHBlci5zdHlsZVtwcm9wXSA9IHRoaXMuZHJhZ0VsZW1lbnRPcmlnaW5TdHlsZVtwcm9wXSB8fCBudWxsKTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gaGVscGVyLnN0eWxlLnRyYW5zaXRpb24gPSB0cmFuc2l0aW9uLCA1MCk7IC8vIHJlY292ZXIgYW5pbWF0aW9uIGZyb20gc2F2ZWQgdmFycyBhZnRlciBhIHBhdXNlICgwIGlzbid0IGVub3VnaCAjMTk3MylcbiAgICAgICAgfVxuICAgICAgICBkZWxldGUgdGhpcy5kcmFnRWxlbWVudE9yaWdpblN0eWxlO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCB1cGRhdGVzIHRoZSB0b3AvbGVmdCBwb3NpdGlvbiB0byBmb2xsb3cgdGhlIG1vdXNlICovXG4gICAgX2RyYWdGb2xsb3coZSkge1xuICAgICAgICBsZXQgY29udGFpbm1lbnRSZWN0ID0geyBsZWZ0OiAwLCB0b3A6IDAgfTtcbiAgICAgICAgLy8gaWYgKHRoaXMuaGVscGVyLnN0eWxlLnBvc2l0aW9uID09PSAnYWJzb2x1dGUnKSB7IC8vIHdlIHVzZSAnZml4ZWQnXG4gICAgICAgIC8vICAgY29uc3QgeyBsZWZ0LCB0b3AgfSA9IHRoaXMuaGVscGVyQ29udGFpbm1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIC8vICAgY29udGFpbm1lbnRSZWN0ID0geyBsZWZ0LCB0b3AgfTtcbiAgICAgICAgLy8gfVxuICAgICAgICBjb25zdCBzdHlsZSA9IHRoaXMuaGVscGVyLnN0eWxlO1xuICAgICAgICBjb25zdCBvZmZzZXQgPSB0aGlzLmRyYWdPZmZzZXQ7XG4gICAgICAgIHN0eWxlLmxlZnQgPSAoZS5jbGllbnRYICsgb2Zmc2V0Lm9mZnNldExlZnQgLSBjb250YWlubWVudFJlY3QubGVmdCkgKiB0aGlzLmRyYWdUcmFuc2Zvcm0ueFNjYWxlICsgJ3B4JztcbiAgICAgICAgc3R5bGUudG9wID0gKGUuY2xpZW50WSArIG9mZnNldC5vZmZzZXRUb3AgLSBjb250YWlubWVudFJlY3QudG9wKSAqIHRoaXMuZHJhZ1RyYW5zZm9ybS55U2NhbGUgKyAncHgnO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsICovXG4gICAgX3NldHVwSGVscGVyQ29udGFpbm1lbnRTdHlsZSgpIHtcbiAgICAgICAgdGhpcy5oZWxwZXJDb250YWlubWVudCA9IHRoaXMuaGVscGVyLnBhcmVudEVsZW1lbnQ7XG4gICAgICAgIGlmICh0aGlzLmhlbHBlci5zdHlsZS5wb3NpdGlvbiAhPT0gJ2ZpeGVkJykge1xuICAgICAgICAgICAgdGhpcy5wYXJlbnRPcmlnaW5TdHlsZVBvc2l0aW9uID0gdGhpcy5oZWxwZXJDb250YWlubWVudC5zdHlsZS5wb3NpdGlvbjtcbiAgICAgICAgICAgIGlmIChnZXRDb21wdXRlZFN0eWxlKHRoaXMuaGVscGVyQ29udGFpbm1lbnQpLnBvc2l0aW9uLm1hdGNoKC9zdGF0aWMvKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGVscGVyQ29udGFpbm1lbnQuc3R5bGUucG9zaXRpb24gPSAncmVsYXRpdmUnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsICovXG4gICAgX2dldERyYWdPZmZzZXQoZXZlbnQsIGVsLCBwYXJlbnQpIHtcbiAgICAgICAgLy8gaW4gY2FzZSBhbmNlc3RvciBoYXMgdHJhbnNmb3JtL3BlcnNwZWN0aXZlIGNzcyBwcm9wZXJ0aWVzIHRoYXQgY2hhbmdlIHRoZSB2aWV3cG9pbnRcbiAgICAgICAgbGV0IHhmb3JtT2Zmc2V0WCA9IDA7XG4gICAgICAgIGxldCB4Zm9ybU9mZnNldFkgPSAwO1xuICAgICAgICBpZiAocGFyZW50KSB7XG4gICAgICAgICAgICB4Zm9ybU9mZnNldFggPSB0aGlzLmRyYWdUcmFuc2Zvcm0ueE9mZnNldDtcbiAgICAgICAgICAgIHhmb3JtT2Zmc2V0WSA9IHRoaXMuZHJhZ1RyYW5zZm9ybS55T2Zmc2V0O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRhcmdldE9mZnNldCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGVmdDogdGFyZ2V0T2Zmc2V0LmxlZnQsXG4gICAgICAgICAgICB0b3A6IHRhcmdldE9mZnNldC50b3AsXG4gICAgICAgICAgICBvZmZzZXRMZWZ0OiAtZXZlbnQuY2xpZW50WCArIHRhcmdldE9mZnNldC5sZWZ0IC0geGZvcm1PZmZzZXRYLFxuICAgICAgICAgICAgb2Zmc2V0VG9wOiAtZXZlbnQuY2xpZW50WSArIHRhcmdldE9mZnNldC50b3AgLSB4Zm9ybU9mZnNldFksXG4gICAgICAgICAgICB3aWR0aDogdGFyZ2V0T2Zmc2V0LndpZHRoICogdGhpcy5kcmFnVHJhbnNmb3JtLnhTY2FsZSxcbiAgICAgICAgICAgIGhlaWdodDogdGFyZ2V0T2Zmc2V0LmhlaWdodCAqIHRoaXMuZHJhZ1RyYW5zZm9ybS55U2NhbGVcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCBUT0RPOiBzZXQgdG8gcHVibGljIGFzIGNhbGxlZCBieSBERERyb3BwYWJsZSEgKi9cbiAgICB1aSgpIHtcbiAgICAgICAgY29uc3QgY29udGFpbm1lbnRFbCA9IHRoaXMuZWwucGFyZW50RWxlbWVudDtcbiAgICAgICAgY29uc3QgY29udGFpbm1lbnRSZWN0ID0gY29udGFpbm1lbnRFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgY29uc3Qgb2Zmc2V0ID0gdGhpcy5oZWxwZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgICAgIHRvcDogKG9mZnNldC50b3AgLSBjb250YWlubWVudFJlY3QudG9wKSAqIHRoaXMuZHJhZ1RyYW5zZm9ybS55U2NhbGUsXG4gICAgICAgICAgICAgICAgbGVmdDogKG9mZnNldC5sZWZ0IC0gY29udGFpbm1lbnRSZWN0LmxlZnQpICogdGhpcy5kcmFnVHJhbnNmb3JtLnhTY2FsZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLyogbm90IHVzZWQgYnkgR3JpZFN0YWNrIGZvciBub3cuLi5cbiAgICAgICAgICAgIGhlbHBlcjogW3RoaXMuaGVscGVyXSwgLy9UaGUgb2JqZWN0IGFyciByZXByZXNlbnRpbmcgdGhlIGhlbHBlciB0aGF0J3MgYmVpbmcgZHJhZ2dlZC5cbiAgICAgICAgICAgIG9mZnNldDogeyB0b3A6IG9mZnNldC50b3AsIGxlZnQ6IG9mZnNldC5sZWZ0IH0gLy8gQ3VycmVudCBvZmZzZXQgcG9zaXRpb24gb2YgdGhlIGhlbHBlciBhcyB7IHRvcCwgbGVmdCB9IG9iamVjdC5cbiAgICAgICAgICAgICovXG4gICAgICAgIH07XG4gICAgfVxufVxuLyoqIEBpbnRlcm5hbCBwcm9wZXJ0aWVzIHdlIGNoYW5nZSBkdXJpbmcgZHJhZ2dpbmcsIGFuZCByZXN0b3JlIGJhY2sgKi9cbkRERHJhZ2dhYmxlLm9yaWdpblN0eWxlUHJvcCA9IFsndHJhbnNpdGlvbicsICdwb2ludGVyRXZlbnRzJywgJ3Bvc2l0aW9uJywgJ2xlZnQnLCAndG9wJywgJ21pbldpZHRoJywgJ3dpbGxDaGFuZ2UnXTtcbmV4cG9ydCB7IERERHJhZ2dhYmxlIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kZC1kcmFnZ2FibGUuanMubWFwIiwiLyoqXG4gKiBkZC1kcm9wcGFibGUudHMgMTAuMS4yXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjEtMjAyMiBBbGFpbiBEdW1lc255IC0gc2VlIEdyaWRTdGFjayByb290IGxpY2Vuc2VcbiAqL1xuaW1wb3J0IHsgRERNYW5hZ2VyIH0gZnJvbSAnLi9kZC1tYW5hZ2VyJztcbmltcG9ydCB7IEREQmFzZUltcGxlbWVudCB9IGZyb20gJy4vZGQtYmFzZS1pbXBsJztcbmltcG9ydCB7IFV0aWxzIH0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgeyBpc1RvdWNoLCBwb2ludGVyZW50ZXIsIHBvaW50ZXJsZWF2ZSB9IGZyb20gJy4vZGQtdG91Y2gnO1xuLy8gbGV0IGNvdW50ID0gMDsgLy8gVEVTVFxuZXhwb3J0IGNsYXNzIERERHJvcHBhYmxlIGV4dGVuZHMgRERCYXNlSW1wbGVtZW50IHtcbiAgICBjb25zdHJ1Y3RvcihlbCwgb3B0aW9uID0ge30pIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5lbCA9IGVsO1xuICAgICAgICB0aGlzLm9wdGlvbiA9IG9wdGlvbjtcbiAgICAgICAgLy8gY3JlYXRlIHZhciBldmVudCBiaW5kaW5nIHNvIHdlIGNhbiBlYXNpbHkgcmVtb3ZlIGFuZCBzdGlsbCBsb29rIGxpa2UgVFMgbWV0aG9kcyAodW5saWtlIGFub255bW91cyBmdW5jdGlvbnMpXG4gICAgICAgIHRoaXMuX21vdXNlRW50ZXIgPSB0aGlzLl9tb3VzZUVudGVyLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuX21vdXNlTGVhdmUgPSB0aGlzLl9tb3VzZUxlYXZlLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuZW5hYmxlKCk7XG4gICAgICAgIHRoaXMuX3NldHVwQWNjZXB0KCk7XG4gICAgfVxuICAgIG9uKGV2ZW50LCBjYWxsYmFjaykge1xuICAgICAgICBzdXBlci5vbihldmVudCwgY2FsbGJhY2spO1xuICAgIH1cbiAgICBvZmYoZXZlbnQpIHtcbiAgICAgICAgc3VwZXIub2ZmKGV2ZW50KTtcbiAgICB9XG4gICAgZW5hYmxlKCkge1xuICAgICAgICBpZiAodGhpcy5kaXNhYmxlZCA9PT0gZmFsc2UpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHN1cGVyLmVuYWJsZSgpO1xuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5hZGQoJ3VpLWRyb3BwYWJsZScpO1xuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5yZW1vdmUoJ3VpLWRyb3BwYWJsZS1kaXNhYmxlZCcpO1xuICAgICAgICB0aGlzLmVsLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZW50ZXInLCB0aGlzLl9tb3VzZUVudGVyKTtcbiAgICAgICAgdGhpcy5lbC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgdGhpcy5fbW91c2VMZWF2ZSk7XG4gICAgICAgIGlmIChpc1RvdWNoKSB7XG4gICAgICAgICAgICB0aGlzLmVsLmFkZEV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJlbnRlcicsIHBvaW50ZXJlbnRlcik7XG4gICAgICAgICAgICB0aGlzLmVsLmFkZEV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJsZWF2ZScsIHBvaW50ZXJsZWF2ZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZGlzYWJsZShmb3JEZXN0cm95ID0gZmFsc2UpIHtcbiAgICAgICAgaWYgKHRoaXMuZGlzYWJsZWQgPT09IHRydWUpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHN1cGVyLmRpc2FibGUoKTtcbiAgICAgICAgdGhpcy5lbC5jbGFzc0xpc3QucmVtb3ZlKCd1aS1kcm9wcGFibGUnKTtcbiAgICAgICAgaWYgKCFmb3JEZXN0cm95KVxuICAgICAgICAgICAgdGhpcy5lbC5jbGFzc0xpc3QuYWRkKCd1aS1kcm9wcGFibGUtZGlzYWJsZWQnKTtcbiAgICAgICAgdGhpcy5lbC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWVudGVyJywgdGhpcy5fbW91c2VFbnRlcik7XG4gICAgICAgIHRoaXMuZWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2VsZWF2ZScsIHRoaXMuX21vdXNlTGVhdmUpO1xuICAgICAgICBpZiAoaXNUb3VjaCkge1xuICAgICAgICAgICAgdGhpcy5lbC5yZW1vdmVFdmVudExpc3RlbmVyKCdwb2ludGVyZW50ZXInLCBwb2ludGVyZW50ZXIpO1xuICAgICAgICAgICAgdGhpcy5lbC5yZW1vdmVFdmVudExpc3RlbmVyKCdwb2ludGVybGVhdmUnLCBwb2ludGVybGVhdmUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuZGlzYWJsZSh0cnVlKTtcbiAgICAgICAgdGhpcy5lbC5jbGFzc0xpc3QucmVtb3ZlKCd1aS1kcm9wcGFibGUnKTtcbiAgICAgICAgdGhpcy5lbC5jbGFzc0xpc3QucmVtb3ZlKCd1aS1kcm9wcGFibGUtZGlzYWJsZWQnKTtcbiAgICAgICAgc3VwZXIuZGVzdHJveSgpO1xuICAgIH1cbiAgICB1cGRhdGVPcHRpb24ob3B0cykge1xuICAgICAgICBPYmplY3Qua2V5cyhvcHRzKS5mb3JFYWNoKGtleSA9PiB0aGlzLm9wdGlvbltrZXldID0gb3B0c1trZXldKTtcbiAgICAgICAgdGhpcy5fc2V0dXBBY2NlcHQoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgY2FsbGVkIHdoZW4gdGhlIGN1cnNvciBlbnRlcnMgb3VyIGFyZWEgLSBwcmVwYXJlIGZvciBhIHBvc3NpYmxlIGRyb3AgYW5kIHRyYWNrIGxlYXZpbmcgKi9cbiAgICBfbW91c2VFbnRlcihlKSB7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGAke2NvdW50Kyt9IEVudGVyICR7dGhpcy5lbC5pZCB8fCAodGhpcy5lbCBhcyBHcmlkSFRNTEVsZW1lbnQpLmdyaWRzdGFjay5vcHRzLmlkfWApOyAvLyBURVNUXG4gICAgICAgIGlmICghRERNYW5hZ2VyLmRyYWdFbGVtZW50KVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBpZiAoIXRoaXMuX2NhbkRyb3AoRERNYW5hZ2VyLmRyYWdFbGVtZW50LmVsKSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAvLyBtYWtlIHN1cmUgd2hlbiB3ZSBlbnRlciB0aGlzLCB0aGF0IHRoZSBsYXN0IG9uZSBnZXRzIGEgbGVhdmUgRklSU1QgdG8gY29ycmVjdGx5IGNsZWFudXAgYXMgd2UgZG9uJ3QgYWx3YXlzIGRvXG4gICAgICAgIGlmIChERE1hbmFnZXIuZHJvcEVsZW1lbnQgJiYgRERNYW5hZ2VyLmRyb3BFbGVtZW50ICE9PSB0aGlzKSB7XG4gICAgICAgICAgICBERE1hbmFnZXIuZHJvcEVsZW1lbnQuX21vdXNlTGVhdmUoZSwgdHJ1ZSk7IC8vIGNhbGxlZEJ5RW50ZXIgPSB0cnVlXG4gICAgICAgIH1cbiAgICAgICAgRERNYW5hZ2VyLmRyb3BFbGVtZW50ID0gdGhpcztcbiAgICAgICAgY29uc3QgZXYgPSBVdGlscy5pbml0RXZlbnQoZSwgeyB0YXJnZXQ6IHRoaXMuZWwsIHR5cGU6ICdkcm9wb3ZlcicgfSk7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbi5vdmVyKSB7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbi5vdmVyKGV2LCB0aGlzLl91aShERE1hbmFnZXIuZHJhZ0VsZW1lbnQpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRyaWdnZXJFdmVudCgnZHJvcG92ZXInLCBldik7XG4gICAgICAgIHRoaXMuZWwuY2xhc3NMaXN0LmFkZCgndWktZHJvcHBhYmxlLW92ZXInKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2coJ3RyYWNraW5nJyk7IC8vIFRFU1RcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCBjYWxsZWQgd2hlbiB0aGUgaXRlbSBpcyBsZWF2aW5nIG91ciBhcmVhLCBzdG9wIHRyYWNraW5nIGlmIHdlIGhhZCBtb3ZpbmcgaXRlbSAqL1xuICAgIF9tb3VzZUxlYXZlKGUsIGNhbGxlZEJ5RW50ZXIgPSBmYWxzZSkge1xuICAgICAgICAvLyBjb25zb2xlLmxvZyhgJHtjb3VudCsrfSBMZWF2ZSAke3RoaXMuZWwuaWQgfHwgKHRoaXMuZWwgYXMgR3JpZEhUTUxFbGVtZW50KS5ncmlkc3RhY2sub3B0cy5pZH1gKTsgLy8gVEVTVFxuICAgICAgICBpZiAoIURETWFuYWdlci5kcmFnRWxlbWVudCB8fCBERE1hbmFnZXIuZHJvcEVsZW1lbnQgIT09IHRoaXMpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgY29uc3QgZXYgPSBVdGlscy5pbml0RXZlbnQoZSwgeyB0YXJnZXQ6IHRoaXMuZWwsIHR5cGU6ICdkcm9wb3V0JyB9KTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9uLm91dCkge1xuICAgICAgICAgICAgdGhpcy5vcHRpb24ub3V0KGV2LCB0aGlzLl91aShERE1hbmFnZXIuZHJhZ0VsZW1lbnQpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRyaWdnZXJFdmVudCgnZHJvcG91dCcsIGV2KTtcbiAgICAgICAgaWYgKERETWFuYWdlci5kcm9wRWxlbWVudCA9PT0gdGhpcykge1xuICAgICAgICAgICAgZGVsZXRlIERETWFuYWdlci5kcm9wRWxlbWVudDtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdub3QgdHJhY2tpbmcnKTsgLy8gVEVTVFxuICAgICAgICAgICAgLy8gaWYgd2UncmUgc3RpbGwgb3ZlciBhIHBhcmVudCBkcm9wcGFibGUsIHNlbmQgaXQgYW4gZW50ZXIgYXMgd2UgZG9uJ3QgZ2V0IG9uZSBmcm9tIGxlYXZpbmcgbmVzdGVkIGNoaWxkcmVuXG4gICAgICAgICAgICBpZiAoIWNhbGxlZEJ5RW50ZXIpIHtcbiAgICAgICAgICAgICAgICBsZXQgcGFyZW50RHJvcDtcbiAgICAgICAgICAgICAgICBsZXQgcGFyZW50ID0gdGhpcy5lbC5wYXJlbnRFbGVtZW50O1xuICAgICAgICAgICAgICAgIHdoaWxlICghcGFyZW50RHJvcCAmJiBwYXJlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50RHJvcCA9IHBhcmVudC5kZEVsZW1lbnQ/LmRkRHJvcHBhYmxlO1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnQucGFyZW50RWxlbWVudDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudERyb3ApIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50RHJvcC5fbW91c2VFbnRlcihlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqIGl0ZW0gaXMgYmVpbmcgZHJvcHBlZCBvbiB1cyAtIGNhbGxlZCBieSB0aGUgZHJhZyBtb3VzZXVwIGhhbmRsZXIgLSB0aGlzIGNhbGxzIHRoZSBjbGllbnQgZHJvcCBldmVudCAqL1xuICAgIGRyb3AoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGNvbnN0IGV2ID0gVXRpbHMuaW5pdEV2ZW50KGUsIHsgdGFyZ2V0OiB0aGlzLmVsLCB0eXBlOiAnZHJvcCcgfSk7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbi5kcm9wKSB7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbi5kcm9wKGV2LCB0aGlzLl91aShERE1hbmFnZXIuZHJhZ0VsZW1lbnQpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRyaWdnZXJFdmVudCgnZHJvcCcsIGV2KTtcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCB0cnVlIGlmIGVsZW1lbnQgbWF0Y2hlcyB0aGUgc3RyaW5nL21ldGhvZCBhY2NlcHQgb3B0aW9uICovXG4gICAgX2NhbkRyb3AoZWwpIHtcbiAgICAgICAgcmV0dXJuIGVsICYmICghdGhpcy5hY2NlcHQgfHwgdGhpcy5hY2NlcHQoZWwpKTtcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF9zZXR1cEFjY2VwdCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLm9wdGlvbi5hY2NlcHQpXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm9wdGlvbi5hY2NlcHQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmFjY2VwdCA9IChlbCkgPT4gZWwuY2xhc3NMaXN0LmNvbnRhaW5zKHRoaXMub3B0aW9uLmFjY2VwdCkgfHwgZWwubWF0Y2hlcyh0aGlzLm9wdGlvbi5hY2NlcHQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hY2NlcHQgPSB0aGlzLm9wdGlvbi5hY2NlcHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBfdWkoZHJhZykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZHJhZ2dhYmxlOiBkcmFnLmVsLFxuICAgICAgICAgICAgLi4uZHJhZy51aSgpXG4gICAgICAgIH07XG4gICAgfVxufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGQtZHJvcHBhYmxlLmpzLm1hcCIsIi8qKlxuICogZGQtZWxlbWVudHMudHMgMTAuMS4yXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjEgQWxhaW4gRHVtZXNueSAtIHNlZSBHcmlkU3RhY2sgcm9vdCBsaWNlbnNlXG4gKi9cbmltcG9ydCB7IEREUmVzaXphYmxlIH0gZnJvbSAnLi9kZC1yZXNpemFibGUnO1xuaW1wb3J0IHsgREREcmFnZ2FibGUgfSBmcm9tICcuL2RkLWRyYWdnYWJsZSc7XG5pbXBvcnQgeyBERERyb3BwYWJsZSB9IGZyb20gJy4vZGQtZHJvcHBhYmxlJztcbmV4cG9ydCBjbGFzcyBEREVsZW1lbnQge1xuICAgIHN0YXRpYyBpbml0KGVsKSB7XG4gICAgICAgIGlmICghZWwuZGRFbGVtZW50KSB7XG4gICAgICAgICAgICBlbC5kZEVsZW1lbnQgPSBuZXcgRERFbGVtZW50KGVsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWwuZGRFbGVtZW50O1xuICAgIH1cbiAgICBjb25zdHJ1Y3RvcihlbCkge1xuICAgICAgICB0aGlzLmVsID0gZWw7XG4gICAgfVxuICAgIG9uKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKHRoaXMuZGREcmFnZ2FibGUgJiYgWydkcmFnJywgJ2RyYWdzdGFydCcsICdkcmFnc3RvcCddLmluZGV4T2YoZXZlbnROYW1lKSA+IC0xKSB7XG4gICAgICAgICAgICB0aGlzLmRkRHJhZ2dhYmxlLm9uKGV2ZW50TmFtZSwgY2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMuZGREcm9wcGFibGUgJiYgWydkcm9wJywgJ2Ryb3BvdmVyJywgJ2Ryb3BvdXQnXS5pbmRleE9mKGV2ZW50TmFtZSkgPiAtMSkge1xuICAgICAgICAgICAgdGhpcy5kZERyb3BwYWJsZS5vbihldmVudE5hbWUsIGNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLmRkUmVzaXphYmxlICYmIFsncmVzaXplc3RhcnQnLCAncmVzaXplJywgJ3Jlc2l6ZXN0b3AnXS5pbmRleE9mKGV2ZW50TmFtZSkgPiAtMSkge1xuICAgICAgICAgICAgdGhpcy5kZFJlc2l6YWJsZS5vbihldmVudE5hbWUsIGNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgb2ZmKGV2ZW50TmFtZSkge1xuICAgICAgICBpZiAodGhpcy5kZERyYWdnYWJsZSAmJiBbJ2RyYWcnLCAnZHJhZ3N0YXJ0JywgJ2RyYWdzdG9wJ10uaW5kZXhPZihldmVudE5hbWUpID4gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuZGREcmFnZ2FibGUub2ZmKGV2ZW50TmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5kZERyb3BwYWJsZSAmJiBbJ2Ryb3AnLCAnZHJvcG92ZXInLCAnZHJvcG91dCddLmluZGV4T2YoZXZlbnROYW1lKSA+IC0xKSB7XG4gICAgICAgICAgICB0aGlzLmRkRHJvcHBhYmxlLm9mZihldmVudE5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMuZGRSZXNpemFibGUgJiYgWydyZXNpemVzdGFydCcsICdyZXNpemUnLCAncmVzaXplc3RvcCddLmluZGV4T2YoZXZlbnROYW1lKSA+IC0xKSB7XG4gICAgICAgICAgICB0aGlzLmRkUmVzaXphYmxlLm9mZihldmVudE5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBzZXR1cERyYWdnYWJsZShvcHRzKSB7XG4gICAgICAgIGlmICghdGhpcy5kZERyYWdnYWJsZSkge1xuICAgICAgICAgICAgdGhpcy5kZERyYWdnYWJsZSA9IG5ldyBERERyYWdnYWJsZSh0aGlzLmVsLCBvcHRzKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZGREcmFnZ2FibGUudXBkYXRlT3B0aW9uKG9wdHMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBjbGVhbkRyYWdnYWJsZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuZGREcmFnZ2FibGUpIHtcbiAgICAgICAgICAgIHRoaXMuZGREcmFnZ2FibGUuZGVzdHJveSgpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuZGREcmFnZ2FibGU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldHVwUmVzaXphYmxlKG9wdHMpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRkUmVzaXphYmxlKSB7XG4gICAgICAgICAgICB0aGlzLmRkUmVzaXphYmxlID0gbmV3IEREUmVzaXphYmxlKHRoaXMuZWwsIG9wdHMpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5kZFJlc2l6YWJsZS51cGRhdGVPcHRpb24ob3B0cyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGNsZWFuUmVzaXphYmxlKCkge1xuICAgICAgICBpZiAodGhpcy5kZFJlc2l6YWJsZSkge1xuICAgICAgICAgICAgdGhpcy5kZFJlc2l6YWJsZS5kZXN0cm95KCk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5kZFJlc2l6YWJsZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0dXBEcm9wcGFibGUob3B0cykge1xuICAgICAgICBpZiAoIXRoaXMuZGREcm9wcGFibGUpIHtcbiAgICAgICAgICAgIHRoaXMuZGREcm9wcGFibGUgPSBuZXcgREREcm9wcGFibGUodGhpcy5lbCwgb3B0cyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmRkRHJvcHBhYmxlLnVwZGF0ZU9wdGlvbihvcHRzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgY2xlYW5Ecm9wcGFibGUoKSB7XG4gICAgICAgIGlmICh0aGlzLmRkRHJvcHBhYmxlKSB7XG4gICAgICAgICAgICB0aGlzLmRkRHJvcHBhYmxlLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmRkRHJvcHBhYmxlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRkLWVsZW1lbnQuanMubWFwIiwiLyoqXG4gKiBkZC1ncmlkc3RhY2sudHMgMTAuMS4yXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjEgQWxhaW4gRHVtZXNueSAtIHNlZSBHcmlkU3RhY2sgcm9vdCBsaWNlbnNlXG4gKi9cbmltcG9ydCB7IFV0aWxzIH0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgeyBERE1hbmFnZXIgfSBmcm9tICcuL2RkLW1hbmFnZXInO1xuaW1wb3J0IHsgRERFbGVtZW50IH0gZnJvbSAnLi9kZC1lbGVtZW50Jztcbi8vIGxldCBjb3VudCA9IDA7IC8vIFRFU1Rcbi8qKlxuICogSFRNTCBOYXRpdmUgTW91c2UgYW5kIFRvdWNoIEV2ZW50cyBEcmFnIGFuZCBEcm9wIGZ1bmN0aW9uYWxpdHkuXG4gKi9cbmV4cG9ydCBjbGFzcyBEREdyaWRTdGFjayB7XG4gICAgcmVzaXphYmxlKGVsLCBvcHRzLCBrZXksIHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX2dldERERWxlbWVudHMoZWwpLmZvckVhY2goZEVsID0+IHtcbiAgICAgICAgICAgIGlmIChvcHRzID09PSAnZGlzYWJsZScgfHwgb3B0cyA9PT0gJ2VuYWJsZScpIHtcbiAgICAgICAgICAgICAgICBkRWwuZGRSZXNpemFibGUgJiYgZEVsLmRkUmVzaXphYmxlW29wdHNdKCk7IC8vIGNhbid0IGNyZWF0ZSBERCBhcyBpdCByZXF1aXJlcyBvcHRpb25zIGZvciBzZXR1cFJlc2l6YWJsZSgpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChvcHRzID09PSAnZGVzdHJveScpIHtcbiAgICAgICAgICAgICAgICBkRWwuZGRSZXNpemFibGUgJiYgZEVsLmNsZWFuUmVzaXphYmxlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChvcHRzID09PSAnb3B0aW9uJykge1xuICAgICAgICAgICAgICAgIGRFbC5zZXR1cFJlc2l6YWJsZSh7IFtrZXldOiB2YWx1ZSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IG4gPSBkRWwuZWwuZ3JpZHN0YWNrTm9kZTtcbiAgICAgICAgICAgICAgICBjb25zdCBncmlkID0gbi5ncmlkO1xuICAgICAgICAgICAgICAgIGxldCBoYW5kbGVzID0gZEVsLmVsLmdldEF0dHJpYnV0ZSgnZ3MtcmVzaXplLWhhbmRsZXMnKSB8fCBncmlkLm9wdHMucmVzaXphYmxlLmhhbmRsZXMgfHwgJ2UscyxzZSc7XG4gICAgICAgICAgICAgICAgaWYgKGhhbmRsZXMgPT09ICdhbGwnKVxuICAgICAgICAgICAgICAgICAgICBoYW5kbGVzID0gJ24sZSxzLHcsc2Usc3csbmUsbncnO1xuICAgICAgICAgICAgICAgIC8vIE5PVEU6IGtlZXAgdGhlIHJlc2l6ZSBoYW5kbGVzIGFzIGUsdyBkb24ndCBoYXZlIGVub3VnaCBzcGFjZSAoMTBweCkgdG8gc2hvdyByZXNpemUgY29ybmVycyBhbnl3YXkuIGxpbWl0IGR1cmluZyBkcmFnIGluc3RlYWRcbiAgICAgICAgICAgICAgICAvLyByZXN0cmljdCB2ZXJ0aWNhbCByZXNpemUgaWYgaGVpZ2h0IGlzIGRvbmUgdG8gbWF0Y2ggY29udGVudCBhbnl3YXkuLi4gb2RkIHRvIGhhdmUgaXQgc3ByaW5nIGJhY2tcbiAgICAgICAgICAgICAgICAvLyBpZiAoVXRpbHMuc2hvdWxkU2l6ZVRvQ29udGVudChuLCB0cnVlKSkge1xuICAgICAgICAgICAgICAgIC8vICAgY29uc3QgZG9FID0gaGFuZGxlcy5pbmRleE9mKCdlJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIC8vICAgY29uc3QgZG9XID0gaGFuZGxlcy5pbmRleE9mKCd3JykgIT09IC0xO1xuICAgICAgICAgICAgICAgIC8vICAgaGFuZGxlcyA9IGRvRSA/IChkb1cgPyAnZSx3JyA6ICdlJykgOiAoZG9XID8gJ3cnIDogJycpO1xuICAgICAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgICAgICBjb25zdCBhdXRvSGlkZSA9ICFncmlkLm9wdHMuYWx3YXlzU2hvd1Jlc2l6ZUhhbmRsZTtcbiAgICAgICAgICAgICAgICBkRWwuc2V0dXBSZXNpemFibGUoe1xuICAgICAgICAgICAgICAgICAgICAuLi5ncmlkLm9wdHMucmVzaXphYmxlLFxuICAgICAgICAgICAgICAgICAgICAuLi57IGhhbmRsZXMsIGF1dG9IaWRlIH0sXG4gICAgICAgICAgICAgICAgICAgIC4uLntcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0OiBvcHRzLnN0YXJ0LFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RvcDogb3B0cy5zdG9wLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzaXplOiBvcHRzLnJlc2l6ZVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgZHJhZ2dhYmxlKGVsLCBvcHRzLCBrZXksIHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX2dldERERWxlbWVudHMoZWwpLmZvckVhY2goZEVsID0+IHtcbiAgICAgICAgICAgIGlmIChvcHRzID09PSAnZGlzYWJsZScgfHwgb3B0cyA9PT0gJ2VuYWJsZScpIHtcbiAgICAgICAgICAgICAgICBkRWwuZGREcmFnZ2FibGUgJiYgZEVsLmRkRHJhZ2dhYmxlW29wdHNdKCk7IC8vIGNhbid0IGNyZWF0ZSBERCBhcyBpdCByZXF1aXJlcyBvcHRpb25zIGZvciBzZXR1cERyYWdnYWJsZSgpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChvcHRzID09PSAnZGVzdHJveScpIHtcbiAgICAgICAgICAgICAgICBkRWwuZGREcmFnZ2FibGUgJiYgZEVsLmNsZWFuRHJhZ2dhYmxlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChvcHRzID09PSAnb3B0aW9uJykge1xuICAgICAgICAgICAgICAgIGRFbC5zZXR1cERyYWdnYWJsZSh7IFtrZXldOiB2YWx1ZSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGdyaWQgPSBkRWwuZWwuZ3JpZHN0YWNrTm9kZS5ncmlkO1xuICAgICAgICAgICAgICAgIGRFbC5zZXR1cERyYWdnYWJsZSh7XG4gICAgICAgICAgICAgICAgICAgIC4uLmdyaWQub3B0cy5kcmFnZ2FibGUsXG4gICAgICAgICAgICAgICAgICAgIC4uLntcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbnRhaW5tZW50OiAoZ3JpZC5wYXJlbnRHcmlkSXRlbSAmJiAhZ3JpZC5vcHRzLmRyYWdPdXQpID8gZ3JpZC5lbC5wYXJlbnRFbGVtZW50IDogKGdyaWQub3B0cy5kcmFnZ2FibGUuY29udGFpbm1lbnQgfHwgbnVsbCksXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydDogb3B0cy5zdGFydCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0b3A6IG9wdHMuc3RvcCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRyYWc6IG9wdHMuZHJhZ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgZHJhZ0luKGVsLCBvcHRzKSB7XG4gICAgICAgIHRoaXMuX2dldERERWxlbWVudHMoZWwpLmZvckVhY2goZEVsID0+IGRFbC5zZXR1cERyYWdnYWJsZShvcHRzKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBkcm9wcGFibGUoZWwsIG9wdHMsIGtleSwgdmFsdWUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRzLmFjY2VwdCA9PT0gJ2Z1bmN0aW9uJyAmJiAhb3B0cy5fYWNjZXB0KSB7XG4gICAgICAgICAgICBvcHRzLl9hY2NlcHQgPSBvcHRzLmFjY2VwdDtcbiAgICAgICAgICAgIG9wdHMuYWNjZXB0ID0gKGVsKSA9PiBvcHRzLl9hY2NlcHQoZWwpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2dldERERWxlbWVudHMoZWwpLmZvckVhY2goZEVsID0+IHtcbiAgICAgICAgICAgIGlmIChvcHRzID09PSAnZGlzYWJsZScgfHwgb3B0cyA9PT0gJ2VuYWJsZScpIHtcbiAgICAgICAgICAgICAgICBkRWwuZGREcm9wcGFibGUgJiYgZEVsLmRkRHJvcHBhYmxlW29wdHNdKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChvcHRzID09PSAnZGVzdHJveScpIHtcbiAgICAgICAgICAgICAgICBpZiAoZEVsLmRkRHJvcHBhYmxlKSB7IC8vIGVycm9yIHRvIGNhbGwgZGVzdHJveSBpZiBub3QgdGhlcmVcbiAgICAgICAgICAgICAgICAgICAgZEVsLmNsZWFuRHJvcHBhYmxlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAob3B0cyA9PT0gJ29wdGlvbicpIHtcbiAgICAgICAgICAgICAgICBkRWwuc2V0dXBEcm9wcGFibGUoeyBba2V5XTogdmFsdWUgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkRWwuc2V0dXBEcm9wcGFibGUob3B0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIHRydWUgaWYgZWxlbWVudCBpcyBkcm9wcGFibGUgKi9cbiAgICBpc0Ryb3BwYWJsZShlbCkge1xuICAgICAgICByZXR1cm4gISEoZWwgJiYgZWwuZGRFbGVtZW50ICYmIGVsLmRkRWxlbWVudC5kZERyb3BwYWJsZSAmJiAhZWwuZGRFbGVtZW50LmRkRHJvcHBhYmxlLmRpc2FibGVkKTtcbiAgICB9XG4gICAgLyoqIHRydWUgaWYgZWxlbWVudCBpcyBkcmFnZ2FibGUgKi9cbiAgICBpc0RyYWdnYWJsZShlbCkge1xuICAgICAgICByZXR1cm4gISEoZWwgJiYgZWwuZGRFbGVtZW50ICYmIGVsLmRkRWxlbWVudC5kZERyYWdnYWJsZSAmJiAhZWwuZGRFbGVtZW50LmRkRHJhZ2dhYmxlLmRpc2FibGVkKTtcbiAgICB9XG4gICAgLyoqIHRydWUgaWYgZWxlbWVudCBpcyBkcmFnZ2FibGUgKi9cbiAgICBpc1Jlc2l6YWJsZShlbCkge1xuICAgICAgICByZXR1cm4gISEoZWwgJiYgZWwuZGRFbGVtZW50ICYmIGVsLmRkRWxlbWVudC5kZFJlc2l6YWJsZSAmJiAhZWwuZGRFbGVtZW50LmRkUmVzaXphYmxlLmRpc2FibGVkKTtcbiAgICB9XG4gICAgb24oZWwsIG5hbWUsIGNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuX2dldERERWxlbWVudHMoZWwpLmZvckVhY2goZEVsID0+IGRFbC5vbihuYW1lLCAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LCBERE1hbmFnZXIuZHJhZ0VsZW1lbnQgPyBERE1hbmFnZXIuZHJhZ0VsZW1lbnQuZWwgOiBldmVudC50YXJnZXQsIERETWFuYWdlci5kcmFnRWxlbWVudCA/IERETWFuYWdlci5kcmFnRWxlbWVudC5oZWxwZXIgOiBudWxsKTtcbiAgICAgICAgfSkpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgb2ZmKGVsLCBuYW1lKSB7XG4gICAgICAgIHRoaXMuX2dldERERWxlbWVudHMoZWwpLmZvckVhY2goZEVsID0+IGRFbC5vZmYobmFtZSkpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCByZXR1cm5zIGEgbGlzdCBvZiBERCBlbGVtZW50cywgY3JlYXRpbmcgdGhlbSBvbiB0aGUgZmx5IGJ5IGRlZmF1bHQgKi9cbiAgICBfZ2V0RERFbGVtZW50cyhlbHMsIGNyZWF0ZSA9IHRydWUpIHtcbiAgICAgICAgbGV0IGhvc3RzID0gVXRpbHMuZ2V0RWxlbWVudHMoZWxzKTtcbiAgICAgICAgaWYgKCFob3N0cy5sZW5ndGgpXG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIGxldCBsaXN0ID0gaG9zdHMubWFwKGUgPT4gZS5kZEVsZW1lbnQgfHwgKGNyZWF0ZSA/IERERWxlbWVudC5pbml0KGUpIDogbnVsbCkpO1xuICAgICAgICBpZiAoIWNyZWF0ZSkge1xuICAgICAgICAgICAgbGlzdC5maWx0ZXIoZCA9PiBkKTtcbiAgICAgICAgfSAvLyByZW1vdmUgbnVsbHNcbiAgICAgICAgcmV0dXJuIGxpc3Q7XG4gICAgfVxufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGQtZ3JpZHN0YWNrLmpzLm1hcCIsIi8qKlxuICogZGQtbWFuYWdlci50cyAxMC4xLjJcbiAqIENvcHlyaWdodCAoYykgMjAyMSBBbGFpbiBEdW1lc255IC0gc2VlIEdyaWRTdGFjayByb290IGxpY2Vuc2VcbiAqL1xuLyoqXG4gKiBnbG9iYWxzIHRoYXQgYXJlIHNoYXJlZCBhY3Jvc3MgRHJhZyAmIERyb3AgaW5zdGFuY2VzXG4gKi9cbmV4cG9ydCBjbGFzcyBERE1hbmFnZXIge1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGQtbWFuYWdlci5qcy5tYXAiLCIvKipcbiAqIGRkLXJlc2l6YWJsZS1oYW5kbGUudHMgMTAuMS4yXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjEtMjAyMiBBbGFpbiBEdW1lc255IC0gc2VlIEdyaWRTdGFjayByb290IGxpY2Vuc2VcbiAqL1xuaW1wb3J0IHsgaXNUb3VjaCwgcG9pbnRlcmRvd24sIHRvdWNoZW5kLCB0b3VjaG1vdmUsIHRvdWNoc3RhcnQgfSBmcm9tICcuL2RkLXRvdWNoJztcbmNsYXNzIEREUmVzaXphYmxlSGFuZGxlIHtcbiAgICBjb25zdHJ1Y3Rvcihob3N0LCBkaXIsIG9wdGlvbikge1xuICAgICAgICB0aGlzLmhvc3QgPSBob3N0O1xuICAgICAgICB0aGlzLmRpciA9IGRpcjtcbiAgICAgICAgdGhpcy5vcHRpb24gPSBvcHRpb247XG4gICAgICAgIC8qKiBAaW50ZXJuYWwgdHJ1ZSBhZnRlciB3ZSd2ZSBtb3ZlZCBlbm91Z2ggcGl4ZWxzIHRvIHN0YXJ0IGEgcmVzaXplICovXG4gICAgICAgIHRoaXMubW92aW5nID0gZmFsc2U7XG4gICAgICAgIC8vIGNyZWF0ZSB2YXIgZXZlbnQgYmluZGluZyBzbyB3ZSBjYW4gZWFzaWx5IHJlbW92ZSBhbmQgc3RpbGwgbG9vayBsaWtlIFRTIG1ldGhvZHMgKHVubGlrZSBhbm9ueW1vdXMgZnVuY3Rpb25zKVxuICAgICAgICB0aGlzLl9tb3VzZURvd24gPSB0aGlzLl9tb3VzZURvd24uYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5fbW91c2VNb3ZlID0gdGhpcy5fbW91c2VNb3ZlLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuX21vdXNlVXAgPSB0aGlzLl9tb3VzZVVwLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuX2luaXQoKTtcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF9pbml0KCkge1xuICAgICAgICBjb25zdCBlbCA9IHRoaXMuZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgZWwuY2xhc3NMaXN0LmFkZCgndWktcmVzaXphYmxlLWhhbmRsZScpO1xuICAgICAgICBlbC5jbGFzc0xpc3QuYWRkKGAke0REUmVzaXphYmxlSGFuZGxlLnByZWZpeH0ke3RoaXMuZGlyfWApO1xuICAgICAgICBlbC5zdHlsZS56SW5kZXggPSAnMTAwJztcbiAgICAgICAgZWwuc3R5bGUudXNlclNlbGVjdCA9ICdub25lJztcbiAgICAgICAgdGhpcy5ob3N0LmFwcGVuZENoaWxkKHRoaXMuZWwpO1xuICAgICAgICB0aGlzLmVsLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX21vdXNlRG93bik7XG4gICAgICAgIGlmIChpc1RvdWNoKSB7XG4gICAgICAgICAgICB0aGlzLmVsLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCB0b3VjaHN0YXJ0KTtcbiAgICAgICAgICAgIHRoaXMuZWwuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcmRvd24nLCBwb2ludGVyZG93bik7XG4gICAgICAgICAgICAvLyB0aGlzLmVsLnN0eWxlLnRvdWNoQWN0aW9uID0gJ25vbmUnOyAvLyBub3QgbmVlZGVkIHVubGlrZSBwb2ludGVyZG93biBkb2MgY29tbWVudFxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogY2FsbCB0aGlzIHdoZW4gcmVzaXplIGhhbmRsZSBuZWVkcyB0byBiZSByZW1vdmVkIGFuZCBjbGVhbmVkIHVwICovXG4gICAgZGVzdHJveSgpIHtcbiAgICAgICAgaWYgKHRoaXMubW92aW5nKVxuICAgICAgICAgICAgdGhpcy5fbW91c2VVcCh0aGlzLm1vdXNlRG93bkV2ZW50KTtcbiAgICAgICAgdGhpcy5lbC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLl9tb3VzZURvd24pO1xuICAgICAgICBpZiAoaXNUb3VjaCkge1xuICAgICAgICAgICAgdGhpcy5lbC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdG91Y2hzdGFydCk7XG4gICAgICAgICAgICB0aGlzLmVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJkb3duJywgcG9pbnRlcmRvd24pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaG9zdC5yZW1vdmVDaGlsZCh0aGlzLmVsKTtcbiAgICAgICAgZGVsZXRlIHRoaXMuZWw7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmhvc3Q7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsIGNhbGxlZCBvbiBtb3VzZSBkb3duIG9uIHVzOiBjYXB0dXJlIG1vdmUgb24gdGhlIGVudGlyZSBkb2N1bWVudCAobW91c2UgbWlnaHQgbm90IHN0YXkgb24gdXMpIHVudGlsIHdlIHJlbGVhc2UgdGhlIG1vdXNlICovXG4gICAgX21vdXNlRG93bihlKSB7XG4gICAgICAgIHRoaXMubW91c2VEb3duRXZlbnQgPSBlO1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9tb3VzZU1vdmUsIHsgY2FwdHVyZTogdHJ1ZSwgcGFzc2l2ZTogdHJ1ZSB9KTsgLy8gY2FwdHVyZSwgbm90IGJ1YmJsZVxuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fbW91c2VVcCwgdHJ1ZSk7XG4gICAgICAgIGlmIChpc1RvdWNoKSB7XG4gICAgICAgICAgICB0aGlzLmVsLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRvdWNobW92ZSk7XG4gICAgICAgICAgICB0aGlzLmVsLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdG91Y2hlbmQpO1xuICAgICAgICB9XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF9tb3VzZU1vdmUoZSkge1xuICAgICAgICBsZXQgcyA9IHRoaXMubW91c2VEb3duRXZlbnQ7XG4gICAgICAgIGlmICh0aGlzLm1vdmluZykge1xuICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KCdtb3ZlJywgZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoTWF0aC5hYnMoZS54IC0gcy54KSArIE1hdGguYWJzKGUueSAtIHMueSkgPiAyKSB7XG4gICAgICAgICAgICAvLyBkb24ndCBzdGFydCB1bmxlc3Mgd2UndmUgbW92ZWQgYXQgbGVhc3QgMyBwaXhlbHNcbiAgICAgICAgICAgIHRoaXMubW92aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudCgnc3RhcnQnLCB0aGlzLm1vdXNlRG93bkV2ZW50KTtcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudCgnbW92ZScsIGUpO1xuICAgICAgICB9XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIC8vIGUucHJldmVudERlZmF1bHQoKTsgcGFzc2l2ZSA9IHRydWVcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF9tb3VzZVVwKGUpIHtcbiAgICAgICAgaWYgKHRoaXMubW92aW5nKSB7XG4gICAgICAgICAgICB0aGlzLl90cmlnZ2VyRXZlbnQoJ3N0b3AnLCBlKTtcbiAgICAgICAgfVxuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9tb3VzZU1vdmUsIHRydWUpO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fbW91c2VVcCwgdHJ1ZSk7XG4gICAgICAgIGlmIChpc1RvdWNoKSB7XG4gICAgICAgICAgICB0aGlzLmVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRvdWNobW92ZSk7XG4gICAgICAgICAgICB0aGlzLmVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdG91Y2hlbmQpO1xuICAgICAgICB9XG4gICAgICAgIGRlbGV0ZSB0aGlzLm1vdmluZztcbiAgICAgICAgZGVsZXRlIHRoaXMubW91c2VEb3duRXZlbnQ7XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF90cmlnZ2VyRXZlbnQobmFtZSwgZXZlbnQpIHtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9uW25hbWVdKVxuICAgICAgICAgICAgdGhpcy5vcHRpb25bbmFtZV0oZXZlbnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG59XG4vKiogQGludGVybmFsICovXG5ERFJlc2l6YWJsZUhhbmRsZS5wcmVmaXggPSAndWktcmVzaXphYmxlLSc7XG5leHBvcnQgeyBERFJlc2l6YWJsZUhhbmRsZSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGQtcmVzaXphYmxlLWhhbmRsZS5qcy5tYXAiLCIvKipcbiAqIGRkLXJlc2l6YWJsZS50cyAxMC4xLjJcbiAqIENvcHlyaWdodCAoYykgMjAyMS0yMDIyIEFsYWluIER1bWVzbnkgLSBzZWUgR3JpZFN0YWNrIHJvb3QgbGljZW5zZVxuICovXG5pbXBvcnQgeyBERFJlc2l6YWJsZUhhbmRsZSB9IGZyb20gJy4vZGQtcmVzaXphYmxlLWhhbmRsZSc7XG5pbXBvcnQgeyBEREJhc2VJbXBsZW1lbnQgfSBmcm9tICcuL2RkLWJhc2UtaW1wbCc7XG5pbXBvcnQgeyBVdGlscyB9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHsgRERNYW5hZ2VyIH0gZnJvbSAnLi9kZC1tYW5hZ2VyJztcbmNsYXNzIEREUmVzaXphYmxlIGV4dGVuZHMgRERCYXNlSW1wbGVtZW50IHtcbiAgICAvLyBoYXZlIHRvIGJlIHB1YmxpYyBlbHNlIGNvbXBsYWlucyBmb3IgSFRNTEVsZW1lbnRFeHRlbmRPcHQgP1xuICAgIGNvbnN0cnVjdG9yKGVsLCBvcHRpb24gPSB7fSkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmVsID0gZWw7XG4gICAgICAgIHRoaXMub3B0aW9uID0gb3B0aW9uO1xuICAgICAgICAvKiogQGludGVybmFsICovXG4gICAgICAgIHRoaXMucmVjdFNjYWxlID0geyB4OiAxLCB5OiAxIH07XG4gICAgICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICAgICAgdGhpcy5fdWkgPSAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb250YWlubWVudEVsID0gdGhpcy5lbC5wYXJlbnRFbGVtZW50O1xuICAgICAgICAgICAgY29uc3QgY29udGFpbm1lbnRSZWN0ID0gY29udGFpbm1lbnRFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIGNvbnN0IG5ld1JlY3QgPSB7XG4gICAgICAgICAgICAgICAgd2lkdGg6IHRoaXMub3JpZ2luYWxSZWN0LndpZHRoLFxuICAgICAgICAgICAgICAgIGhlaWdodDogdGhpcy5vcmlnaW5hbFJlY3QuaGVpZ2h0ICsgdGhpcy5zY3JvbGxlZCxcbiAgICAgICAgICAgICAgICBsZWZ0OiB0aGlzLm9yaWdpbmFsUmVjdC5sZWZ0LFxuICAgICAgICAgICAgICAgIHRvcDogdGhpcy5vcmlnaW5hbFJlY3QudG9wIC0gdGhpcy5zY3JvbGxlZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHJlY3QgPSB0aGlzLnRlbXBvcmFsUmVjdCB8fCBuZXdSZWN0O1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0OiAocmVjdC5sZWZ0IC0gY29udGFpbm1lbnRSZWN0LmxlZnQpICogdGhpcy5yZWN0U2NhbGUueCxcbiAgICAgICAgICAgICAgICAgICAgdG9wOiAocmVjdC50b3AgLSBjb250YWlubWVudFJlY3QudG9wKSAqIHRoaXMucmVjdFNjYWxlLnlcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNpemU6IHtcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6IHJlY3Qud2lkdGggKiB0aGlzLnJlY3RTY2FsZS54LFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHJlY3QuaGVpZ2h0ICogdGhpcy5yZWN0U2NhbGUueVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvKiBHcmlkc3RhY2sgT05MWSBuZWVkcyBwb3NpdGlvbiBzZXQgYWJvdmUuLi4ga2VlcCBhcm91bmQgaW4gY2FzZS5cbiAgICAgICAgICAgICAgICBlbGVtZW50OiBbdGhpcy5lbF0sIC8vIFRoZSBvYmplY3QgcmVwcmVzZW50aW5nIHRoZSBlbGVtZW50IHRvIGJlIHJlc2l6ZWRcbiAgICAgICAgICAgICAgICBoZWxwZXI6IFtdLCAvLyBUT0RPOiBub3Qgc3VwcG9ydCB5ZXQgLSBUaGUgb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgaGVscGVyIHRoYXQncyBiZWluZyByZXNpemVkXG4gICAgICAgICAgICAgICAgb3JpZ2luYWxFbGVtZW50OiBbdGhpcy5lbF0sLy8gd2UgZG9uJ3Qgd3JhcCBoZXJlLCBzbyBzaW1wbGlmeSBhcyB0aGlzLmVsIC8vVGhlIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIG9yaWdpbmFsIGVsZW1lbnQgYmVmb3JlIGl0IGlzIHdyYXBwZWRcbiAgICAgICAgICAgICAgICBvcmlnaW5hbFBvc2l0aW9uOiB7IC8vIFRoZSBwb3NpdGlvbiByZXByZXNlbnRlZCBhcyB7IGxlZnQsIHRvcCB9IGJlZm9yZSB0aGUgcmVzaXphYmxlIGlzIHJlc2l6ZWRcbiAgICAgICAgICAgICAgICAgIGxlZnQ6IHRoaXMub3JpZ2luYWxSZWN0LmxlZnQgLSBjb250YWlubWVudFJlY3QubGVmdCxcbiAgICAgICAgICAgICAgICAgIHRvcDogdGhpcy5vcmlnaW5hbFJlY3QudG9wIC0gY29udGFpbm1lbnRSZWN0LnRvcFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb3JpZ2luYWxTaXplOiB7IC8vIFRoZSBzaXplIHJlcHJlc2VudGVkIGFzIHsgd2lkdGgsIGhlaWdodCB9IGJlZm9yZSB0aGUgcmVzaXphYmxlIGlzIHJlc2l6ZWRcbiAgICAgICAgICAgICAgICAgIHdpZHRoOiB0aGlzLm9yaWdpbmFsUmVjdC53aWR0aCxcbiAgICAgICAgICAgICAgICAgIGhlaWdodDogdGhpcy5vcmlnaW5hbFJlY3QuaGVpZ2h0XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgICAvLyBjcmVhdGUgdmFyIGV2ZW50IGJpbmRpbmcgc28gd2UgY2FuIGVhc2lseSByZW1vdmUgYW5kIHN0aWxsIGxvb2sgbGlrZSBUUyBtZXRob2RzICh1bmxpa2UgYW5vbnltb3VzIGZ1bmN0aW9ucylcbiAgICAgICAgdGhpcy5fbW91c2VPdmVyID0gdGhpcy5fbW91c2VPdmVyLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuX21vdXNlT3V0ID0gdGhpcy5fbW91c2VPdXQuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5lbmFibGUoKTtcbiAgICAgICAgdGhpcy5fc2V0dXBBdXRvSGlkZSh0aGlzLm9wdGlvbi5hdXRvSGlkZSk7XG4gICAgICAgIHRoaXMuX3NldHVwSGFuZGxlcnMoKTtcbiAgICB9XG4gICAgb24oZXZlbnQsIGNhbGxiYWNrKSB7XG4gICAgICAgIHN1cGVyLm9uKGV2ZW50LCBjYWxsYmFjayk7XG4gICAgfVxuICAgIG9mZihldmVudCkge1xuICAgICAgICBzdXBlci5vZmYoZXZlbnQpO1xuICAgIH1cbiAgICBlbmFibGUoKSB7XG4gICAgICAgIHN1cGVyLmVuYWJsZSgpO1xuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5yZW1vdmUoJ3VpLXJlc2l6YWJsZS1kaXNhYmxlZCcpO1xuICAgICAgICB0aGlzLl9zZXR1cEF1dG9IaWRlKHRoaXMub3B0aW9uLmF1dG9IaWRlKTtcbiAgICB9XG4gICAgZGlzYWJsZSgpIHtcbiAgICAgICAgc3VwZXIuZGlzYWJsZSgpO1xuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5hZGQoJ3VpLXJlc2l6YWJsZS1kaXNhYmxlZCcpO1xuICAgICAgICB0aGlzLl9zZXR1cEF1dG9IaWRlKGZhbHNlKTtcbiAgICB9XG4gICAgZGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy5fcmVtb3ZlSGFuZGxlcnMoKTtcbiAgICAgICAgdGhpcy5fc2V0dXBBdXRvSGlkZShmYWxzZSk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmVsO1xuICAgICAgICBzdXBlci5kZXN0cm95KCk7XG4gICAgfVxuICAgIHVwZGF0ZU9wdGlvbihvcHRzKSB7XG4gICAgICAgIGxldCB1cGRhdGVIYW5kbGVzID0gKG9wdHMuaGFuZGxlcyAmJiBvcHRzLmhhbmRsZXMgIT09IHRoaXMub3B0aW9uLmhhbmRsZXMpO1xuICAgICAgICBsZXQgdXBkYXRlQXV0b0hpZGUgPSAob3B0cy5hdXRvSGlkZSAmJiBvcHRzLmF1dG9IaWRlICE9PSB0aGlzLm9wdGlvbi5hdXRvSGlkZSk7XG4gICAgICAgIE9iamVjdC5rZXlzKG9wdHMpLmZvckVhY2goa2V5ID0+IHRoaXMub3B0aW9uW2tleV0gPSBvcHRzW2tleV0pO1xuICAgICAgICBpZiAodXBkYXRlSGFuZGxlcykge1xuICAgICAgICAgICAgdGhpcy5fcmVtb3ZlSGFuZGxlcnMoKTtcbiAgICAgICAgICAgIHRoaXMuX3NldHVwSGFuZGxlcnMoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodXBkYXRlQXV0b0hpZGUpIHtcbiAgICAgICAgICAgIHRoaXMuX3NldHVwQXV0b0hpZGUodGhpcy5vcHRpb24uYXV0b0hpZGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsIHR1cm5zIGF1dG8gaGlkZSBvbi9vZmYgKi9cbiAgICBfc2V0dXBBdXRvSGlkZShhdXRvKSB7XG4gICAgICAgIGlmIChhdXRvKSB7XG4gICAgICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5hZGQoJ3VpLXJlc2l6YWJsZS1hdXRvaGlkZScpO1xuICAgICAgICAgICAgLy8gdXNlIG1vdXNlb3ZlciBhbmQgbm90IG1vdXNlZW50ZXIgdG8gZ2V0IGJldHRlciBwZXJmb3JtYW5jZSBhbmQgdHJhY2sgZm9yIG5lc3RlZCBjYXNlc1xuICAgICAgICAgICAgdGhpcy5lbC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW92ZXInLCB0aGlzLl9tb3VzZU92ZXIpO1xuICAgICAgICAgICAgdGhpcy5lbC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW91dCcsIHRoaXMuX21vdXNlT3V0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWwuY2xhc3NMaXN0LnJlbW92ZSgndWktcmVzaXphYmxlLWF1dG9oaWRlJyk7XG4gICAgICAgICAgICB0aGlzLmVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlb3ZlcicsIHRoaXMuX21vdXNlT3Zlcik7XG4gICAgICAgICAgICB0aGlzLmVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlb3V0JywgdGhpcy5fbW91c2VPdXQpO1xuICAgICAgICAgICAgaWYgKERETWFuYWdlci5vdmVyUmVzaXplRWxlbWVudCA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBERE1hbmFnZXIub3ZlclJlc2l6ZUVsZW1lbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgX21vdXNlT3ZlcihlKSB7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGAke2NvdW50Kyt9IHByZS1lbnRlciAkeyh0aGlzLmVsIGFzIEdyaWRJdGVtSFRNTEVsZW1lbnQpLmdyaWRzdGFja05vZGUuX2lkfWApXG4gICAgICAgIC8vIGFscmVhZHkgb3ZlciBhIGNoaWxkLCBpZ25vcmUuIElkZWFsbHkgd2UganVzdCBjYWxsIGUuc3RvcFByb3BhZ2F0aW9uKCkgYnV0IHNlZSBodHRwczovL2dpdGh1Yi5jb20vZ3JpZHN0YWNrL2dyaWRzdGFjay5qcy9pc3N1ZXMvMjAxOFxuICAgICAgICBpZiAoRERNYW5hZ2VyLm92ZXJSZXNpemVFbGVtZW50IHx8IERETWFuYWdlci5kcmFnRWxlbWVudClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgRERNYW5hZ2VyLm92ZXJSZXNpemVFbGVtZW50ID0gdGhpcztcbiAgICAgICAgLy8gY29uc29sZS5sb2coYCR7Y291bnQrK30gZW50ZXIgJHsodGhpcy5lbCBhcyBHcmlkSXRlbUhUTUxFbGVtZW50KS5ncmlkc3RhY2tOb2RlLl9pZH1gKVxuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5yZW1vdmUoJ3VpLXJlc2l6YWJsZS1hdXRvaGlkZScpO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsICovXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIF9tb3VzZU91dChlKSB7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGAke2NvdW50Kyt9IHByZS1sZWF2ZSAkeyh0aGlzLmVsIGFzIEdyaWRJdGVtSFRNTEVsZW1lbnQpLmdyaWRzdGFja05vZGUuX2lkfWApXG4gICAgICAgIGlmIChERE1hbmFnZXIub3ZlclJlc2l6ZUVsZW1lbnQgIT09IHRoaXMpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGRlbGV0ZSBERE1hbmFnZXIub3ZlclJlc2l6ZUVsZW1lbnQ7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGAke2NvdW50Kyt9IGxlYXZlICR7KHRoaXMuZWwgYXMgR3JpZEl0ZW1IVE1MRWxlbWVudCkuZ3JpZHN0YWNrTm9kZS5faWR9YClcbiAgICAgICAgdGhpcy5lbC5jbGFzc0xpc3QuYWRkKCd1aS1yZXNpemFibGUtYXV0b2hpZGUnKTtcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF9zZXR1cEhhbmRsZXJzKCkge1xuICAgICAgICB0aGlzLmhhbmRsZXJzID0gdGhpcy5vcHRpb24uaGFuZGxlcy5zcGxpdCgnLCcpXG4gICAgICAgICAgICAubWFwKGRpciA9PiBkaXIudHJpbSgpKVxuICAgICAgICAgICAgLm1hcChkaXIgPT4gbmV3IEREUmVzaXphYmxlSGFuZGxlKHRoaXMuZWwsIGRpciwge1xuICAgICAgICAgICAgc3RhcnQ6IChldmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX3Jlc2l6ZVN0YXJ0KGV2ZW50KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzdG9wOiAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9yZXNpemVTdG9wKGV2ZW50KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtb3ZlOiAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9yZXNpemluZyhldmVudCwgZGlyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF9yZXNpemVTdGFydChldmVudCkge1xuICAgICAgICB0aGlzLnNpemVUb0NvbnRlbnQgPSBVdGlscy5zaG91bGRTaXplVG9Db250ZW50KHRoaXMuZWwuZ3JpZHN0YWNrTm9kZSwgdHJ1ZSk7IC8vIHN0cmljayB0cnVlIG9ubHkgYW5kIG5vdCBudW1iZXJcbiAgICAgICAgdGhpcy5vcmlnaW5hbFJlY3QgPSB0aGlzLmVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB0aGlzLnNjcm9sbEVsID0gVXRpbHMuZ2V0U2Nyb2xsRWxlbWVudCh0aGlzLmVsKTtcbiAgICAgICAgdGhpcy5zY3JvbGxZID0gdGhpcy5zY3JvbGxFbC5zY3JvbGxUb3A7XG4gICAgICAgIHRoaXMuc2Nyb2xsZWQgPSAwO1xuICAgICAgICB0aGlzLnN0YXJ0RXZlbnQgPSBldmVudDtcbiAgICAgICAgdGhpcy5fc2V0dXBIZWxwZXIoKTtcbiAgICAgICAgdGhpcy5fYXBwbHlDaGFuZ2UoKTtcbiAgICAgICAgY29uc3QgZXYgPSBVdGlscy5pbml0RXZlbnQoZXZlbnQsIHsgdHlwZTogJ3Jlc2l6ZXN0YXJ0JywgdGFyZ2V0OiB0aGlzLmVsIH0pO1xuICAgICAgICBpZiAodGhpcy5vcHRpb24uc3RhcnQpIHtcbiAgICAgICAgICAgIHRoaXMub3B0aW9uLnN0YXJ0KGV2LCB0aGlzLl91aSgpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5hZGQoJ3VpLXJlc2l6YWJsZS1yZXNpemluZycpO1xuICAgICAgICB0aGlzLnRyaWdnZXJFdmVudCgncmVzaXplc3RhcnQnLCBldik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsICovXG4gICAgX3Jlc2l6aW5nKGV2ZW50LCBkaXIpIHtcbiAgICAgICAgdGhpcy5zY3JvbGxlZCA9IHRoaXMuc2Nyb2xsRWwuc2Nyb2xsVG9wIC0gdGhpcy5zY3JvbGxZO1xuICAgICAgICB0aGlzLnRlbXBvcmFsUmVjdCA9IHRoaXMuX2dldENoYW5nZShldmVudCwgZGlyKTtcbiAgICAgICAgdGhpcy5fYXBwbHlDaGFuZ2UoKTtcbiAgICAgICAgY29uc3QgZXYgPSBVdGlscy5pbml0RXZlbnQoZXZlbnQsIHsgdHlwZTogJ3Jlc2l6ZScsIHRhcmdldDogdGhpcy5lbCB9KTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9uLnJlc2l6ZSkge1xuICAgICAgICAgICAgdGhpcy5vcHRpb24ucmVzaXplKGV2LCB0aGlzLl91aSgpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRyaWdnZXJFdmVudCgncmVzaXplJywgZXYpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF9yZXNpemVTdG9wKGV2ZW50KSB7XG4gICAgICAgIGNvbnN0IGV2ID0gVXRpbHMuaW5pdEV2ZW50KGV2ZW50LCB7IHR5cGU6ICdyZXNpemVzdG9wJywgdGFyZ2V0OiB0aGlzLmVsIH0pO1xuICAgICAgICBpZiAodGhpcy5vcHRpb24uc3RvcCkge1xuICAgICAgICAgICAgdGhpcy5vcHRpb24uc3RvcChldik7IC8vIE5vdGU6IHVpKCkgbm90IHVzZWQgYnkgZ3JpZHN0YWNrIHNvIGRvbid0IHBhc3NcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5yZW1vdmUoJ3VpLXJlc2l6YWJsZS1yZXNpemluZycpO1xuICAgICAgICB0aGlzLnRyaWdnZXJFdmVudCgncmVzaXplc3RvcCcsIGV2KTtcbiAgICAgICAgdGhpcy5fY2xlYW5IZWxwZXIoKTtcbiAgICAgICAgZGVsZXRlIHRoaXMuc3RhcnRFdmVudDtcbiAgICAgICAgZGVsZXRlIHRoaXMub3JpZ2luYWxSZWN0O1xuICAgICAgICBkZWxldGUgdGhpcy50ZW1wb3JhbFJlY3Q7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnNjcm9sbFk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnNjcm9sbGVkO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF9zZXR1cEhlbHBlcigpIHtcbiAgICAgICAgdGhpcy5lbE9yaWdpblN0eWxlVmFsID0gRERSZXNpemFibGUuX29yaWdpblN0eWxlUHJvcC5tYXAocHJvcCA9PiB0aGlzLmVsLnN0eWxlW3Byb3BdKTtcbiAgICAgICAgdGhpcy5wYXJlbnRPcmlnaW5TdHlsZVBvc2l0aW9uID0gdGhpcy5lbC5wYXJlbnRFbGVtZW50LnN0eWxlLnBvc2l0aW9uO1xuICAgICAgICBjb25zdCBwYXJlbnQgPSB0aGlzLmVsLnBhcmVudEVsZW1lbnQ7XG4gICAgICAgIGNvbnN0IGRyYWdUcmFuc2Zvcm0gPSBVdGlscy5nZXRWYWx1ZXNGcm9tVHJhbnNmb3JtZWRFbGVtZW50KHBhcmVudCk7XG4gICAgICAgIHRoaXMucmVjdFNjYWxlID0ge1xuICAgICAgICAgICAgeDogZHJhZ1RyYW5zZm9ybS54U2NhbGUsXG4gICAgICAgICAgICB5OiBkcmFnVHJhbnNmb3JtLnlTY2FsZVxuICAgICAgICB9O1xuICAgICAgICBpZiAoZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLmVsLnBhcmVudEVsZW1lbnQpLnBvc2l0aW9uLm1hdGNoKC9zdGF0aWMvKSkge1xuICAgICAgICAgICAgdGhpcy5lbC5wYXJlbnRFbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVsLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgICAgdGhpcy5lbC5zdHlsZS5vcGFjaXR5ID0gJzAuOCc7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsICovXG4gICAgX2NsZWFuSGVscGVyKCkge1xuICAgICAgICBERFJlc2l6YWJsZS5fb3JpZ2luU3R5bGVQcm9wLmZvckVhY2goKHByb3AsIGkpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZWwuc3R5bGVbcHJvcF0gPSB0aGlzLmVsT3JpZ2luU3R5bGVWYWxbaV0gfHwgbnVsbDtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZWwucGFyZW50RWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9IHRoaXMucGFyZW50T3JpZ2luU3R5bGVQb3NpdGlvbiB8fCBudWxsO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF9nZXRDaGFuZ2UoZXZlbnQsIGRpcikge1xuICAgICAgICBjb25zdCBvRXZlbnQgPSB0aGlzLnN0YXJ0RXZlbnQ7XG4gICAgICAgIGNvbnN0IG5ld1JlY3QgPSB7XG4gICAgICAgICAgICB3aWR0aDogdGhpcy5vcmlnaW5hbFJlY3Qud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IHRoaXMub3JpZ2luYWxSZWN0LmhlaWdodCArIHRoaXMuc2Nyb2xsZWQsXG4gICAgICAgICAgICBsZWZ0OiB0aGlzLm9yaWdpbmFsUmVjdC5sZWZ0LFxuICAgICAgICAgICAgdG9wOiB0aGlzLm9yaWdpbmFsUmVjdC50b3AgLSB0aGlzLnNjcm9sbGVkXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IG9mZnNldFggPSBldmVudC5jbGllbnRYIC0gb0V2ZW50LmNsaWVudFg7XG4gICAgICAgIGNvbnN0IG9mZnNldFkgPSB0aGlzLnNpemVUb0NvbnRlbnQgPyAwIDogZXZlbnQuY2xpZW50WSAtIG9FdmVudC5jbGllbnRZOyAvLyBwcmV2ZW50IHZlcnQgcmVzaXplXG4gICAgICAgIGlmIChkaXIuaW5kZXhPZignZScpID4gLTEpIHtcbiAgICAgICAgICAgIG5ld1JlY3Qud2lkdGggKz0gb2Zmc2V0WDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChkaXIuaW5kZXhPZigndycpID4gLTEpIHtcbiAgICAgICAgICAgIG5ld1JlY3Qud2lkdGggLT0gb2Zmc2V0WDtcbiAgICAgICAgICAgIG5ld1JlY3QubGVmdCArPSBvZmZzZXRYO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkaXIuaW5kZXhPZigncycpID4gLTEpIHtcbiAgICAgICAgICAgIG5ld1JlY3QuaGVpZ2h0ICs9IG9mZnNldFk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZGlyLmluZGV4T2YoJ24nKSA+IC0xKSB7XG4gICAgICAgICAgICBuZXdSZWN0LmhlaWdodCAtPSBvZmZzZXRZO1xuICAgICAgICAgICAgbmV3UmVjdC50b3AgKz0gb2Zmc2V0WTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjb25zdHJhaW4gPSB0aGlzLl9jb25zdHJhaW5TaXplKG5ld1JlY3Qud2lkdGgsIG5ld1JlY3QuaGVpZ2h0KTtcbiAgICAgICAgaWYgKE1hdGgucm91bmQobmV3UmVjdC53aWR0aCkgIT09IE1hdGgucm91bmQoY29uc3RyYWluLndpZHRoKSkgeyAvLyByb3VuZCB0byBpZ25vcmUgc2xpZ2h0IHJvdW5kLW9mZiBlcnJvcnNcbiAgICAgICAgICAgIGlmIChkaXIuaW5kZXhPZigndycpID4gLTEpIHtcbiAgICAgICAgICAgICAgICBuZXdSZWN0LmxlZnQgKz0gbmV3UmVjdC53aWR0aCAtIGNvbnN0cmFpbi53aWR0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5ld1JlY3Qud2lkdGggPSBjb25zdHJhaW4ud2lkdGg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKE1hdGgucm91bmQobmV3UmVjdC5oZWlnaHQpICE9PSBNYXRoLnJvdW5kKGNvbnN0cmFpbi5oZWlnaHQpKSB7XG4gICAgICAgICAgICBpZiAoZGlyLmluZGV4T2YoJ24nKSA+IC0xKSB7XG4gICAgICAgICAgICAgICAgbmV3UmVjdC50b3AgKz0gbmV3UmVjdC5oZWlnaHQgLSBjb25zdHJhaW4uaGVpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbmV3UmVjdC5oZWlnaHQgPSBjb25zdHJhaW4uaGVpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXdSZWN0O1xuICAgIH1cbiAgICAvKiogQGludGVybmFsIGNvbnN0cmFpbiB0aGUgc2l6ZSB0byB0aGUgc2V0IG1pbi9tYXggdmFsdWVzICovXG4gICAgX2NvbnN0cmFpblNpemUob1dpZHRoLCBvSGVpZ2h0KSB7XG4gICAgICAgIGNvbnN0IG1heFdpZHRoID0gdGhpcy5vcHRpb24ubWF4V2lkdGggfHwgTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7XG4gICAgICAgIGNvbnN0IG1pbldpZHRoID0gdGhpcy5vcHRpb24ubWluV2lkdGggLyB0aGlzLnJlY3RTY2FsZS54IHx8IG9XaWR0aDtcbiAgICAgICAgY29uc3QgbWF4SGVpZ2h0ID0gdGhpcy5vcHRpb24ubWF4SGVpZ2h0IHx8IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSO1xuICAgICAgICBjb25zdCBtaW5IZWlnaHQgPSB0aGlzLm9wdGlvbi5taW5IZWlnaHQgLyB0aGlzLnJlY3RTY2FsZS55IHx8IG9IZWlnaHQ7XG4gICAgICAgIGNvbnN0IHdpZHRoID0gTWF0aC5taW4obWF4V2lkdGgsIE1hdGgubWF4KG1pbldpZHRoLCBvV2lkdGgpKTtcbiAgICAgICAgY29uc3QgaGVpZ2h0ID0gTWF0aC5taW4obWF4SGVpZ2h0LCBNYXRoLm1heChtaW5IZWlnaHQsIG9IZWlnaHQpKTtcbiAgICAgICAgcmV0dXJuIHsgd2lkdGgsIGhlaWdodCB9O1xuICAgIH1cbiAgICAvKiogQGludGVybmFsICovXG4gICAgX2FwcGx5Q2hhbmdlKCkge1xuICAgICAgICBsZXQgY29udGFpbm1lbnRSZWN0ID0geyBsZWZ0OiAwLCB0b3A6IDAsIHdpZHRoOiAwLCBoZWlnaHQ6IDAgfTtcbiAgICAgICAgaWYgKHRoaXMuZWwuc3R5bGUucG9zaXRpb24gPT09ICdhYnNvbHV0ZScpIHtcbiAgICAgICAgICAgIGNvbnN0IGNvbnRhaW5tZW50RWwgPSB0aGlzLmVsLnBhcmVudEVsZW1lbnQ7XG4gICAgICAgICAgICBjb25zdCB7IGxlZnQsIHRvcCB9ID0gY29udGFpbm1lbnRFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIGNvbnRhaW5tZW50UmVjdCA9IHsgbGVmdCwgdG9wLCB3aWR0aDogMCwgaGVpZ2h0OiAwIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnRlbXBvcmFsUmVjdClcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICBPYmplY3Qua2V5cyh0aGlzLnRlbXBvcmFsUmVjdCkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnRlbXBvcmFsUmVjdFtrZXldO1xuICAgICAgICAgICAgY29uc3Qgc2NhbGVSZWNpcHJvY2FsID0ga2V5ID09PSAnd2lkdGgnIHx8IGtleSA9PT0gJ2xlZnQnID8gdGhpcy5yZWN0U2NhbGUueCA6IGtleSA9PT0gJ2hlaWdodCcgfHwga2V5ID09PSAndG9wJyA/IHRoaXMucmVjdFNjYWxlLnkgOiAxO1xuICAgICAgICAgICAgdGhpcy5lbC5zdHlsZVtrZXldID0gKHZhbHVlIC0gY29udGFpbm1lbnRSZWN0W2tleV0pICogc2NhbGVSZWNpcHJvY2FsICsgJ3B4JztcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsICovXG4gICAgX3JlbW92ZUhhbmRsZXJzKCkge1xuICAgICAgICB0aGlzLmhhbmRsZXJzLmZvckVhY2goaGFuZGxlID0+IGhhbmRsZS5kZXN0cm95KCkpO1xuICAgICAgICBkZWxldGUgdGhpcy5oYW5kbGVycztcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxufVxuLyoqIEBpbnRlcm5hbCAqL1xuRERSZXNpemFibGUuX29yaWdpblN0eWxlUHJvcCA9IFsnd2lkdGgnLCAnaGVpZ2h0JywgJ3Bvc2l0aW9uJywgJ2xlZnQnLCAndG9wJywgJ29wYWNpdHknLCAnekluZGV4J107XG5leHBvcnQgeyBERFJlc2l6YWJsZSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGQtcmVzaXphYmxlLmpzLm1hcCIsIi8qKlxuICogdG91Y2gudHMgMTAuMS4yXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjEgQWxhaW4gRHVtZXNueSAtIHNlZSBHcmlkU3RhY2sgcm9vdCBsaWNlbnNlXG4gKi9cbmltcG9ydCB7IERETWFuYWdlciB9IGZyb20gJy4vZGQtbWFuYWdlcic7XG4vKipcbiAqIERldGVjdCB0b3VjaCBzdXBwb3J0IC0gV2luZG93cyBTdXJmYWNlIGRldmljZXMgYW5kIG90aGVyIHRvdWNoIGRldmljZXNcbiAqIHNob3VsZCB3ZSB1c2UgdGhpcyBpbnN0ZWFkID8gKHdoYXQgd2UgaGFkIGZvciBhbHdheXMgc2hvd2luZyByZXNpemUgaGFuZGxlcylcbiAqIC9BbmRyb2lkfHdlYk9TfGlQaG9uZXxpUGFkfGlQb2R8QmxhY2tCZXJyeXxJRU1vYmlsZXxPcGVyYSBNaW5pL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KVxuICovXG5leHBvcnQgY29uc3QgaXNUb3VjaCA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnRcbiAgICAgICAgfHwgJ29udG91Y2hzdGFydCcgaW4gd2luZG93XG4gICAgICAgIC8vIHx8ICEhd2luZG93LlRvdWNoRXZlbnQgLy8gdHJ1ZSBvbiBXaW5kb3dzIDEwIENocm9tZSBkZXNrdG9wIHNvIGRvbid0IHVzZSB0aGlzXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgIHx8ICh3aW5kb3cuRG9jdW1lbnRUb3VjaCAmJiBkb2N1bWVudCBpbnN0YW5jZW9mIHdpbmRvdy5Eb2N1bWVudFRvdWNoKVxuICAgICAgICB8fCBuYXZpZ2F0b3IubWF4VG91Y2hQb2ludHMgPiAwXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgIHx8IG5hdmlnYXRvci5tc01heFRvdWNoUG9pbnRzID4gMCk7XG4vLyBpbnRlcmZhY2UgVG91Y2hDb29yZCB7eDogbnVtYmVyLCB5OiBudW1iZXJ9O1xuY2xhc3MgRERUb3VjaCB7XG59XG4vKipcbiogR2V0IHRoZSB4LHkgcG9zaXRpb24gb2YgYSB0b3VjaCBldmVudFxuKi9cbi8vIGZ1bmN0aW9uIGdldFRvdWNoQ29vcmRzKGU6IFRvdWNoRXZlbnQpOiBUb3VjaENvb3JkIHtcbi8vICAgcmV0dXJuIHtcbi8vICAgICB4OiBlLmNoYW5nZWRUb3VjaGVzWzBdLnBhZ2VYLFxuLy8gICAgIHk6IGUuY2hhbmdlZFRvdWNoZXNbMF0ucGFnZVlcbi8vICAgfTtcbi8vIH1cbi8qKlxuICogU2ltdWxhdGUgYSBtb3VzZSBldmVudCBiYXNlZCBvbiBhIGNvcnJlc3BvbmRpbmcgdG91Y2ggZXZlbnRcbiAqIEBwYXJhbSB7T2JqZWN0fSBlIEEgdG91Y2ggZXZlbnRcbiAqIEBwYXJhbSB7U3RyaW5nfSBzaW11bGF0ZWRUeXBlIFRoZSBjb3JyZXNwb25kaW5nIG1vdXNlIGV2ZW50XG4gKi9cbmZ1bmN0aW9uIHNpbXVsYXRlTW91c2VFdmVudChlLCBzaW11bGF0ZWRUeXBlKSB7XG4gICAgLy8gSWdub3JlIG11bHRpLXRvdWNoIGV2ZW50c1xuICAgIGlmIChlLnRvdWNoZXMubGVuZ3RoID4gMSlcbiAgICAgICAgcmV0dXJuO1xuICAgIC8vIFByZXZlbnQgXCJJZ25vcmVkIGF0dGVtcHQgdG8gY2FuY2VsIGEgdG91Y2htb3ZlIGV2ZW50IHdpdGggY2FuY2VsYWJsZT1mYWxzZVwiIGVycm9yc1xuICAgIGlmIChlLmNhbmNlbGFibGUpXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICBjb25zdCB0b3VjaCA9IGUuY2hhbmdlZFRvdWNoZXNbMF0sIHNpbXVsYXRlZEV2ZW50ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ01vdXNlRXZlbnRzJyk7XG4gICAgLy8gSW5pdGlhbGl6ZSB0aGUgc2ltdWxhdGVkIG1vdXNlIGV2ZW50IHVzaW5nIHRoZSB0b3VjaCBldmVudCdzIGNvb3JkaW5hdGVzXG4gICAgc2ltdWxhdGVkRXZlbnQuaW5pdE1vdXNlRXZlbnQoc2ltdWxhdGVkVHlwZSwgLy8gdHlwZVxuICAgIHRydWUsIC8vIGJ1YmJsZXNcbiAgICB0cnVlLCAvLyBjYW5jZWxhYmxlXG4gICAgd2luZG93LCAvLyB2aWV3XG4gICAgMSwgLy8gZGV0YWlsXG4gICAgdG91Y2guc2NyZWVuWCwgLy8gc2NyZWVuWFxuICAgIHRvdWNoLnNjcmVlblksIC8vIHNjcmVlbllcbiAgICB0b3VjaC5jbGllbnRYLCAvLyBjbGllbnRYXG4gICAgdG91Y2guY2xpZW50WSwgLy8gY2xpZW50WVxuICAgIGZhbHNlLCAvLyBjdHJsS2V5XG4gICAgZmFsc2UsIC8vIGFsdEtleVxuICAgIGZhbHNlLCAvLyBzaGlmdEtleVxuICAgIGZhbHNlLCAvLyBtZXRhS2V5XG4gICAgMCwgLy8gYnV0dG9uXG4gICAgbnVsbCAvLyByZWxhdGVkVGFyZ2V0XG4gICAgKTtcbiAgICAvLyBEaXNwYXRjaCB0aGUgc2ltdWxhdGVkIGV2ZW50IHRvIHRoZSB0YXJnZXQgZWxlbWVudFxuICAgIGUudGFyZ2V0LmRpc3BhdGNoRXZlbnQoc2ltdWxhdGVkRXZlbnQpO1xufVxuLyoqXG4gKiBTaW11bGF0ZSBhIG1vdXNlIGV2ZW50IGJhc2VkIG9uIGEgY29ycmVzcG9uZGluZyBQb2ludGVyIGV2ZW50XG4gKiBAcGFyYW0ge09iamVjdH0gZSBBIHBvaW50ZXIgZXZlbnRcbiAqIEBwYXJhbSB7U3RyaW5nfSBzaW11bGF0ZWRUeXBlIFRoZSBjb3JyZXNwb25kaW5nIG1vdXNlIGV2ZW50XG4gKi9cbmZ1bmN0aW9uIHNpbXVsYXRlUG9pbnRlck1vdXNlRXZlbnQoZSwgc2ltdWxhdGVkVHlwZSkge1xuICAgIC8vIFByZXZlbnQgXCJJZ25vcmVkIGF0dGVtcHQgdG8gY2FuY2VsIGEgdG91Y2htb3ZlIGV2ZW50IHdpdGggY2FuY2VsYWJsZT1mYWxzZVwiIGVycm9yc1xuICAgIGlmIChlLmNhbmNlbGFibGUpXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICBjb25zdCBzaW11bGF0ZWRFdmVudCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdNb3VzZUV2ZW50cycpO1xuICAgIC8vIEluaXRpYWxpemUgdGhlIHNpbXVsYXRlZCBtb3VzZSBldmVudCB1c2luZyB0aGUgdG91Y2ggZXZlbnQncyBjb29yZGluYXRlc1xuICAgIHNpbXVsYXRlZEV2ZW50LmluaXRNb3VzZUV2ZW50KHNpbXVsYXRlZFR5cGUsIC8vIHR5cGVcbiAgICB0cnVlLCAvLyBidWJibGVzXG4gICAgdHJ1ZSwgLy8gY2FuY2VsYWJsZVxuICAgIHdpbmRvdywgLy8gdmlld1xuICAgIDEsIC8vIGRldGFpbFxuICAgIGUuc2NyZWVuWCwgLy8gc2NyZWVuWFxuICAgIGUuc2NyZWVuWSwgLy8gc2NyZWVuWVxuICAgIGUuY2xpZW50WCwgLy8gY2xpZW50WFxuICAgIGUuY2xpZW50WSwgLy8gY2xpZW50WVxuICAgIGZhbHNlLCAvLyBjdHJsS2V5XG4gICAgZmFsc2UsIC8vIGFsdEtleVxuICAgIGZhbHNlLCAvLyBzaGlmdEtleVxuICAgIGZhbHNlLCAvLyBtZXRhS2V5XG4gICAgMCwgLy8gYnV0dG9uXG4gICAgbnVsbCAvLyByZWxhdGVkVGFyZ2V0XG4gICAgKTtcbiAgICAvLyBEaXNwYXRjaCB0aGUgc2ltdWxhdGVkIGV2ZW50IHRvIHRoZSB0YXJnZXQgZWxlbWVudFxuICAgIGUudGFyZ2V0LmRpc3BhdGNoRXZlbnQoc2ltdWxhdGVkRXZlbnQpO1xufVxuLyoqXG4gKiBIYW5kbGUgdGhlIHRvdWNoc3RhcnQgZXZlbnRzXG4gKiBAcGFyYW0ge09iamVjdH0gZSBUaGUgd2lkZ2V0IGVsZW1lbnQncyB0b3VjaHN0YXJ0IGV2ZW50XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b3VjaHN0YXJ0KGUpIHtcbiAgICAvLyBJZ25vcmUgdGhlIGV2ZW50IGlmIGFub3RoZXIgd2lkZ2V0IGlzIGFscmVhZHkgYmVpbmcgaGFuZGxlZFxuICAgIGlmIChERFRvdWNoLnRvdWNoSGFuZGxlZClcbiAgICAgICAgcmV0dXJuO1xuICAgIEREVG91Y2gudG91Y2hIYW5kbGVkID0gdHJ1ZTtcbiAgICAvLyBTaW11bGF0ZSB0aGUgbW91c2UgZXZlbnRzXG4gICAgLy8gc2ltdWxhdGVNb3VzZUV2ZW50KGUsICdtb3VzZW92ZXInKTtcbiAgICAvLyBzaW11bGF0ZU1vdXNlRXZlbnQoZSwgJ21vdXNlbW92ZScpO1xuICAgIHNpbXVsYXRlTW91c2VFdmVudChlLCAnbW91c2Vkb3duJyk7XG59XG4vKipcbiAqIEhhbmRsZSB0aGUgdG91Y2htb3ZlIGV2ZW50c1xuICogQHBhcmFtIHtPYmplY3R9IGUgVGhlIGRvY3VtZW50J3MgdG91Y2htb3ZlIGV2ZW50XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b3VjaG1vdmUoZSkge1xuICAgIC8vIElnbm9yZSBldmVudCBpZiBub3QgaGFuZGxlZCBieSB1c1xuICAgIGlmICghRERUb3VjaC50b3VjaEhhbmRsZWQpXG4gICAgICAgIHJldHVybjtcbiAgICBzaW11bGF0ZU1vdXNlRXZlbnQoZSwgJ21vdXNlbW92ZScpO1xufVxuLyoqXG4gKiBIYW5kbGUgdGhlIHRvdWNoZW5kIGV2ZW50c1xuICogQHBhcmFtIHtPYmplY3R9IGUgVGhlIGRvY3VtZW50J3MgdG91Y2hlbmQgZXZlbnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvdWNoZW5kKGUpIHtcbiAgICAvLyBJZ25vcmUgZXZlbnQgaWYgbm90IGhhbmRsZWRcbiAgICBpZiAoIUREVG91Y2gudG91Y2hIYW5kbGVkKVxuICAgICAgICByZXR1cm47XG4gICAgLy8gY2FuY2VsIGRlbGF5ZWQgbGVhdmUgZXZlbnQgd2hlbiB3ZSByZWxlYXNlIG9uIG91cnNlbGYgd2hpY2ggaGFwcGVucyBCRUZPUkUgd2UgZ2V0IHRoaXMhXG4gICAgaWYgKEREVG91Y2gucG9pbnRlckxlYXZlVGltZW91dCkge1xuICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KEREVG91Y2gucG9pbnRlckxlYXZlVGltZW91dCk7XG4gICAgICAgIGRlbGV0ZSBERFRvdWNoLnBvaW50ZXJMZWF2ZVRpbWVvdXQ7XG4gICAgfVxuICAgIGNvbnN0IHdhc0RyYWdnaW5nID0gISFERE1hbmFnZXIuZHJhZ0VsZW1lbnQ7XG4gICAgLy8gU2ltdWxhdGUgdGhlIG1vdXNldXAgZXZlbnRcbiAgICBzaW11bGF0ZU1vdXNlRXZlbnQoZSwgJ21vdXNldXAnKTtcbiAgICAvLyBzaW11bGF0ZU1vdXNlRXZlbnQoZXZlbnQsICdtb3VzZW91dCcpO1xuICAgIC8vIElmIHRoZSB0b3VjaCBpbnRlcmFjdGlvbiBkaWQgbm90IG1vdmUsIGl0IHNob3VsZCB0cmlnZ2VyIGEgY2xpY2tcbiAgICBpZiAoIXdhc0RyYWdnaW5nKSB7XG4gICAgICAgIHNpbXVsYXRlTW91c2VFdmVudChlLCAnY2xpY2snKTtcbiAgICB9XG4gICAgLy8gVW5zZXQgdGhlIGZsYWcgdG8gYWxsb3cgb3RoZXIgd2lkZ2V0cyB0byBpbmhlcml0IHRoZSB0b3VjaCBldmVudFxuICAgIEREVG91Y2gudG91Y2hIYW5kbGVkID0gZmFsc2U7XG59XG4vKipcbiAqIE5vdGUgd2UgZG9uJ3QgZ2V0IHRvdWNoZW50ZXIvdG91Y2hsZWF2ZSAod2hpY2ggYXJlIGRlcHJlY2F0ZWQpXG4gKiBzZWUgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjc5MDgzMzkvanMtdG91Y2gtZXF1aXZhbGVudC1mb3ItbW91c2VlbnRlclxuICogc28gaW5zdGVhZCBvZiBQb2ludGVyRXZlbnQgdG8gc3RpbGwgZ2V0IGVudGVyL2xlYXZlIGFuZCBzZW5kIHRoZSBtYXRjaGluZyBtb3VzZSBldmVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBvaW50ZXJkb3duKGUpIHtcbiAgICAvLyBjb25zb2xlLmxvZyhcInBvaW50ZXIgZG93blwiKVxuICAgIGlmIChlLnBvaW50ZXJUeXBlID09PSAnbW91c2UnKVxuICAgICAgICByZXR1cm47XG4gICAgZS50YXJnZXQucmVsZWFzZVBvaW50ZXJDYXB0dXJlKGUucG9pbnRlcklkKTsgLy8gPC0gSW1wb3J0YW50IVxufVxuZXhwb3J0IGZ1bmN0aW9uIHBvaW50ZXJlbnRlcihlKSB7XG4gICAgLy8gaWdub3JlIHRoZSBpbml0aWFsIG9uZSB3ZSBnZXQgb24gcG9pbnRlcmRvd24gb24gb3Vyc2VsZlxuICAgIGlmICghRERNYW5hZ2VyLmRyYWdFbGVtZW50KSB7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKCdwb2ludGVyZW50ZXIgaWdub3JlZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIGNvbnNvbGUubG9nKCdwb2ludGVyZW50ZXInKTtcbiAgICBpZiAoZS5wb2ludGVyVHlwZSA9PT0gJ21vdXNlJylcbiAgICAgICAgcmV0dXJuO1xuICAgIHNpbXVsYXRlUG9pbnRlck1vdXNlRXZlbnQoZSwgJ21vdXNlZW50ZXInKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBwb2ludGVybGVhdmUoZSkge1xuICAgIC8vIGlnbm9yZSB0aGUgbGVhdmUgb24gb3Vyc2VsZiB3ZSBnZXQgYmVmb3JlIHJlbGVhc2luZyB0aGUgbW91c2Ugb3ZlciBvdXJzZWxmXG4gICAgLy8gYnkgZGVsYXlpbmcgc2VuZGluZyB0aGUgZXZlbnQgYW5kIGhhdmluZyB0aGUgdXAgZXZlbnQgY2FuY2VsIHVzXG4gICAgaWYgKCFERE1hbmFnZXIuZHJhZ0VsZW1lbnQpIHtcbiAgICAgICAgLy8gY29uc29sZS5sb2coJ3BvaW50ZXJsZWF2ZSBpZ25vcmVkJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGUucG9pbnRlclR5cGUgPT09ICdtb3VzZScpXG4gICAgICAgIHJldHVybjtcbiAgICBERFRvdWNoLnBvaW50ZXJMZWF2ZVRpbWVvdXQgPSB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIGRlbGV0ZSBERFRvdWNoLnBvaW50ZXJMZWF2ZVRpbWVvdXQ7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKCdwb2ludGVybGVhdmUgZGVsYXllZCcpO1xuICAgICAgICBzaW11bGF0ZVBvaW50ZXJNb3VzZUV2ZW50KGUsICdtb3VzZWxlYXZlJyk7XG4gICAgfSwgMTApO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGQtdG91Y2guanMubWFwIiwiLyoqXG4gKiBncmlkc3RhY2stZW5naW5lLnRzIDEwLjEuMlxuICogQ29weXJpZ2h0IChjKSAyMDIxLTIwMjIgQWxhaW4gRHVtZXNueSAtIHNlZSBHcmlkU3RhY2sgcm9vdCBsaWNlbnNlXG4gKi9cbmltcG9ydCB7IFV0aWxzIH0gZnJvbSAnLi91dGlscyc7XG4vKipcbiAqIERlZmluZXMgdGhlIEdyaWRTdGFjayBlbmdpbmUgdGhhdCBkb2VzIG1vc3Qgbm8gRE9NIGdyaWQgbWFuaXB1bGF0aW9uLlxuICogU2VlIEdyaWRTdGFjayBtZXRob2RzIGFuZCB2YXJzIGZvciBkZXNjcmlwdGlvbnMuXG4gKlxuICogTk9URTogdmFsdWVzIHNob3VsZCBub3QgYmUgbW9kaWZpZWQgZGlyZWN0bHkgLSBjYWxsIHRoZSBtYWluIEdyaWRTdGFjayBBUEkgaW5zdGVhZFxuICovXG5jbGFzcyBHcmlkU3RhY2tFbmdpbmUge1xuICAgIGNvbnN0cnVjdG9yKG9wdHMgPSB7fSkge1xuICAgICAgICB0aGlzLmFkZGVkTm9kZXMgPSBbXTtcbiAgICAgICAgdGhpcy5yZW1vdmVkTm9kZXMgPSBbXTtcbiAgICAgICAgdGhpcy5jb2x1bW4gPSBvcHRzLmNvbHVtbiB8fCAxMjtcbiAgICAgICAgdGhpcy5tYXhSb3cgPSBvcHRzLm1heFJvdztcbiAgICAgICAgdGhpcy5fZmxvYXQgPSBvcHRzLmZsb2F0O1xuICAgICAgICB0aGlzLm5vZGVzID0gb3B0cy5ub2RlcyB8fCBbXTtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSA9IG9wdHMub25DaGFuZ2U7XG4gICAgfVxuICAgIGJhdGNoVXBkYXRlKGZsYWcgPSB0cnVlLCBkb1BhY2sgPSB0cnVlKSB7XG4gICAgICAgIGlmICghIXRoaXMuYmF0Y2hNb2RlID09PSBmbGFnKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIHRoaXMuYmF0Y2hNb2RlID0gZmxhZztcbiAgICAgICAgaWYgKGZsYWcpIHtcbiAgICAgICAgICAgIHRoaXMuX3ByZXZGbG9hdCA9IHRoaXMuX2Zsb2F0O1xuICAgICAgICAgICAgdGhpcy5fZmxvYXQgPSB0cnVlOyAvLyBsZXQgdGhpbmdzIGdvIGFueXdoZXJlIGZvciBub3cuLi4gd2lsbCByZXN0b3JlIGFuZCBwb3NzaWJseSByZXBvc2l0aW9uIGxhdGVyXG4gICAgICAgICAgICB0aGlzLmNsZWFuTm9kZXMoKTtcbiAgICAgICAgICAgIHRoaXMuc2F2ZUluaXRpYWwoKTsgLy8gc2luY2UgYmVnaW4gdXBkYXRlICh3aGljaCBpcyBjYWxsZWQgbXVsdGlwbGUgdGltZXMpIHdvbid0IGRvIHRoaXNcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2Zsb2F0ID0gdGhpcy5fcHJldkZsb2F0O1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX3ByZXZGbG9hdDtcbiAgICAgICAgICAgIGlmIChkb1BhY2spXG4gICAgICAgICAgICAgICAgdGhpcy5fcGFja05vZGVzKCk7XG4gICAgICAgICAgICB0aGlzLl9ub3RpZnkoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLy8gdXNlIGVudGlyZSByb3cgZm9yIGhpdHRpbmcgYXJlYSAod2lsbCB1c2UgYm90dG9tIHJldmVyc2Ugc29ydGVkIGZpcnN0KSBpZiB3ZSBub3QgYWN0aXZlbHkgbW92aW5nIERPV04gYW5kIGRpZG4ndCBhbHJlYWR5IHNraXBcbiAgICBfdXNlRW50aXJlUm93QXJlYShub2RlLCBubikge1xuICAgICAgICByZXR1cm4gKCF0aGlzLmZsb2F0IHx8IHRoaXMuYmF0Y2hNb2RlICYmICF0aGlzLl9wcmV2RmxvYXQpICYmICF0aGlzLl9oYXNMb2NrZWQgJiYgKCFub2RlLl9tb3ZpbmcgfHwgbm9kZS5fc2tpcERvd24gfHwgbm4ueSA8PSBub2RlLnkpO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsIGZpeCBjb2xsaXNpb24gb24gZ2l2ZW4gJ25vZGUnLCBnb2luZyB0byBnaXZlbiBuZXcgbG9jYXRpb24gJ25uJywgd2l0aCBvcHRpb25hbCAnY29sbGlkZScgbm9kZSBhbHJlYWR5IGZvdW5kLlxuICAgICAqIHJldHVybiB0cnVlIGlmIHdlIG1vdmVkLiAqL1xuICAgIF9maXhDb2xsaXNpb25zKG5vZGUsIG5uID0gbm9kZSwgY29sbGlkZSwgb3B0ID0ge30pIHtcbiAgICAgICAgdGhpcy5zb3J0Tm9kZXMoLTEpOyAvLyBmcm9tIGxhc3QgdG8gZmlyc3QsIHNvIHJlY3Vyc2l2ZSBjb2xsaXNpb24gbW92ZSBpdGVtcyBpbiB0aGUgcmlnaHQgb3JkZXJcbiAgICAgICAgY29sbGlkZSA9IGNvbGxpZGUgfHwgdGhpcy5jb2xsaWRlKG5vZGUsIG5uKTsgLy8gUkVBTCBhcmVhIGNvbGxpZGUgZm9yIHN3YXAgYW5kIHNraXAgaWYgbm9uZS4uLlxuICAgICAgICBpZiAoIWNvbGxpZGUpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIC8vIHN3YXAgY2hlY2s6IGlmIHdlJ3JlIGFjdGl2ZWx5IG1vdmluZyBpbiBncmF2aXR5IG1vZGUsIHNlZSBpZiB3ZSBjb2xsaWRlIHdpdGggYW4gb2JqZWN0IHRoZSBzYW1lIHNpemVcbiAgICAgICAgaWYgKG5vZGUuX21vdmluZyAmJiAhb3B0Lm5lc3RlZCAmJiAhdGhpcy5mbG9hdCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3dhcChub2RlLCBjb2xsaWRlKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBkdXJpbmcgd2hpbGUoKSBjb2xsaXNpb25zIE1BS0UgU1VSRSB0byBjaGVjayBlbnRpcmUgcm93IHNvIGxhcmdlciBpdGVtcyBkb24ndCBsZWFwIGZyb2cgc21hbGwgb25lcyAocHVzaCB0aGVtIGFsbCBkb3duIHN0YXJ0aW5nIGxhc3QgaW4gZ3JpZClcbiAgICAgICAgbGV0IGFyZWEgPSBubjtcbiAgICAgICAgaWYgKHRoaXMuX3VzZUVudGlyZVJvd0FyZWEobm9kZSwgbm4pKSB7XG4gICAgICAgICAgICBhcmVhID0geyB4OiAwLCB3OiB0aGlzLmNvbHVtbiwgeTogbm4ueSwgaDogbm4uaCB9O1xuICAgICAgICAgICAgY29sbGlkZSA9IHRoaXMuY29sbGlkZShub2RlLCBhcmVhLCBvcHQuc2tpcCk7IC8vIGZvcmNlIG5ldyBoaXRcbiAgICAgICAgfVxuICAgICAgICBsZXQgZGlkTW92ZSA9IGZhbHNlO1xuICAgICAgICBsZXQgbmV3T3B0ID0geyBuZXN0ZWQ6IHRydWUsIHBhY2s6IGZhbHNlIH07XG4gICAgICAgIHdoaWxlIChjb2xsaWRlID0gY29sbGlkZSB8fCB0aGlzLmNvbGxpZGUobm9kZSwgYXJlYSwgb3B0LnNraXApKSB7IC8vIGNvdWxkIGNvbGxpZGUgd2l0aCBtb3JlIHRoYW4gMSBpdGVtLi4uIHNvIHJlcGVhdCBmb3IgZWFjaFxuICAgICAgICAgICAgbGV0IG1vdmVkO1xuICAgICAgICAgICAgLy8gaWYgY29sbGlkaW5nIHdpdGggYSBsb2NrZWQgaXRlbSBPUiBtb3ZpbmcgZG93biB3aXRoIHRvcCBncmF2aXR5IChhbmQgY29sbGlkZSBjb3VsZCBtb3ZlIHVwKSAtPiBza2lwIHBhc3QgdGhlIGNvbGxpZGUsXG4gICAgICAgICAgICAvLyBidXQgcmVtZW1iZXIgdGhhdCBza2lwIGRvd24gc28gd2Ugb25seSBkbyB0aGlzIG9uY2UgKGFuZCBwdXNoIG90aGVycyBvdGhlcndpc2UpLlxuICAgICAgICAgICAgaWYgKGNvbGxpZGUubG9ja2VkIHx8IG5vZGUuX21vdmluZyAmJiAhbm9kZS5fc2tpcERvd24gJiYgbm4ueSA+IG5vZGUueSAmJiAhdGhpcy5mbG9hdCAmJlxuICAgICAgICAgICAgICAgIC8vIGNhbiB0YWtlIHNwYWNlIHdlIGhhZCwgb3IgYmVmb3JlIHdoZXJlIHdlJ3JlIGdvaW5nXG4gICAgICAgICAgICAgICAgKCF0aGlzLmNvbGxpZGUoY29sbGlkZSwgeyAuLi5jb2xsaWRlLCB5OiBub2RlLnkgfSwgbm9kZSkgfHwgIXRoaXMuY29sbGlkZShjb2xsaWRlLCB7IC4uLmNvbGxpZGUsIHk6IG5uLnkgLSBjb2xsaWRlLmggfSwgbm9kZSkpKSB7XG4gICAgICAgICAgICAgICAgbm9kZS5fc2tpcERvd24gPSAobm9kZS5fc2tpcERvd24gfHwgbm4ueSA+IG5vZGUueSk7XG4gICAgICAgICAgICAgICAgbW92ZWQgPSB0aGlzLm1vdmVOb2RlKG5vZGUsIHsgLi4ubm4sIHk6IGNvbGxpZGUueSArIGNvbGxpZGUuaCwgLi4ubmV3T3B0IH0pO1xuICAgICAgICAgICAgICAgIGlmIChjb2xsaWRlLmxvY2tlZCAmJiBtb3ZlZCkge1xuICAgICAgICAgICAgICAgICAgICBVdGlscy5jb3B5UG9zKG5uLCBub2RlKTsgLy8gbW92aW5nIGFmdGVyIGxvY2sgYmVjb21lIG91ciBuZXcgZGVzaXJlZCBsb2NhdGlvblxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICghY29sbGlkZS5sb2NrZWQgJiYgbW92ZWQgJiYgb3B0LnBhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gd2UgbW92ZWQgYWZ0ZXIgYW5kIHdpbGwgcGFjazogZG8gaXQgbm93IGFuZCBrZWVwIHRoZSBvcmlnaW5hbCBkcm9wIGxvY2F0aW9uLCBidXQgcGFzdCB0aGUgb2xkIGNvbGxpZGUgdG8gc2VlIHdoYXQgZWxzZSB3ZSBtaWdodCBwdXNoIHdheVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9wYWNrTm9kZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgbm4ueSA9IGNvbGxpZGUueSArIGNvbGxpZGUuaDtcbiAgICAgICAgICAgICAgICAgICAgVXRpbHMuY29weVBvcyhub2RlLCBubik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRpZE1vdmUgPSBkaWRNb3ZlIHx8IG1vdmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gbW92ZSBjb2xsaWRlIGRvd24gKmFmdGVyKiB3aGVyZSB3ZSB3aWxsIGJlLCBpZ25vcmluZyB3aGVyZSB3ZSBhcmUgbm93IChkb24ndCBjb2xsaWRlIHdpdGggdXMpXG4gICAgICAgICAgICAgICAgbW92ZWQgPSB0aGlzLm1vdmVOb2RlKGNvbGxpZGUsIHsgLi4uY29sbGlkZSwgeTogbm4ueSArIG5uLmgsIHNraXA6IG5vZGUsIC4uLm5ld09wdCB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbW92ZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGlkTW92ZTtcbiAgICAgICAgICAgIH0gLy8gYnJlYWsgaW5mIGxvb3AgaWYgd2UgY291bGRuJ3QgbW92ZSBhZnRlciBhbGwgKGV4OiBtYXhSb3csIGZpeGVkKVxuICAgICAgICAgICAgY29sbGlkZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlkTW92ZTtcbiAgICB9XG4gICAgLyoqIHJldHVybiB0aGUgbm9kZXMgdGhhdCBpbnRlcmNlcHQgdGhlIGdpdmVuIG5vZGUuIE9wdGlvbmFsbHkgYSBkaWZmZXJlbnQgYXJlYSBjYW4gYmUgdXNlZCwgYXMgd2VsbCBhcyBhIHNlY29uZCBub2RlIHRvIHNraXAgKi9cbiAgICBjb2xsaWRlKHNraXAsIGFyZWEgPSBza2lwLCBza2lwMikge1xuICAgICAgICBjb25zdCBza2lwSWQgPSBza2lwLl9pZDtcbiAgICAgICAgY29uc3Qgc2tpcDJJZCA9IHNraXAyPy5faWQ7XG4gICAgICAgIHJldHVybiB0aGlzLm5vZGVzLmZpbmQobiA9PiBuLl9pZCAhPT0gc2tpcElkICYmIG4uX2lkICE9PSBza2lwMklkICYmIFV0aWxzLmlzSW50ZXJjZXB0ZWQobiwgYXJlYSkpO1xuICAgIH1cbiAgICBjb2xsaWRlQWxsKHNraXAsIGFyZWEgPSBza2lwLCBza2lwMikge1xuICAgICAgICBjb25zdCBza2lwSWQgPSBza2lwLl9pZDtcbiAgICAgICAgY29uc3Qgc2tpcDJJZCA9IHNraXAyPy5faWQ7XG4gICAgICAgIHJldHVybiB0aGlzLm5vZGVzLmZpbHRlcihuID0+IG4uX2lkICE9PSBza2lwSWQgJiYgbi5faWQgIT09IHNraXAySWQgJiYgVXRpbHMuaXNJbnRlcmNlcHRlZChuLCBhcmVhKSk7XG4gICAgfVxuICAgIC8qKiBkb2VzIGEgcGl4ZWwgY292ZXJhZ2UgY29sbGlzaW9uIGJhc2VkIG9uIHdoZXJlIHdlIHN0YXJ0ZWQsIHJldHVybmluZyB0aGUgbm9kZSB0aGF0IGhhcyB0aGUgbW9zdCBjb3ZlcmFnZSB0aGF0IGlzID41MCUgbWlkIGxpbmUgKi9cbiAgICBkaXJlY3Rpb25Db2xsaWRlQ292ZXJhZ2Uobm9kZSwgbywgY29sbGlkZXMpIHtcbiAgICAgICAgaWYgKCFvLnJlY3QgfHwgIW5vZGUuX3JlY3QpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGxldCByMCA9IG5vZGUuX3JlY3Q7IC8vIHdoZXJlIHN0YXJ0ZWRcbiAgICAgICAgbGV0IHIgPSB7IC4uLm8ucmVjdCB9OyAvLyB3aGVyZSB3ZSBhcmVcbiAgICAgICAgLy8gdXBkYXRlIGRyYWdnZWQgcmVjdCB0byBzaG93IHdoZXJlIGl0J3MgY29taW5nIGZyb20gKGFib3ZlIG9yIGJlbG93LCBldGMuLi4pXG4gICAgICAgIGlmIChyLnkgPiByMC55KSB7XG4gICAgICAgICAgICByLmggKz0gci55IC0gcjAueTtcbiAgICAgICAgICAgIHIueSA9IHIwLnk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByLmggKz0gcjAueSAtIHIueTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoci54ID4gcjAueCkge1xuICAgICAgICAgICAgci53ICs9IHIueCAtIHIwLng7XG4gICAgICAgICAgICByLnggPSByMC54O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgci53ICs9IHIwLnggLSByLng7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGNvbGxpZGU7XG4gICAgICAgIGxldCBvdmVyTWF4ID0gMC41OyAvLyBuZWVkID41MCVcbiAgICAgICAgZm9yIChsZXQgbiBvZiBjb2xsaWRlcykge1xuICAgICAgICAgICAgaWYgKG4ubG9ja2VkIHx8ICFuLl9yZWN0KSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcjIgPSBuLl9yZWN0OyAvLyBvdmVybGFwcGluZyB0YXJnZXRcbiAgICAgICAgICAgIGxldCB5T3ZlciA9IE51bWJlci5NQVhfVkFMVUUsIHhPdmVyID0gTnVtYmVyLk1BWF9WQUxVRTtcbiAgICAgICAgICAgIC8vIGRlcGVuZGluZyBvbiB3aGljaCBzaWRlIHdlIHN0YXJ0ZWQgZnJvbSwgY29tcHV0ZSB0aGUgb3ZlcmxhcCAlIG9mIGNvdmVyYWdlXG4gICAgICAgICAgICAvLyAoZXg6IGZyb20gYWJvdmUvYmVsb3cgd2Ugb25seSBjb21wdXRlIHRoZSBtYXggaG9yaXpvbnRhbCBsaW5lIGNvdmVyYWdlKVxuICAgICAgICAgICAgaWYgKHIwLnkgPCByMi55KSB7IC8vIGZyb20gYWJvdmVcbiAgICAgICAgICAgICAgICB5T3ZlciA9ICgoci55ICsgci5oKSAtIHIyLnkpIC8gcjIuaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHIwLnkgKyByMC5oID4gcjIueSArIHIyLmgpIHsgLy8gZnJvbSBiZWxvd1xuICAgICAgICAgICAgICAgIHlPdmVyID0gKChyMi55ICsgcjIuaCkgLSByLnkpIC8gcjIuaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyMC54IDwgcjIueCkgeyAvLyBmcm9tIHRoZSBsZWZ0XG4gICAgICAgICAgICAgICAgeE92ZXIgPSAoKHIueCArIHIudykgLSByMi54KSAvIHIyLnc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChyMC54ICsgcjAudyA+IHIyLnggKyByMi53KSB7IC8vIGZyb20gdGhlIHJpZ2h0XG4gICAgICAgICAgICAgICAgeE92ZXIgPSAoKHIyLnggKyByMi53KSAtIHIueCkgLyByMi53O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG92ZXIgPSBNYXRoLm1pbih4T3ZlciwgeU92ZXIpO1xuICAgICAgICAgICAgaWYgKG92ZXIgPiBvdmVyTWF4KSB7XG4gICAgICAgICAgICAgICAgb3Zlck1heCA9IG92ZXI7XG4gICAgICAgICAgICAgICAgY29sbGlkZSA9IG47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgby5jb2xsaWRlID0gY29sbGlkZTsgLy8gc2F2ZSBpdCBzbyB3ZSBkb24ndCBoYXZlIHRvIGZpbmQgaXQgYWdhaW5cbiAgICAgICAgcmV0dXJuIGNvbGxpZGU7XG4gICAgfVxuICAgIC8qKiBkb2VzIGEgcGl4ZWwgY292ZXJhZ2UgcmV0dXJuaW5nIHRoZSBub2RlIHRoYXQgaGFzIHRoZSBtb3N0IGNvdmVyYWdlIGJ5IGFyZWEgKi9cbiAgICAvKlxuICAgIHByb3RlY3RlZCBjb2xsaWRlQ292ZXJhZ2UocjogR3JpZFN0YWNrUG9zaXRpb24sIGNvbGxpZGVzOiBHcmlkU3RhY2tOb2RlW10pOiB7Y29sbGlkZTogR3JpZFN0YWNrTm9kZSwgb3ZlcjogbnVtYmVyfSB7XG4gICAgICBsZXQgY29sbGlkZTogR3JpZFN0YWNrTm9kZTtcbiAgICAgIGxldCBvdmVyTWF4ID0gMDtcbiAgICAgIGNvbGxpZGVzLmZvckVhY2gobiA9PiB7XG4gICAgICAgIGlmIChuLmxvY2tlZCB8fCAhbi5fcmVjdCkgcmV0dXJuO1xuICAgICAgICBsZXQgb3ZlciA9IFV0aWxzLmFyZWFJbnRlcmNlcHQociwgbi5fcmVjdCk7XG4gICAgICAgIGlmIChvdmVyID4gb3Zlck1heCkge1xuICAgICAgICAgIG92ZXJNYXggPSBvdmVyO1xuICAgICAgICAgIGNvbGxpZGUgPSBuO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7Y29sbGlkZSwgb3Zlcjogb3Zlck1heH07XG4gICAgfVxuICAgICovXG4gICAgLyoqIGNhbGxlZCB0byBjYWNoZSB0aGUgbm9kZXMgcGl4ZWwgcmVjdGFuZ2xlcyB1c2VkIGZvciBjb2xsaXNpb24gZGV0ZWN0aW9uIGR1cmluZyBkcmFnICovXG4gICAgY2FjaGVSZWN0cyh3LCBoLCB0b3AsIHJpZ2h0LCBib3R0b20sIGxlZnQpIHtcbiAgICAgICAgdGhpcy5ub2Rlcy5mb3JFYWNoKG4gPT4gbi5fcmVjdCA9IHtcbiAgICAgICAgICAgIHk6IG4ueSAqIGggKyB0b3AsXG4gICAgICAgICAgICB4OiBuLnggKiB3ICsgbGVmdCxcbiAgICAgICAgICAgIHc6IG4udyAqIHcgLSBsZWZ0IC0gcmlnaHQsXG4gICAgICAgICAgICBoOiBuLmggKiBoIC0gdG9wIC0gYm90dG9tXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIGNhbGxlZCB0byBwb3NzaWJseSBzd2FwIGJldHdlZW4gMiBub2RlcyAoc2FtZSBzaXplIG9yIGNvbHVtbiwgbm90IGxvY2tlZCwgdG91Y2hpbmcpLCByZXR1cm5pbmcgdHJ1ZSBpZiBzdWNjZXNzZnVsICovXG4gICAgc3dhcChhLCBiKSB7XG4gICAgICAgIGlmICghYiB8fCBiLmxvY2tlZCB8fCAhYSB8fCBhLmxvY2tlZClcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgZnVuY3Rpb24gX2RvU3dhcCgpIHtcbiAgICAgICAgICAgIGxldCB4ID0gYi54LCB5ID0gYi55O1xuICAgICAgICAgICAgYi54ID0gYS54O1xuICAgICAgICAgICAgYi55ID0gYS55OyAvLyBiIC0+IGEgcG9zaXRpb25cbiAgICAgICAgICAgIGlmIChhLmggIT0gYi5oKSB7XG4gICAgICAgICAgICAgICAgYS54ID0geDtcbiAgICAgICAgICAgICAgICBhLnkgPSBiLnkgKyBiLmg7IC8vIGEgLT4gZ29lcyBhZnRlciBiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChhLncgIT0gYi53KSB7XG4gICAgICAgICAgICAgICAgYS54ID0gYi54ICsgYi53O1xuICAgICAgICAgICAgICAgIGEueSA9IHk7IC8vIGEgLT4gZ29lcyBhZnRlciBiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBhLnggPSB4O1xuICAgICAgICAgICAgICAgIGEueSA9IHk7IC8vIGEgLT4gb2xkIGIgcG9zaXRpb25cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGEuX2RpcnR5ID0gYi5fZGlydHkgPSB0cnVlO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHRvdWNoaW5nOyAvLyByZW1lbWJlciBpZiB3ZSBjYWxsZWQgaXQgKHZzIHVuZGVmaW5lZClcbiAgICAgICAgLy8gc2FtZSBzaXplIGFuZCBzYW1lIHJvdyBvciBjb2x1bW4sIGFuZCB0b3VjaGluZ1xuICAgICAgICBpZiAoYS53ID09PSBiLncgJiYgYS5oID09PSBiLmggJiYgKGEueCA9PT0gYi54IHx8IGEueSA9PT0gYi55KSAmJiAodG91Y2hpbmcgPSBVdGlscy5pc1RvdWNoaW5nKGEsIGIpKSlcbiAgICAgICAgICAgIHJldHVybiBfZG9Td2FwKCk7XG4gICAgICAgIGlmICh0b3VjaGluZyA9PT0gZmFsc2UpXG4gICAgICAgICAgICByZXR1cm47IC8vIElGRiByYW4gdGVzdCBhbmQgZmFpbCwgYmFpbCBvdXRcbiAgICAgICAgLy8gY2hlY2sgZm9yIHRha2luZyBzYW1lIGNvbHVtbnMgKGJ1dCBkaWZmZXJlbnQgaGVpZ2h0KSBhbmQgdG91Y2hpbmdcbiAgICAgICAgaWYgKGEudyA9PT0gYi53ICYmIGEueCA9PT0gYi54ICYmICh0b3VjaGluZyB8fCAodG91Y2hpbmcgPSBVdGlscy5pc1RvdWNoaW5nKGEsIGIpKSkpIHtcbiAgICAgICAgICAgIGlmIChiLnkgPCBhLnkpIHtcbiAgICAgICAgICAgICAgICBsZXQgdCA9IGE7XG4gICAgICAgICAgICAgICAgYSA9IGI7XG4gICAgICAgICAgICAgICAgYiA9IHQ7XG4gICAgICAgICAgICB9IC8vIHN3YXAgYSA8LT4gYiB2YXJzIHNvIGEgaXMgZmlyc3RcbiAgICAgICAgICAgIHJldHVybiBfZG9Td2FwKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRvdWNoaW5nID09PSBmYWxzZSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gY2hlY2sgaWYgdGFraW5nIHNhbWUgcm93IChidXQgZGlmZmVyZW50IHdpZHRoKSBhbmQgdG91Y2hpbmdcbiAgICAgICAgaWYgKGEuaCA9PT0gYi5oICYmIGEueSA9PT0gYi55ICYmICh0b3VjaGluZyB8fCAodG91Y2hpbmcgPSBVdGlscy5pc1RvdWNoaW5nKGEsIGIpKSkpIHtcbiAgICAgICAgICAgIGlmIChiLnggPCBhLngpIHtcbiAgICAgICAgICAgICAgICBsZXQgdCA9IGE7XG4gICAgICAgICAgICAgICAgYSA9IGI7XG4gICAgICAgICAgICAgICAgYiA9IHQ7XG4gICAgICAgICAgICB9IC8vIHN3YXAgYSA8LT4gYiB2YXJzIHNvIGEgaXMgZmlyc3RcbiAgICAgICAgICAgIHJldHVybiBfZG9Td2FwKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpc0FyZWFFbXB0eSh4LCB5LCB3LCBoKSB7XG4gICAgICAgIGxldCBubiA9IHsgeDogeCB8fCAwLCB5OiB5IHx8IDAsIHc6IHcgfHwgMSwgaDogaCB8fCAxIH07XG4gICAgICAgIHJldHVybiAhdGhpcy5jb2xsaWRlKG5uKTtcbiAgICB9XG4gICAgLyoqIHJlLWxheW91dCBncmlkIGl0ZW1zIHRvIHJlY2xhaW0gYW55IGVtcHR5IHNwYWNlIC0gb3B0aW9uYWxseSBrZWVwaW5nIHRoZSBzb3J0IG9yZGVyIGV4YWN0bHkgdGhlIHNhbWUgKCdsaXN0JyBtb2RlKSB2cyB0cnVseSBmaW5kaW5nIGFuIGVtcHR5IHNwYWNlcyAqL1xuICAgIGNvbXBhY3QobGF5b3V0ID0gJ2NvbXBhY3QnLCBkb1NvcnQgPSB0cnVlKSB7XG4gICAgICAgIGlmICh0aGlzLm5vZGVzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICBpZiAoZG9Tb3J0KVxuICAgICAgICAgICAgdGhpcy5zb3J0Tm9kZXMoKTtcbiAgICAgICAgY29uc3Qgd2FzQmF0Y2ggPSB0aGlzLmJhdGNoTW9kZTtcbiAgICAgICAgaWYgKCF3YXNCYXRjaClcbiAgICAgICAgICAgIHRoaXMuYmF0Y2hVcGRhdGUoKTtcbiAgICAgICAgY29uc3Qgd2FzQ29sdW1uUmVzaXplID0gdGhpcy5faW5Db2x1bW5SZXNpemU7XG4gICAgICAgIGlmICghd2FzQ29sdW1uUmVzaXplKVxuICAgICAgICAgICAgdGhpcy5faW5Db2x1bW5SZXNpemUgPSB0cnVlOyAvLyBmYXN0ZXIgYWRkTm9kZSgpXG4gICAgICAgIGxldCBjb3B5Tm9kZXMgPSB0aGlzLm5vZGVzO1xuICAgICAgICB0aGlzLm5vZGVzID0gW107IC8vIHByZXRlbmQgd2UgaGF2ZSBubyBub2RlcyB0byBjb25mbGljdCBsYXlvdXQgdG8gc3RhcnQgd2l0aC4uLlxuICAgICAgICBjb3B5Tm9kZXMuZm9yRWFjaCgobiwgaW5kZXgsIGxpc3QpID0+IHtcbiAgICAgICAgICAgIGxldCBhZnRlcjtcbiAgICAgICAgICAgIGlmICghbi5sb2NrZWQpIHtcbiAgICAgICAgICAgICAgICBuLmF1dG9Qb3NpdGlvbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgaWYgKGxheW91dCA9PT0gJ2xpc3QnICYmIGluZGV4KVxuICAgICAgICAgICAgICAgICAgICBhZnRlciA9IGxpc3RbaW5kZXggLSAxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuYWRkTm9kZShuLCBmYWxzZSwgYWZ0ZXIpOyAvLyAnZmFsc2UnIGZvciBhZGQgZXZlbnQgdHJpZ2dlclxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCF3YXNDb2x1bW5SZXNpemUpXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5faW5Db2x1bW5SZXNpemU7XG4gICAgICAgIGlmICghd2FzQmF0Y2gpXG4gICAgICAgICAgICB0aGlzLmJhdGNoVXBkYXRlKGZhbHNlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBlbmFibGUvZGlzYWJsZSBmbG9hdGluZyB3aWRnZXRzIChkZWZhdWx0OiBgZmFsc2VgKSBTZWUgW2V4YW1wbGVdKGh0dHA6Ly9ncmlkc3RhY2tqcy5jb20vZGVtby9mbG9hdC5odG1sKSAqL1xuICAgIHNldCBmbG9hdCh2YWwpIHtcbiAgICAgICAgaWYgKHRoaXMuX2Zsb2F0ID09PSB2YWwpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHRoaXMuX2Zsb2F0ID0gdmFsIHx8IGZhbHNlO1xuICAgICAgICBpZiAoIXZhbCkge1xuICAgICAgICAgICAgdGhpcy5fcGFja05vZGVzKCkuX25vdGlmeSgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKiBmbG9hdCBnZXR0ZXIgbWV0aG9kICovXG4gICAgZ2V0IGZsb2F0KCkgeyByZXR1cm4gdGhpcy5fZmxvYXQgfHwgZmFsc2U7IH1cbiAgICAvKiogc29ydCB0aGUgbm9kZXMgYXJyYXkgZnJvbSBmaXJzdCB0byBsYXN0LCBvciByZXZlcnNlLiBDYWxsZWQgZHVyaW5nIGNvbGxpc2lvbi9wbGFjZW1lbnQgdG8gZm9yY2UgYW4gb3JkZXIgKi9cbiAgICBzb3J0Tm9kZXMoZGlyID0gMSkge1xuICAgICAgICB0aGlzLm5vZGVzID0gVXRpbHMuc29ydCh0aGlzLm5vZGVzLCBkaXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCBjYWxsZWQgdG8gdG9wIGdyYXZpdHkgcGFjayB0aGUgaXRlbXMgYmFjayBPUiByZXZlcnQgYmFjayB0byBvcmlnaW5hbCBZIHBvc2l0aW9ucyB3aGVuIGZsb2F0aW5nICovXG4gICAgX3BhY2tOb2RlcygpIHtcbiAgICAgICAgaWYgKHRoaXMuYmF0Y2hNb2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNvcnROb2RlcygpOyAvLyBmaXJzdCB0byBsYXN0XG4gICAgICAgIGlmICh0aGlzLmZsb2F0KSB7XG4gICAgICAgICAgICAvLyByZXN0b3JlIG9yaWdpbmFsIFkgcG9zXG4gICAgICAgICAgICB0aGlzLm5vZGVzLmZvckVhY2gobiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKG4uX3VwZGF0aW5nIHx8IG4uX29yaWcgPT09IHVuZGVmaW5lZCB8fCBuLnkgPT09IG4uX29yaWcueSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIGxldCBuZXdZID0gbi55O1xuICAgICAgICAgICAgICAgIHdoaWxlIChuZXdZID4gbi5fb3JpZy55KSB7XG4gICAgICAgICAgICAgICAgICAgIC0tbmV3WTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvbGxpZGUgPSB0aGlzLmNvbGxpZGUobiwgeyB4OiBuLngsIHk6IG5ld1ksIHc6IG4udywgaDogbi5oIH0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbGxpZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG4uX2RpcnR5ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG4ueSA9IG5ld1k7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIHRvcCBncmF2aXR5IHBhY2tcbiAgICAgICAgICAgIHRoaXMubm9kZXMuZm9yRWFjaCgobiwgaSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChuLmxvY2tlZClcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIHdoaWxlIChuLnkgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBuZXdZID0gaSA9PT0gMCA/IDAgOiBuLnkgLSAxO1xuICAgICAgICAgICAgICAgICAgICBsZXQgY2FuQmVNb3ZlZCA9IGkgPT09IDAgfHwgIXRoaXMuY29sbGlkZShuLCB7IHg6IG4ueCwgeTogbmV3WSwgdzogbi53LCBoOiBuLmggfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY2FuQmVNb3ZlZClcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAvLyBOb3RlOiBtdXN0IGJlIGRpcnR5IChmcm9tIGxhc3QgcG9zaXRpb24pIGZvciBHcmlkU3RhY2s6Ok9uQ2hhbmdlIENCIHRvIHVwZGF0ZSBwb3NpdGlvbnNcbiAgICAgICAgICAgICAgICAgICAgLy8gYW5kIG1vdmUgaXRlbXMgYmFjay4gVGhlIHVzZXIgJ2NoYW5nZScgQ0Igc2hvdWxkIGRldGVjdCBjaGFuZ2VzIGZyb20gdGhlIG9yaWdpbmFsXG4gICAgICAgICAgICAgICAgICAgIC8vIHN0YXJ0aW5nIHBvc2l0aW9uIGluc3RlYWQuXG4gICAgICAgICAgICAgICAgICAgIG4uX2RpcnR5ID0gKG4ueSAhPT0gbmV3WSk7XG4gICAgICAgICAgICAgICAgICAgIG4ueSA9IG5ld1k7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIGdpdmVuIGEgcmFuZG9tIG5vZGUsIG1ha2VzIHN1cmUgaXQncyBjb29yZGluYXRlcy92YWx1ZXMgYXJlIHZhbGlkIGluIHRoZSBjdXJyZW50IGdyaWRcbiAgICAgKiBAcGFyYW0gbm9kZSB0byBhZGp1c3RcbiAgICAgKiBAcGFyYW0gcmVzaXppbmcgaWYgb3V0IG9mIGJvdW5kLCByZXNpemUgZG93biBvciBtb3ZlIGludG8gdGhlIGdyaWQgdG8gZml0ID9cbiAgICAgKi9cbiAgICBwcmVwYXJlTm9kZShub2RlLCByZXNpemluZykge1xuICAgICAgICBub2RlLl9pZCA9IG5vZGUuX2lkID8/IEdyaWRTdGFja0VuZ2luZS5faWRTZXErKztcbiAgICAgICAgLy8gaWYgd2UncmUgbWlzc2luZyBwb3NpdGlvbiwgaGF2ZSB0aGUgZ3JpZCBwb3NpdGlvbiB1cyBhdXRvbWF0aWNhbGx5IChiZWZvcmUgd2Ugc2V0IHRoZW0gdG8gMCwwKVxuICAgICAgICBpZiAobm9kZS54ID09PSB1bmRlZmluZWQgfHwgbm9kZS55ID09PSB1bmRlZmluZWQgfHwgbm9kZS54ID09PSBudWxsIHx8IG5vZGUueSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgbm9kZS5hdXRvUG9zaXRpb24gPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIGFzc2lnbiBkZWZhdWx0cyBmb3IgbWlzc2luZyByZXF1aXJlZCBmaWVsZHNcbiAgICAgICAgbGV0IGRlZmF1bHRzID0geyB4OiAwLCB5OiAwLCB3OiAxLCBoOiAxIH07XG4gICAgICAgIFV0aWxzLmRlZmF1bHRzKG5vZGUsIGRlZmF1bHRzKTtcbiAgICAgICAgaWYgKCFub2RlLmF1dG9Qb3NpdGlvbikge1xuICAgICAgICAgICAgZGVsZXRlIG5vZGUuYXV0b1Bvc2l0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGlmICghbm9kZS5ub1Jlc2l6ZSkge1xuICAgICAgICAgICAgZGVsZXRlIG5vZGUubm9SZXNpemU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFub2RlLm5vTW92ZSkge1xuICAgICAgICAgICAgZGVsZXRlIG5vZGUubm9Nb3ZlO1xuICAgICAgICB9XG4gICAgICAgIFV0aWxzLnNhbml0aXplTWluTWF4KG5vZGUpO1xuICAgICAgICAvLyBjaGVjayBmb3IgTmFOIChpbiBjYXNlIG1lc3NlZCB1cCBzdHJpbmdzIHdlcmUgcGFzc2VkLiBjYW4ndCBkbyBwYXJzZUludCgpIHx8IGRlZmF1bHRzLnggYWJvdmUgYXMgMCBpcyB2YWxpZCAjKVxuICAgICAgICBpZiAodHlwZW9mIG5vZGUueCA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgbm9kZS54ID0gTnVtYmVyKG5vZGUueCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBub2RlLnkgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIG5vZGUueSA9IE51bWJlcihub2RlLnkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygbm9kZS53ID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBub2RlLncgPSBOdW1iZXIobm9kZS53KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIG5vZGUuaCA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgbm9kZS5oID0gTnVtYmVyKG5vZGUuaCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzTmFOKG5vZGUueCkpIHtcbiAgICAgICAgICAgIG5vZGUueCA9IGRlZmF1bHRzLng7XG4gICAgICAgICAgICBub2RlLmF1dG9Qb3NpdGlvbiA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzTmFOKG5vZGUueSkpIHtcbiAgICAgICAgICAgIG5vZGUueSA9IGRlZmF1bHRzLnk7XG4gICAgICAgICAgICBub2RlLmF1dG9Qb3NpdGlvbiA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzTmFOKG5vZGUudykpIHtcbiAgICAgICAgICAgIG5vZGUudyA9IGRlZmF1bHRzLnc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzTmFOKG5vZGUuaCkpIHtcbiAgICAgICAgICAgIG5vZGUuaCA9IGRlZmF1bHRzLmg7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ub2RlQm91bmRGaXgobm9kZSwgcmVzaXppbmcpO1xuICAgICAgICByZXR1cm4gbm9kZTtcbiAgICB9XG4gICAgLyoqIHBhcnQyIG9mIHByZXBhcmluZyBhIG5vZGUgdG8gZml0IGluc2lkZSBvdXIgZ3JpZCAtIGNoZWNrcyBmb3IgeCx5LHcgZnJvbSBncmlkIGRpbWVuc2lvbnMgKi9cbiAgICBub2RlQm91bmRGaXgobm9kZSwgcmVzaXppbmcpIHtcbiAgICAgICAgbGV0IGJlZm9yZSA9IG5vZGUuX29yaWcgfHwgVXRpbHMuY29weVBvcyh7fSwgbm9kZSk7XG4gICAgICAgIGlmIChub2RlLm1heFcpIHtcbiAgICAgICAgICAgIG5vZGUudyA9IE1hdGgubWluKG5vZGUudywgbm9kZS5tYXhXKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm9kZS5tYXhIKSB7XG4gICAgICAgICAgICBub2RlLmggPSBNYXRoLm1pbihub2RlLmgsIG5vZGUubWF4SCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5vZGUubWluVyAmJiBub2RlLm1pblcgPD0gdGhpcy5jb2x1bW4pIHtcbiAgICAgICAgICAgIG5vZGUudyA9IE1hdGgubWF4KG5vZGUudywgbm9kZS5taW5XKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm9kZS5taW5IKSB7XG4gICAgICAgICAgICBub2RlLmggPSBNYXRoLm1heChub2RlLmgsIG5vZGUubWluSCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgdXNlciBsb2FkZWQgYSBsYXJnZXIgdGhhbiBhbGxvd2VkIHdpZGdldCBmb3IgY3VycmVudCAjIG9mIGNvbHVtbnMsXG4gICAgICAgIC8vIHJlbWVtYmVyIGl0J3MgcG9zaXRpb24gJiB3aWR0aCBzbyB3ZSBjYW4gcmVzdG9yZSBiYWNrICgxIC0+IDEyIGNvbHVtbikgIzE2NTUgIzE5ODVcbiAgICAgICAgLy8gSUZGIHdlJ3JlIG5vdCBpbiB0aGUgbWlkZGxlIG9mIGNvbHVtbiByZXNpemluZyFcbiAgICAgICAgY29uc3Qgc2F2ZU9yaWcgPSAobm9kZS54IHx8IDApICsgKG5vZGUudyB8fCAxKSA+IHRoaXMuY29sdW1uO1xuICAgICAgICBpZiAoc2F2ZU9yaWcgJiYgdGhpcy5jb2x1bW4gPCAxMiAmJiAhdGhpcy5faW5Db2x1bW5SZXNpemUgJiYgbm9kZS5faWQgJiYgdGhpcy5maW5kQ2FjaGVMYXlvdXQobm9kZSwgMTIpID09PSAtMSkge1xuICAgICAgICAgICAgbGV0IGNvcHkgPSB7IC4uLm5vZGUgfTsgLy8gbmVlZCBfaWQgKyBwb3NpdGlvbnNcbiAgICAgICAgICAgIGlmIChjb3B5LmF1dG9Qb3NpdGlvbiB8fCBjb3B5LnggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBjb3B5Lng7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGNvcHkueTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICBjb3B5LnggPSBNYXRoLm1pbigxMSwgY29weS54KTtcbiAgICAgICAgICAgIGNvcHkudyA9IE1hdGgubWluKDEyLCBjb3B5LncgfHwgMSk7XG4gICAgICAgICAgICB0aGlzLmNhY2hlT25lTGF5b3V0KGNvcHksIDEyKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm9kZS53ID4gdGhpcy5jb2x1bW4pIHtcbiAgICAgICAgICAgIG5vZGUudyA9IHRoaXMuY29sdW1uO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG5vZGUudyA8IDEpIHtcbiAgICAgICAgICAgIG5vZGUudyA9IDE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMubWF4Um93ICYmIG5vZGUuaCA+IHRoaXMubWF4Um93KSB7XG4gICAgICAgICAgICBub2RlLmggPSB0aGlzLm1heFJvdztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChub2RlLmggPCAxKSB7XG4gICAgICAgICAgICBub2RlLmggPSAxO1xuICAgICAgICB9XG4gICAgICAgIGlmIChub2RlLnggPCAwKSB7XG4gICAgICAgICAgICBub2RlLnggPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChub2RlLnkgPCAwKSB7XG4gICAgICAgICAgICBub2RlLnkgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChub2RlLnggKyBub2RlLncgPiB0aGlzLmNvbHVtbikge1xuICAgICAgICAgICAgaWYgKHJlc2l6aW5nKSB7XG4gICAgICAgICAgICAgICAgbm9kZS53ID0gdGhpcy5jb2x1bW4gLSBub2RlLng7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBub2RlLnggPSB0aGlzLmNvbHVtbiAtIG5vZGUudztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5tYXhSb3cgJiYgbm9kZS55ICsgbm9kZS5oID4gdGhpcy5tYXhSb3cpIHtcbiAgICAgICAgICAgIGlmIChyZXNpemluZykge1xuICAgICAgICAgICAgICAgIG5vZGUuaCA9IHRoaXMubWF4Um93IC0gbm9kZS55O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbm9kZS55ID0gdGhpcy5tYXhSb3cgLSBub2RlLmg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFVdGlscy5zYW1lUG9zKG5vZGUsIGJlZm9yZSkpIHtcbiAgICAgICAgICAgIG5vZGUuX2RpcnR5ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIHJldHVybnMgYSBsaXN0IG9mIG1vZGlmaWVkIG5vZGVzIGZyb20gdGhlaXIgb3JpZ2luYWwgdmFsdWVzICovXG4gICAgZ2V0RGlydHlOb2Rlcyh2ZXJpZnkpIHtcbiAgICAgICAgLy8gY29tcGFyZSBvcmlnaW5hbCB4LHksdyxoIGluc3RlYWQgYXMgX2RpcnR5IGNhbiBiZSBhIHRlbXBvcmFyeSBzdGF0ZVxuICAgICAgICBpZiAodmVyaWZ5KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ub2Rlcy5maWx0ZXIobiA9PiBuLl9kaXJ0eSAmJiAhVXRpbHMuc2FtZVBvcyhuLCBuLl9vcmlnKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMubm9kZXMuZmlsdGVyKG4gPT4gbi5fZGlydHkpO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsIGNhbGwgdGhpcyB0byBjYWxsIG9uQ2hhbmdlIGNhbGxiYWNrIHdpdGggZGlydHkgbm9kZXMgc28gRE9NIGNhbiBiZSB1cGRhdGVkICovXG4gICAgX25vdGlmeShyZW1vdmVkTm9kZXMpIHtcbiAgICAgICAgaWYgKHRoaXMuYmF0Y2hNb2RlIHx8ICF0aGlzLm9uQ2hhbmdlKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIGxldCBkaXJ0eU5vZGVzID0gKHJlbW92ZWROb2RlcyB8fCBbXSkuY29uY2F0KHRoaXMuZ2V0RGlydHlOb2RlcygpKTtcbiAgICAgICAgdGhpcy5vbkNoYW5nZShkaXJ0eU5vZGVzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgcmVtb3ZlIGRpcnR5IGFuZCBsYXN0IHRyaWVkIGluZm8gKi9cbiAgICBjbGVhbk5vZGVzKCkge1xuICAgICAgICBpZiAodGhpcy5iYXRjaE1vZGUpXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgdGhpcy5ub2Rlcy5mb3JFYWNoKG4gPT4ge1xuICAgICAgICAgICAgZGVsZXRlIG4uX2RpcnR5O1xuICAgICAgICAgICAgZGVsZXRlIG4uX2xhc3RUcmllZDtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsIGNhbGxlZCB0byBzYXZlIGluaXRpYWwgcG9zaXRpb24vc2l6ZSB0byB0cmFjayByZWFsIGRpcnR5IHN0YXRlLlxuICAgICAqIE5vdGU6IHNob3VsZCBiZSBjYWxsZWQgcmlnaHQgYWZ0ZXIgd2UgY2FsbCBjaGFuZ2UgZXZlbnQgKHNvIG5leHQgQVBJIGlzIGNhbiBkZXRlY3QgY2hhbmdlcylcbiAgICAgKiBhcyB3ZWxsIGFzIHJpZ2h0IGJlZm9yZSB3ZSBzdGFydCBtb3ZlL3Jlc2l6ZS9lbnRlciAoc28gd2UgY2FuIHJlc3RvcmUgaXRlbXMgdG8gcHJldiB2YWx1ZXMpICovXG4gICAgc2F2ZUluaXRpYWwoKSB7XG4gICAgICAgIHRoaXMubm9kZXMuZm9yRWFjaChuID0+IHtcbiAgICAgICAgICAgIG4uX29yaWcgPSBVdGlscy5jb3B5UG9zKHt9LCBuKTtcbiAgICAgICAgICAgIGRlbGV0ZSBuLl9kaXJ0eTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuX2hhc0xvY2tlZCA9IHRoaXMubm9kZXMuc29tZShuID0+IG4ubG9ja2VkKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgcmVzdG9yZSBhbGwgdGhlIG5vZGVzIGJhY2sgdG8gaW5pdGlhbCB2YWx1ZXMgKGNhbGxlZCB3aGVuIHdlIGxlYXZlKSAqL1xuICAgIHJlc3RvcmVJbml0aWFsKCkge1xuICAgICAgICB0aGlzLm5vZGVzLmZvckVhY2gobiA9PiB7XG4gICAgICAgICAgICBpZiAoVXRpbHMuc2FtZVBvcyhuLCBuLl9vcmlnKSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICBVdGlscy5jb3B5UG9zKG4sIG4uX29yaWcpO1xuICAgICAgICAgICAgbi5fZGlydHkgPSB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fbm90aWZ5KCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogZmluZCB0aGUgZmlyc3QgYXZhaWxhYmxlIGVtcHR5IHNwb3QgZm9yIHRoZSBnaXZlbiBub2RlIHdpZHRoL2hlaWdodCwgdXBkYXRpbmcgdGhlIHgseSBhdHRyaWJ1dGVzLiByZXR1cm4gdHJ1ZSBpZiBmb3VuZC5cbiAgICAgKiBvcHRpb25hbGx5IHlvdSBjYW4gcGFzcyB5b3VyIG93biBleGlzdGluZyBub2RlIGxpc3QgYW5kIGNvbHVtbiBjb3VudCwgb3RoZXJ3aXNlIGRlZmF1bHRzIHRvIHRoYXQgZW5naW5lIGRhdGEuXG4gICAgICogT3B0aW9uYWxseSBwYXNzIGEgd2lkZ2V0IHRvIHN0YXJ0IHNlYXJjaCBBRlRFUiwgbWVhbmluZyB0aGUgb3JkZXIgd2lsbCByZW1haW4gdGhlIHNhbWUgYnV0IHBvc3NpYmx5IGhhdmUgZW1wdHkgc2xvdHMgd2Ugc2tpcHBlZFxuICAgICAqL1xuICAgIGZpbmRFbXB0eVBvc2l0aW9uKG5vZGUsIG5vZGVMaXN0ID0gdGhpcy5ub2RlcywgY29sdW1uID0gdGhpcy5jb2x1bW4sIGFmdGVyKSB7XG4gICAgICAgIGxldCBzdGFydCA9IGFmdGVyID8gYWZ0ZXIueSAqIGNvbHVtbiArIChhZnRlci54ICsgYWZ0ZXIudykgOiAwO1xuICAgICAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IHN0YXJ0OyAhZm91bmQ7ICsraSkge1xuICAgICAgICAgICAgbGV0IHggPSBpICUgY29sdW1uO1xuICAgICAgICAgICAgbGV0IHkgPSBNYXRoLmZsb29yKGkgLyBjb2x1bW4pO1xuICAgICAgICAgICAgaWYgKHggKyBub2RlLncgPiBjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBib3ggPSB7IHgsIHksIHc6IG5vZGUudywgaDogbm9kZS5oIH07XG4gICAgICAgICAgICBpZiAoIW5vZGVMaXN0LmZpbmQobiA9PiBVdGlscy5pc0ludGVyY2VwdGVkKGJveCwgbikpKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGUueCAhPT0geCB8fCBub2RlLnkgIT09IHkpXG4gICAgICAgICAgICAgICAgICAgIG5vZGUuX2RpcnR5ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBub2RlLnggPSB4O1xuICAgICAgICAgICAgICAgIG5vZGUueSA9IHk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIG5vZGUuYXV0b1Bvc2l0aW9uO1xuICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZm91bmQ7XG4gICAgfVxuICAgIC8qKiBjYWxsIHRvIGFkZCB0aGUgZ2l2ZW4gbm9kZSB0byBvdXIgbGlzdCwgZml4aW5nIGNvbGxpc2lvbiBhbmQgcmUtcGFja2luZyAqL1xuICAgIGFkZE5vZGUobm9kZSwgdHJpZ2dlckFkZEV2ZW50ID0gZmFsc2UsIGFmdGVyKSB7XG4gICAgICAgIGxldCBkdXAgPSB0aGlzLm5vZGVzLmZpbmQobiA9PiBuLl9pZCA9PT0gbm9kZS5faWQpO1xuICAgICAgICBpZiAoZHVwKVxuICAgICAgICAgICAgcmV0dXJuIGR1cDsgLy8gcHJldmVudCBpbnNlcnRpbmcgdHdpY2UhIHJldHVybiBpdCBpbnN0ZWFkLlxuICAgICAgICAvLyBza2lwIHByZXBhcmVOb2RlIGlmIHdlJ3JlIGluIG1pZGRsZSBvZiBjb2x1bW4gcmVzaXplIChub3QgbmV3KSBidXQgZG8gY2hlY2sgZm9yIGJvdW5kcyFcbiAgICAgICAgdGhpcy5faW5Db2x1bW5SZXNpemUgPyB0aGlzLm5vZGVCb3VuZEZpeChub2RlKSA6IHRoaXMucHJlcGFyZU5vZGUobm9kZSk7XG4gICAgICAgIGRlbGV0ZSBub2RlLl90ZW1wb3JhcnlSZW1vdmVkO1xuICAgICAgICBkZWxldGUgbm9kZS5fcmVtb3ZlRE9NO1xuICAgICAgICBsZXQgc2tpcENvbGxpc2lvbjtcbiAgICAgICAgaWYgKG5vZGUuYXV0b1Bvc2l0aW9uICYmIHRoaXMuZmluZEVtcHR5UG9zaXRpb24obm9kZSwgdGhpcy5ub2RlcywgdGhpcy5jb2x1bW4sIGFmdGVyKSkge1xuICAgICAgICAgICAgZGVsZXRlIG5vZGUuYXV0b1Bvc2l0aW9uOyAvLyBmb3VuZCBvdXIgc2xvdFxuICAgICAgICAgICAgc2tpcENvbGxpc2lvbiA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ub2Rlcy5wdXNoKG5vZGUpO1xuICAgICAgICBpZiAodHJpZ2dlckFkZEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLmFkZGVkTm9kZXMucHVzaChub2RlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXNraXBDb2xsaXNpb24pXG4gICAgICAgICAgICB0aGlzLl9maXhDb2xsaXNpb25zKG5vZGUpO1xuICAgICAgICBpZiAoIXRoaXMuYmF0Y2hNb2RlKSB7XG4gICAgICAgICAgICB0aGlzLl9wYWNrTm9kZXMoKS5fbm90aWZ5KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfVxuICAgIHJlbW92ZU5vZGUobm9kZSwgcmVtb3ZlRE9NID0gdHJ1ZSwgdHJpZ2dlckV2ZW50ID0gZmFsc2UpIHtcbiAgICAgICAgaWYgKCF0aGlzLm5vZGVzLmZpbmQobiA9PiBuLl9pZCA9PT0gbm9kZS5faWQpKSB7XG4gICAgICAgICAgICAvLyBURVNUIGNvbnNvbGUubG9nKGBFcnJvcjogR3JpZFN0YWNrRW5naW5lLnJlbW92ZU5vZGUoKSBub2RlLl9pZD0ke25vZGUuX2lkfSBub3QgZm91bmQhYClcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0cmlnZ2VyRXZlbnQpIHsgLy8gd2Ugd2FpdCB1bnRpbCBmaW5hbCBkcm9wIHRvIG1hbnVhbGx5IHRyYWNrIHJlbW92ZWQgaXRlbXMgKHJhdGhlciB0aGFuIGR1cmluZyBkcmFnKVxuICAgICAgICAgICAgdGhpcy5yZW1vdmVkTm9kZXMucHVzaChub2RlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVtb3ZlRE9NKVxuICAgICAgICAgICAgbm9kZS5fcmVtb3ZlRE9NID0gdHJ1ZTsgLy8gbGV0IENCIHJlbW92ZSBhY3R1YWwgSFRNTCAodXNlZCB0byBzZXQgX2lkIHRvIG51bGwsIGJ1dCB0aGVuIHdlIGxvb3NlIGxheW91dCBpbmZvKVxuICAgICAgICAvLyBkb24ndCB1c2UgJ2Zhc3RlcicgLnNwbGljZShmaW5kSW5kZXgoKSwxKSBpbiBjYXNlIG5vZGUgaXNuJ3QgaW4gb3VyIGxpc3QsIG9yIGluIG11bHRpcGxlIHRpbWVzLlxuICAgICAgICB0aGlzLm5vZGVzID0gdGhpcy5ub2Rlcy5maWx0ZXIobiA9PiBuLl9pZCAhPT0gbm9kZS5faWQpO1xuICAgICAgICBpZiAoIW5vZGUuX2lzQWJvdXRUb1JlbW92ZSlcbiAgICAgICAgICAgIHRoaXMuX3BhY2tOb2RlcygpOyAvLyBpZiBkcmFnZ2VkIG91dCwgbm8gbmVlZCB0byByZWxheW91dCBhcyBhbHJlYWR5IGRvbmUuLi5cbiAgICAgICAgdGhpcy5fbm90aWZ5KFtub2RlXSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICByZW1vdmVBbGwocmVtb3ZlRE9NID0gdHJ1ZSwgdHJpZ2dlckV2ZW50ID0gdHJ1ZSkge1xuICAgICAgICBkZWxldGUgdGhpcy5fbGF5b3V0cztcbiAgICAgICAgaWYgKCF0aGlzLm5vZGVzLmxlbmd0aClcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICByZW1vdmVET00gJiYgdGhpcy5ub2Rlcy5mb3JFYWNoKG4gPT4gbi5fcmVtb3ZlRE9NID0gdHJ1ZSk7IC8vIGxldCBDQiByZW1vdmUgYWN0dWFsIEhUTUwgKHVzZWQgdG8gc2V0IF9pZCB0byBudWxsLCBidXQgdGhlbiB3ZSBsb29zZSBsYXlvdXQgaW5mbylcbiAgICAgICAgY29uc3QgcmVtb3ZlZE5vZGVzID0gdGhpcy5ub2RlcztcbiAgICAgICAgdGhpcy5yZW1vdmVkTm9kZXMgPSB0cmlnZ2VyRXZlbnQgPyByZW1vdmVkTm9kZXMgOiBbXTtcbiAgICAgICAgdGhpcy5ub2RlcyA9IFtdO1xuICAgICAgICByZXR1cm4gdGhpcy5fbm90aWZ5KHJlbW92ZWROb2Rlcyk7XG4gICAgfVxuICAgIC8qKiBjaGVja3MgaWYgaXRlbSBjYW4gYmUgbW92ZWQgKGxheW91dCBjb25zdHJhaW4pIHZzIG1vdmVOb2RlKCksIHJldHVybmluZyB0cnVlIGlmIHdhcyBhYmxlIHRvIG1vdmUuXG4gICAgICogSW4gbW9yZSBjb21wbGljYXRlZCBjYXNlcyAobWF4Um93KSBpdCB3aWxsIGF0dGVtcHQgYXQgbW92aW5nIHRoZSBpdGVtIGFuZCBmaXhpbmdcbiAgICAgKiBvdGhlcnMgaW4gYSBjbG9uZSBmaXJzdCwgdGhlbiBhcHBseSB0aG9zZSBjaGFuZ2VzIGlmIHN0aWxsIHdpdGhpbiBzcGVjcy4gKi9cbiAgICBtb3ZlTm9kZUNoZWNrKG5vZGUsIG8pIHtcbiAgICAgICAgLy8gaWYgKG5vZGUubG9ja2VkKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGlmICghdGhpcy5jaGFuZ2VkUG9zQ29uc3RyYWluKG5vZGUsIG8pKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBvLnBhY2sgPSB0cnVlO1xuICAgICAgICAvLyBzaW1wbGVyIGNhc2U6IG1vdmUgaXRlbSBkaXJlY3RseS4uLlxuICAgICAgICBpZiAoIXRoaXMubWF4Um93KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tb3ZlTm9kZShub2RlLCBvKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBjb21wbGV4IGNhc2U6IGNyZWF0ZSBhIGNsb25lIHdpdGggTk8gbWF4Um93ICh3aWxsIGNoZWNrIGZvciBvdXQgb2YgYm91bmRzIGF0IHRoZSBlbmQpXG4gICAgICAgIGxldCBjbG9uZWROb2RlO1xuICAgICAgICBsZXQgY2xvbmUgPSBuZXcgR3JpZFN0YWNrRW5naW5lKHtcbiAgICAgICAgICAgIGNvbHVtbjogdGhpcy5jb2x1bW4sXG4gICAgICAgICAgICBmbG9hdDogdGhpcy5mbG9hdCxcbiAgICAgICAgICAgIG5vZGVzOiB0aGlzLm5vZGVzLm1hcChuID0+IHtcbiAgICAgICAgICAgICAgICBpZiAobi5faWQgPT09IG5vZGUuX2lkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsb25lZE5vZGUgPSB7IC4uLm4gfTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNsb25lZE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLm4gfTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIWNsb25lZE5vZGUpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIC8vIGNoZWNrIGlmIHdlJ3JlIGNvdmVyaW5nIDUwJSBjb2xsaXNpb24gYW5kIGNvdWxkIG1vdmUsIHdoaWxlIHN0aWxsIGJlaW5nIHVuZGVyIG1heFJvdyBvciBhdCBsZWFzdCBub3QgbWFraW5nIGl0IHdvcnNlXG4gICAgICAgIC8vIChjYXNlIHdoZXJlIHdpZGdldCB3YXMgc29tZWhvdyBhZGRlZCBwYXN0IG91ciBtYXggIzI0NDkpXG4gICAgICAgIGxldCBjYW5Nb3ZlID0gY2xvbmUubW92ZU5vZGUoY2xvbmVkTm9kZSwgbykgJiYgY2xvbmUuZ2V0Um93KCkgPD0gTWF0aC5tYXgodGhpcy5nZXRSb3coKSwgdGhpcy5tYXhSb3cpO1xuICAgICAgICAvLyBlbHNlIGNoZWNrIGlmIHdlIGNhbiBmb3JjZSBhIHN3YXAgKGZsb2F0PXRydWUsIG9yIGRpZmZlcmVudCBzaGFwZXMpIG9uIG5vbi1yZXNpemVcbiAgICAgICAgaWYgKCFjYW5Nb3ZlICYmICFvLnJlc2l6aW5nICYmIG8uY29sbGlkZSkge1xuICAgICAgICAgICAgbGV0IGNvbGxpZGUgPSBvLmNvbGxpZGUuZWwuZ3JpZHN0YWNrTm9kZTsgLy8gZmluZCB0aGUgc291cmNlIG5vZGUgdGhlIGNsb25lIGNvbGxpZGVkIHdpdGggYXQgNTAlXG4gICAgICAgICAgICBpZiAodGhpcy5zd2FwKG5vZGUsIGNvbGxpZGUpKSB7IC8vIHN3YXBzIGFuZCBtYXJrIGRpcnR5XG4gICAgICAgICAgICAgICAgdGhpcy5fbm90aWZ5KCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFjYW5Nb3ZlKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAvLyBpZiBjbG9uZSB3YXMgYWJsZSB0byBtb3ZlLCBjb3B5IHRob3NlIG1vZHMgb3ZlciB0byB1cyBub3cgaW5zdGVhZCBvZiBjYWxsZXIgdHJ5aW5nIHRvIGRvIHRoaXMgYWxsIG92ZXIhXG4gICAgICAgIC8vIE5vdGU6IHdlIGNhbid0IHVzZSB0aGUgbGlzdCBkaXJlY3RseSBhcyBlbGVtZW50cyBhbmQgb3RoZXIgcGFydHMgcG9pbnQgdG8gYWN0dWFsIG5vZGUsIHNvIGNvcHkgY29udGVudFxuICAgICAgICBjbG9uZS5ub2Rlcy5maWx0ZXIobiA9PiBuLl9kaXJ0eSkuZm9yRWFjaChjID0+IHtcbiAgICAgICAgICAgIGxldCBuID0gdGhpcy5ub2Rlcy5maW5kKGEgPT4gYS5faWQgPT09IGMuX2lkKTtcbiAgICAgICAgICAgIGlmICghbilcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICBVdGlscy5jb3B5UG9zKG4sIGMpO1xuICAgICAgICAgICAgbi5fZGlydHkgPSB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fbm90aWZ5KCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICAvKiogcmV0dXJuIHRydWUgaWYgY2FuIGZpdCBpbiBncmlkIGhlaWdodCBjb25zdHJhaW4gb25seSAoYWx3YXlzIHRydWUgaWYgbm8gbWF4Um93KSAqL1xuICAgIHdpbGxJdEZpdChub2RlKSB7XG4gICAgICAgIGRlbGV0ZSBub2RlLl93aWxsRml0UG9zO1xuICAgICAgICBpZiAoIXRoaXMubWF4Um93KVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIC8vIGNyZWF0ZSBhIGNsb25lIHdpdGggTk8gbWF4Um93IGFuZCBjaGVjayBpZiBzdGlsbCB3aXRoaW4gc2l6ZVxuICAgICAgICBsZXQgY2xvbmUgPSBuZXcgR3JpZFN0YWNrRW5naW5lKHtcbiAgICAgICAgICAgIGNvbHVtbjogdGhpcy5jb2x1bW4sXG4gICAgICAgICAgICBmbG9hdDogdGhpcy5mbG9hdCxcbiAgICAgICAgICAgIG5vZGVzOiB0aGlzLm5vZGVzLm1hcChuID0+IHsgcmV0dXJuIHsgLi4ubiB9OyB9KVxuICAgICAgICB9KTtcbiAgICAgICAgbGV0IG4gPSB7IC4uLm5vZGUgfTsgLy8gY2xvbmUgbm9kZSBzbyB3ZSBkb24ndCBtb2QgYW55IHNldHRpbmdzIG9uIGl0IGJ1dCBoYXZlIGZ1bGwgYXV0b1Bvc2l0aW9uIGFuZCBtaW4vbWF4IGFzIHdlbGwhICMxNjg3XG4gICAgICAgIHRoaXMuY2xlYW51cE5vZGUobik7XG4gICAgICAgIGRlbGV0ZSBuLmVsO1xuICAgICAgICBkZWxldGUgbi5faWQ7XG4gICAgICAgIGRlbGV0ZSBuLmNvbnRlbnQ7XG4gICAgICAgIGRlbGV0ZSBuLmdyaWQ7XG4gICAgICAgIGNsb25lLmFkZE5vZGUobik7XG4gICAgICAgIGlmIChjbG9uZS5nZXRSb3coKSA8PSB0aGlzLm1heFJvdykge1xuICAgICAgICAgICAgbm9kZS5fd2lsbEZpdFBvcyA9IFV0aWxzLmNvcHlQb3Moe30sIG4pO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvKiogdHJ1ZSBpZiB4LHkgb3IgdyxoIGFyZSBkaWZmZXJlbnQgYWZ0ZXIgY2xhbXBpbmcgdG8gbWluL21heCAqL1xuICAgIGNoYW5nZWRQb3NDb25zdHJhaW4obm9kZSwgcCkge1xuICAgICAgICAvLyBmaXJzdCBtYWtlIHN1cmUgdyxoIGFyZSBzZXQgZm9yIGNhbGxlclxuICAgICAgICBwLncgPSBwLncgfHwgbm9kZS53O1xuICAgICAgICBwLmggPSBwLmggfHwgbm9kZS5oO1xuICAgICAgICBpZiAobm9kZS54ICE9PSBwLnggfHwgbm9kZS55ICE9PSBwLnkpXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgLy8gY2hlY2sgY29uc3RyYWluZWQgdyxoXG4gICAgICAgIGlmIChub2RlLm1heFcpIHtcbiAgICAgICAgICAgIHAudyA9IE1hdGgubWluKHAudywgbm9kZS5tYXhXKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm9kZS5tYXhIKSB7XG4gICAgICAgICAgICBwLmggPSBNYXRoLm1pbihwLmgsIG5vZGUubWF4SCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5vZGUubWluVykge1xuICAgICAgICAgICAgcC53ID0gTWF0aC5tYXgocC53LCBub2RlLm1pblcpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChub2RlLm1pbkgpIHtcbiAgICAgICAgICAgIHAuaCA9IE1hdGgubWF4KHAuaCwgbm9kZS5taW5IKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKG5vZGUudyAhPT0gcC53IHx8IG5vZGUuaCAhPT0gcC5oKTtcbiAgICB9XG4gICAgLyoqIHJldHVybiB0cnVlIGlmIHRoZSBwYXNzZWQgaW4gbm9kZSB3YXMgYWN0dWFsbHkgbW92ZWQgKGNoZWNrcyBmb3Igbm8tb3AgYW5kIGxvY2tlZCkgKi9cbiAgICBtb3ZlTm9kZShub2RlLCBvKSB7XG4gICAgICAgIGlmICghbm9kZSB8fCAvKm5vZGUubG9ja2VkIHx8Ki8gIW8pXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGxldCB3YXNVbmRlZmluZWRQYWNrO1xuICAgICAgICBpZiAoby5wYWNrID09PSB1bmRlZmluZWQgJiYgIXRoaXMuYmF0Y2hNb2RlKSB7XG4gICAgICAgICAgICB3YXNVbmRlZmluZWRQYWNrID0gby5wYWNrID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBjb25zdHJhaW4gdGhlIHBhc3NlZCBpbiB2YWx1ZXMgYW5kIGNoZWNrIGlmIHdlJ3JlIHN0aWxsIGNoYW5naW5nIG91ciBub2RlXG4gICAgICAgIGlmICh0eXBlb2Ygby54ICE9PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgby54ID0gbm9kZS54O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygby55ICE9PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgby55ID0gbm9kZS55O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygby53ICE9PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgby53ID0gbm9kZS53O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygby5oICE9PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgby5oID0gbm9kZS5oO1xuICAgICAgICB9XG4gICAgICAgIGxldCByZXNpemluZyA9IChub2RlLncgIT09IG8udyB8fCBub2RlLmggIT09IG8uaCk7XG4gICAgICAgIGxldCBubiA9IFV0aWxzLmNvcHlQb3Moe30sIG5vZGUsIHRydWUpOyAvLyBnZXQgbWluL21heCBvdXQgZmlyc3QsIHRoZW4gb3B0IHBvc2l0aW9ucyBuZXh0XG4gICAgICAgIFV0aWxzLmNvcHlQb3Mobm4sIG8pO1xuICAgICAgICB0aGlzLm5vZGVCb3VuZEZpeChubiwgcmVzaXppbmcpO1xuICAgICAgICBVdGlscy5jb3B5UG9zKG8sIG5uKTtcbiAgICAgICAgaWYgKCFvLmZvcmNlQ29sbGlkZSAmJiBVdGlscy5zYW1lUG9zKG5vZGUsIG8pKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBsZXQgcHJldlBvcyA9IFV0aWxzLmNvcHlQb3Moe30sIG5vZGUpO1xuICAgICAgICAvLyBjaGVjayBpZiB3ZSB3aWxsIG5lZWQgdG8gZml4IGNvbGxpc2lvbiBhdCBvdXIgbmV3IGxvY2F0aW9uXG4gICAgICAgIGxldCBjb2xsaWRlcyA9IHRoaXMuY29sbGlkZUFsbChub2RlLCBubiwgby5za2lwKTtcbiAgICAgICAgbGV0IG5lZWRUb01vdmUgPSB0cnVlO1xuICAgICAgICBpZiAoY29sbGlkZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBsZXQgYWN0aXZlRHJhZyA9IG5vZGUuX21vdmluZyAmJiAhby5uZXN0ZWQ7XG4gICAgICAgICAgICAvLyBjaGVjayB0byBtYWtlIHN1cmUgd2UgYWN0dWFsbHkgY29sbGlkZWQgb3ZlciA1MCUgc3VyZmFjZSBhcmVhIHdoaWxlIGRyYWdnaW5nXG4gICAgICAgICAgICBsZXQgY29sbGlkZSA9IGFjdGl2ZURyYWcgPyB0aGlzLmRpcmVjdGlvbkNvbGxpZGVDb3ZlcmFnZShub2RlLCBvLCBjb2xsaWRlcykgOiBjb2xsaWRlc1swXTtcbiAgICAgICAgICAgIC8vIGlmIHdlJ3JlIGVuYWJsaW5nIGNyZWF0aW9uIG9mIHN1Yi1ncmlkcyBvbiB0aGUgZmx5LCBzZWUgaWYgd2UncmUgY292ZXJpbmcgODAlIG9mIGVpdGhlciBvbmUsIGlmIHdlIGRpZG4ndCBhbHJlYWR5IGRvIHRoYXRcbiAgICAgICAgICAgIGlmIChhY3RpdmVEcmFnICYmIGNvbGxpZGUgJiYgbm9kZS5ncmlkPy5vcHRzPy5zdWJHcmlkRHluYW1pYyAmJiAhbm9kZS5ncmlkLl9pc1RlbXApIHtcbiAgICAgICAgICAgICAgICBsZXQgb3ZlciA9IFV0aWxzLmFyZWFJbnRlcmNlcHQoby5yZWN0LCBjb2xsaWRlLl9yZWN0KTtcbiAgICAgICAgICAgICAgICBsZXQgYTEgPSBVdGlscy5hcmVhKG8ucmVjdCk7XG4gICAgICAgICAgICAgICAgbGV0IGEyID0gVXRpbHMuYXJlYShjb2xsaWRlLl9yZWN0KTtcbiAgICAgICAgICAgICAgICBsZXQgcGVyYyA9IG92ZXIgLyAoYTEgPCBhMiA/IGExIDogYTIpO1xuICAgICAgICAgICAgICAgIGlmIChwZXJjID4gLjgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sbGlkZS5ncmlkLm1ha2VTdWJHcmlkKGNvbGxpZGUuZWwsIHVuZGVmaW5lZCwgbm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbGxpZGUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbGxpZGUpIHtcbiAgICAgICAgICAgICAgICBuZWVkVG9Nb3ZlID0gIXRoaXMuX2ZpeENvbGxpc2lvbnMobm9kZSwgbm4sIGNvbGxpZGUsIG8pOyAvLyBjaGVjayBpZiBhbHJlYWR5IG1vdmVkLi4uXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBuZWVkVG9Nb3ZlID0gZmFsc2U7IC8vIHdlIGRpZG4ndCBjb3ZlciA+NTAlIGZvciBhIG1vdmUsIHNraXAuLi5cbiAgICAgICAgICAgICAgICBpZiAod2FzVW5kZWZpbmVkUGFjaylcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG8ucGFjaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBub3cgbW92ZSAodG8gdGhlIG9yaWdpbmFsIGFzayB2cyB0aGUgY29sbGlzaW9uIHZlcnNpb24gd2hpY2ggbWlnaHQgZGlmZmVyKSBhbmQgcmVwYWNrIHRoaW5nc1xuICAgICAgICBpZiAobmVlZFRvTW92ZSkge1xuICAgICAgICAgICAgbm9kZS5fZGlydHkgPSB0cnVlO1xuICAgICAgICAgICAgVXRpbHMuY29weVBvcyhub2RlLCBubik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG8ucGFjaykge1xuICAgICAgICAgICAgdGhpcy5fcGFja05vZGVzKClcbiAgICAgICAgICAgICAgICAuX25vdGlmeSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAhVXRpbHMuc2FtZVBvcyhub2RlLCBwcmV2UG9zKTsgLy8gcGFjayBtaWdodCBoYXZlIG1vdmVkIHRoaW5ncyBiYWNrXG4gICAgfVxuICAgIGdldFJvdygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubm9kZXMucmVkdWNlKChyb3csIG4pID0+IE1hdGgubWF4KHJvdywgbi55ICsgbi5oKSwgMCk7XG4gICAgfVxuICAgIGJlZ2luVXBkYXRlKG5vZGUpIHtcbiAgICAgICAgaWYgKCFub2RlLl91cGRhdGluZykge1xuICAgICAgICAgICAgbm9kZS5fdXBkYXRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgZGVsZXRlIG5vZGUuX3NraXBEb3duO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmJhdGNoTW9kZSlcbiAgICAgICAgICAgICAgICB0aGlzLnNhdmVJbml0aWFsKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGVuZFVwZGF0ZSgpIHtcbiAgICAgICAgbGV0IG4gPSB0aGlzLm5vZGVzLmZpbmQobiA9PiBuLl91cGRhdGluZyk7XG4gICAgICAgIGlmIChuKSB7XG4gICAgICAgICAgICBkZWxldGUgbi5fdXBkYXRpbmc7XG4gICAgICAgICAgICBkZWxldGUgbi5fc2tpcERvd247XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBzYXZlcyBhIGNvcHkgb2YgdGhlIGxhcmdlc3QgY29sdW1uIGxheW91dCAoZWcgMTIgZXZlbiB3aGVuIHJlbmRlcmluZyBvbmVDb2x1bW5Nb2RlKSBzbyB3ZSBkb24ndCBsb29zZSBvcmlnIGxheW91dCxcbiAgICAgKiByZXR1cm5pbmcgYSBsaXN0IG9mIHdpZGdldHMgZm9yIHNlcmlhbGl6YXRpb24gKi9cbiAgICBzYXZlKHNhdmVFbGVtZW50ID0gdHJ1ZSwgc2F2ZUNCKSB7XG4gICAgICAgIC8vIHVzZSB0aGUgaGlnaGVzdCBsYXlvdXQgZm9yIGFueSBzYXZlZCBpbmZvIHNvIHdlIGNhbiBoYXZlIGZ1bGwgZGV0YWlsIG9uIHJlbG9hZCAjMTg0OVxuICAgICAgICBsZXQgbGVuID0gdGhpcy5fbGF5b3V0cz8ubGVuZ3RoO1xuICAgICAgICBsZXQgbGF5b3V0ID0gbGVuICYmIHRoaXMuY29sdW1uICE9PSAobGVuIC0gMSkgPyB0aGlzLl9sYXlvdXRzW2xlbiAtIDFdIDogbnVsbDtcbiAgICAgICAgbGV0IGxpc3QgPSBbXTtcbiAgICAgICAgdGhpcy5zb3J0Tm9kZXMoKTtcbiAgICAgICAgdGhpcy5ub2Rlcy5mb3JFYWNoKG4gPT4ge1xuICAgICAgICAgICAgbGV0IHdsID0gbGF5b3V0Py5maW5kKGwgPT4gbC5faWQgPT09IG4uX2lkKTtcbiAgICAgICAgICAgIC8vIHVzZSBsYXlvdXQgaW5mbyBmaWVsZHMgaW5zdGVhZCBpZiBzZXRcbiAgICAgICAgICAgIGxldCB3ID0geyAuLi5uLCAuLi4od2wgfHwge30pIH07XG4gICAgICAgICAgICBVdGlscy5yZW1vdmVJbnRlcm5hbEZvclNhdmUodywgIXNhdmVFbGVtZW50KTtcbiAgICAgICAgICAgIGlmIChzYXZlQ0IpXG4gICAgICAgICAgICAgICAgc2F2ZUNCKG4sIHcpO1xuICAgICAgICAgICAgbGlzdC5wdXNoKHcpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGxpc3Q7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgY2FsbGVkIHdoZW5ldmVyIGEgbm9kZSBpcyBhZGRlZCBvciBtb3ZlZCAtIHVwZGF0ZXMgdGhlIGNhY2hlZCBsYXlvdXRzICovXG4gICAgbGF5b3V0c05vZGVzQ2hhbmdlKG5vZGVzKSB7XG4gICAgICAgIGlmICghdGhpcy5fbGF5b3V0cyB8fCB0aGlzLl9pbkNvbHVtblJlc2l6ZSlcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAvLyByZW1vdmUgc21hbGxlciBsYXlvdXRzIC0gd2Ugd2lsbCByZS1nZW5lcmF0ZSB0aG9zZSBvbiB0aGUgZmx5Li4uIGxhcmdlciBvbmVzIG5lZWQgdG8gdXBkYXRlXG4gICAgICAgIHRoaXMuX2xheW91dHMuZm9yRWFjaCgobGF5b3V0LCBjb2x1bW4pID0+IHtcbiAgICAgICAgICAgIGlmICghbGF5b3V0IHx8IGNvbHVtbiA9PT0gdGhpcy5jb2x1bW4pXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICBpZiAoY29sdW1uIDwgdGhpcy5jb2x1bW4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9sYXlvdXRzW2NvbHVtbl0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyB3ZSBzYXZlIHRoZSBvcmlnaW5hbCB4LHksdyAoaCBpc24ndCBjYWNoZWQpIHRvIHNlZSB3aGF0IGFjdHVhbGx5IGNoYW5nZWQgdG8gcHJvcGFnYXRlIGJldHRlci5cbiAgICAgICAgICAgICAgICAvLyBOT1RFOiB3ZSBkb24ndCBuZWVkIHRvIGNoZWNrIGFnYWluc3Qgb3V0IG9mIGJvdW5kIHNjYWxpbmcvbW92aW5nIGFzIHRoYXQgd2lsbCBiZSBkb25lIHdoZW4gdXNpbmcgdGhvc2UgY2FjaGUgdmFsdWVzLiAjMTc4NVxuICAgICAgICAgICAgICAgIGxldCByYXRpbyA9IGNvbHVtbiAvIHRoaXMuY29sdW1uO1xuICAgICAgICAgICAgICAgIG5vZGVzLmZvckVhY2gobm9kZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghbm9kZS5fb3JpZylcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsgLy8gZGlkbid0IGNoYW5nZSAobmV3bHkgYWRkZWQgPylcbiAgICAgICAgICAgICAgICAgICAgbGV0IG4gPSBsYXlvdXQuZmluZChsID0+IGwuX2lkID09PSBub2RlLl9pZCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghbilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsgLy8gbm8gY2FjaGUgZm9yIG5ldyBub2Rlcy4gV2lsbCB1c2UgdGhvc2UgdmFsdWVzLlxuICAgICAgICAgICAgICAgICAgICAvLyBZIGNoYW5nZWQsIHB1c2ggZG93biBzYW1lIGFtb3VudFxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBkZXRlY3QgZG9pbmcgaXRlbSAnc3dhcHMnIHdpbGwgaGVscCBpbnN0ZWFkIG9mIG1vdmUgKGVzcGVjaWFsbHkgaW4gMSBjb2x1bW4gbW9kZSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKG4ueSA+PSAwICYmIG5vZGUueSAhPT0gbm9kZS5fb3JpZy55KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuLnkgKz0gKG5vZGUueSAtIG5vZGUuX29yaWcueSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gWCBjaGFuZ2VkLCBzY2FsZSBmcm9tIG5ldyBwb3NpdGlvblxuICAgICAgICAgICAgICAgICAgICBpZiAobm9kZS54ICE9PSBub2RlLl9vcmlnLngpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG4ueCA9IE1hdGgucm91bmQobm9kZS54ICogcmF0aW8pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIHdpZHRoIGNoYW5nZWQsIHNjYWxlIGZyb20gbmV3IHdpZHRoXG4gICAgICAgICAgICAgICAgICAgIGlmIChub2RlLncgIT09IG5vZGUuX29yaWcudykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbi53ID0gTWF0aC5yb3VuZChub2RlLncgKiByYXRpbyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gLi4uaGVpZ2h0IGFsd2F5cyBjYXJyaWVzIG92ZXIgZnJvbSBjYWNoZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbCBDYWxsZWQgdG8gc2NhbGUgdGhlIHdpZGdldCB3aWR0aCAmIHBvc2l0aW9uIHVwL2Rvd24gYmFzZWQgb24gdGhlIGNvbHVtbiBjaGFuZ2UuXG4gICAgICogTm90ZSB3ZSBzdG9yZSBwcmV2aW91cyBsYXlvdXRzIChlc3BlY2lhbGx5IG9yaWdpbmFsIG9uZXMpIHRvIG1ha2UgaXQgcG9zc2libGUgdG8gZ29cbiAgICAgKiBmcm9tIHNheSAxMiAtPiAxIC0+IDEyIGFuZCBnZXQgYmFjayB0byB3aGVyZSB3ZSB3ZXJlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHByZXZDb2x1bW4gcHJldmlvdXMgbnVtYmVyIG9mIGNvbHVtbnNcbiAgICAgKiBAcGFyYW0gY29sdW1uICBuZXcgY29sdW1uIG51bWJlclxuICAgICAqIEBwYXJhbSBsYXlvdXQgc3BlY2lmeSB0aGUgdHlwZSBvZiByZS1sYXlvdXQgdGhhdCB3aWxsIGhhcHBlbiAocG9zaXRpb24sIHNpemUsIGV0Yy4uLikuXG4gICAgICogTm90ZTogaXRlbXMgd2lsbCBuZXZlciBiZSBvdXRzaWRlIG9mIHRoZSBjdXJyZW50IGNvbHVtbiBib3VuZGFyaWVzLiBkZWZhdWx0IChtb3ZlU2NhbGUpLiBJZ25vcmVkIGZvciAxIGNvbHVtblxuICAgICAqL1xuICAgIGNvbHVtbkNoYW5nZWQocHJldkNvbHVtbiwgY29sdW1uLCBsYXlvdXQgPSAnbW92ZVNjYWxlJykge1xuICAgICAgICBpZiAoIXRoaXMubm9kZXMubGVuZ3RoIHx8ICFjb2x1bW4gfHwgcHJldkNvbHVtbiA9PT0gY29sdW1uKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIC8vIGluIHRoaXMgbW9kZSBubyBsYXlvdXQgaXMgZG9uZSB3aGF0c29ldmVyLCB1cCB0byB0aGUgY2FsbGVyIHRvIGhhbmRsZSBpdFxuICAgICAgICBpZiAobGF5b3V0ID09PSAnbm9uZScpXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgLy8gc2ltcGxlciBzaG9ydGN1dHMgbGF5b3V0c1xuICAgICAgICBjb25zdCBkb0NvbXBhY3QgPSBsYXlvdXQgPT09ICdjb21wYWN0JyB8fCBsYXlvdXQgPT09ICdsaXN0JztcbiAgICAgICAgaWYgKGRvQ29tcGFjdCkge1xuICAgICAgICAgICAgdGhpcy5zb3J0Tm9kZXMoMSk7IC8vIHNvcnQgd2l0aCBvcmlnaW5hbCBsYXlvdXQgb25jZSBhbmQgb25seSBvbmNlIChuZXcgY29sdW1uIHdpbGwgYWZmZWN0IG9yZGVyIG90aGVyd2lzZSlcbiAgICAgICAgfVxuICAgICAgICAvLyBjYWNoZSB0aGUgY3VycmVudCBsYXlvdXQgaW4gY2FzZSB0aGV5IHdhbnQgdG8gZ28gYmFjayAobGlrZSAxMiAtPiAxIC0+IDEyKSBhcyBpdCByZXF1aXJlcyBvcmlnaW5hbCBkYXRhIElGRiB3ZSdyZSBzaXppbmcgZG93biAoc2VlIGJlbG93KVxuICAgICAgICBpZiAoY29sdW1uIDwgcHJldkNvbHVtbilcbiAgICAgICAgICAgIHRoaXMuY2FjaGVMYXlvdXQodGhpcy5ub2RlcywgcHJldkNvbHVtbik7XG4gICAgICAgIHRoaXMuYmF0Y2hVcGRhdGUoKTsgLy8gZG8gdGhpcyBFQVJMWSBhcyBpdCB3aWxsIGNhbGwgc2F2ZUluaXRpYWwoKSBzbyB3ZSBjYW4gZGV0ZWN0IHdoZXJlIHdlIHN0YXJ0ZWQgZm9yIF9kaXJ0eSBhbmQgY29sbGlzaW9uXG4gICAgICAgIGxldCBuZXdOb2RlcyA9IFtdO1xuICAgICAgICBsZXQgbm9kZXMgPSBkb0NvbXBhY3QgPyB0aGlzLm5vZGVzIDogVXRpbHMuc29ydCh0aGlzLm5vZGVzLCAtMSk7IC8vIGN1cnJlbnQgY29sdW1uIHJldmVyc2Ugc29ydGluZyBzbyB3ZSBjYW4gaW5zZXJ0IGxhc3QgdG8gZnJvbnQgKGxpbWl0IGNvbGxpc2lvbilcbiAgICAgICAgLy8gc2VlIGlmIHdlIGhhdmUgY2FjaGVkIHByZXZpb3VzIGxheW91dCBJRkYgd2UgYXJlIGdvaW5nIHVwIGluIHNpemUgKHJlc3RvcmUpIG90aGVyd2lzZSBhbHdheXNcbiAgICAgICAgLy8gZ2VuZXJhdGUgbmV4dCBzaXplIGRvd24gZnJvbSB3aGVyZSB3ZSBhcmUgKGxvb2tzIG1vcmUgbmF0dXJhbCBhcyB5b3UgZ3JhZHVhbGx5IHNpemUgZG93bikuXG4gICAgICAgIGlmIChjb2x1bW4gPiBwcmV2Q29sdW1uICYmIHRoaXMuX2xheW91dHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGNhY2hlTm9kZXMgPSB0aGlzLl9sYXlvdXRzW2NvbHVtbl0gfHwgW107XG4gICAgICAgICAgICAvLyAuLi5pZiBub3QsIHN0YXJ0IHdpdGggdGhlIGxhcmdlc3QgbGF5b3V0IChpZiBub3QgYWxyZWFkeSB0aGVyZSkgYXMgZG93bi1zY2FsaW5nIGlzIG1vcmUgYWNjdXJhdGVcbiAgICAgICAgICAgIC8vIGJ5IHByZXRlbmRpbmcgd2UgY2FtZSBmcm9tIHRoYXQgbGFyZ2VyIGNvbHVtbiBieSBhc3NpZ25pbmcgdGhvc2UgdmFsdWVzIGFzIHN0YXJ0aW5nIHBvaW50XG4gICAgICAgICAgICBsZXQgbGFzdEluZGV4ID0gdGhpcy5fbGF5b3V0cy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgaWYgKCFjYWNoZU5vZGVzLmxlbmd0aCAmJiBwcmV2Q29sdW1uICE9PSBsYXN0SW5kZXggJiYgdGhpcy5fbGF5b3V0c1tsYXN0SW5kZXhdPy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBwcmV2Q29sdW1uID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgIHRoaXMuX2xheW91dHNbbGFzdEluZGV4XS5mb3JFYWNoKGNhY2hlTm9kZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBuID0gbm9kZXMuZmluZChuID0+IG4uX2lkID09PSBjYWNoZU5vZGUuX2lkKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0aWxsIGN1cnJlbnQsIHVzZSBjYWNoZSBpbmZvIHBvc2l0aW9uc1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkb0NvbXBhY3QgJiYgIWNhY2hlTm9kZS5hdXRvUG9zaXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuLnggPSBjYWNoZU5vZGUueCA/PyBuLng7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbi55ID0gY2FjaGVOb2RlLnkgPz8gbi55O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbi53ID0gY2FjaGVOb2RlLncgPz8gbi53O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhY2hlTm9kZS54ID09IHVuZGVmaW5lZCB8fCBjYWNoZU5vZGUueSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4uYXV0b1Bvc2l0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgd2UgZm91bmQgY2FjaGUgcmUtdXNlIHRob3NlIG5vZGVzIHRoYXQgYXJlIHN0aWxsIGN1cnJlbnRcbiAgICAgICAgICAgIGNhY2hlTm9kZXMuZm9yRWFjaChjYWNoZU5vZGUgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBqID0gbm9kZXMuZmluZEluZGV4KG4gPT4gbi5faWQgPT09IGNhY2hlTm9kZS5faWQpO1xuICAgICAgICAgICAgICAgIGlmIChqICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuID0gbm9kZXNbal07XG4gICAgICAgICAgICAgICAgICAgIC8vIHN0aWxsIGN1cnJlbnQsIHVzZSBjYWNoZSBpbmZvIHBvc2l0aW9uc1xuICAgICAgICAgICAgICAgICAgICBpZiAoZG9Db21wYWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuLncgPSBjYWNoZU5vZGUudzsgLy8gb25seSB3IGlzIHVzZWQsIGFuZCBkb24ndCB0cmltIHRoZSBsaXN0XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhY2hlTm9kZS5hdXRvUG9zaXRpb24gfHwgaXNOYU4oY2FjaGVOb2RlLngpIHx8IGlzTmFOKGNhY2hlTm9kZS55KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maW5kRW1wdHlQb3NpdGlvbihjYWNoZU5vZGUsIG5ld05vZGVzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNhY2hlTm9kZS5hdXRvUG9zaXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG4ueCA9IGNhY2hlTm9kZS54ID8/IG4ueDtcbiAgICAgICAgICAgICAgICAgICAgICAgIG4ueSA9IGNhY2hlTm9kZS55ID8/IG4ueTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG4udyA9IGNhY2hlTm9kZS53ID8/IG4udztcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGVzLnB1c2gobik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbm9kZXMuc3BsaWNlKGosIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIG11Y2ggc2ltcGxlciBsYXlvdXQgdGhhdCBqdXN0IGNvbXBhY3RzXG4gICAgICAgIGlmIChkb0NvbXBhY3QpIHtcbiAgICAgICAgICAgIHRoaXMuY29tcGFjdChsYXlvdXQsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIC4uLmFuZCBhZGQgYW55IGV4dHJhIG5vbi1jYWNoZWQgb25lc1xuICAgICAgICAgICAgaWYgKG5vZGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbGF5b3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGxheW91dChjb2x1bW4sIHByZXZDb2x1bW4sIG5ld05vZGVzLCBub2Rlcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsZXQgcmF0aW8gPSBkb0NvbXBhY3QgPyAxIDogY29sdW1uIC8gcHJldkNvbHVtbjtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG1vdmUgPSAobGF5b3V0ID09PSAnbW92ZScgfHwgbGF5b3V0ID09PSAnbW92ZVNjYWxlJyk7XG4gICAgICAgICAgICAgICAgICAgIGxldCBzY2FsZSA9IChsYXlvdXQgPT09ICdzY2FsZScgfHwgbGF5b3V0ID09PSAnbW92ZVNjYWxlJyk7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVzLmZvckVhY2gobm9kZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBOT1RFOiB4ICsgdyBjb3VsZCBiZSBvdXRzaWRlIG9mIHRoZSBncmlkLCBidXQgYWRkTm9kZSgpIGJlbG93IHdpbGwgaGFuZGxlIHRoYXRcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUueCA9IChjb2x1bW4gPT09IDEgPyAwIDogKG1vdmUgPyBNYXRoLnJvdW5kKG5vZGUueCAqIHJhdGlvKSA6IE1hdGgubWluKG5vZGUueCwgY29sdW1uIC0gMSkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUudyA9ICgoY29sdW1uID09PSAxIHx8IHByZXZDb2x1bW4gPT09IDEpID8gMSA6IHNjYWxlID8gKE1hdGgucm91bmQobm9kZS53ICogcmF0aW8pIHx8IDEpIDogKE1hdGgubWluKG5vZGUudywgY29sdW1uKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZXMucHVzaChub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZmluYWxseSByZS1sYXlvdXQgdGhlbSBpbiByZXZlcnNlIG9yZGVyICh0byBnZXQgY29ycmVjdCBwbGFjZW1lbnQpXG4gICAgICAgICAgICBuZXdOb2RlcyA9IFV0aWxzLnNvcnQobmV3Tm9kZXMsIC0xKTtcbiAgICAgICAgICAgIHRoaXMuX2luQ29sdW1uUmVzaXplID0gdHJ1ZTsgLy8gcHJldmVudCBjYWNoZSB1cGRhdGVcbiAgICAgICAgICAgIHRoaXMubm9kZXMgPSBbXTsgLy8gcHJldGVuZCB3ZSBoYXZlIG5vIG5vZGVzIHRvIHN0YXJ0IHdpdGggKGFkZCgpIHdpbGwgdXNlIHNhbWUgc3RydWN0dXJlcykgdG8gc2ltcGxpZnkgbGF5b3V0XG4gICAgICAgICAgICBuZXdOb2Rlcy5mb3JFYWNoKG5vZGUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkTm9kZShub2RlLCBmYWxzZSk7IC8vICdmYWxzZScgZm9yIGFkZCBldmVudCB0cmlnZ2VyXG4gICAgICAgICAgICAgICAgZGVsZXRlIG5vZGUuX29yaWc7IC8vIG1ha2Ugc3VyZSB0aGUgY29tbWl0IGRvZXNuJ3QgdHJ5IHRvIHJlc3RvcmUgdGhpbmdzIGJhY2sgdG8gb3JpZ2luYWxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubm9kZXMuZm9yRWFjaChuID0+IGRlbGV0ZSBuLl9vcmlnKTsgLy8gY2xlYXIgX29yaWcgYmVmb3JlIGJhdGNoPWZhbHNlIHNvIGl0IGRvZXNuJ3QgaGFuZGxlIGZsb2F0PXRydWUgcmVzdG9yZVxuICAgICAgICB0aGlzLmJhdGNoVXBkYXRlKGZhbHNlLCAhZG9Db21wYWN0KTtcbiAgICAgICAgZGVsZXRlIHRoaXMuX2luQ29sdW1uUmVzaXplO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogY2FsbCB0byBjYWNoZSB0aGUgZ2l2ZW4gbGF5b3V0IGludGVybmFsbHkgdG8gdGhlIGdpdmVuIGxvY2F0aW9uIHNvIHdlIGNhbiByZXN0b3JlIGJhY2sgd2hlbiBjb2x1bW4gY2hhbmdlcyBzaXplXG4gICAgICogQHBhcmFtIG5vZGVzIGxpc3Qgb2Ygbm9kZXNcbiAgICAgKiBAcGFyYW0gY29sdW1uIGNvcnJlc3BvbmRpbmcgY29sdW1uIGluZGV4IHRvIHNhdmUgaXQgdW5kZXJcbiAgICAgKiBAcGFyYW0gY2xlYXIgaWYgdHJ1ZSwgd2lsbCBmb3JjZSBvdGhlciBjYWNoZXMgdG8gYmUgcmVtb3ZlZCAoZGVmYXVsdCBmYWxzZSlcbiAgICAgKi9cbiAgICBjYWNoZUxheW91dChub2RlcywgY29sdW1uLCBjbGVhciA9IGZhbHNlKSB7XG4gICAgICAgIGxldCBjb3B5ID0gW107XG4gICAgICAgIG5vZGVzLmZvckVhY2goKG4sIGkpID0+IHtcbiAgICAgICAgICAgIC8vIG1ha2Ugc3VyZSB3ZSBoYXZlIGFuIGlkIGluIGNhc2UgdGhpcyBpcyBuZXcgbGF5b3V0LCBlbHNlIHJlLXVzZSBpZCBhbHJlYWR5IHNldFxuICAgICAgICAgICAgaWYgKG4uX2lkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBleGlzdGluZyA9IG4uaWQgPyB0aGlzLm5vZGVzLmZpbmQobjIgPT4gbjIuaWQgPT09IG4uaWQpIDogdW5kZWZpbmVkOyAvLyBmaW5kIGV4aXN0aW5nIG5vZGUgdXNpbmcgdXNlcnMgaWRcbiAgICAgICAgICAgICAgICBuLl9pZCA9IGV4aXN0aW5nPy5faWQgPz8gR3JpZFN0YWNrRW5naW5lLl9pZFNlcSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29weVtpXSA9IHsgeDogbi54LCB5OiBuLnksIHc6IG4udywgX2lkOiBuLl9pZCB9OyAvLyBvbmx5IHRoaW5nIHdlIGNoYW5nZSBpcyB4LHksdyBhbmQgaWQgdG8gZmluZCBpdCBiYWNrXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLl9sYXlvdXRzID0gY2xlYXIgPyBbXSA6IHRoaXMuX2xheW91dHMgfHwgW107IC8vIHVzZSBhcnJheSB0byBmaW5kIGxhcmdlciBxdWlja1xuICAgICAgICB0aGlzLl9sYXlvdXRzW2NvbHVtbl0gPSBjb3B5O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogY2FsbCB0byBjYWNoZSB0aGUgZ2l2ZW4gbm9kZSBsYXlvdXQgaW50ZXJuYWxseSB0byB0aGUgZ2l2ZW4gbG9jYXRpb24gc28gd2UgY2FuIHJlc3RvcmUgYmFjayB3aGVuIGNvbHVtbiBjaGFuZ2VzIHNpemVcbiAgICAgKiBAcGFyYW0gbm9kZSBzaW5nbGUgbm9kZSB0byBjYWNoZVxuICAgICAqIEBwYXJhbSBjb2x1bW4gY29ycmVzcG9uZGluZyBjb2x1bW4gaW5kZXggdG8gc2F2ZSBpdCB1bmRlclxuICAgICAqL1xuICAgIGNhY2hlT25lTGF5b3V0KG4sIGNvbHVtbikge1xuICAgICAgICBuLl9pZCA9IG4uX2lkID8/IEdyaWRTdGFja0VuZ2luZS5faWRTZXErKztcbiAgICAgICAgbGV0IGwgPSB7IHg6IG4ueCwgeTogbi55LCB3OiBuLncsIF9pZDogbi5faWQgfTtcbiAgICAgICAgaWYgKG4uYXV0b1Bvc2l0aW9uIHx8IG4ueCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBkZWxldGUgbC54O1xuICAgICAgICAgICAgZGVsZXRlIGwueTtcbiAgICAgICAgICAgIGlmIChuLmF1dG9Qb3NpdGlvbilcbiAgICAgICAgICAgICAgICBsLmF1dG9Qb3NpdGlvbiA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fbGF5b3V0cyA9IHRoaXMuX2xheW91dHMgfHwgW107XG4gICAgICAgIHRoaXMuX2xheW91dHNbY29sdW1uXSA9IHRoaXMuX2xheW91dHNbY29sdW1uXSB8fCBbXTtcbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5maW5kQ2FjaGVMYXlvdXQobiwgY29sdW1uKTtcbiAgICAgICAgaWYgKGluZGV4ID09PSAtMSlcbiAgICAgICAgICAgIHRoaXMuX2xheW91dHNbY29sdW1uXS5wdXNoKGwpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aGlzLl9sYXlvdXRzW2NvbHVtbl1baW5kZXhdID0gbDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGZpbmRDYWNoZUxheW91dChuLCBjb2x1bW4pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xheW91dHM/Lltjb2x1bW5dPy5maW5kSW5kZXgobCA9PiBsLl9pZCA9PT0gbi5faWQpID8/IC0xO1xuICAgIH1cbiAgICByZW1vdmVOb2RlRnJvbUxheW91dENhY2hlKG4pIHtcbiAgICAgICAgaWYgKCF0aGlzLl9sYXlvdXRzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLl9sYXlvdXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSB0aGlzLmZpbmRDYWNoZUxheW91dChuLCBpKTtcbiAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9sYXlvdXRzW2ldLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqIGNhbGxlZCB0byByZW1vdmUgYWxsIGludGVybmFsIHZhbHVlcyBidXQgdGhlIF9pZCAqL1xuICAgIGNsZWFudXBOb2RlKG5vZGUpIHtcbiAgICAgICAgZm9yIChsZXQgcHJvcCBpbiBub2RlKSB7XG4gICAgICAgICAgICBpZiAocHJvcFswXSA9PT0gJ18nICYmIHByb3AgIT09ICdfaWQnKVxuICAgICAgICAgICAgICAgIGRlbGV0ZSBub2RlW3Byb3BdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn1cbi8qKiBAaW50ZXJuYWwgdW5pcXVlIGdsb2JhbCBpbnRlcm5hbCBfaWQgY291bnRlciAqL1xuR3JpZFN0YWNrRW5naW5lLl9pZFNlcSA9IDA7XG5leHBvcnQgeyBHcmlkU3RhY2tFbmdpbmUgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWdyaWRzdGFjay1lbmdpbmUuanMubWFwIiwiLyohXG4gKiBHcmlkU3RhY2sgMTAuMS4yXG4gKiBodHRwczovL2dyaWRzdGFja2pzLmNvbS9cbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjEtMjAyMiBBbGFpbiBEdW1lc255XG4gKiBzZWUgcm9vdCBsaWNlbnNlIGh0dHBzOi8vZ2l0aHViLmNvbS9ncmlkc3RhY2svZ3JpZHN0YWNrLmpzL3RyZWUvbWFzdGVyL0xJQ0VOU0VcbiAqL1xuaW1wb3J0IHsgR3JpZFN0YWNrRW5naW5lIH0gZnJvbSAnLi9ncmlkc3RhY2stZW5naW5lJztcbmltcG9ydCB7IFV0aWxzLCBvYnNvbGV0ZSB9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHsgZ3JpZERlZmF1bHRzLCBkcmFnSW5EZWZhdWx0T3B0aW9ucyB9IGZyb20gJy4vdHlwZXMnO1xuLypcbiAqIGFuZCBpbmNsdWRlIEQmRCBieSBkZWZhdWx0XG4gKiBUT0RPOiB3aGlsZSB3ZSBjb3VsZCBnZW5lcmF0ZSBhIGdyaWRzdGFjay1zdGF0aWMuanMgYXQgc21hbGxlciBzaXplIC0gc2F2ZXMgYWJvdXQgMzFrICg0MWsgLT4gNzJrKVxuICogSSBkb24ndCBrbm93IGhvdyB0byBnZW5lcmF0ZSB0aGUgREQgb25seSBjb2RlIGF0IHRoZSByZW1haW5pbmcgMzFrIHRvIGRlbGF5IGxvYWQgYXMgY29kZSBkZXBlbmRzIG9uIEdyaWRzdGFjay50c1xuICogYWxzbyBpdCBjYXVzZWQgbG9hZGluZyBpc3N1ZXMgaW4gcHJvZCAtIHNlZSBodHRwczovL2dpdGh1Yi5jb20vZ3JpZHN0YWNrL2dyaWRzdGFjay5qcy9pc3N1ZXMvMjAzOVxuICovXG5pbXBvcnQgeyBEREdyaWRTdGFjayB9IGZyb20gJy4vZGQtZ3JpZHN0YWNrJztcbmltcG9ydCB7IGlzVG91Y2ggfSBmcm9tICcuL2RkLXRvdWNoJztcbmltcG9ydCB7IERETWFuYWdlciB9IGZyb20gJy4vZGQtbWFuYWdlcic7XG5jb25zdCBkZCA9IG5ldyBEREdyaWRTdGFjaztcbi8vIGV4cG9ydCBhbGwgZGVwZW5kZW50IGZpbGUgYXMgd2VsbCB0byBtYWtlIGl0IGVhc2llciBmb3IgdXNlcnMgdG8ganVzdCBpbXBvcnQgdGhlIG1haW4gZmlsZVxuZXhwb3J0ICogZnJvbSAnLi90eXBlcyc7XG5leHBvcnQgKiBmcm9tICcuL3V0aWxzJztcbmV4cG9ydCAqIGZyb20gJy4vZ3JpZHN0YWNrLWVuZ2luZSc7XG5leHBvcnQgKiBmcm9tICcuL2RkLWdyaWRzdGFjayc7XG4vKipcbiAqIE1haW4gZ3JpZHN0YWNrIGNsYXNzIC0geW91IHdpbGwgbmVlZCB0byBjYWxsIGBHcmlkU3RhY2suaW5pdCgpYCBmaXJzdCB0byBpbml0aWFsaXplIHlvdXIgZ3JpZC5cbiAqIE5vdGU6IHlvdXIgZ3JpZCBlbGVtZW50cyBNVVNUIGhhdmUgdGhlIGZvbGxvd2luZyBjbGFzc2VzIGZvciB0aGUgQ1NTIGxheW91dCB0byB3b3JrOlxuICogQGV4YW1wbGVcbiAqIDxkaXYgY2xhc3M9XCJncmlkLXN0YWNrXCI+XG4gKiAgIDxkaXYgY2xhc3M9XCJncmlkLXN0YWNrLWl0ZW1cIj5cbiAqICAgICA8ZGl2IGNsYXNzPVwiZ3JpZC1zdGFjay1pdGVtLWNvbnRlbnRcIj5JdGVtIDE8L2Rpdj5cbiAqICAgPC9kaXY+XG4gKiA8L2Rpdj5cbiAqL1xuY2xhc3MgR3JpZFN0YWNrIHtcbiAgICAvKipcbiAgICAgKiBpbml0aWFsaXppbmcgdGhlIEhUTUwgZWxlbWVudCwgb3Igc2VsZWN0b3Igc3RyaW5nLCBpbnRvIGEgZ3JpZCB3aWxsIHJldHVybiB0aGUgZ3JpZC4gQ2FsbGluZyBpdCBhZ2FpbiB3aWxsXG4gICAgICogc2ltcGx5IHJldHVybiB0aGUgZXhpc3RpbmcgaW5zdGFuY2UgKGlnbm9yZSBhbnkgcGFzc2VkIG9wdGlvbnMpLiBUaGVyZSBpcyBhbHNvIGFuIGluaXRBbGwoKSB2ZXJzaW9uIHRoYXQgc3VwcG9ydFxuICAgICAqIG11bHRpcGxlIGdyaWRzIGluaXRpYWxpemF0aW9uIGF0IG9uY2UuIE9yIHlvdSBjYW4gdXNlIGFkZEdyaWQoKSB0byBjcmVhdGUgdGhlIGVudGlyZSBncmlkIGZyb20gSlNPTi5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBncmlkIG9wdGlvbnMgKG9wdGlvbmFsKVxuICAgICAqIEBwYXJhbSBlbE9yU3RyaW5nIGVsZW1lbnQgb3IgQ1NTIHNlbGVjdG9yIChmaXJzdCBvbmUgdXNlZCkgdG8gY29udmVydCB0byBhIGdyaWQgKGRlZmF1bHQgdG8gJy5ncmlkLXN0YWNrJyBjbGFzcyBzZWxlY3RvcilcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogbGV0IGdyaWQgPSBHcmlkU3RhY2suaW5pdCgpO1xuICAgICAqXG4gICAgICogTm90ZTogdGhlIEhUTUxFbGVtZW50IChvZiB0eXBlIEdyaWRIVE1MRWxlbWVudCkgd2lsbCBzdG9yZSBhIGBncmlkc3RhY2s6IEdyaWRTdGFja2AgdmFsdWUgdGhhdCBjYW4gYmUgcmV0cmlldmUgbGF0ZXJcbiAgICAgKiBsZXQgZ3JpZCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5ncmlkLXN0YWNrJykuZ3JpZHN0YWNrO1xuICAgICAqL1xuICAgIHN0YXRpYyBpbml0KG9wdGlvbnMgPSB7fSwgZWxPclN0cmluZyA9ICcuZ3JpZC1zdGFjaycpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCA9PT0gJ3VuZGVmaW5lZCcpXG4gICAgICAgICAgICByZXR1cm4gbnVsbDsgLy8gdGVtcCB3b3JrYXJvdW5kIFNTUlxuICAgICAgICBsZXQgZWwgPSBHcmlkU3RhY2suZ2V0R3JpZEVsZW1lbnQoZWxPclN0cmluZyk7XG4gICAgICAgIGlmICghZWwpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZWxPclN0cmluZyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdHcmlkU3RhY2suaW5pdEFsbCgpIG5vIGdyaWQgd2FzIGZvdW5kIHdpdGggc2VsZWN0b3IgXCInICsgZWxPclN0cmluZyArICdcIiAtIGVsZW1lbnQgbWlzc2luZyBvciB3cm9uZyBzZWxlY3RvciA/JyArXG4gICAgICAgICAgICAgICAgICAgICdcXG5Ob3RlOiBcIi5ncmlkLXN0YWNrXCIgaXMgcmVxdWlyZWQgZm9yIHByb3BlciBDU1Mgc3R5bGluZyBhbmQgZHJhZy9kcm9wLCBhbmQgaXMgdGhlIGRlZmF1bHQgc2VsZWN0b3IuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdHcmlkU3RhY2suaW5pdCgpIG5vIGdyaWQgZWxlbWVudCB3YXMgcGFzc2VkLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFlbC5ncmlkc3RhY2spIHtcbiAgICAgICAgICAgIGVsLmdyaWRzdGFjayA9IG5ldyBHcmlkU3RhY2soZWwsIFV0aWxzLmNsb25lRGVlcChvcHRpb25zKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVsLmdyaWRzdGFjaztcbiAgICB9XG4gICAgLyoqXG4gICAgICogV2lsbCBpbml0aWFsaXplIGEgbGlzdCBvZiBlbGVtZW50cyAoZ2l2ZW4gYSBzZWxlY3RvcikgYW5kIHJldHVybiBhbiBhcnJheSBvZiBncmlkcy5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBncmlkIG9wdGlvbnMgKG9wdGlvbmFsKVxuICAgICAqIEBwYXJhbSBzZWxlY3RvciBlbGVtZW50cyBzZWxlY3RvciB0byBjb252ZXJ0IHRvIGdyaWRzIChkZWZhdWx0IHRvICcuZ3JpZC1zdGFjaycgY2xhc3Mgc2VsZWN0b3IpXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGxldCBncmlkcyA9IEdyaWRTdGFjay5pbml0QWxsKCk7XG4gICAgICogZ3JpZHMuZm9yRWFjaCguLi4pXG4gICAgICovXG4gICAgc3RhdGljIGluaXRBbGwob3B0aW9ucyA9IHt9LCBzZWxlY3RvciA9ICcuZ3JpZC1zdGFjaycpIHtcbiAgICAgICAgbGV0IGdyaWRzID0gW107XG4gICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnKVxuICAgICAgICAgICAgcmV0dXJuIGdyaWRzOyAvLyB0ZW1wIHdvcmthcm91bmQgU1NSXG4gICAgICAgIEdyaWRTdGFjay5nZXRHcmlkRWxlbWVudHMoc2VsZWN0b3IpLmZvckVhY2goZWwgPT4ge1xuICAgICAgICAgICAgaWYgKCFlbC5ncmlkc3RhY2spIHtcbiAgICAgICAgICAgICAgICBlbC5ncmlkc3RhY2sgPSBuZXcgR3JpZFN0YWNrKGVsLCBVdGlscy5jbG9uZURlZXAob3B0aW9ucykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZ3JpZHMucHVzaChlbC5ncmlkc3RhY2spO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGdyaWRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignR3JpZFN0YWNrLmluaXRBbGwoKSBubyBncmlkIHdhcyBmb3VuZCB3aXRoIHNlbGVjdG9yIFwiJyArIHNlbGVjdG9yICsgJ1wiIC0gZWxlbWVudCBtaXNzaW5nIG9yIHdyb25nIHNlbGVjdG9yID8nICtcbiAgICAgICAgICAgICAgICAnXFxuTm90ZTogXCIuZ3JpZC1zdGFja1wiIGlzIHJlcXVpcmVkIGZvciBwcm9wZXIgQ1NTIHN0eWxpbmcgYW5kIGRyYWcvZHJvcCwgYW5kIGlzIHRoZSBkZWZhdWx0IHNlbGVjdG9yLicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBncmlkcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogY2FsbCB0byBjcmVhdGUgYSBncmlkIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMsIGluY2x1ZGluZyBsb2FkaW5nIGFueSBjaGlsZHJlbiBmcm9tIEpTT04gc3RydWN0dXJlLiBUaGlzIHdpbGwgY2FsbCBHcmlkU3RhY2suaW5pdCgpLCB0aGVuXG4gICAgICogZ3JpZC5sb2FkKCkgb24gYW55IHBhc3NlZCBjaGlsZHJlbiAocmVjdXJzaXZlbHkpLiBHcmVhdCBhbHRlcm5hdGl2ZSB0byBjYWxsaW5nIGluaXQoKSBpZiB5b3Ugd2FudCBlbnRpcmUgZ3JpZCB0byBjb21lIGZyb21cbiAgICAgKiBKU09OIHNlcmlhbGl6ZWQgZGF0YSwgaW5jbHVkaW5nIG9wdGlvbnMuXG4gICAgICogQHBhcmFtIHBhcmVudCBIVE1MIGVsZW1lbnQgcGFyZW50IHRvIHRoZSBncmlkXG4gICAgICogQHBhcmFtIG9wdCBncmlkcyBvcHRpb25zIHVzZWQgdG8gaW5pdGlhbGl6ZSB0aGUgZ3JpZCwgYW5kIGxpc3Qgb2YgY2hpbGRyZW5cbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkR3JpZChwYXJlbnQsIG9wdCA9IHt9KSB7XG4gICAgICAgIGlmICghcGFyZW50KVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIGxldCBlbCA9IHBhcmVudDtcbiAgICAgICAgaWYgKGVsLmdyaWRzdGFjaykge1xuICAgICAgICAgICAgLy8gYWxyZWFkeSBhIGdyaWQgLSBzZXQgb3B0aW9uIGFuZCBsb2FkIGRhdGFcbiAgICAgICAgICAgIGNvbnN0IGdyaWQgPSBlbC5ncmlkc3RhY2s7XG4gICAgICAgICAgICBpZiAob3B0KVxuICAgICAgICAgICAgICAgIGdyaWQub3B0cyA9IHsgLi4uZ3JpZC5vcHRzLCAuLi5vcHQgfTtcbiAgICAgICAgICAgIGlmIChvcHQuY2hpbGRyZW4gIT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgICAgICBncmlkLmxvYWQob3B0LmNoaWxkcmVuKTtcbiAgICAgICAgICAgIHJldHVybiBncmlkO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNyZWF0ZSB0aGUgZ3JpZCBlbGVtZW50LCBidXQgY2hlY2sgaWYgdGhlIHBhc3NlZCAncGFyZW50JyBhbHJlYWR5IGhhcyBncmlkIHN0eWxpbmcgYW5kIHNob3VsZCBiZSB1c2VkIGluc3RlYWRcbiAgICAgICAgY29uc3QgcGFyZW50SXNHcmlkID0gcGFyZW50LmNsYXNzTGlzdC5jb250YWlucygnZ3JpZC1zdGFjaycpO1xuICAgICAgICBpZiAoIXBhcmVudElzR3JpZCB8fCBHcmlkU3RhY2suYWRkUmVtb3ZlQ0IpIHtcbiAgICAgICAgICAgIGlmIChHcmlkU3RhY2suYWRkUmVtb3ZlQ0IpIHtcbiAgICAgICAgICAgICAgICBlbCA9IEdyaWRTdGFjay5hZGRSZW1vdmVDQihwYXJlbnQsIG9wdCwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBsZXQgZG9jID0gZG9jdW1lbnQuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCcnKTsgLy8gSUUgbmVlZHMgYSBwYXJhbVxuICAgICAgICAgICAgICAgIGRvYy5ib2R5LmlubmVySFRNTCA9IGA8ZGl2IGNsYXNzPVwiZ3JpZC1zdGFjayAke29wdC5jbGFzcyB8fCAnJ31cIj48L2Rpdj5gO1xuICAgICAgICAgICAgICAgIGVsID0gZG9jLmJvZHkuY2hpbGRyZW5bMF07XG4gICAgICAgICAgICAgICAgcGFyZW50LmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBjcmVhdGUgZ3JpZCBjbGFzcyBhbmQgbG9hZCBhbnkgY2hpbGRyZW5cbiAgICAgICAgbGV0IGdyaWQgPSBHcmlkU3RhY2suaW5pdChvcHQsIGVsKTtcbiAgICAgICAgcmV0dXJuIGdyaWQ7XG4gICAgfVxuICAgIC8qKiBjYWxsIHRoaXMgbWV0aG9kIHRvIHJlZ2lzdGVyIHlvdXIgZW5naW5lIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLlxuICAgICAqIFNlZSBpbnN0ZWFkIGBHcmlkU3RhY2tPcHRpb25zLmVuZ2luZUNsYXNzYCBpZiB5b3Ugb25seSBuZWVkIHRvXG4gICAgICogcmVwbGFjZSBqdXN0IG9uZSBpbnN0YW5jZS5cbiAgICAgKi9cbiAgICBzdGF0aWMgcmVnaXN0ZXJFbmdpbmUoZW5naW5lQ2xhc3MpIHtcbiAgICAgICAgR3JpZFN0YWNrLmVuZ2luZUNsYXNzID0gZW5naW5lQ2xhc3M7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgY3JlYXRlIHBsYWNlaG9sZGVyIERJViBhcyBuZWVkZWQgKi9cbiAgICBnZXQgcGxhY2Vob2xkZXIoKSB7XG4gICAgICAgIGlmICghdGhpcy5fcGxhY2Vob2xkZXIpIHtcbiAgICAgICAgICAgIGxldCBwbGFjZWhvbGRlckNoaWxkID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7IC8vIGNoaWxkIHNvIHBhZGRpbmcgbWF0Y2ggaXRlbS1jb250ZW50XG4gICAgICAgICAgICBwbGFjZWhvbGRlckNoaWxkLmNsYXNzTmFtZSA9ICdwbGFjZWhvbGRlci1jb250ZW50JztcbiAgICAgICAgICAgIGlmICh0aGlzLm9wdHMucGxhY2Vob2xkZXJUZXh0KSB7XG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXJDaGlsZC5pbm5lckhUTUwgPSB0aGlzLm9wdHMucGxhY2Vob2xkZXJUZXh0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcGxhY2Vob2xkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgICAgIHRoaXMuX3BsYWNlaG9sZGVyLmNsYXNzTGlzdC5hZGQodGhpcy5vcHRzLnBsYWNlaG9sZGVyQ2xhc3MsIGdyaWREZWZhdWx0cy5pdGVtQ2xhc3MsIHRoaXMub3B0cy5pdGVtQ2xhc3MpO1xuICAgICAgICAgICAgdGhpcy5wbGFjZWhvbGRlci5hcHBlbmRDaGlsZChwbGFjZWhvbGRlckNoaWxkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fcGxhY2Vob2xkZXI7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdCBhIGdyaWQgaXRlbSBmcm9tIHRoZSBnaXZlbiBlbGVtZW50IGFuZCBvcHRpb25zXG4gICAgICogQHBhcmFtIGVsIHRoZSBIVE1MIGVsZW1lbnQgdGllZCB0byB0aGlzIGdyaWQgYWZ0ZXIgaXQncyBiZWVuIGluaXRpYWxpemVkXG4gICAgICogQHBhcmFtIG9wdHMgZ3JpZCBvcHRpb25zIC0gcHVibGljIGZvciBjbGFzc2VzIHRvIGFjY2VzcywgYnV0IHVzZSBtZXRob2RzIHRvIG1vZGlmeSFcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihlbCwgb3B0cyA9IHt9KSB7XG4gICAgICAgIHRoaXMuZWwgPSBlbDtcbiAgICAgICAgdGhpcy5vcHRzID0gb3B0cztcbiAgICAgICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgICAgICB0aGlzLl9nc0V2ZW50SGFuZGxlciA9IHt9O1xuICAgICAgICAvKiogQGludGVybmFsIGV4dHJhIHJvdyBhZGRlZCB3aGVuIGRyYWdnaW5nIGF0IHRoZSBib3R0b20gb2YgdGhlIGdyaWQgKi9cbiAgICAgICAgdGhpcy5fZXh0cmFEcmFnUm93ID0gMDtcbiAgICAgICAgLyoqIEBpbnRlcm5hbCBtZWFudCB0byBzdG9yZSB0aGUgc2NhbGUgb2YgdGhlIGFjdGl2ZSBncmlkICovXG4gICAgICAgIHRoaXMuZHJhZ1RyYW5zZm9ybSA9IHsgeFNjYWxlOiAxLCB5U2NhbGU6IDEsIHhPZmZzZXQ6IDAsIHlPZmZzZXQ6IDAgfTtcbiAgICAgICAgZWwuZ3JpZHN0YWNrID0gdGhpcztcbiAgICAgICAgb3B0cyA9IG9wdHMgfHwge307IC8vIGhhbmRsZXMgbnVsbC91bmRlZmluZWQvMFxuICAgICAgICBpZiAoIWVsLmNsYXNzTGlzdC5jb250YWlucygnZ3JpZC1zdGFjaycpKSB7XG4gICAgICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5hZGQoJ2dyaWQtc3RhY2snKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiByb3cgcHJvcGVydHkgZXhpc3RzLCByZXBsYWNlIG1pblJvdyBhbmQgbWF4Um93IGluc3RlYWRcbiAgICAgICAgaWYgKG9wdHMucm93KSB7XG4gICAgICAgICAgICBvcHRzLm1pblJvdyA9IG9wdHMubWF4Um93ID0gb3B0cy5yb3c7XG4gICAgICAgICAgICBkZWxldGUgb3B0cy5yb3c7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHJvd0F0dHIgPSBVdGlscy50b051bWJlcihlbC5nZXRBdHRyaWJ1dGUoJ2dzLXJvdycpKTtcbiAgICAgICAgLy8gZmxhZyBvbmx5IHZhbGlkIGluIHN1Yi1ncmlkcyAoaGFuZGxlZCBieSBwYXJlbnQsIG5vdCBoZXJlKVxuICAgICAgICBpZiAob3B0cy5jb2x1bW4gPT09ICdhdXRvJykge1xuICAgICAgICAgICAgZGVsZXRlIG9wdHMuY29sdW1uO1xuICAgICAgICB9XG4gICAgICAgIC8vIHNhdmUgb3JpZ2luYWwgc2V0dGluZyBzbyB3ZSBjYW4gcmVzdG9yZSBvbiBzYXZlXG4gICAgICAgIGlmIChvcHRzLmFsd2F5c1Nob3dSZXNpemVIYW5kbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgb3B0cy5fYWx3YXlzU2hvd1Jlc2l6ZUhhbmRsZSA9IG9wdHMuYWx3YXlzU2hvd1Jlc2l6ZUhhbmRsZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgYmsgPSBvcHRzLmNvbHVtbk9wdHM/LmJyZWFrcG9pbnRzO1xuICAgICAgICAvLyBMRUdBQ1k6IG9uZUNvbHVtbk1vZGUgc3R1ZmYgY2hhbmdlZCBpbiB2MTAueCAtIGNoZWNrIGlmIHVzZXIgZXhwbGljaXRseSBzZXQgc29tZXRoaW5nIHRvIGNvbnZlcnQgb3ZlclxuICAgICAgICBjb25zdCBvbGRPcHRzID0gb3B0cztcbiAgICAgICAgaWYgKG9sZE9wdHMub25lQ29sdW1uTW9kZURvbVNvcnQpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBvbGRPcHRzLm9uZUNvbHVtbk1vZGVEb21Tb3J0O1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ3dhcm5pbmc6IEdyaWRzdGFjayBvbmVDb2x1bW5Nb2RlRG9tU29ydCBubyBsb25nZXIgc3VwcG9ydGVkLiBVc2UgR3JpZFN0YWNrT3B0aW9ucy5jb2x1bW5PcHRzIGluc3RlYWQuJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9sZE9wdHMub25lQ29sdW1uU2l6ZSB8fCBvbGRPcHRzLmRpc2FibGVPbmVDb2x1bW5Nb2RlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgY29uc3Qgb25lU2l6ZSA9IG9sZE9wdHMub25lQ29sdW1uU2l6ZSB8fCA3Njg7XG4gICAgICAgICAgICBkZWxldGUgb2xkT3B0cy5vbmVDb2x1bW5TaXplO1xuICAgICAgICAgICAgZGVsZXRlIG9sZE9wdHMuZGlzYWJsZU9uZUNvbHVtbk1vZGU7XG4gICAgICAgICAgICBvcHRzLmNvbHVtbk9wdHMgPSBvcHRzLmNvbHVtbk9wdHMgfHwge307XG4gICAgICAgICAgICBiayA9IG9wdHMuY29sdW1uT3B0cy5icmVha3BvaW50cyA9IG9wdHMuY29sdW1uT3B0cy5icmVha3BvaW50cyB8fCBbXTtcbiAgICAgICAgICAgIGxldCBvbmVDb2x1bW4gPSBiay5maW5kKGIgPT4gYi5jID09PSAxKTtcbiAgICAgICAgICAgIGlmICghb25lQ29sdW1uKSB7XG4gICAgICAgICAgICAgICAgb25lQ29sdW1uID0geyBjOiAxLCB3OiBvbmVTaXplIH07XG4gICAgICAgICAgICAgICAgYmsucHVzaChvbmVDb2x1bW4sIHsgYzogMTIsIHc6IG9uZVNpemUgKyAxIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIG9uZUNvbHVtbi53ID0gb25lU2l6ZTtcbiAgICAgICAgfVxuICAgICAgICAvLy4uLmVuZCBMRUdBQ1lcbiAgICAgICAgLy8gY2xlYW51cCByZXNwb25zaXZlIG9wdHMgKG11c3QgaGF2ZSBjb2x1bW5XaWR0aCB8IGJyZWFrcG9pbnRzKSB0aGVuIHNvcnQgYnJlYWtwb2ludHMgYnkgc2l6ZSAoc28gd2UgY2FuIG1hdGNoIGR1cmluZyByZXNpemUpXG4gICAgICAgIGNvbnN0IHJlc3AgPSBvcHRzLmNvbHVtbk9wdHM7XG4gICAgICAgIGlmIChyZXNwKSB7XG4gICAgICAgICAgICBpZiAoIXJlc3AuY29sdW1uV2lkdGggJiYgIXJlc3AuYnJlYWtwb2ludHM/Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvcHRzLmNvbHVtbk9wdHM7XG4gICAgICAgICAgICAgICAgYmsgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXNwLmNvbHVtbk1heCA9IHJlc3AuY29sdW1uTWF4IHx8IDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChiaz8ubGVuZ3RoID4gMSlcbiAgICAgICAgICAgIGJrLnNvcnQoKGEsIGIpID0+IChiLncgfHwgMCkgLSAoYS53IHx8IDApKTtcbiAgICAgICAgLy8gZWxlbWVudHMgRE9NIGF0dHJpYnV0ZXMgb3ZlcnJpZGUgYW55IHBhc3NlZCBvcHRpb25zIChsaWtlIENTUyBzdHlsZSkgLSBtZXJnZSB0aGUgdHdvIHRvZ2V0aGVyXG4gICAgICAgIGxldCBkZWZhdWx0cyA9IHtcbiAgICAgICAgICAgIC4uLlV0aWxzLmNsb25lRGVlcChncmlkRGVmYXVsdHMpLFxuICAgICAgICAgICAgY29sdW1uOiBVdGlscy50b051bWJlcihlbC5nZXRBdHRyaWJ1dGUoJ2dzLWNvbHVtbicpKSB8fCBncmlkRGVmYXVsdHMuY29sdW1uLFxuICAgICAgICAgICAgbWluUm93OiByb3dBdHRyID8gcm93QXR0ciA6IFV0aWxzLnRvTnVtYmVyKGVsLmdldEF0dHJpYnV0ZSgnZ3MtbWluLXJvdycpKSB8fCBncmlkRGVmYXVsdHMubWluUm93LFxuICAgICAgICAgICAgbWF4Um93OiByb3dBdHRyID8gcm93QXR0ciA6IFV0aWxzLnRvTnVtYmVyKGVsLmdldEF0dHJpYnV0ZSgnZ3MtbWF4LXJvdycpKSB8fCBncmlkRGVmYXVsdHMubWF4Um93LFxuICAgICAgICAgICAgc3RhdGljR3JpZDogVXRpbHMudG9Cb29sKGVsLmdldEF0dHJpYnV0ZSgnZ3Mtc3RhdGljJykpIHx8IGdyaWREZWZhdWx0cy5zdGF0aWNHcmlkLFxuICAgICAgICAgICAgZHJhZ2dhYmxlOiB7XG4gICAgICAgICAgICAgICAgaGFuZGxlOiAob3B0cy5oYW5kbGVDbGFzcyA/ICcuJyArIG9wdHMuaGFuZGxlQ2xhc3MgOiAob3B0cy5oYW5kbGUgPyBvcHRzLmhhbmRsZSA6ICcnKSkgfHwgZ3JpZERlZmF1bHRzLmRyYWdnYWJsZS5oYW5kbGUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVtb3ZhYmxlT3B0aW9uczoge1xuICAgICAgICAgICAgICAgIGFjY2VwdDogb3B0cy5pdGVtQ2xhc3MgfHwgZ3JpZERlZmF1bHRzLnJlbW92YWJsZU9wdGlvbnMuYWNjZXB0LFxuICAgICAgICAgICAgICAgIGRlY2xpbmU6IGdyaWREZWZhdWx0cy5yZW1vdmFibGVPcHRpb25zLmRlY2xpbmVcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICAgIGlmIChlbC5nZXRBdHRyaWJ1dGUoJ2dzLWFuaW1hdGUnKSkgeyAvLyBkZWZhdWx0IHRvIHRydWUsIGJ1dCBpZiBzZXQgdG8gZmFsc2UgdXNlIHRoYXQgaW5zdGVhZFxuICAgICAgICAgICAgZGVmYXVsdHMuYW5pbWF0ZSA9IFV0aWxzLnRvQm9vbChlbC5nZXRBdHRyaWJ1dGUoJ2dzLWFuaW1hdGUnKSk7XG4gICAgICAgIH1cbiAgICAgICAgb3B0cyA9IFV0aWxzLmRlZmF1bHRzKG9wdHMsIGRlZmF1bHRzKTtcbiAgICAgICAgdGhpcy5faW5pdE1hcmdpbigpOyAvLyBwYXJ0IG9mIHNldHRpbmdzIGRlZmF1bHRzLi4uXG4gICAgICAgIC8vIE5vdyBjaGVjayBpZiB3ZSdyZSBsb2FkaW5nIGludG8gMSBjb2x1bW4gbW9kZSBGSVJTVCBzbyB3ZSBkb24ndCBkbyB1bi1uZWNlc3Nhcnkgd29yayAobGlrZSBjZWxsSGVpZ2h0ID0gd2lkdGggLyAxMiB0aGVuIGdvIDEgY29sdW1uKVxuICAgICAgICB0aGlzLmNoZWNrRHluYW1pY0NvbHVtbigpO1xuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5hZGQoJ2dzLScgKyBvcHRzLmNvbHVtbik7XG4gICAgICAgIGlmIChvcHRzLnJ0bCA9PT0gJ2F1dG8nKSB7XG4gICAgICAgICAgICBvcHRzLnJ0bCA9IChlbC5zdHlsZS5kaXJlY3Rpb24gPT09ICdydGwnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0cy5ydGwpIHtcbiAgICAgICAgICAgIHRoaXMuZWwuY2xhc3NMaXN0LmFkZCgnZ3JpZC1zdGFjay1ydGwnKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBjaGVjayBpZiB3ZSdyZSBiZWVuIG5lc3RlZCwgYW5kIGlmIHNvIHVwZGF0ZSBvdXIgc3R5bGUgYW5kIGtlZXAgcG9pbnRlciBhcm91bmQgKHVzZWQgZHVyaW5nIHNhdmUpXG4gICAgICAgIGNvbnN0IGdyYW5kUGFyZW50ID0gdGhpcy5lbC5wYXJlbnRFbGVtZW50Py5wYXJlbnRFbGVtZW50O1xuICAgICAgICBsZXQgcGFyZW50R3JpZEl0ZW0gPSBncmFuZFBhcmVudD8uY2xhc3NMaXN0LmNvbnRhaW5zKGdyaWREZWZhdWx0cy5pdGVtQ2xhc3MpID8gZ3JhbmRQYXJlbnQuZ3JpZHN0YWNrTm9kZSA6IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHBhcmVudEdyaWRJdGVtKSB7XG4gICAgICAgICAgICBwYXJlbnRHcmlkSXRlbS5zdWJHcmlkID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMucGFyZW50R3JpZEl0ZW0gPSBwYXJlbnRHcmlkSXRlbTtcbiAgICAgICAgICAgIHRoaXMuZWwuY2xhc3NMaXN0LmFkZCgnZ3JpZC1zdGFjay1uZXN0ZWQnKTtcbiAgICAgICAgICAgIHBhcmVudEdyaWRJdGVtLmVsLmNsYXNzTGlzdC5hZGQoJ2dyaWQtc3RhY2stc3ViLWdyaWQnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9pc0F1dG9DZWxsSGVpZ2h0ID0gKG9wdHMuY2VsbEhlaWdodCA9PT0gJ2F1dG8nKTtcbiAgICAgICAgaWYgKHRoaXMuX2lzQXV0b0NlbGxIZWlnaHQgfHwgb3B0cy5jZWxsSGVpZ2h0ID09PSAnaW5pdGlhbCcpIHtcbiAgICAgICAgICAgIC8vIG1ha2UgdGhlIGNlbGwgY29udGVudCBzcXVhcmUgaW5pdGlhbGx5ICh3aWxsIHVzZSByZXNpemUvY29sdW1uIGV2ZW50IHRvIGtlZXAgaXQgc3F1YXJlKVxuICAgICAgICAgICAgdGhpcy5jZWxsSGVpZ2h0KHVuZGVmaW5lZCwgZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gYXBwZW5kIHVuaXQgaWYgYW55IGFyZSBzZXRcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0cy5jZWxsSGVpZ2h0ID09ICdudW1iZXInICYmIG9wdHMuY2VsbEhlaWdodFVuaXQgJiYgb3B0cy5jZWxsSGVpZ2h0VW5pdCAhPT0gZ3JpZERlZmF1bHRzLmNlbGxIZWlnaHRVbml0KSB7XG4gICAgICAgICAgICAgICAgb3B0cy5jZWxsSGVpZ2h0ID0gb3B0cy5jZWxsSGVpZ2h0ICsgb3B0cy5jZWxsSGVpZ2h0VW5pdDtcbiAgICAgICAgICAgICAgICBkZWxldGUgb3B0cy5jZWxsSGVpZ2h0VW5pdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuY2VsbEhlaWdodChvcHRzLmNlbGxIZWlnaHQsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBzZWUgaWYgd2UgbmVlZCB0byBhZGp1c3QgYXV0by1oaWRlXG4gICAgICAgIGlmIChvcHRzLmFsd2F5c1Nob3dSZXNpemVIYW5kbGUgPT09ICdtb2JpbGUnKSB7XG4gICAgICAgICAgICBvcHRzLmFsd2F5c1Nob3dSZXNpemVIYW5kbGUgPSBpc1RvdWNoO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3N0eWxlU2hlZXRDbGFzcyA9ICdncy1pZC0nICsgR3JpZFN0YWNrRW5naW5lLl9pZFNlcSsrO1xuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5hZGQodGhpcy5fc3R5bGVTaGVldENsYXNzKTtcbiAgICAgICAgdGhpcy5fc2V0U3RhdGljQ2xhc3MoKTtcbiAgICAgICAgbGV0IGVuZ2luZUNsYXNzID0gb3B0cy5lbmdpbmVDbGFzcyB8fCBHcmlkU3RhY2suZW5naW5lQ2xhc3MgfHwgR3JpZFN0YWNrRW5naW5lO1xuICAgICAgICB0aGlzLmVuZ2luZSA9IG5ldyBlbmdpbmVDbGFzcyh7XG4gICAgICAgICAgICBjb2x1bW46IHRoaXMuZ2V0Q29sdW1uKCksXG4gICAgICAgICAgICBmbG9hdDogb3B0cy5mbG9hdCxcbiAgICAgICAgICAgIG1heFJvdzogb3B0cy5tYXhSb3csXG4gICAgICAgICAgICBvbkNoYW5nZTogKGNiTm9kZXMpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgbWF4SCA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmdpbmUubm9kZXMuZm9yRWFjaChuID0+IHsgbWF4SCA9IE1hdGgubWF4KG1heEgsIG4ueSArIG4uaCk7IH0pO1xuICAgICAgICAgICAgICAgIGNiTm9kZXMuZm9yRWFjaChuID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGVsID0gbi5lbDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFlbClcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG4uX3JlbW92ZURPTSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG4uX3JlbW92ZURPTTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3dyaXRlUG9zQXR0cihlbCwgbik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGVTdHlsZXMoZmFsc2UsIG1heEgpOyAvLyBmYWxzZSA9IGRvbid0IHJlY3JlYXRlLCBqdXN0IGFwcGVuZCBpZiBuZWVkIGJlXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBjcmVhdGUgaW5pdGlhbCBnbG9iYWwgc3R5bGVzIEJFRk9SRSBsb2FkaW5nIGNoaWxkcmVuIHNvIHJlc2l6ZVRvQ29udGVudCBtYXJnaW4gY2FuIGJlIGNhbGN1bGF0ZWQgY29ycmVjdGx5XG4gICAgICAgIHRoaXMuX3VwZGF0ZVN0eWxlcyhmYWxzZSwgMCk7XG4gICAgICAgIGlmIChvcHRzLmF1dG8pIHtcbiAgICAgICAgICAgIHRoaXMuYmF0Y2hVcGRhdGUoKTsgLy8gcHJldmVudCBpbiBiZXR3ZWVuIHJlLWxheW91dCAjMTUzNSBUT0RPOiB0aGlzIG9ubHkgc2V0IGZsb2F0PXRydWUsIG5lZWQgdG8gcHJldmVudCBjb2xsaXNpb24gY2hlY2suLi5cbiAgICAgICAgICAgIHRoaXMuZ2V0R3JpZEl0ZW1zKCkuZm9yRWFjaChlbCA9PiB0aGlzLl9wcmVwYXJlRWxlbWVudChlbCkpO1xuICAgICAgICAgICAgdGhpcy5iYXRjaFVwZGF0ZShmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gbG9hZCBhbnkgcGFzc2VkIGluIGNoaWxkcmVuIGFzIHdlbGwsIHdoaWNoIG92ZXJyaWRlcyBhbnkgRE9NIGxheW91dCBkb25lIGFib3ZlXG4gICAgICAgIGlmIChvcHRzLmNoaWxkcmVuKSB7XG4gICAgICAgICAgICBsZXQgY2hpbGRyZW4gPSBvcHRzLmNoaWxkcmVuO1xuICAgICAgICAgICAgZGVsZXRlIG9wdHMuY2hpbGRyZW47XG4gICAgICAgICAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoKVxuICAgICAgICAgICAgICAgIHRoaXMubG9hZChjaGlsZHJlbik7IC8vIGRvbid0IGxvYWQgZW1wdHlcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiAodGhpcy5lbmdpbmUubm9kZXMubGVuZ3RoKSB0aGlzLl91cGRhdGVTdHlsZXMoKTsgLy8gdXBkYXRlIGJhc2VkIG9uICMgb2YgY2hpbGRyZW4uIGRvbmUgaW4gZW5naW5lIG9uQ2hhbmdlIENCXG4gICAgICAgIHRoaXMuc2V0QW5pbWF0aW9uKG9wdHMuYW5pbWF0ZSk7XG4gICAgICAgIC8vIGR5bmFtaWMgZ3JpZHMgcmVxdWlyZSBwYXVzaW5nIGR1cmluZyBkcmFnIHRvIGRldGVjdCBvdmVyIHRvIG5lc3QgdnMgcHVzaFxuICAgICAgICBpZiAob3B0cy5zdWJHcmlkRHluYW1pYyAmJiAhRERNYW5hZ2VyLnBhdXNlRHJhZylcbiAgICAgICAgICAgIERETWFuYWdlci5wYXVzZURyYWcgPSB0cnVlO1xuICAgICAgICBpZiAob3B0cy5kcmFnZ2FibGU/LnBhdXNlICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICBERE1hbmFnZXIucGF1c2VEcmFnID0gb3B0cy5kcmFnZ2FibGUucGF1c2U7XG4gICAgICAgIHRoaXMuX3NldHVwUmVtb3ZlRHJvcCgpO1xuICAgICAgICB0aGlzLl9zZXR1cEFjY2VwdFdpZGdldCgpO1xuICAgICAgICB0aGlzLl91cGRhdGVSZXNpemVFdmVudCgpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBhZGQgYSBuZXcgd2lkZ2V0IGFuZCByZXR1cm5zIGl0LlxuICAgICAqXG4gICAgICogV2lkZ2V0IHdpbGwgYmUgYWx3YXlzIHBsYWNlZCBldmVuIGlmIHJlc3VsdCBoZWlnaHQgaXMgbW9yZSB0aGFuIGFjdHVhbCBncmlkIGhlaWdodC5cbiAgICAgKiBZb3UgbmVlZCB0byB1c2UgYHdpbGxJdEZpdCgpYCBiZWZvcmUgY2FsbGluZyBhZGRXaWRnZXQgZm9yIGFkZGl0aW9uYWwgY2hlY2suXG4gICAgICogU2VlIGFsc28gYG1ha2VXaWRnZXQoKWAuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGxldCBncmlkID0gR3JpZFN0YWNrLmluaXQoKTtcbiAgICAgKiBncmlkLmFkZFdpZGdldCh7dzogMywgY29udGVudDogJ2hlbGxvJ30pO1xuICAgICAqIGdyaWQuYWRkV2lkZ2V0KCc8ZGl2IGNsYXNzPVwiZ3JpZC1zdGFjay1pdGVtXCI+PGRpdiBjbGFzcz1cImdyaWQtc3RhY2staXRlbS1jb250ZW50XCI+aGVsbG88L2Rpdj48L2Rpdj4nLCB7dzogM30pO1xuICAgICAqXG4gICAgICogQHBhcmFtIGVsICBHcmlkU3RhY2tXaWRnZXQgKHdoaWNoIGNhbiBoYXZlIGNvbnRlbnQgc3RyaW5nIGFzIHdlbGwpLCBodG1sIGVsZW1lbnQsIG9yIHN0cmluZyBkZWZpbml0aW9uIHRvIGFkZFxuICAgICAqIEBwYXJhbSBvcHRpb25zIHdpZGdldCBwb3NpdGlvbi9zaXplIG9wdGlvbnMgKG9wdGlvbmFsLCBhbmQgaWdub3JlIGlmIGZpcnN0IHBhcmFtIGlzIGFscmVhZHkgb3B0aW9uKSAtIHNlZSBHcmlkU3RhY2tXaWRnZXRcbiAgICAgKi9cbiAgICBhZGRXaWRnZXQoZWxzLCBvcHRpb25zKSB7XG4gICAgICAgIGZ1bmN0aW9uIGlzR3JpZFN0YWNrV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgIHJldHVybiB3LmVsICE9PSB1bmRlZmluZWQgfHwgdy54ICE9PSB1bmRlZmluZWQgfHwgdy55ICE9PSB1bmRlZmluZWQgfHwgdy53ICE9PSB1bmRlZmluZWQgfHwgdy5oICE9PSB1bmRlZmluZWQgfHwgdy5jb250ZW50ICE9PSB1bmRlZmluZWQgPyB0cnVlIDogZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGVsO1xuICAgICAgICBsZXQgbm9kZTtcbiAgICAgICAgaWYgKHR5cGVvZiBlbHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBsZXQgZG9jID0gZG9jdW1lbnQuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCcnKTsgLy8gSUUgbmVlZHMgYSBwYXJhbVxuICAgICAgICAgICAgZG9jLmJvZHkuaW5uZXJIVE1MID0gZWxzO1xuICAgICAgICAgICAgZWwgPSBkb2MuYm9keS5jaGlsZHJlblswXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwIHx8IGFyZ3VtZW50cy5sZW5ndGggPT09IDEgJiYgaXNHcmlkU3RhY2tXaWRnZXQoZWxzKSkge1xuICAgICAgICAgICAgbm9kZSA9IG9wdGlvbnMgPSBlbHM7XG4gICAgICAgICAgICBpZiAobm9kZT8uZWwpIHtcbiAgICAgICAgICAgICAgICBlbCA9IG5vZGUuZWw7IC8vIHJlLXVzZSBlbGVtZW50IHN0b3JlZCBpbiB0aGUgbm9kZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoR3JpZFN0YWNrLmFkZFJlbW92ZUNCKSB7XG4gICAgICAgICAgICAgICAgZWwgPSBHcmlkU3RhY2suYWRkUmVtb3ZlQ0IodGhpcy5lbCwgb3B0aW9ucywgdHJ1ZSwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbGV0IGNvbnRlbnQgPSBvcHRpb25zPy5jb250ZW50IHx8ICcnO1xuICAgICAgICAgICAgICAgIGxldCBkb2MgPSBkb2N1bWVudC5pbXBsZW1lbnRhdGlvbi5jcmVhdGVIVE1MRG9jdW1lbnQoJycpOyAvLyBJRSBuZWVkcyBhIHBhcmFtXG4gICAgICAgICAgICAgICAgZG9jLmJvZHkuaW5uZXJIVE1MID0gYDxkaXYgY2xhc3M9XCJncmlkLXN0YWNrLWl0ZW0gJHt0aGlzLm9wdHMuaXRlbUNsYXNzIHx8ICcnfVwiPjxkaXYgY2xhc3M9XCJncmlkLXN0YWNrLWl0ZW0tY29udGVudFwiPiR7Y29udGVudH08L2Rpdj48L2Rpdj5gO1xuICAgICAgICAgICAgICAgIGVsID0gZG9jLmJvZHkuY2hpbGRyZW5bMF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBlbCA9IGVscztcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWVsKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBpZiB0aGUgY2FsbGVyIGVuZGVkIHVwIGluaXRpYWxpemluZyB0aGUgd2lkZ2V0IGluIGFkZFJlbW92ZUNCLCBvciB3ZSBzdGFyZWQgd2l0aCBvbmUgYWxyZWFkeSwgc2tpcCB0aGUgcmVzdFxuICAgICAgICBub2RlID0gZWwuZ3JpZHN0YWNrTm9kZTtcbiAgICAgICAgaWYgKG5vZGUgJiYgZWwucGFyZW50RWxlbWVudCA9PT0gdGhpcy5lbCAmJiB0aGlzLmVuZ2luZS5ub2Rlcy5maW5kKG4gPT4gbi5faWQgPT09IG5vZGUuX2lkKSlcbiAgICAgICAgICAgIHJldHVybiBlbDtcbiAgICAgICAgLy8gVGVtcHRpbmcgdG8gaW5pdGlhbGl6ZSB0aGUgcGFzc2VkIGluIG9wdCB3aXRoIGRlZmF1bHQgYW5kIHZhbGlkIHZhbHVlcywgYnV0IHRoaXMgYnJlYWsga25vY2tvdXQgZGVtb3NcbiAgICAgICAgLy8gYXMgdGhlIGFjdHVhbCB2YWx1ZSBhcmUgZmlsbGVkIGluIHdoZW4gX3ByZXBhcmVFbGVtZW50KCkgY2FsbHMgZWwuZ2V0QXR0cmlidXRlKCdncy14eXonKSBiZWZvcmUgYWRkaW5nIHRoZSBub2RlLlxuICAgICAgICAvLyBTbyBtYWtlIHN1cmUgd2UgbG9hZCBhbnkgRE9NIGF0dHJpYnV0ZXMgdGhhdCBhcmUgbm90IHNwZWNpZmllZCBpbiBwYXNzZWQgaW4gb3B0aW9ucyAod2hpY2ggb3ZlcnJpZGUpXG4gICAgICAgIGxldCBkb21BdHRyID0gdGhpcy5fcmVhZEF0dHIoZWwpO1xuICAgICAgICBvcHRpb25zID0gVXRpbHMuY2xvbmVEZWVwKG9wdGlvbnMpIHx8IHt9OyAvLyBtYWtlIGEgY29weSBiZWZvcmUgd2UgbW9kaWZ5IGluIGNhc2UgY2FsbGVyIHJlLXVzZXMgaXRcbiAgICAgICAgVXRpbHMuZGVmYXVsdHMob3B0aW9ucywgZG9tQXR0cik7XG4gICAgICAgIG5vZGUgPSB0aGlzLmVuZ2luZS5wcmVwYXJlTm9kZShvcHRpb25zKTtcbiAgICAgICAgdGhpcy5fd3JpdGVBdHRyKGVsLCBvcHRpb25zKTtcbiAgICAgICAgaWYgKHRoaXMuX2luc2VydE5vdEFwcGVuZCkge1xuICAgICAgICAgICAgdGhpcy5lbC5wcmVwZW5kKGVsKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWwuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubWFrZVdpZGdldChlbCwgb3B0aW9ucyk7XG4gICAgICAgIHJldHVybiBlbDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29udmVydCBhbiBleGlzdGluZyBncmlkSXRlbSBlbGVtZW50IGludG8gYSBzdWItZ3JpZCB3aXRoIHRoZSBnaXZlbiAob3B0aW9uYWwpIG9wdGlvbnMsIGVsc2UgaW5oZXJpdCB0aGVtXG4gICAgICogZnJvbSB0aGUgcGFyZW50J3Mgc3ViR3JpZCBvcHRpb25zLlxuICAgICAqIEBwYXJhbSBlbCBncmlkSXRlbSBlbGVtZW50IHRvIGNvbnZlcnRcbiAgICAgKiBAcGFyYW0gb3BzIChvcHRpb25hbCkgc3ViLWdyaWQgb3B0aW9ucywgZWxzZSBkZWZhdWx0IHRvIG5vZGUsIHRoZW4gcGFyZW50IHNldHRpbmdzLCBlbHNlIGRlZmF1bHRzXG4gICAgICogQHBhcmFtIG5vZGVUb0FkZCAob3B0aW9uYWwpIG5vZGUgdG8gYWRkIHRvIHRoZSBuZXdseSBjcmVhdGVkIHN1YiBncmlkICh1c2VkIHdoZW4gZHJhZ2dpbmcgb3ZlciBleGlzdGluZyByZWd1bGFyIGl0ZW0pXG4gICAgICogQHBhcmFtIHNhdmVDb250ZW50IGlmIHRydWUgKGRlZmF1bHQpIHRoZSBodG1sIGluc2lkZSAuZ3JpZC1zdGFjay1jb250ZW50IHdpbGwgYmUgc2F2ZWQgdG8gY2hpbGQgd2lkZ2V0XG4gICAgICogQHJldHVybnMgbmV3bHkgY3JlYXRlZCBncmlkXG4gICAgICovXG4gICAgbWFrZVN1YkdyaWQoZWwsIG9wcywgbm9kZVRvQWRkLCBzYXZlQ29udGVudCA9IHRydWUpIHtcbiAgICAgICAgbGV0IG5vZGUgPSBlbC5ncmlkc3RhY2tOb2RlO1xuICAgICAgICBpZiAoIW5vZGUpIHtcbiAgICAgICAgICAgIG5vZGUgPSB0aGlzLm1ha2VXaWRnZXQoZWwpLmdyaWRzdGFja05vZGU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5vZGUuc3ViR3JpZD8uZWwpXG4gICAgICAgICAgICByZXR1cm4gbm9kZS5zdWJHcmlkOyAvLyBhbHJlYWR5IGRvbmVcbiAgICAgICAgLy8gZmluZCB0aGUgdGVtcGxhdGUgc3ViR3JpZCBzdG9yZWQgb24gYSBwYXJlbnQgYXMgZmFsbGJhY2suLi5cbiAgICAgICAgbGV0IHN1YkdyaWRUZW1wbGF0ZTsgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby10aGlzLWFsaWFzXG4gICAgICAgIGxldCBncmlkID0gdGhpcztcbiAgICAgICAgd2hpbGUgKGdyaWQgJiYgIXN1YkdyaWRUZW1wbGF0ZSkge1xuICAgICAgICAgICAgc3ViR3JpZFRlbXBsYXRlID0gZ3JpZC5vcHRzPy5zdWJHcmlkT3B0cztcbiAgICAgICAgICAgIGdyaWQgPSBncmlkLnBhcmVudEdyaWRJdGVtPy5ncmlkO1xuICAgICAgICB9XG4gICAgICAgIC8vLi4uIGFuZCBzZXQgdGhlIGNyZWF0ZSBvcHRpb25zXG4gICAgICAgIG9wcyA9IFV0aWxzLmNsb25lRGVlcCh7IC4uLihzdWJHcmlkVGVtcGxhdGUgfHwge30pLCBjaGlsZHJlbjogdW5kZWZpbmVkLCAuLi4ob3BzIHx8IG5vZGUuc3ViR3JpZE9wdHMgfHwge30pIH0pO1xuICAgICAgICBub2RlLnN1YkdyaWRPcHRzID0gb3BzO1xuICAgICAgICAvLyBpZiBjb2x1bW4gc3BlY2lhbCBjYXNlIGl0IHNldCwgcmVtZW1iZXIgdGhhdCBmbGFnIGFuZCBzZXQgZGVmYXVsdFxuICAgICAgICBsZXQgYXV0b0NvbHVtbjtcbiAgICAgICAgaWYgKG9wcy5jb2x1bW4gPT09ICdhdXRvJykge1xuICAgICAgICAgICAgYXV0b0NvbHVtbiA9IHRydWU7XG4gICAgICAgICAgICBvcHMuY29sdW1uID0gTWF0aC5tYXgobm9kZS53IHx8IDEsIG5vZGVUb0FkZD8udyB8fCAxKTtcbiAgICAgICAgICAgIGRlbGV0ZSBvcHMuY29sdW1uT3B0czsgLy8gZHJpdmVuIGJ5IHBhcmVudFxuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHdlJ3JlIGNvbnZlcnRpbmcgYW4gZXhpc3RpbmcgZnVsbCBpdGVtLCBtb3ZlIG92ZXIgdGhlIGNvbnRlbnQgdG8gYmUgdGhlIGZpcnN0IHN1YiBpdGVtIGluIHRoZSBuZXcgZ3JpZFxuICAgICAgICBsZXQgY29udGVudCA9IG5vZGUuZWwucXVlcnlTZWxlY3RvcignLmdyaWQtc3RhY2staXRlbS1jb250ZW50Jyk7XG4gICAgICAgIGxldCBuZXdJdGVtO1xuICAgICAgICBsZXQgbmV3SXRlbU9wdDtcbiAgICAgICAgaWYgKHNhdmVDb250ZW50KSB7XG4gICAgICAgICAgICB0aGlzLl9yZW1vdmVERChub2RlLmVsKTsgLy8gcmVtb3ZlIEQmRCBzaW5jZSBpdCdzIHNldCBvbiBjb250ZW50IGRpdlxuICAgICAgICAgICAgbmV3SXRlbU9wdCA9IHsgLi4ubm9kZSwgeDogMCwgeTogMCB9O1xuICAgICAgICAgICAgVXRpbHMucmVtb3ZlSW50ZXJuYWxGb3JTYXZlKG5ld0l0ZW1PcHQpO1xuICAgICAgICAgICAgZGVsZXRlIG5ld0l0ZW1PcHQuc3ViR3JpZE9wdHM7XG4gICAgICAgICAgICBpZiAobm9kZS5jb250ZW50KSB7XG4gICAgICAgICAgICAgICAgbmV3SXRlbU9wdC5jb250ZW50ID0gbm9kZS5jb250ZW50O1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBub2RlLmNvbnRlbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoR3JpZFN0YWNrLmFkZFJlbW92ZUNCKSB7XG4gICAgICAgICAgICAgICAgbmV3SXRlbSA9IEdyaWRTdGFjay5hZGRSZW1vdmVDQih0aGlzLmVsLCBuZXdJdGVtT3B0LCB0cnVlLCBmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBsZXQgZG9jID0gZG9jdW1lbnQuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCcnKTsgLy8gSUUgbmVlZHMgYSBwYXJhbVxuICAgICAgICAgICAgICAgIGRvYy5ib2R5LmlubmVySFRNTCA9IGA8ZGl2IGNsYXNzPVwiZ3JpZC1zdGFjay1pdGVtXCI+PC9kaXY+YDtcbiAgICAgICAgICAgICAgICBuZXdJdGVtID0gZG9jLmJvZHkuY2hpbGRyZW5bMF07XG4gICAgICAgICAgICAgICAgbmV3SXRlbS5hcHBlbmRDaGlsZChjb250ZW50KTtcbiAgICAgICAgICAgICAgICBkb2MuYm9keS5pbm5lckhUTUwgPSBgPGRpdiBjbGFzcz1cImdyaWQtc3RhY2staXRlbS1jb250ZW50XCI+PC9kaXY+YDtcbiAgICAgICAgICAgICAgICBjb250ZW50ID0gZG9jLmJvZHkuY2hpbGRyZW5bMF07XG4gICAgICAgICAgICAgICAgbm9kZS5lbC5hcHBlbmRDaGlsZChjb250ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3ByZXBhcmVEcmFnRHJvcEJ5Tm9kZShub2RlKTsgLy8gLi4uIGFuZCByZXN0b3JlIG9yaWdpbmFsIEQmRFxuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHdlJ3JlIGFkZGluZyBhbiBhZGRpdGlvbmFsIGl0ZW0sIG1ha2UgdGhlIGNvbnRhaW5lciBsYXJnZSBlbm91Z2ggdG8gaGF2ZSB0aGVtIGJvdGhcbiAgICAgICAgaWYgKG5vZGVUb0FkZCkge1xuICAgICAgICAgICAgbGV0IHcgPSBhdXRvQ29sdW1uID8gb3BzLmNvbHVtbiA6IG5vZGUudztcbiAgICAgICAgICAgIGxldCBoID0gbm9kZS5oICsgbm9kZVRvQWRkLmg7XG4gICAgICAgICAgICBsZXQgc3R5bGUgPSBub2RlLmVsLnN0eWxlO1xuICAgICAgICAgICAgc3R5bGUudHJhbnNpdGlvbiA9ICdub25lJzsgLy8gc2hvdyB1cCBpbnN0YW50bHkgc28gd2UgZG9uJ3Qgc2VlIHNjcm9sbGJhciB3aXRoIG5vZGVUb0FkZFxuICAgICAgICAgICAgdGhpcy51cGRhdGUobm9kZS5lbCwgeyB3LCBoIH0pO1xuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiBzdHlsZS50cmFuc2l0aW9uID0gbnVsbCk7IC8vIHJlY292ZXIgYW5pbWF0aW9uXG4gICAgICAgIH1cbiAgICAgICAgbGV0IHN1YkdyaWQgPSBub2RlLnN1YkdyaWQgPSBHcmlkU3RhY2suYWRkR3JpZChjb250ZW50LCBvcHMpO1xuICAgICAgICBpZiAobm9kZVRvQWRkPy5fbW92aW5nKVxuICAgICAgICAgICAgc3ViR3JpZC5faXNUZW1wID0gdHJ1ZTsgLy8gcHJldmVudCByZS1uZXN0aW5nIGFzIHdlIGFkZCBvdmVyXG4gICAgICAgIGlmIChhdXRvQ29sdW1uKVxuICAgICAgICAgICAgc3ViR3JpZC5fYXV0b0NvbHVtbiA9IHRydWU7XG4gICAgICAgIC8vIGFkZCB0aGUgb3JpZ2luYWwgY29udGVudCBiYWNrIGFzIGEgY2hpbGQgb2YgaHRlIG5ld2x5IGNyZWF0ZWQgZ3JpZFxuICAgICAgICBpZiAoc2F2ZUNvbnRlbnQpIHtcbiAgICAgICAgICAgIHN1YkdyaWQuYWRkV2lkZ2V0KG5ld0l0ZW0sIG5ld0l0ZW1PcHQpO1xuICAgICAgICB9XG4gICAgICAgIC8vIG5vdyBhZGQgYW55IGFkZGl0aW9uYWwgbm9kZVxuICAgICAgICBpZiAobm9kZVRvQWRkKSB7XG4gICAgICAgICAgICBpZiAobm9kZVRvQWRkLl9tb3ZpbmcpIHtcbiAgICAgICAgICAgICAgICAvLyBjcmVhdGUgYW4gYXJ0aWZpY2lhbCBldmVudCBldmVuIGZvciB0aGUganVzdCBjcmVhdGVkIGdyaWQgdG8gcmVjZWl2ZSB0aGlzIGl0ZW1cbiAgICAgICAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiBVdGlscy5zaW11bGF0ZU1vdXNlRXZlbnQobm9kZVRvQWRkLl9ldmVudCwgJ21vdXNlZW50ZXInLCBzdWJHcmlkLmVsKSwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdWJHcmlkLmFkZFdpZGdldChub2RlLmVsLCBub2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3ViR3JpZDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogY2FsbGVkIHdoZW4gYW4gaXRlbSB3YXMgY29udmVydGVkIGludG8gYSBuZXN0ZWQgZ3JpZCB0byBhY2NvbW1vZGF0ZSBhIGRyYWdnZWQgb3ZlciBpdGVtLCBidXQgdGhlbiBpdGVtIGxlYXZlcyAtIHJldHVybiBiYWNrXG4gICAgICogdG8gdGhlIG9yaWdpbmFsIGdyaWQtaXRlbS4gQWxzbyBjYWxsZWQgdG8gcmVtb3ZlIGVtcHR5IHN1Yi1ncmlkcyB3aGVuIGxhc3QgaXRlbSBpcyBkcmFnZ2VkIG91dCAoc2luY2UgcmUtY3JlYXRpbmcgaXMgc2ltcGxlKVxuICAgICAqL1xuICAgIHJlbW92ZUFzU3ViR3JpZChub2RlVGhhdFJlbW92ZWQpIHtcbiAgICAgICAgbGV0IHBHcmlkID0gdGhpcy5wYXJlbnRHcmlkSXRlbT8uZ3JpZDtcbiAgICAgICAgaWYgKCFwR3JpZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgcEdyaWQuYmF0Y2hVcGRhdGUoKTtcbiAgICAgICAgcEdyaWQucmVtb3ZlV2lkZ2V0KHRoaXMucGFyZW50R3JpZEl0ZW0uZWwsIHRydWUsIHRydWUpO1xuICAgICAgICB0aGlzLmVuZ2luZS5ub2Rlcy5mb3JFYWNoKG4gPT4ge1xuICAgICAgICAgICAgLy8gbWlncmF0ZSBhbnkgY2hpbGRyZW4gb3ZlciBhbmQgb2Zmc2V0dGluZyBieSBvdXIgbG9jYXRpb25cbiAgICAgICAgICAgIG4ueCArPSB0aGlzLnBhcmVudEdyaWRJdGVtLng7XG4gICAgICAgICAgICBuLnkgKz0gdGhpcy5wYXJlbnRHcmlkSXRlbS55O1xuICAgICAgICAgICAgcEdyaWQuYWRkV2lkZ2V0KG4uZWwsIG4pO1xuICAgICAgICB9KTtcbiAgICAgICAgcEdyaWQuYmF0Y2hVcGRhdGUoZmFsc2UpO1xuICAgICAgICBpZiAodGhpcy5wYXJlbnRHcmlkSXRlbSlcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnBhcmVudEdyaWRJdGVtLnN1YkdyaWQ7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnBhcmVudEdyaWRJdGVtO1xuICAgICAgICAvLyBjcmVhdGUgYW4gYXJ0aWZpY2lhbCBldmVudCBmb3IgdGhlIG9yaWdpbmFsIGdyaWQgbm93IHRoYXQgdGhpcyBvbmUgaXMgZ29uZSAoZ290IGEgbGVhdmUsIGJ1dCB3b24ndCBnZXQgZW50ZXIpXG4gICAgICAgIGlmIChub2RlVGhhdFJlbW92ZWQpIHtcbiAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IFV0aWxzLnNpbXVsYXRlTW91c2VFdmVudChub2RlVGhhdFJlbW92ZWQuX2V2ZW50LCAnbW91c2VlbnRlcicsIHBHcmlkLmVsKSwgMCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogc2F2ZXMgdGhlIGN1cnJlbnQgbGF5b3V0IHJldHVybmluZyBhIGxpc3Qgb2Ygd2lkZ2V0cyBmb3Igc2VyaWFsaXphdGlvbiB3aGljaCBtaWdodCBpbmNsdWRlIGFueSBuZXN0ZWQgZ3JpZHMuXG4gICAgICogQHBhcmFtIHNhdmVDb250ZW50IGlmIHRydWUgKGRlZmF1bHQpIHRoZSBsYXRlc3QgaHRtbCBpbnNpZGUgLmdyaWQtc3RhY2stY29udGVudCB3aWxsIGJlIHNhdmVkIHRvIEdyaWRTdGFja1dpZGdldC5jb250ZW50IGZpZWxkLCBlbHNlIGl0IHdpbGxcbiAgICAgKiBiZSByZW1vdmVkLlxuICAgICAqIEBwYXJhbSBzYXZlR3JpZE9wdCBpZiB0cnVlIChkZWZhdWx0IGZhbHNlKSwgc2F2ZSB0aGUgZ3JpZCBvcHRpb25zIGl0c2VsZiwgc28geW91IGNhbiBjYWxsIHRoZSBuZXcgR3JpZFN0YWNrLmFkZEdyaWQoKVxuICAgICAqIHRvIHJlY3JlYXRlIGV2ZXJ5dGhpbmcgZnJvbSBzY3JhdGNoLiBHcmlkU3RhY2tPcHRpb25zLmNoaWxkcmVuIHdvdWxkIHRoZW4gY29udGFpbiB0aGUgd2lkZ2V0IGxpc3QgaW5zdGVhZC5cbiAgICAgKiBAcGFyYW0gc2F2ZUNCIGNhbGxiYWNrIGZvciBlYWNoIG5vZGUgLT4gd2lkZ2V0LCBzbyBhcHBsaWNhdGlvbiBjYW4gaW5zZXJ0IGFkZGl0aW9uYWwgZGF0YSB0byBiZSBzYXZlZCBpbnRvIHRoZSB3aWRnZXQgZGF0YSBzdHJ1Y3R1cmUuXG4gICAgICogQHJldHVybnMgbGlzdCBvZiB3aWRnZXRzIG9yIGZ1bGwgZ3JpZCBvcHRpb24sIGluY2x1ZGluZyAuY2hpbGRyZW4gbGlzdCBvZiB3aWRnZXRzXG4gICAgICovXG4gICAgc2F2ZShzYXZlQ29udGVudCA9IHRydWUsIHNhdmVHcmlkT3B0ID0gZmFsc2UsIHNhdmVDQiA9IEdyaWRTdGFjay5zYXZlQ0IpIHtcbiAgICAgICAgLy8gcmV0dXJuIGNvcGllZCBHcmlkU3RhY2tXaWRnZXQgKHdpdGggb3B0aW9uYWxseSAuZWwpIHdlIGNhbiBtb2RpZnkgYXQgd2lsbC4uLlxuICAgICAgICBsZXQgbGlzdCA9IHRoaXMuZW5naW5lLnNhdmUoc2F2ZUNvbnRlbnQsIHNhdmVDQik7XG4gICAgICAgIC8vIGNoZWNrIGZvciBIVE1MIGNvbnRlbnQgYW5kIG5lc3RlZCBncmlkc1xuICAgICAgICBsaXN0LmZvckVhY2gobiA9PiB7XG4gICAgICAgICAgICBpZiAoc2F2ZUNvbnRlbnQgJiYgbi5lbCAmJiAhbi5zdWJHcmlkICYmICFzYXZlQ0IpIHsgLy8gc3ViLWdyaWQgYXJlIHNhdmVkIGRpZmZlcmVudGx5LCBub3QgcGxhaW4gY29udGVudFxuICAgICAgICAgICAgICAgIGxldCBzdWIgPSBuLmVsLnF1ZXJ5U2VsZWN0b3IoJy5ncmlkLXN0YWNrLWl0ZW0tY29udGVudCcpO1xuICAgICAgICAgICAgICAgIG4uY29udGVudCA9IHN1YiA/IHN1Yi5pbm5lckhUTUwgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgaWYgKCFuLmNvbnRlbnQpXG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBuLmNvbnRlbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoIXNhdmVDb250ZW50ICYmICFzYXZlQ0IpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG4uY29udGVudDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gY2hlY2sgZm9yIG5lc3RlZCBncmlkXG4gICAgICAgICAgICAgICAgaWYgKG4uc3ViR3JpZD8uZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGlzdE9yT3B0ID0gbi5zdWJHcmlkLnNhdmUoc2F2ZUNvbnRlbnQsIHNhdmVHcmlkT3B0LCBzYXZlQ0IpO1xuICAgICAgICAgICAgICAgICAgICBuLnN1YkdyaWRPcHRzID0gKHNhdmVHcmlkT3B0ID8gbGlzdE9yT3B0IDogeyBjaGlsZHJlbjogbGlzdE9yT3B0IH0pO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgbi5zdWJHcmlkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBuLmVsO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gY2hlY2sgaWYgc2F2ZSBlbnRpcmUgZ3JpZCBvcHRpb25zIChuZWVkZWQgZm9yIHJlY3Vyc2l2ZSkgKyBjaGlsZHJlbi4uLlxuICAgICAgICBpZiAoc2F2ZUdyaWRPcHQpIHtcbiAgICAgICAgICAgIGxldCBvID0gVXRpbHMuY2xvbmVEZWVwKHRoaXMub3B0cyk7XG4gICAgICAgICAgICAvLyBkZWxldGUgZGVmYXVsdCB2YWx1ZXMgdGhhdCB3aWxsIGJlIHJlY3JlYXRlZCBvbiBsYXVuY2hcbiAgICAgICAgICAgIGlmIChvLm1hcmdpbkJvdHRvbSA9PT0gby5tYXJnaW5Ub3AgJiYgby5tYXJnaW5SaWdodCA9PT0gby5tYXJnaW5MZWZ0ICYmIG8ubWFyZ2luVG9wID09PSBvLm1hcmdpblJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgby5tYXJnaW4gPSBvLm1hcmdpblRvcDtcbiAgICAgICAgICAgICAgICBkZWxldGUgby5tYXJnaW5Ub3A7XG4gICAgICAgICAgICAgICAgZGVsZXRlIG8ubWFyZ2luUmlnaHQ7XG4gICAgICAgICAgICAgICAgZGVsZXRlIG8ubWFyZ2luQm90dG9tO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvLm1hcmdpbkxlZnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoby5ydGwgPT09ICh0aGlzLmVsLnN0eWxlLmRpcmVjdGlvbiA9PT0gJ3J0bCcpKSB7XG4gICAgICAgICAgICAgICAgby5ydGwgPSAnYXV0byc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNBdXRvQ2VsbEhlaWdodCkge1xuICAgICAgICAgICAgICAgIG8uY2VsbEhlaWdodCA9ICdhdXRvJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9hdXRvQ29sdW1uKSB7XG4gICAgICAgICAgICAgICAgby5jb2x1bW4gPSAnYXV0byc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvcmlnU2hvdyA9IG8uX2Fsd2F5c1Nob3dSZXNpemVIYW5kbGU7XG4gICAgICAgICAgICBkZWxldGUgby5fYWx3YXlzU2hvd1Jlc2l6ZUhhbmRsZTtcbiAgICAgICAgICAgIGlmIChvcmlnU2hvdyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgby5hbHdheXNTaG93UmVzaXplSGFuZGxlID0gb3JpZ1Nob3c7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgby5hbHdheXNTaG93UmVzaXplSGFuZGxlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgVXRpbHMucmVtb3ZlSW50ZXJuYWxBbmRTYW1lKG8sIGdyaWREZWZhdWx0cyk7XG4gICAgICAgICAgICBvLmNoaWxkcmVuID0gbGlzdDtcbiAgICAgICAgICAgIHJldHVybiBvO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsaXN0O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBsb2FkIHRoZSB3aWRnZXRzIGZyb20gYSBsaXN0LiBUaGlzIHdpbGwgY2FsbCB1cGRhdGUoKSBvbiBlYWNoIChtYXRjaGluZyBieSBpZCkgb3IgYWRkL3JlbW92ZSB3aWRnZXRzIHRoYXQgYXJlIG5vdCB0aGVyZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBsYXlvdXQgbGlzdCBvZiB3aWRnZXRzIGRlZmluaXRpb24gdG8gdXBkYXRlL2NyZWF0ZVxuICAgICAqIEBwYXJhbSBhZGRBbmRSZW1vdmUgYm9vbGVhbiAoZGVmYXVsdCB0cnVlKSBvciBjYWxsYmFjayBtZXRob2QgY2FuIGJlIHBhc3NlZCB0byBjb250cm9sIGlmIGFuZCBob3cgbWlzc2luZyB3aWRnZXRzIGNhbiBiZSBhZGRlZC9yZW1vdmVkLCBnaXZpbmdcbiAgICAgKiB0aGUgdXNlciBjb250cm9sIG9mIGluc2VydGlvbi5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogc2VlIGh0dHA6Ly9ncmlkc3RhY2tqcy5jb20vZGVtby9zZXJpYWxpemF0aW9uLmh0bWxcbiAgICAgKi9cbiAgICBsb2FkKGl0ZW1zLCBhZGRSZW1vdmUgPSBHcmlkU3RhY2suYWRkUmVtb3ZlQ0IgfHwgdHJ1ZSkge1xuICAgICAgICBpdGVtcyA9IFV0aWxzLmNsb25lRGVlcChpdGVtcyk7IC8vIHNvIHdlIGNhbiBtb2RcbiAgICAgICAgY29uc3QgY29sdW1uID0gdGhpcy5nZXRDb2x1bW4oKTtcbiAgICAgICAgLy8gaWYgd2UgaGF2ZSBhIG1peCBvZiBuZXcgaXRlbXMgd2l0aG91dCBjb29yZGluYXRlcyBhbmQgZXhpc3RpbmcgaXRlbXMsIHNlcGFyYXRlIHRoZW0gb3V0IHNvIHRoZXkgY2FuIGJlIGFkZGVkIGFmdGVyICMyNjM5XG4gICAgICAgIGxldCBhZGRBZnRlciA9IGl0ZW1zLmZpbHRlcihuID0+IChuLnggPT09IHVuZGVmaW5lZCB8fCBuLnkgPT09IHVuZGVmaW5lZCkgJiYgIVV0aWxzLmZpbmQodGhpcy5lbmdpbmUubm9kZXMsIG4uaWQpKTtcbiAgICAgICAgaWYgKGFkZEFmdGVyLmxlbmd0aCAmJiBhZGRBZnRlci5sZW5ndGggIT09IGl0ZW1zLmxlbmd0aCkge1xuICAgICAgICAgICAgaXRlbXMgPSBpdGVtcy5maWx0ZXIobiA9PiAhVXRpbHMuZmluZChhZGRBZnRlciwgbi5pZCkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGFkZEFmdGVyID0gW107XG4gICAgICAgIC8vIGlmIHBhc3NlZCBsaXN0IGhhcyBjb29yZGluYXRlcywgdXNlIHRoZW0gKGluc2VydCBmcm9tIGVuZCB0byBiZWdpbm5pbmcgZm9yIGNvbmZsaWN0IHJlc29sdXRpb24pIGVsc2Uga2VlcCB3aWRnZXQgb3JkZXJcbiAgICAgICAgY29uc3QgaGF2ZUNvb3JkID0gaXRlbXMuc29tZSh3ID0+IHcueCAhPT0gdW5kZWZpbmVkIHx8IHcueSAhPT0gdW5kZWZpbmVkKTtcbiAgICAgICAgaWYgKGhhdmVDb29yZClcbiAgICAgICAgICAgIGl0ZW1zID0gVXRpbHMuc29ydChpdGVtcywgLTEpO1xuICAgICAgICB0aGlzLl9pbnNlcnROb3RBcHBlbmQgPSBoYXZlQ29vcmQ7IC8vIGlmIHdlIGNyZWF0ZSBpbiByZXZlcnNlIG9yZGVyLi4uXG4gICAgICAgIC8vIGlmIHdlJ3JlIGxvYWRpbmcgYSBsYXlvdXQgaW50byBmb3IgZXhhbXBsZSAxIGNvbHVtbiBhbmQgaXRlbXMgZG9uJ3QgZml0LCBtYWtlIHN1cmUgdG8gc2F2ZVxuICAgICAgICAvLyB0aGUgb3JpZ2luYWwgd2FudGVkIGxheW91dCBzbyB3ZSBjYW4gc2NhbGUgYmFjayB1cCBjb3JyZWN0bHkgIzE0NzFcbiAgICAgICAgaWYgKGl0ZW1zLnNvbWUobiA9PiAoKG4ueCB8fCAwKSArIChuLncgfHwgMSkpID4gY29sdW1uKSkge1xuICAgICAgICAgICAgdGhpcy5faWdub3JlTGF5b3V0c05vZGVDaGFuZ2UgPSB0cnVlOyAvLyBza2lwIGxheW91dCB1cGRhdGVcbiAgICAgICAgICAgIHRoaXMuZW5naW5lLmNhY2hlTGF5b3V0KGl0ZW1zLCAxMiwgdHJ1ZSk7IC8vIFRPRE86IDEyIGlzIGFyYml0cmFyeS4gdXNlIG1heCB2YWx1ZSBpbiBsYXlvdXQgP1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIGdpdmVuIGEgZGlmZmVyZW50IGNhbGxiYWNrLCB0ZW1wb3JhbGx5IHNldCBpdCBhcyBnbG9iYWwgb3B0aW9uIHNvIGNyZWF0aW5nIHdpbGwgdXNlIGl0XG4gICAgICAgIGNvbnN0IHByZXZDQiA9IEdyaWRTdGFjay5hZGRSZW1vdmVDQjtcbiAgICAgICAgaWYgKHR5cGVvZiAoYWRkUmVtb3ZlKSA9PT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgICAgIEdyaWRTdGFjay5hZGRSZW1vdmVDQiA9IGFkZFJlbW92ZTtcbiAgICAgICAgbGV0IHJlbW92ZWQgPSBbXTtcbiAgICAgICAgdGhpcy5iYXRjaFVwZGF0ZSgpO1xuICAgICAgICAvLyBpZiB3ZSBhcmUgYmxhbmsgKGxvYWRpbmcgaW50byBlbXB0eSBsaWtlIHN0YXJ0dXApIHRlbXAgcmVtb3ZlIGFuaW1hdGlvblxuICAgICAgICBjb25zdCBub0FuaW0gPSAhdGhpcy5lbmdpbmUubm9kZXMubGVuZ3RoO1xuICAgICAgICBpZiAobm9BbmltKVxuICAgICAgICAgICAgdGhpcy5zZXRBbmltYXRpb24oZmFsc2UpO1xuICAgICAgICAvLyBzZWUgaWYgYW55IGl0ZW1zIGFyZSBtaXNzaW5nIGZyb20gbmV3IGxheW91dCBhbmQgbmVlZCB0byBiZSByZW1vdmVkIGZpcnN0XG4gICAgICAgIGlmIChhZGRSZW1vdmUpIHtcbiAgICAgICAgICAgIGxldCBjb3B5Tm9kZXMgPSBbLi4udGhpcy5lbmdpbmUubm9kZXNdOyAvLyBkb24ndCBsb29wIHRocm91Z2ggYXJyYXkgeW91IG1vZGlmeVxuICAgICAgICAgICAgY29weU5vZGVzLmZvckVhY2gobiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFuLmlkKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgbGV0IGl0ZW0gPSBVdGlscy5maW5kKGl0ZW1zLCBuLmlkKTtcbiAgICAgICAgICAgICAgICBpZiAoIWl0ZW0pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEdyaWRTdGFjay5hZGRSZW1vdmVDQilcbiAgICAgICAgICAgICAgICAgICAgICAgIEdyaWRTdGFjay5hZGRSZW1vdmVDQih0aGlzLmVsLCBuLCBmYWxzZSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVkLnB1c2gobik7IC8vIGJhdGNoIGtlZXAgdHJhY2tcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVXaWRnZXQobi5lbCwgdHJ1ZSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIG5vdyBhZGQvdXBkYXRlIHRoZSB3aWRnZXRzIC0gc3RhcnRpbmcgd2l0aCByZW1vdmluZyBpdGVtcyBpbiB0aGUgbmV3IGxheW91dCB3ZSB3aWxsIHJlcG9zaXRpb25cbiAgICAgICAgLy8gdG8gcmVkdWNlIGNvbGxpc2lvbiBhbmQgYWRkIG5vLWNvb3JkIG9uZXMgYXQgbmV4dCBhdmFpbGFibGUgc3BvdFxuICAgICAgICBsZXQgdXBkYXRlTm9kZXMgPSBbXTtcbiAgICAgICAgdGhpcy5lbmdpbmUubm9kZXMgPSB0aGlzLmVuZ2luZS5ub2Rlcy5maWx0ZXIobiA9PiB7XG4gICAgICAgICAgICBpZiAoVXRpbHMuZmluZChpdGVtcywgbi5pZCkpIHtcbiAgICAgICAgICAgICAgICB1cGRhdGVOb2Rlcy5wdXNoKG4pO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH0gLy8gcmVtb3ZlIGlmIGZvdW5kIGZyb20gbGlzdFxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pO1xuICAgICAgICBpdGVtcy5mb3JFYWNoKHcgPT4ge1xuICAgICAgICAgICAgbGV0IGl0ZW0gPSBVdGlscy5maW5kKHVwZGF0ZU5vZGVzLCB3LmlkKTtcbiAgICAgICAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgaXRlbSBzaXplcyB0byBjb250ZW50LCByZS11c2UgdGhlIGV4aXRpbmcgaGVpZ2h0IHNvIGl0J3MgYSBiZXR0ZXIgZ3Vlc3MgYXQgdGhlIGZpbmFsIHNpemUgKHNhbWUgaWYgd2lkdGggZG9lc24ndCBjaGFuZ2UpXG4gICAgICAgICAgICAgICAgaWYgKFV0aWxzLnNob3VsZFNpemVUb0NvbnRlbnQoaXRlbSkpXG4gICAgICAgICAgICAgICAgICAgIHcuaCA9IGl0ZW0uaDtcbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiBtaXNzaW5nIGNvb3JkLCBpbiB3aGljaCBjYXNlIGZpbmQgbmV4dCBlbXB0eSBzbG90IHdpdGggbmV3IChvciBvbGQgaWYgbWlzc2luZykgc2l6ZXNcbiAgICAgICAgICAgICAgICB0aGlzLmVuZ2luZS5ub2RlQm91bmRGaXgodyk7XG4gICAgICAgICAgICAgICAgaWYgKHcuYXV0b1Bvc2l0aW9uIHx8IHcueCA9PT0gdW5kZWZpbmVkIHx8IHcueSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHcudyA9IHcudyB8fCBpdGVtLnc7XG4gICAgICAgICAgICAgICAgICAgIHcuaCA9IHcuaCB8fCBpdGVtLmg7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW5naW5lLmZpbmRFbXB0eVBvc2l0aW9uKHcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBhZGQgYmFjayB0byBjdXJyZW50IGxpc3QgQlVUIGZvcmNlIGEgY29sbGlzaW9uIGNoZWNrIGlmIGl0ICdhcHBlYXJzJyB3ZSBkaWRuJ3QgY2hhbmdlIHRvIG1ha2Ugc3VyZSB3ZSBkb24ndCBvdmVybGFwIG90aGVycyBub3dcbiAgICAgICAgICAgICAgICB0aGlzLmVuZ2luZS5ub2Rlcy5wdXNoKGl0ZW0pO1xuICAgICAgICAgICAgICAgIGlmIChVdGlscy5zYW1lUG9zKGl0ZW0sIHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubW92ZU5vZGUoaXRlbSwgeyAuLi53LCBmb3JjZUNvbGxpZGU6IHRydWUgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKGl0ZW0uZWwsIHcpO1xuICAgICAgICAgICAgICAgIGlmICh3LnN1YkdyaWRPcHRzPy5jaGlsZHJlbikgeyAvLyB1cGRhdGUgYW55IHN1YiBncmlkIGFzIHdlbGxcbiAgICAgICAgICAgICAgICAgICAgbGV0IHN1YiA9IGl0ZW0uZWwucXVlcnlTZWxlY3RvcignLmdyaWQtc3RhY2snKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN1YiAmJiBzdWIuZ3JpZHN0YWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWIuZ3JpZHN0YWNrLmxvYWQody5zdWJHcmlkT3B0cy5jaGlsZHJlbik7IC8vIFRPRE86IHN1cHBvcnQgdXBkYXRpbmcgZ3JpZCBvcHRpb25zID9cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2luc2VydE5vdEFwcGVuZCA9IHRydWU7IC8vIGdvdCByZXNldCBieSBhYm92ZSBjYWxsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChhZGRSZW1vdmUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZFdpZGdldCh3KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIC8vIGZpbmFsbHkgYXBwZW5kIGFueSBzZXBhcmF0ZSBvbmVzIHRoYXQgZGlkbid0IGhhdmUgZXhwbGljaXQgY29vcmRpbmF0ZXMgbGFzdCBzbyB0aGV5IGNhbiBmaW5kIG5leHQgZW1wdHkgc3BvdFxuICAgICAgICBpZiAoYWRkUmVtb3ZlKSB7XG4gICAgICAgICAgICBhZGRBZnRlci5mb3JFYWNoKHcgPT4gdGhpcy5hZGRXaWRnZXQodykpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZW5naW5lLnJlbW92ZWROb2RlcyA9IHJlbW92ZWQ7XG4gICAgICAgIHRoaXMuYmF0Y2hVcGRhdGUoZmFsc2UpO1xuICAgICAgICAvLyBhZnRlciBjb21taXQsIGNsZWFyIHRoYXQgZmxhZ1xuICAgICAgICBkZWxldGUgdGhpcy5faWdub3JlTGF5b3V0c05vZGVDaGFuZ2U7XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9pbnNlcnROb3RBcHBlbmQ7XG4gICAgICAgIHByZXZDQiA/IEdyaWRTdGFjay5hZGRSZW1vdmVDQiA9IHByZXZDQiA6IGRlbGV0ZSBHcmlkU3RhY2suYWRkUmVtb3ZlQ0I7XG4gICAgICAgIC8vIGRlbGF5IGFkZGluZyBhbmltYXRpb24gYmFjaywgYnV0IGNoZWNrIHRvIG1ha2Ugc3VyZSBncmlkIChvcHQpIGlzIHN0aWxsIGFyb3VuZFxuICAgICAgICBpZiAobm9BbmltICYmIHRoaXMub3B0cz8uYW5pbWF0ZSlcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4geyBpZiAodGhpcy5vcHRzKVxuICAgICAgICAgICAgICAgIHRoaXMuc2V0QW5pbWF0aW9uKHRoaXMub3B0cy5hbmltYXRlKTsgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiB1c2UgYmVmb3JlIGNhbGxpbmcgYSBidW5jaCBvZiBgYWRkV2lkZ2V0KClgIHRvIHByZXZlbnQgdW4tbmVjZXNzYXJ5IHJlbGF5b3V0cyBpbiBiZXR3ZWVuIChtb3JlIGVmZmljaWVudClcbiAgICAgKiBhbmQgZ2V0IGEgc2luZ2xlIGV2ZW50IGNhbGxiYWNrLiBZb3Ugd2lsbCBzZWUgbm8gY2hhbmdlcyB1bnRpbCBgYmF0Y2hVcGRhdGUoZmFsc2UpYCBpcyBjYWxsZWQuXG4gICAgICovXG4gICAgYmF0Y2hVcGRhdGUoZmxhZyA9IHRydWUpIHtcbiAgICAgICAgdGhpcy5lbmdpbmUuYmF0Y2hVcGRhdGUoZmxhZyk7XG4gICAgICAgIGlmICghZmxhZykge1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlQ29udGFpbmVySGVpZ2h0KCk7XG4gICAgICAgICAgICB0aGlzLl90cmlnZ2VyUmVtb3ZlRXZlbnQoKTtcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJBZGRFdmVudCgpO1xuICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckNoYW5nZUV2ZW50KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldHMgY3VycmVudCBjZWxsIGhlaWdodC5cbiAgICAgKi9cbiAgICBnZXRDZWxsSGVpZ2h0KGZvcmNlUGl4ZWwgPSBmYWxzZSkge1xuICAgICAgICBpZiAodGhpcy5vcHRzLmNlbGxIZWlnaHQgJiYgdGhpcy5vcHRzLmNlbGxIZWlnaHQgIT09ICdhdXRvJyAmJlxuICAgICAgICAgICAgKCFmb3JjZVBpeGVsIHx8ICF0aGlzLm9wdHMuY2VsbEhlaWdodFVuaXQgfHwgdGhpcy5vcHRzLmNlbGxIZWlnaHRVbml0ID09PSAncHgnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub3B0cy5jZWxsSGVpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIC8vIGRvIHJlbS9lbS9jbS9tbSB0byBweCBjb252ZXJzaW9uXG4gICAgICAgIGlmICh0aGlzLm9wdHMuY2VsbEhlaWdodFVuaXQgPT09ICdyZW0nKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vcHRzLmNlbGxIZWlnaHQgKiBwYXJzZUZsb2F0KGdldENvbXB1dGVkU3R5bGUoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS5mb250U2l6ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMub3B0cy5jZWxsSGVpZ2h0VW5pdCA9PT0gJ2VtJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub3B0cy5jZWxsSGVpZ2h0ICogcGFyc2VGbG9hdChnZXRDb21wdXRlZFN0eWxlKHRoaXMuZWwpLmZvbnRTaXplKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5vcHRzLmNlbGxIZWlnaHRVbml0ID09PSAnY20nKSB7XG4gICAgICAgICAgICAvLyAxY20gPSA5NnB4LzIuNTQuIFNlZSBodHRwczovL3d3dy53My5vcmcvVFIvY3NzLXZhbHVlcy0zLyNhYnNvbHV0ZS1sZW5ndGhzXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vcHRzLmNlbGxIZWlnaHQgKiAoOTYgLyAyLjU0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5vcHRzLmNlbGxIZWlnaHRVbml0ID09PSAnbW0nKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vcHRzLmNlbGxIZWlnaHQgKiAoOTYgLyAyLjU0KSAvIDEwO1xuICAgICAgICB9XG4gICAgICAgIC8vIGVsc2UgZ2V0IGZpcnN0IGNlbGwgaGVpZ2h0XG4gICAgICAgIGxldCBlbCA9IHRoaXMuZWwucXVlcnlTZWxlY3RvcignLicgKyB0aGlzLm9wdHMuaXRlbUNsYXNzKTtcbiAgICAgICAgaWYgKGVsKSB7XG4gICAgICAgICAgICBsZXQgaCA9IFV0aWxzLnRvTnVtYmVyKGVsLmdldEF0dHJpYnV0ZSgnZ3MtaCcpKSB8fCAxOyAvLyBzaW5jZSB3ZSBkb24ndCB3cml0ZSAxIGFueW1vcmVcbiAgICAgICAgICAgIHJldHVybiBNYXRoLnJvdW5kKGVsLm9mZnNldEhlaWdodCAvIGgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGVsc2UgZG8gZW50aXJlIGdyaWQgYW5kICMgb2Ygcm93cyAoYnV0IGRvZXNuJ3Qgd29yayBpZiBtaW4taGVpZ2h0IGlzIHRoZSBhY3R1YWwgY29uc3RyYWluKVxuICAgICAgICBsZXQgcm93cyA9IHBhcnNlSW50KHRoaXMuZWwuZ2V0QXR0cmlidXRlKCdncy1jdXJyZW50LXJvdycpKTtcbiAgICAgICAgcmV0dXJuIHJvd3MgPyBNYXRoLnJvdW5kKHRoaXMuZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0IC8gcm93cykgOiB0aGlzLm9wdHMuY2VsbEhlaWdodDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVXBkYXRlIGN1cnJlbnQgY2VsbCBoZWlnaHQgLSBzZWUgYEdyaWRTdGFja09wdGlvbnMuY2VsbEhlaWdodGAgZm9yIGZvcm1hdC5cbiAgICAgKiBUaGlzIG1ldGhvZCByZWJ1aWxkcyBhbiBpbnRlcm5hbCBDU1Mgc3R5bGUgc2hlZXQuXG4gICAgICogTm90ZTogWW91IGNhbiBleHBlY3QgcGVyZm9ybWFuY2UgaXNzdWVzIGlmIGNhbGwgdGhpcyBtZXRob2QgdG9vIG9mdGVuLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbCB0aGUgY2VsbCBoZWlnaHQuIElmIG5vdCBwYXNzZWQgKHVuZGVmaW5lZCksIGNlbGxzIGNvbnRlbnQgd2lsbCBiZSBtYWRlIHNxdWFyZSAobWF0Y2ggd2lkdGggbWludXMgbWFyZ2luKSxcbiAgICAgKiBpZiBwYXNzIDAgdGhlIENTUyB3aWxsIGJlIGdlbmVyYXRlZCBieSB0aGUgYXBwbGljYXRpb24gaW5zdGVhZC5cbiAgICAgKiBAcGFyYW0gdXBkYXRlIChPcHRpb25hbCkgaWYgZmFsc2UsIHN0eWxlcyB3aWxsIG5vdCBiZSB1cGRhdGVkXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGdyaWQuY2VsbEhlaWdodCgxMDApOyAvLyBzYW1lIGFzIDEwMHB4XG4gICAgICogZ3JpZC5jZWxsSGVpZ2h0KCc3MHB4Jyk7XG4gICAgICogZ3JpZC5jZWxsSGVpZ2h0KGdyaWQuY2VsbFdpZHRoKCkgKiAxLjIpO1xuICAgICAqL1xuICAgIGNlbGxIZWlnaHQodmFsLCB1cGRhdGUgPSB0cnVlKSB7XG4gICAgICAgIC8vIGlmIG5vdCBjYWxsZWQgaW50ZXJuYWxseSwgY2hlY2sgaWYgd2UncmUgY2hhbmdpbmcgbW9kZVxuICAgICAgICBpZiAodXBkYXRlICYmIHZhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5faXNBdXRvQ2VsbEhlaWdodCAhPT0gKHZhbCA9PT0gJ2F1dG8nKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2lzQXV0b0NlbGxIZWlnaHQgPSAodmFsID09PSAnYXV0bycpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZVJlc2l6ZUV2ZW50KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbCA9PT0gJ2luaXRpYWwnIHx8IHZhbCA9PT0gJ2F1dG8nKSB7XG4gICAgICAgICAgICB2YWwgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gbWFrZSBpdGVtIGNvbnRlbnQgYmUgc3F1YXJlXG4gICAgICAgIGlmICh2YWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgbGV0IG1hcmdpbkRpZmYgPSAtdGhpcy5vcHRzLm1hcmdpblJpZ2h0IC0gdGhpcy5vcHRzLm1hcmdpbkxlZnRcbiAgICAgICAgICAgICAgICArIHRoaXMub3B0cy5tYXJnaW5Ub3AgKyB0aGlzLm9wdHMubWFyZ2luQm90dG9tO1xuICAgICAgICAgICAgdmFsID0gdGhpcy5jZWxsV2lkdGgoKSArIG1hcmdpbkRpZmY7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGRhdGEgPSBVdGlscy5wYXJzZUhlaWdodCh2YWwpO1xuICAgICAgICBpZiAodGhpcy5vcHRzLmNlbGxIZWlnaHRVbml0ID09PSBkYXRhLnVuaXQgJiYgdGhpcy5vcHRzLmNlbGxIZWlnaHQgPT09IGRhdGEuaCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vcHRzLmNlbGxIZWlnaHRVbml0ID0gZGF0YS51bml0O1xuICAgICAgICB0aGlzLm9wdHMuY2VsbEhlaWdodCA9IGRhdGEuaDtcbiAgICAgICAgdGhpcy5yZXNpemVUb0NvbnRlbnRDaGVjaygpO1xuICAgICAgICBpZiAodXBkYXRlKSB7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVTdHlsZXModHJ1ZSk7IC8vIHRydWUgPSBmb3JjZSByZS1jcmVhdGUgZm9yIGN1cnJlbnQgIyBvZiByb3dzXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBHZXRzIGN1cnJlbnQgY2VsbCB3aWR0aC4gKi9cbiAgICBjZWxsV2lkdGgoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl93aWR0aE9yQ29udGFpbmVyKCkgLyB0aGlzLmdldENvbHVtbigpO1xuICAgIH1cbiAgICAvKiogcmV0dXJuIG91ciBleHBlY3RlZCB3aWR0aCAob3IgcGFyZW50KSAsIGFuZCBvcHRpb25hbGx5IG9mIHdpbmRvdyBmb3IgZHluYW1pYyBjb2x1bW4gY2hlY2sgKi9cbiAgICBfd2lkdGhPckNvbnRhaW5lcihmb3JCcmVha3BvaW50ID0gZmFsc2UpIHtcbiAgICAgICAgLy8gdXNlIGBvZmZzZXRXaWR0aGAgb3IgYGNsaWVudFdpZHRoYCAobm8gc2Nyb2xsYmFyKSA/XG4gICAgICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIxMDY0MTAxL3VuZGVyc3RhbmRpbmctb2Zmc2V0d2lkdGgtY2xpZW50d2lkdGgtc2Nyb2xsd2lkdGgtYW5kLWhlaWdodC1yZXNwZWN0aXZlbHlcbiAgICAgICAgcmV0dXJuIGZvckJyZWFrcG9pbnQgJiYgdGhpcy5vcHRzLmNvbHVtbk9wdHM/LmJyZWFrcG9pbnRGb3JXaW5kb3cgPyB3aW5kb3cuaW5uZXJXaWR0aCA6ICh0aGlzLmVsLmNsaWVudFdpZHRoIHx8IHRoaXMuZWwucGFyZW50RWxlbWVudC5jbGllbnRXaWR0aCB8fCB3aW5kb3cuaW5uZXJXaWR0aCk7XG4gICAgfVxuICAgIC8qKiBjaGVja3MgZm9yIGR5bmFtaWMgY29sdW1uIGNvdW50IGZvciBvdXIgY3VycmVudCBzaXplLCByZXR1cm5pbmcgdHJ1ZSBpZiBjaGFuZ2VkICovXG4gICAgY2hlY2tEeW5hbWljQ29sdW1uKCkge1xuICAgICAgICBjb25zdCByZXNwID0gdGhpcy5vcHRzLmNvbHVtbk9wdHM7XG4gICAgICAgIGlmICghcmVzcCB8fCAoIXJlc3AuY29sdW1uV2lkdGggJiYgIXJlc3AuYnJlYWtwb2ludHM/Lmxlbmd0aCkpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGNvbnN0IGNvbHVtbiA9IHRoaXMuZ2V0Q29sdW1uKCk7XG4gICAgICAgIGxldCBuZXdDb2x1bW4gPSBjb2x1bW47XG4gICAgICAgIGNvbnN0IHcgPSB0aGlzLl93aWR0aE9yQ29udGFpbmVyKHRydWUpO1xuICAgICAgICBpZiAocmVzcC5jb2x1bW5XaWR0aCkge1xuICAgICAgICAgICAgbmV3Q29sdW1uID0gTWF0aC5taW4oTWF0aC5yb3VuZCh3IC8gcmVzcC5jb2x1bW5XaWR0aCkgfHwgMSwgcmVzcC5jb2x1bW5NYXgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gZmluZCB0aGUgY2xvc2VzdCBicmVha3BvaW50IChhbHJlYWR5IHNvcnRlZCBiaWcgdG8gc21hbGwpIHRoYXQgbWF0Y2hlc1xuICAgICAgICAgICAgbmV3Q29sdW1uID0gcmVzcC5jb2x1bW5NYXg7XG4gICAgICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoaSA8IHJlc3AuYnJlYWtwb2ludHMubGVuZ3RoICYmIHcgPD0gcmVzcC5icmVha3BvaW50c1tpXS53KSB7XG4gICAgICAgICAgICAgICAgbmV3Q29sdW1uID0gcmVzcC5icmVha3BvaW50c1tpKytdLmMgfHwgY29sdW1uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChuZXdDb2x1bW4gIT09IGNvbHVtbikge1xuICAgICAgICAgICAgY29uc3QgYmsgPSByZXNwLmJyZWFrcG9pbnRzPy5maW5kKGIgPT4gYi5jID09PSBuZXdDb2x1bW4pO1xuICAgICAgICAgICAgdGhpcy5jb2x1bW4obmV3Q29sdW1uLCBiaz8ubGF5b3V0IHx8IHJlc3AubGF5b3V0KTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogcmUtbGF5b3V0IGdyaWQgaXRlbXMgdG8gcmVjbGFpbSBhbnkgZW1wdHkgc3BhY2UuIE9wdGlvbnMgYXJlOlxuICAgICAqICdsaXN0JyBrZWVwIHRoZSB3aWRnZXQgbGVmdC0+cmlnaHQgb3JkZXIgdGhlIHNhbWUsIGV2ZW4gaWYgdGhhdCBtZWFucyBsZWF2aW5nIGFuIGVtcHR5IHNsb3QgaWYgdGhpbmdzIGRvbid0IGZpdFxuICAgICAqICdjb21wYWN0JyBtaWdodCByZS1vcmRlciBpdGVtcyB0byBmaWxsIGFueSBlbXB0eSBzcGFjZVxuICAgICAqXG4gICAgICogZG9Tb3J0IC0gJ2ZhbHNlJyB0byBsZXQgeW91IGRvIHlvdXIgb3duIHNvcnRpbmcgYWhlYWQgaW4gY2FzZSB5b3UgbmVlZCB0byBjb250cm9sIGEgZGlmZmVyZW50IG9yZGVyLiAoZGVmYXVsdCB0byBzb3J0KVxuICAgICAqL1xuICAgIGNvbXBhY3QobGF5b3V0ID0gJ2NvbXBhY3QnLCBkb1NvcnQgPSB0cnVlKSB7XG4gICAgICAgIHRoaXMuZW5naW5lLmNvbXBhY3QobGF5b3V0LCBkb1NvcnQpO1xuICAgICAgICB0aGlzLl90cmlnZ2VyQ2hhbmdlRXZlbnQoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIHNldCB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIGdyaWQuIFdpbGwgdXBkYXRlIGV4aXN0aW5nIHdpZGdldHMgdG8gY29uZm9ybSB0byBuZXcgbnVtYmVyIG9mIGNvbHVtbnMsXG4gICAgICogYXMgd2VsbCBhcyBjYWNoZSB0aGUgb3JpZ2luYWwgbGF5b3V0IHNvIHlvdSBjYW4gcmV2ZXJ0IGJhY2sgdG8gcHJldmlvdXMgcG9zaXRpb25zIHdpdGhvdXQgbG9zcy5cbiAgICAgKiBSZXF1aXJlcyBgZ3JpZHN0YWNrLWV4dHJhLmNzc2Agb3IgYGdyaWRzdGFjay1leHRyYS5taW4uY3NzYCBmb3IgWzItMTFdLFxuICAgICAqIGVsc2UgeW91IHdpbGwgbmVlZCB0byBnZW5lcmF0ZSBjb3JyZWN0IENTUyAoc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9ncmlkc3RhY2svZ3JpZHN0YWNrLmpzI2NoYW5nZS1ncmlkLWNvbHVtbnMpXG4gICAgICogQHBhcmFtIGNvbHVtbiAtIEludGVnZXIgPiAwIChkZWZhdWx0IDEyKS5cbiAgICAgKiBAcGFyYW0gbGF5b3V0IHNwZWNpZnkgdGhlIHR5cGUgb2YgcmUtbGF5b3V0IHRoYXQgd2lsbCBoYXBwZW4gKHBvc2l0aW9uLCBzaXplLCBldGMuLi4pLlxuICAgICAqIE5vdGU6IGl0ZW1zIHdpbGwgbmV2ZXIgYmUgb3V0c2lkZSBvZiB0aGUgY3VycmVudCBjb2x1bW4gYm91bmRhcmllcy4gZGVmYXVsdCAoJ21vdmVTY2FsZScpLiBJZ25vcmVkIGZvciAxIGNvbHVtblxuICAgICAqL1xuICAgIGNvbHVtbihjb2x1bW4sIGxheW91dCA9ICdtb3ZlU2NhbGUnKSB7XG4gICAgICAgIGlmICghY29sdW1uIHx8IGNvbHVtbiA8IDEgfHwgdGhpcy5vcHRzLmNvbHVtbiA9PT0gY29sdW1uKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIGxldCBvbGRDb2x1bW4gPSB0aGlzLmdldENvbHVtbigpO1xuICAgICAgICB0aGlzLm9wdHMuY29sdW1uID0gY29sdW1uO1xuICAgICAgICBpZiAoIXRoaXMuZW5naW5lKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7IC8vIGNhbGxlZCBpbiBjb25zdHJ1Y3Rvciwgbm90aW5nIGVsc2UgdG8gZG9cbiAgICAgICAgdGhpcy5lbmdpbmUuY29sdW1uID0gY29sdW1uO1xuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5yZW1vdmUoJ2dzLScgKyBvbGRDb2x1bW4pO1xuICAgICAgICB0aGlzLmVsLmNsYXNzTGlzdC5hZGQoJ2dzLScgKyBjb2x1bW4pO1xuICAgICAgICAvLyB1cGRhdGUgdGhlIGl0ZW1zIG5vdywgY2hlY2tpbmcgaWYgd2UgaGF2ZSBhIGN1c3RvbSBjaGlsZHJlbiBsYXlvdXRcbiAgICAgICAgLypjb25zdCBuZXdDaGlsZHJlbiA9IHRoaXMub3B0cy5jb2x1bW5PcHRzPy5icmVha3BvaW50cz8uZmluZChyID0+IHIuYyA9PT0gY29sdW1uKT8uY2hpbGRyZW47XG4gICAgICAgIGlmIChuZXdDaGlsZHJlbikgdGhpcy5sb2FkKG5ld0NoaWxkcmVuKTtcbiAgICAgICAgZWxzZSovIHRoaXMuZW5naW5lLmNvbHVtbkNoYW5nZWQob2xkQ29sdW1uLCBjb2x1bW4sIGxheW91dCk7XG4gICAgICAgIGlmICh0aGlzLl9pc0F1dG9DZWxsSGVpZ2h0KVxuICAgICAgICAgICAgdGhpcy5jZWxsSGVpZ2h0KCk7XG4gICAgICAgIHRoaXMucmVzaXplVG9Db250ZW50Q2hlY2sodHJ1ZSk7IC8vIHdhaXQgZm9yIHdpZHRoIHJlc2l6aW5nXG4gICAgICAgIC8vIGFuZCB0cmlnZ2VyIG91ciBldmVudCBsYXN0Li4uXG4gICAgICAgIHRoaXMuX2lnbm9yZUxheW91dHNOb2RlQ2hhbmdlID0gdHJ1ZTsgLy8gc2tpcCBsYXlvdXQgdXBkYXRlXG4gICAgICAgIHRoaXMuX3RyaWdnZXJDaGFuZ2VFdmVudCgpO1xuICAgICAgICBkZWxldGUgdGhpcy5faWdub3JlTGF5b3V0c05vZGVDaGFuZ2U7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBnZXQgdGhlIG51bWJlciBvZiBjb2x1bW5zIGluIHRoZSBncmlkIChkZWZhdWx0IDEyKVxuICAgICAqL1xuICAgIGdldENvbHVtbigpIHsgcmV0dXJuIHRoaXMub3B0cy5jb2x1bW47IH1cbiAgICAvKiogcmV0dXJucyBhbiBhcnJheSBvZiBncmlkIEhUTUwgZWxlbWVudHMgKG5vIHBsYWNlaG9sZGVyKSAtIHVzZWQgdG8gaXRlcmF0ZSB0aHJvdWdoIG91ciBjaGlsZHJlbiBpbiBET00gb3JkZXIgKi9cbiAgICBnZXRHcmlkSXRlbXMoKSB7XG4gICAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMuZWwuY2hpbGRyZW4pXG4gICAgICAgICAgICAuZmlsdGVyKChlbCkgPT4gZWwubWF0Y2hlcygnLicgKyB0aGlzLm9wdHMuaXRlbUNsYXNzKSAmJiAhZWwubWF0Y2hlcygnLicgKyB0aGlzLm9wdHMucGxhY2Vob2xkZXJDbGFzcykpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBEZXN0cm95cyBhIGdyaWQgaW5zdGFuY2UuIERPIE5PVCBDQUxMIGFueSBtZXRob2RzIG9yIGFjY2VzcyBhbnkgdmFycyBhZnRlciB0aGlzIGFzIGl0IHdpbGwgZnJlZSB1cCBtZW1iZXJzLlxuICAgICAqIEBwYXJhbSByZW1vdmVET00gaWYgYGZhbHNlYCBncmlkIGFuZCBpdGVtcyBIVE1MIGVsZW1lbnRzIHdpbGwgbm90IGJlIHJlbW92ZWQgZnJvbSB0aGUgRE9NIChPcHRpb25hbC4gRGVmYXVsdCBgdHJ1ZWApLlxuICAgICAqL1xuICAgIGRlc3Ryb3kocmVtb3ZlRE9NID0gdHJ1ZSkge1xuICAgICAgICBpZiAoIXRoaXMuZWwpXG4gICAgICAgICAgICByZXR1cm47IC8vIHByZXZlbnQgbXVsdGlwbGUgY2FsbHNcbiAgICAgICAgdGhpcy5vZmZBbGwoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlUmVzaXplRXZlbnQodHJ1ZSk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGljKHRydWUsIGZhbHNlKTsgLy8gcGVybWFuZW50bHkgcmVtb3ZlcyBERCBidXQgZG9uJ3Qgc2V0IENTUyBjbGFzcyAod2UncmUgZ29pbmcgYXdheSlcbiAgICAgICAgdGhpcy5zZXRBbmltYXRpb24oZmFsc2UpO1xuICAgICAgICBpZiAoIXJlbW92ZURPTSkge1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVBbGwocmVtb3ZlRE9NKTtcbiAgICAgICAgICAgIHRoaXMuZWwuY2xhc3NMaXN0LnJlbW92ZSh0aGlzLl9zdHlsZVNoZWV0Q2xhc3MpO1xuICAgICAgICAgICAgdGhpcy5lbC5yZW1vdmVBdHRyaWJ1dGUoJ2dzLWN1cnJlbnQtcm93Jyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVsLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5lbCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcmVtb3ZlU3R5bGVzaGVldCgpO1xuICAgICAgICBpZiAodGhpcy5wYXJlbnRHcmlkSXRlbSlcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnBhcmVudEdyaWRJdGVtLnN1YkdyaWQ7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnBhcmVudEdyaWRJdGVtO1xuICAgICAgICBkZWxldGUgdGhpcy5vcHRzO1xuICAgICAgICBkZWxldGUgdGhpcy5fcGxhY2Vob2xkZXI7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmVuZ2luZTtcbiAgICAgICAgZGVsZXRlIHRoaXMuZWwuZ3JpZHN0YWNrOyAvLyByZW1vdmUgY2lyY3VsYXIgZGVwZW5kZW5jeSB0aGF0IHdvdWxkIHByZXZlbnQgYSBmcmVlaW5nXG4gICAgICAgIGRlbGV0ZSB0aGlzLmVsO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogZW5hYmxlL2Rpc2FibGUgZmxvYXRpbmcgd2lkZ2V0cyAoZGVmYXVsdDogYGZhbHNlYCkgU2VlIFtleGFtcGxlXShodHRwOi8vZ3JpZHN0YWNranMuY29tL2RlbW8vZmxvYXQuaHRtbClcbiAgICAgKi9cbiAgICBmbG9hdCh2YWwpIHtcbiAgICAgICAgaWYgKHRoaXMub3B0cy5mbG9hdCAhPT0gdmFsKSB7XG4gICAgICAgICAgICB0aGlzLm9wdHMuZmxvYXQgPSB0aGlzLmVuZ2luZS5mbG9hdCA9IHZhbDtcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJDaGFuZ2VFdmVudCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBnZXQgdGhlIGN1cnJlbnQgZmxvYXQgbW9kZVxuICAgICAqL1xuICAgIGdldEZsb2F0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbmdpbmUuZmxvYXQ7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgcG9zaXRpb24gb2YgdGhlIGNlbGwgdW5kZXIgYSBwaXhlbCBvbiBzY3JlZW4uXG4gICAgICogQHBhcmFtIHBvc2l0aW9uIHRoZSBwb3NpdGlvbiBvZiB0aGUgcGl4ZWwgdG8gcmVzb2x2ZSBpblxuICAgICAqIGFic29sdXRlIGNvb3JkaW5hdGVzLCBhcyBhbiBvYmplY3Qgd2l0aCB0b3AgYW5kIGxlZnQgcHJvcGVydGllc1xuICAgICAqIEBwYXJhbSB1c2VEb2NSZWxhdGl2ZSBpZiB0cnVlLCB2YWx1ZSB3aWxsIGJlIGJhc2VkIG9uIGRvY3VtZW50IHBvc2l0aW9uIHZzIHBhcmVudCBwb3NpdGlvbiAoT3B0aW9uYWwuIERlZmF1bHQgZmFsc2UpLlxuICAgICAqIFVzZWZ1bCB3aGVuIGdyaWQgaXMgd2l0aGluIGBwb3NpdGlvbjogcmVsYXRpdmVgIGVsZW1lbnRcbiAgICAgKlxuICAgICAqIFJldHVybnMgYW4gb2JqZWN0IHdpdGggcHJvcGVydGllcyBgeGAgYW5kIGB5YCBpLmUuIHRoZSBjb2x1bW4gYW5kIHJvdyBpbiB0aGUgZ3JpZC5cbiAgICAgKi9cbiAgICBnZXRDZWxsRnJvbVBpeGVsKHBvc2l0aW9uLCB1c2VEb2NSZWxhdGl2ZSA9IGZhbHNlKSB7XG4gICAgICAgIGxldCBib3ggPSB0aGlzLmVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyhgZ2V0Qm91bmRpbmdDbGllbnRSZWN0IGxlZnQ6ICR7Ym94LmxlZnR9IHRvcDogJHtib3gudG9wfSB3OiAke2JveC53fSBoOiAke2JveC5ofWApXG4gICAgICAgIGxldCBjb250YWluZXJQb3M7XG4gICAgICAgIGlmICh1c2VEb2NSZWxhdGl2ZSkge1xuICAgICAgICAgICAgY29udGFpbmVyUG9zID0geyB0b3A6IGJveC50b3AgKyBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wLCBsZWZ0OiBib3gubGVmdCB9O1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coYGdldENlbGxGcm9tUGl4ZWwgc2Nyb2xsVG9wOiAke2RvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3B9YClcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRhaW5lclBvcyA9IHsgdG9wOiB0aGlzLmVsLm9mZnNldFRvcCwgbGVmdDogdGhpcy5lbC5vZmZzZXRMZWZ0IH07XG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhgZ2V0Q2VsbEZyb21QaXhlbCBvZmZzZXRUb3A6ICR7Y29udGFpbmVyUG9zLmxlZnR9IG9mZnNldExlZnQ6ICR7Y29udGFpbmVyUG9zLnRvcH1gKVxuICAgICAgICB9XG4gICAgICAgIGxldCByZWxhdGl2ZUxlZnQgPSBwb3NpdGlvbi5sZWZ0IC0gY29udGFpbmVyUG9zLmxlZnQ7XG4gICAgICAgIGxldCByZWxhdGl2ZVRvcCA9IHBvc2l0aW9uLnRvcCAtIGNvbnRhaW5lclBvcy50b3A7XG4gICAgICAgIGxldCBjb2x1bW5XaWR0aCA9IChib3gud2lkdGggLyB0aGlzLmdldENvbHVtbigpKTtcbiAgICAgICAgbGV0IHJvd0hlaWdodCA9IChib3guaGVpZ2h0IC8gcGFyc2VJbnQodGhpcy5lbC5nZXRBdHRyaWJ1dGUoJ2dzLWN1cnJlbnQtcm93JykpKTtcbiAgICAgICAgcmV0dXJuIHsgeDogTWF0aC5mbG9vcihyZWxhdGl2ZUxlZnQgLyBjb2x1bW5XaWR0aCksIHk6IE1hdGguZmxvb3IocmVsYXRpdmVUb3AgLyByb3dIZWlnaHQpIH07XG4gICAgfVxuICAgIC8qKiByZXR1cm5zIHRoZSBjdXJyZW50IG51bWJlciBvZiByb3dzLCB3aGljaCB3aWxsIGJlIGF0IGxlYXN0IGBtaW5Sb3dgIGlmIHNldCAqL1xuICAgIGdldFJvdygpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KHRoaXMuZW5naW5lLmdldFJvdygpLCB0aGlzLm9wdHMubWluUm93KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIHNwZWNpZmllZCBhcmVhIGlzIGVtcHR5LlxuICAgICAqIEBwYXJhbSB4IHRoZSBwb3NpdGlvbiB4LlxuICAgICAqIEBwYXJhbSB5IHRoZSBwb3NpdGlvbiB5LlxuICAgICAqIEBwYXJhbSB3IHRoZSB3aWR0aCBvZiB0byBjaGVja1xuICAgICAqIEBwYXJhbSBoIHRoZSBoZWlnaHQgb2YgdG8gY2hlY2tcbiAgICAgKi9cbiAgICBpc0FyZWFFbXB0eSh4LCB5LCB3LCBoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVuZ2luZS5pc0FyZWFFbXB0eSh4LCB5LCB3LCBoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSWYgeW91IGFkZCBlbGVtZW50cyB0byB5b3VyIGdyaWQgYnkgaGFuZCAob3IgaGF2ZSBzb21lIGZyYW1ld29yayBjcmVhdGluZyBET00pLCB5b3UgaGF2ZSB0byB0ZWxsIGdyaWRzdGFjayBhZnRlcndhcmRzIHRvIG1ha2UgdGhlbSB3aWRnZXRzLlxuICAgICAqIElmIHlvdSB3YW50IGdyaWRzdGFjayB0byBhZGQgdGhlIGVsZW1lbnRzIGZvciB5b3UsIHVzZSBgYWRkV2lkZ2V0KClgIGluc3RlYWQuXG4gICAgICogTWFrZXMgdGhlIGdpdmVuIGVsZW1lbnQgYSB3aWRnZXQgYW5kIHJldHVybnMgaXQuXG4gICAgICogQHBhcmFtIGVscyB3aWRnZXQgb3Igc2luZ2xlIHNlbGVjdG9yIHRvIGNvbnZlcnQuXG4gICAgICogQHBhcmFtIG9wdGlvbnMgd2lkZ2V0IGRlZmluaXRpb24gdG8gdXNlIGluc3RlYWQgb2YgcmVhZGluZyBhdHRyaWJ1dGVzIG9yIHVzaW5nIGRlZmF1bHQgc2l6aW5nIHZhbHVlc1xuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBsZXQgZ3JpZCA9IEdyaWRTdGFjay5pbml0KCk7XG4gICAgICogZ3JpZC5lbC5hcHBlbmRDaGlsZCgnPGRpdiBpZD1cIjFcIiBncy13PVwiM1wiPjwvZGl2PicpO1xuICAgICAqIGdyaWQuZWwuYXBwZW5kQ2hpbGQoJzxkaXYgaWQ9XCIyXCI+PC9kaXY+Jyk7XG4gICAgICogZ3JpZC5tYWtlV2lkZ2V0KCcxJyk7XG4gICAgICogZ3JpZC5tYWtlV2lkZ2V0KCcyJywge3c6MiwgY29udGVudDogJ2hlbGxvJ30pO1xuICAgICAqL1xuICAgIG1ha2VXaWRnZXQoZWxzLCBvcHRpb25zKSB7XG4gICAgICAgIGxldCBlbCA9IEdyaWRTdGFjay5nZXRFbGVtZW50KGVscyk7XG4gICAgICAgIHRoaXMuX3ByZXBhcmVFbGVtZW50KGVsLCB0cnVlLCBvcHRpb25zKTtcbiAgICAgICAgY29uc3Qgbm9kZSA9IGVsLmdyaWRzdGFja05vZGU7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUNvbnRhaW5lckhlaWdodCgpO1xuICAgICAgICAvLyBzZWUgaWYgdGhlcmUgaXMgYSBzdWItZ3JpZCB0byBjcmVhdGVcbiAgICAgICAgaWYgKG5vZGUuc3ViR3JpZE9wdHMpIHtcbiAgICAgICAgICAgIHRoaXMubWFrZVN1YkdyaWQoZWwsIG5vZGUuc3ViR3JpZE9wdHMsIHVuZGVmaW5lZCwgZmFsc2UpOyAvLyBub2RlLnN1YkdyaWQgd2lsbCBiZSB1c2VkIGFzIG9wdGlvbiBpbiBtZXRob2QsIG5vIG5lZWQgdG8gcGFzc1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHdlJ3JlIGFkZGluZyBhbiBpdGVtIGludG8gMSBjb2x1bW4gbWFrZSBzdXJlXG4gICAgICAgIC8vIHdlIGRvbid0IG92ZXJyaWRlIHRoZSBsYXJnZXIgMTIgY29sdW1uIGxheW91dCB0aGF0IHdhcyBhbHJlYWR5IHNhdmVkLiAjMTk4NVxuICAgICAgICBpZiAodGhpcy5vcHRzLmNvbHVtbiA9PT0gMSkge1xuICAgICAgICAgICAgdGhpcy5faWdub3JlTGF5b3V0c05vZGVDaGFuZ2UgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3RyaWdnZXJBZGRFdmVudCgpO1xuICAgICAgICB0aGlzLl90cmlnZ2VyQ2hhbmdlRXZlbnQoKTtcbiAgICAgICAgZGVsZXRlIHRoaXMuX2lnbm9yZUxheW91dHNOb2RlQ2hhbmdlO1xuICAgICAgICByZXR1cm4gZWw7XG4gICAgfVxuICAgIG9uKG5hbWUsIGNhbGxiYWNrKSB7XG4gICAgICAgIC8vIGNoZWNrIGZvciBhcnJheSBvZiBuYW1lcyBiZWluZyBwYXNzZWQgaW5zdGVhZFxuICAgICAgICBpZiAobmFtZS5pbmRleE9mKCcgJykgIT09IC0xKSB7XG4gICAgICAgICAgICBsZXQgbmFtZXMgPSBuYW1lLnNwbGl0KCcgJyk7XG4gICAgICAgICAgICBuYW1lcy5mb3JFYWNoKG5hbWUgPT4gdGhpcy5vbihuYW1lLCBjYWxsYmFjaykpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gbmF0aXZlIEN1c3RvbUV2ZW50IGhhbmRsZXJzIC0gY2FzaCB0aGUgZ2VuZXJpYyBoYW5kbGVycyBzbyB3ZSBjYW4gZWFzaWx5IHJlbW92ZVxuICAgICAgICBpZiAobmFtZSA9PT0gJ2NoYW5nZScgfHwgbmFtZSA9PT0gJ2FkZGVkJyB8fCBuYW1lID09PSAncmVtb3ZlZCcgfHwgbmFtZSA9PT0gJ2VuYWJsZScgfHwgbmFtZSA9PT0gJ2Rpc2FibGUnKSB7XG4gICAgICAgICAgICBsZXQgbm9EYXRhID0gKG5hbWUgPT09ICdlbmFibGUnIHx8IG5hbWUgPT09ICdkaXNhYmxlJyk7XG4gICAgICAgICAgICBpZiAobm9EYXRhKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZ3NFdmVudEhhbmRsZXJbbmFtZV0gPSAoZXZlbnQpID0+IGNhbGxiYWNrKGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX2dzRXZlbnRIYW5kbGVyW25hbWVdID0gKGV2ZW50KSA9PiBjYWxsYmFjayhldmVudCwgZXZlbnQuZGV0YWlsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZWwuYWRkRXZlbnRMaXN0ZW5lcihuYW1lLCB0aGlzLl9nc0V2ZW50SGFuZGxlcltuYW1lXSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAobmFtZSA9PT0gJ2RyYWcnIHx8IG5hbWUgPT09ICdkcmFnc3RhcnQnIHx8IG5hbWUgPT09ICdkcmFnc3RvcCcgfHwgbmFtZSA9PT0gJ3Jlc2l6ZXN0YXJ0JyB8fCBuYW1lID09PSAncmVzaXplJ1xuICAgICAgICAgICAgfHwgbmFtZSA9PT0gJ3Jlc2l6ZXN0b3AnIHx8IG5hbWUgPT09ICdkcm9wcGVkJyB8fCBuYW1lID09PSAncmVzaXplY29udGVudCcpIHtcbiAgICAgICAgICAgIC8vIGRyYWcmZHJvcCBzdG9wIGV2ZW50cyBORUVEIHRvIGJlIGNhbGwgdGhlbSBBRlRFUiB3ZSB1cGRhdGUgbm9kZSBhdHRyaWJ1dGVzIHNvIGhhbmRsZSB0aGVtIG91cnNlbGYuXG4gICAgICAgICAgICAvLyBkbyBzYW1lIGZvciBzdGFydCBldmVudCB0byBtYWtlIGl0IGVhc2llci4uLlxuICAgICAgICAgICAgdGhpcy5fZ3NFdmVudEhhbmRsZXJbbmFtZV0gPSBjYWxsYmFjaztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0dyaWRTdGFjay5vbignICsgbmFtZSArICcpIGV2ZW50IG5vdCBzdXBwb3J0ZWQnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogdW5zdWJzY3JpYmUgZnJvbSB0aGUgJ29uJyBldmVudCBHcmlkU3RhY2tFdmVudFxuICAgICAqIEBwYXJhbSBuYW1lIG9mIHRoZSBldmVudCAoc2VlIHBvc3NpYmxlIHZhbHVlcykgb3IgbGlzdCBvZiBuYW1lcyBzcGFjZSBzZXBhcmF0ZWRcbiAgICAgKi9cbiAgICBvZmYobmFtZSkge1xuICAgICAgICAvLyBjaGVjayBmb3IgYXJyYXkgb2YgbmFtZXMgYmVpbmcgcGFzc2VkIGluc3RlYWRcbiAgICAgICAgaWYgKG5hbWUuaW5kZXhPZignICcpICE9PSAtMSkge1xuICAgICAgICAgICAgbGV0IG5hbWVzID0gbmFtZS5zcGxpdCgnICcpO1xuICAgICAgICAgICAgbmFtZXMuZm9yRWFjaChuYW1lID0+IHRoaXMub2ZmKG5hbWUpKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGlmIChuYW1lID09PSAnY2hhbmdlJyB8fCBuYW1lID09PSAnYWRkZWQnIHx8IG5hbWUgPT09ICdyZW1vdmVkJyB8fCBuYW1lID09PSAnZW5hYmxlJyB8fCBuYW1lID09PSAnZGlzYWJsZScpIHtcbiAgICAgICAgICAgIC8vIHJlbW92ZSBuYXRpdmUgQ3VzdG9tRXZlbnQgaGFuZGxlcnNcbiAgICAgICAgICAgIGlmICh0aGlzLl9nc0V2ZW50SGFuZGxlcltuYW1lXSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihuYW1lLCB0aGlzLl9nc0V2ZW50SGFuZGxlcltuYW1lXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZGVsZXRlIHRoaXMuX2dzRXZlbnRIYW5kbGVyW25hbWVdO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIHJlbW92ZSBhbGwgZXZlbnQgaGFuZGxlcnMgKi9cbiAgICBvZmZBbGwoKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKHRoaXMuX2dzRXZlbnRIYW5kbGVyKS5mb3JFYWNoKChrZXkpID0+IHRoaXMub2ZmKGtleSkpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB3aWRnZXQgZnJvbSB0aGUgZ3JpZC5cbiAgICAgKiBAcGFyYW0gZWwgIHdpZGdldCBvciBzZWxlY3RvciB0byBtb2RpZnlcbiAgICAgKiBAcGFyYW0gcmVtb3ZlRE9NIGlmIGBmYWxzZWAgRE9NIGVsZW1lbnQgd29uJ3QgYmUgcmVtb3ZlZCBmcm9tIHRoZSB0cmVlIChEZWZhdWx0PyB0cnVlKS5cbiAgICAgKiBAcGFyYW0gdHJpZ2dlckV2ZW50IGlmIGBmYWxzZWAgKHF1aWV0IG1vZGUpIGVsZW1lbnQgd2lsbCBub3QgYmUgYWRkZWQgdG8gcmVtb3ZlZCBsaXN0IGFuZCBubyAncmVtb3ZlZCcgY2FsbGJhY2tzIHdpbGwgYmUgY2FsbGVkIChEZWZhdWx0PyB0cnVlKS5cbiAgICAgKi9cbiAgICByZW1vdmVXaWRnZXQoZWxzLCByZW1vdmVET00gPSB0cnVlLCB0cmlnZ2VyRXZlbnQgPSB0cnVlKSB7XG4gICAgICAgIEdyaWRTdGFjay5nZXRFbGVtZW50cyhlbHMpLmZvckVhY2goZWwgPT4ge1xuICAgICAgICAgICAgaWYgKGVsLnBhcmVudEVsZW1lbnQgJiYgZWwucGFyZW50RWxlbWVudCAhPT0gdGhpcy5lbClcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIG5vdCBvdXIgY2hpbGQhXG4gICAgICAgICAgICBsZXQgbm9kZSA9IGVsLmdyaWRzdGFja05vZGU7XG4gICAgICAgICAgICAvLyBGb3IgTWV0ZW9yIHN1cHBvcnQ6IGh0dHBzOi8vZ2l0aHViLmNvbS9ncmlkc3RhY2svZ3JpZHN0YWNrLmpzL3B1bGwvMjcyXG4gICAgICAgICAgICBpZiAoIW5vZGUpIHtcbiAgICAgICAgICAgICAgICBub2RlID0gdGhpcy5lbmdpbmUubm9kZXMuZmluZChuID0+IGVsID09PSBuLmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbm9kZSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICBpZiAocmVtb3ZlRE9NICYmIEdyaWRTdGFjay5hZGRSZW1vdmVDQikge1xuICAgICAgICAgICAgICAgIEdyaWRTdGFjay5hZGRSZW1vdmVDQih0aGlzLmVsLCBub2RlLCBmYWxzZSwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gcmVtb3ZlIG91ciBET00gZGF0YSAoY2lyY3VsYXIgbGluaykgYW5kIGRyYWcmZHJvcCBwZXJtYW5lbnRseVxuICAgICAgICAgICAgZGVsZXRlIGVsLmdyaWRzdGFja05vZGU7XG4gICAgICAgICAgICB0aGlzLl9yZW1vdmVERChlbCk7XG4gICAgICAgICAgICB0aGlzLmVuZ2luZS5yZW1vdmVOb2RlKG5vZGUsIHJlbW92ZURPTSwgdHJpZ2dlckV2ZW50KTtcbiAgICAgICAgICAgIGlmIChyZW1vdmVET00gJiYgZWwucGFyZW50RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGVsLnJlbW92ZSgpOyAvLyBpbiBiYXRjaCBtb2RlIGVuZ2luZS5yZW1vdmVOb2RlIGRvZXNuJ3QgY2FsbCBiYWNrIHRvIHJlbW92ZSBET01cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0cmlnZ2VyRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJSZW1vdmVFdmVudCgpO1xuICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckNoYW5nZUV2ZW50KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIHdpZGdldHMgZnJvbSB0aGUgZ3JpZC5cbiAgICAgKiBAcGFyYW0gcmVtb3ZlRE9NIGlmIGBmYWxzZWAgRE9NIGVsZW1lbnRzIHdvbid0IGJlIHJlbW92ZWQgZnJvbSB0aGUgdHJlZSAoRGVmYXVsdD8gYHRydWVgKS5cbiAgICAgKiBAcGFyYW0gdHJpZ2dlckV2ZW50IGlmIGBmYWxzZWAgKHF1aWV0IG1vZGUpIGVsZW1lbnQgd2lsbCBub3QgYmUgYWRkZWQgdG8gcmVtb3ZlZCBsaXN0IGFuZCBubyAncmVtb3ZlZCcgY2FsbGJhY2tzIHdpbGwgYmUgY2FsbGVkIChEZWZhdWx0PyB0cnVlKS5cbiAgICAgKi9cbiAgICByZW1vdmVBbGwocmVtb3ZlRE9NID0gdHJ1ZSwgdHJpZ2dlckV2ZW50ID0gdHJ1ZSkge1xuICAgICAgICAvLyBhbHdheXMgcmVtb3ZlIG91ciBET00gZGF0YSAoY2lyY3VsYXIgbGluaykgYmVmb3JlIGxpc3QgZ2V0cyBlbXB0aWVkIGFuZCBkcmFnJmRyb3AgcGVybWFuZW50bHlcbiAgICAgICAgdGhpcy5lbmdpbmUubm9kZXMuZm9yRWFjaChuID0+IHtcbiAgICAgICAgICAgIGlmIChyZW1vdmVET00gJiYgR3JpZFN0YWNrLmFkZFJlbW92ZUNCKSB7XG4gICAgICAgICAgICAgICAgR3JpZFN0YWNrLmFkZFJlbW92ZUNCKHRoaXMuZWwsIG4sIGZhbHNlLCBmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWxldGUgbi5lbC5ncmlkc3RhY2tOb2RlO1xuICAgICAgICAgICAgaWYgKCF0aGlzLm9wdHMuc3RhdGljR3JpZClcbiAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVERChuLmVsKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZW5naW5lLnJlbW92ZUFsbChyZW1vdmVET00sIHRyaWdnZXJFdmVudCk7XG4gICAgICAgIGlmICh0cmlnZ2VyRXZlbnQpXG4gICAgICAgICAgICB0aGlzLl90cmlnZ2VyUmVtb3ZlRXZlbnQoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRvZ2dsZSB0aGUgZ3JpZCBhbmltYXRpb24gc3RhdGUuICBUb2dnbGVzIHRoZSBgZ3JpZC1zdGFjay1hbmltYXRlYCBjbGFzcy5cbiAgICAgKiBAcGFyYW0gZG9BbmltYXRlIGlmIHRydWUgdGhlIGdyaWQgd2lsbCBhbmltYXRlLlxuICAgICAqL1xuICAgIHNldEFuaW1hdGlvbihkb0FuaW1hdGUpIHtcbiAgICAgICAgaWYgKGRvQW5pbWF0ZSkge1xuICAgICAgICAgICAgdGhpcy5lbC5jbGFzc0xpc3QuYWRkKCdncmlkLXN0YWNrLWFuaW1hdGUnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWwuY2xhc3NMaXN0LnJlbW92ZSgnZ3JpZC1zdGFjay1hbmltYXRlJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBoYXNBbmltYXRpb25DU1MoKSB7IHJldHVybiB0aGlzLmVsLmNsYXNzTGlzdC5jb250YWlucygnZ3JpZC1zdGFjay1hbmltYXRlJyk7IH1cbiAgICAvKipcbiAgICAgKiBUb2dnbGUgdGhlIGdyaWQgc3RhdGljIHN0YXRlLCB3aGljaCBwZXJtYW5lbnRseSByZW1vdmVzL2FkZCBEcmFnJkRyb3Agc3VwcG9ydCwgdW5saWtlIGRpc2FibGUoKS9lbmFibGUoKSB0aGF0IGp1c3QgdHVybnMgaXQgb2ZmL29uLlxuICAgICAqIEFsc28gdG9nZ2xlIHRoZSBncmlkLXN0YWNrLXN0YXRpYyBjbGFzcy5cbiAgICAgKiBAcGFyYW0gdmFsIGlmIHRydWUgdGhlIGdyaWQgYmVjb21lIHN0YXRpYy5cbiAgICAgKiBAcGFyYW0gdXBkYXRlQ2xhc3MgdHJ1ZSAoZGVmYXVsdCkgaWYgY3NzIGNsYXNzIGdldHMgdXBkYXRlZFxuICAgICAqIEBwYXJhbSByZWN1cnNlIHRydWUgKGRlZmF1bHQpIGlmIHN1Yi1ncmlkcyBhbHNvIGdldCB1cGRhdGVkXG4gICAgICovXG4gICAgc2V0U3RhdGljKHZhbCwgdXBkYXRlQ2xhc3MgPSB0cnVlLCByZWN1cnNlID0gdHJ1ZSkge1xuICAgICAgICBpZiAoISF0aGlzLm9wdHMuc3RhdGljR3JpZCA9PT0gdmFsKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIHZhbCA/IHRoaXMub3B0cy5zdGF0aWNHcmlkID0gdHJ1ZSA6IGRlbGV0ZSB0aGlzLm9wdHMuc3RhdGljR3JpZDtcbiAgICAgICAgdGhpcy5fc2V0dXBSZW1vdmVEcm9wKCk7XG4gICAgICAgIHRoaXMuX3NldHVwQWNjZXB0V2lkZ2V0KCk7XG4gICAgICAgIHRoaXMuZW5naW5lLm5vZGVzLmZvckVhY2gobiA9PiB7XG4gICAgICAgICAgICB0aGlzLl9wcmVwYXJlRHJhZ0Ryb3BCeU5vZGUobik7IC8vIGVpdGhlciBkZWxldGUgb3IgaW5pdCBEcmFnJmRyb3BcbiAgICAgICAgICAgIGlmIChuLnN1YkdyaWQgJiYgcmVjdXJzZSlcbiAgICAgICAgICAgICAgICBuLnN1YkdyaWQuc2V0U3RhdGljKHZhbCwgdXBkYXRlQ2xhc3MsIHJlY3Vyc2UpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHVwZGF0ZUNsYXNzKSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRTdGF0aWNDbGFzcygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHdpZGdldCBwb3NpdGlvbi9zaXplIGFuZCBvdGhlciBpbmZvLiBOb3RlOiBpZiB5b3UgbmVlZCB0byBjYWxsIHRoaXMgb24gYWxsIG5vZGVzLCB1c2UgbG9hZCgpIGluc3RlYWQgd2hpY2ggd2lsbCB1cGRhdGUgd2hhdCBjaGFuZ2VkLlxuICAgICAqIEBwYXJhbSBlbHMgIHdpZGdldCBvciBzZWxlY3RvciBvZiBvYmplY3RzIHRvIG1vZGlmeSAobm90ZTogc2V0dGluZyB0aGUgc2FtZSB4LHkgZm9yIG11bHRpcGxlIGl0ZW1zIHdpbGwgYmUgaW5kZXRlcm1pbmlzdGljIGFuZCBsaWtlbHkgdW53YW50ZWQpXG4gICAgICogQHBhcmFtIG9wdCBuZXcgd2lkZ2V0IG9wdGlvbnMgKHgseSx3LGgsIGV0Yy4uKS4gT25seSB0aG9zZSBzZXQgd2lsbCBiZSB1cGRhdGVkLlxuICAgICAqL1xuICAgIHVwZGF0ZShlbHMsIG9wdCkge1xuICAgICAgICAvLyBzdXBwb3J0IGxlZ2FjeSBjYWxsIGZvciBub3cgP1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignZ3JpZHN0YWNrLnRzOiBgdXBkYXRlKGVsLCB4LCB5LCB3LCBoKWAgaXMgZGVwcmVjYXRlZC4gVXNlIGB1cGRhdGUoZWwsIHt4LCB3LCBjb250ZW50LCAuLi59KWAuIEl0IHdpbGwgYmUgcmVtb3ZlZCBzb29uJyk7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLXJlc3QtcGFyYW1zXG4gICAgICAgICAgICBsZXQgYSA9IGFyZ3VtZW50cywgaSA9IDE7XG4gICAgICAgICAgICBvcHQgPSB7IHg6IGFbaSsrXSwgeTogYVtpKytdLCB3OiBhW2krK10sIGg6IGFbaSsrXSB9O1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudXBkYXRlKGVscywgb3B0KTtcbiAgICAgICAgfVxuICAgICAgICBHcmlkU3RhY2suZ2V0RWxlbWVudHMoZWxzKS5mb3JFYWNoKGVsID0+IHtcbiAgICAgICAgICAgIGxldCBuID0gZWw/LmdyaWRzdGFja05vZGU7XG4gICAgICAgICAgICBpZiAoIW4pXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgbGV0IHcgPSBVdGlscy5jbG9uZURlZXAob3B0KTsgLy8gbWFrZSBhIGNvcHkgd2UgY2FuIG1vZGlmeSBpbiBjYXNlIHRoZXkgcmUtdXNlIGl0IG9yIG11bHRpcGxlIGl0ZW1zXG4gICAgICAgICAgICB0aGlzLmVuZ2luZS5ub2RlQm91bmRGaXgodyk7XG4gICAgICAgICAgICBkZWxldGUgdy5hdXRvUG9zaXRpb247XG4gICAgICAgICAgICBkZWxldGUgdy5pZDtcbiAgICAgICAgICAgIC8vIG1vdmUvcmVzaXplIHdpZGdldCBpZiBhbnl0aGluZyBjaGFuZ2VkXG4gICAgICAgICAgICBsZXQga2V5cyA9IFsneCcsICd5JywgJ3cnLCAnaCddO1xuICAgICAgICAgICAgbGV0IG07XG4gICAgICAgICAgICBpZiAoa2V5cy5zb21lKGsgPT4gd1trXSAhPT0gdW5kZWZpbmVkICYmIHdba10gIT09IG5ba10pKSB7XG4gICAgICAgICAgICAgICAgbSA9IHt9O1xuICAgICAgICAgICAgICAgIGtleXMuZm9yRWFjaChrID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbVtrXSA9ICh3W2tdICE9PSB1bmRlZmluZWQpID8gd1trXSA6IG5ba107XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB3W2tdO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZm9yIGEgbW92ZSBhcyB3ZWxsIElGRiB0aGVyZSBpcyBhbnkgbWluL21heCBmaWVsZHMgc2V0XG4gICAgICAgICAgICBpZiAoIW0gJiYgKHcubWluVyB8fCB3Lm1pbkggfHwgdy5tYXhXIHx8IHcubWF4SCkpIHtcbiAgICAgICAgICAgICAgICBtID0ge307IC8vIHdpbGwgdXNlIG5vZGUgcG9zaXRpb24gYnV0IHZhbGlkYXRlIHZhbHVlc1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gY2hlY2sgZm9yIGNvbnRlbnQgY2hhbmdpbmdcbiAgICAgICAgICAgIGlmICh3LmNvbnRlbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGl0ZW1Db250ZW50ID0gZWwucXVlcnlTZWxlY3RvcignLmdyaWQtc3RhY2staXRlbS1jb250ZW50Jyk7XG4gICAgICAgICAgICAgICAgaWYgKGl0ZW1Db250ZW50ICYmIGl0ZW1Db250ZW50LmlubmVySFRNTCAhPT0gdy5jb250ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGl0ZW1Db250ZW50LmlubmVySFRNTCA9IHcuY29udGVudDtcbiAgICAgICAgICAgICAgICAgICAgLy8gcmVzdG9yZSBhbnkgc3ViLWdyaWQgYmFja1xuICAgICAgICAgICAgICAgICAgICBpZiAobi5zdWJHcmlkPy5lbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUNvbnRlbnQuYXBwZW5kQ2hpbGQobi5zdWJHcmlkLmVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghbi5zdWJHcmlkLm9wdHMuc3R5bGVJbkhlYWQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbi5zdWJHcmlkLl91cGRhdGVTdHlsZXModHJ1ZSk7IC8vIGZvcmNlIGNyZWF0ZVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB3LmNvbnRlbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBhbnkgcmVtYWluaW5nIGZpZWxkcyBhcmUgYXNzaWduZWQsIGJ1dCBjaGVjayBmb3IgZHJhZ2dpbmcgY2hhbmdlcywgcmVzaXplIGNvbnN0cmFpblxuICAgICAgICAgICAgbGV0IGNoYW5nZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBkZENoYW5nZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAoa2V5WzBdICE9PSAnXycgJiYgbltrZXldICE9PSB3W2tleV0pIHtcbiAgICAgICAgICAgICAgICAgICAgbltrZXldID0gd1trZXldO1xuICAgICAgICAgICAgICAgICAgICBjaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgZGRDaGFuZ2VkID0gZGRDaGFuZ2VkIHx8ICghdGhpcy5vcHRzLnN0YXRpY0dyaWQgJiYgKGtleSA9PT0gJ25vUmVzaXplJyB8fCBrZXkgPT09ICdub01vdmUnIHx8IGtleSA9PT0gJ2xvY2tlZCcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBVdGlscy5zYW5pdGl6ZU1pbk1heChuKTtcbiAgICAgICAgICAgIC8vIGZpbmFsbHkgbW92ZSB0aGUgd2lkZ2V0IGFuZCB1cGRhdGUgYXR0clxuICAgICAgICAgICAgaWYgKG0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCB3aWR0aENoYW5nZWQgPSAobS53ICE9PSB1bmRlZmluZWQgJiYgbS53ICE9PSBuLncpO1xuICAgICAgICAgICAgICAgIHRoaXMubW92ZU5vZGUobiwgbSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNpemVUb0NvbnRlbnRDaGVjayh3aWR0aENoYW5nZWQsIG4pOyAvLyB3YWl0IGZvciBhbmltYXRpb24gaWYgd2UgY2hhbmdlZCB3aWR0aFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG0gfHwgY2hhbmdlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3dyaXRlQXR0cihlbCwgbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGRDaGFuZ2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcHJlcGFyZURyYWdEcm9wQnlOb2RlKG4pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIG1vdmVOb2RlKG4sIG0pIHtcbiAgICAgICAgdGhpcy5lbmdpbmUuY2xlYW5Ob2RlcygpXG4gICAgICAgICAgICAuYmVnaW5VcGRhdGUobilcbiAgICAgICAgICAgIC5tb3ZlTm9kZShuLCBtKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlQ29udGFpbmVySGVpZ2h0KCk7XG4gICAgICAgIHRoaXMuX3RyaWdnZXJDaGFuZ2VFdmVudCgpO1xuICAgICAgICB0aGlzLmVuZ2luZS5lbmRVcGRhdGUoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB3aWRnZXQgaGVpZ2h0IHRvIG1hdGNoIHRoZSBjb250ZW50IGhlaWdodCB0byBhdm9pZCB2LXNjcm9sbGJhciBvciBkZWFkIHNwYWNlLlxuICAgICAqIE5vdGU6IHRoaXMgYXNzdW1lcyBvbmx5IDEgY2hpbGQgdW5kZXIgcmVzaXplVG9Db250ZW50UGFyZW50PScuZ3JpZC1zdGFjay1pdGVtLWNvbnRlbnQnIChzaXplZCB0byBncmlkSXRlbSBtaW51cyBwYWRkaW5nKSB0aGF0IGlzIGF0IHRoZSBlbnRpcmUgY29udGVudCBzaXplIHdhbnRlZC5cbiAgICAgKiBAcGFyYW0gZWwgZ3JpZCBpdGVtIGVsZW1lbnRcbiAgICAgKiBAcGFyYW0gdXNlTm9kZUggc2V0IHRvIHRydWUgaWYgR3JpZFN0YWNrTm9kZS5oIHNob3VsZCBiZSB1c2VkIGluc3RlYWQgb2YgYWN0dWFsIGNvbnRhaW5lciBoZWlnaHQgd2hlbiB3ZSBkb24ndCBuZWVkIHRvIHdhaXQgZm9yIGFuaW1hdGlvbiB0byBmaW5pc2ggdG8gZ2V0IGFjdHVhbCBET00gaGVpZ2h0c1xuICAgICAqL1xuICAgIHJlc2l6ZVRvQ29udGVudChlbCkge1xuICAgICAgICBpZiAoIWVsKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBlbC5jbGFzc0xpc3QucmVtb3ZlKCdzaXplLXRvLWNvbnRlbnQtbWF4Jyk7XG4gICAgICAgIGlmICghZWwuY2xpZW50SGVpZ2h0KVxuICAgICAgICAgICAgcmV0dXJuOyAvLyAwIHdoZW4gaGlkZGVuLCBza2lwXG4gICAgICAgIGNvbnN0IG4gPSBlbC5ncmlkc3RhY2tOb2RlO1xuICAgICAgICBpZiAoIW4pXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IGdyaWQgPSBuLmdyaWQ7XG4gICAgICAgIGlmICghZ3JpZCB8fCBlbC5wYXJlbnRFbGVtZW50ICE9PSBncmlkLmVsKVxuICAgICAgICAgICAgcmV0dXJuOyAvLyBza2lwIGlmIHdlIGFyZSBub3QgaW5zaWRlIGEgZ3JpZFxuICAgICAgICBjb25zdCBjZWxsID0gZ3JpZC5nZXRDZWxsSGVpZ2h0KHRydWUpO1xuICAgICAgICBpZiAoIWNlbGwpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGxldCBoZWlnaHQgPSBuLmggPyBuLmggKiBjZWxsIDogZWwuY2xpZW50SGVpZ2h0OyAvLyBnZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQgc2VlbSB0byBmbGlja2VyIGJhY2sgYW5kIGZvcnRoXG4gICAgICAgIGxldCBpdGVtO1xuICAgICAgICBpZiAobi5yZXNpemVUb0NvbnRlbnRQYXJlbnQpXG4gICAgICAgICAgICBpdGVtID0gZWwucXVlcnlTZWxlY3RvcihuLnJlc2l6ZVRvQ29udGVudFBhcmVudCk7XG4gICAgICAgIGlmICghaXRlbSlcbiAgICAgICAgICAgIGl0ZW0gPSBlbC5xdWVyeVNlbGVjdG9yKEdyaWRTdGFjay5yZXNpemVUb0NvbnRlbnRQYXJlbnQpO1xuICAgICAgICBpZiAoIWl0ZW0pXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IHBhZGRpbmcgPSBlbC5jbGllbnRIZWlnaHQgLSBpdGVtLmNsaWVudEhlaWdodDsgLy8gZnVsbCAtIGF2YWlsYWJsZSBoZWlnaHQgdG8gb3VyIGNoaWxkIChtaW51cyBib3JkZXIsIHBhZGRpbmcuLi4pXG4gICAgICAgIGNvbnN0IGl0ZW1IID0gbi5oID8gbi5oICogY2VsbCAtIHBhZGRpbmcgOiBpdGVtLmNsaWVudEhlaWdodDsgLy8gY2FsY3VsYXRlZCB0byB3aGF0IGNlbGxIZWlnaHQgaXMgb3Igd2lsbCBiZWNvbWUgKHJhdGhlciB0aGFuIGFjdHVhbCB0byBwcmV2ZW50IHdhaXRpbmcgZm9yIGFuaW1hdGlvbiB0byBmaW5pc2gpXG4gICAgICAgIGxldCB3YW50ZWRIO1xuICAgICAgICBpZiAobi5zdWJHcmlkKSB7XG4gICAgICAgICAgICAvLyBzdWItZ3JpZCAtIHVzZSB0aGVpciBhY3R1YWwgcm93IGNvdW50ICogdGhlaXIgY2VsbCBoZWlnaHRcbiAgICAgICAgICAgIHdhbnRlZEggPSBuLnN1YkdyaWQuZ2V0Um93KCkgKiBuLnN1YkdyaWQuZ2V0Q2VsbEhlaWdodCh0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIE5PVEU6IGNsaWVudEhlaWdodCAmIGdldEJvdW5kaW5nQ2xpZW50UmVjdCgpIGlzIHVuZGVmaW5lZCBmb3IgdGV4dCBhbmQgb3RoZXIgbGVhZiBub2Rlcy4gdXNlIDxkaXY+IGNvbnRhaW5lciFcbiAgICAgICAgICAgIGNvbnN0IGNoaWxkID0gaXRlbS5maXJzdEVsZW1lbnRDaGlsZDtcbiAgICAgICAgICAgIGlmICghY2hpbGQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvcjogR3JpZFN0YWNrLnJlc2l6ZVRvQ29udGVudCgpIHdpZGdldCBpZDoke24uaWR9ICcke0dyaWRTdGFjay5yZXNpemVUb0NvbnRlbnRQYXJlbnR9Jy5maXJzdEVsZW1lbnRDaGlsZCBpcyBudWxsLCBtYWtlIHN1cmUgdG8gaGF2ZSBhIGRpdiBsaWtlIGNvbnRhaW5lci4gU2tpcHBpbmcgc2l6aW5nLmApO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdhbnRlZEggPSBjaGlsZC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQgfHwgaXRlbUg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGl0ZW1IID09PSB3YW50ZWRIKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBoZWlnaHQgKz0gd2FudGVkSCAtIGl0ZW1IO1xuICAgICAgICBsZXQgaCA9IE1hdGguY2VpbChoZWlnaHQgLyBjZWxsKTtcbiAgICAgICAgLy8gY2hlY2sgZm9yIG1pbi9tYXggYW5kIHNwZWNpYWwgc2l6aW5nXG4gICAgICAgIGNvbnN0IHNvZnRNYXggPSBOdW1iZXIuaXNJbnRlZ2VyKG4uc2l6ZVRvQ29udGVudCkgPyBuLnNpemVUb0NvbnRlbnQgOiAwO1xuICAgICAgICBpZiAoc29mdE1heCAmJiBoID4gc29mdE1heCkge1xuICAgICAgICAgICAgaCA9IHNvZnRNYXg7XG4gICAgICAgICAgICBlbC5jbGFzc0xpc3QuYWRkKCdzaXplLXRvLWNvbnRlbnQtbWF4Jyk7IC8vIGdldCB2LXNjcm9sbCBiYWNrXG4gICAgICAgIH1cbiAgICAgICAgaWYgKG4ubWluSCAmJiBoIDwgbi5taW5IKVxuICAgICAgICAgICAgaCA9IG4ubWluSDtcbiAgICAgICAgZWxzZSBpZiAobi5tYXhIICYmIGggPiBuLm1heEgpXG4gICAgICAgICAgICBoID0gbi5tYXhIO1xuICAgICAgICBpZiAoaCAhPT0gbi5oKSB7XG4gICAgICAgICAgICBncmlkLl9pZ25vcmVMYXlvdXRzTm9kZUNoYW5nZSA9IHRydWU7XG4gICAgICAgICAgICBncmlkLm1vdmVOb2RlKG4sIHsgaCB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSBncmlkLl9pZ25vcmVMYXlvdXRzTm9kZUNoYW5nZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKiogY2FsbCB0aGUgdXNlciByZXNpemUgKHNvIHRoZXkgY2FuIGRvIGV4dHJhIHdvcmspIGVsc2Ugb3VyIGJ1aWxkIGluIHZlcnNpb24gKi9cbiAgICByZXNpemVUb0NvbnRlbnRDQkNoZWNrKGVsKSB7XG4gICAgICAgIGlmIChHcmlkU3RhY2sucmVzaXplVG9Db250ZW50Q0IpXG4gICAgICAgICAgICBHcmlkU3RhY2sucmVzaXplVG9Db250ZW50Q0IoZWwpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aGlzLnJlc2l6ZVRvQ29udGVudChlbCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFVwZGF0ZXMgdGhlIG1hcmdpbnMgd2hpY2ggd2lsbCBzZXQgYWxsIDQgc2lkZXMgYXQgb25jZSAtIHNlZSBgR3JpZFN0YWNrT3B0aW9ucy5tYXJnaW5gIGZvciBmb3JtYXQgb3B0aW9ucyAoQ1NTIHN0cmluZyBmb3JtYXQgb2YgMSwyLDQgdmFsdWVzIG9yIHNpbmdsZSBudW1iZXIpLlxuICAgICAqIEBwYXJhbSB2YWx1ZSBtYXJnaW4gdmFsdWVcbiAgICAgKi9cbiAgICBtYXJnaW4odmFsdWUpIHtcbiAgICAgICAgbGV0IGlzTXVsdGlWYWx1ZSA9ICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlLnNwbGl0KCcgJykubGVuZ3RoID4gMSk7XG4gICAgICAgIC8vIGNoZWNrIGlmIHdlIGNhbiBza2lwIHJlLWNyZWF0aW5nIG91ciBDU1MgZmlsZS4uLiB3b24ndCBjaGVjayBpZiBtdWx0aSB2YWx1ZXMgKHRvbyBtdWNoIGhhc3NsZSlcbiAgICAgICAgaWYgKCFpc011bHRpVmFsdWUpIHtcbiAgICAgICAgICAgIGxldCBkYXRhID0gVXRpbHMucGFyc2VIZWlnaHQodmFsdWUpO1xuICAgICAgICAgICAgaWYgKHRoaXMub3B0cy5tYXJnaW5Vbml0ID09PSBkYXRhLnVuaXQgJiYgdGhpcy5vcHRzLm1hcmdpbiA9PT0gZGF0YS5oKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyByZS11c2UgZXhpc3RpbmcgbWFyZ2luIGhhbmRsaW5nXG4gICAgICAgIHRoaXMub3B0cy5tYXJnaW4gPSB2YWx1ZTtcbiAgICAgICAgdGhpcy5vcHRzLm1hcmdpblRvcCA9IHRoaXMub3B0cy5tYXJnaW5Cb3R0b20gPSB0aGlzLm9wdHMubWFyZ2luTGVmdCA9IHRoaXMub3B0cy5tYXJnaW5SaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5faW5pdE1hcmdpbigpO1xuICAgICAgICB0aGlzLl91cGRhdGVTdHlsZXModHJ1ZSk7IC8vIHRydWUgPSBmb3JjZSByZS1jcmVhdGVcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiByZXR1cm5zIGN1cnJlbnQgbWFyZ2luIG51bWJlciB2YWx1ZSAodW5kZWZpbmVkIGlmIDQgc2lkZXMgZG9uJ3QgbWF0Y2gpICovXG4gICAgZ2V0TWFyZ2luKCkgeyByZXR1cm4gdGhpcy5vcHRzLm1hcmdpbjsgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgaGVpZ2h0IG9mIHRoZSBncmlkIHdpbGwgYmUgbGVzcyB0aGFuIHRoZSB2ZXJ0aWNhbFxuICAgICAqIGNvbnN0cmFpbnQuIEFsd2F5cyByZXR1cm5zIHRydWUgaWYgZ3JpZCBkb2Vzbid0IGhhdmUgaGVpZ2h0IGNvbnN0cmFpbnQuXG4gICAgICogQHBhcmFtIG5vZGUgY29udGFpbnMgeCx5LHcsaCxhdXRvLXBvc2l0aW9uIG9wdGlvbnNcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogaWYgKGdyaWQud2lsbEl0Rml0KG5ld1dpZGdldCkpIHtcbiAgICAgKiAgIGdyaWQuYWRkV2lkZ2V0KG5ld1dpZGdldCk7XG4gICAgICogfSBlbHNlIHtcbiAgICAgKiAgIGFsZXJ0KCdOb3QgZW5vdWdoIGZyZWUgc3BhY2UgdG8gcGxhY2UgdGhlIHdpZGdldCcpO1xuICAgICAqIH1cbiAgICAgKi9cbiAgICB3aWxsSXRGaXQobm9kZSkge1xuICAgICAgICAvLyBzdXBwb3J0IGxlZ2FjeSBjYWxsIGZvciBub3dcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ2dyaWRzdGFjay50czogYHdpbGxJdEZpdCh4LHksdyxoLGF1dG9Qb3NpdGlvbilgIGlzIGRlcHJlY2F0ZWQuIFVzZSBgd2lsbEl0Rml0KHt4LCB5LC4uLn0pYC4gSXQgd2lsbCBiZSByZW1vdmVkIHNvb24nKTtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBwcmVmZXItcmVzdC1wYXJhbXNcbiAgICAgICAgICAgIGxldCBhID0gYXJndW1lbnRzLCBpID0gMCwgdyA9IHsgeDogYVtpKytdLCB5OiBhW2krK10sIHc6IGFbaSsrXSwgaDogYVtpKytdLCBhdXRvUG9zaXRpb246IGFbaSsrXSB9O1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lsbEl0Rml0KHcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmVuZ2luZS53aWxsSXRGaXQobm9kZSk7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBfdHJpZ2dlckNoYW5nZUV2ZW50KCkge1xuICAgICAgICBpZiAodGhpcy5lbmdpbmUuYmF0Y2hNb2RlKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIGxldCBlbGVtZW50cyA9IHRoaXMuZW5naW5lLmdldERpcnR5Tm9kZXModHJ1ZSk7IC8vIHZlcmlmeSB0aGV5IHJlYWxseSBjaGFuZ2VkXG4gICAgICAgIGlmIChlbGVtZW50cyAmJiBlbGVtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5faWdub3JlTGF5b3V0c05vZGVDaGFuZ2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuZ2luZS5sYXlvdXRzTm9kZXNDaGFuZ2UoZWxlbWVudHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KCdjaGFuZ2UnLCBlbGVtZW50cyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lbmdpbmUuc2F2ZUluaXRpYWwoKTsgLy8gd2UgY2FsbGVkLCBub3cgcmVzZXQgaW5pdGlhbCB2YWx1ZXMgJiBkaXJ0eSBmbGFnc1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF90cmlnZ2VyQWRkRXZlbnQoKSB7XG4gICAgICAgIGlmICh0aGlzLmVuZ2luZS5iYXRjaE1vZGUpXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgaWYgKHRoaXMuZW5naW5lLmFkZGVkTm9kZXM/Lmxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9pZ25vcmVMYXlvdXRzTm9kZUNoYW5nZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW5naW5lLmxheW91dHNOb2Rlc0NoYW5nZSh0aGlzLmVuZ2luZS5hZGRlZE5vZGVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHByZXZlbnQgYWRkZWQgbm9kZXMgZnJvbSBhbHNvIHRyaWdnZXJpbmcgJ2NoYW5nZScgZXZlbnQgKHdoaWNoIGlzIGNhbGxlZCBuZXh0KVxuICAgICAgICAgICAgdGhpcy5lbmdpbmUuYWRkZWROb2Rlcy5mb3JFYWNoKG4gPT4geyBkZWxldGUgbi5fZGlydHk7IH0pO1xuICAgICAgICAgICAgY29uc3QgYWRkZWROb2RlcyA9IFsuLi50aGlzLmVuZ2luZS5hZGRlZE5vZGVzXTtcbiAgICAgICAgICAgIHRoaXMuZW5naW5lLmFkZGVkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudCgnYWRkZWQnLCBhZGRlZE5vZGVzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF90cmlnZ2VyUmVtb3ZlRXZlbnQoKSB7XG4gICAgICAgIGlmICh0aGlzLmVuZ2luZS5iYXRjaE1vZGUpXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgaWYgKHRoaXMuZW5naW5lLnJlbW92ZWROb2Rlcz8ubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCByZW1vdmVkTm9kZXMgPSBbLi4udGhpcy5lbmdpbmUucmVtb3ZlZE5vZGVzXTtcbiAgICAgICAgICAgIHRoaXMuZW5naW5lLnJlbW92ZWROb2RlcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KCdyZW1vdmVkJywgcmVtb3ZlZE5vZGVzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF90cmlnZ2VyRXZlbnQodHlwZSwgZGF0YSkge1xuICAgICAgICBsZXQgZXZlbnQgPSBkYXRhID8gbmV3IEN1c3RvbUV2ZW50KHR5cGUsIHsgYnViYmxlczogZmFsc2UsIGRldGFpbDogZGF0YSB9KSA6IG5ldyBFdmVudCh0eXBlKTtcbiAgICAgICAgdGhpcy5lbC5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgY2FsbGVkIHRvIGRlbGV0ZSB0aGUgY3VycmVudCBkeW5hbWljIHN0eWxlIHNoZWV0IHVzZWQgZm9yIG91ciBsYXlvdXQgKi9cbiAgICBfcmVtb3ZlU3R5bGVzaGVldCgpIHtcbiAgICAgICAgaWYgKHRoaXMuX3N0eWxlcykge1xuICAgICAgICAgICAgY29uc3Qgc3R5bGVMb2NhdGlvbiA9IHRoaXMub3B0cy5zdHlsZUluSGVhZCA/IHVuZGVmaW5lZCA6IHRoaXMuZWwucGFyZW50Tm9kZTtcbiAgICAgICAgICAgIFV0aWxzLnJlbW92ZVN0eWxlc2hlZXQodGhpcy5fc3R5bGVTaGVldENsYXNzLCBzdHlsZUxvY2F0aW9uKTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9zdHlsZXM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgdXBkYXRlZC9jcmVhdGUgdGhlIENTUyBzdHlsZXMgZm9yIHJvdyBiYXNlZCBsYXlvdXQgYW5kIGluaXRpYWwgbWFyZ2luIHNldHRpbmcgKi9cbiAgICBfdXBkYXRlU3R5bGVzKGZvcmNlVXBkYXRlID0gZmFsc2UsIG1heEgpIHtcbiAgICAgICAgLy8gY2FsbCB0byBkZWxldGUgZXhpc3Rpbmcgb25lIGlmIHdlIGNoYW5nZSBjZWxsSGVpZ2h0IC8gbWFyZ2luXG4gICAgICAgIGlmIChmb3JjZVVwZGF0ZSkge1xuICAgICAgICAgICAgdGhpcy5fcmVtb3ZlU3R5bGVzaGVldCgpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXhIID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICBtYXhIID0gdGhpcy5nZXRSb3coKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlQ29udGFpbmVySGVpZ2h0KCk7XG4gICAgICAgIC8vIGlmIHVzZXIgaXMgdGVsbGluZyB1cyB0aGV5IHdpbGwgaGFuZGxlIHRoZSBDU1MgdGhlbXNlbHZlcyBieSBzZXR0aW5nIGhlaWdodHMgdG8gMC4gRG8gd2UgbmVlZCB0aGlzIG9wdHMgcmVhbGx5ID8/XG4gICAgICAgIGlmICh0aGlzLm9wdHMuY2VsbEhlaWdodCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGNlbGxIZWlnaHQgPSB0aGlzLm9wdHMuY2VsbEhlaWdodDtcbiAgICAgICAgbGV0IGNlbGxIZWlnaHRVbml0ID0gdGhpcy5vcHRzLmNlbGxIZWlnaHRVbml0O1xuICAgICAgICBsZXQgcHJlZml4ID0gYC4ke3RoaXMuX3N0eWxlU2hlZXRDbGFzc30gPiAuJHt0aGlzLm9wdHMuaXRlbUNsYXNzfWA7XG4gICAgICAgIC8vIGNyZWF0ZSBvbmUgYXMgbmVlZGVkXG4gICAgICAgIGlmICghdGhpcy5fc3R5bGVzKSB7XG4gICAgICAgICAgICAvLyBpbnNlcnQgc3R5bGUgdG8gcGFyZW50IChpbnN0ZWFkIG9mICdoZWFkJyBieSBkZWZhdWx0KSB0byBzdXBwb3J0IFdlYkNvbXBvbmVudFxuICAgICAgICAgICAgY29uc3Qgc3R5bGVMb2NhdGlvbiA9IHRoaXMub3B0cy5zdHlsZUluSGVhZCA/IHVuZGVmaW5lZCA6IHRoaXMuZWwucGFyZW50Tm9kZTtcbiAgICAgICAgICAgIHRoaXMuX3N0eWxlcyA9IFV0aWxzLmNyZWF0ZVN0eWxlc2hlZXQodGhpcy5fc3R5bGVTaGVldENsYXNzLCBzdHlsZUxvY2F0aW9uLCB7XG4gICAgICAgICAgICAgICAgbm9uY2U6IHRoaXMub3B0cy5ub25jZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9zdHlsZXMpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB0aGlzLl9zdHlsZXMuX21heCA9IDA7XG4gICAgICAgICAgICAvLyB0aGVzZSBhcmUgZG9uZSBvbmNlIG9ubHlcbiAgICAgICAgICAgIFV0aWxzLmFkZENTU1J1bGUodGhpcy5fc3R5bGVzLCBwcmVmaXgsIGBoZWlnaHQ6ICR7Y2VsbEhlaWdodH0ke2NlbGxIZWlnaHRVbml0fWApO1xuICAgICAgICAgICAgLy8gY29udGVudCBtYXJnaW5zXG4gICAgICAgICAgICBsZXQgdG9wID0gdGhpcy5vcHRzLm1hcmdpblRvcCArIHRoaXMub3B0cy5tYXJnaW5Vbml0O1xuICAgICAgICAgICAgbGV0IGJvdHRvbSA9IHRoaXMub3B0cy5tYXJnaW5Cb3R0b20gKyB0aGlzLm9wdHMubWFyZ2luVW5pdDtcbiAgICAgICAgICAgIGxldCByaWdodCA9IHRoaXMub3B0cy5tYXJnaW5SaWdodCArIHRoaXMub3B0cy5tYXJnaW5Vbml0O1xuICAgICAgICAgICAgbGV0IGxlZnQgPSB0aGlzLm9wdHMubWFyZ2luTGVmdCArIHRoaXMub3B0cy5tYXJnaW5Vbml0O1xuICAgICAgICAgICAgbGV0IGNvbnRlbnQgPSBgJHtwcmVmaXh9ID4gLmdyaWQtc3RhY2staXRlbS1jb250ZW50YDtcbiAgICAgICAgICAgIGxldCBwbGFjZWhvbGRlciA9IGAuJHt0aGlzLl9zdHlsZVNoZWV0Q2xhc3N9ID4gLmdyaWQtc3RhY2stcGxhY2Vob2xkZXIgPiAucGxhY2Vob2xkZXItY29udGVudGA7XG4gICAgICAgICAgICBVdGlscy5hZGRDU1NSdWxlKHRoaXMuX3N0eWxlcywgY29udGVudCwgYHRvcDogJHt0b3B9OyByaWdodDogJHtyaWdodH07IGJvdHRvbTogJHtib3R0b219OyBsZWZ0OiAke2xlZnR9O2ApO1xuICAgICAgICAgICAgVXRpbHMuYWRkQ1NTUnVsZSh0aGlzLl9zdHlsZXMsIHBsYWNlaG9sZGVyLCBgdG9wOiAke3RvcH07IHJpZ2h0OiAke3JpZ2h0fTsgYm90dG9tOiAke2JvdHRvbX07IGxlZnQ6ICR7bGVmdH07YCk7XG4gICAgICAgICAgICAvLyByZXNpemUgaGFuZGxlcyBvZmZzZXQgKHRvIG1hdGNoIG1hcmdpbilcbiAgICAgICAgICAgIFV0aWxzLmFkZENTU1J1bGUodGhpcy5fc3R5bGVzLCBgJHtwcmVmaXh9ID4gLnVpLXJlc2l6YWJsZS1uYCwgYHRvcDogJHt0b3B9O2ApO1xuICAgICAgICAgICAgVXRpbHMuYWRkQ1NTUnVsZSh0aGlzLl9zdHlsZXMsIGAke3ByZWZpeH0gPiAudWktcmVzaXphYmxlLXNgLCBgYm90dG9tOiAke2JvdHRvbX1gKTtcbiAgICAgICAgICAgIFV0aWxzLmFkZENTU1J1bGUodGhpcy5fc3R5bGVzLCBgJHtwcmVmaXh9ID4gLnVpLXJlc2l6YWJsZS1uZWAsIGByaWdodDogJHtyaWdodH1gKTtcbiAgICAgICAgICAgIFV0aWxzLmFkZENTU1J1bGUodGhpcy5fc3R5bGVzLCBgJHtwcmVmaXh9ID4gLnVpLXJlc2l6YWJsZS1lYCwgYHJpZ2h0OiAke3JpZ2h0fWApO1xuICAgICAgICAgICAgVXRpbHMuYWRkQ1NTUnVsZSh0aGlzLl9zdHlsZXMsIGAke3ByZWZpeH0gPiAudWktcmVzaXphYmxlLXNlYCwgYHJpZ2h0OiAke3JpZ2h0fTsgYm90dG9tOiAke2JvdHRvbX1gKTtcbiAgICAgICAgICAgIFV0aWxzLmFkZENTU1J1bGUodGhpcy5fc3R5bGVzLCBgJHtwcmVmaXh9ID4gLnVpLXJlc2l6YWJsZS1ud2AsIGBsZWZ0OiAke2xlZnR9YCk7XG4gICAgICAgICAgICBVdGlscy5hZGRDU1NSdWxlKHRoaXMuX3N0eWxlcywgYCR7cHJlZml4fSA+IC51aS1yZXNpemFibGUtd2AsIGBsZWZ0OiAke2xlZnR9YCk7XG4gICAgICAgICAgICBVdGlscy5hZGRDU1NSdWxlKHRoaXMuX3N0eWxlcywgYCR7cHJlZml4fSA+IC51aS1yZXNpemFibGUtc3dgLCBgbGVmdDogJHtsZWZ0fTsgYm90dG9tOiAke2JvdHRvbX1gKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBub3cgdXBkYXRlIHRoZSBoZWlnaHQgc3BlY2lmaWMgZmllbGRzXG4gICAgICAgIG1heEggPSBtYXhIIHx8IHRoaXMuX3N0eWxlcy5fbWF4O1xuICAgICAgICBpZiAobWF4SCA+IHRoaXMuX3N0eWxlcy5fbWF4KSB7XG4gICAgICAgICAgICBsZXQgZ2V0SGVpZ2h0ID0gKHJvd3MpID0+IChjZWxsSGVpZ2h0ICogcm93cykgKyBjZWxsSGVpZ2h0VW5pdDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSB0aGlzLl9zdHlsZXMuX21heCArIDE7IGkgPD0gbWF4SDsgaSsrKSB7IC8vIHN0YXJ0IGF0IDFcbiAgICAgICAgICAgICAgICBVdGlscy5hZGRDU1NSdWxlKHRoaXMuX3N0eWxlcywgYCR7cHJlZml4fVtncy15PVwiJHtpfVwiXWAsIGB0b3A6ICR7Z2V0SGVpZ2h0KGkpfWApO1xuICAgICAgICAgICAgICAgIFV0aWxzLmFkZENTU1J1bGUodGhpcy5fc3R5bGVzLCBgJHtwcmVmaXh9W2dzLWg9XCIke2kgKyAxfVwiXWAsIGBoZWlnaHQ6ICR7Z2V0SGVpZ2h0KGkgKyAxKX1gKTsgLy8gc3RhcnQgYXQgMlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fc3R5bGVzLl9tYXggPSBtYXhIO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsICovXG4gICAgX3VwZGF0ZUNvbnRhaW5lckhlaWdodCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmVuZ2luZSB8fCB0aGlzLmVuZ2luZS5iYXRjaE1vZGUpXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgY29uc3QgcGFyZW50ID0gdGhpcy5wYXJlbnRHcmlkSXRlbTtcbiAgICAgICAgbGV0IHJvdyA9IHRoaXMuZ2V0Um93KCkgKyB0aGlzLl9leHRyYURyYWdSb3c7IC8vIHRoaXMgY2hlY2tzIGZvciBtaW5Sb3cgYWxyZWFkeVxuICAgICAgICBjb25zdCBjZWxsSGVpZ2h0ID0gdGhpcy5vcHRzLmNlbGxIZWlnaHQ7XG4gICAgICAgIGNvbnN0IHVuaXQgPSB0aGlzLm9wdHMuY2VsbEhlaWdodFVuaXQ7XG4gICAgICAgIGlmICghY2VsbEhlaWdodClcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAvLyBjaGVjayBmb3IgY3NzIG1pbiBoZWlnaHQgKG5vbiBuZXN0ZWQgZ3JpZCkuIFRPRE86IHN1cHBvcnQgbWlzbWF0Y2gsIHNheTogbWluICUgd2hpbGUgdW5pdCBpcyBweC5cbiAgICAgICAgaWYgKCFwYXJlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IGNzc01pbkhlaWdodCA9IFV0aWxzLnBhcnNlSGVpZ2h0KGdldENvbXB1dGVkU3R5bGUodGhpcy5lbClbJ21pbkhlaWdodCddKTtcbiAgICAgICAgICAgIGlmIChjc3NNaW5IZWlnaHQuaCA+IDAgJiYgY3NzTWluSGVpZ2h0LnVuaXQgPT09IHVuaXQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtaW5Sb3cgPSBNYXRoLmZsb29yKGNzc01pbkhlaWdodC5oIC8gY2VsbEhlaWdodCk7XG4gICAgICAgICAgICAgICAgaWYgKHJvdyA8IG1pblJvdykge1xuICAgICAgICAgICAgICAgICAgICByb3cgPSBtaW5Sb3c7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuZWwuc2V0QXR0cmlidXRlKCdncy1jdXJyZW50LXJvdycsIFN0cmluZyhyb3cpKTtcbiAgICAgICAgdGhpcy5lbC5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgnbWluLWhlaWdodCcpO1xuICAgICAgICB0aGlzLmVsLnN0eWxlLnJlbW92ZVByb3BlcnR5KCdoZWlnaHQnKTtcbiAgICAgICAgaWYgKHJvdykge1xuICAgICAgICAgICAgLy8gbmVzdGVkIGdyaWRzIGhhdmUgJ2luc2VydDowJyB0byBmaWxsIHRoZSBzcGFjZSBvZiBwYXJlbnQgYnkgZGVmYXVsdCwgYnV0IHdlIG1heSBiZSB0YWxsZXIgc28gdXNlIG1pbi1oZWlnaHQgZm9yIHBvc3NpYmxlIHNjcm9sbGJhcnNcbiAgICAgICAgICAgIHRoaXMuZWwuc3R5bGVbcGFyZW50ID8gJ21pbkhlaWdodCcgOiAnaGVpZ2h0J10gPSByb3cgKiBjZWxsSGVpZ2h0ICsgdW5pdDtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB3ZSdyZSBhIG5lc3RlZCBncmlkIGluc2lkZSBhbiBzaXplVG9Db250ZW50IGl0ZW0sIHRlbGwgaXQgdG8gcmVzaXplIGl0c2VsZiB0b29cbiAgICAgICAgaWYgKHBhcmVudCAmJiAhcGFyZW50LmdyaWQuZW5naW5lLmJhdGNoTW9kZSAmJiBVdGlscy5zaG91bGRTaXplVG9Db250ZW50KHBhcmVudCkpIHtcbiAgICAgICAgICAgIHBhcmVudC5ncmlkLnJlc2l6ZVRvQ29udGVudENCQ2hlY2socGFyZW50LmVsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF9wcmVwYXJlRWxlbWVudChlbCwgdHJpZ2dlckFkZEV2ZW50ID0gZmFsc2UsIG5vZGUpIHtcbiAgICAgICAgbm9kZSA9IG5vZGUgfHwgdGhpcy5fcmVhZEF0dHIoZWwpO1xuICAgICAgICBlbC5ncmlkc3RhY2tOb2RlID0gbm9kZTtcbiAgICAgICAgbm9kZS5lbCA9IGVsO1xuICAgICAgICBub2RlLmdyaWQgPSB0aGlzO1xuICAgICAgICBub2RlID0gdGhpcy5lbmdpbmUuYWRkTm9kZShub2RlLCB0cmlnZ2VyQWRkRXZlbnQpO1xuICAgICAgICAvLyB3cml0ZSB0aGUgZG9tIHNpemVzIGFuZCBjbGFzc1xuICAgICAgICB0aGlzLl93cml0ZUF0dHIoZWwsIG5vZGUpO1xuICAgICAgICBlbC5jbGFzc0xpc3QuYWRkKGdyaWREZWZhdWx0cy5pdGVtQ2xhc3MsIHRoaXMub3B0cy5pdGVtQ2xhc3MpO1xuICAgICAgICBjb25zdCBzaXplVG9Db250ZW50ID0gVXRpbHMuc2hvdWxkU2l6ZVRvQ29udGVudChub2RlKTtcbiAgICAgICAgc2l6ZVRvQ29udGVudCA/IGVsLmNsYXNzTGlzdC5hZGQoJ3NpemUtdG8tY29udGVudCcpIDogZWwuY2xhc3NMaXN0LnJlbW92ZSgnc2l6ZS10by1jb250ZW50Jyk7XG4gICAgICAgIGlmIChzaXplVG9Db250ZW50KVxuICAgICAgICAgICAgdGhpcy5yZXNpemVUb0NvbnRlbnRDaGVjayhmYWxzZSwgbm9kZSk7XG4gICAgICAgIHRoaXMuX3ByZXBhcmVEcmFnRHJvcEJ5Tm9kZShub2RlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgY2FsbCB0byB3cml0ZSBwb3NpdGlvbiB4LHksdyxoIGF0dHJpYnV0ZXMgYmFjayB0byBlbGVtZW50ICovXG4gICAgX3dyaXRlUG9zQXR0cihlbCwgbikge1xuICAgICAgICBpZiAobi54ICE9PSB1bmRlZmluZWQgJiYgbi54ICE9PSBudWxsKSB7XG4gICAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoJ2dzLXgnLCBTdHJpbmcobi54KSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG4ueSAhPT0gdW5kZWZpbmVkICYmIG4ueSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgZWwuc2V0QXR0cmlidXRlKCdncy15JywgU3RyaW5nKG4ueSkpO1xuICAgICAgICB9XG4gICAgICAgIG4udyA+IDEgPyBlbC5zZXRBdHRyaWJ1dGUoJ2dzLXcnLCBTdHJpbmcobi53KSkgOiBlbC5yZW1vdmVBdHRyaWJ1dGUoJ2dzLXcnKTtcbiAgICAgICAgbi5oID4gMSA/IGVsLnNldEF0dHJpYnV0ZSgnZ3MtaCcsIFN0cmluZyhuLmgpKSA6IGVsLnJlbW92ZUF0dHJpYnV0ZSgnZ3MtaCcpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCBjYWxsIHRvIHdyaXRlIGFueSBkZWZhdWx0IGF0dHJpYnV0ZXMgYmFjayB0byBlbGVtZW50ICovXG4gICAgX3dyaXRlQXR0cihlbCwgbm9kZSkge1xuICAgICAgICBpZiAoIW5vZGUpXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgdGhpcy5fd3JpdGVQb3NBdHRyKGVsLCBub2RlKTtcbiAgICAgICAgbGV0IGF0dHJzIC8qOiBHcmlkU3RhY2tXaWRnZXQgYnV0IHN0cmluZ3MgKi8gPSB7XG4gICAgICAgICAgICBhdXRvUG9zaXRpb246ICdncy1hdXRvLXBvc2l0aW9uJyxcbiAgICAgICAgICAgIG5vUmVzaXplOiAnZ3Mtbm8tcmVzaXplJyxcbiAgICAgICAgICAgIG5vTW92ZTogJ2dzLW5vLW1vdmUnLFxuICAgICAgICAgICAgbG9ja2VkOiAnZ3MtbG9ja2VkJyxcbiAgICAgICAgICAgIGlkOiAnZ3MtaWQnLFxuICAgICAgICB9O1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBhdHRycykge1xuICAgICAgICAgICAgaWYgKG5vZGVba2V5XSkgeyAvLyAwIGlzIHZhbGlkIGZvciB4LHkgb25seSBidXQgZG9uZSBhYm92ZSBhbHJlYWR5IGFuZCBub3QgaW4gbGlzdCBhbnl3YXlcbiAgICAgICAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoYXR0cnNba2V5XSwgU3RyaW5nKG5vZGVba2V5XSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZWwucmVtb3ZlQXR0cmlidXRlKGF0dHJzW2tleV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsIGNhbGwgdG8gcmVhZCBhbnkgZGVmYXVsdCBhdHRyaWJ1dGVzIGZyb20gZWxlbWVudCAqL1xuICAgIF9yZWFkQXR0cihlbCwgY2xlYXJEZWZhdWx0QXR0ciA9IHRydWUpIHtcbiAgICAgICAgbGV0IG4gPSB7fTtcbiAgICAgICAgbi54ID0gVXRpbHMudG9OdW1iZXIoZWwuZ2V0QXR0cmlidXRlKCdncy14JykpO1xuICAgICAgICBuLnkgPSBVdGlscy50b051bWJlcihlbC5nZXRBdHRyaWJ1dGUoJ2dzLXknKSk7XG4gICAgICAgIG4udyA9IFV0aWxzLnRvTnVtYmVyKGVsLmdldEF0dHJpYnV0ZSgnZ3MtdycpKTtcbiAgICAgICAgbi5oID0gVXRpbHMudG9OdW1iZXIoZWwuZ2V0QXR0cmlidXRlKCdncy1oJykpO1xuICAgICAgICBuLmF1dG9Qb3NpdGlvbiA9IFV0aWxzLnRvQm9vbChlbC5nZXRBdHRyaWJ1dGUoJ2dzLWF1dG8tcG9zaXRpb24nKSk7XG4gICAgICAgIG4ubm9SZXNpemUgPSBVdGlscy50b0Jvb2woZWwuZ2V0QXR0cmlidXRlKCdncy1uby1yZXNpemUnKSk7XG4gICAgICAgIG4ubm9Nb3ZlID0gVXRpbHMudG9Cb29sKGVsLmdldEF0dHJpYnV0ZSgnZ3Mtbm8tbW92ZScpKTtcbiAgICAgICAgbi5sb2NrZWQgPSBVdGlscy50b0Jvb2woZWwuZ2V0QXR0cmlidXRlKCdncy1sb2NrZWQnKSk7XG4gICAgICAgIG4uaWQgPSBlbC5nZXRBdHRyaWJ1dGUoJ2dzLWlkJyk7XG4gICAgICAgIC8vIHJlYWQgYnV0IG5ldmVyIHdyaXR0ZW4gb3V0XG4gICAgICAgIG4ubWF4VyA9IFV0aWxzLnRvTnVtYmVyKGVsLmdldEF0dHJpYnV0ZSgnZ3MtbWF4LXcnKSk7XG4gICAgICAgIG4ubWluVyA9IFV0aWxzLnRvTnVtYmVyKGVsLmdldEF0dHJpYnV0ZSgnZ3MtbWluLXcnKSk7XG4gICAgICAgIG4ubWF4SCA9IFV0aWxzLnRvTnVtYmVyKGVsLmdldEF0dHJpYnV0ZSgnZ3MtbWF4LWgnKSk7XG4gICAgICAgIG4ubWluSCA9IFV0aWxzLnRvTnVtYmVyKGVsLmdldEF0dHJpYnV0ZSgnZ3MtbWluLWgnKSk7XG4gICAgICAgIC8vIHY4Lnggb3B0aW1pemF0aW9uIHRvIHJlZHVjZSB1bi1uZWVkZWQgYXR0ciB0aGF0IGRvbid0IHJlbmRlciBvciBhcmUgZGVmYXVsdCBDU1NcbiAgICAgICAgaWYgKGNsZWFyRGVmYXVsdEF0dHIpIHtcbiAgICAgICAgICAgIGlmIChuLncgPT09IDEpXG4gICAgICAgICAgICAgICAgZWwucmVtb3ZlQXR0cmlidXRlKCdncy13Jyk7XG4gICAgICAgICAgICBpZiAobi5oID09PSAxKVxuICAgICAgICAgICAgICAgIGVsLnJlbW92ZUF0dHJpYnV0ZSgnZ3MtaCcpO1xuICAgICAgICAgICAgaWYgKG4ubWF4VylcbiAgICAgICAgICAgICAgICBlbC5yZW1vdmVBdHRyaWJ1dGUoJ2dzLW1heC13Jyk7XG4gICAgICAgICAgICBpZiAobi5taW5XKVxuICAgICAgICAgICAgICAgIGVsLnJlbW92ZUF0dHJpYnV0ZSgnZ3MtbWluLXcnKTtcbiAgICAgICAgICAgIGlmIChuLm1heEgpXG4gICAgICAgICAgICAgICAgZWwucmVtb3ZlQXR0cmlidXRlKCdncy1tYXgtaCcpO1xuICAgICAgICAgICAgaWYgKG4ubWluSClcbiAgICAgICAgICAgICAgICBlbC5yZW1vdmVBdHRyaWJ1dGUoJ2dzLW1pbi1oJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVtb3ZlIGFueSBrZXkgbm90IGZvdW5kIChudWxsIG9yIGZhbHNlIHdoaWNoIGlzIGRlZmF1bHQpXG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIG4pIHtcbiAgICAgICAgICAgIGlmICghbi5oYXNPd25Qcm9wZXJ0eShrZXkpKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIGlmICghbltrZXldICYmIG5ba2V5XSAhPT0gMCkgeyAvLyAwIGNhbiBiZSB2YWxpZCB2YWx1ZSAoeCx5IG9ubHkgcmVhbGx5KVxuICAgICAgICAgICAgICAgIGRlbGV0ZSBuW2tleV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG47XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBfc2V0U3RhdGljQ2xhc3MoKSB7XG4gICAgICAgIGxldCBjbGFzc2VzID0gWydncmlkLXN0YWNrLXN0YXRpYyddO1xuICAgICAgICBpZiAodGhpcy5vcHRzLnN0YXRpY0dyaWQpIHtcbiAgICAgICAgICAgIHRoaXMuZWwuY2xhc3NMaXN0LmFkZCguLi5jbGFzc2VzKTtcbiAgICAgICAgICAgIHRoaXMuZWwuc2V0QXR0cmlidXRlKCdncy1zdGF0aWMnLCAndHJ1ZScpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lbC5jbGFzc0xpc3QucmVtb3ZlKC4uLmNsYXNzZXMpO1xuICAgICAgICAgICAgdGhpcy5lbC5yZW1vdmVBdHRyaWJ1dGUoJ2dzLXN0YXRpYycpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBjYWxsZWQgd2hlbiB3ZSBhcmUgYmVpbmcgcmVzaXplZCAtIGNoZWNrIGlmIHRoZSBvbmUgQ29sdW1uIE1vZGUgbmVlZHMgdG8gYmUgdHVybmVkIG9uL29mZlxuICAgICAqIGFuZCByZW1lbWJlciB0aGUgcHJldiBjb2x1bW5zIHdlIHVzZWQsIG9yIGdldCBvdXIgY291bnQgZnJvbSBwYXJlbnQsIGFzIHdlbGwgYXMgY2hlY2sgZm9yIGNlbGxIZWlnaHQ9PT0nYXV0bycgKHNxdWFyZSlcbiAgICAgKiBvciBgc2l6ZVRvQ29udGVudGAgZ3JpZEl0ZW0gb3B0aW9ucy5cbiAgICAgKi9cbiAgICBvblJlc2l6ZSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmVsPy5jbGllbnRXaWR0aClcbiAgICAgICAgICAgIHJldHVybjsgLy8gcmV0dXJuIGlmIHdlJ3JlIGdvbmUgb3Igbm8gc2l6ZSB5ZXQgKHdpbGwgZ2V0IGNhbGxlZCBhZ2FpbilcbiAgICAgICAgaWYgKHRoaXMucHJldldpZHRoID09PSB0aGlzLmVsLmNsaWVudFdpZHRoKVxuICAgICAgICAgICAgcmV0dXJuOyAvLyBuby1vcFxuICAgICAgICB0aGlzLnByZXZXaWR0aCA9IHRoaXMuZWwuY2xpZW50V2lkdGg7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKCdvblJlc2l6ZSAnLCB0aGlzLmVsLmNsaWVudFdpZHRoKTtcbiAgICAgICAgdGhpcy5iYXRjaFVwZGF0ZSgpO1xuICAgICAgICAvLyBzZWUgaWYgd2UncmUgbmVzdGVkIGFuZCB0YWtlIG91ciBjb2x1bW4gY291bnQgZnJvbSBvdXIgcGFyZW50Li4uLlxuICAgICAgICBsZXQgY29sdW1uQ2hhbmdlZCA9IGZhbHNlO1xuICAgICAgICBpZiAodGhpcy5fYXV0b0NvbHVtbiAmJiB0aGlzLnBhcmVudEdyaWRJdGVtKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5vcHRzLmNvbHVtbiAhPT0gdGhpcy5wYXJlbnRHcmlkSXRlbS53KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb2x1bW4odGhpcy5wYXJlbnRHcmlkSXRlbS53LCAnbm9uZScpO1xuICAgICAgICAgICAgICAgIGNvbHVtbkNoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gZWxzZSBjaGVjayBmb3IgZHluYW1pYyBjb2x1bW5cbiAgICAgICAgICAgIGNvbHVtbkNoYW5nZWQgPSB0aGlzLmNoZWNrRHluYW1pY0NvbHVtbigpO1xuICAgICAgICB9XG4gICAgICAgIC8vIG1ha2UgdGhlIGNlbGxzIGNvbnRlbnQgc3F1YXJlIGFnYWluXG4gICAgICAgIGlmICh0aGlzLl9pc0F1dG9DZWxsSGVpZ2h0KVxuICAgICAgICAgICAgdGhpcy5jZWxsSGVpZ2h0KCk7XG4gICAgICAgIC8vIHVwZGF0ZSBhbnkgbmVzdGVkIGdyaWRzLCBvciBpdGVtcyBzaXplXG4gICAgICAgIHRoaXMuZW5naW5lLm5vZGVzLmZvckVhY2gobiA9PiB7XG4gICAgICAgICAgICBpZiAobi5zdWJHcmlkKVxuICAgICAgICAgICAgICAgIG4uc3ViR3JpZC5vblJlc2l6ZSgpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCF0aGlzLl9za2lwSW5pdGlhbFJlc2l6ZSlcbiAgICAgICAgICAgIHRoaXMucmVzaXplVG9Db250ZW50Q2hlY2soY29sdW1uQ2hhbmdlZCk7IC8vIHdhaXQgZm9yIGFuaW0gb2YgY29sdW1uIGNoYW5nZWQgKERPTSByZWZsb3cgYmVmb3JlIHdlIGNhbiBzaXplIGNvcnJlY3RseSlcbiAgICAgICAgZGVsZXRlIHRoaXMuX3NraXBJbml0aWFsUmVzaXplO1xuICAgICAgICB0aGlzLmJhdGNoVXBkYXRlKGZhbHNlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiByZXNpemVzIGNvbnRlbnQgZm9yIGdpdmVuIG5vZGUgKG9yIGFsbCkgaWYgc2hvdWxkU2l6ZVRvQ29udGVudCgpIGlzIHRydWUgKi9cbiAgICByZXNpemVUb0NvbnRlbnRDaGVjayhkZWxheSA9IGZhbHNlLCBuID0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmICghdGhpcy5lbmdpbmUpXG4gICAgICAgICAgICByZXR1cm47IC8vIHdlJ3ZlIGJlZW4gZGVsZXRlZCBpbiBiZXR3ZWVuIVxuICAgICAgICAvLyB1cGRhdGUgYW55IGdyaWRJdGVtIGhlaWdodCB3aXRoIHNpemVUb0NvbnRlbnQsIGJ1dCB3YWl0IGZvciBET00gJGFuaW1hdGlvbl9zcGVlZCB0byBzZXR0bGUgaWYgd2UgY2hhbmdlZCBjb2x1bW4gY291bnRcbiAgICAgICAgLy8gVE9ETzogaXMgdGhlcmUgYSB3YXkgdG8ga25vdyB3aGF0IHRoZSBmaW5hbCAocG9zdCBhbmltYXRpb24pIHNpemUgb2YgdGhlIGNvbnRlbnQgd2lsbCBiZSBzbyB3ZSBjYW4gYW5pbWF0ZSB0aGUgY29sdW1uIHdpZHRoIGFuZCBoZWlnaHQgdG9nZXRoZXIgcmF0aGVyIHRoYW4gc2VxdWVudGlhbGx5ID9cbiAgICAgICAgaWYgKGRlbGF5ICYmIHRoaXMuaGFzQW5pbWF0aW9uQ1NTKCkpXG4gICAgICAgICAgICByZXR1cm4gc2V0VGltZW91dCgoKSA9PiB0aGlzLnJlc2l6ZVRvQ29udGVudENoZWNrKGZhbHNlLCBuKSwgMzAwICsgMTApO1xuICAgICAgICBpZiAobikge1xuICAgICAgICAgICAgaWYgKFV0aWxzLnNob3VsZFNpemVUb0NvbnRlbnQobikpXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNpemVUb0NvbnRlbnRDQkNoZWNrKG4uZWwpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMuZW5naW5lLm5vZGVzLnNvbWUobiA9PiBVdGlscy5zaG91bGRTaXplVG9Db250ZW50KG4pKSkge1xuICAgICAgICAgICAgY29uc3Qgbm9kZXMgPSBbLi4udGhpcy5lbmdpbmUubm9kZXNdOyAvLyBpbiBjYXNlIG9yZGVyIGNoYW5nZXMgd2hpbGUgcmVzaXppbmcgb25lXG4gICAgICAgICAgICB0aGlzLmJhdGNoVXBkYXRlKCk7XG4gICAgICAgICAgICBub2Rlcy5mb3JFYWNoKG4gPT4ge1xuICAgICAgICAgICAgICAgIGlmIChVdGlscy5zaG91bGRTaXplVG9Db250ZW50KG4pKVxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZVRvQ29udGVudENCQ2hlY2sobi5lbCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuYmF0Y2hVcGRhdGUoZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNhbGwgdGhpcyByZWdhcmRsZXNzIG9mIHNob3VsZFNpemVUb0NvbnRlbnQgYmVjYXVzZSB3aWRnZXQgbWlnaHQgbmVlZCB0byBzdHJldGNoIHRvIHRha2UgYXZhaWxhYmxlIHNwYWNlIGFmdGVyIGEgcmVzaXplXG4gICAgICAgIGlmICh0aGlzLl9nc0V2ZW50SGFuZGxlclsncmVzaXplY29udGVudCddKVxuICAgICAgICAgICAgdGhpcy5fZ3NFdmVudEhhbmRsZXJbJ3Jlc2l6ZWNvbnRlbnQnXShudWxsLCBuID8gW25dIDogdGhpcy5lbmdpbmUubm9kZXMpO1xuICAgIH1cbiAgICAvKiogYWRkIG9yIHJlbW92ZSB0aGUgZ3JpZCBlbGVtZW50IHNpemUgZXZlbnQgaGFuZGxlciAqL1xuICAgIF91cGRhdGVSZXNpemVFdmVudChmb3JjZVJlbW92ZSA9IGZhbHNlKSB7XG4gICAgICAgIC8vIG9ubHkgYWRkIGV2ZW50IGlmIHdlJ3JlIG5vdCBuZXN0ZWQgKHBhcmVudCB3aWxsIGNhbGwgdXMpIGFuZCB3ZSdyZSBhdXRvIHNpemluZyBjZWxscyBvciBzdXBwb3J0aW5nIGR5bmFtaWMgY29sdW1uIChpLmUuIGRvaW5nIHdvcmspXG4gICAgICAgIC8vIG9yIHN1cHBvcnRpbmcgbmV3IHNpemVUb0NvbnRlbnQgb3B0aW9uLlxuICAgICAgICBjb25zdCB0cmFja1NpemUgPSAhdGhpcy5wYXJlbnRHcmlkSXRlbSAmJiAodGhpcy5faXNBdXRvQ2VsbEhlaWdodCB8fCB0aGlzLm9wdHMuc2l6ZVRvQ29udGVudCB8fCB0aGlzLm9wdHMuY29sdW1uT3B0c1xuICAgICAgICAgICAgfHwgdGhpcy5lbmdpbmUubm9kZXMuZmluZChuID0+IG4uc2l6ZVRvQ29udGVudCkpO1xuICAgICAgICBpZiAoIWZvcmNlUmVtb3ZlICYmIHRyYWNrU2l6ZSAmJiAhdGhpcy5yZXNpemVPYnNlcnZlcikge1xuICAgICAgICAgICAgdGhpcy5fc2l6ZVRocm90dGxlID0gVXRpbHMudGhyb3R0bGUoKCkgPT4gdGhpcy5vblJlc2l6ZSgpLCB0aGlzLm9wdHMuY2VsbEhlaWdodFRocm90dGxlKTtcbiAgICAgICAgICAgIHRoaXMucmVzaXplT2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoKCkgPT4gdGhpcy5fc2l6ZVRocm90dGxlKCkpO1xuICAgICAgICAgICAgdGhpcy5yZXNpemVPYnNlcnZlci5vYnNlcnZlKHRoaXMuZWwpO1xuICAgICAgICAgICAgdGhpcy5fc2tpcEluaXRpYWxSZXNpemUgPSB0cnVlOyAvLyBtYWtlV2lkZ2V0IHdpbGwgb3JpZ2luYWxseSBoYXZlIGNhbGxlZCBvbiBzdGFydHVwXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoKGZvcmNlUmVtb3ZlIHx8ICF0cmFja1NpemUpICYmIHRoaXMucmVzaXplT2JzZXJ2ZXIpIHtcbiAgICAgICAgICAgIHRoaXMucmVzaXplT2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVzaXplT2JzZXJ2ZXI7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fc2l6ZVRocm90dGxlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsIGNvbnZlcnQgYSBwb3RlbnRpYWwgc2VsZWN0b3IgaW50byBhY3R1YWwgZWxlbWVudCAqL1xuICAgIHN0YXRpYyBnZXRFbGVtZW50KGVscyA9ICcuZ3JpZC1zdGFjay1pdGVtJykgeyByZXR1cm4gVXRpbHMuZ2V0RWxlbWVudChlbHMpOyB9XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIHN0YXRpYyBnZXRFbGVtZW50cyhlbHMgPSAnLmdyaWQtc3RhY2staXRlbScpIHsgcmV0dXJuIFV0aWxzLmdldEVsZW1lbnRzKGVscyk7IH1cbiAgICAvKiogQGludGVybmFsICovXG4gICAgc3RhdGljIGdldEdyaWRFbGVtZW50KGVscykgeyByZXR1cm4gR3JpZFN0YWNrLmdldEVsZW1lbnQoZWxzKTsgfVxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBzdGF0aWMgZ2V0R3JpZEVsZW1lbnRzKGVscykgeyByZXR1cm4gVXRpbHMuZ2V0RWxlbWVudHMoZWxzKTsgfVxuICAgIC8qKiBAaW50ZXJuYWwgaW5pdGlhbGl6ZSBtYXJnaW4gdG9wL2JvdHRvbS9sZWZ0L3JpZ2h0IGFuZCB1bml0cyAqL1xuICAgIF9pbml0TWFyZ2luKCkge1xuICAgICAgICBsZXQgZGF0YTtcbiAgICAgICAgbGV0IG1hcmdpbiA9IDA7XG4gICAgICAgIC8vIHN1cHBvcnQgcGFzc2luZyBtdWx0aXBsZSB2YWx1ZXMgbGlrZSBDU1MgKGV4OiAnNXB4IDEwcHggMCAyMHB4JylcbiAgICAgICAgbGV0IG1hcmdpbnMgPSBbXTtcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm9wdHMubWFyZ2luID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgbWFyZ2lucyA9IHRoaXMub3B0cy5tYXJnaW4uc3BsaXQoJyAnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWFyZ2lucy5sZW5ndGggPT09IDIpIHsgLy8gdG9wL2JvdCwgbGVmdC9yaWdodCBsaWtlIENTU1xuICAgICAgICAgICAgdGhpcy5vcHRzLm1hcmdpblRvcCA9IHRoaXMub3B0cy5tYXJnaW5Cb3R0b20gPSBtYXJnaW5zWzBdO1xuICAgICAgICAgICAgdGhpcy5vcHRzLm1hcmdpbkxlZnQgPSB0aGlzLm9wdHMubWFyZ2luUmlnaHQgPSBtYXJnaW5zWzFdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG1hcmdpbnMubGVuZ3RoID09PSA0KSB7IC8vIENsb2Nrd2lzZSBsaWtlIENTU1xuICAgICAgICAgICAgdGhpcy5vcHRzLm1hcmdpblRvcCA9IG1hcmdpbnNbMF07XG4gICAgICAgICAgICB0aGlzLm9wdHMubWFyZ2luUmlnaHQgPSBtYXJnaW5zWzFdO1xuICAgICAgICAgICAgdGhpcy5vcHRzLm1hcmdpbkJvdHRvbSA9IG1hcmdpbnNbMl07XG4gICAgICAgICAgICB0aGlzLm9wdHMubWFyZ2luTGVmdCA9IG1hcmdpbnNbM107XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBkYXRhID0gVXRpbHMucGFyc2VIZWlnaHQodGhpcy5vcHRzLm1hcmdpbik7XG4gICAgICAgICAgICB0aGlzLm9wdHMubWFyZ2luVW5pdCA9IGRhdGEudW5pdDtcbiAgICAgICAgICAgIG1hcmdpbiA9IHRoaXMub3B0cy5tYXJnaW4gPSBkYXRhLmg7XG4gICAgICAgIH1cbiAgICAgICAgLy8gc2VlIGlmIHRvcC9ib3R0b20vbGVmdC9yaWdodCBuZWVkIHRvIGJlIHNldCBhcyB3ZWxsXG4gICAgICAgIGlmICh0aGlzLm9wdHMubWFyZ2luVG9wID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMub3B0cy5tYXJnaW5Ub3AgPSBtYXJnaW47XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBkYXRhID0gVXRpbHMucGFyc2VIZWlnaHQodGhpcy5vcHRzLm1hcmdpblRvcCk7XG4gICAgICAgICAgICB0aGlzLm9wdHMubWFyZ2luVG9wID0gZGF0YS5oO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMub3B0cy5tYXJnaW47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMub3B0cy5tYXJnaW5Cb3R0b20gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5vcHRzLm1hcmdpbkJvdHRvbSA9IG1hcmdpbjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRhdGEgPSBVdGlscy5wYXJzZUhlaWdodCh0aGlzLm9wdHMubWFyZ2luQm90dG9tKTtcbiAgICAgICAgICAgIHRoaXMub3B0cy5tYXJnaW5Cb3R0b20gPSBkYXRhLmg7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5vcHRzLm1hcmdpbjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5vcHRzLm1hcmdpblJpZ2h0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMub3B0cy5tYXJnaW5SaWdodCA9IG1hcmdpbjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRhdGEgPSBVdGlscy5wYXJzZUhlaWdodCh0aGlzLm9wdHMubWFyZ2luUmlnaHQpO1xuICAgICAgICAgICAgdGhpcy5vcHRzLm1hcmdpblJpZ2h0ID0gZGF0YS5oO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMub3B0cy5tYXJnaW47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMub3B0cy5tYXJnaW5MZWZ0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMub3B0cy5tYXJnaW5MZWZ0ID0gbWFyZ2luO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZGF0YSA9IFV0aWxzLnBhcnNlSGVpZ2h0KHRoaXMub3B0cy5tYXJnaW5MZWZ0KTtcbiAgICAgICAgICAgIHRoaXMub3B0cy5tYXJnaW5MZWZ0ID0gZGF0YS5oO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMub3B0cy5tYXJnaW47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vcHRzLm1hcmdpblVuaXQgPSBkYXRhLnVuaXQ7IC8vIGluIGNhc2Ugc2lkZSB3ZXJlIHNwZWxsZWQgb3V0LCB1c2UgdGhvc2UgdW5pdHMgaW5zdGVhZC4uLlxuICAgICAgICBpZiAodGhpcy5vcHRzLm1hcmdpblRvcCA9PT0gdGhpcy5vcHRzLm1hcmdpbkJvdHRvbSAmJiB0aGlzLm9wdHMubWFyZ2luTGVmdCA9PT0gdGhpcy5vcHRzLm1hcmdpblJpZ2h0ICYmIHRoaXMub3B0cy5tYXJnaW5Ub3AgPT09IHRoaXMub3B0cy5tYXJnaW5SaWdodCkge1xuICAgICAgICAgICAgdGhpcy5vcHRzLm1hcmdpbiA9IHRoaXMub3B0cy5tYXJnaW5Ub3A7IC8vIG1ha2VzIGl0IGVhc2llciB0byBjaGVjayBmb3Igbm8tb3BzIGluIHNldE1hcmdpbigpXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAgKiBkcmFnJmRyb3AgbWV0aG9kcyB0aGF0IHVzZWQgdG8gYmUgc3R1YmJlZCBvdXQgYW5kIGltcGxlbWVudGVkIGluIGRkLWdyaWRzdGFjay50c1xuICAgICAqIGJ1dCBjYXVzZWQgbG9hZGluZyBpc3N1ZXMgaW4gcHJvZCAtIHNlZSBodHRwczovL2dpdGh1Yi5jb20vZ3JpZHN0YWNrL2dyaWRzdGFjay5qcy9pc3N1ZXMvMjAzOVxuICAgICAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAgKi9cbiAgICAvKiogZ2V0IHRoZSBnbG9iYWwgKGJ1dCBzdGF0aWMgdG8gdGhpcyBjb2RlKSBERCBpbXBsZW1lbnRhdGlvbiAqL1xuICAgIHN0YXRpYyBnZXRERCgpIHtcbiAgICAgICAgcmV0dXJuIGRkO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBjYWxsIHRvIHNldHVwIGRyYWdnaW5nIGluIGZyb20gdGhlIG91dHNpZGUgKHNheSB0b29sYmFyKSwgYnkgc3BlY2lmeWluZyB0aGUgY2xhc3Mgc2VsZWN0aW9uIGFuZCBvcHRpb25zLlxuICAgICAqIENhbGxlZCBkdXJpbmcgR3JpZFN0YWNrLmluaXQoKSBhcyBvcHRpb25zLCBidXQgY2FuIGFsc28gYmUgY2FsbGVkIGRpcmVjdGx5IChsYXN0IHBhcmFtIGFyZSB1c2VkKSBpbiBjYXNlIHRoZSB0b29sYmFyXG4gICAgICogaXMgZHluYW1pY2FsbHkgY3JlYXRlIGFuZCBuZWVkcyB0byBiZSBzZXQgbGF0ZXIuXG4gICAgICogQHBhcmFtIGRyYWdJbiBzdHJpbmcgc2VsZWN0b3IgKGV4OiAnLnNpZGViYXIgLmdyaWQtc3RhY2staXRlbScpIG9yIGxpc3Qgb2YgZG9tIGVsZW1lbnRzXG4gICAgICogQHBhcmFtIGRyYWdJbk9wdGlvbnMgb3B0aW9ucyAtIHNlZSBERERyYWdJbk9wdC4gKGRlZmF1bHQ6IHtoYW5kbGU6ICcuZ3JpZC1zdGFjay1pdGVtLWNvbnRlbnQnLCBhcHBlbmRUbzogJ2JvZHknfVxuICAgICAqIEBwYXJhbSByb290IG9wdGlvbmFsIHJvb3Qgd2hpY2ggZGVmYXVsdHMgdG8gZG9jdW1lbnQgKGZvciBzaGFkb3cgZG9tIHBhcyB0aGUgcGFyZW50IEhUTUxEb2N1bWVudClcbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0dXBEcmFnSW4oZHJhZ0luLCBkcmFnSW5PcHRpb25zLCByb290ID0gZG9jdW1lbnQpIHtcbiAgICAgICAgaWYgKGRyYWdJbk9wdGlvbnM/LnBhdXNlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIERETWFuYWdlci5wYXVzZURyYWcgPSBkcmFnSW5PcHRpb25zLnBhdXNlO1xuICAgICAgICB9XG4gICAgICAgIGRyYWdJbk9wdGlvbnMgPSB7IC4uLmRyYWdJbkRlZmF1bHRPcHRpb25zLCAuLi4oZHJhZ0luT3B0aW9ucyB8fCB7fSkgfTtcbiAgICAgICAgbGV0IGVscyA9ICh0eXBlb2YgZHJhZ0luID09PSAnc3RyaW5nJykgPyBVdGlscy5nZXRFbGVtZW50cyhkcmFnSW4sIHJvb3QpIDogZHJhZ0luO1xuICAgICAgICBpZiAoZWxzLmxlbmd0aClcbiAgICAgICAgICAgIGVscz8uZm9yRWFjaChlbCA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFkZC5pc0RyYWdnYWJsZShlbCkpXG4gICAgICAgICAgICAgICAgICAgIGRkLmRyYWdJbihlbCwgZHJhZ0luT3B0aW9ucyk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRW5hYmxlcy9EaXNhYmxlcyBkcmFnZ2luZyBieSB0aGUgdXNlciBvZiBzcGVjaWZpYyBncmlkIGVsZW1lbnQuIElmIHlvdSB3YW50IGFsbCBpdGVtcywgYW5kIGhhdmUgaXQgYWZmZWN0IGZ1dHVyZSBpdGVtcywgdXNlIGVuYWJsZU1vdmUoKSBpbnN0ZWFkLiBOby1vcCBmb3Igc3RhdGljIGdyaWRzLlxuICAgICAqIElGIHlvdSBhcmUgbG9va2luZyB0byBwcmV2ZW50IGFuIGl0ZW0gZnJvbSBtb3ZpbmcgKGR1ZSB0byBiZWluZyBwdXNoZWQgYXJvdW5kIGJ5IGFub3RoZXIgZHVyaW5nIGNvbGxpc2lvbikgdXNlIGxvY2tlZCBwcm9wZXJ0eSBpbnN0ZWFkLlxuICAgICAqIEBwYXJhbSBlbHMgd2lkZ2V0IG9yIHNlbGVjdG9yIHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0gdmFsIGlmIHRydWUgd2lkZ2V0IHdpbGwgYmUgZHJhZ2dhYmxlLCBhc3N1bWluZyB0aGUgcGFyZW50IGdyaWQgaXNuJ3Qgbm9Nb3ZlIG9yIHN0YXRpYy5cbiAgICAgKi9cbiAgICBtb3ZhYmxlKGVscywgdmFsKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdHMuc3RhdGljR3JpZClcbiAgICAgICAgICAgIHJldHVybiB0aGlzOyAvLyBjYW4ndCBtb3ZlIGEgc3RhdGljIGdyaWQhXG4gICAgICAgIEdyaWRTdGFjay5nZXRFbGVtZW50cyhlbHMpLmZvckVhY2goZWwgPT4ge1xuICAgICAgICAgICAgY29uc3QgbiA9IGVsLmdyaWRzdGFja05vZGU7XG4gICAgICAgICAgICBpZiAoIW4pXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgdmFsID8gZGVsZXRlIG4ubm9Nb3ZlIDogbi5ub01vdmUgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5fcHJlcGFyZURyYWdEcm9wQnlOb2RlKG4pOyAvLyBpbml0IEREIGlmIG5lZWQgYmUsIGFuZCBhZGp1c3RcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBFbmFibGVzL0Rpc2FibGVzIHVzZXIgcmVzaXppbmcgb2Ygc3BlY2lmaWMgZ3JpZCBlbGVtZW50LiBJZiB5b3Ugd2FudCBhbGwgaXRlbXMsIGFuZCBoYXZlIGl0IGFmZmVjdCBmdXR1cmUgaXRlbXMsIHVzZSBlbmFibGVSZXNpemUoKSBpbnN0ZWFkLiBOby1vcCBmb3Igc3RhdGljIGdyaWRzLlxuICAgICAqIEBwYXJhbSBlbHMgIHdpZGdldCBvciBzZWxlY3RvciB0byBtb2RpZnlcbiAgICAgKiBAcGFyYW0gdmFsICBpZiB0cnVlIHdpZGdldCB3aWxsIGJlIHJlc2l6YWJsZSwgYXNzdW1pbmcgdGhlIHBhcmVudCBncmlkIGlzbid0IG5vUmVzaXplIG9yIHN0YXRpYy5cbiAgICAgKi9cbiAgICByZXNpemFibGUoZWxzLCB2YWwpIHtcbiAgICAgICAgaWYgKHRoaXMub3B0cy5zdGF0aWNHcmlkKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7IC8vIGNhbid0IHJlc2l6ZSBhIHN0YXRpYyBncmlkIVxuICAgICAgICBHcmlkU3RhY2suZ2V0RWxlbWVudHMoZWxzKS5mb3JFYWNoKGVsID0+IHtcbiAgICAgICAgICAgIGxldCBuID0gZWwuZ3JpZHN0YWNrTm9kZTtcbiAgICAgICAgICAgIGlmICghbilcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB2YWwgPyBkZWxldGUgbi5ub1Jlc2l6ZSA6IG4ubm9SZXNpemUgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5fcHJlcGFyZURyYWdEcm9wQnlOb2RlKG4pOyAvLyBpbml0IEREIGlmIG5lZWQgYmUsIGFuZCBhZGp1c3RcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBUZW1wb3JhcmlseSBkaXNhYmxlcyB3aWRnZXRzIG1vdmluZy9yZXNpemluZy5cbiAgICAgKiBJZiB5b3Ugd2FudCBhIG1vcmUgcGVybWFuZW50IHdheSAod2hpY2ggZnJlZXplcyB1cCByZXNvdXJjZXMpIHVzZSBgc2V0U3RhdGljKHRydWUpYCBpbnN0ZWFkLlxuICAgICAqIE5vdGU6IG5vLW9wIGZvciBzdGF0aWMgZ3JpZFxuICAgICAqIFRoaXMgaXMgYSBzaG9ydGN1dCBmb3I6XG4gICAgICogQGV4YW1wbGVcbiAgICAgKiAgZ3JpZC5lbmFibGVNb3ZlKGZhbHNlKTtcbiAgICAgKiAgZ3JpZC5lbmFibGVSZXNpemUoZmFsc2UpO1xuICAgICAqIEBwYXJhbSByZWN1cnNlIHRydWUgKGRlZmF1bHQpIGlmIHN1Yi1ncmlkcyBhbHNvIGdldCB1cGRhdGVkXG4gICAgICovXG4gICAgZGlzYWJsZShyZWN1cnNlID0gdHJ1ZSkge1xuICAgICAgICBpZiAodGhpcy5vcHRzLnN0YXRpY0dyaWQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHRoaXMuZW5hYmxlTW92ZShmYWxzZSwgcmVjdXJzZSk7XG4gICAgICAgIHRoaXMuZW5hYmxlUmVzaXplKGZhbHNlLCByZWN1cnNlKTtcbiAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KCdkaXNhYmxlJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZS1lbmFibGVzIHdpZGdldHMgbW92aW5nL3Jlc2l6aW5nIC0gc2VlIGRpc2FibGUoKS5cbiAgICAgKiBOb3RlOiBuby1vcCBmb3Igc3RhdGljIGdyaWQuXG4gICAgICogVGhpcyBpcyBhIHNob3J0Y3V0IGZvcjpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqICBncmlkLmVuYWJsZU1vdmUodHJ1ZSk7XG4gICAgICogIGdyaWQuZW5hYmxlUmVzaXplKHRydWUpO1xuICAgICAqIEBwYXJhbSByZWN1cnNlIHRydWUgKGRlZmF1bHQpIGlmIHN1Yi1ncmlkcyBhbHNvIGdldCB1cGRhdGVkXG4gICAgICovXG4gICAgZW5hYmxlKHJlY3Vyc2UgPSB0cnVlKSB7XG4gICAgICAgIGlmICh0aGlzLm9wdHMuc3RhdGljR3JpZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgdGhpcy5lbmFibGVNb3ZlKHRydWUsIHJlY3Vyc2UpO1xuICAgICAgICB0aGlzLmVuYWJsZVJlc2l6ZSh0cnVlLCByZWN1cnNlKTtcbiAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KCdlbmFibGUnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEVuYWJsZXMvZGlzYWJsZXMgd2lkZ2V0IG1vdmluZy4gTm8tb3AgZm9yIHN0YXRpYyBncmlkcywgYW5kIGxvY2FsbHkgZGVmaW5lZCBpdGVtcyBzdGlsbCBvdmVycnVsZVxuICAgICAqIEBwYXJhbSByZWN1cnNlIHRydWUgKGRlZmF1bHQpIGlmIHN1Yi1ncmlkcyBhbHNvIGdldCB1cGRhdGVkXG4gICAgICovXG4gICAgZW5hYmxlTW92ZShkb0VuYWJsZSwgcmVjdXJzZSA9IHRydWUpIHtcbiAgICAgICAgaWYgKHRoaXMub3B0cy5zdGF0aWNHcmlkKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7IC8vIGNhbid0IG1vdmUgYSBzdGF0aWMgZ3JpZCFcbiAgICAgICAgZG9FbmFibGUgPyBkZWxldGUgdGhpcy5vcHRzLmRpc2FibGVEcmFnIDogdGhpcy5vcHRzLmRpc2FibGVEcmFnID0gdHJ1ZTsgLy8gRklSU1QgYmVmb3JlIHdlIHVwZGF0ZSBjaGlsZHJlbiBhcyBncmlkIG92ZXJyaWRlcyAjMTY1OFxuICAgICAgICB0aGlzLmVuZ2luZS5ub2Rlcy5mb3JFYWNoKG4gPT4ge1xuICAgICAgICAgICAgdGhpcy5fcHJlcGFyZURyYWdEcm9wQnlOb2RlKG4pO1xuICAgICAgICAgICAgaWYgKG4uc3ViR3JpZCAmJiByZWN1cnNlKVxuICAgICAgICAgICAgICAgIG4uc3ViR3JpZC5lbmFibGVNb3ZlKGRvRW5hYmxlLCByZWN1cnNlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBFbmFibGVzL2Rpc2FibGVzIHdpZGdldCByZXNpemluZy4gTm8tb3AgZm9yIHN0YXRpYyBncmlkcy5cbiAgICAgKiBAcGFyYW0gcmVjdXJzZSB0cnVlIChkZWZhdWx0KSBpZiBzdWItZ3JpZHMgYWxzbyBnZXQgdXBkYXRlZFxuICAgICAqL1xuICAgIGVuYWJsZVJlc2l6ZShkb0VuYWJsZSwgcmVjdXJzZSA9IHRydWUpIHtcbiAgICAgICAgaWYgKHRoaXMub3B0cy5zdGF0aWNHcmlkKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7IC8vIGNhbid0IHNpemUgYSBzdGF0aWMgZ3JpZCFcbiAgICAgICAgZG9FbmFibGUgPyBkZWxldGUgdGhpcy5vcHRzLmRpc2FibGVSZXNpemUgOiB0aGlzLm9wdHMuZGlzYWJsZVJlc2l6ZSA9IHRydWU7IC8vIEZJUlNUIGJlZm9yZSB3ZSB1cGRhdGUgY2hpbGRyZW4gYXMgZ3JpZCBvdmVycmlkZXMgIzE2NThcbiAgICAgICAgdGhpcy5lbmdpbmUubm9kZXMuZm9yRWFjaChuID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3ByZXBhcmVEcmFnRHJvcEJ5Tm9kZShuKTtcbiAgICAgICAgICAgIGlmIChuLnN1YkdyaWQgJiYgcmVjdXJzZSlcbiAgICAgICAgICAgICAgICBuLnN1YkdyaWQuZW5hYmxlUmVzaXplKGRvRW5hYmxlLCByZWN1cnNlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsIHJlbW92ZXMgYW55IGRyYWcmZHJvcCBwcmVzZW50IChjYWxsZWQgZHVyaW5nIGRlc3Ryb3kpICovXG4gICAgX3JlbW92ZUREKGVsKSB7XG4gICAgICAgIGRkLmRyYWdnYWJsZShlbCwgJ2Rlc3Ryb3knKS5yZXNpemFibGUoZWwsICdkZXN0cm95Jyk7XG4gICAgICAgIGlmIChlbC5ncmlkc3RhY2tOb2RlKSB7XG4gICAgICAgICAgICBkZWxldGUgZWwuZ3JpZHN0YWNrTm9kZS5faW5pdEREOyAvLyByZXNldCBvdXIgREQgaW5pdCBmbGFnXG4gICAgICAgIH1cbiAgICAgICAgZGVsZXRlIGVsLmRkRWxlbWVudDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgY2FsbGVkIHRvIGFkZCBkcmFnIG92ZXIgdG8gc3VwcG9ydCB3aWRnZXRzIGJlaW5nIGFkZGVkIGV4dGVybmFsbHkgKi9cbiAgICBfc2V0dXBBY2NlcHRXaWRnZXQoKSB7XG4gICAgICAgIC8vIGNoZWNrIGlmIHdlIG5lZWQgdG8gZGlzYWJsZSB0aGluZ3NcbiAgICAgICAgaWYgKHRoaXMub3B0cy5zdGF0aWNHcmlkIHx8ICghdGhpcy5vcHRzLmFjY2VwdFdpZGdldHMgJiYgIXRoaXMub3B0cy5yZW1vdmFibGUpKSB7XG4gICAgICAgICAgICBkZC5kcm9wcGFibGUodGhpcy5lbCwgJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIC8vIHZhcnMgc2hhcmVkIGFjcm9zcyBhbGwgbWV0aG9kc1xuICAgICAgICBsZXQgY2VsbEhlaWdodCwgY2VsbFdpZHRoO1xuICAgICAgICBsZXQgb25EcmFnID0gKGV2ZW50LCBlbCwgaGVscGVyKSA9PiB7XG4gICAgICAgICAgICBsZXQgbm9kZSA9IGVsLmdyaWRzdGFja05vZGU7XG4gICAgICAgICAgICBpZiAoIW5vZGUpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgaGVscGVyID0gaGVscGVyIHx8IGVsO1xuICAgICAgICAgICAgLy8gaWYgdGhlIGVsZW1lbnQgaXMgYmVpbmcgZHJhZ2dlZCBmcm9tIG91dHNpZGUsIHNjYWxlIGl0IGRvd24gdG8gbWF0Y2ggdGhlIGdyaWQncyBzY2FsZVxuICAgICAgICAgICAgLy8gYW5kIHNsaWdodGx5IGFkanVzdCBpdHMgcG9zaXRpb24gcmVsYXRpdmUgdG8gdGhlIG1vdXNlXG4gICAgICAgICAgICBpZiAoIW5vZGUuZ3JpZD8uZWwpIHtcbiAgICAgICAgICAgICAgICAvLyB0aGlzIHNjYWxlcyB0aGUgaGVscGVyIGRvd25cbiAgICAgICAgICAgICAgICBoZWxwZXIuc3R5bGUudHJhbnNmb3JtID0gYHNjYWxlKCR7MSAvIHRoaXMuZHJhZ1RyYW5zZm9ybS54U2NhbGV9LCR7MSAvIHRoaXMuZHJhZ1RyYW5zZm9ybS55U2NhbGV9KWA7XG4gICAgICAgICAgICAgICAgLy8gdGhpcyBtYWtlcyBpdCBzbyB0aGF0IHRoZSBoZWxwZXIgaXMgd2VsbCBwb3NpdGlvbmVkIHJlbGF0aXZlIHRvIHRoZSBtb3VzZSBhZnRlciBzY2FsaW5nXG4gICAgICAgICAgICAgICAgY29uc3QgaGVscGVyUmVjdCA9IGhlbHBlci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgICAgICBoZWxwZXIuc3R5bGUubGVmdCA9IGhlbHBlclJlY3QueCArICh0aGlzLmRyYWdUcmFuc2Zvcm0ueFNjYWxlIC0gMSkgKiAoZXZlbnQuY2xpZW50WCAtIGhlbHBlclJlY3QueCkgLyB0aGlzLmRyYWdUcmFuc2Zvcm0ueFNjYWxlICsgJ3B4JztcbiAgICAgICAgICAgICAgICBoZWxwZXIuc3R5bGUudG9wID0gaGVscGVyUmVjdC55ICsgKHRoaXMuZHJhZ1RyYW5zZm9ybS55U2NhbGUgLSAxKSAqIChldmVudC5jbGllbnRZIC0gaGVscGVyUmVjdC55KSAvIHRoaXMuZHJhZ1RyYW5zZm9ybS55U2NhbGUgKyAncHgnO1xuICAgICAgICAgICAgICAgIGhlbHBlci5zdHlsZS50cmFuc2Zvcm1PcmlnaW4gPSBgMHB4IDBweGA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcGFyZW50ID0gdGhpcy5lbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIGxldCB7IHRvcCwgbGVmdCB9ID0gaGVscGVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgbGVmdCAtPSBwYXJlbnQubGVmdDtcbiAgICAgICAgICAgIHRvcCAtPSBwYXJlbnQudG9wO1xuICAgICAgICAgICAgbGV0IHVpID0ge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgICAgICAgIHRvcDogdG9wICogdGhpcy5kcmFnVHJhbnNmb3JtLnhTY2FsZSxcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogbGVmdCAqIHRoaXMuZHJhZ1RyYW5zZm9ybS55U2NhbGVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKG5vZGUuX3RlbXBvcmFyeVJlbW92ZWQpIHtcbiAgICAgICAgICAgICAgICBub2RlLnggPSBNYXRoLm1heCgwLCBNYXRoLnJvdW5kKGxlZnQgLyBjZWxsV2lkdGgpKTtcbiAgICAgICAgICAgICAgICBub2RlLnkgPSBNYXRoLm1heCgwLCBNYXRoLnJvdW5kKHRvcCAvIGNlbGxIZWlnaHQpKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgbm9kZS5hdXRvUG9zaXRpb247XG4gICAgICAgICAgICAgICAgdGhpcy5lbmdpbmUubm9kZUJvdW5kRml4KG5vZGUpO1xuICAgICAgICAgICAgICAgIC8vIGRvbid0IGFjY2VwdCAqaW5pdGlhbCogbG9jYXRpb24gaWYgZG9lc24ndCBmaXQgIzE0MTkgKGxvY2tlZCBkcm9wIHJlZ2lvbiwgb3IgY2FuJ3QgZ3JvdyksIGJ1dCBtYXliZSB0cnkgaWYgaXQgd2lsbCBnbyBzb21ld2hlcmVcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuZW5naW5lLndpbGxJdEZpdChub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlLmF1dG9Qb3NpdGlvbiA9IHRydWU7IC8vIGlnbm9yZSB4LHkgYW5kIHRyeSBmb3IgYW55IHNsb3QuLi5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmVuZ2luZS53aWxsSXRGaXQobm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRkLm9mZihlbCwgJ2RyYWcnKTsgLy8gc3RvcCBjYWxsaW5nIHVzXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47IC8vIGZ1bGwgZ3JpZCBvciBjYW4ndCBncm93XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vZGUuX3dpbGxGaXRQb3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHVzZSB0aGUgYXV0byBwb3NpdGlvbiBpbnN0ZWFkICMxNjg3XG4gICAgICAgICAgICAgICAgICAgICAgICBVdGlscy5jb3B5UG9zKG5vZGUsIG5vZGUuX3dpbGxGaXRQb3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG5vZGUuX3dpbGxGaXRQb3M7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gcmUtdXNlIHRoZSBleGlzdGluZyBub2RlIGRyYWdnaW5nIG1ldGhvZFxuICAgICAgICAgICAgICAgIHRoaXMuX29uU3RhcnRNb3ZpbmcoaGVscGVyLCBldmVudCwgdWksIG5vZGUsIGNlbGxXaWR0aCwgY2VsbEhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyByZS11c2UgdGhlIGV4aXN0aW5nIG5vZGUgZHJhZ2dpbmcgdGhhdCBkb2VzIHNvIG11Y2ggb2YgdGhlIGNvbGxpc2lvbiBkZXRlY3Rpb25cbiAgICAgICAgICAgICAgICB0aGlzLl9kcmFnT3JSZXNpemUoaGVscGVyLCBldmVudCwgdWksIG5vZGUsIGNlbGxXaWR0aCwgY2VsbEhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGRkLmRyb3BwYWJsZSh0aGlzLmVsLCB7XG4gICAgICAgICAgICBhY2NlcHQ6IChlbCkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBub2RlID0gZWwuZ3JpZHN0YWNrTm9kZSB8fCB0aGlzLl9yZWFkQXR0cihlbCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIC8vIHNldCBhY2NlcHQgZHJvcCB0byB0cnVlIG9uIG91cnNlbGYgKHdoaWNoIHdlIGlnbm9yZSkgc28gd2UgZG9uJ3QgZ2V0IFwiY2FuJ3QgZHJvcFwiIGljb24gaW4gSFRNTDUgbW9kZSB3aGlsZSBtb3ZpbmdcbiAgICAgICAgICAgICAgICBpZiAobm9kZT8uZ3JpZCA9PT0gdGhpcylcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLm9wdHMuYWNjZXB0V2lkZ2V0cylcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIC8vIGNoZWNrIGZvciBhY2NlcHQgbWV0aG9kIG9yIGNsYXNzIG1hdGNoaW5nXG4gICAgICAgICAgICAgICAgbGV0IGNhbkFjY2VwdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm9wdHMuYWNjZXB0V2lkZ2V0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBjYW5BY2NlcHQgPSB0aGlzLm9wdHMuYWNjZXB0V2lkZ2V0cyhlbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsZXQgc2VsZWN0b3IgPSAodGhpcy5vcHRzLmFjY2VwdFdpZGdldHMgPT09IHRydWUgPyAnLmdyaWQtc3RhY2staXRlbScgOiB0aGlzLm9wdHMuYWNjZXB0V2lkZ2V0cyk7XG4gICAgICAgICAgICAgICAgICAgIGNhbkFjY2VwdCA9IGVsLm1hdGNoZXMoc2VsZWN0b3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBmaW5hbGx5IGNoZWNrIHRvIG1ha2Ugc3VyZSB3ZSBhY3R1YWxseSBoYXZlIHNwYWNlIGxlZnQgIzE1NzEgIzI2MzNcbiAgICAgICAgICAgICAgICBpZiAoY2FuQWNjZXB0ICYmIG5vZGUgJiYgdGhpcy5vcHRzLm1heFJvdykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgbiA9IHsgdzogbm9kZS53LCBoOiBub2RlLmgsIG1pblc6IG5vZGUubWluVywgbWluSDogbm9kZS5taW5IIH07IC8vIG9ubHkgd2lkdGgvaGVpZ2h0IG1hdHRlcnMgYW5kIGF1dG9Qb3NpdGlvblxuICAgICAgICAgICAgICAgICAgICBjYW5BY2NlcHQgPSB0aGlzLmVuZ2luZS53aWxsSXRGaXQobik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBjYW5BY2NlcHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIGVudGVyaW5nIG91ciBncmlkIGFyZWFcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgLm9uKHRoaXMuZWwsICdkcm9wb3ZlcicsIChldmVudCwgZWwsIGhlbHBlcikgPT4ge1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coYG92ZXIgJHt0aGlzLmVsLmdyaWRzdGFjay5vcHRzLmlkfSAke2NvdW50Kyt9YCk7IC8vIFRFU1RcbiAgICAgICAgICAgIGxldCBub2RlID0gZWwuZ3JpZHN0YWNrTm9kZTtcbiAgICAgICAgICAgIC8vIGlnbm9yZSBkcm9wIGVudGVyIG9uIG91cnNlbGYgKHVubGVzcyB3ZSB0ZW1wb3JhcmlseSByZW1vdmVkKSB3aGljaCBoYXBwZW5zIG9uIGEgc2ltcGxlIGRyYWcgb2Ygb3VyIGl0ZW1cbiAgICAgICAgICAgIGlmIChub2RlPy5ncmlkID09PSB0aGlzICYmICFub2RlLl90ZW1wb3JhcnlSZW1vdmVkKSB7XG4gICAgICAgICAgICAgICAgLy8gZGVsZXRlIG5vZGUuX2FkZGVkOyAvLyByZXNldCB0aGlzIHRvIHRyYWNrIHBsYWNlaG9sZGVyIGFnYWluIGluIGNhc2Ugd2Ugd2VyZSBvdmVyIG90aGVyIGdyaWQgIzE0ODQgKGRyb3BvdXQgZG9lc24ndCBhbHdheXMgY2xlYXIpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBwcmV2ZW50IHBhcmVudCBmcm9tIHJlY2VpdmluZyBtc2cgKHdoaWNoIG1heSBiZSBhIGdyaWQgYXMgd2VsbClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGZpeCAjMTU3OCB3aGVuIGRyYWdnaW5nIGZhc3QsIHdlIG1heSBub3QgZ2V0IGEgbGVhdmUgb24gdGhlIHByZXZpb3VzIGdyaWQgc28gZm9yY2Ugb25lIG5vd1xuICAgICAgICAgICAgaWYgKG5vZGU/LmdyaWQgJiYgbm9kZS5ncmlkICE9PSB0aGlzICYmICFub2RlLl90ZW1wb3JhcnlSZW1vdmVkKSB7XG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ2Ryb3BvdmVyIHdpdGhvdXQgbGVhdmUnKTsgLy8gVEVTVFxuICAgICAgICAgICAgICAgIGxldCBvdGhlckdyaWQgPSBub2RlLmdyaWQ7XG4gICAgICAgICAgICAgICAgb3RoZXJHcmlkLl9sZWF2ZShlbCwgaGVscGVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGNhY2hlIGNlbGwgZGltZW5zaW9ucyAod2hpY2ggZG9uJ3QgY2hhbmdlKSwgcG9zaXRpb24gY2FuIGFuaW1hdGUgaWYgd2UgcmVtb3ZlZCBhbiBpdGVtIGluIG90aGVyR3JpZCB0aGF0IGFmZmVjdHMgdXMuLi5cbiAgICAgICAgICAgIGNlbGxXaWR0aCA9IHRoaXMuY2VsbFdpZHRoKCk7XG4gICAgICAgICAgICBjZWxsSGVpZ2h0ID0gdGhpcy5nZXRDZWxsSGVpZ2h0KHRydWUpO1xuICAgICAgICAgICAgLy8gbG9hZCBhbnkgZWxlbWVudCBhdHRyaWJ1dGVzIGlmIHdlIGRvbid0IGhhdmUgYSBub2RlXG4gICAgICAgICAgICBpZiAoIW5vZGUpIHtcbiAgICAgICAgICAgICAgICBub2RlID0gdGhpcy5fcmVhZEF0dHIoZWwsIGZhbHNlKTsgLy8gZG9uJ3Qgd2lwZSBleHRlcm5hbCAoZS5nLiBkcmFnIHRvb2xiYXIpIGF0dHIgIzIzNTRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbm9kZS5ncmlkKSB7XG4gICAgICAgICAgICAgICAgbm9kZS5faXNFeHRlcm5hbCA9IHRydWU7XG4gICAgICAgICAgICAgICAgZWwuZ3JpZHN0YWNrTm9kZSA9IG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBjYWxjdWxhdGUgdGhlIGdyaWQgc2l6ZSBiYXNlZCBvbiBlbGVtZW50IG91dGVyIHNpemVcbiAgICAgICAgICAgIGhlbHBlciA9IGhlbHBlciB8fCBlbDtcbiAgICAgICAgICAgIGxldCB3ID0gbm9kZS53IHx8IE1hdGgucm91bmQoaGVscGVyLm9mZnNldFdpZHRoIC8gY2VsbFdpZHRoKSB8fCAxO1xuICAgICAgICAgICAgbGV0IGggPSBub2RlLmggfHwgTWF0aC5yb3VuZChoZWxwZXIub2Zmc2V0SGVpZ2h0IC8gY2VsbEhlaWdodCkgfHwgMTtcbiAgICAgICAgICAgIC8vIGlmIHRoZSBpdGVtIGNhbWUgZnJvbSBhbm90aGVyIGdyaWQsIG1ha2UgYSBjb3B5IGFuZCBzYXZlIHRoZSBvcmlnaW5hbCBpbmZvIGluIGNhc2Ugd2UgZ28gYmFjayB0aGVyZVxuICAgICAgICAgICAgaWYgKG5vZGUuZ3JpZCAmJiBub2RlLmdyaWQgIT09IHRoaXMpIHtcbiAgICAgICAgICAgICAgICAvLyBjb3B5IHRoZSBub2RlIG9yaWdpbmFsIHZhbHVlcyAobWluL21heC9pZC9ldGMuLi4pIGJ1dCBvdmVycmlkZSB3aWR0aC9oZWlnaHQvb3RoZXIgZmxhZ3Mgd2hpY2ggYXJlIHRoaXMgZ3JpZCBzcGVjaWZpY1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdkcm9wb3ZlciBjbG9uaW5nIG5vZGUnKTsgLy8gVEVTVFxuICAgICAgICAgICAgICAgIGlmICghZWwuX2dyaWRzdGFja05vZGVPcmlnKVxuICAgICAgICAgICAgICAgICAgICBlbC5fZ3JpZHN0YWNrTm9kZU9yaWcgPSBub2RlOyAvLyBzaG91bGRuJ3QgaGF2ZSBtdWx0aXBsZSBuZXN0ZWQhXG4gICAgICAgICAgICAgICAgZWwuZ3JpZHN0YWNrTm9kZSA9IG5vZGUgPSB7IC4uLm5vZGUsIHcsIGgsIGdyaWQ6IHRoaXMgfTtcbiAgICAgICAgICAgICAgICBkZWxldGUgbm9kZS54O1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBub2RlLnk7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmdpbmUuY2xlYW51cE5vZGUobm9kZSlcbiAgICAgICAgICAgICAgICAgICAgLm5vZGVCb3VuZEZpeChub2RlKTtcbiAgICAgICAgICAgICAgICAvLyByZXN0b3JlIHNvbWUgaW50ZXJuYWwgZmllbGRzIHdlIG5lZWQgYWZ0ZXIgY2xlYXJpbmcgdGhlbSBhbGxcbiAgICAgICAgICAgICAgICBub2RlLl9pbml0REQgPVxuICAgICAgICAgICAgICAgICAgICBub2RlLl9pc0V4dGVybmFsID0gLy8gRE9NIG5lZWRzIHRvIGJlIHJlLXBhcmVudGVkIG9uIGEgZHJvcFxuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5fdGVtcG9yYXJ5UmVtb3ZlZCA9IHRydWU7IC8vIHNvIGl0IGNhbiBiZSBpbnNlcnRlZCBvbkRyYWcgYmVsb3dcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG5vZGUudyA9IHc7XG4gICAgICAgICAgICAgICAgbm9kZS5oID0gaDtcbiAgICAgICAgICAgICAgICBub2RlLl90ZW1wb3JhcnlSZW1vdmVkID0gdHJ1ZTsgLy8gc28gd2UgY2FuIGluc2VydCBpdFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gY2xlYXIgYW55IG1hcmtlZCBmb3IgY29tcGxldGUgcmVtb3ZhbCAoTm90ZTogZG9uJ3QgY2hlY2sgX2lzQWJvdXRUb1JlbW92ZSBhcyB0aGF0IGlzIGNsZWFyZWQgYWJvdmUgLSBqdXN0IGRvIGl0KVxuICAgICAgICAgICAgR3JpZFN0YWNrLl9pdGVtUmVtb3Zpbmcobm9kZS5lbCwgZmFsc2UpO1xuICAgICAgICAgICAgZGQub24oZWwsICdkcmFnJywgb25EcmFnKTtcbiAgICAgICAgICAgIC8vIG1ha2Ugc3VyZSB0aGlzIGlzIGNhbGxlZCBhdCBsZWFzdCBvbmNlIHdoZW4gZ29pbmcgZmFzdCAjMTU3OFxuICAgICAgICAgICAgb25EcmFnKGV2ZW50LCBlbCwgaGVscGVyKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTsgLy8gcHJldmVudCBwYXJlbnQgZnJvbSByZWNlaXZpbmcgbXNnICh3aGljaCBtYXkgYmUgYSBncmlkIGFzIHdlbGwpXG4gICAgICAgIH0pXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIExlYXZpbmcgb3VyIGdyaWQgYXJlYS4uLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICAub24odGhpcy5lbCwgJ2Ryb3BvdXQnLCAoZXZlbnQsIGVsLCBoZWxwZXIpID0+IHtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGBvdXQgJHt0aGlzLmVsLmdyaWRzdGFjay5vcHRzLmlkfSAke2NvdW50Kyt9YCk7IC8vIFRFU1RcbiAgICAgICAgICAgIGxldCBub2RlID0gZWwuZ3JpZHN0YWNrTm9kZTtcbiAgICAgICAgICAgIGlmICghbm9kZSlcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAvLyBmaXggIzE1Nzggd2hlbiBkcmFnZ2luZyBmYXN0LCB3ZSBtaWdodCBnZXQgbGVhdmUgYWZ0ZXIgb3RoZXIgZ3JpZCBnZXRzIGVudGVyICh3aGljaCBjYWxscyB1cyB0byBjbGVhbilcbiAgICAgICAgICAgIC8vIHNvIHNraXAgdGhpcyBvbmUgaWYgd2UncmUgbm90IHRoZSBhY3RpdmUgZ3JpZCByZWFsbHkuLlxuICAgICAgICAgICAgaWYgKCFub2RlLmdyaWQgfHwgbm9kZS5ncmlkID09PSB0aGlzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fbGVhdmUoZWwsIGhlbHBlcik7XG4gICAgICAgICAgICAgICAgLy8gaWYgd2Ugd2VyZSBjcmVhdGVkIGFzIHRlbXBvcmFyeSBuZXN0ZWQgZ3JpZCwgZ28gYmFjayB0byBiZWZvcmUgc3RhdGVcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5faXNUZW1wKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlQXNTdWJHcmlkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTsgLy8gcHJldmVudCBwYXJlbnQgZnJvbSByZWNlaXZpbmcgbXNnICh3aGljaCBtYXkgYmUgZ3JpZCBhcyB3ZWxsKVxuICAgICAgICB9KVxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBlbmQgLSByZWxlYXNpbmcgdGhlIG1vdXNlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIC5vbih0aGlzLmVsLCAnZHJvcCcsIChldmVudCwgZWwsIGhlbHBlcikgPT4ge1xuICAgICAgICAgICAgbGV0IG5vZGUgPSBlbC5ncmlkc3RhY2tOb2RlO1xuICAgICAgICAgICAgLy8gaWdub3JlIGRyb3Agb24gb3Vyc2VsZiBmcm9tIG91cnNlbGYgdGhhdCBkaWRuJ3QgY29tZSBmcm9tIHRoZSBvdXRzaWRlIC0gZHJhZ2VuZCB3aWxsIGhhbmRsZSB0aGUgc2ltcGxlIG1vdmUgaW5zdGVhZFxuICAgICAgICAgICAgaWYgKG5vZGU/LmdyaWQgPT09IHRoaXMgJiYgIW5vZGUuX2lzRXh0ZXJuYWwpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgY29uc3Qgd2FzQWRkZWQgPSAhIXRoaXMucGxhY2Vob2xkZXIucGFyZW50RWxlbWVudDsgLy8gc2tpcCBpdGVtcyBub3QgYWN0dWFsbHkgYWRkZWQgdG8gdXMgYmVjYXVzZSBvZiBjb25zdHJhaW5zLCBidXQgZG8gY2xlYW51cCAjMTQxOVxuICAgICAgICAgICAgdGhpcy5wbGFjZWhvbGRlci5yZW1vdmUoKTtcbiAgICAgICAgICAgIC8vIGRpc2FibGUgYW5pbWF0aW9uIHdoZW4gcmVwbGFjaW5nIGEgcGxhY2Vob2xkZXIgKGFscmVhZHkgcG9zaXRpb25lZCkgd2l0aCBhY3R1YWwgY29udGVudFxuICAgICAgICAgICAgY29uc3Qgbm9BbmltID0gd2FzQWRkZWQgJiYgdGhpcy5vcHRzLmFuaW1hdGU7XG4gICAgICAgICAgICBpZiAobm9BbmltKVxuICAgICAgICAgICAgICAgIHRoaXMuc2V0QW5pbWF0aW9uKGZhbHNlKTtcbiAgICAgICAgICAgIC8vIG5vdGlmeSBwcmV2aW91cyBncmlkIG9mIHJlbW92YWxcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdkcm9wIGRlbGV0ZSBfZ3JpZHN0YWNrTm9kZU9yaWcnKSAvLyBURVNUXG4gICAgICAgICAgICBsZXQgb3JpZ05vZGUgPSBlbC5fZ3JpZHN0YWNrTm9kZU9yaWc7XG4gICAgICAgICAgICBkZWxldGUgZWwuX2dyaWRzdGFja05vZGVPcmlnO1xuICAgICAgICAgICAgaWYgKHdhc0FkZGVkICYmIG9yaWdOb2RlPy5ncmlkICYmIG9yaWdOb2RlLmdyaWQgIT09IHRoaXMpIHtcbiAgICAgICAgICAgICAgICBsZXQgb0dyaWQgPSBvcmlnTm9kZS5ncmlkO1xuICAgICAgICAgICAgICAgIG9HcmlkLmVuZ2luZS5yZW1vdmVOb2RlRnJvbUxheW91dENhY2hlKG9yaWdOb2RlKTtcbiAgICAgICAgICAgICAgICBvR3JpZC5lbmdpbmUucmVtb3ZlZE5vZGVzLnB1c2gob3JpZ05vZGUpO1xuICAgICAgICAgICAgICAgIG9HcmlkLl90cmlnZ2VyUmVtb3ZlRXZlbnQoKS5fdHJpZ2dlckNoYW5nZUV2ZW50KCk7XG4gICAgICAgICAgICAgICAgLy8gaWYgaXQncyBhbiBlbXB0eSBzdWItZ3JpZCB0aGF0IGdvdCBhdXRvLWNyZWF0ZWQsIG51a2UgaXRcbiAgICAgICAgICAgICAgICBpZiAob0dyaWQucGFyZW50R3JpZEl0ZW0gJiYgIW9HcmlkLmVuZ2luZS5ub2Rlcy5sZW5ndGggJiYgb0dyaWQub3B0cy5zdWJHcmlkRHluYW1pYykge1xuICAgICAgICAgICAgICAgICAgICBvR3JpZC5yZW1vdmVBc1N1YkdyaWQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIW5vZGUpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgLy8gdXNlIGV4aXN0aW5nIHBsYWNlaG9sZGVyIG5vZGUgYXMgaXQncyBhbHJlYWR5IGluIG91ciBsaXN0IHdpdGggZHJvcCBsb2NhdGlvblxuICAgICAgICAgICAgaWYgKHdhc0FkZGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmdpbmUuY2xlYW51cE5vZGUobm9kZSk7IC8vIHJlbW92ZXMgYWxsIGludGVybmFsIF94eXogdmFsdWVzXG4gICAgICAgICAgICAgICAgbm9kZS5ncmlkID0gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBub2RlLmdyaWQuX2lzVGVtcDtcbiAgICAgICAgICAgIGRkLm9mZihlbCwgJ2RyYWcnKTtcbiAgICAgICAgICAgIC8vIGlmIHdlIG1hZGUgYSBjb3B5ICgnaGVscGVyJyB3aGljaCBpcyB0ZW1wKSBvZiB0aGUgb3JpZ2luYWwgbm9kZSB0aGVuIGluc2VydCBhIGNvcHksIGVsc2Ugd2UgbW92ZSB0aGUgb3JpZ2luYWwgbm9kZSAoIzExMDIpXG4gICAgICAgICAgICAvLyBhcyB0aGUgaGVscGVyIHdpbGwgYmUgbnVrZWQgYnkganF1ZXJ5LXVpIG90aGVyd2lzZS4gVE9ETzogdXBkYXRlIG9sZCBjb2RlIHBhdGhcbiAgICAgICAgICAgIGlmIChoZWxwZXIgIT09IGVsKSB7XG4gICAgICAgICAgICAgICAgaGVscGVyLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIGVsLmdyaWRzdGFja05vZGUgPSBvcmlnTm9kZTsgLy8gb3JpZ2luYWwgaXRlbSAobGVmdCBiZWhpbmQpIGlzIHJlLXN0b3JlZCB0byBwcmUgZHJhZ2dpbmcgYXMgdGhlIG5vZGUgbm93IGhhcyBkcm9wIGluZm9cbiAgICAgICAgICAgICAgICBpZiAod2FzQWRkZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZWwgPSBlbC5jbG9uZU5vZGUodHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZWwucmVtb3ZlKCk7IC8vIHJlZHVjZSBmbGlja2VyIGFzIHdlIGNoYW5nZSBkZXB0aCBoZXJlLCBhbmQgc2l6ZSBmdXJ0aGVyIGRvd25cbiAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVERChlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXdhc0FkZGVkKVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIGVsLmdyaWRzdGFja05vZGUgPSBub2RlO1xuICAgICAgICAgICAgbm9kZS5lbCA9IGVsO1xuICAgICAgICAgICAgbGV0IHN1YkdyaWQgPSBub2RlLnN1YkdyaWQ/LmVsPy5ncmlkc3RhY2s7IC8vIHNldCB3aGVuIGFjdHVhbCBzdWItZ3JpZCBwcmVzZW50XG4gICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICBVdGlscy5jb3B5UG9zKG5vZGUsIHRoaXMuX3JlYWRBdHRyKHRoaXMucGxhY2Vob2xkZXIpKTsgLy8gcGxhY2Vob2xkZXIgdmFsdWVzIGFzIG1vdmluZyBWRVJZIGZhc3QgY2FuIHRocm93IHRoaW5ncyBvZmYgIzE1NzhcbiAgICAgICAgICAgIFV0aWxzLnJlbW92ZVBvc2l0aW9uaW5nU3R5bGVzKGVsKTsgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgdGhpcy5lbC5hcHBlbmRDaGlsZChlbCk7IC8vIEB0cy1pZ25vcmUgLy8gVE9ETzogbm93IHdvdWxkIGJlIGlkZWFsIHRpbWUgdG8gX3JlbW92ZUhlbHBlclN0eWxlKCkgb3ZlcnJpZGluZyBmbG9hdGluZyBzdHlsZXMgKG5hdGl2ZSBvbmx5KVxuICAgICAgICAgICAgdGhpcy5fcHJlcGFyZUVsZW1lbnQoZWwsIHRydWUsIG5vZGUpO1xuICAgICAgICAgICAgaWYgKHN1YkdyaWQpIHtcbiAgICAgICAgICAgICAgICBzdWJHcmlkLnBhcmVudEdyaWRJdGVtID0gbm9kZTtcbiAgICAgICAgICAgICAgICBpZiAoIXN1YkdyaWQub3B0cy5zdHlsZUluSGVhZClcbiAgICAgICAgICAgICAgICAgICAgc3ViR3JpZC5fdXBkYXRlU3R5bGVzKHRydWUpOyAvLyByZS1jcmVhdGUgc3ViLWdyaWQgc3R5bGVzIG5vdyB0aGF0IHdlJ3ZlIG1vdmVkXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVDb250YWluZXJIZWlnaHQoKTtcbiAgICAgICAgICAgIHRoaXMuZW5naW5lLmFkZGVkTm9kZXMucHVzaChub2RlKTsgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckFkZEV2ZW50KCk7IC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJDaGFuZ2VFdmVudCgpO1xuICAgICAgICAgICAgdGhpcy5lbmdpbmUuZW5kVXBkYXRlKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5fZ3NFdmVudEhhbmRsZXJbJ2Ryb3BwZWQnXSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2dzRXZlbnRIYW5kbGVyWydkcm9wcGVkJ10oeyAuLi5ldmVudCwgdHlwZTogJ2Ryb3BwZWQnIH0sIG9yaWdOb2RlICYmIG9yaWdOb2RlLmdyaWQgPyBvcmlnTm9kZSA6IHVuZGVmaW5lZCwgbm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBkZWxheSBhZGRpbmcgYW5pbWF0aW9uIGJhY2ssIGJ1dCBjaGVjayB0byBtYWtlIHN1cmUgZ3JpZCAob3B0KSBpcyBzdGlsbCBhcm91bmRcbiAgICAgICAgICAgIGlmIChub0FuaW0pXG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7IGlmICh0aGlzLm9wdHMpXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0QW5pbWF0aW9uKHRoaXMub3B0cy5hbmltYXRlKTsgfSk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7IC8vIHByZXZlbnQgcGFyZW50IGZyb20gcmVjZWl2aW5nIG1zZyAod2hpY2ggbWF5IGJlIGdyaWQgYXMgd2VsbClcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsIG1hcmsgaXRlbSBmb3IgcmVtb3ZhbCAqL1xuICAgIHN0YXRpYyBfaXRlbVJlbW92aW5nKGVsLCByZW1vdmUpIHtcbiAgICAgICAgY29uc3Qgbm9kZSA9IGVsID8gZWwuZ3JpZHN0YWNrTm9kZSA6IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKCFub2RlPy5ncmlkIHx8IGVsLmNsYXNzTGlzdC5jb250YWlucyhub2RlLmdyaWQub3B0cy5yZW1vdmFibGVPcHRpb25zLmRlY2xpbmUpKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICByZW1vdmUgPyBub2RlLl9pc0Fib3V0VG9SZW1vdmUgPSB0cnVlIDogZGVsZXRlIG5vZGUuX2lzQWJvdXRUb1JlbW92ZTtcbiAgICAgICAgcmVtb3ZlID8gZWwuY2xhc3NMaXN0LmFkZCgnZ3JpZC1zdGFjay1pdGVtLXJlbW92aW5nJykgOiBlbC5jbGFzc0xpc3QucmVtb3ZlKCdncmlkLXN0YWNrLWl0ZW0tcmVtb3ZpbmcnKTtcbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCBjYWxsZWQgdG8gc2V0dXAgYSB0cmFzaCBkcm9wIHpvbmUgaWYgdGhlIHVzZXIgc3BlY2lmaWVzIGl0ICovXG4gICAgX3NldHVwUmVtb3ZlRHJvcCgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm9wdHMucmVtb3ZhYmxlICE9PSAnc3RyaW5nJylcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICBsZXQgdHJhc2hFbCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5vcHRzLnJlbW92YWJsZSk7XG4gICAgICAgIGlmICghdHJhc2hFbClcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAvLyBvbmx5IHJlZ2lzdGVyIE9ORSBzdGF0aWMgZHJvcC1vdmVyL2Ryb3BvdXQgY2FsbGJhY2sgZm9yIHRoZSAndHJhc2gnLCBhbmQgaXQgd2lsbFxuICAgICAgICAvLyB1cGRhdGUgdGhlIHBhc3NlZCBpbiBpdGVtIGFuZCBwYXJlbnQgZ3JpZCBiZWNhdXNlIHRoZSAnLnRyYXNoJyBpcyBhIHNoYXJlZCByZXNvdXJjZSBhbnl3YXksXG4gICAgICAgIC8vIGFuZCBOYXRpdmUgREQgb25seSBoYXMgMSBldmVudCBDQiAoaGF2aW5nIGEgbGlzdCBhbmQgdGVjaG5pY2FsbHkgYSBwZXIgZ3JpZCByZW1vdmFibGVPcHRpb25zIGNvbXBsaWNhdGVzIHRoaW5ncyBncmVhdGx5KVxuICAgICAgICBpZiAoIXRoaXMub3B0cy5zdGF0aWNHcmlkICYmICFkZC5pc0Ryb3BwYWJsZSh0cmFzaEVsKSkge1xuICAgICAgICAgICAgZGQuZHJvcHBhYmxlKHRyYXNoRWwsIHRoaXMub3B0cy5yZW1vdmFibGVPcHRpb25zKVxuICAgICAgICAgICAgICAgIC5vbih0cmFzaEVsLCAnZHJvcG92ZXInLCAoZXZlbnQsIGVsKSA9PiBHcmlkU3RhY2suX2l0ZW1SZW1vdmluZyhlbCwgdHJ1ZSkpXG4gICAgICAgICAgICAgICAgLm9uKHRyYXNoRWwsICdkcm9wb3V0JywgKGV2ZW50LCBlbCkgPT4gR3JpZFN0YWNrLl9pdGVtUmVtb3ZpbmcoZWwsIGZhbHNlKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgcHJlcGFyZXMgdGhlIGVsZW1lbnQgZm9yIGRyYWcmZHJvcCAqL1xuICAgIF9wcmVwYXJlRHJhZ0Ryb3BCeU5vZGUobm9kZSkge1xuICAgICAgICBsZXQgZWwgPSBub2RlLmVsO1xuICAgICAgICBjb25zdCBub01vdmUgPSBub2RlLm5vTW92ZSB8fCB0aGlzLm9wdHMuZGlzYWJsZURyYWc7XG4gICAgICAgIGNvbnN0IG5vUmVzaXplID0gbm9kZS5ub1Jlc2l6ZSB8fCB0aGlzLm9wdHMuZGlzYWJsZVJlc2l6ZTtcbiAgICAgICAgLy8gY2hlY2sgZm9yIGRpc2FibGVkIGdyaWQgZmlyc3RcbiAgICAgICAgaWYgKHRoaXMub3B0cy5zdGF0aWNHcmlkIHx8IChub01vdmUgJiYgbm9SZXNpemUpKSB7XG4gICAgICAgICAgICBpZiAobm9kZS5faW5pdEREKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlREQoZWwpOyAvLyBudWtlcyBldmVyeXRoaW5nIGluc3RlYWQgb2YganVzdCBkaXNhYmxlLCB3aWxsIGFkZCBzb21lIHN0eWxlcyBiYWNrIG5leHRcbiAgICAgICAgICAgICAgICBkZWxldGUgbm9kZS5faW5pdEREO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWwuY2xhc3NMaXN0LmFkZCgndWktZHJhZ2dhYmxlLWRpc2FibGVkJywgJ3VpLXJlc2l6YWJsZS1kaXNhYmxlZCcpOyAvLyBhZGQgc3R5bGVzIG9uZSBtaWdodCBkZXBlbmQgb24gIzE0MzVcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGlmICghbm9kZS5faW5pdEREKSB7XG4gICAgICAgICAgICAvLyB2YXJpYWJsZXMgdXNlZC9jYXNoZWQgYmV0d2VlbiB0aGUgMyBzdGFydC9tb3ZlL2VuZCBtZXRob2RzLCBpbiBhZGRpdGlvbiB0byBub2RlIHBhc3NlZCBhYm92ZVxuICAgICAgICAgICAgbGV0IGNlbGxXaWR0aDtcbiAgICAgICAgICAgIGxldCBjZWxsSGVpZ2h0O1xuICAgICAgICAgICAgLyoqIGNhbGxlZCB3aGVuIGl0ZW0gc3RhcnRzIG1vdmluZy9yZXNpemluZyAqL1xuICAgICAgICAgICAgbGV0IG9uU3RhcnRNb3ZpbmcgPSAoZXZlbnQsIHVpKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gdHJpZ2dlciBhbnkgJ2RyYWdzdGFydCcgLyAncmVzaXplc3RhcnQnIG1hbnVhbGx5XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2dzRXZlbnRIYW5kbGVyW2V2ZW50LnR5cGVdKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2dzRXZlbnRIYW5kbGVyW2V2ZW50LnR5cGVdKGV2ZW50LCBldmVudC50YXJnZXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjZWxsV2lkdGggPSB0aGlzLmNlbGxXaWR0aCgpO1xuICAgICAgICAgICAgICAgIGNlbGxIZWlnaHQgPSB0aGlzLmdldENlbGxIZWlnaHQodHJ1ZSk7IC8vIGZvcmNlIHBpeGVscyBmb3IgY2FsY3VsYXRpb25zXG4gICAgICAgICAgICAgICAgdGhpcy5fb25TdGFydE1vdmluZyhlbCwgZXZlbnQsIHVpLCBub2RlLCBjZWxsV2lkdGgsIGNlbGxIZWlnaHQpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIC8qKiBjYWxsZWQgd2hlbiBpdGVtIGlzIGJlaW5nIGRyYWdnZWQvcmVzaXplZCAqL1xuICAgICAgICAgICAgbGV0IGRyYWdPclJlc2l6ZSA9IChldmVudCwgdWkpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9kcmFnT3JSZXNpemUoZWwsIGV2ZW50LCB1aSwgbm9kZSwgY2VsbFdpZHRoLCBjZWxsSGVpZ2h0KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvKiogY2FsbGVkIHdoZW4gdGhlIGl0ZW0gc3RvcHMgbW92aW5nL3Jlc2l6aW5nICovXG4gICAgICAgICAgICBsZXQgb25FbmRNb3ZpbmcgPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnBsYWNlaG9sZGVyLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBub2RlLl9tb3Zpbmc7XG4gICAgICAgICAgICAgICAgZGVsZXRlIG5vZGUuX2V2ZW50O1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBub2RlLl9sYXN0VHJpZWQ7XG4gICAgICAgICAgICAgICAgY29uc3Qgd2lkdGhDaGFuZ2VkID0gbm9kZS53ICE9PSBub2RlLl9vcmlnLnc7XG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlIGl0ZW0gaGFzIG1vdmVkIHRvIGFub3RoZXIgZ3JpZCwgd2UncmUgZG9uZSBoZXJlXG4gICAgICAgICAgICAgICAgbGV0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcbiAgICAgICAgICAgICAgICBpZiAoIXRhcmdldC5ncmlkc3RhY2tOb2RlIHx8IHRhcmdldC5ncmlkc3RhY2tOb2RlLmdyaWQgIT09IHRoaXMpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICBub2RlLmVsID0gdGFyZ2V0O1xuICAgICAgICAgICAgICAgIGlmIChub2RlLl9pc0Fib3V0VG9SZW1vdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGdyaWQgPSBlbC5ncmlkc3RhY2tOb2RlLmdyaWQ7XG4gICAgICAgICAgICAgICAgICAgIGlmIChncmlkLl9nc0V2ZW50SGFuZGxlcltldmVudC50eXBlXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ3JpZC5fZ3NFdmVudEhhbmRsZXJbZXZlbnQudHlwZV0oZXZlbnQsIHRhcmdldCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZ3JpZC5lbmdpbmUubm9kZXMucHVzaChub2RlKTsgLy8gdGVtcCBhZGQgaXQgYmFjayBzbyB3ZSBjYW4gcHJvcGVyIHJlbW92ZSBpdCBuZXh0XG4gICAgICAgICAgICAgICAgICAgIGdyaWQucmVtb3ZlV2lkZ2V0KGVsLCB0cnVlLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIFV0aWxzLnJlbW92ZVBvc2l0aW9uaW5nU3R5bGVzKHRhcmdldCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChub2RlLl90ZW1wb3JhcnlSZW1vdmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBnb3QgcmVtb3ZlZCAtIHJlc3RvcmUgaXRlbSBiYWNrIHRvIGJlZm9yZSBkcmFnZ2luZyBwb3NpdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgVXRpbHMuY29weVBvcyhub2RlLCBub2RlLl9vcmlnKTsgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fd3JpdGVQb3NBdHRyKHRhcmdldCwgbm9kZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVuZ2luZS5hZGROb2RlKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbW92ZSB0byBuZXcgcGxhY2Vob2xkZXIgbG9jYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3dyaXRlUG9zQXR0cih0YXJnZXQsIG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9nc0V2ZW50SGFuZGxlcltldmVudC50eXBlXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZ3NFdmVudEhhbmRsZXJbZXZlbnQudHlwZV0oZXZlbnQsIHRhcmdldCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgICAgIHRoaXMuX2V4dHJhRHJhZ1JvdyA9IDA7IC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGVDb250YWluZXJIZWlnaHQoKTsgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJDaGFuZ2VFdmVudCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuZW5naW5lLmVuZFVwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIGlmIChldmVudC50eXBlID09PSAncmVzaXplc3RvcCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIobm9kZS5zaXplVG9Db250ZW50KSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2l6ZVRvQ29udGVudCA9IG5vZGUuaDsgLy8gbmV3IHNvZnQgbGltaXRcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNpemVUb0NvbnRlbnRDaGVjayh3aWR0aENoYW5nZWQsIG5vZGUpOyAvLyB3YWl0IGZvciB3aWR0aCBhbmltYXRpb24gaWYgY2hhbmdlZFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBkZC5kcmFnZ2FibGUoZWwsIHtcbiAgICAgICAgICAgICAgICBzdGFydDogb25TdGFydE1vdmluZyxcbiAgICAgICAgICAgICAgICBzdG9wOiBvbkVuZE1vdmluZyxcbiAgICAgICAgICAgICAgICBkcmFnOiBkcmFnT3JSZXNpemVcbiAgICAgICAgICAgIH0pLnJlc2l6YWJsZShlbCwge1xuICAgICAgICAgICAgICAgIHN0YXJ0OiBvblN0YXJ0TW92aW5nLFxuICAgICAgICAgICAgICAgIHN0b3A6IG9uRW5kTW92aW5nLFxuICAgICAgICAgICAgICAgIHJlc2l6ZTogZHJhZ09yUmVzaXplXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIG5vZGUuX2luaXRERCA9IHRydWU7IC8vIHdlJ3ZlIHNldCBERCBzdXBwb3J0IG5vd1xuICAgICAgICB9XG4gICAgICAgIC8vIGZpbmFsbHkgZmluZSB0dW5lIG1vdmUgdnMgcmVzaXplIGJ5IGRpc2FibGluZyBhbnkgcGFydC4uLlxuICAgICAgICBkZC5kcmFnZ2FibGUoZWwsIG5vTW92ZSA/ICdkaXNhYmxlJyA6ICdlbmFibGUnKVxuICAgICAgICAgICAgLnJlc2l6YWJsZShlbCwgbm9SZXNpemUgPyAnZGlzYWJsZScgOiAnZW5hYmxlJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKiogQGludGVybmFsIGhhbmRsZXMgYWN0dWFsIGRyYWcvcmVzaXplIHN0YXJ0ICovXG4gICAgX29uU3RhcnRNb3ZpbmcoZWwsIGV2ZW50LCB1aSwgbm9kZSwgY2VsbFdpZHRoLCBjZWxsSGVpZ2h0KSB7XG4gICAgICAgIHRoaXMuZW5naW5lLmNsZWFuTm9kZXMoKVxuICAgICAgICAgICAgLmJlZ2luVXBkYXRlKG5vZGUpO1xuICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgIHRoaXMuX3dyaXRlUG9zQXR0cih0aGlzLnBsYWNlaG9sZGVyLCBub2RlKTtcbiAgICAgICAgdGhpcy5lbC5hcHBlbmRDaGlsZCh0aGlzLnBsYWNlaG9sZGVyKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2coJ19vblN0YXJ0TW92aW5nIHBsYWNlaG9sZGVyJykgLy8gVEVTVFxuICAgICAgICAvLyBpZiB0aGUgZWxlbWVudCBpcyBpbnNpZGUgYSBncmlkLCBpdCBoYXMgYWxyZWFkeSBiZWVuIHNjYWxlZFxuICAgICAgICAvLyB3ZSBjYW4gdXNlIHRoYXQgYXMgYSBzY2FsZSByZWZlcmVuY2VcbiAgICAgICAgaWYgKG5vZGUuZ3JpZD8uZWwpIHtcbiAgICAgICAgICAgIHRoaXMuZHJhZ1RyYW5zZm9ybSA9IFV0aWxzLmdldFZhbHVlc0Zyb21UcmFuc2Zvcm1lZEVsZW1lbnQoZWwpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHRoZSBlbGVtZW50IGlzIGJlaW5nIGRyYWdnZWQgZnJvbSBvdXRzaWRlIChub3QgZnJvbSBhbnkgZ3JpZClcbiAgICAgICAgLy8gd2UgdXNlIHRoZSBncmlkIGFzIHRoZSB0cmFuc2Zvcm1hdGlvbiByZWZlcmVuY2UsIHNpbmNlIHRoZSBoZWxwZXIgaXMgbm90IHN1YmplY3QgdG8gdHJhbnNmb3JtYXRpb25cbiAgICAgICAgZWxzZSBpZiAodGhpcy5wbGFjZWhvbGRlciAmJiB0aGlzLnBsYWNlaG9sZGVyLmNsb3Nlc3QoJy5ncmlkLXN0YWNrJykpIHtcbiAgICAgICAgICAgIGNvbnN0IGdyaWRFbCA9IHRoaXMucGxhY2Vob2xkZXIuY2xvc2VzdCgnLmdyaWQtc3RhY2snKTtcbiAgICAgICAgICAgIHRoaXMuZHJhZ1RyYW5zZm9ybSA9IFV0aWxzLmdldFZhbHVlc0Zyb21UcmFuc2Zvcm1lZEVsZW1lbnQoZ3JpZEVsKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBGYWxsYmFja1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZHJhZ1RyYW5zZm9ybSA9IHtcbiAgICAgICAgICAgICAgICB4U2NhbGU6IDEsXG4gICAgICAgICAgICAgICAgeE9mZnNldDogMCxcbiAgICAgICAgICAgICAgICB5U2NhbGU6IDEsXG4gICAgICAgICAgICAgICAgeU9mZnNldDogMCxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgbm9kZS5lbCA9IHRoaXMucGxhY2Vob2xkZXI7XG4gICAgICAgIG5vZGUuX2xhc3RVaVBvc2l0aW9uID0gdWkucG9zaXRpb247XG4gICAgICAgIG5vZGUuX3ByZXZZUGl4ID0gdWkucG9zaXRpb24udG9wO1xuICAgICAgICBub2RlLl9tb3ZpbmcgPSAoZXZlbnQudHlwZSA9PT0gJ2RyYWdzdGFydCcpOyAvLyAnZHJvcG92ZXInIGFyZSBub3QgaW5pdGlhbGx5IG1vdmluZyBzbyB0aGV5IGNhbiBnbyBleGFjdGx5IHdoZXJlIHRoZXkgZW50ZXIgKHdpbGwgcHVzaCBzdHVmZiBvdXQgb2YgdGhlIHdheSlcbiAgICAgICAgZGVsZXRlIG5vZGUuX2xhc3RUcmllZDtcbiAgICAgICAgaWYgKGV2ZW50LnR5cGUgPT09ICdkcm9wb3ZlcicgJiYgbm9kZS5fdGVtcG9yYXJ5UmVtb3ZlZCkge1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ2VuZ2luZS5hZGROb2RlIHg9JyArIG5vZGUueCk7IC8vIFRFU1RcbiAgICAgICAgICAgIHRoaXMuZW5naW5lLmFkZE5vZGUobm9kZSk7IC8vIHdpbGwgYWRkLCBmaXggY29sbGlzaW9ucywgdXBkYXRlIGF0dHIgYW5kIGNsZWFyIF90ZW1wb3JhcnlSZW1vdmVkXG4gICAgICAgICAgICBub2RlLl9tb3ZpbmcgPSB0cnVlOyAvLyBBRlRFUiwgbWFyayBhcyBtb3Zpbmcgb2JqZWN0ICh3YW50ZWQgZml4IGxvY2F0aW9uIGJlZm9yZSlcbiAgICAgICAgfVxuICAgICAgICAvLyBzZXQgdGhlIG1pbi9tYXggcmVzaXplIGluZm9cbiAgICAgICAgdGhpcy5lbmdpbmUuY2FjaGVSZWN0cyhjZWxsV2lkdGgsIGNlbGxIZWlnaHQsIHRoaXMub3B0cy5tYXJnaW5Ub3AsIHRoaXMub3B0cy5tYXJnaW5SaWdodCwgdGhpcy5vcHRzLm1hcmdpbkJvdHRvbSwgdGhpcy5vcHRzLm1hcmdpbkxlZnQpO1xuICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gJ3Jlc2l6ZXN0YXJ0Jykge1xuICAgICAgICAgICAgZGQucmVzaXphYmxlKGVsLCAnb3B0aW9uJywgJ21pbldpZHRoJywgY2VsbFdpZHRoICogKG5vZGUubWluVyB8fCAxKSlcbiAgICAgICAgICAgICAgICAucmVzaXphYmxlKGVsLCAnb3B0aW9uJywgJ21pbkhlaWdodCcsIGNlbGxIZWlnaHQgKiAobm9kZS5taW5IIHx8IDEpKTtcbiAgICAgICAgICAgIGlmIChub2RlLm1heFcpIHtcbiAgICAgICAgICAgICAgICBkZC5yZXNpemFibGUoZWwsICdvcHRpb24nLCAnbWF4V2lkdGgnLCBjZWxsV2lkdGggKiBub2RlLm1heFcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5vZGUubWF4SCkge1xuICAgICAgICAgICAgICAgIGRkLnJlc2l6YWJsZShlbCwgJ29wdGlvbicsICdtYXhIZWlnaHQnLCBjZWxsSGVpZ2h0ICogbm9kZS5tYXhIKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvKiogQGludGVybmFsIGhhbmRsZXMgYWN0dWFsIGRyYWcvcmVzaXplICovXG4gICAgX2RyYWdPclJlc2l6ZShlbCwgZXZlbnQsIHVpLCBub2RlLCBjZWxsV2lkdGgsIGNlbGxIZWlnaHQpIHtcbiAgICAgICAgbGV0IHAgPSB7IC4uLm5vZGUuX29yaWcgfTsgLy8gY291bGQgYmUgdW5kZWZpbmVkIChfaXNFeHRlcm5hbCkgd2hpY2ggaXMgb2sgKGRyYWcgb25seSBzZXQgeCx5IGFuZCB3LGggd2lsbCBkZWZhdWx0IHRvIG5vZGUgdmFsdWUpXG4gICAgICAgIGxldCByZXNpemluZztcbiAgICAgICAgbGV0IG1MZWZ0ID0gdGhpcy5vcHRzLm1hcmdpbkxlZnQsIG1SaWdodCA9IHRoaXMub3B0cy5tYXJnaW5SaWdodCwgbVRvcCA9IHRoaXMub3B0cy5tYXJnaW5Ub3AsIG1Cb3R0b20gPSB0aGlzLm9wdHMubWFyZ2luQm90dG9tO1xuICAgICAgICAvLyBpZiBtYXJnaW5zICh3aGljaCBhcmUgdXNlZCB0byBwYXNzIG1pZCBwb2ludCBieSkgYXJlIGxhcmdlIHJlbGF0aXZlIHRvIGNlbGwgaGVpZ2h0L3dpZHRoLCByZWR1Y2UgdGhlbSBkb3duICMxODU1XG4gICAgICAgIGxldCBtSGVpZ2h0ID0gTWF0aC5yb3VuZChjZWxsSGVpZ2h0ICogMC4xKSwgbVdpZHRoID0gTWF0aC5yb3VuZChjZWxsV2lkdGggKiAwLjEpO1xuICAgICAgICBtTGVmdCA9IE1hdGgubWluKG1MZWZ0LCBtV2lkdGgpO1xuICAgICAgICBtUmlnaHQgPSBNYXRoLm1pbihtUmlnaHQsIG1XaWR0aCk7XG4gICAgICAgIG1Ub3AgPSBNYXRoLm1pbihtVG9wLCBtSGVpZ2h0KTtcbiAgICAgICAgbUJvdHRvbSA9IE1hdGgubWluKG1Cb3R0b20sIG1IZWlnaHQpO1xuICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gJ2RyYWcnKSB7XG4gICAgICAgICAgICBpZiAobm9kZS5fdGVtcG9yYXJ5UmVtb3ZlZClcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIGhhbmRsZWQgYnkgZHJvcG92ZXJcbiAgICAgICAgICAgIGxldCBkaXN0YW5jZSA9IHVpLnBvc2l0aW9uLnRvcCAtIG5vZGUuX3ByZXZZUGl4O1xuICAgICAgICAgICAgbm9kZS5fcHJldllQaXggPSB1aS5wb3NpdGlvbi50b3A7XG4gICAgICAgICAgICBpZiAodGhpcy5vcHRzLmRyYWdnYWJsZS5zY3JvbGwgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgVXRpbHMudXBkYXRlU2Nyb2xsUG9zaXRpb24oZWwsIHVpLnBvc2l0aW9uLCBkaXN0YW5jZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBnZXQgbmV3IHBvc2l0aW9uIHRha2luZyBpbnRvIGFjY291bnQgdGhlIG1hcmdpbiBpbiB0aGUgZGlyZWN0aW9uIHdlIGFyZSBtb3ZpbmchIChuZWVkIHRvIHBhc3MgbWlkIHBvaW50IGJ5IG1hcmdpbilcbiAgICAgICAgICAgIGxldCBsZWZ0ID0gdWkucG9zaXRpb24ubGVmdCArICh1aS5wb3NpdGlvbi5sZWZ0ID4gbm9kZS5fbGFzdFVpUG9zaXRpb24ubGVmdCA/IC1tUmlnaHQgOiBtTGVmdCk7XG4gICAgICAgICAgICBsZXQgdG9wID0gdWkucG9zaXRpb24udG9wICsgKHVpLnBvc2l0aW9uLnRvcCA+IG5vZGUuX2xhc3RVaVBvc2l0aW9uLnRvcCA/IC1tQm90dG9tIDogbVRvcCk7XG4gICAgICAgICAgICBwLnggPSBNYXRoLnJvdW5kKGxlZnQgLyBjZWxsV2lkdGgpO1xuICAgICAgICAgICAgcC55ID0gTWF0aC5yb3VuZCh0b3AgLyBjZWxsSGVpZ2h0KTtcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmUvLyBpZiB3ZSdyZSBhdCB0aGUgYm90dG9tIGhpdHRpbmcgc29tZXRoaW5nIGVsc2UsIGdyb3cgdGhlIGdyaWQgc28gY3Vyc29yIGRvZXNuJ3QgbGVhdmUgd2hlbiB0cnlpbmcgdG8gcGxhY2UgYmVsb3cgb3RoZXJzXG4gICAgICAgICAgICBsZXQgcHJldiA9IHRoaXMuX2V4dHJhRHJhZ1JvdztcbiAgICAgICAgICAgIGlmICh0aGlzLmVuZ2luZS5jb2xsaWRlKG5vZGUsIHApKSB7XG4gICAgICAgICAgICAgICAgbGV0IHJvdyA9IHRoaXMuZ2V0Um93KCk7XG4gICAgICAgICAgICAgICAgbGV0IGV4dHJhID0gTWF0aC5tYXgoMCwgKHAueSArIG5vZGUuaCkgLSByb3cpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm9wdHMubWF4Um93ICYmIHJvdyArIGV4dHJhID4gdGhpcy5vcHRzLm1heFJvdykge1xuICAgICAgICAgICAgICAgICAgICBleHRyYSA9IE1hdGgubWF4KDAsIHRoaXMub3B0cy5tYXhSb3cgLSByb3cpO1xuICAgICAgICAgICAgICAgIH0gLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgICAgIHRoaXMuX2V4dHJhRHJhZ1JvdyA9IGV4dHJhOyAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgdGhpcy5fZXh0cmFEcmFnUm93ID0gMDsgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgaWYgKHRoaXMuX2V4dHJhRHJhZ1JvdyAhPT0gcHJldilcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGVDb250YWluZXJIZWlnaHQoKTtcbiAgICAgICAgICAgIGlmIChub2RlLnggPT09IHAueCAmJiBub2RlLnkgPT09IHAueSlcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIHNraXAgc2FtZVxuICAgICAgICAgICAgLy8gRE9OJ1Qgc2tpcCBvbmUgd2UgdHJpZWQgYXMgd2UgbWlnaHQgaGF2ZSBmYWlsZWQgYmVjYXVzZSBvZiBjb3ZlcmFnZSA8NTAlIGJlZm9yZVxuICAgICAgICAgICAgLy8gaWYgKG5vZGUuX2xhc3RUcmllZCAmJiBub2RlLl9sYXN0VHJpZWQueCA9PT0geCAmJiBub2RlLl9sYXN0VHJpZWQueSA9PT0geSkgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2ZW50LnR5cGUgPT09ICdyZXNpemUnKSB7XG4gICAgICAgICAgICBpZiAocC54IDwgMClcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAvLyBTY3JvbGxpbmcgcGFnZSBpZiBuZWVkZWRcbiAgICAgICAgICAgIFV0aWxzLnVwZGF0ZVNjcm9sbFJlc2l6ZShldmVudCwgZWwsIGNlbGxIZWlnaHQpO1xuICAgICAgICAgICAgLy8gZ2V0IG5ldyBzaXplXG4gICAgICAgICAgICBwLncgPSBNYXRoLnJvdW5kKCh1aS5zaXplLndpZHRoIC0gbUxlZnQpIC8gY2VsbFdpZHRoKTtcbiAgICAgICAgICAgIHAuaCA9IE1hdGgucm91bmQoKHVpLnNpemUuaGVpZ2h0IC0gbVRvcCkgLyBjZWxsSGVpZ2h0KTtcbiAgICAgICAgICAgIGlmIChub2RlLncgPT09IHAudyAmJiBub2RlLmggPT09IHAuaClcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICBpZiAobm9kZS5fbGFzdFRyaWVkICYmIG5vZGUuX2xhc3RUcmllZC53ID09PSBwLncgJiYgbm9kZS5fbGFzdFRyaWVkLmggPT09IHAuaClcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIHNraXAgb25lIHdlIHRyaWVkIChidXQgZmFpbGVkKVxuICAgICAgICAgICAgLy8gaWYgd2Ugc2l6ZSBvbiBsZWZ0L3RvcCBzaWRlIHRoaXMgbWlnaHQgbW92ZSB1cywgc28gZ2V0IHBvc3NpYmxlIG5ldyBwb3NpdGlvbiBhcyB3ZWxsXG4gICAgICAgICAgICBsZXQgbGVmdCA9IHVpLnBvc2l0aW9uLmxlZnQgKyBtTGVmdDtcbiAgICAgICAgICAgIGxldCB0b3AgPSB1aS5wb3NpdGlvbi50b3AgKyBtVG9wO1xuICAgICAgICAgICAgcC54ID0gTWF0aC5yb3VuZChsZWZ0IC8gY2VsbFdpZHRoKTtcbiAgICAgICAgICAgIHAueSA9IE1hdGgucm91bmQodG9wIC8gY2VsbEhlaWdodCk7XG4gICAgICAgICAgICByZXNpemluZyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgbm9kZS5fZXZlbnQgPSBldmVudDtcbiAgICAgICAgbm9kZS5fbGFzdFRyaWVkID0gcDsgLy8gc2V0IGFzIGxhc3QgdHJpZWQgKHdpbGwgbnVrZSBpZiB3ZSBnbyB0aGVyZSlcbiAgICAgICAgbGV0IHJlY3QgPSB7XG4gICAgICAgICAgICB4OiB1aS5wb3NpdGlvbi5sZWZ0ICsgbUxlZnQsXG4gICAgICAgICAgICB5OiB1aS5wb3NpdGlvbi50b3AgKyBtVG9wLFxuICAgICAgICAgICAgdzogKHVpLnNpemUgPyB1aS5zaXplLndpZHRoIDogbm9kZS53ICogY2VsbFdpZHRoKSAtIG1MZWZ0IC0gbVJpZ2h0LFxuICAgICAgICAgICAgaDogKHVpLnNpemUgPyB1aS5zaXplLmhlaWdodCA6IG5vZGUuaCAqIGNlbGxIZWlnaHQpIC0gbVRvcCAtIG1Cb3R0b21cbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHRoaXMuZW5naW5lLm1vdmVOb2RlQ2hlY2sobm9kZSwgeyAuLi5wLCBjZWxsV2lkdGgsIGNlbGxIZWlnaHQsIHJlY3QsIHJlc2l6aW5nIH0pKSB7XG4gICAgICAgICAgICBub2RlLl9sYXN0VWlQb3NpdGlvbiA9IHVpLnBvc2l0aW9uO1xuICAgICAgICAgICAgdGhpcy5lbmdpbmUuY2FjaGVSZWN0cyhjZWxsV2lkdGgsIGNlbGxIZWlnaHQsIG1Ub3AsIG1SaWdodCwgbUJvdHRvbSwgbUxlZnQpO1xuICAgICAgICAgICAgZGVsZXRlIG5vZGUuX3NraXBEb3duO1xuICAgICAgICAgICAgaWYgKHJlc2l6aW5nICYmIG5vZGUuc3ViR3JpZClcbiAgICAgICAgICAgICAgICBub2RlLnN1YkdyaWQub25SZXNpemUoKTtcbiAgICAgICAgICAgIHRoaXMuX2V4dHJhRHJhZ1JvdyA9IDA7IC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZUNvbnRhaW5lckhlaWdodCgpO1xuICAgICAgICAgICAgbGV0IHRhcmdldCA9IGV2ZW50LnRhcmdldDsgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgdGhpcy5fd3JpdGVQb3NBdHRyKHRhcmdldCwgbm9kZSk7XG4gICAgICAgICAgICBpZiAodGhpcy5fZ3NFdmVudEhhbmRsZXJbZXZlbnQudHlwZV0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9nc0V2ZW50SGFuZGxlcltldmVudC50eXBlXShldmVudCwgdGFyZ2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvKiogQGludGVybmFsIGNhbGxlZCB3aGVuIGl0ZW0gbGVhdmluZyBvdXIgYXJlYSBieSBlaXRoZXIgY3Vyc29yIGRyb3BvdXQgZXZlbnRcbiAgICAgKiBvciBzaGFwZSBpcyBvdXRzaWRlIG91ciBib3VuZGFyaWVzLiByZW1vdmUgaXQgZnJvbSB1cywgYW5kIG1hcmsgdGVtcG9yYXJ5IGlmIHRoaXMgd2FzXG4gICAgICogb3VyIGl0ZW0gdG8gc3RhcnQgd2l0aCBlbHNlIHJlc3RvcmUgcHJldiBub2RlIHZhbHVlcyBmcm9tIHByZXYgZ3JpZCBpdCBjYW1lIGZyb20uXG4gICAgICovXG4gICAgX2xlYXZlKGVsLCBoZWxwZXIpIHtcbiAgICAgICAgbGV0IG5vZGUgPSBlbC5ncmlkc3RhY2tOb2RlO1xuICAgICAgICBpZiAoIW5vZGUpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGhlbHBlciA9IGhlbHBlciB8fCBlbDtcbiAgICAgICAgLy8gcmVzdG9yZSB0aGUgc2NhbGUgb2YgdGhlIGhlbHBlciBvbiBsZWF2ZVxuICAgICAgICBoZWxwZXIuc3R5bGUudHJhbnNmb3JtID0gJ3NjYWxlKDEpJztcbiAgICAgICAgZGQub2ZmKGVsLCAnZHJhZycpOyAvLyBubyBuZWVkIHRvIHRyYWNrIHdoaWxlIGJlaW5nIG91dHNpZGVcbiAgICAgICAgLy8gdGhpcyBnZXRzIGNhbGxlZCB3aGVuIGN1cnNvciBsZWF2ZXMgYW5kIHNoYXBlIGlzIG91dHNpZGUsIHNvIG9ubHkgZG8gdGhpcyBvbmNlXG4gICAgICAgIGlmIChub2RlLl90ZW1wb3JhcnlSZW1vdmVkKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBub2RlLl90ZW1wb3JhcnlSZW1vdmVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5lbmdpbmUucmVtb3ZlTm9kZShub2RlKTsgLy8gcmVtb3ZlIHBsYWNlaG9sZGVyIGFzIHdlbGwsIG90aGVyd2lzZSBpdCdzIGEgc2lnbiBub2RlIGlzIG5vdCBpbiBvdXIgbGlzdCwgd2hpY2ggaXMgYSBiaWdnZXIgaXNzdWVcbiAgICAgICAgbm9kZS5lbCA9IG5vZGUuX2lzRXh0ZXJuYWwgJiYgaGVscGVyID8gaGVscGVyIDogZWw7IC8vIHBvaW50IGJhY2sgdG8gcmVhbCBpdGVtIGJlaW5nIGRyYWdnZWRcbiAgICAgICAgaWYgKHRoaXMub3B0cy5yZW1vdmFibGUgPT09IHRydWUpIHsgLy8gYm9vbGVhbiB2cyBhIGNsYXNzIHN0cmluZ1xuICAgICAgICAgICAgLy8gaXRlbSBsZWF2aW5nIHVzIGFuZCB3ZSBhcmUgc3VwcG9zZWQgdG8gcmVtb3ZlIG9uIGxlYXZlIChubyBuZWVkIHRvIGRyYWcgb250byB0cmFzaCkgbWFyayBpdCBzb1xuICAgICAgICAgICAgR3JpZFN0YWNrLl9pdGVtUmVtb3ZpbmcoZWwsIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGZpbmFsbHkgaWYgaXRlbSBvcmlnaW5hbGx5IGNhbWUgZnJvbSBhbm90aGVyIGdyaWQsIGJ1dCBsZWZ0IHVzLCByZXN0b3JlIHRoaW5ncyBiYWNrIHRvIHByZXYgaW5mb1xuICAgICAgICBpZiAoZWwuX2dyaWRzdGFja05vZGVPcmlnKSB7XG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnbGVhdmUgZGVsZXRlIF9ncmlkc3RhY2tOb2RlT3JpZycpIC8vIFRFU1RcbiAgICAgICAgICAgIGVsLmdyaWRzdGFja05vZGUgPSBlbC5fZ3JpZHN0YWNrTm9kZU9yaWc7XG4gICAgICAgICAgICBkZWxldGUgZWwuX2dyaWRzdGFja05vZGVPcmlnO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG5vZGUuX2lzRXh0ZXJuYWwpIHtcbiAgICAgICAgICAgIC8vIGl0ZW0gY2FtZSBmcm9tIG91dHNpZGUgKGxpa2UgYSB0b29sYmFyKSBzbyBudWtlIGFueSBub2RlIGluZm9cbiAgICAgICAgICAgIGRlbGV0ZSBub2RlLmVsO1xuICAgICAgICAgICAgZGVsZXRlIGVsLmdyaWRzdGFja05vZGU7XG4gICAgICAgICAgICAvLyBhbmQgcmVzdG9yZSBhbGwgbm9kZXMgYmFjayB0byBvcmlnaW5hbFxuICAgICAgICAgICAgdGhpcy5lbmdpbmUucmVzdG9yZUluaXRpYWwoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBsZWdhY3kgbWV0aG9kIHJlbW92ZWRcbiAgICBjb21taXQoKSB7IG9ic29sZXRlKHRoaXMsIHRoaXMuYmF0Y2hVcGRhdGUoZmFsc2UpLCAnY29tbWl0JywgJ2JhdGNoVXBkYXRlJywgJzUuMicpOyByZXR1cm4gdGhpczsgfVxufVxuLyoqIHBhcmVudCBjbGFzcyBmb3Igc2l6aW5nIGNvbnRlbnQuIGRlZmF1bHRzIHRvICcuZ3JpZC1zdGFjay1pdGVtLWNvbnRlbnQnICovXG5HcmlkU3RhY2sucmVzaXplVG9Db250ZW50UGFyZW50ID0gJy5ncmlkLXN0YWNrLWl0ZW0tY29udGVudCc7XG4vKiogc2NvcGluZyBzbyB1c2VycyBjYW4gY2FsbCBHcmlkU3RhY2suVXRpbHMuc29ydCgpIGZvciBleGFtcGxlICovXG5HcmlkU3RhY2suVXRpbHMgPSBVdGlscztcbi8qKiBzY29waW5nIHNvIHVzZXJzIGNhbiBjYWxsIG5ldyBHcmlkU3RhY2suRW5naW5lKDEyKSBmb3IgZXhhbXBsZSAqL1xuR3JpZFN0YWNrLkVuZ2luZSA9IEdyaWRTdGFja0VuZ2luZTtcbkdyaWRTdGFjay5HRFJldiA9ICcxMC4xLjInO1xuZXhwb3J0IHsgR3JpZFN0YWNrIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1ncmlkc3RhY2suanMubWFwIiwiLyoqXG4gKiB0eXBlcy50cyAxMC4xLjJcbiAqIENvcHlyaWdodCAoYykgMjAyMSBBbGFpbiBEdW1lc255IC0gc2VlIEdyaWRTdGFjayByb290IGxpY2Vuc2VcbiAqL1xuLy8gZGVmYXVsdCB2YWx1ZXMgZm9yIGdyaWQgb3B0aW9ucyAtIHVzZWQgZHVyaW5nIGluaXQgYW5kIHdoZW4gc2F2aW5nIG91dFxuZXhwb3J0IGNvbnN0IGdyaWREZWZhdWx0cyA9IHtcbiAgICBhbHdheXNTaG93UmVzaXplSGFuZGxlOiAnbW9iaWxlJyxcbiAgICBhbmltYXRlOiB0cnVlLFxuICAgIGF1dG86IHRydWUsXG4gICAgY2VsbEhlaWdodDogJ2F1dG8nLFxuICAgIGNlbGxIZWlnaHRUaHJvdHRsZTogMTAwLFxuICAgIGNlbGxIZWlnaHRVbml0OiAncHgnLFxuICAgIGNvbHVtbjogMTIsXG4gICAgZHJhZ2dhYmxlOiB7IGhhbmRsZTogJy5ncmlkLXN0YWNrLWl0ZW0tY29udGVudCcsIGFwcGVuZFRvOiAnYm9keScsIHNjcm9sbDogdHJ1ZSB9LFxuICAgIGhhbmRsZTogJy5ncmlkLXN0YWNrLWl0ZW0tY29udGVudCcsXG4gICAgaXRlbUNsYXNzOiAnZ3JpZC1zdGFjay1pdGVtJyxcbiAgICBtYXJnaW46IDEwLFxuICAgIG1hcmdpblVuaXQ6ICdweCcsXG4gICAgbWF4Um93OiAwLFxuICAgIG1pblJvdzogMCxcbiAgICBwbGFjZWhvbGRlckNsYXNzOiAnZ3JpZC1zdGFjay1wbGFjZWhvbGRlcicsXG4gICAgcGxhY2Vob2xkZXJUZXh0OiAnJyxcbiAgICByZW1vdmFibGVPcHRpb25zOiB7IGFjY2VwdDogJ2dyaWQtc3RhY2staXRlbScsIGRlY2xpbmU6ICdncmlkLXN0YWNrLW5vbi1yZW1vdmFibGUnIH0sXG4gICAgcmVzaXphYmxlOiB7IGhhbmRsZXM6ICdzZScgfSxcbiAgICBydGw6ICdhdXRvJyxcbiAgICAvLyAqKioqIHNhbWUgYXMgbm90IGJlaW5nIHNldCAqKioqXG4gICAgLy8gZGlzYWJsZURyYWc6IGZhbHNlLFxuICAgIC8vIGRpc2FibGVSZXNpemU6IGZhbHNlLFxuICAgIC8vIGZsb2F0OiBmYWxzZSxcbiAgICAvLyBoYW5kbGVDbGFzczogbnVsbCxcbiAgICAvLyByZW1vdmFibGU6IGZhbHNlLFxuICAgIC8vIHN0YXRpY0dyaWQ6IGZhbHNlLFxuICAgIC8vIHN0eWxlSW5IZWFkOiBmYWxzZSxcbiAgICAvL3JlbW92YWJsZVxufTtcbi8qKiBkZWZhdWx0IGRyYWdJbiBvcHRpb25zICovXG5leHBvcnQgY29uc3QgZHJhZ0luRGVmYXVsdE9wdGlvbnMgPSB7XG4gICAgaGFuZGxlOiAnLmdyaWQtc3RhY2staXRlbS1jb250ZW50JyxcbiAgICBhcHBlbmRUbzogJ2JvZHknLFxuICAgIC8vIHJldmVydDogJ2ludmFsaWQnLFxuICAgIC8vIHNjcm9sbDogZmFsc2UsXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dHlwZXMuanMubWFwIiwiLyoqXG4gKiB1dGlscy50cyAxMC4xLjJcbiAqIENvcHlyaWdodCAoYykgMjAyMSBBbGFpbiBEdW1lc255IC0gc2VlIEdyaWRTdGFjayByb290IGxpY2Vuc2VcbiAqL1xuLyoqIGNoZWNrcyBmb3Igb2Jzb2xldGUgbWV0aG9kIG5hbWVzICovXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbmV4cG9ydCBmdW5jdGlvbiBvYnNvbGV0ZShzZWxmLCBmLCBvbGROYW1lLCBuZXdOYW1lLCByZXYpIHtcbiAgICBsZXQgd3JhcHBlciA9ICguLi5hcmdzKSA9PiB7XG4gICAgICAgIGNvbnNvbGUud2FybignZ3JpZHN0YWNrLmpzOiBGdW5jdGlvbiBgJyArIG9sZE5hbWUgKyAnYCBpcyBkZXByZWNhdGVkIGluICcgKyByZXYgKyAnIGFuZCBoYXMgYmVlbiByZXBsYWNlZCAnICtcbiAgICAgICAgICAgICd3aXRoIGAnICsgbmV3TmFtZSArICdgLiBJdCB3aWxsIGJlICoqcmVtb3ZlZCoqIGluIGEgZnV0dXJlIHJlbGVhc2UnKTtcbiAgICAgICAgcmV0dXJuIGYuYXBwbHkoc2VsZiwgYXJncyk7XG4gICAgfTtcbiAgICB3cmFwcGVyLnByb3RvdHlwZSA9IGYucHJvdG90eXBlO1xuICAgIHJldHVybiB3cmFwcGVyO1xufVxuLyoqIGNoZWNrcyBmb3Igb2Jzb2xldGUgZ3JpZCBvcHRpb25zIChjYW4gYmUgdXNlZCBmb3IgYW55IGZpZWxkcywgYnV0IG1zZyBpcyBhYm91dCBvcHRpb25zKSAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9ic29sZXRlT3B0cyhvcHRzLCBvbGROYW1lLCBuZXdOYW1lLCByZXYpIHtcbiAgICBpZiAob3B0c1tvbGROYW1lXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIG9wdHNbbmV3TmFtZV0gPSBvcHRzW29sZE5hbWVdO1xuICAgICAgICBjb25zb2xlLndhcm4oJ2dyaWRzdGFjay5qczogT3B0aW9uIGAnICsgb2xkTmFtZSArICdgIGlzIGRlcHJlY2F0ZWQgaW4gJyArIHJldiArICcgYW5kIGhhcyBiZWVuIHJlcGxhY2VkIHdpdGggYCcgK1xuICAgICAgICAgICAgbmV3TmFtZSArICdgLiBJdCB3aWxsIGJlICoqcmVtb3ZlZCoqIGluIGEgZnV0dXJlIHJlbGVhc2UnKTtcbiAgICB9XG59XG4vKiogY2hlY2tzIGZvciBvYnNvbGV0ZSBncmlkIG9wdGlvbnMgd2hpY2ggYXJlIGdvbmUgKi9cbmV4cG9ydCBmdW5jdGlvbiBvYnNvbGV0ZU9wdHNEZWwob3B0cywgb2xkTmFtZSwgcmV2LCBpbmZvKSB7XG4gICAgaWYgKG9wdHNbb2xkTmFtZV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ2dyaWRzdGFjay5qczogT3B0aW9uIGAnICsgb2xkTmFtZSArICdgIGlzIGRlcHJlY2F0ZWQgaW4gJyArIHJldiArIGluZm8pO1xuICAgIH1cbn1cbi8qKiBjaGVja3MgZm9yIG9ic29sZXRlIEpxdWVyeSBlbGVtZW50IGF0dHJpYnV0ZXMgKi9cbmV4cG9ydCBmdW5jdGlvbiBvYnNvbGV0ZUF0dHIoZWwsIG9sZE5hbWUsIG5ld05hbWUsIHJldikge1xuICAgIGxldCBvbGRBdHRyID0gZWwuZ2V0QXR0cmlidXRlKG9sZE5hbWUpO1xuICAgIGlmIChvbGRBdHRyICE9PSBudWxsKSB7XG4gICAgICAgIGVsLnNldEF0dHJpYnV0ZShuZXdOYW1lLCBvbGRBdHRyKTtcbiAgICAgICAgY29uc29sZS53YXJuKCdncmlkc3RhY2suanM6IGF0dHJpYnV0ZSBgJyArIG9sZE5hbWUgKyAnYD0nICsgb2xkQXR0ciArICcgaXMgZGVwcmVjYXRlZCBvbiB0aGlzIG9iamVjdCBpbiAnICsgcmV2ICsgJyBhbmQgaGFzIGJlZW4gcmVwbGFjZWQgd2l0aCBgJyArXG4gICAgICAgICAgICBuZXdOYW1lICsgJ2AuIEl0IHdpbGwgYmUgKipyZW1vdmVkKiogaW4gYSBmdXR1cmUgcmVsZWFzZScpO1xuICAgIH1cbn1cbi8qKlxuICogVXRpbGl0eSBtZXRob2RzXG4gKi9cbmV4cG9ydCBjbGFzcyBVdGlscyB7XG4gICAgLyoqIGNvbnZlcnQgYSBwb3RlbnRpYWwgc2VsZWN0b3IgaW50byBhY3R1YWwgbGlzdCBvZiBodG1sIGVsZW1lbnRzLiBvcHRpb25hbCByb290IHdoaWNoIGRlZmF1bHRzIHRvIGRvY3VtZW50IChmb3Igc2hhZG93IGRvbSkgKi9cbiAgICBzdGF0aWMgZ2V0RWxlbWVudHMoZWxzLCByb290ID0gZG9jdW1lbnQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBlbHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCBkb2MgPSAoJ2dldEVsZW1lbnRCeUlkJyBpbiByb290KSA/IHJvb3QgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAvLyBOb3RlOiB2ZXJ5IGNvbW1vbiBmb3IgcGVvcGxlIHVzZSB0byBpZD0nMSwyLDMnIHdoaWNoIGlzIG9ubHkgbGVnYWwgYXMgSFRNTDUgaWQsIGJ1dCBub3QgQ1NTIHNlbGVjdG9yc1xuICAgICAgICAgICAgLy8gc28gaWYgd2Ugc3RhcnQgd2l0aCBhIG51bWJlciwgYXNzdW1lIGl0J3MgYW4gaWQgYW5kIGp1c3QgcmV0dXJuIHRoYXQgb25lIGl0ZW0uLi5cbiAgICAgICAgICAgIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vZ3JpZHN0YWNrL2dyaWRzdGFjay5qcy9pc3N1ZXMvMjIzNCNpc3N1ZWNvbW1lbnQtMTUyMzc5NjU2MlxuICAgICAgICAgICAgaWYgKGRvYyAmJiAhaXNOYU4oK2Vsc1swXSkpIHsgLy8gc3RhcnQgd2l0aCBkaWdpdFxuICAgICAgICAgICAgICAgIGNvbnN0IGVsID0gZG9jLmdldEVsZW1lbnRCeUlkKGVscyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsID8gW2VsXSA6IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGxpc3QgPSByb290LnF1ZXJ5U2VsZWN0b3JBbGwoZWxzKTtcbiAgICAgICAgICAgIGlmICghbGlzdC5sZW5ndGggJiYgZWxzWzBdICE9PSAnLicgJiYgZWxzWzBdICE9PSAnIycpIHtcbiAgICAgICAgICAgICAgICBsaXN0ID0gcm9vdC5xdWVyeVNlbGVjdG9yQWxsKCcuJyArIGVscyk7XG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ID0gcm9vdC5xdWVyeVNlbGVjdG9yQWxsKCcjJyArIGVscyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIEFycmF5LmZyb20obGlzdCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtlbHNdO1xuICAgIH1cbiAgICAvKiogY29udmVydCBhIHBvdGVudGlhbCBzZWxlY3RvciBpbnRvIGFjdHVhbCBzaW5nbGUgZWxlbWVudC4gb3B0aW9uYWwgcm9vdCB3aGljaCBkZWZhdWx0cyB0byBkb2N1bWVudCAoZm9yIHNoYWRvdyBkb20pICovXG4gICAgc3RhdGljIGdldEVsZW1lbnQoZWxzLCByb290ID0gZG9jdW1lbnQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBlbHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCBkb2MgPSAoJ2dldEVsZW1lbnRCeUlkJyBpbiByb290KSA/IHJvb3QgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICBpZiAoIWVscy5sZW5ndGgpXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICBpZiAoZG9jICYmIGVsc1swXSA9PT0gJyMnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5nZXRFbGVtZW50QnlJZChlbHMuc3Vic3RyaW5nKDEpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChlbHNbMF0gPT09ICcjJyB8fCBlbHNbMF0gPT09ICcuJyB8fCBlbHNbMF0gPT09ICdbJykge1xuICAgICAgICAgICAgICAgIHJldHVybiByb290LnF1ZXJ5U2VsZWN0b3IoZWxzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGlmIHdlIHN0YXJ0IHdpdGggYSBkaWdpdCwgYXNzdW1lIGl0J3MgYW4gaWQgKGVycm9yIGNhbGxpbmcgcXVlcnlTZWxlY3RvcignIzEnKSkgYXMgY2xhc3MgYXJlIG5vdCB2YWxpZCBDU1NcbiAgICAgICAgICAgIGlmIChkb2MgJiYgIWlzTmFOKCtlbHNbMF0pKSB7IC8vIHN0YXJ0IHdpdGggZGlnaXRcbiAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmdldEVsZW1lbnRCeUlkKGVscyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBmaW5hbGx5IHRyeSBzdHJpbmcsIHRoZW4gaWQsIHRoZW4gY2xhc3NcbiAgICAgICAgICAgIGxldCBlbCA9IHJvb3QucXVlcnlTZWxlY3RvcihlbHMpO1xuICAgICAgICAgICAgaWYgKGRvYyAmJiAhZWwpIHtcbiAgICAgICAgICAgICAgICBlbCA9IGRvYy5nZXRFbGVtZW50QnlJZChlbHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFlbCkge1xuICAgICAgICAgICAgICAgIGVsID0gcm9vdC5xdWVyeVNlbGVjdG9yKCcuJyArIGVscyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZWw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVscztcbiAgICB9XG4gICAgLyoqIHRydWUgaWYgd2Ugc2hvdWxkIHJlc2l6ZSB0byBjb250ZW50LiBzdHJpY3Q9dHJ1ZSB3aGVuIG9ubHkgJ3NpemVUb0NvbnRlbnQ6dHJ1ZScgYW5kIG5vdCBhIG51bWJlciB3aGljaCBsZXRzIHVzZXIgYWRqdXN0ICovXG4gICAgc3RhdGljIHNob3VsZFNpemVUb0NvbnRlbnQobiwgc3RyaWN0ID0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuIG4/LmdyaWQgJiYgKHN0cmljdCA/XG4gICAgICAgICAgICAobi5zaXplVG9Db250ZW50ID09PSB0cnVlIHx8IChuLmdyaWQub3B0cy5zaXplVG9Db250ZW50ID09PSB0cnVlICYmIG4uc2l6ZVRvQ29udGVudCA9PT0gdW5kZWZpbmVkKSkgOlxuICAgICAgICAgICAgKCEhbi5zaXplVG9Db250ZW50IHx8IChuLmdyaWQub3B0cy5zaXplVG9Db250ZW50ICYmIG4uc2l6ZVRvQ29udGVudCAhPT0gZmFsc2UpKSk7XG4gICAgfVxuICAgIC8qKiByZXR1cm5zIHRydWUgaWYgYSBhbmQgYiBvdmVybGFwICovXG4gICAgc3RhdGljIGlzSW50ZXJjZXB0ZWQoYSwgYikge1xuICAgICAgICByZXR1cm4gIShhLnkgPj0gYi55ICsgYi5oIHx8IGEueSArIGEuaCA8PSBiLnkgfHwgYS54ICsgYS53IDw9IGIueCB8fCBhLnggPj0gYi54ICsgYi53KTtcbiAgICB9XG4gICAgLyoqIHJldHVybnMgdHJ1ZSBpZiBhIGFuZCBiIHRvdWNoIGVkZ2VzIG9yIGNvcm5lcnMgKi9cbiAgICBzdGF0aWMgaXNUb3VjaGluZyhhLCBiKSB7XG4gICAgICAgIHJldHVybiBVdGlscy5pc0ludGVyY2VwdGVkKGEsIHsgeDogYi54IC0gMC41LCB5OiBiLnkgLSAwLjUsIHc6IGIudyArIDEsIGg6IGIuaCArIDEgfSk7XG4gICAgfVxuICAgIC8qKiByZXR1cm5zIHRoZSBhcmVhIGEgYW5kIGIgb3ZlcmxhcCAqL1xuICAgIHN0YXRpYyBhcmVhSW50ZXJjZXB0KGEsIGIpIHtcbiAgICAgICAgbGV0IHgwID0gKGEueCA+IGIueCkgPyBhLnggOiBiLng7XG4gICAgICAgIGxldCB4MSA9IChhLnggKyBhLncgPCBiLnggKyBiLncpID8gYS54ICsgYS53IDogYi54ICsgYi53O1xuICAgICAgICBpZiAoeDEgPD0geDApXG4gICAgICAgICAgICByZXR1cm4gMDsgLy8gbm8gb3ZlcmxhcFxuICAgICAgICBsZXQgeTAgPSAoYS55ID4gYi55KSA/IGEueSA6IGIueTtcbiAgICAgICAgbGV0IHkxID0gKGEueSArIGEuaCA8IGIueSArIGIuaCkgPyBhLnkgKyBhLmggOiBiLnkgKyBiLmg7XG4gICAgICAgIGlmICh5MSA8PSB5MClcbiAgICAgICAgICAgIHJldHVybiAwOyAvLyBubyBvdmVybGFwXG4gICAgICAgIHJldHVybiAoeDEgLSB4MCkgKiAoeTEgLSB5MCk7XG4gICAgfVxuICAgIC8qKiByZXR1cm5zIHRoZSBhcmVhICovXG4gICAgc3RhdGljIGFyZWEoYSkge1xuICAgICAgICByZXR1cm4gYS53ICogYS5oO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTb3J0cyBhcnJheSBvZiBub2Rlc1xuICAgICAqIEBwYXJhbSBub2RlcyBhcnJheSB0byBzb3J0XG4gICAgICogQHBhcmFtIGRpciAxIGZvciBhc2NlbmRpbmcsIC0xIGZvciBkZXNjZW5kaW5nIChvcHRpb25hbClcbiAgICAgKiovXG4gICAgc3RhdGljIHNvcnQobm9kZXMsIGRpciA9IDEpIHtcbiAgICAgICAgY29uc3QgdW5kID0gMTAwMDA7XG4gICAgICAgIHJldHVybiBub2Rlcy5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgICAgICBsZXQgZGlmZlkgPSBkaXIgKiAoKGEueSA/PyB1bmQpIC0gKGIueSA/PyB1bmQpKTtcbiAgICAgICAgICAgIGlmIChkaWZmWSA9PT0gMClcbiAgICAgICAgICAgICAgICByZXR1cm4gZGlyICogKChhLnggPz8gdW5kKSAtIChiLnggPz8gdW5kKSk7XG4gICAgICAgICAgICByZXR1cm4gZGlmZlk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKiogZmluZCBhbiBpdGVtIGJ5IGlkICovXG4gICAgc3RhdGljIGZpbmQobm9kZXMsIGlkKSB7XG4gICAgICAgIHJldHVybiBpZCA/IG5vZGVzLmZpbmQobiA9PiBuLmlkID09PSBpZCkgOiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIGNyZWF0ZXMgYSBzdHlsZSBzaGVldCB3aXRoIHN0eWxlIGlkIHVuZGVyIGdpdmVuIHBhcmVudFxuICAgICAqIEBwYXJhbSBpZCB3aWxsIHNldCB0aGUgJ2dzLXN0eWxlLWlkJyBhdHRyaWJ1dGUgdG8gdGhhdCBpZFxuICAgICAqIEBwYXJhbSBwYXJlbnQgdG8gaW5zZXJ0IHRoZSBzdHlsZXNoZWV0IGFzIGZpcnN0IGNoaWxkLFxuICAgICAqIGlmIG5vbmUgc3VwcGxpZWQgaXQgd2lsbCBiZSBhcHBlbmRlZCB0byB0aGUgZG9jdW1lbnQgaGVhZCBpbnN0ZWFkLlxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVTdHlsZXNoZWV0KGlkLCBwYXJlbnQsIG9wdGlvbnMpIHtcbiAgICAgICAgbGV0IHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcbiAgICAgICAgY29uc3Qgbm9uY2UgPSBvcHRpb25zPy5ub25jZTtcbiAgICAgICAgaWYgKG5vbmNlKVxuICAgICAgICAgICAgc3R5bGUubm9uY2UgPSBub25jZTtcbiAgICAgICAgc3R5bGUuc2V0QXR0cmlidXRlKCd0eXBlJywgJ3RleHQvY3NzJyk7XG4gICAgICAgIHN0eWxlLnNldEF0dHJpYnV0ZSgnZ3Mtc3R5bGUtaWQnLCBpZCk7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgIGlmIChzdHlsZS5zdHlsZVNoZWV0KSB7IC8vIFRPRE86IG9ubHkgQ1NTSW1wb3J0UnVsZSBoYXZlIHRoYXQgYW5kIGRpZmZlcmVudCBiZWFzdCA/P1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgICAgIHN0eWxlLnN0eWxlU2hlZXQuY3NzVGV4dCA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc3R5bGUuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJycpKTsgLy8gV2ViS2l0IGhhY2tcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXBhcmVudCkge1xuICAgICAgICAgICAgLy8gZGVmYXVsdCB0byBoZWFkXG4gICAgICAgICAgICBwYXJlbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaGVhZCcpWzBdO1xuICAgICAgICAgICAgcGFyZW50LmFwcGVuZENoaWxkKHN0eWxlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHBhcmVudC5pbnNlcnRCZWZvcmUoc3R5bGUsIHBhcmVudC5maXJzdENoaWxkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3R5bGUuc2hlZXQ7XG4gICAgfVxuICAgIC8qKiByZW1vdmVkIHRoZSBnaXZlbiBzdHlsZXNoZWV0IGlkICovXG4gICAgc3RhdGljIHJlbW92ZVN0eWxlc2hlZXQoaWQsIHBhcmVudCkge1xuICAgICAgICBjb25zdCB0YXJnZXQgPSBwYXJlbnQgfHwgZG9jdW1lbnQ7XG4gICAgICAgIGxldCBlbCA9IHRhcmdldC5xdWVyeVNlbGVjdG9yKCdTVFlMRVtncy1zdHlsZS1pZD0nICsgaWQgKyAnXScpO1xuICAgICAgICBpZiAoZWwgJiYgZWwucGFyZW50Tm9kZSlcbiAgICAgICAgICAgIGVsLnJlbW92ZSgpO1xuICAgIH1cbiAgICAvKiogaW5zZXJ0cyBhIENTUyBydWxlICovXG4gICAgc3RhdGljIGFkZENTU1J1bGUoc2hlZXQsIHNlbGVjdG9yLCBydWxlcykge1xuICAgICAgICBpZiAodHlwZW9mIHNoZWV0LmFkZFJ1bGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHNoZWV0LmFkZFJ1bGUoc2VsZWN0b3IsIHJ1bGVzKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2Ygc2hlZXQuaW5zZXJ0UnVsZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgc2hlZXQuaW5zZXJ0UnVsZShgJHtzZWxlY3Rvcn17JHtydWxlc319YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICBzdGF0aWMgdG9Cb29sKHYpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB2ID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgIHJldHVybiB2O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgdiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHYgPSB2LnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICByZXR1cm4gISh2ID09PSAnJyB8fCB2ID09PSAnbm8nIHx8IHYgPT09ICdmYWxzZScgfHwgdiA9PT0gJzAnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gQm9vbGVhbih2KTtcbiAgICB9XG4gICAgc3RhdGljIHRvTnVtYmVyKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUubGVuZ3RoID09PSAwKSA/IHVuZGVmaW5lZCA6IE51bWJlcih2YWx1ZSk7XG4gICAgfVxuICAgIHN0YXRpYyBwYXJzZUhlaWdodCh2YWwpIHtcbiAgICAgICAgbGV0IGg7XG4gICAgICAgIGxldCB1bml0ID0gJ3B4JztcbiAgICAgICAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAodmFsID09PSAnYXV0bycgfHwgdmFsID09PSAnJylcbiAgICAgICAgICAgICAgICBoID0gMDtcbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGxldCBtYXRjaCA9IHZhbC5tYXRjaCgvXigtWzAtOV0rXFwuWzAtOV0rfFswLTldKlxcLlswLTldK3wtWzAtOV0rfFswLTldKykocHh8ZW18cmVtfHZofHZ3fCV8Y218bW0pPyQvKTtcbiAgICAgICAgICAgICAgICBpZiAoIW1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBoZWlnaHQgdmFsID0gJHt2YWx9YCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHVuaXQgPSBtYXRjaFsyXSB8fCAncHgnO1xuICAgICAgICAgICAgICAgIGggPSBwYXJzZUZsb2F0KG1hdGNoWzFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGggPSB2YWw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgaCwgdW5pdCB9O1xuICAgIH1cbiAgICAvKiogY29waWVzIHVuc2V0IGZpZWxkcyBpbiB0YXJnZXQgdG8gdXNlIHRoZSBnaXZlbiBkZWZhdWx0IHNvdXJjZXMgdmFsdWVzICovXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgc3RhdGljIGRlZmF1bHRzKHRhcmdldCwgLi4uc291cmNlcykge1xuICAgICAgICBzb3VyY2VzLmZvckVhY2goc291cmNlID0+IHtcbiAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIHNvdXJjZSkge1xuICAgICAgICAgICAgICAgIGlmICghc291cmNlLmhhc093blByb3BlcnR5KGtleSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICBpZiAodGFyZ2V0W2tleV0gPT09IG51bGwgfHwgdGFyZ2V0W2tleV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXRba2V5XSA9IHNvdXJjZVtrZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygc291cmNlW2tleV0gPT09ICdvYmplY3QnICYmIHR5cGVvZiB0YXJnZXRba2V5XSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gcHJvcGVydHkgaXMgYW4gb2JqZWN0LCByZWN1cnNpdmVseSBhZGQgaXQncyBmaWVsZCBvdmVyLi4uICMxMzczXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGVmYXVsdHModGFyZ2V0W2tleV0sIHNvdXJjZVtrZXldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgIH1cbiAgICAvKiogZ2l2ZW4gMiBvYmplY3RzIHJldHVybiB0cnVlIGlmIHRoZXkgaGF2ZSB0aGUgc2FtZSB2YWx1ZXMuIENoZWNrcyBmb3IgT2JqZWN0IHt9IGhhdmluZyBzYW1lIGZpZWxkcyBhbmQgdmFsdWVzIChqdXN0IDEgbGV2ZWwgZG93bikgKi9cbiAgICBzdGF0aWMgc2FtZShhLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYSAhPT0gJ29iamVjdCcpXG4gICAgICAgICAgICByZXR1cm4gYSA9PSBiO1xuICAgICAgICBpZiAodHlwZW9mIGEgIT09IHR5cGVvZiBiKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAvLyBlbHNlIHdlIGhhdmUgb2JqZWN0LCBjaGVjayBqdXN0IDEgbGV2ZWwgZGVlcCBmb3IgYmVpbmcgc2FtZSB0aGluZ3MuLi5cbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKGEpLmxlbmd0aCAhPT0gT2JqZWN0LmtleXMoYikubGVuZ3RoKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBhKSB7XG4gICAgICAgICAgICBpZiAoYVtrZXldICE9PSBiW2tleV0pXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICAvKiogY29waWVzIG92ZXIgYiBzaXplICYgcG9zaXRpb24gKEdyaWRTdGFja1Bvc2l0aW9uKSwgYW5kIG9wdGlvbmFsbHkgbWluL21heCBhcyB3ZWxsICovXG4gICAgc3RhdGljIGNvcHlQb3MoYSwgYiwgZG9NaW5NYXggPSBmYWxzZSkge1xuICAgICAgICBpZiAoYi54ICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICBhLnggPSBiLng7XG4gICAgICAgIGlmIChiLnkgIT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIGEueSA9IGIueTtcbiAgICAgICAgaWYgKGIudyAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgYS53ID0gYi53O1xuICAgICAgICBpZiAoYi5oICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICBhLmggPSBiLmg7XG4gICAgICAgIGlmIChkb01pbk1heCkge1xuICAgICAgICAgICAgaWYgKGIubWluVylcbiAgICAgICAgICAgICAgICBhLm1pblcgPSBiLm1pblc7XG4gICAgICAgICAgICBpZiAoYi5taW5IKVxuICAgICAgICAgICAgICAgIGEubWluSCA9IGIubWluSDtcbiAgICAgICAgICAgIGlmIChiLm1heFcpXG4gICAgICAgICAgICAgICAgYS5tYXhXID0gYi5tYXhXO1xuICAgICAgICAgICAgaWYgKGIubWF4SClcbiAgICAgICAgICAgICAgICBhLm1heEggPSBiLm1heEg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfVxuICAgIC8qKiB0cnVlIGlmIGEgYW5kIGIgaGFzIHNhbWUgc2l6ZSAmIHBvc2l0aW9uICovXG4gICAgc3RhdGljIHNhbWVQb3MoYSwgYikge1xuICAgICAgICByZXR1cm4gYSAmJiBiICYmIGEueCA9PT0gYi54ICYmIGEueSA9PT0gYi55ICYmIChhLncgfHwgMSkgPT09IChiLncgfHwgMSkgJiYgKGEuaCB8fCAxKSA9PT0gKGIuaCB8fCAxKTtcbiAgICB9XG4gICAgLyoqIGdpdmVuIGEgbm9kZSwgbWFrZXMgc3VyZSBpdCdzIG1pbi9tYXggYXJlIHZhbGlkICovXG4gICAgc3RhdGljIHNhbml0aXplTWluTWF4KG5vZGUpIHtcbiAgICAgICAgLy8gcmVtb3ZlIDAsIHVuZGVmaW5lLCBudWxsXG4gICAgICAgIGlmICghbm9kZS5taW5XKSB7XG4gICAgICAgICAgICBkZWxldGUgbm9kZS5taW5XO1xuICAgICAgICB9XG4gICAgICAgIGlmICghbm9kZS5taW5IKSB7XG4gICAgICAgICAgICBkZWxldGUgbm9kZS5taW5IO1xuICAgICAgICB9XG4gICAgICAgIGlmICghbm9kZS5tYXhXKSB7XG4gICAgICAgICAgICBkZWxldGUgbm9kZS5tYXhXO1xuICAgICAgICB9XG4gICAgICAgIGlmICghbm9kZS5tYXhIKSB7XG4gICAgICAgICAgICBkZWxldGUgbm9kZS5tYXhIO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKiByZW1vdmVzIGZpZWxkIGZyb20gdGhlIGZpcnN0IG9iamVjdCBpZiBzYW1lIGFzIHRoZSBzZWNvbmQgb2JqZWN0cyAobGlrZSBkaWZmaW5nKSBhbmQgaW50ZXJuYWwgJ18nIGZvciBzYXZpbmcgKi9cbiAgICBzdGF0aWMgcmVtb3ZlSW50ZXJuYWxBbmRTYW1lKGEsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBhICE9PSAnb2JqZWN0JyB8fCB0eXBlb2YgYiAhPT0gJ29iamVjdCcpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGZvciAobGV0IGtleSBpbiBhKSB7XG4gICAgICAgICAgICBsZXQgdmFsID0gYVtrZXldO1xuICAgICAgICAgICAgaWYgKGtleVswXSA9PT0gJ18nIHx8IHZhbCA9PT0gYltrZXldKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGFba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiBiW2tleV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgaW4gdmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWxbaV0gPT09IGJba2V5XVtpXSB8fCBpWzBdID09PSAnXycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB2YWxbaV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFPYmplY3Qua2V5cyh2YWwpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgYVtrZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvKiogcmVtb3ZlcyBpbnRlcm5hbCBmaWVsZHMgJ18nIGFuZCBkZWZhdWx0IHZhbHVlcyBmb3Igc2F2aW5nICovXG4gICAgc3RhdGljIHJlbW92ZUludGVybmFsRm9yU2F2ZShuLCByZW1vdmVFbCA9IHRydWUpIHtcbiAgICAgICAgZm9yIChsZXQga2V5IGluIG4pIHtcbiAgICAgICAgICAgIGlmIChrZXlbMF0gPT09ICdfJyB8fCBuW2tleV0gPT09IG51bGwgfHwgbltrZXldID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICAgICAgZGVsZXRlIG5ba2V5XTtcbiAgICAgICAgfVxuICAgICAgICBkZWxldGUgbi5ncmlkO1xuICAgICAgICBpZiAocmVtb3ZlRWwpXG4gICAgICAgICAgICBkZWxldGUgbi5lbDtcbiAgICAgICAgLy8gZGVsZXRlIGRlZmF1bHQgdmFsdWVzICh3aWxsIGJlIHJlLWNyZWF0ZWQgb24gcmVhZClcbiAgICAgICAgaWYgKCFuLmF1dG9Qb3NpdGlvbilcbiAgICAgICAgICAgIGRlbGV0ZSBuLmF1dG9Qb3NpdGlvbjtcbiAgICAgICAgaWYgKCFuLm5vUmVzaXplKVxuICAgICAgICAgICAgZGVsZXRlIG4ubm9SZXNpemU7XG4gICAgICAgIGlmICghbi5ub01vdmUpXG4gICAgICAgICAgICBkZWxldGUgbi5ub01vdmU7XG4gICAgICAgIGlmICghbi5sb2NrZWQpXG4gICAgICAgICAgICBkZWxldGUgbi5sb2NrZWQ7XG4gICAgICAgIGlmIChuLncgPT09IDEgfHwgbi53ID09PSBuLm1pblcpXG4gICAgICAgICAgICBkZWxldGUgbi53O1xuICAgICAgICBpZiAobi5oID09PSAxIHx8IG4uaCA9PT0gbi5taW5IKVxuICAgICAgICAgICAgZGVsZXRlIG4uaDtcbiAgICB9XG4gICAgLyoqIHJldHVybiB0aGUgY2xvc2VzdCBwYXJlbnQgKG9yIGl0c2VsZikgbWF0Y2hpbmcgdGhlIGdpdmVuIGNsYXNzICovXG4gICAgLy8gc3RhdGljIGNsb3Nlc3RVcEJ5Q2xhc3MoZWw6IEhUTUxFbGVtZW50LCBuYW1lOiBzdHJpbmcpOiBIVE1MRWxlbWVudCB7XG4gICAgLy8gICB3aGlsZSAoZWwpIHtcbiAgICAvLyAgICAgaWYgKGVsLmNsYXNzTGlzdC5jb250YWlucyhuYW1lKSkgcmV0dXJuIGVsO1xuICAgIC8vICAgICBlbCA9IGVsLnBhcmVudEVsZW1lbnRcbiAgICAvLyAgIH1cbiAgICAvLyAgIHJldHVybiBudWxsO1xuICAgIC8vIH1cbiAgICAvKiogZGVsYXkgY2FsbGluZyB0aGUgZ2l2ZW4gZnVuY3Rpb24gZm9yIGdpdmVuIGRlbGF5LCBwcmV2ZW50aW5nIG5ldyBjYWxscyBmcm9tIGhhcHBlbmluZyB3aGlsZSB3YWl0aW5nICovXG4gICAgc3RhdGljIHRocm90dGxlKGZ1bmMsIGRlbGF5KSB7XG4gICAgICAgIGxldCBpc1dhaXRpbmcgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuICguLi5hcmdzKSA9PiB7XG4gICAgICAgICAgICBpZiAoIWlzV2FpdGluZykge1xuICAgICAgICAgICAgICAgIGlzV2FpdGluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7IGZ1bmMoLi4uYXJncyk7IGlzV2FpdGluZyA9IGZhbHNlOyB9LCBkZWxheSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuICAgIHN0YXRpYyByZW1vdmVQb3NpdGlvbmluZ1N0eWxlcyhlbCkge1xuICAgICAgICBsZXQgc3R5bGUgPSBlbC5zdHlsZTtcbiAgICAgICAgaWYgKHN0eWxlLnBvc2l0aW9uKSB7XG4gICAgICAgICAgICBzdHlsZS5yZW1vdmVQcm9wZXJ0eSgncG9zaXRpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc3R5bGUubGVmdCkge1xuICAgICAgICAgICAgc3R5bGUucmVtb3ZlUHJvcGVydHkoJ2xlZnQnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc3R5bGUudG9wKSB7XG4gICAgICAgICAgICBzdHlsZS5yZW1vdmVQcm9wZXJ0eSgndG9wJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0eWxlLndpZHRoKSB7XG4gICAgICAgICAgICBzdHlsZS5yZW1vdmVQcm9wZXJ0eSgnd2lkdGgnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc3R5bGUuaGVpZ2h0KSB7XG4gICAgICAgICAgICBzdHlsZS5yZW1vdmVQcm9wZXJ0eSgnaGVpZ2h0Jyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqIEBpbnRlcm5hbCByZXR1cm5zIHRoZSBwYXNzZWQgZWxlbWVudCBpZiBzY3JvbGxhYmxlLCBlbHNlIHRoZSBjbG9zZXN0IHBhcmVudCB0aGF0IHdpbGwsIHVwIHRvIHRoZSBlbnRpcmUgZG9jdW1lbnQgc2Nyb2xsaW5nIGVsZW1lbnQgKi9cbiAgICBzdGF0aWMgZ2V0U2Nyb2xsRWxlbWVudChlbCkge1xuICAgICAgICBpZiAoIWVsKVxuICAgICAgICAgICAgcmV0dXJuIGRvY3VtZW50LnNjcm9sbGluZ0VsZW1lbnQgfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50OyAvLyBJRSBzdXBwb3J0XG4gICAgICAgIGNvbnN0IHN0eWxlID0gZ2V0Q29tcHV0ZWRTdHlsZShlbCk7XG4gICAgICAgIGNvbnN0IG92ZXJmbG93UmVnZXggPSAvKGF1dG98c2Nyb2xsKS87XG4gICAgICAgIGlmIChvdmVyZmxvd1JlZ2V4LnRlc3Qoc3R5bGUub3ZlcmZsb3cgKyBzdHlsZS5vdmVyZmxvd1kpKSB7XG4gICAgICAgICAgICByZXR1cm4gZWw7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRTY3JvbGxFbGVtZW50KGVsLnBhcmVudEVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBzdGF0aWMgdXBkYXRlU2Nyb2xsUG9zaXRpb24oZWwsIHBvc2l0aW9uLCBkaXN0YW5jZSkge1xuICAgICAgICAvLyBpcyB3aWRnZXQgaW4gdmlldz9cbiAgICAgICAgbGV0IHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgbGV0IGlubmVySGVpZ2h0T3JDbGllbnRIZWlnaHQgPSAod2luZG93LmlubmVySGVpZ2h0IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQpO1xuICAgICAgICBpZiAocmVjdC50b3AgPCAwIHx8XG4gICAgICAgICAgICByZWN0LmJvdHRvbSA+IGlubmVySGVpZ2h0T3JDbGllbnRIZWlnaHQpIHtcbiAgICAgICAgICAgIC8vIHNldCBzY3JvbGxUb3Agb2YgZmlyc3QgcGFyZW50IHRoYXQgc2Nyb2xsc1xuICAgICAgICAgICAgLy8gaWYgcGFyZW50IGlzIGxhcmdlciB0aGFuIGVsLCBzZXQgYXMgbG93IGFzIHBvc3NpYmxlXG4gICAgICAgICAgICAvLyB0byBnZXQgZW50aXJlIHdpZGdldCBvbiBzY3JlZW5cbiAgICAgICAgICAgIGxldCBvZmZzZXREaWZmRG93biA9IHJlY3QuYm90dG9tIC0gaW5uZXJIZWlnaHRPckNsaWVudEhlaWdodDtcbiAgICAgICAgICAgIGxldCBvZmZzZXREaWZmVXAgPSByZWN0LnRvcDtcbiAgICAgICAgICAgIGxldCBzY3JvbGxFbCA9IHRoaXMuZ2V0U2Nyb2xsRWxlbWVudChlbCk7XG4gICAgICAgICAgICBpZiAoc2Nyb2xsRWwgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBsZXQgcHJldlNjcm9sbCA9IHNjcm9sbEVsLnNjcm9sbFRvcDtcbiAgICAgICAgICAgICAgICBpZiAocmVjdC50b3AgPCAwICYmIGRpc3RhbmNlIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBtb3ZpbmcgdXBcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVsLm9mZnNldEhlaWdodCA+IGlubmVySGVpZ2h0T3JDbGllbnRIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbEVsLnNjcm9sbFRvcCArPSBkaXN0YW5jZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbEVsLnNjcm9sbFRvcCArPSBNYXRoLmFicyhvZmZzZXREaWZmVXApID4gTWF0aC5hYnMoZGlzdGFuY2UpID8gZGlzdGFuY2UgOiBvZmZzZXREaWZmVXA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZGlzdGFuY2UgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIG1vdmluZyBkb3duXG4gICAgICAgICAgICAgICAgICAgIGlmIChlbC5vZmZzZXRIZWlnaHQgPiBpbm5lckhlaWdodE9yQ2xpZW50SGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzY3JvbGxFbC5zY3JvbGxUb3AgKz0gZGlzdGFuY2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzY3JvbGxFbC5zY3JvbGxUb3AgKz0gb2Zmc2V0RGlmZkRvd24gPiBkaXN0YW5jZSA/IGRpc3RhbmNlIDogb2Zmc2V0RGlmZkRvd247XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gbW92ZSB3aWRnZXQgeSBieSBhbW91bnQgc2Nyb2xsZWRcbiAgICAgICAgICAgICAgICBwb3NpdGlvbi50b3AgKz0gc2Nyb2xsRWwuc2Nyb2xsVG9wIC0gcHJldlNjcm9sbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWwgRnVuY3Rpb24gdXNlZCB0byBzY3JvbGwgdGhlIHBhZ2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZXZlbnQgYE1vdXNlRXZlbnRgIHRoYXQgdHJpZ2dlcnMgdGhlIHJlc2l6ZVxuICAgICAqIEBwYXJhbSBlbCBgSFRNTEVsZW1lbnRgIHRoYXQncyBiZWluZyByZXNpemVkXG4gICAgICogQHBhcmFtIGRpc3RhbmNlIERpc3RhbmNlIGZyb20gdGhlIFYgZWRnZXMgdG8gc3RhcnQgc2Nyb2xsaW5nXG4gICAgICovXG4gICAgc3RhdGljIHVwZGF0ZVNjcm9sbFJlc2l6ZShldmVudCwgZWwsIGRpc3RhbmNlKSB7XG4gICAgICAgIGNvbnN0IHNjcm9sbEVsID0gdGhpcy5nZXRTY3JvbGxFbGVtZW50KGVsKTtcbiAgICAgICAgY29uc3QgaGVpZ2h0ID0gc2Nyb2xsRWwuY2xpZW50SGVpZ2h0O1xuICAgICAgICAvLyAjMTcyNyBldmVudC5jbGllbnRZIGlzIHJlbGF0aXZlIHRvIHZpZXdwb3J0LCBzbyBtdXN0IGNvbXBhcmUgdGhpcyBhZ2FpbnN0IHBvc2l0aW9uIG9mIHNjcm9sbEVsIGdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcFxuICAgICAgICAvLyAjMTc0NSBTcGVjaWFsIHNpdHVhdGlvbiBpZiBzY3JvbGxFbCBpcyBkb2N1bWVudCAnaHRtbCc6IGhlcmUgYnJvd3NlciBzcGVjIHN0YXRlcyB0aGF0XG4gICAgICAgIC8vIGNsaWVudEhlaWdodCBpcyBoZWlnaHQgb2Ygdmlld3BvcnQsIGJ1dCBnZXRCb3VuZGluZ0NsaWVudFJlY3QoKSBpcyByZWN0YW5nbGUgb2YgaHRtbCBlbGVtZW50O1xuICAgICAgICAvLyB0aGlzIGRpc2NyZXBhbmN5IGFyaXNlcyBiZWNhdXNlIGluIHJlYWxpdHkgc2Nyb2xsYmFyIGlzIGF0dGFjaGVkIHRvIHZpZXdwb3J0LCBub3QgaHRtbCBlbGVtZW50IGl0c2VsZi5cbiAgICAgICAgY29uc3Qgb2Zmc2V0VG9wID0gKHNjcm9sbEVsID09PSB0aGlzLmdldFNjcm9sbEVsZW1lbnQoKSkgPyAwIDogc2Nyb2xsRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wO1xuICAgICAgICBjb25zdCBwb2ludGVyUG9zWSA9IGV2ZW50LmNsaWVudFkgLSBvZmZzZXRUb3A7XG4gICAgICAgIGNvbnN0IHRvcCA9IHBvaW50ZXJQb3NZIDwgZGlzdGFuY2U7XG4gICAgICAgIGNvbnN0IGJvdHRvbSA9IHBvaW50ZXJQb3NZID4gaGVpZ2h0IC0gZGlzdGFuY2U7XG4gICAgICAgIGlmICh0b3ApIHtcbiAgICAgICAgICAgIC8vIFRoaXMgYWxzbyBjYW4gYmUgZG9uZSB3aXRoIGEgdGltZW91dCB0byBrZWVwIHNjcm9sbGluZyB3aGlsZSB0aGUgbW91c2UgaXNcbiAgICAgICAgICAgIC8vIGluIHRoZSBzY3JvbGxpbmcgem9uZS4gKHdpbGwgaGF2ZSBzbW9vdGhlciBiZWhhdmlvcilcbiAgICAgICAgICAgIHNjcm9sbEVsLnNjcm9sbEJ5KHsgYmVoYXZpb3I6ICdzbW9vdGgnLCB0b3A6IHBvaW50ZXJQb3NZIC0gZGlzdGFuY2UgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoYm90dG9tKSB7XG4gICAgICAgICAgICBzY3JvbGxFbC5zY3JvbGxCeSh7IGJlaGF2aW9yOiAnc21vb3RoJywgdG9wOiBkaXN0YW5jZSAtIChoZWlnaHQgLSBwb2ludGVyUG9zWSkgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqIHNpbmdsZSBsZXZlbCBjbG9uZSwgcmV0dXJuaW5nIGEgbmV3IG9iamVjdCB3aXRoIHNhbWUgdG9wIGZpZWxkcy4gVGhpcyB3aWxsIHNoYXJlIHN1YiBvYmplY3RzIGFuZCBhcnJheXMgKi9cbiAgICBzdGF0aWMgY2xvbmUob2JqKSB7XG4gICAgICAgIGlmIChvYmogPT09IG51bGwgfHwgb2JqID09PSB1bmRlZmluZWQgfHwgdHlwZW9mIChvYmopICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgfVxuICAgICAgICAvLyByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgb2JqKTtcbiAgICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAgICAgcmV0dXJuIFsuLi5vYmpdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IC4uLm9iaiB9O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWN1cnNpdmUgY2xvbmUgdmVyc2lvbiB0aGF0IHJldHVybnMgYSBmdWxsIGNvcHksIGNoZWNraW5nIGZvciBuZXN0ZWQgb2JqZWN0cyBhbmQgYXJyYXlzIE9OTFkuXG4gICAgICogTm90ZTogdGhpcyB3aWxsIHVzZSBhcy1pcyBhbnkga2V5IHN0YXJ0aW5nIHdpdGggZG91YmxlIF9fIChhbmQgbm90IGNvcHkgaW5zaWRlKSBzb21lIGxpYiBoYXZlIGNpcmN1bGFyIGRlcGVuZGVuY2llcy5cbiAgICAgKi9cbiAgICBzdGF0aWMgY2xvbmVEZWVwKG9iaikge1xuICAgICAgICAvLyBsaXN0IG9mIGZpZWxkcyB3ZSB3aWxsIHNraXAgZHVyaW5nIGNsb25lRGVlcCAobmVzdGVkIG9iamVjdHMsIG90aGVyIGludGVybmFsKVxuICAgICAgICBjb25zdCBza2lwRmllbGRzID0gWydwYXJlbnRHcmlkJywgJ2VsJywgJ2dyaWQnLCAnc3ViR3JpZCcsICdlbmdpbmUnXTtcbiAgICAgICAgLy8gcmV0dXJuIEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkob2JqKSk7IC8vIGRvZXNuJ3Qgd29yayB3aXRoIGRhdGUgZm9ybWF0ID9cbiAgICAgICAgY29uc3QgcmV0ID0gVXRpbHMuY2xvbmUob2JqKTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gcmV0KSB7XG4gICAgICAgICAgICAvLyBOT1RFOiB3ZSBkb24ndCBzdXBwb3J0IGZ1bmN0aW9uL2NpcmN1bGFyIGRlcGVuZGVuY2llcyBzbyBza2lwIHRob3NlIHByb3BlcnRpZXMgZm9yIG5vdy4uLlxuICAgICAgICAgICAgaWYgKHJldC5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIHR5cGVvZiAocmV0W2tleV0pID09PSAnb2JqZWN0JyAmJiBrZXkuc3Vic3RyaW5nKDAsIDIpICE9PSAnX18nICYmICFza2lwRmllbGRzLmZpbmQoayA9PiBrID09PSBrZXkpKSB7XG4gICAgICAgICAgICAgICAgcmV0W2tleV0gPSBVdGlscy5jbG9uZURlZXAob2JqW2tleV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgfVxuICAgIC8qKiBkZWVwIGNsb25lIHRoZSBnaXZlbiBIVE1MIG5vZGUsIHJlbW92aW5nIHRlaCB1bmlxdWUgaWQgZmllbGQgKi9cbiAgICBzdGF0aWMgY2xvbmVOb2RlKGVsKSB7XG4gICAgICAgIGNvbnN0IG5vZGUgPSBlbC5jbG9uZU5vZGUodHJ1ZSk7XG4gICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKCdpZCcpO1xuICAgICAgICByZXR1cm4gbm9kZTtcbiAgICB9XG4gICAgc3RhdGljIGFwcGVuZFRvKGVsLCBwYXJlbnQpIHtcbiAgICAgICAgbGV0IHBhcmVudE5vZGU7XG4gICAgICAgIGlmICh0eXBlb2YgcGFyZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcGFyZW50Tm9kZSA9IFV0aWxzLmdldEVsZW1lbnQocGFyZW50KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHBhcmVudE5vZGUgPSBwYXJlbnQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIHB1YmxpYyBzdGF0aWMgc2V0UG9zaXRpb25SZWxhdGl2ZShlbDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcbiAgICAvLyAgIGlmICghKC9eKD86cnxhfGYpLykudGVzdChnZXRDb21wdXRlZFN0eWxlKGVsKS5wb3NpdGlvbikpIHtcbiAgICAvLyAgICAgZWwuc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG4gICAgLy8gICB9XG4gICAgLy8gfVxuICAgIHN0YXRpYyBhZGRFbFN0eWxlcyhlbCwgc3R5bGVzKSB7XG4gICAgICAgIGlmIChzdHlsZXMgaW5zdGFuY2VvZiBPYmplY3QpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcyBpbiBzdHlsZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoc3R5bGVzLmhhc093blByb3BlcnR5KHMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHN0eWxlc1tzXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgZmFsbGJhY2sgdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlc1tzXS5mb3JFYWNoKHZhbCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuc3R5bGVbc10gPSB2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsLnN0eWxlW3NdID0gc3R5bGVzW3NdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHN0YXRpYyBpbml0RXZlbnQoZSwgaW5mbykge1xuICAgICAgICBjb25zdCBldnQgPSB7IHR5cGU6IGluZm8udHlwZSB9O1xuICAgICAgICBjb25zdCBvYmogPSB7XG4gICAgICAgICAgICBidXR0b246IDAsXG4gICAgICAgICAgICB3aGljaDogMCxcbiAgICAgICAgICAgIGJ1dHRvbnM6IDEsXG4gICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIHRhcmdldDogaW5mby50YXJnZXQgPyBpbmZvLnRhcmdldCA6IGUudGFyZ2V0XG4gICAgICAgIH07XG4gICAgICAgIC8vIGRvbid0IGNoZWNrIGZvciBgaW5zdGFuY2VvZiBEcmFnRXZlbnRgIGFzIFNhZmFyaSB1c2UgTW91c2VFdmVudCAjMTU0MFxuICAgICAgICBpZiAoZS5kYXRhVHJhbnNmZXIpIHtcbiAgICAgICAgICAgIGV2dFsnZGF0YVRyYW5zZmVyJ10gPSBlLmRhdGFUcmFuc2ZlcjsgLy8gd29ya2Fyb3VuZCAncmVhZG9ubHknIGZpZWxkLlxuICAgICAgICB9XG4gICAgICAgIFsnYWx0S2V5JywgJ2N0cmxLZXknLCAnbWV0YUtleScsICdzaGlmdEtleSddLmZvckVhY2gocCA9PiBldnRbcF0gPSBlW3BdKTsgLy8ga2V5c1xuICAgICAgICBbJ3BhZ2VYJywgJ3BhZ2VZJywgJ2NsaWVudFgnLCAnY2xpZW50WScsICdzY3JlZW5YJywgJ3NjcmVlblknXS5mb3JFYWNoKHAgPT4gZXZ0W3BdID0gZVtwXSk7IC8vIHBvaW50IGluZm9cbiAgICAgICAgcmV0dXJuIHsgLi4uZXZ0LCAuLi5vYmogfTtcbiAgICB9XG4gICAgLyoqIGNvcGllcyB0aGUgTW91c2VFdmVudCBwcm9wZXJ0aWVzIGFuZCBzZW5kcyBpdCBhcyBhbm90aGVyIGV2ZW50IHRvIHRoZSBnaXZlbiB0YXJnZXQgKi9cbiAgICBzdGF0aWMgc2ltdWxhdGVNb3VzZUV2ZW50KGUsIHNpbXVsYXRlZFR5cGUsIHRhcmdldCkge1xuICAgICAgICBjb25zdCBzaW11bGF0ZWRFdmVudCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdNb3VzZUV2ZW50cycpO1xuICAgICAgICBzaW11bGF0ZWRFdmVudC5pbml0TW91c2VFdmVudChzaW11bGF0ZWRUeXBlLCAvLyB0eXBlXG4gICAgICAgIHRydWUsIC8vIGJ1YmJsZXNcbiAgICAgICAgdHJ1ZSwgLy8gY2FuY2VsYWJsZVxuICAgICAgICB3aW5kb3csIC8vIHZpZXdcbiAgICAgICAgMSwgLy8gZGV0YWlsXG4gICAgICAgIGUuc2NyZWVuWCwgLy8gc2NyZWVuWFxuICAgICAgICBlLnNjcmVlblksIC8vIHNjcmVlbllcbiAgICAgICAgZS5jbGllbnRYLCAvLyBjbGllbnRYXG4gICAgICAgIGUuY2xpZW50WSwgLy8gY2xpZW50WVxuICAgICAgICBlLmN0cmxLZXksIC8vIGN0cmxLZXlcbiAgICAgICAgZS5hbHRLZXksIC8vIGFsdEtleVxuICAgICAgICBlLnNoaWZ0S2V5LCAvLyBzaGlmdEtleVxuICAgICAgICBlLm1ldGFLZXksIC8vIG1ldGFLZXlcbiAgICAgICAgMCwgLy8gYnV0dG9uXG4gICAgICAgIGUudGFyZ2V0IC8vIHJlbGF0ZWRUYXJnZXRcbiAgICAgICAgKTtcbiAgICAgICAgKHRhcmdldCB8fCBlLnRhcmdldCkuZGlzcGF0Y2hFdmVudChzaW11bGF0ZWRFdmVudCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIGRlZmluZXMgYW4gZWxlbWVudCB0aGF0IGlzIHVzZWQgdG8gZ2V0IHRoZSBvZmZzZXQgYW5kIHNjYWxlIGZyb20gZ3JpZCB0cmFuc2Zvcm1zXG4gICAgICogcmV0dXJucyB0aGUgc2NhbGUgYW5kIG9mZnNldHMgZnJvbSBzYWlkIGVsZW1lbnRcbiAgICAqL1xuICAgIHN0YXRpYyBnZXRWYWx1ZXNGcm9tVHJhbnNmb3JtZWRFbGVtZW50KHBhcmVudCkge1xuICAgICAgICBjb25zdCB0cmFuc2Zvcm1SZWZlcmVuY2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgVXRpbHMuYWRkRWxTdHlsZXModHJhbnNmb3JtUmVmZXJlbmNlLCB7XG4gICAgICAgICAgICBvcGFjaXR5OiAnMCcsXG4gICAgICAgICAgICBwb3NpdGlvbjogJ2ZpeGVkJyxcbiAgICAgICAgICAgIHRvcDogMCArICdweCcsXG4gICAgICAgICAgICBsZWZ0OiAwICsgJ3B4JyxcbiAgICAgICAgICAgIHdpZHRoOiAnMXB4JyxcbiAgICAgICAgICAgIGhlaWdodDogJzFweCcsXG4gICAgICAgICAgICB6SW5kZXg6ICctOTk5OTk5JyxcbiAgICAgICAgfSk7XG4gICAgICAgIHBhcmVudC5hcHBlbmRDaGlsZCh0cmFuc2Zvcm1SZWZlcmVuY2UpO1xuICAgICAgICBjb25zdCB0cmFuc2Zvcm1WYWx1ZXMgPSB0cmFuc2Zvcm1SZWZlcmVuY2UuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHBhcmVudC5yZW1vdmVDaGlsZCh0cmFuc2Zvcm1SZWZlcmVuY2UpO1xuICAgICAgICB0cmFuc2Zvcm1SZWZlcmVuY2UucmVtb3ZlKCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4U2NhbGU6IDEgLyB0cmFuc2Zvcm1WYWx1ZXMud2lkdGgsXG4gICAgICAgICAgICB5U2NhbGU6IDEgLyB0cmFuc2Zvcm1WYWx1ZXMuaGVpZ2h0LFxuICAgICAgICAgICAgeE9mZnNldDogdHJhbnNmb3JtVmFsdWVzLmxlZnQsXG4gICAgICAgICAgICB5T2Zmc2V0OiB0cmFuc2Zvcm1WYWx1ZXMudG9wLFxuICAgICAgICB9O1xuICAgIH1cbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXV0aWxzLmpzLm1hcCIsIlxuICAgICAgaW1wb3J0IEFQSSBmcm9tIFwiIS4uLy4uL3N0eWxlLWxvYWRlci9kaXN0L3J1bnRpbWUvaW5qZWN0U3R5bGVzSW50b1N0eWxlVGFnLmpzXCI7XG4gICAgICBpbXBvcnQgZG9tQVBJIGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9zdHlsZURvbUFQSS5qc1wiO1xuICAgICAgaW1wb3J0IGluc2VydEZuIGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9pbnNlcnRCeVNlbGVjdG9yLmpzXCI7XG4gICAgICBpbXBvcnQgc2V0QXR0cmlidXRlcyBmcm9tIFwiIS4uLy4uL3N0eWxlLWxvYWRlci9kaXN0L3J1bnRpbWUvc2V0QXR0cmlidXRlc1dpdGhvdXRBdHRyaWJ1dGVzLmpzXCI7XG4gICAgICBpbXBvcnQgaW5zZXJ0U3R5bGVFbGVtZW50IGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9pbnNlcnRTdHlsZUVsZW1lbnQuanNcIjtcbiAgICAgIGltcG9ydCBzdHlsZVRhZ1RyYW5zZm9ybUZuIGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9zdHlsZVRhZ1RyYW5zZm9ybS5qc1wiO1xuICAgICAgaW1wb3J0IGNvbnRlbnQsICogYXMgbmFtZWRFeHBvcnQgZnJvbSBcIiEhLi4vLi4vY3NzLWxvYWRlci9kaXN0L2Nqcy5qcyEuL2dyaWRzdGFjay1leHRyYS5taW4uY3NzXCI7XG4gICAgICBcbiAgICAgIFxuXG52YXIgb3B0aW9ucyA9IHt9O1xuXG5vcHRpb25zLnN0eWxlVGFnVHJhbnNmb3JtID0gc3R5bGVUYWdUcmFuc2Zvcm1Gbjtcbm9wdGlvbnMuc2V0QXR0cmlidXRlcyA9IHNldEF0dHJpYnV0ZXM7XG5vcHRpb25zLmluc2VydCA9IGluc2VydEZuLmJpbmQobnVsbCwgXCJoZWFkXCIpO1xub3B0aW9ucy5kb21BUEkgPSBkb21BUEk7XG5vcHRpb25zLmluc2VydFN0eWxlRWxlbWVudCA9IGluc2VydFN0eWxlRWxlbWVudDtcblxudmFyIHVwZGF0ZSA9IEFQSShjb250ZW50LCBvcHRpb25zKTtcblxuXG5cbmV4cG9ydCAqIGZyb20gXCIhIS4uLy4uL2Nzcy1sb2FkZXIvZGlzdC9janMuanMhLi9ncmlkc3RhY2stZXh0cmEubWluLmNzc1wiO1xuICAgICAgIGV4cG9ydCBkZWZhdWx0IGNvbnRlbnQgJiYgY29udGVudC5sb2NhbHMgPyBjb250ZW50LmxvY2FscyA6IHVuZGVmaW5lZDtcbiIsIlxuICAgICAgaW1wb3J0IEFQSSBmcm9tIFwiIS4uLy4uL3N0eWxlLWxvYWRlci9kaXN0L3J1bnRpbWUvaW5qZWN0U3R5bGVzSW50b1N0eWxlVGFnLmpzXCI7XG4gICAgICBpbXBvcnQgZG9tQVBJIGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9zdHlsZURvbUFQSS5qc1wiO1xuICAgICAgaW1wb3J0IGluc2VydEZuIGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9pbnNlcnRCeVNlbGVjdG9yLmpzXCI7XG4gICAgICBpbXBvcnQgc2V0QXR0cmlidXRlcyBmcm9tIFwiIS4uLy4uL3N0eWxlLWxvYWRlci9kaXN0L3J1bnRpbWUvc2V0QXR0cmlidXRlc1dpdGhvdXRBdHRyaWJ1dGVzLmpzXCI7XG4gICAgICBpbXBvcnQgaW5zZXJ0U3R5bGVFbGVtZW50IGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9pbnNlcnRTdHlsZUVsZW1lbnQuanNcIjtcbiAgICAgIGltcG9ydCBzdHlsZVRhZ1RyYW5zZm9ybUZuIGZyb20gXCIhLi4vLi4vc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9zdHlsZVRhZ1RyYW5zZm9ybS5qc1wiO1xuICAgICAgaW1wb3J0IGNvbnRlbnQsICogYXMgbmFtZWRFeHBvcnQgZnJvbSBcIiEhLi4vLi4vY3NzLWxvYWRlci9kaXN0L2Nqcy5qcyEuL2dyaWRzdGFjay5taW4uY3NzXCI7XG4gICAgICBcbiAgICAgIFxuXG52YXIgb3B0aW9ucyA9IHt9O1xuXG5vcHRpb25zLnN0eWxlVGFnVHJhbnNmb3JtID0gc3R5bGVUYWdUcmFuc2Zvcm1Gbjtcbm9wdGlvbnMuc2V0QXR0cmlidXRlcyA9IHNldEF0dHJpYnV0ZXM7XG5vcHRpb25zLmluc2VydCA9IGluc2VydEZuLmJpbmQobnVsbCwgXCJoZWFkXCIpO1xub3B0aW9ucy5kb21BUEkgPSBkb21BUEk7XG5vcHRpb25zLmluc2VydFN0eWxlRWxlbWVudCA9IGluc2VydFN0eWxlRWxlbWVudDtcblxudmFyIHVwZGF0ZSA9IEFQSShjb250ZW50LCBvcHRpb25zKTtcblxuXG5cbmV4cG9ydCAqIGZyb20gXCIhIS4uLy4uL2Nzcy1sb2FkZXIvZGlzdC9janMuanMhLi9ncmlkc3RhY2subWluLmNzc1wiO1xuICAgICAgIGV4cG9ydCBkZWZhdWx0IGNvbnRlbnQgJiYgY29udGVudC5sb2NhbHMgPyBjb250ZW50LmxvY2FscyA6IHVuZGVmaW5lZDtcbiIsIlxuICAgICAgaW1wb3J0IEFQSSBmcm9tIFwiIS4uLy4uL25vZGVfbW9kdWxlcy9zdHlsZS1sb2FkZXIvZGlzdC9ydW50aW1lL2luamVjdFN0eWxlc0ludG9TdHlsZVRhZy5qc1wiO1xuICAgICAgaW1wb3J0IGRvbUFQSSBmcm9tIFwiIS4uLy4uL25vZGVfbW9kdWxlcy9zdHlsZS1sb2FkZXIvZGlzdC9ydW50aW1lL3N0eWxlRG9tQVBJLmpzXCI7XG4gICAgICBpbXBvcnQgaW5zZXJ0Rm4gZnJvbSBcIiEuLi8uLi9ub2RlX21vZHVsZXMvc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9pbnNlcnRCeVNlbGVjdG9yLmpzXCI7XG4gICAgICBpbXBvcnQgc2V0QXR0cmlidXRlcyBmcm9tIFwiIS4uLy4uL25vZGVfbW9kdWxlcy9zdHlsZS1sb2FkZXIvZGlzdC9ydW50aW1lL3NldEF0dHJpYnV0ZXNXaXRob3V0QXR0cmlidXRlcy5qc1wiO1xuICAgICAgaW1wb3J0IGluc2VydFN0eWxlRWxlbWVudCBmcm9tIFwiIS4uLy4uL25vZGVfbW9kdWxlcy9zdHlsZS1sb2FkZXIvZGlzdC9ydW50aW1lL2luc2VydFN0eWxlRWxlbWVudC5qc1wiO1xuICAgICAgaW1wb3J0IHN0eWxlVGFnVHJhbnNmb3JtRm4gZnJvbSBcIiEuLi8uLi9ub2RlX21vZHVsZXMvc3R5bGUtbG9hZGVyL2Rpc3QvcnVudGltZS9zdHlsZVRhZ1RyYW5zZm9ybS5qc1wiO1xuICAgICAgaW1wb3J0IGNvbnRlbnQsICogYXMgbmFtZWRFeHBvcnQgZnJvbSBcIiEhLi4vLi4vbm9kZV9tb2R1bGVzL2Nzcy1sb2FkZXIvZGlzdC9janMuanMhLi9jdXN0b20uY3NzXCI7XG4gICAgICBcbiAgICAgIFxuXG52YXIgb3B0aW9ucyA9IHt9O1xuXG5vcHRpb25zLnN0eWxlVGFnVHJhbnNmb3JtID0gc3R5bGVUYWdUcmFuc2Zvcm1Gbjtcbm9wdGlvbnMuc2V0QXR0cmlidXRlcyA9IHNldEF0dHJpYnV0ZXM7XG5vcHRpb25zLmluc2VydCA9IGluc2VydEZuLmJpbmQobnVsbCwgXCJoZWFkXCIpO1xub3B0aW9ucy5kb21BUEkgPSBkb21BUEk7XG5vcHRpb25zLmluc2VydFN0eWxlRWxlbWVudCA9IGluc2VydFN0eWxlRWxlbWVudDtcblxudmFyIHVwZGF0ZSA9IEFQSShjb250ZW50LCBvcHRpb25zKTtcblxuXG5cbmV4cG9ydCAqIGZyb20gXCIhIS4uLy4uL25vZGVfbW9kdWxlcy9jc3MtbG9hZGVyL2Rpc3QvY2pzLmpzIS4vY3VzdG9tLmNzc1wiO1xuICAgICAgIGV4cG9ydCBkZWZhdWx0IGNvbnRlbnQgJiYgY29udGVudC5sb2NhbHMgPyBjb250ZW50LmxvY2FscyA6IHVuZGVmaW5lZDtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgc3R5bGVzSW5ET00gPSBbXTtcbmZ1bmN0aW9uIGdldEluZGV4QnlJZGVudGlmaWVyKGlkZW50aWZpZXIpIHtcbiAgdmFyIHJlc3VsdCA9IC0xO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0eWxlc0luRE9NLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKHN0eWxlc0luRE9NW2ldLmlkZW50aWZpZXIgPT09IGlkZW50aWZpZXIpIHtcbiAgICAgIHJlc3VsdCA9IGk7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIG1vZHVsZXNUb0RvbShsaXN0LCBvcHRpb25zKSB7XG4gIHZhciBpZENvdW50TWFwID0ge307XG4gIHZhciBpZGVudGlmaWVycyA9IFtdO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgaXRlbSA9IGxpc3RbaV07XG4gICAgdmFyIGlkID0gb3B0aW9ucy5iYXNlID8gaXRlbVswXSArIG9wdGlvbnMuYmFzZSA6IGl0ZW1bMF07XG4gICAgdmFyIGNvdW50ID0gaWRDb3VudE1hcFtpZF0gfHwgMDtcbiAgICB2YXIgaWRlbnRpZmllciA9IFwiXCIuY29uY2F0KGlkLCBcIiBcIikuY29uY2F0KGNvdW50KTtcbiAgICBpZENvdW50TWFwW2lkXSA9IGNvdW50ICsgMTtcbiAgICB2YXIgaW5kZXhCeUlkZW50aWZpZXIgPSBnZXRJbmRleEJ5SWRlbnRpZmllcihpZGVudGlmaWVyKTtcbiAgICB2YXIgb2JqID0ge1xuICAgICAgY3NzOiBpdGVtWzFdLFxuICAgICAgbWVkaWE6IGl0ZW1bMl0sXG4gICAgICBzb3VyY2VNYXA6IGl0ZW1bM10sXG4gICAgICBzdXBwb3J0czogaXRlbVs0XSxcbiAgICAgIGxheWVyOiBpdGVtWzVdXG4gICAgfTtcbiAgICBpZiAoaW5kZXhCeUlkZW50aWZpZXIgIT09IC0xKSB7XG4gICAgICBzdHlsZXNJbkRPTVtpbmRleEJ5SWRlbnRpZmllcl0ucmVmZXJlbmNlcysrO1xuICAgICAgc3R5bGVzSW5ET01baW5kZXhCeUlkZW50aWZpZXJdLnVwZGF0ZXIob2JqKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHVwZGF0ZXIgPSBhZGRFbGVtZW50U3R5bGUob2JqLCBvcHRpb25zKTtcbiAgICAgIG9wdGlvbnMuYnlJbmRleCA9IGk7XG4gICAgICBzdHlsZXNJbkRPTS5zcGxpY2UoaSwgMCwge1xuICAgICAgICBpZGVudGlmaWVyOiBpZGVudGlmaWVyLFxuICAgICAgICB1cGRhdGVyOiB1cGRhdGVyLFxuICAgICAgICByZWZlcmVuY2VzOiAxXG4gICAgICB9KTtcbiAgICB9XG4gICAgaWRlbnRpZmllcnMucHVzaChpZGVudGlmaWVyKTtcbiAgfVxuICByZXR1cm4gaWRlbnRpZmllcnM7XG59XG5mdW5jdGlvbiBhZGRFbGVtZW50U3R5bGUob2JqLCBvcHRpb25zKSB7XG4gIHZhciBhcGkgPSBvcHRpb25zLmRvbUFQSShvcHRpb25zKTtcbiAgYXBpLnVwZGF0ZShvYmopO1xuICB2YXIgdXBkYXRlciA9IGZ1bmN0aW9uIHVwZGF0ZXIobmV3T2JqKSB7XG4gICAgaWYgKG5ld09iaikge1xuICAgICAgaWYgKG5ld09iai5jc3MgPT09IG9iai5jc3MgJiYgbmV3T2JqLm1lZGlhID09PSBvYmoubWVkaWEgJiYgbmV3T2JqLnNvdXJjZU1hcCA9PT0gb2JqLnNvdXJjZU1hcCAmJiBuZXdPYmouc3VwcG9ydHMgPT09IG9iai5zdXBwb3J0cyAmJiBuZXdPYmoubGF5ZXIgPT09IG9iai5sYXllcikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBhcGkudXBkYXRlKG9iaiA9IG5ld09iaik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFwaS5yZW1vdmUoKTtcbiAgICB9XG4gIH07XG4gIHJldHVybiB1cGRhdGVyO1xufVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAobGlzdCwgb3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgbGlzdCA9IGxpc3QgfHwgW107XG4gIHZhciBsYXN0SWRlbnRpZmllcnMgPSBtb2R1bGVzVG9Eb20obGlzdCwgb3B0aW9ucyk7XG4gIHJldHVybiBmdW5jdGlvbiB1cGRhdGUobmV3TGlzdCkge1xuICAgIG5ld0xpc3QgPSBuZXdMaXN0IHx8IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGFzdElkZW50aWZpZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgaWRlbnRpZmllciA9IGxhc3RJZGVudGlmaWVyc1tpXTtcbiAgICAgIHZhciBpbmRleCA9IGdldEluZGV4QnlJZGVudGlmaWVyKGlkZW50aWZpZXIpO1xuICAgICAgc3R5bGVzSW5ET01baW5kZXhdLnJlZmVyZW5jZXMtLTtcbiAgICB9XG4gICAgdmFyIG5ld0xhc3RJZGVudGlmaWVycyA9IG1vZHVsZXNUb0RvbShuZXdMaXN0LCBvcHRpb25zKTtcbiAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgbGFzdElkZW50aWZpZXJzLmxlbmd0aDsgX2krKykge1xuICAgICAgdmFyIF9pZGVudGlmaWVyID0gbGFzdElkZW50aWZpZXJzW19pXTtcbiAgICAgIHZhciBfaW5kZXggPSBnZXRJbmRleEJ5SWRlbnRpZmllcihfaWRlbnRpZmllcik7XG4gICAgICBpZiAoc3R5bGVzSW5ET01bX2luZGV4XS5yZWZlcmVuY2VzID09PSAwKSB7XG4gICAgICAgIHN0eWxlc0luRE9NW19pbmRleF0udXBkYXRlcigpO1xuICAgICAgICBzdHlsZXNJbkRPTS5zcGxpY2UoX2luZGV4LCAxKTtcbiAgICAgIH1cbiAgICB9XG4gICAgbGFzdElkZW50aWZpZXJzID0gbmV3TGFzdElkZW50aWZpZXJzO1xuICB9O1xufTsiLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIG1lbW8gPSB7fTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgICovXG5mdW5jdGlvbiBnZXRUYXJnZXQodGFyZ2V0KSB7XG4gIGlmICh0eXBlb2YgbWVtb1t0YXJnZXRdID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgdmFyIHN0eWxlVGFyZ2V0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0YXJnZXQpO1xuXG4gICAgLy8gU3BlY2lhbCBjYXNlIHRvIHJldHVybiBoZWFkIG9mIGlmcmFtZSBpbnN0ZWFkIG9mIGlmcmFtZSBpdHNlbGZcbiAgICBpZiAod2luZG93LkhUTUxJRnJhbWVFbGVtZW50ICYmIHN0eWxlVGFyZ2V0IGluc3RhbmNlb2Ygd2luZG93LkhUTUxJRnJhbWVFbGVtZW50KSB7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBUaGlzIHdpbGwgdGhyb3cgYW4gZXhjZXB0aW9uIGlmIGFjY2VzcyB0byBpZnJhbWUgaXMgYmxvY2tlZFxuICAgICAgICAvLyBkdWUgdG8gY3Jvc3Mtb3JpZ2luIHJlc3RyaWN0aW9uc1xuICAgICAgICBzdHlsZVRhcmdldCA9IHN0eWxlVGFyZ2V0LmNvbnRlbnREb2N1bWVudC5oZWFkO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBpc3RhbmJ1bCBpZ25vcmUgbmV4dFxuICAgICAgICBzdHlsZVRhcmdldCA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIG1lbW9bdGFyZ2V0XSA9IHN0eWxlVGFyZ2V0O1xuICB9XG4gIHJldHVybiBtZW1vW3RhcmdldF07XG59XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICAqL1xuZnVuY3Rpb24gaW5zZXJ0QnlTZWxlY3RvcihpbnNlcnQsIHN0eWxlKSB7XG4gIHZhciB0YXJnZXQgPSBnZXRUYXJnZXQoaW5zZXJ0KTtcbiAgaWYgKCF0YXJnZXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZG4ndCBmaW5kIGEgc3R5bGUgdGFyZ2V0LiBUaGlzIHByb2JhYmx5IG1lYW5zIHRoYXQgdGhlIHZhbHVlIGZvciB0aGUgJ2luc2VydCcgcGFyYW1ldGVyIGlzIGludmFsaWQuXCIpO1xuICB9XG4gIHRhcmdldC5hcHBlbmRDaGlsZChzdHlsZSk7XG59XG5tb2R1bGUuZXhwb3J0cyA9IGluc2VydEJ5U2VsZWN0b3I7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICAqL1xuZnVuY3Rpb24gaW5zZXJ0U3R5bGVFbGVtZW50KG9wdGlvbnMpIHtcbiAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3R5bGVcIik7XG4gIG9wdGlvbnMuc2V0QXR0cmlidXRlcyhlbGVtZW50LCBvcHRpb25zLmF0dHJpYnV0ZXMpO1xuICBvcHRpb25zLmluc2VydChlbGVtZW50LCBvcHRpb25zLm9wdGlvbnMpO1xuICByZXR1cm4gZWxlbWVudDtcbn1cbm1vZHVsZS5leHBvcnRzID0gaW5zZXJ0U3R5bGVFbGVtZW50OyIsIlwidXNlIHN0cmljdFwiO1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAgKi9cbmZ1bmN0aW9uIHNldEF0dHJpYnV0ZXNXaXRob3V0QXR0cmlidXRlcyhzdHlsZUVsZW1lbnQpIHtcbiAgdmFyIG5vbmNlID0gdHlwZW9mIF9fd2VicGFja19ub25jZV9fICE9PSBcInVuZGVmaW5lZFwiID8gX193ZWJwYWNrX25vbmNlX18gOiBudWxsO1xuICBpZiAobm9uY2UpIHtcbiAgICBzdHlsZUVsZW1lbnQuc2V0QXR0cmlidXRlKFwibm9uY2VcIiwgbm9uY2UpO1xuICB9XG59XG5tb2R1bGUuZXhwb3J0cyA9IHNldEF0dHJpYnV0ZXNXaXRob3V0QXR0cmlidXRlczsiLCJcInVzZSBzdHJpY3RcIjtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgICovXG5mdW5jdGlvbiBhcHBseShzdHlsZUVsZW1lbnQsIG9wdGlvbnMsIG9iaikge1xuICB2YXIgY3NzID0gXCJcIjtcbiAgaWYgKG9iai5zdXBwb3J0cykge1xuICAgIGNzcyArPSBcIkBzdXBwb3J0cyAoXCIuY29uY2F0KG9iai5zdXBwb3J0cywgXCIpIHtcIik7XG4gIH1cbiAgaWYgKG9iai5tZWRpYSkge1xuICAgIGNzcyArPSBcIkBtZWRpYSBcIi5jb25jYXQob2JqLm1lZGlhLCBcIiB7XCIpO1xuICB9XG4gIHZhciBuZWVkTGF5ZXIgPSB0eXBlb2Ygb2JqLmxheWVyICE9PSBcInVuZGVmaW5lZFwiO1xuICBpZiAobmVlZExheWVyKSB7XG4gICAgY3NzICs9IFwiQGxheWVyXCIuY29uY2F0KG9iai5sYXllci5sZW5ndGggPiAwID8gXCIgXCIuY29uY2F0KG9iai5sYXllcikgOiBcIlwiLCBcIiB7XCIpO1xuICB9XG4gIGNzcyArPSBvYmouY3NzO1xuICBpZiAobmVlZExheWVyKSB7XG4gICAgY3NzICs9IFwifVwiO1xuICB9XG4gIGlmIChvYmoubWVkaWEpIHtcbiAgICBjc3MgKz0gXCJ9XCI7XG4gIH1cbiAgaWYgKG9iai5zdXBwb3J0cykge1xuICAgIGNzcyArPSBcIn1cIjtcbiAgfVxuICB2YXIgc291cmNlTWFwID0gb2JqLnNvdXJjZU1hcDtcbiAgaWYgKHNvdXJjZU1hcCAmJiB0eXBlb2YgYnRvYSAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIGNzcyArPSBcIlxcbi8qIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsXCIuY29uY2F0KGJ0b2EodW5lc2NhcGUoZW5jb2RlVVJJQ29tcG9uZW50KEpTT04uc3RyaW5naWZ5KHNvdXJjZU1hcCkpKSksIFwiICovXCIpO1xuICB9XG5cbiAgLy8gRm9yIG9sZCBJRVxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgICovXG4gIG9wdGlvbnMuc3R5bGVUYWdUcmFuc2Zvcm0oY3NzLCBzdHlsZUVsZW1lbnQsIG9wdGlvbnMub3B0aW9ucyk7XG59XG5mdW5jdGlvbiByZW1vdmVTdHlsZUVsZW1lbnQoc3R5bGVFbGVtZW50KSB7XG4gIC8vIGlzdGFuYnVsIGlnbm9yZSBpZlxuICBpZiAoc3R5bGVFbGVtZW50LnBhcmVudE5vZGUgPT09IG51bGwpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgc3R5bGVFbGVtZW50LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoc3R5bGVFbGVtZW50KTtcbn1cblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgICovXG5mdW5jdGlvbiBkb21BUEkob3B0aW9ucykge1xuICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHVwZGF0ZTogZnVuY3Rpb24gdXBkYXRlKCkge30sXG4gICAgICByZW1vdmU6IGZ1bmN0aW9uIHJlbW92ZSgpIHt9XG4gICAgfTtcbiAgfVxuICB2YXIgc3R5bGVFbGVtZW50ID0gb3B0aW9ucy5pbnNlcnRTdHlsZUVsZW1lbnQob3B0aW9ucyk7XG4gIHJldHVybiB7XG4gICAgdXBkYXRlOiBmdW5jdGlvbiB1cGRhdGUob2JqKSB7XG4gICAgICBhcHBseShzdHlsZUVsZW1lbnQsIG9wdGlvbnMsIG9iaik7XG4gICAgfSxcbiAgICByZW1vdmU6IGZ1bmN0aW9uIHJlbW92ZSgpIHtcbiAgICAgIHJlbW92ZVN0eWxlRWxlbWVudChzdHlsZUVsZW1lbnQpO1xuICAgIH1cbiAgfTtcbn1cbm1vZHVsZS5leHBvcnRzID0gZG9tQVBJOyIsIlwidXNlIHN0cmljdFwiO1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAgKi9cbmZ1bmN0aW9uIHN0eWxlVGFnVHJhbnNmb3JtKGNzcywgc3R5bGVFbGVtZW50KSB7XG4gIGlmIChzdHlsZUVsZW1lbnQuc3R5bGVTaGVldCkge1xuICAgIHN0eWxlRWxlbWVudC5zdHlsZVNoZWV0LmNzc1RleHQgPSBjc3M7XG4gIH0gZWxzZSB7XG4gICAgd2hpbGUgKHN0eWxlRWxlbWVudC5maXJzdENoaWxkKSB7XG4gICAgICBzdHlsZUVsZW1lbnQucmVtb3ZlQ2hpbGQoc3R5bGVFbGVtZW50LmZpcnN0Q2hpbGQpO1xuICAgIH1cbiAgICBzdHlsZUVsZW1lbnQuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoY3NzKSk7XG4gIH1cbn1cbm1vZHVsZS5leHBvcnRzID0gc3R5bGVUYWdUcmFuc2Zvcm07IiwiXG4vLyBGcm9tIEZyaXNzIHR1dG8gKGh0dHBzOi8vZ2l0aHViLmNvbS9Gcmlzc0FuYWx5dGljcy9zaGlueUpzVHV0b3JpYWxzL2Jsb2IvbWFzdGVyL3R1dG9yaWFscy90dXRvcmlhbF8wMy5SbWQpXG5leHBvcnQgZnVuY3Rpb24gZ2V0V2lkZ2V0KGlkKSB7XG4gIHZhciBodG1sV2lkZ2V0c09iaiA9IEhUTUxXaWRnZXRzLmZpbmQoXCIjXCIgKyBpZCk7XG4gIHZhciB3aWRnZXRPYmo7XG4gIGlmICh0eXBlb2YgaHRtbFdpZGdldHNPYmogIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICB3aWRnZXRPYmogPSBodG1sV2lkZ2V0c09iai5nZXRXaWRnZXQoKTtcbiAgfVxuICByZXR1cm4gd2lkZ2V0T2JqO1xufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBIVE1MV2lkZ2V0czsiLCIvLyBUaGUgbW9kdWxlIGNhY2hlXG52YXIgX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fID0ge307XG5cbi8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG5mdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuXHR2YXIgY2FjaGVkTW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXTtcblx0aWYgKGNhY2hlZE1vZHVsZSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0cmV0dXJuIGNhY2hlZE1vZHVsZS5leHBvcnRzO1xuXHR9XG5cdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG5cdHZhciBtb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdID0ge1xuXHRcdGlkOiBtb2R1bGVJZCxcblx0XHQvLyBubyBtb2R1bGUubG9hZGVkIG5lZWRlZFxuXHRcdGV4cG9ydHM6IHt9XG5cdH07XG5cblx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG5cdF9fd2VicGFja19tb2R1bGVzX19bbW9kdWxlSWRdKG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG5cdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG5cdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbn1cblxuLy8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbl9fd2VicGFja19yZXF1aXJlX18ubSA9IF9fd2VicGFja19tb2R1bGVzX187XG5cbiIsIi8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSAobW9kdWxlKSA9PiB7XG5cdHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgP1xuXHRcdCgpID0+IChtb2R1bGVbJ2RlZmF1bHQnXSkgOlxuXHRcdCgpID0+IChtb2R1bGUpO1xuXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCB7IGE6IGdldHRlciB9KTtcblx0cmV0dXJuIGdldHRlcjtcbn07IiwiLy8gZGVmaW5lIGdldHRlciBmdW5jdGlvbnMgZm9yIGhhcm1vbnkgZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5kID0gKGV4cG9ydHMsIGRlZmluaXRpb24pID0+IHtcblx0Zm9yKHZhciBrZXkgaW4gZGVmaW5pdGlvbikge1xuXHRcdGlmKF9fd2VicGFja19yZXF1aXJlX18ubyhkZWZpbml0aW9uLCBrZXkpICYmICFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywga2V5KSkge1xuXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIGtleSwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGRlZmluaXRpb25ba2V5XSB9KTtcblx0XHR9XG5cdH1cbn07IiwiX193ZWJwYWNrX3JlcXVpcmVfXy5vID0gKG9iaiwgcHJvcCkgPT4gKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApKSIsIi8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uciA9IChleHBvcnRzKSA9PiB7XG5cdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuXHR9XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18uYiA9IGRvY3VtZW50LmJhc2VVUkkgfHwgc2VsZi5sb2NhdGlvbi5ocmVmO1xuXG4vLyBvYmplY3QgdG8gc3RvcmUgbG9hZGVkIGFuZCBsb2FkaW5nIGNodW5rc1xuLy8gdW5kZWZpbmVkID0gY2h1bmsgbm90IGxvYWRlZCwgbnVsbCA9IGNodW5rIHByZWxvYWRlZC9wcmVmZXRjaGVkXG4vLyBbcmVzb2x2ZSwgcmVqZWN0LCBQcm9taXNlXSA9IGNodW5rIGxvYWRpbmcsIDAgPSBjaHVuayBsb2FkZWRcbnZhciBpbnN0YWxsZWRDaHVua3MgPSB7XG5cdFwiZ3JpZHN0YWNrXCI6IDBcbn07XG5cbi8vIG5vIGNodW5rIG9uIGRlbWFuZCBsb2FkaW5nXG5cbi8vIG5vIHByZWZldGNoaW5nXG5cbi8vIG5vIHByZWxvYWRlZFxuXG4vLyBubyBITVJcblxuLy8gbm8gSE1SIG1hbmlmZXN0XG5cbi8vIG5vIG9uIGNodW5rcyBsb2FkZWRcblxuLy8gbm8ganNvbnAgZnVuY3Rpb24iLCJfX3dlYnBhY2tfcmVxdWlyZV9fLm5jID0gdW5kZWZpbmVkOyIsImltcG9ydCBcIndpZGdldHNcIjtcbmltcG9ydCBcImdyaWRzdGFjay9kaXN0L2dyaWRzdGFjay5taW4uY3NzXCI7XG5pbXBvcnQgXCJncmlkc3RhY2svZGlzdC9ncmlkc3RhY2stZXh0cmEubWluLmNzc1wiO1xuaW1wb3J0IHsgR3JpZFN0YWNrIH0gZnJvbSBcImdyaWRzdGFja1wiO1xuaW1wb3J0IFwiLi4vY3NzL2N1c3RvbS5jc3NcIjtcbmltcG9ydCAqIGFzIHV0aWxzIGZyb20gXCIuLi9tb2R1bGVzL3V0aWxzXCI7XG5cbkhUTUxXaWRnZXRzLndpZGdldCh7XG5cbiAgbmFtZTogXCJncmlkc3RhY2tcIixcblxuICB0eXBlOiBcIm91dHB1dFwiLFxuXG4gIGZhY3Rvcnk6IGZ1bmN0aW9uKGVsLCB3aWR0aCwgaGVpZ2h0KSB7XG5cbiAgICB2YXIgZ3JpZDtcblxuICAgIHJldHVybiB7XG5cbiAgICAgIHJlbmRlclZhbHVlOiBmdW5jdGlvbih4KSB7XG5cbiAgICAgICAgZWwuY2xhc3NMaXN0LmFkZChcImdyaWQtc3RhY2tcIik7XG4gICAgICAgIGVsLmNsYXNzTGlzdC5hZGQoXCJncmlkLXN0YWNrLWVkaXRcIik7XG4gICAgICAgIGVsLnN0eWxlLmJhY2tncm91bmQgPSB4LmJnO1xuICAgICAgICBlbC5pbm5lckhUTUwgPSB4Lmh0bWw7XG5cbiAgICAgICAgZ3JpZCA9IEdyaWRTdGFjay5pbml0KHgub3B0aW9ucywgZWwpO1xuICAgICAgICBncmlkLm9uKFwicmVzaXplc3RvcFwiLCBmdW5jdGlvbihldmVudCwgZWwpIHtcbiAgICAgICAgICB3aW5kb3cuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoXCJyZXNpemVcIikpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKEhUTUxXaWRnZXRzLnNoaW55TW9kZSkge1xuICAgICAgICAgIHZhciAkYWxsID0gJChlbCk7XG4gICAgICAgICAgU2hpbnkuYmluZEFsbCgkYWxsKTtcbiAgICAgICAgfVxuICAgICAgICBncmlkLm9uKFwiYWRkZWRcIiwgZnVuY3Rpb24oZXZlbnQsIGl0ZW1zKSB7XG4gICAgICAgICAgaWYgKEhUTUxXaWRnZXRzLnNoaW55TW9kZSkge1xuICAgICAgICAgICAgaXRlbXMuZm9yRWFjaChmdW5jdGlvbihpdGVtKSB7XG4gICAgICAgICAgICAgIHZhciAkaXRlbSA9ICQoaXRlbSk7XG4gICAgICAgICAgICAgIFNoaW55LmJpbmRBbGwoJGl0ZW0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoSFRNTFdpZGdldHMuc2hpbnlNb2RlKSB7XG4gICAgICAgICAgdmFyIHNlcmlhbGl6ZWRGdWxsID0gZ3JpZC5zYXZlKHRydWUsIHRydWUpO1xuICAgICAgICAgIFNoaW55LnNldElucHV0VmFsdWUoZWwuaWQgKyBcIl9sYXlvdXRcIiwgc2VyaWFsaXplZEZ1bGwpO1xuICAgICAgICAgIGdyaWQub24oXCJhZGRlZCByZW1vdmVkIGNoYW5nZVwiLCBmdW5jdGlvbihldmVudCwgaXRlbXMpIHtcbiAgICAgICAgICAgIHNlcmlhbGl6ZWRGdWxsID0gZ3JpZC5zYXZlKHRydWUsIHRydWUpO1xuICAgICAgICAgICAgU2hpbnkuc2V0SW5wdXRWYWx1ZShlbC5pZCArIFwiX2xheW91dFwiLCBzZXJpYWxpemVkRnVsbCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgfSxcblxuICAgICAgZ2V0V2lkZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGdyaWQ7XG4gICAgICB9LFxuXG4gICAgICByZXNpemU6IGZ1bmN0aW9uKHdpZHRoLCBoZWlnaHQpIHtcblxuICAgICAgICAvLyBUT0RPOiBjb2RlIHRvIHJlLXJlbmRlciB0aGUgd2lkZ2V0IHdpdGggYSBuZXcgc2l6ZVxuXG4gICAgICB9XG5cbiAgICB9O1xuICB9XG59KTtcblxuXG5pZiAoSFRNTFdpZGdldHMuc2hpbnlNb2RlKSB7XG5cbiAgLy8gYWRkIGEgd2lkZ2V0XG4gIFNoaW55LmFkZEN1c3RvbU1lc3NhZ2VIYW5kbGVyKFwiZ3JpZHN0YWNrci1hZGQtd2lkZ2V0XCIsIGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBncmlkID0gdXRpbHMuZ2V0V2lkZ2V0KG9iai5pZCk7XG4gICAgaWYgKHR5cGVvZiBncmlkICE9IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgIGdyaWQuYWRkV2lkZ2V0KG9iai5kYXRhLm9wdGlvbnMpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gY29tcGFjdCBsYXlvdXRcbiAgU2hpbnkuYWRkQ3VzdG9tTWVzc2FnZUhhbmRsZXIoXCJncmlkc3RhY2tyLWNvbXBhY3RcIiwgZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIGdyaWQgPSB1dGlscy5nZXRXaWRnZXQob2JqLmlkKTtcbiAgICBpZiAodHlwZW9mIGdyaWQgIT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgZ3JpZC5jb21wYWN0KG9iai5kYXRhKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIGRpc2FibGVcbiAgU2hpbnkuYWRkQ3VzdG9tTWVzc2FnZUhhbmRsZXIoXCJncmlkc3RhY2tyLWRpc2FibGVcIiwgZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIGdyaWQgPSB1dGlscy5nZXRXaWRnZXQob2JqLmlkKTtcbiAgICBpZiAodHlwZW9mIGdyaWQgIT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgZ3JpZC5kaXNhYmxlKCk7XG4gICAgfVxuICB9KTtcblxuICAvLyBlbmFibGVcbiAgU2hpbnkuYWRkQ3VzdG9tTWVzc2FnZUhhbmRsZXIoXCJncmlkc3RhY2tyLWVuYWJsZVwiLCBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgZ3JpZCA9IHV0aWxzLmdldFdpZGdldChvYmouaWQpO1xuICAgIGlmICh0eXBlb2YgZ3JpZCAhPSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICBncmlkLmVuYWJsZSgpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gZW5hYmxlTW92ZVxuICBTaGlueS5hZGRDdXN0b21NZXNzYWdlSGFuZGxlcihcImdyaWRzdGFja3ItZW5hYmxlLW1vdmVcIiwgZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIGdyaWQgPSB1dGlscy5nZXRXaWRnZXQob2JqLmlkKTtcbiAgICBpZiAodHlwZW9mIGdyaWQgIT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgZ3JpZC5lbmFibGVNb3ZlKG9iai5kYXRhLmRvRW5hYmxlKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIGVuYWJsZVJlc2l6ZVxuICBTaGlueS5hZGRDdXN0b21NZXNzYWdlSGFuZGxlcihcImdyaWRzdGFja3ItZW5hYmxlLXJlc2l6ZVwiLCBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgZ3JpZCA9IHV0aWxzLmdldFdpZGdldChvYmouaWQpO1xuICAgIGlmICh0eXBlb2YgZ3JpZCAhPSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICBncmlkLmVuYWJsZVJlc2l6ZShvYmouZGF0YS5kb0VuYWJsZSk7XG4gICAgfVxuICB9KTtcblxuICAvLyByZW1vdmVBbGxcbiAgU2hpbnkuYWRkQ3VzdG9tTWVzc2FnZUhhbmRsZXIoXCJncmlkc3RhY2tyLXJlbW92ZS1hbGxcIiwgZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIGdyaWQgPSB1dGlscy5nZXRXaWRnZXQob2JqLmlkKTtcbiAgICBpZiAodHlwZW9mIGdyaWQgIT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgZ3JpZC5yZW1vdmVBbGwoKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIHJlbW92ZVdpZGdldFxuICBTaGlueS5hZGRDdXN0b21NZXNzYWdlSGFuZGxlcihcImdyaWRzdGFja3ItcmVtb3ZlLXdpZGdldFwiLCBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgZ3JpZCA9IHV0aWxzLmdldFdpZGdldChvYmouaWQpO1xuICAgIGlmICh0eXBlb2YgZ3JpZCAhPSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICB2YXIgY29udGFpbmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQob2JqLmlkKTtcbiAgICAgIHZhciBlbCA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKFwiZGl2W2dzLWlkPSdcIiArIG9iai5kYXRhLmlkICsgXCInXVwiKTtcbiAgICAgIGdyaWQucmVtb3ZlV2lkZ2V0KGVsKVxuICAgIH1cbiAgfSk7XG5cbn1cblxuXG5cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/srcjs/widgets/gridstack.js b/srcjs/widgets/gridstack.js index c4bcee0..b73bf31 100644 --- a/srcjs/widgets/gridstack.js +++ b/srcjs/widgets/gridstack.js @@ -1,5 +1,6 @@ import "widgets"; import "gridstack/dist/gridstack.min.css"; +import "gridstack/dist/gridstack-extra.min.css"; import { GridStack } from "gridstack"; import "../css/custom.css"; import * as utils from "../modules/utils"; From 4ad09ed4c113d7ffa48d1f26120d106f89331ca7 Mon Sep 17 00:00:00 2001 From: darcyabjones Date: Thu, 19 Sep 2024 17:41:38 +0200 Subject: [PATCH 2/3] Trying to get a bslib style card working with it --- examples/cards.R | 234 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 examples/cards.R diff --git a/examples/cards.R b/examples/cards.R new file mode 100644 index 0000000..630ab91 --- /dev/null +++ b/examples/cards.R @@ -0,0 +1,234 @@ + +library(shiny) +library(bslib) +library(ggplot2) +library(gridstackr) + + +full_screen_toggle <- function(id_controls) { + tooltip( + tags$button( + class = "bslib-full-screen-enter", + class = "badge rounded-pill", + "aria-expanded" = "false", + "aria-controls" = id_controls, + "aria-label" = "Expand card", + full_screen_toggle_icon() + ), + "Expand" + ) +} + +card_init_js <- function() { + tags$script( + `data-bslib-card-init` = NA, + HTML("bslib.Card.initializeAllCards();") + ) +} + +full_screen_toggle_icon <- function() { + # https://www.visiwig.com/icons/ + # https://www.visiwig.com/icons-license/ + HTML('') +} + +# jcheng 2022-06-06: Removing for now; list items have more features than I'm +# ready to design an API for right now +# +# #' @rdname card_body +# #' @export +# card_list <- function(...) { +# res <- tags$ul(class = "list-group list-group-flush", ...) +# as.card_item(res) +# } +# +# #' @export +# card_list_item <- function(...) { +# tags$li(class = "list-group-item", ...) +# } + +component_dependencies <- function() { + list( + component_dependency_js(), + bs_dependency_defer(component_dependency_sass) + ) +} + +get_package_version <- function(pkg) { + # `utils::packageVersion()` can be slow, so first try the fast path of + # checking if the package is already loaded. + ns <- .getNamespace(pkg) + if (is.null(ns)) { + utils::packageVersion(pkg) + } else { + as.package_version(ns$.__NAMESPACE__.$spec[["version"]]) + } +} + +component_dependency_js <- function() { + minified <- TRUE #get_shiny_devmode_option("shiny.minified", default = TRUE) + + htmltools::htmlDependency( + name = "bslib-component-js", + version = get_package_version("bslib"), + package = "bslib", + src = "components/dist", + script = list( + list(src = paste0("components", if (minified) ".min", ".js")), + list( + src = paste0("web-components", if (minified) ".min", ".js"), + type = "module" + ) + ) + ) +} + +# Pre-compiled component styles +component_dependency_css <- function() { + htmlDependency( + name = "bslib-component-css", + version = get_package_version("bslib"), + package = "bslib", + src = "components/dist", + stylesheet = "components.css" + ) +} + +# Run-time (Sass) component styles +component_dependency_sass <- function(theme) { + precompiled <- isTRUE(get_precompiled_option()) + default_theme <- !is_bs_theme(theme) || identical(theme, bs_theme()) + if (precompiled && default_theme) { + component_dependency_css() + } else { + component_dependency_sass_(theme) + } +} + +component_dependency_sass_files <- function() { + scss_dir <- path_inst("components", "scss") + scss_files <- c( + file.path(scss_dir, "mixins", "_mixins.scss"), + dir(scss_dir, pattern = "\\.scss$", full.names = TRUE) + ) + + lapply(scss_files, sass_file) +} + +component_dependency_sass_ <- function(theme) { + # Although rare, it's possible for bs_dependency_defer() to pass + # along a NULL theme (e.g., renderTags(accordion())), so fallback + # to the default theme if need be + theme <- theme %||% bs_theme() + + if (theme_version(theme) < 5) { + abort(c( + "bslib components require Bootstrap 5 or higher.", + "i" = "Do you need to specify a different `version` in `bs_theme()`?" + )) + } + + bs_dependency( + input = component_dependency_sass_files(), + theme = theme, + name = "bslib-component-css", + version = get_package_version("bslib"), + cache_key_extra = get_package_version("bslib"), + .sass_args = list(options = sass_options(output_style = "compressed")) + ) +} + + +web_component <- function(tagName, ...) { + deps <- component_dependencies() + args <- c(deps, rlang::list2(...)) + htmltools::tag(tagName, args) +} + +ui <- bslib::page_fluid( + tags$h2("GridStack card example"), + theme = bslib::bs_theme(preset = "shiny"), + shiny::tags$head( + shiny::tags$style(" + .card-handle { + cursor: move; + min-height: 25px; + } + .card-handle:hover { + background-color: rgba(0,0,0,0.1); + } + .card { + text-align: left; + } + .resize-vertical { + resize: vertical; + } + .resize-horizontal { + resize: horizontal; + } + .resize-both { + resize: both; + } + ") + ), + gridstack( + margin = "10px", + cellHeight = "140px", + float = FALSE, + column = 6, + options = list(handle = ".card-handle"), + gs_item( + plotOutput("plot1", height = "100%"), + w = 6, h = 2, class_content = "bg-white p-2 border rounded-4" + ), + gs_item( + plotOutput("plot2", height = "100%"), + w = 3, h = 2, class_content = "bg-white p-2 border rounded-4" + ), + gs_item( + plotOutput("plot3", height = "100%"), + w = 3, h = 2, class_content = "bg-white p-2 border rounded-4" + ), + gs_item( + plotOutput("plot4", height = "100%"), + w = 2, h = 2, class_content = "bg-white p-2 border rounded-4" + ), + gs_item( + height = "100%", + class = "card bslib-card bslib-mb-spacing", + "data-bslib-card-init" = NA, + "data-full-screen" = "false", + bslib::card_header( + shiny::icon("up-down-left-right", class = "fa-solid ms-auto card-handle", lib = "font-awesome"), + ), + full_screen_toggle("#test"), + bslib::card_body( + id = "test", + plotOutput("plot4"), + ), + card_init_js(), + component_dependencies(), + w = 4, h = 2 + ) + ) +) + +server <- function(input, output, session) { + + output$plot1 <- renderPlot({ + ggplot(mtcars) + geom_point(aes(mpg, disp)) + }) + output$plot2 <- renderPlot({ + ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear)) + }) + output$plot3 <- renderPlot({ + ggplot(mtcars) + geom_smooth(aes(disp, qsec)) + }) + output$plot4 <- renderPlot({ + ggplot(mtcars) + geom_bar(aes(carb)) + }) + +} + +if (interactive()) + shinyApp(ui, server) From 2dd8412dc4e671be6f331abe7d1cf6f05c9d4385 Mon Sep 17 00:00:00 2001 From: darcyabjones Date: Fri, 20 Sep 2024 10:43:59 +0200 Subject: [PATCH 3/3] Added an example to use handles and n<12 columns --- examples/cards.R | 234 -------------------------------- examples/handles_and_ncolumns.R | 150 ++++++++++++++++++++ 2 files changed, 150 insertions(+), 234 deletions(-) delete mode 100644 examples/cards.R create mode 100644 examples/handles_and_ncolumns.R diff --git a/examples/cards.R b/examples/cards.R deleted file mode 100644 index 630ab91..0000000 --- a/examples/cards.R +++ /dev/null @@ -1,234 +0,0 @@ - -library(shiny) -library(bslib) -library(ggplot2) -library(gridstackr) - - -full_screen_toggle <- function(id_controls) { - tooltip( - tags$button( - class = "bslib-full-screen-enter", - class = "badge rounded-pill", - "aria-expanded" = "false", - "aria-controls" = id_controls, - "aria-label" = "Expand card", - full_screen_toggle_icon() - ), - "Expand" - ) -} - -card_init_js <- function() { - tags$script( - `data-bslib-card-init` = NA, - HTML("bslib.Card.initializeAllCards();") - ) -} - -full_screen_toggle_icon <- function() { - # https://www.visiwig.com/icons/ - # https://www.visiwig.com/icons-license/ - HTML('') -} - -# jcheng 2022-06-06: Removing for now; list items have more features than I'm -# ready to design an API for right now -# -# #' @rdname card_body -# #' @export -# card_list <- function(...) { -# res <- tags$ul(class = "list-group list-group-flush", ...) -# as.card_item(res) -# } -# -# #' @export -# card_list_item <- function(...) { -# tags$li(class = "list-group-item", ...) -# } - -component_dependencies <- function() { - list( - component_dependency_js(), - bs_dependency_defer(component_dependency_sass) - ) -} - -get_package_version <- function(pkg) { - # `utils::packageVersion()` can be slow, so first try the fast path of - # checking if the package is already loaded. - ns <- .getNamespace(pkg) - if (is.null(ns)) { - utils::packageVersion(pkg) - } else { - as.package_version(ns$.__NAMESPACE__.$spec[["version"]]) - } -} - -component_dependency_js <- function() { - minified <- TRUE #get_shiny_devmode_option("shiny.minified", default = TRUE) - - htmltools::htmlDependency( - name = "bslib-component-js", - version = get_package_version("bslib"), - package = "bslib", - src = "components/dist", - script = list( - list(src = paste0("components", if (minified) ".min", ".js")), - list( - src = paste0("web-components", if (minified) ".min", ".js"), - type = "module" - ) - ) - ) -} - -# Pre-compiled component styles -component_dependency_css <- function() { - htmlDependency( - name = "bslib-component-css", - version = get_package_version("bslib"), - package = "bslib", - src = "components/dist", - stylesheet = "components.css" - ) -} - -# Run-time (Sass) component styles -component_dependency_sass <- function(theme) { - precompiled <- isTRUE(get_precompiled_option()) - default_theme <- !is_bs_theme(theme) || identical(theme, bs_theme()) - if (precompiled && default_theme) { - component_dependency_css() - } else { - component_dependency_sass_(theme) - } -} - -component_dependency_sass_files <- function() { - scss_dir <- path_inst("components", "scss") - scss_files <- c( - file.path(scss_dir, "mixins", "_mixins.scss"), - dir(scss_dir, pattern = "\\.scss$", full.names = TRUE) - ) - - lapply(scss_files, sass_file) -} - -component_dependency_sass_ <- function(theme) { - # Although rare, it's possible for bs_dependency_defer() to pass - # along a NULL theme (e.g., renderTags(accordion())), so fallback - # to the default theme if need be - theme <- theme %||% bs_theme() - - if (theme_version(theme) < 5) { - abort(c( - "bslib components require Bootstrap 5 or higher.", - "i" = "Do you need to specify a different `version` in `bs_theme()`?" - )) - } - - bs_dependency( - input = component_dependency_sass_files(), - theme = theme, - name = "bslib-component-css", - version = get_package_version("bslib"), - cache_key_extra = get_package_version("bslib"), - .sass_args = list(options = sass_options(output_style = "compressed")) - ) -} - - -web_component <- function(tagName, ...) { - deps <- component_dependencies() - args <- c(deps, rlang::list2(...)) - htmltools::tag(tagName, args) -} - -ui <- bslib::page_fluid( - tags$h2("GridStack card example"), - theme = bslib::bs_theme(preset = "shiny"), - shiny::tags$head( - shiny::tags$style(" - .card-handle { - cursor: move; - min-height: 25px; - } - .card-handle:hover { - background-color: rgba(0,0,0,0.1); - } - .card { - text-align: left; - } - .resize-vertical { - resize: vertical; - } - .resize-horizontal { - resize: horizontal; - } - .resize-both { - resize: both; - } - ") - ), - gridstack( - margin = "10px", - cellHeight = "140px", - float = FALSE, - column = 6, - options = list(handle = ".card-handle"), - gs_item( - plotOutput("plot1", height = "100%"), - w = 6, h = 2, class_content = "bg-white p-2 border rounded-4" - ), - gs_item( - plotOutput("plot2", height = "100%"), - w = 3, h = 2, class_content = "bg-white p-2 border rounded-4" - ), - gs_item( - plotOutput("plot3", height = "100%"), - w = 3, h = 2, class_content = "bg-white p-2 border rounded-4" - ), - gs_item( - plotOutput("plot4", height = "100%"), - w = 2, h = 2, class_content = "bg-white p-2 border rounded-4" - ), - gs_item( - height = "100%", - class = "card bslib-card bslib-mb-spacing", - "data-bslib-card-init" = NA, - "data-full-screen" = "false", - bslib::card_header( - shiny::icon("up-down-left-right", class = "fa-solid ms-auto card-handle", lib = "font-awesome"), - ), - full_screen_toggle("#test"), - bslib::card_body( - id = "test", - plotOutput("plot4"), - ), - card_init_js(), - component_dependencies(), - w = 4, h = 2 - ) - ) -) - -server <- function(input, output, session) { - - output$plot1 <- renderPlot({ - ggplot(mtcars) + geom_point(aes(mpg, disp)) - }) - output$plot2 <- renderPlot({ - ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear)) - }) - output$plot3 <- renderPlot({ - ggplot(mtcars) + geom_smooth(aes(disp, qsec)) - }) - output$plot4 <- renderPlot({ - ggplot(mtcars) + geom_bar(aes(carb)) - }) - -} - -if (interactive()) - shinyApp(ui, server) diff --git a/examples/handles_and_ncolumns.R b/examples/handles_and_ncolumns.R new file mode 100644 index 0000000..89a38b3 --- /dev/null +++ b/examples/handles_and_ncolumns.R @@ -0,0 +1,150 @@ +# This demonstrates how to use fewer than 12 columns in gridstackr, +# some basic card styling, and how to use grab handles for position +# control instead of making the whole div grabbable.. + +library(shiny) +library(bslib) +library(ggplot2) +library(gridstackr) + + +full_screen_toggle <- function(id_controls) { + tooltip( + tags$button( + class = "bslib-full-screen-enter", + "aria-expanded" = "false", + "aria-controls" = id_controls, + "aria-label" = "Expand card", + full_screen_toggle_icon() + ), + "Expand" + ) +} + +window_move_handle <- function() { + htmltools::tags$div( + class = "card-handle card-handle-button", + shiny::icon("up-down-left-right", class = "fa-solid", lib = "font-awesome") + ) +} + +ui <- bslib::page_fluid( + tags$h2("GridStack card example"), + theme = bslib::bs_theme(preset = "shiny"), + shiny::tags$head( + shiny::tags$style(" + .card-handle { + cursor: move; + } + .card-handle:hover { + background-color: rgba(0,0,0,0.1); + } + .card-handle-button { + position: absolute; + right: 25px; /* sets it in top right of parent container */ + top: 25px; + height: 50px; + width: 50px; + border-radius: 50px; /* gives it the circular button shape */ + text-align: center; /* puts the icon in the middle horizontally */ + } + .card-handle-button i { /* Applies this style to any tags within the container */ + position: relative; + top: calc(50% - 12.5px); + } + + .card-handle-header-button { + float: right; + height: 25px; + width: 25px; + border-radius: 50px; + text-align: center; + } + + /* Applies this style to any tags within the container. + In this case it isn't super necessary because the icon is nearly the same + size as the circle. */ + .card-handle-header-button i { + position: relative; + top: calc(50% - 12.5px); + } + ") + ), + gridstack( + margin = "10px", + cellHeight = "140px", + float = FALSE, # Set to true if you want to be able to keep spaces in the middle of the page + column = 6, + options = list(handle = ".card-handle"), # Necessary to set the grab handle element + gs_item( # If a gard doesn't have an element with class .card-handle the whole thing will be grabbable + class = "card", + shiny::plotOutput("plot1", height = "100%"), + w = 3, + h = 2 + ), + gs_item( + class = "card", + bslib::card_body(paste( + "Notice that we only have 6 columns because we set column=6.", + "This gives it a blockier feel, and can make things align and resize a", + "bit more cleanly depending on what you're after." + )), + w = 3, + h = 2 + ), + gs_item( # Setting an element with class .card-handle means that only that element will be grabbable + class = "card", + window_move_handle(), + shiny::plotOutput("plot2", height = "100%"), + class_content = "p-2", # Gives it a bit of padding on the inside. CF plot 1 + w = 6, + h = 2 + ), + gs_item( + class = "card", + bslib::card_header( + "Plot 3", + htmltools::tags$div( + class = "card-handle-header-button card-handle", + shiny::icon("up-down-left-right", class = "fa-solid", lib = "font-awesome") + ) + ), + bslib::card_body( # You could use bslib instead of class_content + id = "test", + plotOutput("plot3") + ), + w = 4, + h = 2 + ), + gs_item( # You could also just set the whole header to be grabbable. + class = "card", + bslib::card_header( + class = "card-handle", + "Plot 4" + ), + shiny::plotOutput("plot4", height = "100%"), + w = 2, + h = 2 + ) + ) +) + +server <- function(input, output, session) { + + output$plot1 <- renderPlot({ + ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear)) + ggtitle("Plot 1") + }) + output$plot2 <- renderPlot({ + ggplot(mtcars) + geom_point(aes(mpg, disp)) + ggtitle("Plot 2") + }) + output$plot3 <- renderPlot({ + ggplot(mtcars) + geom_smooth(aes(disp, qsec)) + }) + output$plot4 <- renderPlot({ + ggplot(mtcars) + geom_bar(aes(carb)) + }) + +} + +if (interactive()) + shinyApp(ui, server)