diff --git a/build/js/d3sm.min.v0.0.3.js b/build/js/d3sm.min.v0.0.3.js deleted file mode 100644 index fcd6774587a5846d65c234a907118f5425dbe765..0000000000000000000000000000000000000000 --- a/build/js/d3sm.min.v0.0.3.js +++ /dev/null @@ -1,2 +0,0 @@ -var d3sm=function(t){"use strict";function e(t,e,n){return n.indexOf(t)===e}function n(t){var e=document.createElementNS("http://www.w3.org/2000/svg","g");t=void 0==t?"translate(0,0)":t,e.setAttributeNS(null,"transform",t);var n=e.transform.baseVal.consolidate().matrix;return[n.e,n.f]}function r(t,e){(t=String(t).replace(/[^0-9a-f]/gi,"")).length<6&&(t=t[0]+t[0]+t[1]+t[1]+t[2]+t[2]),e=e||0;var n,r,o="#";for(r=0;r<3;r++)n=parseInt(t.substr(2*r,2),16),o+=("00"+(n=Math.round(Math.min(Math.max(0,n+n*e),255)).toString(16))).substr(n.length);return o}function o(t,e){var n=d3.median(t),r=t.filter(function(t){return tn}),a=void 0==(a=d3.median(r))?n:a,i=void 0==(i=d3.min(r))?a:i,l=void 0==(l=d3.median(o))?n:l,c=void 0==(c=d3.max(o))?l:c,u="q0",s="q1",d="q2",f="q3",h="q4",g={};return void 0!=e&&5==e.length&&(u=e[0],s=e[1],d=e[2],f=e[3],h=e[4]),g[u]=i,g[s]=a,g[d]=n,g[f]=l,g[h]=c,g}function a(){return Array.prototype.slice.call(arguments).join("-")}function i(t,e){var n=function(t,e,n){n&&(e=-e);var r=(""+t).split("e");return+(r[0]+"e"+(r[1]?+r[1]+e:e))};return n(Math.round(n(t,e,!1)),e,!0)}function l(t){var e=t.parentElement,n=e.tagName.toLowerCase();return"svg"===n?e:"html"!==n?l(e):void 0}function c(t,e,n){var r=void 0==n?"":"."+n,o=t.select(e+r).empty()?t.append(e):t.select(e+r);return o.classed(r.replace(".",""),!0).attr("transform",void 0==o.attr("transform")?"translate(0,0)":o.attr("transform"))}function u(t,e,n){for(var r=[t],o=(e-t)/(n-1),a=0;a1?o:t*o),l=(i=i<0?0:i)/e;return a&&void 0!=n&&l=r.length?r.push(e.length-1):r[n]+=e.length-1;e.map(function(e,o){Array.isArray(e)&&t(e,n,r)});return r}(t);o=(e-n*r)/i.map(function(t,e){return 1*t/(e+1)}).reduce(function(t,e){return t+e},0);return isNaN(o)?0:o}function b(t,e,n,r,o,a,i){if("up"!=t&&"top"!=t&&1!=t||(t=!0),"down"!=t&&"bottom"!=t&&0!=t||(t=!1),i=void 0==i?"horizontal":i,a=void 0==a?1:a,"horizontal"!=i){var l=o*a,c=(r=t?r:-r,t?e+r:e),u=t?e:e+r,s=t?c:u;return f="M "+c+" "+o/2+" L "+u+" "+o/2+" M "+s+" "+(o/2-l/2)+" L "+s+" "+(o/2+l/2)+" "}var d=r*a,f="M "+r/2+" "+(c=t?n+o:n)+" L "+r/2+" "+(u=t?n:n+o)+" h "+-d/2+" 0 h "+d+" 0 ";return f}function k(){var t,e,n,r=!0,o=d3.scaleLinear(),a="category",i="d3sm-groupped-item",l=1e3,c=d3.easeSin,u="spacer",s=function(t){t.attr("transform",function(t,e){return"translate("+(r?window.outerWidth:0)+","+(r?0:window.outerWidth)+")"})},d=function(t){m("groupingSpacer","exiting with",{current:t,currentNode:t.node()}),t.selectAll("g").classed("to-remove",!0),t.transition().duration(.9*l).ease(c).attr("transform",function(t,e){return"translate("+(r?window.outerWidth:0)+","+(r?0:window.outerWidth)+")"}).remove()};function f(t,h,g){void 0==g&&(g=0);var p=t.selectAll("g."+u+'[level="'+g+'"]').data(h),m=p.enter().append("g").attr("level",g).attr("class",u),v=p.exit();p=p.merge(m),"function"==typeof d?v.each(function(t,e){d(d3.select(this))}):v.remove();var y=n/(g+1),x=0;return p.each(function(t,n){var h=d3.select(this);if(void 0==h.attr("transform")&&"function"==typeof s&&s(h),h.transition().duration(l).ease(c).attr("transform",function(t,e){return"translate("+(r?"scale"==a?o(t):x:0)+","+(r?0:"scale"==a?o(t):x)+")"}),Array.isArray(t)){x+=f(h,t,g+1);var m=h.selectAll("g."+u+'[level="'+g+'"] > g.'+i+"."+u);"function"==typeof d?m.each(function(t,e){d(d3.select(this))}):m.remove()}else{x+=e;var v=h.select("g."+u+'[level="'+g+'"] > g.'+i+"."+u);v.empty()&&(v=h.append("g").attr("class",i).classed(u,!0)),v.attr("parent-index",n);m=h.selectAll("g."+u+'[level="'+(g+1)+'"]');"function"==typeof d?m.each(function(t,e){d(d3.select(this))}):m.remove()}x+=n==p.size()-1?0:y}),x}return f.horizontalQ=function(t){return arguments.length?(r=t,f):r},f.scale=function(t){return arguments.length?(o=t,f):o},f.moveby=function(t){return arguments.length?(a=t,f):a},f.numberOfObjects=function(e){return arguments.length?(t=e,f):t},f.objectClass=function(t){return arguments.length?(i=t,f):i},f.objectSize=function(t){return arguments.length?(e=t,f):e},f.spacerSize=function(t){return arguments.length?(n=t,f):n},f.transitionDuration=function(t){return arguments.length?(l=t,f):l},f.easeFunc=function(t){return arguments.length?(c=t,f):c},f.namespace=function(t){return arguments.length?(u=t,f):u},f.enterFunction=function(t){return arguments.length?(s=t,f):s},f.exitFunction=function(t){return arguments.length?(d=t,f):d},f}var w=function(){return function(t,e){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return function(t,e){var n=[],r=!0,o=!1,a=void 0;try{for(var i,l=t[Symbol.iterator]();!(r=(i=l.next()).done)&&(n.push(i.value),!e||n.length!==e);r=!0);}catch(t){o=!0,a=t}finally{try{!r&&l.return&&l.return()}finally{if(o)throw a}}return n}(t,e);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),S=function(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);ewindow.innerWidth-window.scrollX&&(d=d3.event.pageX-b.width-15),f+b.height>window.innerHeight-window.scrollY&&(f=d3.event.pageY-b.height-15),"relative"==h.style("position")?h.style("position","absolute").style("left",d+"px").style("top",f+"px"):h.style("left",d+"px").style("top",f+"px"),h.attr("z-index",1e4)}return a.keys=function(t){return arguments.length?(e=t,a):e},a.values=function(t){return arguments.length?(n=t,a):n},a.header=function(t){return arguments.length?(r=t,a):r},a.data=function(t){return arguments.length?(o=t,a):o},a.selection=function(e){return arguments.length?(t=e,a):t},a}function A(t){var e,n="d3sm-select-filter",r="Select options:",o=void 0,i=void 0;function l(){var o=c(t,"div","input-group").classed(a(n,"container"),!0),l=(c(c(o,"div","select-prepend").classed("input-group-prepend",!0),"span","input-group-text").text(r),c(o,"select","custom-select").classed(a(n,"select"),!0)),s=c(c(o,"div","select-append").classed("input-group-prepend",!0),"a","filter-button").classed("btn btn-outline-secondary",!0),d=(c(s,"i","fa fa-filter"),c(o,"div","filter-input-group").classed("input-group",!0).classed("d-none",!0)),f=(c(c(c(d,"div","input-group-prepend"),"span","input-group-text").classed("search-button",!0),"i","fa fa-search"),c(d,"input","form-control").attr("placeholder","all").attr("type","text")),h=c(c(d,"div","input-group-append"),"a","close-button").classed("btn btn-outline-secondary",!0),g=(c(h,"i","fa fa-close"),d3.keys(e)),p=l.selectAll("option");p=(p=p.data(d3.keys(e))).merge(p.enter().append("option")).attr("value",function(t,e){return t}).text(function(t,e){return t});var m=h;s.on("click",function(t,e){var n=d.classed("d-none");d.classed("d-none",!n)}),m.on("click",function(t,e){f.property("value","").dispatch("input")}),f.on("input",function(t,n){var r,o=f.property("value"),a=new RegExp(o,"gi");""==o?r=g:(r=[],d3.keys(e).map(function(t,e){var n=t.match(a);null==n||""==n.join("")||r.push(t)})),(p=(p=l.selectAll("option")).data(r)).exit().remove(),p=p.merge(p.enter().append("option")).attr("value",function(t,e){return t}).text(function(t,e){return t});var c=u();i!=c&&(i=c,l.dispatch("change"))})}function u(){var n=t.select("select").property("value");return void 0==n||""==n?void 0==o?d3.keys(e)[0]:o:n}return l.data=function(t){return arguments.length?(e=t,l):e},l.namespace=function(t){return arguments.length?(n=t,l):n},l.selectionName=function(t){return arguments.length?(r=t,l):r},l.defaultValue=function(t){return arguments.length?(o=t,l):o},l.currentOption=u,l}function M(t){var e=t.attr("transform").split("translate("),n=w(e,2),r=(n[0],n[1].split(",")),o=w(r,2),a=o[0],i=o[1];return i.split(")"),[parseFloat(a),parseFloat(i)]}function E(t){var e,n,r,o,i,l,u,s,f,h,g="d3sm-lasso",p=!1,m=[],v=[],y=d3.line().x(function(t,e){return void 0!=s?s(t[0]):t[0]}).y(function(t,e){return void 0!=f?f(t[1]):t[1]}).curve(d3.curveLinearClosed),x=0,b=10,k="#17a2b8",w="10s",S=.3,j="5, 10",z="black",A=2,E="white",O="black",L=3,C=1e3,F=d3.easeExp;function Q(){var t,e;p&&((t=(t=c(n,"g","lasso-container").selectAll('path[instance="'+x+'"]')).data(v)).exit().remove(),e=t.enter().append("path"),V(t=t.merge(e).transition().duration(C).ease(F)))}function B(){var t=c(n,"g","lasso-container");t.selectAll('path[instance="'+x+'"]').remove();t.remove(),n.selectAll(r).classed("in-lasso",!1),Y()}function q(t){t.preventDefault(),t.stopPropagation();var r=c(n,"g","lasso-container");m=[],e.node().addEventListener("mousemove",D),e.node().addEventListener("mouseup",function(t){e.node().removeEventListener("mousemove",D),v.push(m),v=d(v)}),V(h=r.append("path").data([m]))}function V(t){t.attr("class",a(g,"lasso-path")).style("opacity",S).attr("fill",k).attr("d",y).attr("instance",x).style("stroke-dasharray",j).attr("stroke",z).attr("stroke-width",A).style("animation","lassoDash "+w+" linear").style("animation-iteration-count","infinite")}function D(t){if(void 0!=u&&u.dispatch(a(g,"drag")),1==t.which){d3.event=t;var r=d3.mouse(n.node());r=d3.mouse(e.node());if(void 0!=s&&(r[0]=s.invert(r[0])),void 0!=f&&(r[1]=f.invert(r[1])),r[0]=r[0]-i[0]-l[0],r[1]=r[1]-i[1]-l[1],m.length){var o=m[m.length-1],c=[r[0],r[1]],d=[o[0],o[1]];s&&(d[0]=s(d[0]),c[0]=s(c[0])),f&&(d[1]=f(d[1]),c[1]=f(c[1])),function(t,e){var n=t[0]-e[0],r=t[1]-e[1];return Math.sqrt(n*n+r*r)}(d,c)>b&&_(r)}else _(r)}}function _(t){if(void 0!=t){if(m.push(t),h.attr("d",y),m.length<3)return;K(v.concat([m]))}else K(v)}function K(t){return void 0==t&&(t=v),n.selectAll(r).each(function(e,n){var r=d3.select(this),o=r.absolutePosition(),a=[[o.left-i[0]-l[0],o.top-i[1]-l[1]],[o.right-i[0]-l[0],o.top-i[1]-l[1]],[o.left-i[0]-l[0],o.bottom-i[1]-l[1]],[o.right-i[0]-l[0],o.bottom-i[1]-l[1]]];void 0!=s&&(a[0][0]=s.invert(a[0][0]),a[1][0]=s.invert(a[1][0]),a[2][0]=s.invert(a[2][0]),a[3][0]=s.invert(a[3][0])),void 0!=f&&(a[0][1]=f.invert(a[0][1]),a[1][1]=f.invert(a[1][1]),a[2][1]=f.invert(a[2][1]),a[3][1]=f.invert(a[3][1]));var c=!1;for(n=0;nwindow.innerWidth&&o.style("left",d3.event.pageX-15-300+"px")}function ot(t,e){var n=d3.select(this).style("fill","black");if(d3.select(n.node().parentNode).select("line."+a(B,"tick")).attr("stroke",K).attr("stroke-width",Y),M){var o=d3.select(n.node().parentNode).select("line."+a(B,"guideline")),i=o.attr("minor");o.attr("stroke",function(t,e){return"true"==i?r(I,.8):I}).attr("stroke-width",function(t,e){return"true"==i?.8*J:J})}d3.select("#"+a(B,"guideline-tooltip")).remove()}return nt.label=function(t){return arguments.length?(m=t,nt):m},nt.tickTickLabelSpacer=function(t){return arguments.length?(X=t,nt):X},nt.tickLabelMargin=function(t){return arguments.length?(R=t,nt):R},nt.selection=function(e){return arguments.length?(t=e,nt):t},nt.orient=function(t){return arguments.length?(b=t,nt):b},nt.spaceX=function(t){return arguments.length?(w=t,nt):w},nt.spaceY=function(t){return arguments.length?(j=t,nt):j},nt.overflowQ=function(t){return arguments.length?(z=t,nt):z},nt.categoricalQ=function(t){return arguments.length?(A=t,nt):A},nt.guideLinesQ=function(t){return arguments.length?(M=t,nt):M},nt.grouping=function(t){return arguments.length?(e=t,nt):e},nt.scale=function(t){return arguments.length?(E=t,nt):E},nt.domainPadding=function(t){return arguments.length?(O=t,nt):O},nt.objectSpacer=function(t){return arguments.length?(L=t,nt):L},nt.minObjectSize=function(t){return arguments.length?(C=t,nt):C},nt.maxObjectSize=function(t){return arguments.length?(F=t,nt):F},nt.namespace=function(t){return arguments.length?(B=t,nt):B},nt.backgroundFill=function(t){return arguments.length?(Q=t,nt):Q},nt.objectClass=function(t){return arguments.length?(q=t,nt):q},nt.tickLabels=function(t){return arguments.length?(n=t,nt):n},nt.tickValues=function(t){return arguments.length?(o=t,nt):o},nt.numberOfTicks=function(t){return arguments.length?(V=t,nt):V},nt.lineStroke=function(t){return arguments.length?(D=t,nt):D},nt.lineStrokeWidth=function(t){return arguments.length?(_=t,nt):_},nt.tickStroke=function(t){return arguments.length?(K=t,nt):K},nt.tickStrokeWidth=function(t){return arguments.length?(Y=t,nt):Y},nt.tickLength=function(t){return arguments.length?(P=t,nt):P},nt.tickLabelFontSize=function(t){return arguments.length?(W=t,nt):W},nt.tickLabelMinFontSize=function(t){return arguments.length?(N=t,nt):N},nt.tickLabelMaxFontSize=function(t){return arguments.length?(T=t,nt):T},nt.tickLabelTextAnchor=function(t){return arguments.length?(l=t,nt):l},nt.tickLabelRotation=function(t){return arguments.length?(d=t,nt):d},nt.tickLabelFunc=function(t){return arguments.length?(G=t,nt):G},nt.tickLabelOnClick=function(t){return arguments.length?(H=t,nt):H},nt.guidelineSpace=function(t){return arguments.length?(h=t,nt):h},nt.guideLineStroke=function(t){return arguments.length?(I=t,nt):I},nt.guideLineStrokeWidth=function(t){return arguments.length?(J=t,nt):J},nt.transitionDuration=function(t){return arguments.length?(U=t,nt):U},nt.easeFunc=function(t){return arguments.length?($=t,nt):$},nt.objectSize=function(t){return arguments.length?(g=t,nt):g},nt.spacerSize=function(t){return arguments.length?(p=t,nt):p},nt.roundTo=function(t){return arguments.length?(tt=t,nt):tt},nt.reverseScaleQ=function(t){return arguments.length?(et=t,nt):et},nt.tickLabelOnHoverFunc=function(t){return arguments.length?(Z=t,nt):Z},nt},O.bar=function(t){var e,n,r,o,a,i,l,u,s="horizontal",d=!1,h=function(t,n){return e[t]},g=function(t,n){return d3.descending(e[t],e[n])},p=d3.scaleLinear(),m=.5,b=.05,w=50,A=100,M=2,E=j(),O="transparent",L="d3sm-bar",C="bar",F=1e3,Q=d3.easeExp,B=z(),q=1;function V(){var j="horizontal"==s||"bottom"==s||"top"==s,z=!j,V=v(t,L,{x:0,y:0,width:n,height:r},O);a=d3.keys(e),i=a.map(h);var D=void 0==o?a.sort(g):o,_=(a=f(D)).length,K=[Math.min.apply(Math,S(i))-m,Math.max.apply(Math,S(i))+m];p.domain(K).range(j?[0,r]:"right"==s?[0,n]:[n,0]);var Y=j?n:r;l=void 0==l?y(Y,_,w,A,b,d):l,u=void 0==u?x(a,Y,l,_,b,d):u;var P=k().horizontalQ(j).scale(p).moveby("category").numberOfObjects(_).objectClass(C).objectSize(l).spacerSize(u).transitionDuration(F).easeFunc(Q).namespace(L),X=P.exitFunction();P.exitFunction(function(t){void 0==l&&console.log(t.nodes(),l),X(t),t.selectAll("g").classed("to-remove",!0),t.selectAll("* > rect").transition().duration(F).attr("transform",function(t,e){return"translate(0,"+(z?0:p(K[1]))+")"}).attr("width",j?l:0).attr("height",z?l:0).remove()}),P(V,D,0);var R=[];V.selectAll("g:not(.to-remove)."+C).each(function(t,e){R.push(Number(d3.select(this).attr("parent-index")))}),E="index"==E.colorBy()?E.dataExtent([0,Math.max.apply(Math,R)]):E.dataExtent(K),V.selectAll("g."+C+":not(.to-remove)").each(function(t,n){var r=d3.select(this),o=(e[t],h(t,n)),a=(n=void 0==r.attr("parent-index")?n:r.attr("parent-index"),E(t,o,n,"fill")),i=E(t,o,n,"stroke"),u=c(r,"rect","bar-rect");void 0==u.attr("transform")&&u.attr("transform",function(t,e){return"translate(0,"+(z?0:p(K[1]))+")"}).attr("width",j?l:0).attr("height",z?l:0),u.transition().duration(F).ease(Q).attr("transform",function(t,e){return"translate("+(j?l-l*q:"right"==s?p(K[1])-p(o):l-l*q)+","+(z?l-l*q:p(K[1])-p(o))+")"}).attr("width",j?l*q:p(o)).attr("height",z?l*q:p(o)).attr("fill",a).attr("stroke",i).attr("stroke-width",M),r.on("mouseover",function(t,e){V.selectAll("g."+C).style("opacity",.2),r.style("opacity",1),u.attr("stroke-width",2*M)}),r.on("mouseout",function(){V.selectAll("g."+C).style("opacity",1),u.attr("stroke-width",M)})}),B.selection(V.selectAll(".bar-rect")).data(e),B()}return V.selection=function(e){return arguments.length?(t=e,V):t},V.data=function(t){return arguments.length?(e=t,V):e},V.orient=function(t){return arguments.length?(s=t,V):s},V.spaceX=function(t){return arguments.length?(n=t,V):n},V.spaceY=function(t){return arguments.length?(r=t,V):r},V.overflowQ=function(t){return arguments.length?(d=t,V):d},V.grouping=function(t){return arguments.length?(o=t,V):o},V.valueExtractor=function(t){return arguments.length?(h=t,V):h},V.sortingFunction=function(t){return arguments.length?(g=t,V):g},V.scale=function(t){return arguments.length?(p=t,V):p},V.domainPadding=function(t){return arguments.length?(m=t,V):m},V.objectSpacer=function(t){return arguments.length?(b=t,V):b},V.minObjectSize=function(t){return arguments.length?(w=t,V):w},V.maxObjectSize=function(t){return arguments.length?(A=t,V):A},V.barStrokeWidth=function(t){return arguments.length?(M=t,V):M},V.colorFunction=function(t){return arguments.length?(E=t,V):E},V.backgroundFill=function(t){return arguments.length?(O=t,V):O},V.namespace=function(t){return arguments.length?(L=t,V):L},V.objectClass=function(t){return arguments.length?(C=t,V):C},V.transitionDuration=function(t){return arguments.length?(F=t,V):F},V.easeFunc=function(t){return arguments.length?(Q=t,V):Q},V.barKeys=function(t){return arguments.length?(a=t,V):a},V.barValues=function(t){return arguments.length?(i=t,V):i},V.objectSize=function(t){return arguments.length?(l=t,V):l},V.spacerSize=function(t){return arguments.length?(u=t,V):u},V.tooltip=function(t){return arguments.length?(B=t,V):B},V.barPercent=function(t){return arguments.length?(q=t,V):q},V},O.bubbleHeatmap=function(t){var e,n,r,o,i,l,u,s,f,h,g,p,b="x",w="y",A="r",M="v",E=function(t,n){return e[t][b]},O=function(t,n){return e[t][w]},L=function(t,n){return e[t][A]},C=function(t,n){return e[t][M]},F=!1,Q=d3.scaleLinear(),B=.5,q=0,V=50,D=100,_=2,K="transparent",Y="d3sm-bubble",P="bubble",X=1e3,R=d3.easeExp,W=function(t,e){return E(t)-E(e)},N=function(t,e){return O(t)-O(e)},T=j().colorBy("value"),G=z();function H(){var b=v(t,Y,{x:0,y:0,width:n,height:r},K);(o=d3.keys(e)).sort(function(t,e){return W(t,e)||N(t,e)}),m("bubbleHeatmap","cells are sorted by",o),i=d(o.map(E)),l=d(o.map(O)),u=d(o.map(L)),s=d(o.map(C)),m("bubbleHeatmap","x and y keys are",{x:i,y:l});var w=i.length,j=l.length,z=[Math.min.apply(Math,S(u))-B,Math.max.apply(Math,S(u))+B];g=y(r,j,V,D,q,F),f=y(n,w,V,D,q,F),p=x(l,r,g,j,q,F),h=x(i,n,f,w,q,F),m("bubbleHeatmap","size of",{x:f,y:g}),Q.domain(z).range([Math.min(V/2,Math.min(g,f)/2),Math.min(g,f)/2]);var A=k().horizontalQ(!1).moveby("category").numberOfObjects(j).objectClass(a(P,"row")).objectSize(g).spacerSize(p).transitionDuration(X).easeFunc(R).namespace("row"),M=k().horizontalQ(!0).moveby("category").numberOfObjects(w).objectClass(P).objectSize(f).spacerSize(h).transitionDuration(X).easeFunc(R);A(b,l,0),b.selectAll("g."+a(P,"row")).each(function(t,e){M(d3.select(this),i,0)});var H=b.selectAll("g:not(.to-remove)."+P).data(o),Z=[];H.each(function(t,e){Z.push(Number(d3.select(this).attr("parent-index")))}),T="index"==T.colorBy()?T.dataExtent([0,Math.max.apply(Math,Z)]):T.dataExtent([0,Math.max.apply(Math,S(s))]),H.each(function(t,n){m("bubbleHeatmap","each cell",{key:t,index:n,node:d3.select(this).node()});var r=d3.select(this),o=(e[t],C(t,n)),i=L(t,n),l=(n=void 0==r.attr("parent-index")?n:r.attr("parent-index"),T(t,o,n,"fill")),u=T(t,o,n,"stroke");m("bubbleHeatmap","radius",{radius:i,scaled:Q(i),extent:z,range:Q.range()}),c(r,"circle",a(P,"circle")).attr("cx",f/2).attr("cy",g/2).attr("r",Q(i)).attr("fill",l).attr("stroke",u).attr("stroke-width",_)}),G.selection(H.selectAll("circle."+a(P,"circle"))).data(e),G()}return H.selection=function(e){return arguments.length?(t=e,H):t},H.data=function(t){return arguments.length?(e=t,H):e},H.spaceX=function(t){return arguments.length?(n=t,H):n},H.spaceY=function(t){return arguments.length?(r=t,H):r},H.xKey=function(t){return arguments.length?(b=t,H):b},H.yKey=function(t){return arguments.length?(w=t,H):w},H.rKey=function(t){return arguments.length?(A=t,H):A},H.vKey=function(t){return arguments.length?(M=t,H):M},H.cellKeys=function(t){return arguments.length?(o=t,H):o},H.xValues=function(t){return arguments.length?(i=t,H):i},H.yValues=function(t){return arguments.length?(l=t,H):l},H.rValues=function(t){return arguments.length?(u=t,H):u},H.vValues=function(t){return arguments.length?(s=t,H):s},H.xExtractor=function(t){return arguments.length?(E=t,H):E},H.yExtractor=function(t){return arguments.length?(O=t,H):O},H.rExtractor=function(t){return arguments.length?(L=t,H):L},H.vExtractor=function(t){return arguments.length?(C=t,H):C},H.overflowQ=function(t){return arguments.length?(F=t,H):F},H.scale=function(t){return arguments.length?(Q=t,H):Q},H.domainPadding=function(t){return arguments.length?(B=t,H):B},H.objectSpacer=function(t){return arguments.length?q=t:e},H.minObjectSize=function(t){return arguments.length?(V=t,H):V},H.maxObjectSize=function(t){return arguments.length?(D=t,H):D},H.bubbleStrokeWidth=function(t){return arguments.length?(_=t,H):_},H.backgroundFill=function(t){return arguments.length?(K=t,H):K},H.namespace=function(t){return arguments.length?(Y=t,H):Y},H.objectClass=function(t){return arguments.length?(P=t,H):P},H.transitionDuration=function(t){return arguments.length?(X=t,H):X},H.easeFunc=function(t){return arguments.length?(R=t,H):R},H.tooltip=function(t){return arguments.length?(G=t,H):G},H.colorFunction=function(t){return arguments.length?(T=t,H):T},H.xSize=function(t){return arguments.length?(f=t,H):f},H.xSpacerSize=function(t){return arguments.length?(h=t,H):h},H.ySize=function(t){return arguments.length?(g=t,H):g},H.ySpacerSize=function(t){return arguments.length?(p=t,H):p},H},O.heatmap=function(t){var e,n,r,o,i,l,u,s,f,h,g,p="x",b="y",w="v",A=function(t,n){return e[t][p]},M=function(t,n){return e[t][b]},E=function(t,n){return e[t][w]},O=!1,L=0,C=50,F=50,Q=100,B=100,q=2,V="transparent",D="d3sm-heatmap",_="heatmap",K=1e3,Y=d3.easeExp,P=function(t,e){return i.indexOf(A(t))-i.indexOf(A(e))},X=function(t,e){return l.indexOf(M(t))-l.indexOf(M(e))},R=j().colorBy("category"),W=z();function N(){var p=v(t,D,{x:0,y:0,width:n,height:r},V);o=d3.keys(e),i=d(o.map(A)),l=d(o.map(M)),u=d(o.map(E)),o.sort(function(t,e){return P(t,e)||X(t,e)}),m("heatmap","cells are sorted by",o),m("heatmap","x and y keys are",{x:i,y:l});var b=i.length,w=l.length;h=y(r,w,C,B,L,O),s=y(n,b,F,Q,L,O),g=x(l,r,h,w,L,O),f=x(i,n,s,b,L,O),m("heatmap","size of",{x:s,y:h});var j=k().horizontalQ(!1).moveby("category").numberOfObjects(w).objectClass(a(_,"row")).objectSize(h+g).spacerSize(0).transitionDuration(K).easeFunc(Y).namespace("row"),z=k().horizontalQ(!0).moveby("category").numberOfObjects(b).objectClass(_).objectSize(s+f).spacerSize(0).transitionDuration(K).easeFunc(Y);j(p,l,0),p.selectAll("g."+a(_,"row")).each(function(t,e){z(d3.select(this),i,0)});var N=p.selectAll("g:not(.to-remove)."+_);if(o.length!=l.length*i.length){var T={};o.map(function(t,e){T[A(t)+"::"+M(t)]=t});for(var G=[],H=0;Hr?r:n}).attr("fill",h).attr("stroke",v).attr("stroke-width",Q).attr("transform",function(t,e){return"translate("+(g?l/2:A(u))+","+(j?l/2:A(R[1])-A(u))+")"}),k.transition().duration(_).ease(K).attr("d",function(t,e){var n=g?A(i)-A(a):l;return b(!1,0,0,j?A(i)-A(a):l,n,C,d)}).attr("transform",function(t,e){return"translate("+(g?0:A(i))+","+(j?0:A(R[1])-A(i))+")"}).attr("stroke","black").attr("stroke-width",B).attr("fill","none"),x.transition().duration(_).ease(K).attr("d",function(t,e){var n=g?A(f)-A(s):l;return b(!0,0,0,j?A(f)-A(s):l,n,C,d)}).attr("transform",function(t,e){return"translate("+(g?0:A(s))+","+(j?0:A(R[1])-A(f))+")"}).attr("stroke","black").attr("stroke-width",B).attr("fill","none")}),Y.selection(z.selectAll("g:not(.to-remove)."+D)).data(e),Y()}return P.selection=function(e){return arguments.length?(t=e,P):t},P.data=function(t){return arguments.length?(e=t,P):e},P.orient=function(t){return arguments.length?(d=t,P):d},P.spaceX=function(t){return arguments.length?(n=t,P):n},P.spaceY=function(t){return arguments.length?(r=t,P):r},P.overflowQ=function(t){return arguments.length?(h=t,P):h},P.grouping=function(t){return arguments.length?(o=t,P):o},P.quartilesKey=function(t){return arguments.length?(g=t,P):g},P.quartilesKeys=function(t){return arguments.length?(p=t,P):p},P.valueExtractor=function(t){return arguments.length?(m=t,P):m},P.sortingFunction=function(t){return arguments.length?(w=t,P):w},P.scale=function(t){return arguments.length?(A=t,P):A},P.domainPadding=function(t){return arguments.length?(M=t,P):M},P.objectSpacer=function(t){return arguments.length?(E=t,P):E},P.minObjectSize=function(t){return arguments.length?(O=t,P):O},P.maxObjectSize=function(t){return arguments.length?(L=t,P):L},P.whiskerWidthPercent=function(t){return arguments.length?(C=t,P):C},P.colorFunction=function(t){return arguments.length?(F=t,P):F},P.boxStrokeWidth=function(t){return arguments.length?(Q=t,P):Q},P.whiskerStrokeWidth=function(t){return arguments.length?(B=t,P):B},P.backgroundFill=function(t){return arguments.length?(q=t,P):q},P.namespace=function(t){return arguments.length?(V=t,P):V},P.objectClass=function(t){return arguments.length?(D=t,P):D},P.transitionDuration=function(t){return arguments.length?(_=t,P):_},P.easeFunc=function(t){return arguments.length?(K=t,P):K},P.boxKeys=function(t){return arguments.length?(a=t,P):a},P.boxValues=function(t){return arguments.length?(i=t,P):i},P.objectSize=function(t){return arguments.length?(l=t,P):l},P.spacerSize=function(t){return arguments.length?(u=t,P):u},P.tooltip=function(t){return arguments.length?(Y=t,P):Y},P},O.colorFunction=j,O.datatoggle=function(t){var e,n,r,o=function(){},i="d3sm-databar",l=!1,u=!1;d.xAxisSelectQ=function(t){return arguments.length?(l=t,d):l},d.yAxisSelectQ=function(t){return arguments.length?(u=t,d):u},d.xAxisOptions=function(t){return arguments.length?(e=t,d):e},d.yAxisOptions=function(t){return arguments.length?(n=t,d):n},d.data=function(t){return arguments.length?(r=t,d):r},d.updateFunction=function(t){return arguments.length?(o=t,d):o},d.namespace=function(t){return arguments.length?(i=t,d):i},d.currentKeys=function(){var t={};return d3.keys(s).map(function(e,n){t[e]=s[e].currentOption()}),t};var s={};function d(){var e=c(t,"div","d-inline-flex flex-row flex-wrap").selectAll("div."+a(i,"select-filter"));e.exit().remove();var n=(e=e.data(d3.keys(r))).enter().append("div").attr("class","select-filter");return(e=e.merge(n).style("margin-right","10px")).each(function(t,e){var n=A(d3.select(this)).data(r[t]).namespace(a(i,t)).selectionName(t);n(),s[t]=n}),t.selectAll("select").on("change",function(){o()}),d}return d},O.groupingSpacer=k,O.tooltip=z,O.scatter=function(t){var e,n,r,o,a,i,l,c=d3.scaleLinear(),u=.5,s=function(t,n){return e[t].x},d=d3.scaleLinear(),f=.5,h=function(t,n){return e[t].y},g=d3.scaleLinear(),p=.5,m=function(t,e){return 2},y=2,x=10,b=2,k=j(),w="transparent",A="d3sm-scatter",M="scatter-point",E=1e3,O=d3.easeExp,L=z();function C(){var j=v(t,A,{x:0,y:0,width:n,height:r},w);o=d3.keys(e),a=o.map(s),i=o.map(h),l=o.map(m),o.length;var z=[Math.min.apply(Math,S(a))-u,Math.max.apply(Math,S(a))+u],C=[Math.min.apply(Math,S(i))-f,Math.max.apply(Math,S(i))+f],F=[Math.min.apply(Math,S(l))-p,Math.max.apply(Math,S(l))+p];c.domain(z).range([0,n]),d.domain(C).range([r,0]),g.domain(F).range([y,x]);var Q=j.selectAll("."+M),B=(Q=Q.data(o)).enter().append("circle").attr("class",M).attr("cx",0).attr("cy",r).attr("r",0),q=Q.exit();(Q=Q.merge(B)).each(function(t,n){var r=d3.select(this),o=e[t],u=a[n],s=i[n],f=l[n],h=k(t,o,n,"fill"),p=k(t,o,n,"stroke");r.transition().duration(E).ease(O).attr("cx",c(u)).attr("cy",d(s)).attr("r",g(f)).attr("fill",h).attr("stroke",p).attr("stroke-width",b),r.on("mouseover",function(t,e){Q.style("opacity",.2),r.style("opacity",1),r.transition().duration(E/2).ease(O).attr("stroke-width",2*b).attr("r",1.5*g(f))}),r.node().addEventListener("mouseout",function(){j.selectAll("."+M).style("opacity",1),r.transition().duration(E/2).ease(O).attr("stroke-width",b).attr("r",g(f))})}),q.transition().duration(E).ease(O).attr("cx",0).attr("cy",r).attr("r",0).remove(),L.selection(Q).data(e),L()}return C.selection=function(e){return arguments.length?(t=e,C):t},C.data=function(t){return arguments.length?(e=t,C):e},C.spaceX=function(t){return arguments.length?(n=t,C):n},C.spaceY=function(t){return arguments.length?(r=t,C):r},C.scaleX=function(t){return arguments.length?(c=t,C):c},C.domainPaddingX=function(t){return arguments.length?(u=t,C):u},C.valueExtractorX=function(t){return arguments.length?(s=t,C):s},C.scaleY=function(t){return arguments.length?(d=t,C):d},C.domainPaddingY=function(t){return arguments.length?(f=t,C):f},C.valueExtractorY=function(t){return arguments.length?(h=t,C):h},C.scaleR=function(t){return arguments.length?(g=t,C):g},C.domainPaddingR=function(t){return arguments.length?(p=t,C):p},C.valueExtractorR=function(t){return arguments.length?(m=t,C):m},C.minRadius=function(t){return arguments.length?(y=t,C):y},C.maxRadius=function(t){return arguments.length?(x=t,C):x},C.pointStrokeWidth=function(t){return arguments.length?(b=t,C):b},C.colorFunction=function(t){return arguments.length?(k=t,C):k},C.backgroundFill=function(t){return arguments.length?(w=t,C):w},C.namespace=function(t){return arguments.length?(A=t,C):A},C.objectClass=function(t){return arguments.length?(M=t,C):M},C.transitionDuration=function(t){return arguments.length?(E=t,C):E},C.easeFunc=function(t){return arguments.length?(O=t,C):O},C.pointKeys=function(t){return arguments.length?(o=t,C):o},C.valuesX=function(t){return arguments.length?(a=t,C):a},C.valuesY=function(t){return arguments.length?(i=t,C):i},C.valuesR=function(t){return arguments.length?(l=t,C):l},C.tooltip=function(t){return arguments.length?(L=t,C):L},C},O.plotZoom=function(t,e,r){var o,i=20,l=void 0==t.orient?"horizontal":t.orient(),c=t.spaceX(),u=t.spaceY(),s=t.selection(),d=e.selection(),f=r.selection();function h(){var e=s.select("."+a(t.namespace(),"object-container")),r=n(e.attr("transform")),o=e.attr("transform","translate(0,0)");c=s.node().getBBox().width-.9*t.spaceX(),u=s.node().getBBox().height-.9*t.spaceY(),o.attr("transform","translate("+r[0]+","+r[1]+")"),m("plotZoom","setLocks",{xLock:c,yLock:u})}function g(){var g,p;h(),"2D"==l&&(g=!0,p=!0),"horizontal"==l&&(g=!0,p=!1),"vertical"==l&&(p=!0,g=!1);var m=d3.event.transform,v=s.node().getBBox(),y=d.node().getBBox(),x=d.node().getBBox();if(v.width,v.x,v.height,v.y,y.width,y.height,x.width,x.height,"wheel"==o){d3.event.preventDefault();var b=d3.event.deltaY*i,k=d3.event.shiftKey;(m="2D"==l?k?{k:1,x:b,y:0}:{k:1,x:0,y:b}:g?{k:1,x:b,y:0}:{k:1,x:0,y:b}).applyX=function(t){return t*this.k+-1*this.x},m.applyY=function(t){return t*this.k+-1*this.y}}var w=s.select("."+a(t.namespace(),"object-container")),S=d.select("."+a(e.namespace(),"object-container")),j=f.select("."+a(r.namespace(),"object-container")),z=n(w.attr("transform")),A=(n(S.attr("transform")),n(j.attr("transform")),g?m.applyX(z[0]):0);g&&(A=A<-c?(m.x=0,-c):(m.x=0,Math.min(A,0)));var M=p?m.applyY(z[1]):0;p&&(M=M<-u?(m.y=0,-u):(m.y=0,Math.min(M,0))),w.attr("transform","translate("+A+","+M+")"),g&&S.attr("transform","translate("+A+",0)"),p&&j.attr("transform","translate(0,"+M+")")}return d3.select(s.thisSVG()),g.eventType=function(t){return arguments.length?(o=t,g):o},g.wheelSpeed=function(t){return arguments.length?(i=t,g):i},g.orient=function(t){return arguments.length?(l=t,g):l},g.xLock=function(t){return arguments.length?(c=t,g):c},g.yLock=function(t){return arguments.length?(u=t,g):u},g.setLocks=h,g.reset=function(){var n=s.select("."+a(t.namespace(),"object-container")),o=d.select("."+a(e.namespace(),"object-container")),i=f.select("."+a(r.namespace(),"object-container"));n.attr("transform","translate(0,0)"),o.attr("transform","translate(0,0)"),i.attr("transform","translate(0,0)")},g},O.multiPlotZoom=function(t){var e,r=20,o=void 0==t.orient?"horizontal":t.orient(),i=t.spaceX(),l=t.spaceY(),c=t.selection(),u=(d3.select(c.thisSVG()),[]),s=[];function d(){var e=c.select("."+a(t.namespace(),"object-container")),r=n(e.attr("transform")),o=e.attr("transform","translate(0,0)");i=c.node().getBBox().width-t.spaceX(),l=c.node().getBBox().height-t.spaceY(),o.attr("transform","translate("+r[0]+","+r[1]+")"),m("plotZoom","setLocks",{xLock:i,yLock:l})}function f(){d();var f,h,g=u.map(function(t,e){return t.selection()}),p=s.map(function(t,e){return t.selection()});"2D"==o&&(f=!0,h=!0),"horizontal"==o&&(f=!0,h=!1),"vertical"==o&&(h=!0,f=!1);var m=d3.event.transform,v=c.node().getBBox();if(g.map(function(t,e){return t.node().getBBox()}),g.map(function(t,e){return t.node().getBBox()}),v.width,v.x,v.height,v.y,"wheel"==e){d3.event.preventDefault();var y=d3.event.deltaY*r,x=d3.event.shiftKey;(m="2D"==o?x?{k:1,x:y,y:0}:{k:1,x:0,y:y}:f?{k:1,x:y,y:0}:{k:1,x:0,y:y}).applyX=function(t){return t*this.k+-1*this.x},m.applyY=function(t){return t*this.k+-1*this.y}}var b=c.select("."+a(t.namespace(),"object-container")),k=g.map(function(t,e){return t.select("."+a(u[e].namespace(),"object-container"))}),w=p.map(function(t,e){return t.select("."+a(s[e].namespace(),"object-container"))}),S=n(b.attr("transform")),j=(k.map(function(t,e){return n(t.attr("transform"))}),w.map(function(t,e){return n(t.attr("transform"))}),f?m.applyX(S[0]):0);f&&(j=j<-i?(m.x=0,-i):(m.x=0,Math.min(j,0)));var z=h?m.applyY(S[1]):0;h&&(z=z<-l?(m.y=0,-l):(m.y=0,Math.min(z,0))),b.attr("transform","translate("+j+","+z+")"),f&&k.map(function(t,e){t.attr("transform","translate("+j+",0)")}),h&&w.map(function(t,e){t.attr("transform","translate(0,"+z+")")})}return f.eventType=function(t){return arguments.length?(e=t,f):e},f.wheelSpeed=function(t){return arguments.length?(r=t,f):r},f.orient=function(t){return arguments.length?(o=t,f):o},f.xLock=function(t){return arguments.length?(i=t,f):i},f.yLock=function(t){return arguments.length?(l=t,f):l},f.xComponents=function(t){return arguments.length?(u=t,f):u},f.yComponents=function(t){return arguments.length?(s=t,f):s},f.setLocks=d,f.reset=function(){var e=c.select("."+a(t.namespace(),"object-container")),n=xAxisSel.select("."+a(xAxis.namespace(),"object-container")),r=yAxisSel.select("."+a(yAxis.namespace(),"object-container"));e.attr("transform","translate(0,0)"),n.attr("transform","translate(0,0)"),r.attr("transform","translate(0,0)")},f},O.violin=function(t){var e,n,a,i,l,u,d,g,p="horizontal",m=!0,b=!0,w=function(t,n){return e[t]},A=function(t,n){return d3.descending(e[t],e[n])},M=d3.scaleLinear(),E=.5,O=.05,L=50,C=100,F=2,Q=j(),B=function(t,e,n,o,a){var i=d3.scaleLinear().domain([o,a]).range([-.25,.05]),l=r(n.replace("#",""),i(t)),c="stroke"==e?0:.25;return r(l.replace("#",""),c)},q=3,V=2,D="transparent",_="d3sm-violin",K="violin",Y=1e3,P=d3.easeExp,X=["Q0","Q1","Q2","Q3","Q4"],R=z().keys([X[4],X[3],X[2],X[1],X[0]]),W=z(),N=function(t,e){return e.points},T=function(t,e){return e[t].value};function G(){var r,u,w,j="horizontal"==p,G=v(t,_,{x:0,y:0,width:n,height:a},D),H=void 0==i?d3.keys(e).sort(A):i;l=f(H);var Z=function(){var t,e,n=!0,r=["Q0","Q1","Q2","Q3","Q4"];function a(a,i){var l=i[a],c=t(a,l),u=d3.keys(c),s=u.map(function(t,n){return e(t,c)}),d=o(s,r),f=d3.histogram()(s),h=f.map(function(t){return t.length}),g=n?{x:0,y:d3.min(s)}:{x:d3.min(s),y:0},p=n?{x:0,y:d3.max(s)}:{x:d3.max(s),y:0},m=f.map(function(t,e){return n?{y:t.length?d3.median(t):d3.median([t.x0,t.x1]),x:h[e]}:{x:t.length?d3.median(t):d3.median([t.x0,t.x1]),y:h[e]}});m=[g].concat(m).concat([p]),l.binned=f,l.frequencies=h,l.contour=m,l.quartiles=d,l.pointKeys=u,l.pointValues=s}return a.horizontalQ=function(t){return arguments.length?(n=t,a):n},a.quartileKeys=function(t){return arguments.length?(r=t,a):r},a.violinPointsExtractor=function(e){return arguments.length?(t=e,a):t},a.violinPointValueExtractor=function(t){return arguments.length?(e=t,a):e},a}().horizontalQ(j).quartileKeys(X).violinPointsExtractor(N).violinPointValueExtractor(T);l.map(function(t,n){Z(t,e)});var I=l.length,J=(r=[]).concat.apply(r,S(l.map(function(t,n){return e[t].quartiles[X[0]]}))),U=(u=[]).concat.apply(u,S(l.map(function(t,n){return e[t].quartiles[X[X.length-1]]}))),$=[Math.min.apply(Math,S(J))-E,Math.max.apply(Math,S(U))+E];M.domain($).range(j?[0,a]:[0,n]);var tt=j?n:a;d=y(tt,I,L,C,O,m),g=x(H,tt,d,I,O,m),k().horizontalQ(j).scale(M).moveby("category").numberOfObjects(I).objectClass(K).objectSize(d).spacerSize(g).transitionDuration(Y).easeFunc(P).namespace(_)(G,H,0);var et=[];G.selectAll("g:not(.to-remove)."+K).each(function(t,e){s(l,t)&&et.push(Number(d3.select(this).attr("parent-index")))}),Q="index"==Q.colorBy()?Q.dataExtent([0,Math.max.apply(Math,et)]):Q.dataExtent($);var nt=Math.max.apply(Math,S((w=[]).concat.apply(w,S(l.map(function(t,n){return d3.max(e[t].frequencies)}))))),rt=d3.scaleLinear().domain([0,nt]).range([0,d/2]),ot=d3.line().x(function(t,e){return j?-rt(t.x):M(t.x)}).y(function(t,e){return j?M($[1])-M(t.y):-rt(t.y)}).curve(d3.curveBasis),at=d3.line().x(function(t,e){return j?rt(t.x):M(t.x)}).y(function(t,e){return j?M($[1])-M(t.y):rt(t.y)}).curve(d3.curveBasis);G.selectAll("g:not(.to-remove)."+K).each(function(t,n){var r=d3.select(this),o=e[t];if(s(l,t)){n=void 0==r.attr("parent-index")?n:r.attr("parent-index");var a=Q(t,o,n,"fill"),i=Q(t,o,n,"stroke"),u=c(r,"g","area"),f=c(u,"path","left"),g=c(u,"path","right"),p=c(r,"g","quarts"),m=(c(p,"line","q3"),c(p,"line","q1"),o.quartiles[X[3]],o.quartiles[X[2]]);if(o.quartiles[X[1]],r.attr("transform",j?"translate("+d/2+",0)":"translate(0,"+d/2+")"),f.transition().duration(Y).attr("d",function(t,e){return ot(o.contour)}).attr("fill",a).attr("stroke",i).attr("stroke-width",F),g.transition().duration(Y).attr("d",function(t,e){return at(o.contour)}).attr("fill",a).attr("stroke",i).attr("stroke-width",F),u.node().addEventListener("mouseover",function(t,e){G.selectAll("g."+K).style("opacity",.2),r.style("opacity",1),f.attr("stroke-width",2*F),g.attr("stroke-width",2*F)}),u.node().addEventListener("mouseout",function(t,e){G.selectAll("g."+K).style("opacity",1),f.attr("stroke-width",F),g.attr("stroke-width",F)}),b){var v=c(r,"g","points"),y=v.selectAll(".point").data(o.pointKeys);y.on("mouseover",null),y.exit().transition().ease(P).duration(Y).attr("r",0).attr("cy",j?M($[1])-M(m):rt(0)).attr("cx",j?rt(0):M(m)).remove();var x=y.enter().append("circle").attr("class","point").attr("r",0).attr("cx",j?0:M(m)).attr("cy",j?M(m):0);y=y.merge(x),z().selection(y).data(N(t,o)).header(W.header()).keys(W.keys()).values(W.values())();var k=d3.min(o.pointValues),w=d3.max(o.pointValues);y.transition().duration(Y).ease(P).attr("r",q).attr("cy",function(t,e){var n=o.pointValues[e];if(j)return M($[1])-M(n);var r=h(o.binned,n),a=Math.random(),i=rt(a*o.frequencies[r]*.5);return Math.random()>.5?i:-i}).attr("cx",function(t,e){var n=o.pointValues[e];if(j){var r=h(o.binned,n),a=Math.random(),i=rt(a*o.frequencies[r]*.5);return Math.random()>.5?i:-i}return M(n)}).attr("stroke",function(t,e){return t=o.pointValues[e],B(t,"stroke",i,k,w)}).attr("fill",function(t,e){return t=o.pointValues[e],B(t,"fill",i,k,w)}).attr("stroke-width",V),v.selectAll("circle.point").on("mouseover",function(t,e){G.selectAll("g."+K).style("opacity",.2),r.style("opacity",1),f.attr("stroke-width",2*F),g.attr("stroke-width",2*F),G.selectAll(".point").style("opacity",.2),d3.select(this).style("opacity",1).attr("r",2*q).attr("stroke-width",2*V)}),v.selectAll("circle.point").on("mouseout",function(t,e){var n=document.createEvent("SVGEvents");n.initEvent("mouseout",!0,!0),u.node().dispatchEvent(n),G.selectAll(".point").style("opacity",1),d3.select(this).attr("stroke-width",V).attr("r",q)})}else cV.selectAll(".point").transition().duration(Y).ease(P).attr("r",0).attr("cy",j?M($[1])-M(m):rt(0)).attr("cx",j?rt(0):M(m)).remove()}}),R.selection(G.selectAll("g:not(.to-remove)."+K+" .area")),void 0==R.data()&&R.data(e),R(),void 0==R.values()&&R.values([function(t,e){return t.quartiles[e]},function(t,e){return t.quartiles[e]},function(t,e){return t.quartiles[e]},function(t,e){return t.quartiles[e]},function(t,e){return t.quartiles[e]}])}return G.violinPointsExtractor=function(t){return arguments.length?(N=t,G):N},G.violinPointValueExtractor=function(t){return arguments.length?(T=t,G):T},G.selection=function(e){return arguments.length?(t=e,G):t},G.data=function(t){return arguments.length?(e=t,G):e},G.orient=function(t){return arguments.length?(p=t,G):p},G.spaceX=function(t){return arguments.length?(n=t,G):n},G.spaceY=function(t){return arguments.length?(a=t,G):a},G.overflowQ=function(t){return arguments.length?(m=t,G):m},G.pointsQ=function(t){return arguments.length?(b=t,G):b},G.grouping=function(t){return arguments.length?(i=t,G):i},G.valueExtractor=function(t){return arguments.length?(w=t,G):w},G.sortingFunction=function(t){return arguments.length?(A=t,G):A},G.scale=function(t){return arguments.length?(M=t,G):M},G.domainPadding=function(t){return arguments.length?(E=t,G):E},G.objectSpacer=function(t){return arguments.length?(O=t,G):O},G.minObjectSize=function(t){return arguments.length?(L=t,G):L},G.maxObjectSize=function(t){return arguments.length?(C=t,G):C},G.objectStrokeWidth=function(t){return arguments.length?(F=t,G):F},G.colorFunction=function(t){return arguments.length?(Q=t,G):Q},G.pointColorFunc=function(t){return arguments.length?(B=t,G):B},G.pointRadius=function(t){return arguments.length?(q=t,G):q},G.pointStrokeWidth=function(t){return arguments.length?(V=t,G):V},G.backgroundFill=function(t){return arguments.length?(D=t,G):D},G.namespace=function(t){return arguments.length?(_=t,G):_},G.objectClass=function(t){return arguments.length?(K=t,G):K},G.transitionDuration=function(t){return arguments.length?(Y=t,G):Y},G.easeFunc=function(t){return arguments.length?(P=t,G):P},G.quartileKey=function(t){return arguments.length?(quartileKey=t,G):quartileKey},G.quartileKeys=function(t){return arguments.length?(X=t,G):X},G.violinKeys=function(t){return arguments.length?(l=t,G):l},G.violinValues=function(t){return arguments.length?(u=t,G):u},G.objectSize=function(t){return arguments.length?(d=t,G):d},G.spacerSize=function(t){return arguments.length?(g=t,G):g},G.tooltip=function(t){return arguments.length?(R=t,G):R},G.pointsTooltip=function(t){return arguments.length?(W=t,G):W},G},O.numericLegend=function(t){var e,n,r=0,o=1,l=j(),u="d3sm-linear-vertical-gradient",s=12,d="transparent",f="black",h=2;function g(){var g=v(t,u,{x:0,y:0,width:e,height:n},d),p=c(c(t,"defs"),"linearGradient").attr("x1","0%").attr("y1","100%").attr("x2","0%").attr("y2","0%").attr("id",a(u,"numerical-legend-gradient"));l.dataExtent([r,o]).colorBy("value").valueExtractor(function(t,e,n){return e}),p.selectAll("stop").data(l.colors()).enter().append("stop").attr("offset",function(t,e){return e/(l.colors().length-1)}).attr("stop-color",function(t){return t});var m=c(g,"rect","legend").attr("transform","translate(0,"+s+")").style("fill","url(#"+a(u,"numerical-legend-gradient")+")").attr("x",0).attr("y",0).attr("width",e).attr("height",n-2*s).on("mousemove",function(t,e){!function(t,e,n,d){var g=d3.scaleLinear().domain([0,n.attr("height")]).range([o,r]),p=d3.mouse(n.node()),m=i(g(p[1]),h),v=l(void 0,m,void 0,"stroke"),y=l(void 0,m,void 0,"fill");c(c(d3.select("body"),"div",a(u,"legend-tooltip")).attr("id",a(u,"legend-tooltip")).style("position","absolute").style("left",d3.event.pageX+15+"px").style("top",d3.event.pageY+15+"px").style("background-color",y).style("border-color",v).style("min-width",s*(String(o).split(".")[0].length+3)+"px").style("min-height",s*(String(o).split(".")[0].length+3)+"px").style("border-radius","50%").style("border-radius","5000px").style("display","flex").style("justify-content","center").style("text-align","middle").style("padding","2px").style("border-style","solid").style("border-width",2),"div").text(m).style("color",f).style("align-self","center")}(0,0,m,d3.select(this))}).on("mouseout",function(t,e){d3.select("#"+a(u,"legend-tooltip")).remove()});c(g,"text","min").text(i(r,2)).attr("text-anchor","middle").attr("font-size",s+"px").attr("transform",function(t,r){return"translate("+e/2+","+(n-s/4)+")"}),c(g,"text","max").text(i(o,2)).attr("text-anchor","middle").attr("font-size",s+"px").attr("transform",function(t,n){return"translate("+e/2+","+s+")"})}return g.min=function(t){return arguments.length?(r=t,g):r},g.max=function(t){return arguments.length?(o=t,g):o},g.spaceX=function(t){return arguments.length?(e=t,g):e},g.spaceY=function(t){return arguments.length?(n=t,g):n},g.namespace=function(t){return arguments.length?(u=t,g):u},g.fontSize=function(t){return arguments.length?(s=t,g):s},g.backgroundFill=function(t){return arguments.length?(d=t,g):d},g.colorFunction=function(t){return arguments.length?(l=t,g):l},g.textColor=function(t){return arguments.length?(f=t,g):f},g.roundTo=function(t){return arguments.length?(h=t,g):h},g},O.categoricLegend=function(t){var e,n,r,o,a,i="horizontal",l=!1,u=function(t,e){return n[t]},s=function(t,e){return d3.ascending(t,e)},d=.05,h=10,g=100,p=2,m=j(),b="transparent",w="d3sm-legend",S="legend",z=1e3,A=d3.easeExp;function M(){var n="horizontal"==i,u=!n,j=v(t,w,{x:0,y:0,width:r,height:o},b);m.dataExtent([0,e.length-1]).colorBy("categories").categoryExtractor(function(t,e,n){return e});var M=Math.min(r,o),E=e.length,O=void 0==a?e.sort(s):a,L=f(O),C=n?r:o,F=y(C,E,h,g,d,l),Q=x(L,C,F,E,d,l);k().horizontalQ(n).scale(scale).moveby("category").numberOfObjects(E).objectClass(S).objectSize(F).spacerSize(Q).transitionDuration(z).easeFunc(A).namespace(w)(j,O,0),M=Math.min(F,r,o)/2-p,j.selectAll("g:not(.to-remove)."+S).each(function(t,e){var o=d3.select(this),a=c(o,"circle"),i=m(void 0,t,e,"fill"),l=m(void 0,t,e,"stroke"),s=n?M+p:(r-2*M)/2+M,d=u?M+p:(r-2*M)/2+M;a.attr("r",M).attr("cx",s).attr("cy",d).attr("fill",i).attr("stroke",l).attr("stroke-width",p);var f=c(o,"text");f.text(t).attr("text-anchor","middle").attr("transform",function(t,e){return"translate("+s+","+(d+f.node().getBoundingClientRect().height/4)+")"})})}return M.categories=function(t){return arguments.length?(e=t,M):e},M.selection=function(e){return arguments.length?(t=e,M):t},M.data=function(t){return arguments.length?(n=t,M):n},M.orient=function(t){return arguments.length?(i=t,M):i},M.spaceX=function(t){return arguments.length?(r=t,M):r},M.spaceY=function(t){return arguments.length?(o=t,M):o},M.overflowQ=function(t){return arguments.length?(l=t,M):l},M.grouping=function(t){return arguments.length?(a=t,M):a},M.valueExtractor=function(t){return arguments.length?(u=t,M):u},M.sortingFunction=function(t){return arguments.length?(s=t,M):s},M.objectSpacer=function(t){return arguments.length?(d=t,M):d},M.minObjectSize=function(t){return arguments.length?(h=t,M):h},M.maxObjectSize=function(t){return arguments.length?(g=t,M):g},M.bubbleStrokeWidth=function(t){return arguments.length?(p=t,M):p},M.colorFunction=function(t){return arguments.length?(m=t,M):m},M.backgroundFill=function(t){return arguments.length?(b=t,M):b},M.namespace=function(t){return arguments.length?(w=t,M):w},M.objectClass=function(t){return arguments.length?(S=t,M):S},M.transitionDuration=function(t){return arguments.length?(z=t,M):z},M.easeFunc=function(t){return arguments.length?(A=t,M):A},M},O.lasso=E,O.lassoWidget=function(t){var e,n,r,o,i,l,u,s,d="d3sm-lasso",f=(t=t,d3.line().x(function(t,e){return t[0]}).y(function(t,e){return t[1]}).curve(d3.curveLinearClosed),j());function h(t,e){console.log(t,e)}function g(){d3.select("html").select("style."+d+"lasso-widget").empty()&&d3.select("html").append("style").classed(d+"lasso-widget",!0).html("."+a(d,"data-table")+"{ height:100px; overflow:auto; }")}function p(t){console.log(t)}function m(){p((t.select("."+a(d,"tab-list")),t.select("."+a(d,"tab-content")).selectAll("."+a(d,"data-table")),{}))}function v(e,n){var r,o;t.select("#"+a(d,"tab",e)),t.select("#"+a(d,"tab","pane",e)),function(){var e=t.select("."+a(d,"tab-list")),n=(t.select("."+a(d,"tab-content")),e.selectAll("."+a(d,"tab")));if(0==n.size());else{var r=n.nodes()[n.size()-1];d3.select(r).select("a").attr("href")}}(),r=t.select("."+a(d,"tab-list")),o=t.select("."+a(d,"tab-content")),r=r.selectAll("."+a(d,"tab")),o=o.selectAll("."+a(d,"tab","pane")),r.each(function(t,e){d3.select(this).datum(e).attr("id",a(d,"tab",e)).select("a").attr("href","#"+a(d,"tab","pane",e)).text(function(t,n){var r=d3.select(this).text();return"Group"==r.split(" ")[0]?"Group "+e:r})}),o.each(function(t,e){d3.select(this).datum(e).attr("id",a(d,"tab","pane",e)),c(d3.select(this),"p","lead").text(function(t,n){var r=d3.select(this).text();return"Group"==r.split(" ")[0]?"Group "+e:r}),c(d3.select(this),"button","remove-btn").on("click",v)})}function y(t,i){var h=c(t,"p","lead").text("Group "+i),g=c(c(t,"div","table-responsive").attr("class",a(d,"data-table")),"table","table").classed("table-sm",!0).classed("table-hover",!0),p=(c(g,"caption","caption").html("List of selected"),c(t,"div","text-right")),m=i%f.colors().length;i%2!=0&&(m=f.colors().length-1-m);var y,k,w,S=function(t){var e=c(t,"button","lasso-btn").classed("btn btn-info",!0).classed(d,!0);return c(e,"i","fa").classed("fa-hand-pointer-o",!0),c(e,"span").text("Lasso select"),e}(p),j=(y=i,k=f.colors()[m],E().namespace(d).svg(e).objectClass(o).chartContainer(n).objectContainer(r).instance(y).color(k).yScale(s).xScale(u));!function(t,e,r,o){r.eventCatcher(t),t.node().addEventListener("click",x),t.datum([r]).on(a(d,"render"),function(){d3.select(this).datum()[0].draw()}).on(a(d,"drag"),function(t){var e=n.selectAll(".in-lasso-"+t[0].instance()).nodes(),a=e.map(function(t,e){var n=l(d3.select(t).datum());return n.__node=t,n});b(o,a,r)}),e.on("click",function(){r.allPoints([]),r.currentPoints([]),t.dispatch(a(d,"drag"))})}(S,function(t){var e=c(t,"button","clear-btn").classed("btn btn-light",!0).classed(d,!0);return c(e,"i","fa").classed("fa-eraser",!0),c(e,"span").text("Clear selection"),e}(p),j,g),c(w=c(p,"button","remove-btn").classed("btn btn-danger",!0).on("click",v),"i","fa").classed("fa-trash-o",!0),c(w,"span").text("Remove group"),h.on("mouseover",function(){j.draw()}),h.on("mouseout",function(){j.remove()})}function x(){var e=d3.select(this),n=e.datum()[0];n.toggle();var r=n.activeQ();function o(t){t.target!=e.node()&&t.target!=e.select("span").node()&&t.target!=e.select("i").node()&&(n.toggle(!1),e.classed("btn-info",!0),e.classed("btn-warning",!1),e.select("span").text("Lasso select"))}n.activeQ()?(e.classed("btn-info",!r),e.classed("btn-warning",r),e.select("span").text("Lasso select (active)"),t.selectAll("."+d+".lasso-btn").dispatch(a(d,"render")),d3.select("html").node().addEventListener("mousedown",o)):(e.classed("btn-info",!r),e.classed("btn-warning",r),e.select("span").text("Lasso select"),d3.select("html").node().removeEventListener("mousedown",o))}function b(t,e,n){var r=c(c(t,"thead"),"tr"),o=c(t,"tbody"),a=function(t,e){var n=d3.keys(e[0]).filter(function(t){return"__node"!=t});n.length>0&&n.push("remove");var r=t.selectAll("th");return(r=r.data(n)).exit().remove(),r=r.merge(r.enter().append("th").attr("scope","col")).text(function(t,e){return t}),n}(r,e);(function(t,e){var n=t.selectAll("tr");return(n=n.data(e)).exit().remove(),n=n.merge(n.enter().append("tr"))})(o,e).each(function(r,o){var i=d3.select(this);!function(t,e,n,r,o,a){(t=t.data(e)).exit().remove(),(t=t.merge(t.enter().append("td"))).html(function(t,e){return"remove"!=t?n[t]:""}).classed("text-left",function(t,e){return"remove"==t}),t.select("i.fa-close").on("click",function(t,e){var i=n.__node,l=d3.select(i);l.classed("in-lasso",!1),l.classed("in-lasso-"+o.instance(),!1),r.map(function(t,e){t.__node==i&&(r.splice(e,1),b(a,r,o))})})}(i.selectAll("td"),a,r,e,n,t),i.on("mouseover",function(t,e){n.applyObjectAttributes(d3.select(t.__node),!0)}).on("mouseout",function(t,e){n.applyObjectAttributes(d3.select(t.__node),!1)})})}function k(e,n){var r=t.select("."+a(d,"tab-list")),o=t.select("."+a(d,"tab-content")),l=function(){for(var e=t.select("."+a(d,"tab-list")).selectAll("li").size()-3,n="Group "+e,r=[];r.includes(n);)n="Group "+(e+=1);return e}();if(r.selectAll("."+a(d,"tab")).size()!=i){!function(t,e){var n=t.insert("li",".right-aligned-tabs").classed("nav-item",!0).classed("alert",!0).classed("alert-secondary",!0).classed("alert-dismissable",!0).classed("fade",!0).classed("show",!0).attr("role","alert").attr("id",a(d,"tab",e)).classed(a(d,"tab"),!0);c(n,"a").attr("data-toggle","tab").text("Group "+e).attr("href","#"+a(d,"tab","pane",e)).on("dblclick",function(t,e){var n=d3.select(this);n.attr("contenteditable",!0),d3.select(n.node().parentNode).classed("alert-secondary",!1).classed("alert-warning",!0)}).on("blur",function(t,e){var n=d3.select(this);n.attr("contenteditable",!1),d3.select(n.node().parentNode).classed("alert-secondary",!0).classed("alert-warning",!1)}).on("input",function(t,e){var n=d3.select(this),r=n.text();d3.select(n.attr("href")).select("p.lead").text(r)})}(r,l);var u=function(t,e){return t.append("div").datum(e).attr("role","tabpanel").classed("tab-pane",!0).classed("text-left",!0).classed(a(d,"tab","pane"),!0).attr("id",a(d,"tab","pane",e))}(o,l);y(u,l),u.attr("id"),t.select("."+a(d,"tab-content"))}else h("only "+i+" allowed.","warning")}return w=c(t,"div","card"),S=c(c(w,"div","card-header"),"ul","nav").classed("nav-tabs card-header-tabs",!0).classed(a(d,"tab-list"),!0).attr("role","tablist"),z=c(c(w,"div","card-body"),"div","tab-content").classed(a(d,"tab-content"),!0),A=c(S,"div","right-aligned-tabs").classed("nav ml-auto ",!0),function(t){c(c(c(t,"li",a(d,"plus-tab")).classed("ml-auto",!0).classed("nav-item",!0).on("click",k),"a","nav-link"),"i","fa").classed("fa-plus fa-2x text-success",!0)}(A),function(t){c(c(c(t,"li",a(d,"send-tab")).classed("ml-auto",!0).classed("nav-item",!0).on("click",m),"a","nav-link"),"i","fa").classed("fa-paper-plane-o fa-2x text-primary",!0)}(A),function(t){c(c(c(t,"li",a(d,"close-tab")).classed("ml-auto",!0).classed("nav-item",!0).on("click",function(){d3.mouse(d3.select("html").node())}),"a","nav-link"),"i","fa").classed("fa-window-close-o fa-2x text-danger",!0)}(A),c(c(z,"div","tab-pane").classed(a(d,"default-tab"),!0).classed("active",!0).classed("text-left",!0),"div").html("Click to add a new group.
Click to submit for re-analysis.
Click to close the dataselect widget."),g.objectClass=function(t){return arguments.length?(o="."+t.replace(".",""),g):o},g.svg=function(t){return arguments.length?(e=t,g):e},g.submit=function(t){return arguments.length?(p=t,g):p},g.maxNumberOfGroups=function(t){return arguments.length?(i=t,g):i},g.onError=function(t){return arguments.length?(h=t,g):h},g.objectContainer=function(t){return arguments.length?(r=t,g):r},g.chartContainer=function(t){return arguments.length?(n=t,g):n},g.dataExtractor=function(t){return arguments.length?(l=t,g):l},g.xScale=function(t){return arguments.length?(u=t,g):u},g.yScale=function(t){return arguments.length?(s=t,g):s},g;var w,S,z,A},O.selectFilter=A,O.upset=function(t){var e,n,r,o,i,l,u,s,f,h,g,p="horizontal",m=!1,b=20,w=50,S=2,j="transparent",z="d3sm-upset",A="upset",M=1e3,E=d3.easeExp,O=function(t,n){return e[t].set},L=function(t,n){return e[t].intersection},C=function(t,n){return e[t].elements},F=.05,Q=.05,B=function(t,e){return i.indexOf(O(t))-i.indexOf(O(e))},q=function(t,e){return l.indexOf(L(t))-l.indexOf(L(e))};function V(){var S="horizontal"==p,C=!S,V=v(t,z,{x:0,y:0,width:n,height:r},j);o=d3.keys(e),i=d(o.map(O)).sort(),l=d(o.map(L)).sort().sort(function(t,e){return t.split(";").length-e.split(";").length}),S?o.sort(function(t,e){return q(t,e)||B(t,e)}):o.sort(function(t,e){return B(t,e)||q(t,e)});var D=S?l:i,_=S?i:l,K=S?D.length:_.length,Y=S?_.length:D.length;h=y(n,K,b,w,F,m),s=y(r,Y,b,w,Q,m),g=x(D,n,h,K,F,m),f=x(_,r,s,Y,Q,m);var P=k().horizontalQ(!1).moveby("category").numberOfObjects(Y).objectSize(s).spacerSize(f).transitionDuration(M).easeFunc(E),X=k().horizontalQ(!0).moveby("category").numberOfObjects(K).objectClass(A).objectSize(h).spacerSize(g).transitionDuration(M).easeFunc(E);C?(X.objectClass(A),P.namespace("across").objectClass(a(A,"across")),P(V,_,0),V.selectAll("g."+a(A,"across")).each(function(t,e){X(d3.select(this),D,0)})):(X.namespace("across").objectClass(a(A,"across")),P.objectClass(A),X(V,D,0),V.selectAll("g."+a(A,"across")).each(function(t,e){P(d3.select(this),_,0)}));var R=V.selectAll("g:not(.to-remove)."+A),W={};o.map(function(t,e){W[O(t)+"::"+L(t)]=t}),R.data(o),R.each(function(t,n){var r=d3.select(this);if(void 0!=t){e[t];var o=O(t,n),i=L(t,n);r.classed(i,!0),r.classed(o,!0),c(r,"circle",a(A,"circle")).attr("cx",h/2).attr("cy",s/2).attr("r",void 0==u?Math.min(h,s)/2:u).attr("fill",i.includes(o)?"black":"rgb(233,233,233)").attr("stroke","black").attr("in-intersection",i.includes(o))}})}return V.selection=function(e){return arguments.length?(t=e,V):t},V.data=function(t){return arguments.length?(e=t,V):e},V.orient=function(t){return arguments.length?(p=t,V):p},V.spaceX=function(t){return arguments.length?(n=t,V):n},V.spaceY=function(t){return arguments.length?(r=t,V):r},V.overflowQ=function(t){return arguments.length?(m=t,V):m},V.minObjectSize=function(t){return arguments.length?(b=t,V):b},V.maxObjectSize=function(t){return arguments.length?(w=t,V):w},V.circleStrokeWidth=function(t){return arguments.length?(S=t,V):S},V.backgroundFill=function(t){return arguments.length?(j=t,V):j},V.namespace=function(t){return arguments.length?(z=t,V):z},V.objectClass=function(t){return arguments.length?(A=t,V):A},V.transitionDuration=function(t){return arguments.length?(M=t,V):M},V.easeFunc=function(t){return arguments.length?(E=t,V):E},V.cellKeys=function(t){return arguments.length?(o=t,V):o},V.setValues=function(t){return arguments.length?(i=t,V):i},V.intersectionValues=function(t){return arguments.length?(l=t,V):l},V.xObjectSpacer=function(t){return arguments.length?(F=t,V):F},V.yObjectSpacer=function(t){return arguments.length?(Q=t,V):Q},V.radius=function(t){return arguments.length?(u=t,V):u},V.setExtractor=function(t){return arguments.length?(O=t,V):O},V.intersectionExtractor=function(t){return arguments.length?(L=t,V):L},V.elementExtractor=function(t){return arguments.length?(C=t,V):C},V.setKeySortingFunction=function(t){return arguments.length?(B=t,V):B},V.intersectionKeySortingFunction=function(t){return arguments.length?(q=t,V):q},V.yObjectSize=function(t){return arguments.length?(s=t,V):s},V.ySpacerSize=function(t){return arguments.length?(f=t,V):f},V.xObjectSize=function(t){return arguments.length?(h=t,V):h},V.xSpacerSize=function(t){return arguments.length?(g=t,V):g},V.intersectionTotals=function(){var t={};return l.map(function(e,n){t[e]={total:0}}),o.map(function(e,n){var r=C(e,n);0==t[L(e,n)].total&&(Array.isArray(r)?(t[L(e,n)].total+=r.length,t[L(e,n)].values=r):t[L(e,n)].total+=r)}),t},V.setTotals=function(){var t={};return i.map(function(e,n){t[e]={total:0}}),o.map(function(e,n){var r=C(e,n);Array.isArray(r)?t[O(e,n)].total+=r.length:t[O(e,n)].total+=r}),t},V},O.filterTable=function(t){var e,n="d3sm-filter-table",r=function(t,e,n){return n};function o(){var o=c(t,"div","filter-table").classed(a(n,"container"),!0),u=c(o,"div","filter-input-group").classed("input-group",!0),s=(c(c(c(u,"div","input-group-prepend"),"span","input-group-text").classed("search-button",!0),"i","fa fa-search"),c(u,"input","form-control").attr("placeholder","filter").attr("type","text")),d=c(c(u,"div","input-group-append"),"a","close-button").classed("btn btn-outline-secondary",!0),f=(c(d,"i","fa fa-close"),d),h=c(c(o,"div","table-responsive"),"table","table").classed("table-hover",!0).classed("table-bordered",!0).classed("table-striped",!0),g=c(c(h,"thead").classed("thead-dark",!0),"tr"),p=c(h,"tbody"),m=d3.keys(e),v=d3.keys(e[m[0]]);(function(t,e){var n=t.selectAll("th");(n=n.data(e)).exit().remove(),(n=n.merge(n.enter().append("th"))).attr("scope","col").text(function(t,e){return t})})(g,v),l(i(p,m),v),s.on("input",function(t,n){var o,a=s.property("value"),c=new RegExp(a,"gi");""==a?o=m:(o=[],m.map(function(t,n){var a=e[t],i=v.map(function(t,e){return r(a,t,a[t])}).join("").match(c);null==i||""==i.join("")||o.push(t)})),l(i(p,o),v)}),f.on("click",function(t,e){s.property("value","").dispatch("input")})}function i(t,e){var n=t.selectAll("tr");return(n=n.data(e)).exit().remove(),n=n.merge(n.enter().append("tr"))}function l(t,n){return t.each(function(t,o){var a=e[t],i=d3.select(this).selectAll("td");(i=i.data(n)).exit().remove(),(i=i.merge(i.enter().append("td"))).attr("scope",function(t,e){return 0==e}).html(function(t,e){return r(a,t,a[t])})}),t}return o.data=function(t){return arguments.length?(e=t,o):e},o.namespace=function(t){return arguments.length?(n=t,o):n},o.fieldFunction=function(t){return arguments.length?(r=t,o):r},o},O.uniqueElements=e,O.getTranslation=n,O.modifyHexidecimalColorLuminance=r,O.tickRange=u,O.quartiles=o,O.extractViolinValues=function(t,e,n,r,a,i){var l={};return t.map(function(t,c){var u=n(t,c,e),s=d3.histogram()(u),d=s.map(function(t){return t.length}),f=r?{y:d3.min(u),x:0}:{x:d3.min(u),y:0},h=r?{y:d3.max(u),x:0}:{x:d3.max(u),y:0},g=s.map(function(t,e){return r?{y:t.length?d3.median(t):d3.median([t.x0,t.x1]),x:d[e]}:{x:t.length?d3.median(t):d3.median([t.x0,t.x1]),y:d[e]}}),p=o(u,i),m={values:u,binned:s,frequencies:d,points:[f].concat(g).concat([h])};m[a]=p,l[t]=m}),l},O.hypenate=a,O.round=i,O.getContainingSVG=l,O.interpolateColors=function(){return d3.interpolateRgbBasis(arguments)},O.truncateText=function(t,e,n,r,o,a){var i=t.node().getBoundingClientRect();for(t.text(e);Math.max(i.width,i.height)>o-r&&(e=(e=String(e)).slice(0,e.length-1),t.text(e+"..."),i=t.node().getBoundingClientRect(),0!=e.length););},O.safeSelect=c,O.whichBin=h,O.unique=d,O.flatten=f,O.setupStandardChartContainers=function(t,e,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{top:.01,bottom:.01,left:.01,right:.01},o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{w:.8,h:.6},a=arguments.length>5&&void 0!==arguments[5]?arguments[5]:{y:.1,x:.1},i=arguments.length>6&&void 0!==arguments[6]?arguments[6]:{x:0,margin:0,pos:"left"};void 0==n&&(n={w:window.innerWidth,h:window.Height});var l={w:n.w*o.w,h:n.h*o.h},c={top:r.top*l.h,bottom:r.bottom*l.h,left:r.left*l.w,right:r.right*l.w},u=l.w-c.left-c.right,s=l.h-c.top-c.bottom,d={x:s*a.x,y:u*a.y},f={x:u-d.y-i.x-2*i.margin,y:s-d.x},h={x:i.margin+c.left+("left"==i.pos?0:f.x+d.y),y:c.top,w:i.x,h:f.y},g={x:d.y+c.left+("left"==i.pos?i.x+2*i.margin:0),y:c.top,w:d.y,h:f.y},p={x:d.y+c.left+("left"==i.pos?i.x+2*i.margin:0),y:c.top,w:f.x,h:f.y},m={x:d.y+c.left+("left"==i.pos?i.x+2*i.margin:0),y:c.top+f.y,w:f.x,h:d.x};return n=d3sm.safeSelect(t,"svg",e).style("width",l.w+"px").style("height",l.h+"px"),a=d3sm.safeSelect(n,"g",d3sm.hypenate(e,"axes")),i=d3sm.safeSelect(n,"g",d3sm.hypenate(e,"legend")).attr("transform","translate("+h.x+","+h.y+")"),{svg:{selection:n,rect:l},plot:{selection:d3sm.safeSelect(n,"g",d3sm.hypenate(e,"plot")).attr("transform","translate("+p.x+","+p.y+")"),rect:p},xAxis:{selection:d3sm.safeSelect(a,"g",d3sm.hypenate(e,"x-axis")).attr("transform","translate("+m.x+","+m.y+")"),rect:m},yAxis:{selection:d3sm.safeSelect(a,"g",d3sm.hypenate(e,"y-axis")).attr("transform","translate("+g.x+","+g.y+")"),rect:g},legend:{selection:i,rect:h}}},O.log=m,O.warn=function(t,e,n){!0===window.d3sm.debugQ&&console.warn("%c[d3sm::"+t+"]:\t"+e,["background: #ffd53e","border-radius: 5000px","padding: 0px 2px","font-size: 14px"].join(";")),console.table(n)},O.info=function(t,e,n){window.d3sm.debugQ&&console.info("%c[d3sm::"+t+"]:\t"+e,["background: #009ccd","border-radius: 5000px","padding: 0px 2px","font-size: 14px"].join(";")),console.table(n)},O.error=function(t,e,n){window.d3sm.debugQ&&console.error("[d3sm::"+t+"]:\t"+e+"\t%o",n)},O.consoleGroup=g,O.consoleGroupEnd=p,O.resizeDebounce=function(t,e){var n=function(t,e,n){var r;return function(){var o=this,a=arguments,i=n&&!r;clearTimeout(r),r=setTimeout(function(){r=null,n||t.apply(o,a)},e),i&&t.apply(o,a)}}(function(){t()},e);window.addEventListener("resize",n)},O.debugQ=!1,window.d3sm=O,t.default=O,t}({}); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZDNzbS5taW4udjAuMC4zLmpzIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL2hlbHBlcnMuanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL2FycmF5LWZ1bmN0aW9ucy5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvdXRpbHMuanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL2dyb3VwaW5nLXNwYWNlci5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvY29sb3ItZnVuY3Rpb24uanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL3Rvb2x0aXAuanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL3NlbGVjdC1maWx0ZXIuanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL2xhc3NvLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9kMy1wcm90b3R5cGVzLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbWFpbi5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvYXhpcy5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvYmFyLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9idWJibGUtaGVhdG1hcC5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvaGVhdG1hcC5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvYm94LXdoaXNrZXIuanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL2RhdGEtdG9nZ2xlLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9zY2F0dGVyLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9wbG90LXpvb20uanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL211bHRpLXBsb3Qtem9vbS5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvdmlvbGluLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9udW1lcmljLWxlZ2VuZC5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvY2F0ZWdvcmljYWwtbGVnZW5kLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9sYXNzby13aWRnZXQuanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL3Vwc2V0LmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9maWx0ZXItdGFibGUuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gaW1wb3J0IHtoYXNRfSBmcm9tICcuL2FycmF5LWZ1bmN0aW9ucyc7XG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSEVMUEVSUyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuLyoqXG4qIEhlbHBlciBmdW5jdGlvbiBmb3IgQXJyYXkuZmlsdGVyIHRvIGdldCB1bmlxdWUgZWxlbWVudHMgb2YgdGhlIGFycmF5XG4qIEBwYXJhbSB7Kn0gdmFsdWUgY3VycmVudCB2YWx1ZSBhcyBtYXBwaW5nIG92ZXIgYXJyYXkgKHNlbGYpXG4qIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBjdXJyZW50IGluZGV4IGluIHRoZSBhcnJheVxuKiBAcGFyYW0ge0FycmF5fSBzZWxmIHBhc3NlZCBhcnJheSBmcm9tIEFycmF5LmZpbHRlciBtZXRob2RcbiogQHJldHVybnMge2Jvb2xlYW59IHdoZXRoZXIgb3Igbm90IHZhbHVlIGlzIHRoZSBmaXJzdCBvZiBpdHMga2luZCAoaS5lLiBpbmRleE9mKHZhbHVlKSA9PSBpbmRleClcbiovXG5leHBvcnQgZnVuY3Rpb24gdW5pcXVlRWxlbWVudHModmFsdWUsIGluZGV4LCBzZWxmKSB7IHJldHVybiBzZWxmLmluZGV4T2YodmFsdWUpID09PSBpbmRleDsgfVxuXG4vKipcbiogRXh0cmFjdHMgeCBhbmQgeSBvZiB0cmFuc2xhdGUgZnJvbSB0cmFuc2Zvcm0gcHJvcGVydHlcbiogQHBhcmFtIHtzdHJpbmd9IHRyYW5zZm9ybSB0cmFuc2Zvcm0gcHJvcGVydHkgb2Ygc3ZnIGVsZW1lbnRcbiogQHJldHVybnMge251bWJlcltdfSB4LCB5IG9mIHRyYW5zbGF0ZSh4LCB5KVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRUcmFuc2xhdGlvbih0cmFuc2Zvcm0pIHtcbiAgLy8gQ3JlYXRlIGEgZHVtbXkgZyBmb3IgY2FsY3VsYXRpb24gcHVycG9zZXMgb25seS4gVGhpcyB3aWxsIG5ldmVyXG4gIC8vIGJlIGFwcGVuZGVkIHRvIHRoZSBET00gYW5kIHdpbGwgYmUgZGlzY2FyZGVkIG9uY2UgdGhpcyBmdW5jdGlvblxuICAvLyByZXR1cm5zLlxuICB2YXIgZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUygnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnLCAnZycpO1xuICAvLyBTZXQgdGhlIHRyYW5zZm9ybSBhdHRyaWJ1dGUgdG8gdGhlIHByb3ZpZGVkIHN0cmluZyB2YWx1ZS5cbiAgdHJhbnNmb3JtID0gdHJhbnNmb3JtID09IHVuZGVmaW5lZCA/ICd0cmFuc2xhdGUoMCwwKScgOiB0cmFuc2Zvcm07XG4gIGcuc2V0QXR0cmlidXRlTlMobnVsbCwgJ3RyYW5zZm9ybScsIHRyYW5zZm9ybSk7XG4gIC8vIGNvbnNvbGlkYXRlIHRoZSBTVkdUcmFuc2Zvcm1MaXN0IGNvbnRhaW5pbmcgYWxsIHRyYW5zZm9ybWF0aW9uc1xuICAvLyB0byBhIHNpbmdsZSBTVkdUcmFuc2Zvcm0gb2YgdHlwZSBTVkdfVFJBTlNGT1JNX01BVFJJWCBhbmQgZ2V0XG4gIC8vIGl0cyBTVkdNYXRyaXguXG4gIHZhciBtYXRyaXggPSBnLnRyYW5zZm9ybS5iYXNlVmFsLmNvbnNvbGlkYXRlKCkubWF0cml4O1xuICAvLyBBcyBwZXIgZGVmaW5pdGlvbiB2YWx1ZXMgZSBhbmQgZiBhcmUgdGhlIG9uZXMgZm9yIHRoZSB0cmFuc2xhdGlvbi5cbiAgcmV0dXJuIFttYXRyaXguZSwgbWF0cml4LmZdO1xufVxuXG5cbi8qKlxuKiBNb2RpZmllcyBsdW1pbmFuY2Ugb2YgaGV4aWRlY2ltYWwgbnVtYmVyXG4qIEBwYXJhbSB7c3RyaW5nfSBoZXggc2hvdWxkIGJlIGhleGlkZWNpbWFsIHZhbHVlIHdpdGggb3Igd2l0aG91dCB0aGUgcHJvY2VlZGluZyBvY3RvdHJvcGVcbiogQHBhcmFtIHtudW1iZXJ9IGx1bSB2YWx1ZSB0byBpbmNyZWFzZSBvciBkZWNyZWFzZSBsdW1pbm9zaXR5IGJ5XG4qIEByZXR1cm5zIHtzdHJpbmd9IHVwZGF0ZWQgaGV4aWRlY2ltYWwgdmFsdWUgd2l0aG91dCB0aGUgcHJvY2VlZGluZyBvY3RvdHJvcGVcbiovXG5leHBvcnQgZnVuY3Rpb24gbW9kaWZ5SGV4aWRlY2ltYWxDb2xvckx1bWluYW5jZShoZXgsIGx1bSkge1xuICAvLyB2YWxpZGF0ZSBoZXggc3RyaW5nXG4gIHZhciBoZXggPSBTdHJpbmcoaGV4KS5yZXBsYWNlKC9bXjAtOWEtZl0vZ2ksICcnKTtcblxuICBpZiAoaGV4Lmxlbmd0aCA8IDYpIHtcbiAgICBoZXggPSBoZXhbMF0raGV4WzBdK2hleFsxXStoZXhbMV0raGV4WzJdK2hleFsyXTtcblx0fVxuXHRsdW0gPSBsdW0gfHwgMDtcblxuXHQvLyBjb252ZXJ0IHRvIGRlY2ltYWwgYW5kIGNoYW5nZSBsdW1pbm9zaXR5XG5cdHZhciByZ2IgPSAnIycsIGMsIGk7XG5cdGZvciAoaSA9IDA7IGkgPCAzOyBpKyspIHtcblx0XHRjID0gcGFyc2VJbnQoaGV4LnN1YnN0cihpKjIsMiksIDE2KTtcblx0XHRjID0gTWF0aC5yb3VuZChNYXRoLm1pbihNYXRoLm1heCgwLCBjICsgKGMgKiBsdW0pKSwgMjU1KSkudG9TdHJpbmcoMTYpO1xuXHRcdHJnYiArPSAoJzAwJytjKS5zdWJzdHIoYy5sZW5ndGgpO1xuXHR9XG5cblx0cmV0dXJuIHJnYjtcbn1cblxuXG4vKipcbiogQGRlcHJlY2F0ZWQgQHNlZXtAbGluayB0aWNrUmFuZ2V9XG4qIEBwYXJhbSB7bnVtYmVyfSBtaW5cbiogQHBhcmFtIHtudW1iZXJ9IG1heFxuKiBAcGFyYW0ge251bWJlcn0gcGFydHNcbiogQHJldHVybnMge251bWJlcltdfSBhcnJheSBvZiBsZW5ndGggcGFydHMgZXZlbmx5IHBhcnRpdGlvbmVkIGJldHdlZW4gbWluIGFuZCBtYXhcbiovXG5leHBvcnQgZnVuY3Rpb24gcGFydGl0aW9uUmFuZ2VJbnRvKG1pbiwgbWF4LCBwYXJ0cykge1xuICB2YXIgZGlmZiA9IG1heCAtIG1pblxuICByZXR1cm4gQXJyYXkocGFydHMpLm1hcChmdW5jdGlvbiAoZSwgaSkgeyByZXR1cm4gbWluICsgZGlmZiAvIHBhcnRzICogaSB9KVxufVxuXG5cbi8qKlxuKiBDYWxjdWxhdGVkIHRoZSBxdWFydGlsZXMgb2YgdGhlIHBhc3NlZCBkYXRhIGFuZCBzdG9yZXMgdGhlbSB3aXRoIHFLZXlzXG4qIEBwYXJhbSB7bnVtYmVyW119IGRhdGEgbGlzdCBvZiBudW1lcmljYWwgdmFsdWVzXG4qIEBwYXJhbSB7c3RyaW5nW119IFtxS2V5cz1bJ3EwJywgJ3ExJywgJ3EyJywgJ3EzJywgJ3E0J11dIGhvdyByZXR1cm5lZCBvYmplY3Qgd2l0aCBxdWFydGlsZXMgc2hvdWxkIGJlIHN0b3JlZFxuKiBAcmV0dXJucyB7T2JqZWN0fSB3aXRoIGtleXMgcUtleXMgZ2l2aW5nIG9ubHkgdGhlIG51bWVyaWNhbCB2YWx1ZXMgZm9yIHRoZSBxdWFydGlsZXNcbiovXG5leHBvcnQgZnVuY3Rpb24gcXVhcnRpbGVzKGRhdGEsIHFLZXlzKSB7XG4gIHZhclxuICBxMiA9IGQzLm1lZGlhbihkYXRhKSxcbiAgbG93ZXIgPSBkYXRhLmZpbHRlcih4ID0+IHggPCBxMiksXG4gIHVwcGVyID0gZGF0YS5maWx0ZXIoeCA9PiB4ID4gcTIpLFxuXG4gIHExID0gZDMubWVkaWFuKGxvd2VyKSxcbiAgcTEgPSBxMSA9PSB1bmRlZmluZWQgPyBxMiA6IHExLFxuXG4gIHEwID0gZDMubWluKGxvd2VyKSxcbiAgcTAgPSBxMCA9PSB1bmRlZmluZWQgPyBxMSA6IHEwLFxuXG4gIHEzID0gZDMubWVkaWFuKHVwcGVyKSxcbiAgcTMgPSBxMyA9PSB1bmRlZmluZWQgPyBxMiA6IHEzLFxuXG4gIHE0ID0gZDMubWF4KHVwcGVyKSxcbiAgcTQgPSBxNCA9PSB1bmRlZmluZWQgPyBxMyA6IHE0LFxuXG4gIGswID0gJ3EwJywgazEgPSAncTEnLCBrMiA9ICdxMicsIGszID0gJ3EzJywgazQgPSAncTQnLFxuICBvYmogPSB7fVxuICBpZiAocUtleXMhPXVuZGVmaW5lZCAmJiBxS2V5cy5sZW5ndGggPT0gNSkgeyBrMCA9IHFLZXlzWzBdOyBrMSA9IHFLZXlzWzFdOyBrMiA9IHFLZXlzWzJdOyBrMyA9IHFLZXlzWzNdOyBrNCA9IHFLZXlzWzRdOyB9XG4gIG9ialtrMF0gPSBxMDsgb2JqW2sxXSA9IHExOyBvYmpbazJdID0gcTI7IG9ialtrM10gPSBxMzsgb2JqW2s0XSA9IHE0O1xuXG4gIHJldHVybiBvYmpcbn1cblxuXG4vKipcbiogSGVscGVyIGZ1bmN0aW9uIHRvIGdldCBhbGwgdmFsdWVzIG5lZWRlZCBpbiBtYWtpbmcgdmlvbGluIHBsb3RzXG4qIEBwYXJhbSB7c3RyaW5nW119IHZpb2xpbktleXNcbiogQHBhcmFtIHtudW1iZXJbXX0gZGF0YVxuKiBAcGFyYW0ge0Z1bmN0aW9ufSB2YWx1ZUV4dHJhY3RvckZ1bmN0aW9uIGhvdyB0byBnZXQgdmFsdWVzIGZyb20gZGF0YVt2aW9saW5LZXlzW2ldXVxuKiBAcGFyYW0ge2Jvb2xlYW59IGhvcml6b250YWxRIHdoZXRoZXIgb3Igbm90IHZpb2xpbnMgd2lsbCBiZSByZW5kZXJlZCBob3Jpem9udGFsbHkgb3IgdmVydGljYWxseVxuKiBAcGFyYW0ge3N0cmluZ30gcUtleSBob3cgdGhlIG9iamVjdCBjb250YWluaW5nIHRoZSBxdWFydGlsZXMgc2hvdWxkIGJlIGxhYmVsZWQgYXNcbiogQHBhcmFtIHtzdHJpbmdbXX0gcUtleXMgaG93IGVhY2ggcXVhcnRpbGUgc2hvdWxkIGJlIGxhYmVsZWQgYXNcbiogQHJldHVybnMge09iamVjdH0gcmVxdWlyZWQgZm9yIEBzZWV7QGxpbmsgdmlvbGlufSBjb250YWluaW5nIGtleXMgdmFsdWVzLCBiaW5ubmVkLCBmcmVxdWVuY2llcywgcG9pbnRzLCBhbmQgcXVhcnRpbGVzXG4qIEBzZWV7QGxpbmsgcXVhcnRpbGVzfVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0VmlvbGluVmFsdWVzKFxuICB2aW9saW5LZXlzLFxuICBkYXRhLFxuICB2YWx1ZUV4dHJhY3RvckZ1bmN0aW9uLFxuICBob3Jpem9udGFsUSxcbiAgcUtleSxcbiAgcUtleXNcbil7XG4gIHZhciBvYmogPSB7fVxuICB2aW9saW5LZXlzLm1hcChmdW5jdGlvbihrLCBpKXtcbiAgICAgdmFyIGQgPSB2YWx1ZUV4dHJhY3RvckZ1bmN0aW9uKGssIGksIGRhdGEpLFxuICAgICBiaW5uZWQgPSBkMy5oaXN0b2dyYW0oKShkKSxcbiAgICAgZnJlcXVlbmNpZXMgPSBiaW5uZWQubWFwKHg9PngubGVuZ3RoKSxcbiAgICAgbWluUG9pbnQgPSBob3Jpem9udGFsUSA/IHt5OiBkMy5taW4oZCksIHg6IDB9IDoge3g6IGQzLm1pbihkKSwgeTogMH0sXG4gICAgIG1heFBvaW50ID0gaG9yaXpvbnRhbFEgPyB7eTogZDMubWF4KGQpLCB4OiAwfSA6IHt4OiBkMy5tYXgoZCksIHk6IDB9LFxuICAgICBwb2ludHMgPSBiaW5uZWQubWFwKGZ1bmN0aW9uKGJpbiwgaSkge1xuICAgICAgIHJldHVybiBob3Jpem9udGFsUVxuICAgICAgID8ge3k6IChiaW4ubGVuZ3RoKSA/IGQzLm1lZGlhbihiaW4pOiBkMy5tZWRpYW4oW2Jpbi54MCwgYmluLngxXSksIHg6IGZyZXF1ZW5jaWVzW2ldfVxuICAgICAgIDoge3g6IChiaW4ubGVuZ3RoKSA/IGQzLm1lZGlhbihiaW4pOiBkMy5tZWRpYW4oW2Jpbi54MCwgYmluLngxXSksIHk6IGZyZXF1ZW5jaWVzW2ldfVxuICAgICB9KSxcbiAgICAgcXVhcnRzID0gcXVhcnRpbGVzKGQsIHFLZXlzKSxcbiAgICAgbyA9IHtcbiAgICAgICB2YWx1ZXM6IGQsXG4gICAgICAgYmlubmVkOiBiaW5uZWQsXG4gICAgICAgZnJlcXVlbmNpZXM6IGZyZXF1ZW5jaWVzLFxuICAgICAgIHBvaW50czogW21pblBvaW50XS5jb25jYXQocG9pbnRzKS5jb25jYXQoW21heFBvaW50XSlcbiAgICAgfVxuICAgICBvW3FLZXldID0gcXVhcnRzO1xuICAgICBvYmpba10gPSBvO1xuICAgfSk7XG4gICByZXR1cm4gb2JqO1xufVxuXG4vKipcbiogSHlwZW5hdGVzIGFsbCBzdHJpbmdzIHRvZ2V0aGVyXG4qIEBwYXJhbSB7c3RyaW5nW119IGFyZ3VtZW50c1xuKiBAcmV0dXJucyB7c3RyaW5nfSBcImFyZzEtYXJnMi0uLi4tYXJnblwiXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIGh5cGVuYXRlKCl7IHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpLmpvaW4oJy0nKSB9XG5cblxuLyoqXG4qIFJvdW5kcyBkZWNpbWFscyBvZiBudW1iZXIgdG8gcHJlY2lzaW9uXG4qIEBwYXJhbSB7bnVtYmVyfSBudW1iZXJcbiogQHBhcmFtIHtudW1iZXJ9IHByZWNpc2lvblxuKiBAcmV0dXJucyB7bnVtYmVyfSByb3VuZGVkIHRvIHByZWNpc2lvblxuKi9cbmV4cG9ydCBmdW5jdGlvbiByb3VuZChudW1iZXIsIHByZWNpc2lvbikge1xuICB2YXIgc2hpZnQgPSBmdW5jdGlvbiAobnVtYmVyLCBwcmVjaXNpb24sIHJldmVyc2VTaGlmdCkge1xuICAgIGlmIChyZXZlcnNlU2hpZnQpIHtcbiAgICAgIHByZWNpc2lvbiA9IC1wcmVjaXNpb247XG4gICAgfVxuICAgIHZhciBudW1BcnJheSA9ICgnJyArIG51bWJlcikuc3BsaXQoJ2UnKTtcbiAgICByZXR1cm4gKyhudW1BcnJheVswXSArICdlJyArIChudW1BcnJheVsxXSA/ICgrbnVtQXJyYXlbMV0gKyBwcmVjaXNpb24pIDogcHJlY2lzaW9uKSk7XG4gIH07XG4gIHJldHVybiBzaGlmdChNYXRoLnJvdW5kKHNoaWZ0KG51bWJlciwgcHJlY2lzaW9uLCBmYWxzZSkpLCBwcmVjaXNpb24sIHRydWUpO1xufVxuXG4vKipcbiogcmVjdXJzaXZlbHkgYXNjZW5kcyBlbGVtZW50LnBhcmVudEVsZW1lbnQgdG8gZmluZCBhIHN2ZyB0YWdcbiogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4qIEByZXR1cm5zIHtFbGVtZW50IHwgdW5kZWZpbmVkfVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb250YWluaW5nU1ZHKGVsZW1lbnQpIHtcbiAgdmFyIHBhcmVudCA9IGVsZW1lbnQucGFyZW50RWxlbWVudFxuICB2YXIgdGFnID0gcGFyZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKVxuICBpZiAodGFnID09PSAnc3ZnJykgeyByZXR1cm4gcGFyZW50OyB9XG4gIGlmICh0YWcgPT09ICdodG1sJykgeyByZXR1cm4gdW5kZWZpbmVkOyB9XG4gIHJldHVybiBnZXRDb250YWluaW5nU1ZHKHBhcmVudCk7XG59XG5cbi8qKlxuKiBNYXBzIGFyZ3VtZW50cyBpbiB0byBkMy5pbnRlcnBvbGF0ZVJnYkJhc2lzXG4qIEBwYXJhbSBhcmd1bWVudHNcbiogQHJldHVybnMge0Z1bmN0aW9ufVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcnBvbGF0ZUNvbG9ycygpe3JldHVybiBkMy5pbnRlcnBvbGF0ZVJnYkJhc2lzKGFyZ3VtZW50cyl9XG5cblxuLyoqXG4qIFRyeXMgdG8gcmVkdWNlIHRleHQgdG8gZml0IGluIHNwZWNpZmllZCBhcmVhLCBtYWRlIGZvciB0aWNrIGxhYmVscyBhcyBjYWxsZWQgYnlcbiogQHNlZXtAbGluayBheGlzfVxuKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gdCBjb250YWluZXIgZm9yIHNwZWNpZmljIGF4aXMgdGlja1xuKiBAcGFyYW0ge3N0cmluZ30gdGV4dCB0byBiZSB0aGUgbGFiZWwgb2YgdGhlIHBhc3NlZCBheGlzIHRpY2tcbiogQHBhcmFtIHtib29sZWFufSBvcmllbnQgb2YgdGhlIGF4aXMsIHRydWUgaXMgaG9yaXpvbnRhbCwgZmFsc2UgaXMgdmVydGljYWxcbiogQHBhcmFtIHtudW1iZXJ9IHRpY2tMZW5ndGggaXMgdGhlIGxlbmd0aCBvZiB0aGUgdGV4dFxuKiBAcGFyYW0ge251bWJlcn0gc3BhY2UgaXMgdGhlIGFtb3VudCBvZiBhdmFpbGJsZSBzcGFjZSBmb3IgdGhlIHRleHQgYW5kIHRoZSB0aWNrIHRvIGZpdCBpblxuKiBAcGFyYW0ge2Jvb2xlYW59IG92ZXJmbG93USB3aGV0aGVyIG9yIG5vdCBhbGxvd2VkIHRvIGdvIG92ZXIgdGhlIGFsbG90ZWQgc3BhY2VcbiogQHJldHVybnMge25vbmV9XG4qL1xuZXhwb3J0IGZ1bmN0aW9uIHRydW5jYXRlVGV4dCh0LCB0ZXh0LCBvcmllbnQsIHRpY2tMZW5ndGgsIHNwYWNlLCBvdmVyZmxvd1EpIHtcbiAgdmFyIHJlY3QgPSB0Lm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVxuICB0LnRleHQodGV4dClcbiAgd2hpbGUgKE1hdGgubWF4KHJlY3Qud2lkdGgsIHJlY3QuaGVpZ2h0KSA+IHNwYWNlIC0gdGlja0xlbmd0aCkge1xuICAgIHRleHQgPSBTdHJpbmcodGV4dClcbiAgICB0ZXh0ID0gdGV4dC5zbGljZSgwLCB0ZXh0Lmxlbmd0aCAtIDEpXG4gICAgdC50ZXh0KHRleHQgKyAnLi4uJylcbiAgICByZWN0ID0gdC5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClcbiAgICBpZiAodGV4dC5sZW5ndGggPT0gMCkgYnJlYWtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJ1bmNhdGVTdHJpbmcoc3RyaW5nLCBzcGFjZSwgZm9udCkge1xuICB2YXIgY2hhcnMgPSBzcGFjZSAvIGZvbnQ7XG4gIGlmIChjaGFycyA8IHN0cmluZy5sZW5ndGgpIHtcbiAgICByZXR1cm4gc3RyaW5nLnNsaWNlKDAsIE1hdGgucm91bmQoY2hhcnMtNSkpICsgJy4uLidcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gc3RyaW5nXG4gIH1cbn1cblxuXG4vKipcbiogVHJ5cyB0byB1c2UgZDMuc2VsZWN0aW9uIHRvIGdldCBlbGVtZW50LCBpZiBpdCBkb2VzbnQgZXhpc3QsIG1ha2VzIG9uZVxuKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gc2VsIHNlbGVjdGlvbiBpbiB3aGljaCB0byB0cnkgYW5kIGZpbmQgb2JqZWN0XG4qIEBwYXJhbSB7c3RyaW5nfSB0YWcgdGFnIG9mIHdoaWNoIHRvIHRyeSBhbmQgc2VsZWN0XG4qIEBwYXJhbSB7c3RyaW5nfSBbY2xzPScnXSBjbGFzcyBvZiB0YWcgdG8gdHJ5IGFuZCBncmFiXG4qIEByZXR1cm5zIHtkMy5zZWxlY3Rpb259IG9mIGVpdGhlciBhcHBlbmQgb3Igc2VsZWN0ZWQgdGFnLmNscyB3aXRoaW4gc2VsXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIHNhZmVTZWxlY3Qoc2VsLCB0YWcsIGNscykge1xuICB2YXIgY2xzU3RyID0gY2xzID09IHVuZGVmaW5lZCA/ICcnIDogJy4nK2NscztcbiAgdmFyIHNTZWwgPSBzZWwuc2VsZWN0KHRhZytjbHNTdHIpLmVtcHR5KClcbiAgPyBzZWwuYXBwZW5kKHRhZylcbiAgOiBzZWwuc2VsZWN0KHRhZytjbHNTdHIpXG4gIHJldHVybiBzU2VsXG4gIC5jbGFzc2VkKGNsc1N0ci5yZXBsYWNlKCcuJywgJycpLCB0cnVlKVxuICAuYXR0cigndHJhbnNmb3JtJywgc1NlbC5hdHRyKCd0cmFuc2Zvcm0nKSA9PSB1bmRlZmluZWQgPyAndHJhbnNsYXRlKDAsMCknIDogc1NlbC5hdHRyKCd0cmFuc2Zvcm0nKSlcbn1cblxuLyoqXG4qIGV2ZW5seSBwYXJ0aXRpb25zIHRoZSByYW5nZSBbbWluLCBtYXhdIGludG8gbiBwYXJ0c1xuKiBAcGFyYW0ge251bWJlcn0gbWluXG4qIEBwYXJhbSB7bnVtYmVyfSBtYXhcbiogQHBhcmFtIHtudW1iZXJ9IG5cbiogQHJldHVybnMge251bWJlcltdfSBhcnJheSBvZiBsZW5ndGggbiBldmVubHkgcGFydGl0aW9uZWQgYmV0d2VlbiBtaW4gYW5kIG1heFxuKi9cbmV4cG9ydCBmdW5jdGlvbiB0aWNrUmFuZ2UobWluLCBtYXgsIG4pIHtcbiAgdmFyIGEgPSBbbWluXVxuICB2YXIgZCA9IG1heC1taW5cbiAgdmFyIHMgPSBkIC8gKG4tMSlcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuLTI7IGkrKykgeyBhLnB1c2gobWluICsgcyAqIChpKzEpKSB9XG4gIGEucHVzaChtYXgpXG4gIHJldHVybiBhXG59XG5cblxuZXhwb3J0IGZ1bmN0aW9uIGV1Y2xpZGVhbkRpc3RhbmNlKHAxLCBwMil7XG4gIHZhciBhID0gIHAxWzBdIC0gcDJbMF0sIGIgPSAgcDFbMV0gLSBwMlsxXVxuICByZXR1cm4gTWF0aC5zcXJ0KGEqYSArIGIqYilcbn1cbiIsImltcG9ydCB7dW5pcXVlRWxlbWVudHN9IGZyb20gJy4vaGVscGVycyc7XG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBST1RPVFlQRVMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuLyoqXG4qIFRoaXMgZnVuY3Rpb24gdGVzdHMgdG8gc2VlIGlmIGFsbCBlbGVtZW50cyBvZiB0aGUgcGFzc2VkIGFycmF5IGFyZSB0cnVlLlxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiB2YWx1ZXNcbiogQHBhcmFtIHtGdW5jdGlvbn0gW2Z1bmMgZnVuY3Rpb24odmFsdWUpe3JldHVybiB2YWx1ZSA9PSB0cnVlO31dIGlzIGFwcGxpZWQgdG8gZWFjaCB2YWx1ZSBvZiB0aGUgYXJyYXkgYW5kIHNob3VsZCByZXR1cm4gYSBib29sZWFuLlxuKiBAcmV0dXJucyB7Ym9vbGVhbn0gaWYgYWxsIHZhbHVlcyBhcmUgdHJ1ZSBieSBmdW5jdGlvblxuKi9cbmV4cG9ydCBmdW5jdGlvbiBhbGwoIGFycmF5LCBmdW5jICkge1xuICBpZiAoZnVuYyA9PSB1bmRlZmluZWQpIHsgcmV0dXJuIGFycmF5LmV2ZXJ5KCBmdW5jdGlvbih2YWx1ZSkgeyByZXR1cm4gdmFsdWUgPT09IHRydWU7IH0pOyB9XG4gIHJldHVybiBhcnJheS5ldmVyeSggZnVuY3Rpb24odmFsdWUpIHsgcmV0dXJuIGZ1bmModmFsdWUpOyB9ICk7XG59XG5cbi8qKlxuKiBDb3VudHMgdGhlIG51bWJlciBvZiBvY2N1cmFuY2VzIG9mIGVhY2ggZWxlbWVudCBpbiB0aGUgZ2l2ZW4gYXJyYXkuXG4qIEBwYXJhbSB7QXJyYXl9IGFycmF5IG9mIGVsZW1lbnRzXG4qIEByZXR1cm5zIHtPYmplY3R9IG9mIGtleTogdmFsdWUgcGFpcnMgd2hlcmUga2V5IGlzIGFuIGVsZW1lbnQgaW4gdGhlIGFycmF5IGFuZCB2YWx1ZSBpcyB0aGUgbnVtYmVyIG9mIHRpbWVzIGl0IG9jY3Vycy5cbiovXG5leHBvcnQgZnVuY3Rpb24gdGFsbHkoIGFycmF5ICkge1xuICB2YXIgdGFsbGllcyA9IHt9O1xuICBhcnJheS5tYXAoIGZ1bmN0aW9uICggZWxlbWVudCApIHtcbiAgICBpZiAoIGhhc1EoT2JqZWN0LmtleXModGFsbGllcyksIGVsZW1lbnQpICkgeyB0YWxsaWVzW2VsZW1lbnRdID0gMTsgfVxuICAgIGVsc2UgeyB0YWxsaWVzW2VsZW1lbnRdICs9IDE7IH1cbiAgfSk7XG4gIHJldHVybiB0YWxsaWVzO1xufVxuLyoqXG4qIFNob3J0LWhhbmQgZm9yIGFycmF5LmluY2x1ZGVzKGl0ZW0pO1xuKiBAcGFyYW0ge0FycmF5fSBhcnJheVxuKiBAcGFyYW0geyp9IGl0ZW0gdG8gdGVzdCBpZiBjb250YWluZWQgaW4gIHthcnJheX1cbiogQHJldHVybnMge2Jvb2xlYW59XG4qL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc1EoIGFycmF5LCBpdGVtICkgeyByZXR1cm4gYXJyYXkuaW5jbHVkZXMoaXRlbSk7IH1cblxuLyoqXG4qIFJldHVybnMgZmlyc3QgaXRlbSBpbiBhcnJheVxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtc1xuKiBAcmV0dXJucyB7Kn0gYXJyYXlbMF1cbiovXG5leHBvcnQgZnVuY3Rpb24gZmlyc3QoIGFycmF5ICkgeyByZXR1cm4gYXJyYXlbMF07IH1cblxuLyoqXG4qIFJldHVybnMgbGFzdCBpdGVtIGluIGFycmF5XG4qIEBwYXJhbSB7QXJyYXl9IGFycmF5IG9mIGl0ZW1zXG4qIEByZXR1cm5zIHsqfSBhcnJheVthcnJheS5sZW5ndGgtMV1cbiovXG5leHBvcnQgZnVuY3Rpb24gbGFzdCggYXJyYXkgKSB7IHJldHVybiBhcnJheVthcnJheS5sZW5ndGgtMV07IH1cblxuLyoqXG4qIENhbGN1bGF0ZXMgdGhlIHRvdGFsIHZhbHVlIG9mIG51bWJlcnMgaW4gcGFzc2VkIGFycmF5XG4qIEBwYXJhbSB7bnVtYmVyW119IGFycmF5IG9mIG51bWVyaWNhbCB2YWx1ZXNcbiogQHJldHVybnMge251bWJlcn0gc3VtIG92ZXIgZWxlbWVudHMgaW4gYXJyYXlcbiovXG5leHBvcnQgZnVuY3Rpb24gdG90YWwoIGFycmF5ICkgeyByZXR1cm4gYXJyYXkucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCkgfTtcblxuLyoqXG4qIFJlbW92ZXMgZHVwbGljYXRlcyBpbiBhcnJheVxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtc1xuKiBAcmV0dXJucyB7QXJyYXl9IG9mIGl0ZW1zIHN1Y2ggdGhhdCBpdGVtX2kgIT0gaXRlbV9qIGZvciBhbGwgaSA8IGpcbiogQHNlZXtAbGluayB1bmlxdWVFbGVtZW50c30gZm9yIHRoZSBmaWx0ZXJpbmcgZnVuY3Rpb25cbiovXG5leHBvcnQgZnVuY3Rpb24gdW5pcXVlKCBhcnJheSApIHsgcmV0dXJuIGFycmF5LmZpbHRlciggdW5pcXVlRWxlbWVudHMgKTsgfVxuXG4vKipcbiogRmlsdGVycyBwYXNzZWQgYXJyYXkgZm9yIHNwZWNpZmllZCBpbmRpY2llc1xuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtc1xuKiBAcGFyYW0ge251bWJlcltdfSBwb3NpdGlvbnMgb2YgaW50ZWdlcnMgc3VjaCB0aGF0IGkgPCBhcnJheS5sZW5ndGhcbiogQHJldHVybnMge0FycmF5fSBvZiBpdGVtcyBzdWNoIHRoYXQgZm9yIGFueSBpdGVtX2ksIHBvc2l0aW9ucy5pbmNsdWRlcyhpKSA9PT0gdHJ1ZVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXQoIGFycmF5LCBwb3NpdGlvbnMgKSB7XG4gIHJldHVybiBhcnJheS5maWx0ZXIoIGZ1bmN0aW9uKCB2YWx1ZSwgaW5kZXggKSB7IHJldHVybiBoYXNRKHBvc2l0aW9ucywgaW5kZXgpOyB9ICk7XG59XG5cbi8qKlxuKiBEZXRlcm1pbmVzIGlmIGFsbCBlbGVtZW50cyBpbiBwYXNzZWQgYXJyYXkgYXJlIGFycmF5cyB0aGVtc2VsdmVzLlxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtc1xuKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiBBcnJheS5pc0FycmF5KGUpIGlzIHRydWUgZm9yIGFsbCBlIGluIGFycmF5XG4qIEBzZWV7QGxpbmsgYWxsfVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXN0T2ZMaXN0c1EoIGFycmF5ICkge1xuICByZXR1cm4gYWxsKCBhcnJheS5tYXAoIGZ1bmN0aW9uKCBlbGVtZW50LCBpbmRleCApIHsgcmV0dXJuIEFycmF5LmlzQXJyYXkoZWxlbWVudCkgfSApIClcbn1cblxuLyoqXG4qIEJ1aWx0IG9uIHRvcCBvZiBAc2Vle0BsaW5rIGdldH0sIG1hcHBpbmcgaWYgcG9zaXRpb25zIGlzIGEgbGlzdCBvZiBsaXN0cyAoQHNlZXtAbGluayBsaXN0T2ZMaXN0c1F9KVxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtc1xuKiBAcGFyYW0ge251bWJlcltdIHwgW11udW1iZXJbXSB9IHBvc2l0aW9ucyBvZiBpbnRlZ2VycyBvciBsaXN0IG9mIHBvc2l0aW9ucyBvZiBpbnRlZ2Vyc1xuKiBAcmV0dXJucyB7Ym9vbGVhbn0gcmV0dXJucyBzcGVjaWZpZWQgcG9zaXRpb25zIGZyb20gYXJyYXkuIElmIG5lc3RlZCBwb3NpdGlvbnMgcGFzc2VkLCByZXR1cm5zIHJlcXVlc3RlZCBpdGVtcyBpbiBzYW1lIHN0cnVjdHVyZS5cbiovXG5leHBvcnQgZnVuY3Rpb24gY3V0KCBhcnJheSwgcG9zaXRpb25zICkge1xuICBpZiAoIGxpc3RPZkxpc3RzUShhcnJheSkgKSB7IHJldHVybiBwb3NpdGlvbnMubWFwKGZ1bmN0aW9uKHBvcywgaSkgeyByZXR1cm4gYXJyYXkuZ2V0KHBvcyk7IH0pOyB9XG4gIHJldHVybiBnZXQoIGFycmF5LCBwb3NpdGlvbnMgKTtcbn1cblxuLyoqXG4qIEdpdmVuIGFuIGFycmF5IG9mIG9iamVjdHMsIGNvbnN0cnVjdHMgbmV3IG9iamVjdHMgd2hlcmUgZWFjaCB2YWx1ZSBpcyBhIGxpc3RcbiogYmFzZWQgb24gdGhlIGNvcnJlc29uZGluZyBrZXksIHdoaWNoIGlzIGV4dHJhY3RlZCBieSB0aGUgcGFyYW1ldGVyIGJ5XG4qIEBwYXJhbSB7T2JqZWN0c1tdfSBhcnJheSBvZiBvYmplY3RzXG4qIEBwYXJhbSB7c3RyaW5nfSBieSBrZXkgd2l0aGluIGFsbCBvYmplY3RzIG9mIHBhc3NlZCBhcnJheVxuKiBAcGFyYW0ge3N0cmluZ1tdfSBbZ3JvdXBzXSBzYXZlcyBzb21lIGNvbXB1dGF0aW9uIGlmIGFsbCBrbm93biB2YWx1ZXMgZXh0cmFjdGVkIGJ5IG1hcHBpbmcgb3ZlciB0aGUgcGFyYW1ldGVyIGJ5IGFyZSBwYXNzZWRcbiogQHJldHVybnMge09iamVjdH0gb2Yga2V5IHZhbHVlIHBhaXJzLCB3aGVyZSBrZXlzIGFyZSBhbGwgdmFsdWVzIG9mIHRoZSBrZXkgYnkgZnJvbSBhbiBvYmplY3QgaW4gdGhlIHBhc3NlZCBhcnJheSBhbmQgdGhlIHZhbHVlIGFyZSB0aG9zZSBjb3JyZXNwb25kaW5nIG9iamVjdHMuXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIGdyb3VwQnkgKGFycmF5LCBieSwgZ3JvdXBzKSB7XG4gIGlmIChncm91cHMgPT0gdW5kZWZpbmVkKSB7XG4gICAgZ3JvdXBzID0gdW5pcXVlKGFycmF5Lm1hcChmdW5jdGlvbihlbGVtZW50cywgaW5kZXgpeyByZXR1cm4gZWxlbWVudFtieV07IH0pKTtcbiAgICBncm91cHMubWFwKGZ1bmN0aW9uKHZhbHVlLCBpbmRleCl7Z3JvdXBwZWRbdmFsdWVdID0gW119KVxuICB9XG5cbiAgdmFyIGdyb3VwcGVkID0ge307XG4gIGFycmF5Lm1hcChmdW5jdGlvbihlbGVtZW50LCBpbmRleCl7Z3JvdXBwZWRbZWxlbWVudFtieV1dLnB1c2goZWxlbWVudCl9KTtcbiAgcmV0dXJuIGdyb3VwcGVkXG59XG5cbi8qKlxuKiBUZXN0cyBpZiB0d28gYXJyYXlzIGFyZSBlcXVpdmFsZW50XG4qIEBwYXJhbSB7QXJyYXl9IGFycmF5XG4qIEBwYXJhbSB7QXJyYXl9IG90aGVyXG4qIEByZXR1cm5zIHtib29sZWFufSBpZiBldmVyeSBlbGVtZW50IG9mIGFycmF5IG1hdGNoZXMgdGhhdCBvZiBvdGhlclxuKi9cbmV4cG9ydCBmdW5jdGlvbiBhcnJheUVxdWFscyhhcnJheSwgb3RoZXIpIHtcbiAgaWYgKCFvdGhlcilcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgLy8gY29tcGFyZSBsZW5ndGhzIC0gY2FuIHNhdmUgYSBsb3Qgb2YgdGltZVxuICBpZiAoYXJyYXkubGVuZ3RoICE9IG90aGVyLmxlbmd0aClcbiAgICAgIHJldHVybiBmYWxzZTtcblxuICBmb3IgKHZhciBpID0gMCwgbD1hcnJheS5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgbmVzdGVkIGFycmF5c1xuICAgICAgaWYgKGFycmF5W2ldIGluc3RhbmNlb2YgQXJyYXkgJiYgb3RoZXJbaV0gaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgIC8vIHJlY3Vyc2UgaW50byB0aGUgbmVzdGVkIGFycmF5c1xuICAgICAgICAgIGlmICghYXJyYXlFcXVhbHMoYXJyYXlbaV0sb3RoZXJbaV0pKVxuICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChhcnJheVtpXSAhPSBvdGhlcltpXSkge1xuICAgICAgICAgIC8vIFdhcm5pbmcgLSB0d28gZGlmZmVyZW50IG9iamVjdCBpbnN0YW5jZXMgd2lsbCBuZXZlciBiZSBlcXVhbDoge3g6MjB9ICE9IHt4OjIwfVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuXG5cbi8qKlxuKiBSZWN1cnNpdmVseSB0YWxsaWVzIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgYXQgZWFjaCBsZXZlbCBvZiB0aGUgcGFzc2VkLCBwdXRhdGl2ZWx5IG5lc3RlZCBhcnJheVxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtcyB3aGljaCBtYXkgaW5jbHVkZSBuZXN0ZWQgYXJyYXlzXG4qIEBwYXJhbSB7bnVtYmVyfSBbbGV2ZWw9MF0gY3VycmVudCBkZXB0aCBpbiB0aGUgcmVjdXJzaW9uXG4qIEBwYXJhbSB7QXJyYXl9IFtsZXZlbERhdGE9W11dIGtlZXBzIHRyYWNrIG9mIGl0ZW1zIHNlZW4gc28gZmFyIGF0IGVhY2ggZGVwdGhcbiogQHJldHVybnMge0FycmF5fSBzdGF0aW5nIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgKGFycmF5IGluY2x1c2l2ZSkgZm91bmQgYXQgZWFjaCBsZXZlbCBvZiB0aGUgYXJyYXlcbiovXG5leHBvcnQgZnVuY3Rpb24gZWxlbWVudHNBdExldmVscyhhcnJheSwgbGV2ZWwsIGxldmVsRGF0YSkge1xuICBsZXZlbCA9IGxldmVsID09IHVuZGVmaW5lZCA/IDAgOiBsZXZlbCArIDE7XG4gIGxldmVsRGF0YSA9IGxldmVsRGF0YSA9PSB1bmRlZmluZWQgPyBbXSA6IGxldmVsRGF0YTtcbiAgaWYgKCBsZXZlbCA+PSBsZXZlbERhdGEubGVuZ3RoICkgeyBsZXZlbERhdGEucHVzaChhcnJheS5sZW5ndGgpfSBlbHNlIHtsZXZlbERhdGFbbGV2ZWxdICs9IGFycmF5Lmxlbmd0aCB9XG4gIGFycmF5Lm1hcChmdW5jdGlvbihlLCBpKSB7aWYgKEFycmF5LmlzQXJyYXkoZSkpeyBlbGVtZW50c0F0TGV2ZWxzKGUsIGxldmVsLCBsZXZlbERhdGEpIH19KVxuICByZXR1cm4gbGV2ZWxEYXRhXG59XG5cblxuLyoqXG4qIFJlY3Vyc2l2ZWx5IHRhbGxpZXMgdGhlIG51bWJlciBvZiBlbGVtZW50cyBvZiB0aGUgcGFzc2VkLCBwdXRhdGl2ZWx5IG5lc3RlZCBhcnJheVxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtcyB3aGljaCBtYXkgaW5jbHVkZSBuZXN0ZWQgYXJyYXlzXG4qIEBwYXJhbSB7bnVtYmVyfSBbZWxlbWVudHM9MF0gY3VycmVudCBudW1iZXIgb2YgZWxlbWVudHMgc2VlbiBzbyBmYXJcbiogQHJldHVybnMge251bWJlcn0gbnVtYmVyIG9mIGVsZW1lbnRzIChhcnJheSBpbmNsdXNpdmUpIGZvdW5kIGluIHBhc3NlZCBhcnJheVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBudW1iZXJPZkVsZW1lbnRzKCBhcnJheSwgZWxlbWVudHMgKSB7XG4gIGVsZW1lbnRzID0gZWxlbWVudHMgPT0gdW5kZWZpbmVkID8gMCA6IGVsZW1lbnRzO1xuICBhcnJheS5tYXAoZnVuY3Rpb24oZSwgaSkge1xuICAgIGlmICggQXJyYXkuaXNBcnJheShlKSApIHsgZWxlbWVudHMgPSBudW1iZXJPZkVsZW1lbnRzKGUsIGVsZW1lbnRzKSB9XG4gICAgZWxzZSB7IGVsZW1lbnRzICs9IDEgfVxuICB9KVxuICByZXR1cm4gZWxlbWVudHNcbn1cblxuLyoqXG4qIENvbmNhdHMgYWxsIG5lc3RlZCBhcnJheXMgaW4gcGFzc2VkIGFycmF5IHRvIGZvcm0gYSBzaW5nbGUgYXJyYXlcbiogQHBhcmFtIHtBcnJheX0gYXJyYXkgb2YgcHV0YXRpdmVseSBuZXN0ZWQgYXJyYXlzXG4qIEBwYXJhbSB7QXJyYXl9IFtmbGF0PVtdXSBjdXJyZW50IGZsYXR0ZW5lZCBhcnJheVxuKiBAcmV0dXJucyB7QXJyYXl9IHdpdGggZXZlcnkgZWxlbWVudCBpbiB0aGUgc2FtZSBsZXZlbFxuKi9cbmV4cG9ydCBmdW5jdGlvbiBmbGF0dGVuKCBhcnJheSwgZmxhdCApIHtcbiAgZmxhdCA9IGZsYXQgPT0gdW5kZWZpbmVkID8gW10gOiBmbGF0O1xuICBhcnJheS5tYXAoZnVuY3Rpb24oZSwgaSl7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZSkpIHtmbGF0ID0gZmxhdC5jb25jYXQoZmxhdHRlbihlKSl9XG4gICAgZWxzZSB7ZmxhdC5wdXNoKGUpfVxuICB9KVxuICByZXR1cm4gZmxhdDtcbn1cblxuLyoqXG4qIFNlYXJjaCBvZiBsaXN0IG9mIGxpc3RzIHRvIGZpbmQgd2hpY2ggLSBpZiBhbnkgLSBwYXNzZWQgdmFsdWUgaXMgaW5cbiogQHBhcmFtIHtBcnJheVtdfSBiaW5zIGxpc3Qgb2YgbGlzdHMgb2YgdmFsdWVzXG4qIEBwYXJhbSB7Kn0gdmFsdWUgaXRlbSB0byB0ZXN0IGlmIGluIGFueSBvZiB0aGUgYmluc1xuKiBAcmV0dXJucyB7bnVtYmVyfSBpbmRpY2F0aW5nIHRoZSBpbmRleCBvZiB0aGUgYmluIGluIHdoaWNoIHZhbHVlIHdhcyBmb3VuZFxuKi9cbmV4cG9ydCBmdW5jdGlvbiB3aGljaEJpbihiaW5zLCB2YWx1ZSkge1xuICB2YXIgaSA9IC0xXG4gIGZvciAodmFyIGogPSAwOyBqIDwgYmlucy5sZW5ndGg7IGorKykgeyBpZiAoaGFzUShiaW5zW2pdLHZhbHVlKSkge3JldHVybiBqfSB9XG4gIHJldHVybiBpXG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHt0b3RhbH0gZnJvbSAnLi9hcnJheS1mdW5jdGlvbnMnO1xuXG5cbi8qKlxuICogY2FsbHMgY29uc29sZS5ncm91cCBpZiBkM3NtLmRlYnVnUSA9PSB0cnVlXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBvZiB0aGUgZ3JvdXBcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25zb2xlR3JvdXAobmFtZSkge1xuICBpZiAod2luZG93LmQzc20uZGVidWdRID09PSB0cnVlKXtcbiAgICBjb25zb2xlLmdyb3VwKG5hbWUpXG4gIH1cbn1cblxuLyoqXG4gKiBjYWxscyBjb25zb2xlLmdyb3VwRW5kIGlmIGQzc20uZGVidWdRID09IHRydWVcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25zb2xlR3JvdXBFbmQoKSB7XG4gIGlmICh3aW5kb3cuZDNzbS5kZWJ1Z1EgPT09IHRydWUpe1xuICAgIGNvbnNvbGUuZ3JvdXBFbmQoKVxuICB9XG59XG5cbi8qKlxuICogQ2FsbHMgY29uc29sZS5sb2cgaWYgZDNzbS5kZWJ1Z1EgPT0gdHJ1ZVxuICogQHBhcmFtIHtzdHJpbmd9IGZ1bmMgbmFtZSBvZiB0aGUgZnVuY3Rpb24gbG9nZ2luZ1xuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0byBsb2dcbiAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhIHRvIGJlIGxvZ2dlZCBhbG9uZyBzaWRlIHRoZSBtZXNzYWdlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gbG9nKGZ1bmMsIG1zZywgZGF0YSkge1xuICBpZiAod2luZG93LmQzc20uZGVidWdRID09PSB0cnVlKXtcbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGAlY1tkM3NtOjoke2Z1bmN9XTpcXHQke21zZ31gLFxuICAgICAgW1xuICAgICAgICAnYmFja2dyb3VuZDogIzZjZDFlZicsXG4gICAgICAgICdib3JkZXItcmFkaXVzOiA1MDAwcHgnLFxuICAgICAgICAncGFkZGluZzogMHB4IDJweCcsXG4gICAgICAgICdmb250LXNpemU6IDE0cHgnXG4gICAgICBdLmpvaW4oJzsnKVxuICAgIClcbiAgICBjb25zb2xlLnRhYmxlKGRhdGEpXG4gICAgLy8gY29uc29sZS50cmFjZSgpXG4gIH1cbn1cblxuLyoqXG4gKiBDYWxscyBjb25zb2xlLndhcm4gaWYgZDNzbS5kZWJ1Z1EgPT0gdHJ1ZVxuICogQHBhcmFtIHtzdHJpbmd9IGZ1bmMgbmFtZSBvZiB0aGUgZnVuY3Rpb24gd2FybmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0byBkaXNwbGF5XG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YSB0byBiZSBkaXNwbGF5ZWQgYWxvbmcgc2lkZSB0aGUgbWVzc2FnZVxuICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdhcm4oZnVuYywgbXNnLCBkYXRhKSB7XG4gIGlmICh3aW5kb3cuZDNzbS5kZWJ1Z1EgPT09IHRydWUpXG4gICAgY29uc29sZS53YXJuKFxuICAgICAgYCVjW2Qzc206OiR7ZnVuY31dOlxcdCR7bXNnfWAsXG4gICAgICBbXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjZmZkNTNlJyxcbiAgICAgICAgJ2JvcmRlci1yYWRpdXM6IDUwMDBweCcsXG4gICAgICAgICdwYWRkaW5nOiAwcHggMnB4JyxcbiAgICAgICAgJ2ZvbnQtc2l6ZTogMTRweCdcbiAgICAgIF0uam9pbignOycpXG4gICAgKVxuICAgIGNvbnNvbGUudGFibGUoZGF0YSlcbn1cbi8qKlxuICogQ2FsbHMgdGhlIGNvbnNvbGUuaW5mbyBpZiBkM3NtLmRlYnVnUSA9PSB0cnVlXG4gKiBAcGFyYW0ge3N0cmluZ30gZnVuYyBuYW1lIG9mIHRoZSBmdW5jdGlvbiBwcm92aWRpbmcgaW5mb1xuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0byBkaXNwbGF5XG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YSB0byBiZSBkaXNwbGF5ZWQgYWxvbmcgc2lkZSB0aGUgbWVzc2FnZVxuICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluZm8oZnVuYywgbXNnLCBkYXRhKSB7XG4gIGlmICh3aW5kb3cuZDNzbS5kZWJ1Z1EpXG4gICAgY29uc29sZS5pbmZvKFxuICAgICAgYCVjW2Qzc206OiR7ZnVuY31dOlxcdCR7bXNnfWAsXG4gICAgICBbXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjMDA5Y2NkJyxcbiAgICAgICAgJ2JvcmRlci1yYWRpdXM6IDUwMDBweCcsXG4gICAgICAgICdwYWRkaW5nOiAwcHggMnB4JyxcbiAgICAgICAgJ2ZvbnQtc2l6ZTogMTRweCdcbiAgICAgIF0uam9pbignOycpXG4gICAgKVxuICAgIGNvbnNvbGUudGFibGUoZGF0YSlcbn1cblxuXG4vKipcbiAqIENhbGxzIGNvbnNvbGUuZXJyb3IgaWYgZDNzbS5kZWJ1Z1EgPT0gdHJ1ZVxuICogQHBhcmFtIHtzdHJpbmd9IGZ1bmMgbmFtZSBvZiB0aGUgZnVuY3Rpb24gd2hpY2ggc2VuZHMgdGhlIGVycm9yXG4gKiBAcGFyYW0ge3N0cmluZ30gbXNnIHRvIGRpc3BsYXlcbiAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhIHRvIGJlIGRpc3BsYXllZCBhbG9uZyBzaWRlIHRoZSBtZXNzYWdlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZXJyb3IoZnVuYywgbXNnLCBkYXRhKSB7XG4gIGlmICh3aW5kb3cuZDNzbS5kZWJ1Z1EpXG4gICAgY29uc29sZS5lcnJvcihgW2Qzc206OiR7ZnVuY31dOlxcdCR7bXNnfVxcdCVvYCxkYXRhKVxufVxuXG5cblxuXG5cbi8qKlxuKiBGdW5jdGlvbiBmb3Igc2V0dGluZyB1cCBjb250YWluZXJzIGZvciBtb3N0IHBsb3RzIHdpdGggdGhlIHkgYXhpcyBjb250YWluZXJcbiogcG9zaXRpb25lZCBvbiB0aGUgbGVmdCBhbmQgdGhlIHggYXhpcyBjb250YWluZXIgcG9zaXRpb25lZCBvbiB0aGUgYm90dG9tXG4qIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBzZWxlY3Rpb24gc2VsZWN0aW9uIG9mIGNvbnRhaW5lciBpbiB3aGljaCB0aGUgc3ZnIGlzIG9yIHNob3VsZCBiZSBtYWRlXG4qIEBwYXJhbSB7c3RyaW5nfSBuYW1lc3BhY2UgbmFtZXNwYWNlIG9mIHRoZSBjaGFydFxuKiBAcGFyYW0ge09iamVjdH0gW3NwYWNlPXt3OndpbmRvdy5pbm5lcldpZHRoLCBoOndpbmRvdy5pbm5lckhlaWdodH1dIHRoZSB3aWR0aCAodykgYW5kIGhlaWdodCAoaCkgYXZhaWxibGVcbiogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZS53PXdpbmRvdy5pbm5lcldpZHRoXSB0aGUgYXZhaWxhYmxlIHdpZHRoIGluIHdoaWNoIHRvIHJlbmRlciB0aGUgY2hhcnRcbiogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZS5oPXdpbmRvdy5pbm5lckhlaWdodF0gdGhlIGF2YWlsYWJsZSBoZWlnaHQgaW4gd2hpY2ggdG8gcmVuZGVyIHRoZSBjaGFydFxuXG4qIEBwYXJhbSB7T2JqZWN0fSBbbWFyZ2lucz17dG9wOiAwLjAxLCBib3R0b206IDAuMDEsIGxlZnQ6IDAuMDEsIHJpZ2h0OiAwLjAxfV0gdGhlIG1hcmdpbnMgZm9yIHRoZSBjaGFydFxuKiBAcGFyYW0ge251bWJlcn0gW21hcmdpbnMudG9wPTAuMDFdIHRoZSB0b3AgbWFyZ2luIG9mIHRoZSBjaGFydFxuKiBAcGFyYW0ge251bWJlcn0gW21hcmdpbnMuYm90dG9tPTAuMDFdIHRoZSBib3R0b20gbWFyZ2luIG9mIHRoZSBjaGFydFxuKiBAcGFyYW0ge251bWJlcn0gW21hcmdpbnMubGVmdD0wLjAxXSB0aGUgbGVmdCBtYXJnaW4gb2YgdGhlIGNoYXJ0XG4qIEBwYXJhbSB7bnVtYmVyfSBbbWFyZ2lucy5yaWdodD0wLjAxXSB0aGUgcmlnaHQgbWFyZ2luIG9mIHRoZSBjaGFydFxuXG5cbiogQHBhcmFtIHtPYmplY3R9IFtwZXJjZW50YWdlcyA9IHtheGVzOnt4OjAuMSx5OjAuMX0sc3BhY2U6e3c6MC44LGg6MC42fX1dIHBlcmNlbnRhZ2VzIG9mIHRoZSBwYXJhbWF0ZXIgc3BhY2Ugb2Ygd2hpY2ggdG8gbWFrZSB0aGUgeCBhbmQgeSBheGVzIGFzIHdlbGwgYXMgdGhlIHBlcmNlbnQgb2YgdGhlIGF2YWlsYmxlIHNwYWNlIGluIHdoaWNoIHRvIHJlbmRlciB0aGUgcGxvdFxuKiBAcGFyYW0ge09iamVjdH0gW3BlcmNlbnRhZ2VzLmF4ZXM9e3g6MC4xLHk6MC4xfV0gdGhlIHBlcmNlbnRhZ2VzIG9mIHRoZSBwYXJhbWF0ZXIgc3BhY2UsIG9mIHdoaWNoIHRoZSB4IGFuZCB5IGF4ZXMgd2lsbCB0YWtlIHVwXG4qIEBwYXJhbSB7bnVtYmVyfSBbcGVyY2VudGFnZXMuYXhlcy54QXhpc1BlcmNlbnQ9MC4xXSB0aGUgcGVyY2VudGFnZXMgb2YgdGhlIHBhcmFtYXRlciBzcGFjZSwgb2Ygd2hpY2ggdGhlIHggYXhpcyB3aWxsIHRha2UgdXBcbiogQHBhcmFtIHtudW1iZXJ9IFtwZXJjZW50YWdlcy5heGVzLnlBeGlzUGVyY2VudD0wLjFdIHRoZSBwZXJjZW50YWdlcyBvZiB0aGUgcGFyYW1hdGVyIHNwYWNlLCBvZiB3aGljaCB0aGUgeSBheGlzIHdpbGwgdGFrZSB1cFxuXG4qIEBwYXJhbSB7T2JqZWN0fSBbcGVyY2VudGFnZXMuc3BhY2U9e3c6MC44LGg6MC42fV0gdGhlIHBlcmNlbnRhZ2VzIG9mIHRoZSBwYXJhbWF0ZXIgc3BhY2UsIG9mIHdoaWNoIHRoZSBTVkcncyB3aWR0aCBhbmQgaGVpZ2h0IHdpbGwgYmUgc2V0XG4qIEBwYXJhbSB7bnVtYmVyfSBbcGVyY2VudGFnZXMuc3BhY2UucGVyY2VudE9mU3BhY2VGb3JXaWR0aD0wLjFdIHRoZSBwZXJjZW50YWdlcyBvZiB0aGUgcGFyYW1hdGVyIHNwYWNlLCBvZiB3aGljaCB0aGUgU1ZHJ3Mgd2lkdGggd2lsbCBiZSBzZXRcbiogQHBhcmFtIHtudW1iZXJ9IFtwZXJjZW50YWdlcy5zcGFjZS5wZXJjZW50T2ZTcGFjZUZvckhlaWdodD0wLjFdIHRoZSBwZXJjZW50YWdlcyBvZiB0aGUgcGFyYW1hdGVyIHNwYWNlLCBvZiB3aGljaCB0aGUgU1ZHJ3MgaGVpZ2h0IHdpbGwgYmUgc2V0XG5cbiogQHJldHVybnMge09iamVjdH0gcmV0dXJucyB0aGUgc2VsZWN0aW9uIGFuZCBcImJvdW5kaW5nUmVjdHNcIiBvZiB0aGUgcGxvdCBjb250YWluZXIsIHgtYXhpcyBjb250YWluZXIgYW5kIHktYXhpcyBjb250YWluZXJcbiogYXNcbipcbioge1xuKlxuKiAgIHBsb3Q6IHtzZWxlY3Rpb246IHBsb3RTZWxlY3Rpb24sIHJlY3Q6IHBsb3RSZWN0fSxcbipcbiogICB4QXhpczp7c2VsZWN0aW9uOnhBeGlzU2VsZWN0aW9uLCByZWN0OnhBeGlzUmVjdH0sXG4qXG4qICAgeUF4aXM6IHtzZWxlY3Rpb246eUF4aXNTZWxlY3Rpb24sIHJlY3Q6eUF4aXNSZWN0fVxuKlxuKiB9XG4qXG4qIHdoZXJlIGVhY2ggcmVjdCBoYXMgZm9ybTpcbipcbioge3g6ICMsIHk6ICMsIGg6ICMsIHc6ICN9XG4qXG4qIGRlcGljdGluZyB0aGUgc3RhcnRpbmcgeCBhbmQgeSBjb29yZGluYXRlIG9mIHRoZSBjb3Jlc3BvbmRpbmcgY29udGFpbmVyIChhbHNvIHRoZWlyIGRlZmF1bHQgdHJhbnNmb3JtIHZhbHVlcykgYXMgd2VsbCB0aGVpciBoZWlnaHQgKGgpIGFucyB3aWR0aCAodylcbiovXG4vLyBleHBvcnQgZnVuY3Rpb24gc2V0dXBTdGFuZGFyZENoYXJ0Q29udGFpbmVycyggc2VsZWN0aW9uLCBuYW1lc3BhY2UsIHNwYWNlLCBtYXJnaW5zLCBwZXJjZW50YWdlcykge1xuLy8gZXhwb3J0IGZ1bmN0aW9uIHNldHVwU3RhbmRhcmRDaGFydENvbnRhaW5lcnMoXG4vLyAgIHNlbGVjdGlvbixcbi8vICAgbmFtZXNwYWNlLFxuLy8gICBzcGFjZT17dzphdmFpbGFibGVXaWR0aD13aW5kb3cuaW5uZXJXaWR0aCwgaDphdmFpbGFibGVIZWlnaHQ9d2luZG93LmlubmVySGVpZ2h0fSxcbi8vICAgbWFyZ2lucz17dG9wOjAuMDEsIGJvdHRvbTowLjAxLCBsZWZ0OjAuMDEsIHJpZ2h0OjAuMDF9LFxuLy8gICBwZXJjZW50YWdlcz17YXhlczoge3g6IHhBeGlzUGVyY2VudD0wLjEsIHk6IHlBeGlzUGVyY2VudD0wLjF9LCBzcGFjZToge3c6IHBlcmNlbnRPZlNwYWNlRm9yV2lkdGgsIGg6IHBlcmNlbnRPZlNwYWNlRm9ySGVpZ2h0fX1cbi8vICkge1xuLy8gICBpZiAoc3BhY2UgPT0gdW5kZWZpbmVkKSB7IHNwYWNlID0ge3c6IHdpbmRvdy5pbm5lcldpZHRoLCBoOiB3aW5kb3cuaW5uZXJIZWlnaHR9IH1cbi8vICAgaWYgKG1hcmdpbnMgPT0gdW5kZWZpbmVkKSB7IG1hcmdpbnMgPSB7dG9wOiAwLjAxLCBib3R0b206IDAuMDEsIGxlZnQ6IDAuMDEsIHJpZ2h0OiAwLjAxfSB9XG4vLyAgIGlmIChwZXJjZW50YWdlcyA9PSB1bmRlZmluZWQpIHsgcGVyY2VudGFnZXMgPSB7fTsgfVxuLy8gICBpZiAocGVyY2VudGFnZXMuYXhlcyA9PSB1bmRlZmluZWQpIHsgcGVyY2VudGFnZXMuYXhlcyA9IHsgeDowLjEsIHk6MC4xIH0gfVxuLy8gICBpZiAocGVyY2VudGFnZXMuc3BhY2UgPT0gdW5kZWZpbmVkKSB7IHBlcmNlbnRhZ2VzLnNwYWNlID0geyB3OiAwLjgsIGg6IDAuNiB9IH1cbi8vXG4vLyAgIC8vIFNWRyB3aWR0aCBhbmQgaGVpZ2h0XG4vLyAgIHZhciBzdmdTcGFjZSA9ICB7XG4vLyAgICAgdzogc3BhY2UudyAqIHBlcmNlbnRhZ2VzLnNwYWNlLncsXG4vLyAgICAgaDogc3BhY2UuaCAqIHBlcmNlbnRhZ2VzLnNwYWNlLmhcbi8vICAgfSxcbi8vXG4vLyAgIC8vIFNwYWNlIGFmdGVyIHJlbW92aW5nIG1hcmdpbnNcbi8vICAgY2hhcnRTcGFjZSA9IHtcbi8vICAgICB3OiBzdmdTcGFjZS53IC0gKG1hcmdpbnMubGVmdCAqIHNwYWNlLncpIC0gKG1hcmdpbnMucmlnaHQgKiBzcGFjZS53KSxcbi8vICAgICBoOiBzdmdTcGFjZS5oIC0gKG1hcmdpbnMudG9wICogc3BhY2UuaCkgLSAobWFyZ2lucy5ib3R0b20gKiBzcGFjZS5oKVxuLy8gICB9LFxuLy9cbi8vICAgLy8gbWFpbiBkaW1lbnNpb24gb2YgeCBhbmQgeSBheGllc1xuLy8gICAvLyBlLmcuIGRlZmluZXMgaG93IHRhbGwgeCBheGlzIGlzIGFzIGxlbmd0aCBpcyBkZXRlcm1pbmVkIGJ5IHBsb3RSZWN0Lndcbi8vICAgYXhlc1NwYWNlID0ge1xuLy8gICAgIHg6IGNoYXJ0U3BhY2UuaCAqIHBlcmNlbnRhZ2VzLmF4ZXMueCxcbi8vICAgICB5OiBjaGFydFNwYWNlLncgKiBwZXJjZW50YWdlcy5heGVzLnlcbi8vICAgfSxcbi8vXG4vLyAgIC8vIHNwYWNlIGxlZnQgZm9yIGRyYXdpbmcgdGhlIGNoYXJ0IHByb3Blcmx5IChlLmcuIGJhcnMsIHZpb2xpbnMsIGV0Yylcbi8vICAgZHJhd2luZ1NwYWNlID0ge1xuLy8gICAgIHg6IGNoYXJ0U3BhY2UudyAtIGF4ZXNTcGFjZS55LFxuLy8gICAgIHk6IGNoYXJ0U3BhY2UuaCAtIGF4ZXNTcGFjZS54XG4vLyAgIH0sXG4vL1xuLy9cbi8vICAgeUF4aXNSZWN0ID0ge1xuLy8gICAgIHg6IGF4ZXNTcGFjZS55ICsgKG1hcmdpbnMubGVmdCAqIHNwYWNlLncpLFxuLy8gICAgIHk6IChtYXJnaW5zLnRvcCAqIHNwYWNlLmgpLFxuLy8gICAgIHc6IGF4ZXNTcGFjZS55LFxuLy8gICAgIGg6IGRyYXdpbmdTcGFjZS55XG4vLyAgIH0sXG4vL1xuLy8gICBwbG90UmVjdCA9IHtcbi8vICAgICB4OiBheGVzU3BhY2UueSArIChtYXJnaW5zLmxlZnQgKiBzcGFjZS53KSxcbi8vICAgICB5OiAobWFyZ2lucy50b3AgKiBzcGFjZS5oKSxcbi8vICAgICB3OiBkcmF3aW5nU3BhY2UueCxcbi8vICAgICBoOiBkcmF3aW5nU3BhY2UueVxuLy8gICB9LFxuLy9cbi8vICAgeEF4aXNSZWN0ID0ge1xuLy8gICAgIHg6IGF4ZXNTcGFjZS55ICsgKG1hcmdpbnMubGVmdCAqIHNwYWNlLncpLFxuLy8gICAgIHk6IChtYXJnaW5zLnRvcCAqIHNwYWNlLmggKyBwbG90UmVjdC5oKSxcbi8vICAgICB3OiBkcmF3aW5nU3BhY2UueCxcbi8vICAgICBoOiBheGVzU3BhY2UueFxuLy8gICB9XG4vL1xuLy9cbi8vICAgdmFyIGNvbnRhaW5lciA9IHNhZmVTZWxlY3Qoc2VsZWN0aW9uLCAnc3ZnJywgbmFtZXNwYWNlKVxuLy8gICAgIC5zdHlsZSgnd2lkdGgnLCBzdmdTcGFjZS53KydweCcpXG4vLyAgICAgLnN0eWxlKCdoZWlnaHQnLCBzdmdTcGFjZS5oKydweCcpXG4vL1xuLy8gICB2YXIgYXhlcyA9IHNhZmVTZWxlY3QoY29udGFpbmVyLCAnZycsIGh5cGVuYXRlKG5hbWVzcGFjZSwgJ2F4ZXMnKSlcbi8vXG4vLyAgIC8vIC5hdHRyKCd0cmFuc2Zvcm0nLCBcInRyYW5zbGF0ZShcIitwbG90UmVjdC54K1wiLFwiK3Bsb3RSZWN0LnkrXCIpXCIpLFxuLy9cbi8vICAgdmFyIHBsb3QgPSBzYWZlU2VsZWN0KGNvbnRhaW5lciwgJ2cnLCBoeXBlbmF0ZShuYW1lc3BhY2UsICdwbG90JykpXG4vLyAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIFwidHJhbnNsYXRlKFwiK3Bsb3RSZWN0LngrXCIsXCIrcGxvdFJlY3QueStcIilcIilcbi8vXG4vLyAgIHZhciB4QXhpcyA9IHNhZmVTZWxlY3QoYXhlcywgJ2cnLCBoeXBlbmF0ZShuYW1lc3BhY2UsICd4LWF4aXMnKSlcbi8vICAgICAuYXR0cigndHJhbnNmb3JtJywgXCJ0cmFuc2xhdGUoXCIreEF4aXNSZWN0LngrXCIsXCIreEF4aXNSZWN0LnkrXCIpXCIpXG4vL1xuLy8gICB2YXIgeUF4aXMgPSBzYWZlU2VsZWN0KGF4ZXMsICdnJywgaHlwZW5hdGUobmFtZXNwYWNlLCAneS1heGlzJykpXG4vLyAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIFwidHJhbnNsYXRlKFwiK3lBeGlzUmVjdC54K1wiLFwiK3lBeGlzUmVjdC55K1wiKVwiKVxuLy9cbi8vICAgcmV0dXJuIHtcbi8vICAgICBzdmc6IHtcbi8vICAgICAgIHNlbGVjdGlvbjogY29udGFpbmVyLFxuLy8gICAgICAgcmVjdDogc3ZnU3BhY2Vcbi8vICAgICB9LFxuLy8gICAgIHBsb3Q6IHtcbi8vICAgICAgIHNlbGVjdGlvbjogcGxvdCxcbi8vICAgICAgIHJlY3Q6IHBsb3RSZWN0XG4vLyAgICAgfSxcbi8vICAgICB4QXhpczoge1xuLy8gICAgICAgc2VsZWN0aW9uOiB4QXhpcyxcbi8vICAgICAgIHJlY3Q6IHhBeGlzUmVjdFxuLy8gICAgIH0sXG4vLyAgICAgeUF4aXM6IHtcbi8vICAgICAgIHNlbGVjdGlvbjogeUF4aXMsXG4vLyAgICAgICByZWN0OiB5QXhpc1JlY3Rcbi8vICAgICB9XG4vLyAgIH1cbi8vXG4vLyAgIC8vIHJldHVybiBbcGxvdCwgeEF4aXMsIHlBeGlzXVxuLy8gfVxuLy9cbi8vXG5cblxuXG5cblxuZXhwb3J0IGZ1bmN0aW9uIHNldHVwU3RhbmRhcmRDaGFydENvbnRhaW5lcnMoXG4gIHNlbGVjdGlvbixcbiAgbmFtZXNwYWNlLFxuICBjb250YWluZXIsXG4gIG1hcmdpbnM9e3RvcDowLjAxLCBib3R0b206MC4wMSwgbGVmdDowLjAxLCByaWdodDowLjAxfSxcbiAgc3ZnPXt3OjAuOCwgaDowLjZ9LCAvLyBwZXJjZW50IG9mIGNvbnRhaW5lciBzcGFjZSBmb3Igc3ZnXG4gIGF4ZXM9e3k6MC4xLCB4OjAuMX0sIC8vIHBlcmNlbnQgb2YgY29udGFpbmVyIHNwYWNlIGZvciBheGVzLFxuICBsZWc9e3g6MCwgbWFyZ2luOjAsIHBvczonbGVmdCd9IC8vIGFic29sdXRlIHdpZHRoIG9mIGxlZ2VuZCBhbmQgc3BhY2Ugb24gZWl0aGVyIHNpemVcbilcbntcbiAgaWYgKGNvbnRhaW5lciA9PSB1bmRlZmluZWQpIHtjb250YWluZXIgPSB7dzp3aW5kb3cuaW5uZXJXaWR0aCwgaDp3aW5kb3cuSGVpZ2h0fX1cbiAgLy8gU1ZHIHdpZHRoIGFuZCBoZWlnaHRcblxuICB2YXIgc3ZnU3BhY2UgPSAge1xuICAgIHc6IGNvbnRhaW5lci53ICogc3ZnLncsXG4gICAgaDogY29udGFpbmVyLmggKiBzdmcuaFxuICB9XG5cbiAgdmFyIG1hcmdQeCA9IHtcbiAgICB0b3A6IG1hcmdpbnMudG9wICogc3ZnU3BhY2UuaCxcbiAgICBib3R0b206IG1hcmdpbnMuYm90dG9tICogc3ZnU3BhY2UuaCxcbiAgICBsZWZ0OiBtYXJnaW5zLmxlZnQgKiBzdmdTcGFjZS53LFxuICAgIHJpZ2h0OiBtYXJnaW5zLnJpZ2h0ICogc3ZnU3BhY2Uud1xuICB9LFxuXG5cblxuICAvLyBTcGFjZSBhZnRlciByZW1vdmluZyBtYXJnaW5zXG4gIGNoYXJ0U3BhY2UgPSB7XG4gICAgdzogc3ZnU3BhY2UudyAtIG1hcmdQeC5sZWZ0IC0gbWFyZ1B4LnJpZ2h0LFxuICAgIGg6IHN2Z1NwYWNlLmggLSBtYXJnUHgudG9wIC0gbWFyZ1B4LmJvdHRvbVxuICB9LFxuXG4gIC8vIG1haW4gZGltZW5zaW9uIG9mIHggYW5kIHkgYXhpZXNcbiAgLy8gZS5nLiBkZWZpbmVzIGhvdyB0YWxsIHggYXhpcyBpcyBhcyBsZW5ndGggaXMgZGV0ZXJtaW5lZCBieSBwbG90UmVjdC53XG4gIGF4ZXNTcGFjZSA9IHtcbiAgICB4OiBjaGFydFNwYWNlLmggKiBheGVzLngsXG4gICAgeTogY2hhcnRTcGFjZS53ICogYXhlcy55XG4gIH0sXG5cbiAgLy8gc3BhY2UgbGVmdCBmb3IgZHJhd2luZyB0aGUgY2hhcnQgcHJvcGVybHkgKGUuZy4gYmFycywgdmlvbGlucywgZXRjKVxuICBkcmF3aW5nU3BhY2UgPSB7XG4gICAgeDogY2hhcnRTcGFjZS53IC0gYXhlc1NwYWNlLnkgLSBsZWcueCAtIDIqbGVnLm1hcmdpbixcbiAgICB5OiBjaGFydFNwYWNlLmggLSBheGVzU3BhY2UueFxuICB9LFxuXG5cbiAgbGVnUmVjdCA9IHtcbiAgICB4OiBsZWcubWFyZ2luICsgbWFyZ1B4LmxlZnQgKyAobGVnLnBvcyA9PSAnbGVmdCcgPyAwIDogZHJhd2luZ1NwYWNlLnggKyBheGVzU3BhY2UueSksXG4gICAgeTogbWFyZ1B4LnRvcCwgLy8gdGhpcyBpcyBzb29tZWhvdyBnZXR0aW5nIGNhbGN1bGF0ZWQgaW5jb3JlY3RseVxuICAgIHc6IGxlZy54LFxuICAgIGg6IGRyYXdpbmdTcGFjZS55XG4gIH0sXG5cbiAgeUF4aXNSZWN0ID0ge1xuICAgIHg6IGF4ZXNTcGFjZS55ICsgbWFyZ1B4LmxlZnQgKyAobGVnLnBvcyA9PSAnbGVmdCcgPyBsZWcueCArIDIqbGVnLm1hcmdpbiA6IDApLFxuICAgIHk6IG1hcmdQeC50b3AsXG4gICAgdzogYXhlc1NwYWNlLnksXG4gICAgaDogZHJhd2luZ1NwYWNlLnlcbiAgfSxcblxuICBwbG90UmVjdCA9IHtcbiAgICB4OiBheGVzU3BhY2UueSArIG1hcmdQeC5sZWZ0ICsgKGxlZy5wb3MgPT0gJ2xlZnQnID8gbGVnLnggKyAyKmxlZy5tYXJnaW4gOiAwKSxcbiAgICB5OiBtYXJnUHgudG9wLFxuICAgIHc6IGRyYXdpbmdTcGFjZS54LFxuICAgIGg6IGRyYXdpbmdTcGFjZS55XG4gIH0sXG5cbiAgeEF4aXNSZWN0ID0ge1xuICAgIHg6IGF4ZXNTcGFjZS55ICsgbWFyZ1B4LmxlZnQgKyAobGVnLnBvcyA9PSAnbGVmdCcgPyBsZWcueCArIDIqbGVnLm1hcmdpbiA6IDApLFxuICAgIHk6IG1hcmdQeC50b3AgKyBkcmF3aW5nU3BhY2UueSxcbiAgICB3OiBkcmF3aW5nU3BhY2UueCxcbiAgICBoOiBheGVzU3BhY2UueFxuICB9XG5cblxuXG4gIGNvbnRhaW5lciA9IGQzc20uc2FmZVNlbGVjdChzZWxlY3Rpb24sICdzdmcnLCBuYW1lc3BhY2UpXG4gICAgLnN0eWxlKCd3aWR0aCcsIHN2Z1NwYWNlLncrJ3B4JylcbiAgICAuc3R5bGUoJ2hlaWdodCcsIHN2Z1NwYWNlLmgrJ3B4JylcblxuICB2YXIgYXhlcyA9IGQzc20uc2FmZVNlbGVjdChjb250YWluZXIsICdnJywgZDNzbS5oeXBlbmF0ZShuYW1lc3BhY2UsICdheGVzJykpXG5cbiAgdmFyIGxlZyA9IGQzc20uc2FmZVNlbGVjdChjb250YWluZXIsICdnJywgZDNzbS5oeXBlbmF0ZShuYW1lc3BhY2UsICdsZWdlbmQnKSlcbiAgLmF0dHIoJ3RyYW5zZm9ybScsIFwidHJhbnNsYXRlKFwiK2xlZ1JlY3QueCtcIixcIitsZWdSZWN0LnkrXCIpXCIpXG5cbiAgdmFyIHBsb3QgPSBkM3NtLnNhZmVTZWxlY3QoY29udGFpbmVyLCAnZycsIGQzc20uaHlwZW5hdGUobmFtZXNwYWNlLCAncGxvdCcpKVxuICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBcInRyYW5zbGF0ZShcIitwbG90UmVjdC54K1wiLFwiK3Bsb3RSZWN0LnkrXCIpXCIpXG5cbiAgdmFyIHhBeGlzID0gZDNzbS5zYWZlU2VsZWN0KGF4ZXMsICdnJywgZDNzbS5oeXBlbmF0ZShuYW1lc3BhY2UsICd4LWF4aXMnKSlcbiAgICAuYXR0cigndHJhbnNmb3JtJywgXCJ0cmFuc2xhdGUoXCIreEF4aXNSZWN0LngrXCIsXCIreEF4aXNSZWN0LnkrXCIpXCIpXG5cbiAgdmFyIHlBeGlzID0gZDNzbS5zYWZlU2VsZWN0KGF4ZXMsICdnJywgZDNzbS5oeXBlbmF0ZShuYW1lc3BhY2UsICd5LWF4aXMnKSlcbiAgICAuYXR0cigndHJhbnNmb3JtJywgXCJ0cmFuc2xhdGUoXCIreUF4aXNSZWN0LngrXCIsXCIreUF4aXNSZWN0LnkrXCIpXCIpXG5cbiAgcmV0dXJuIHtcbiAgICBzdmc6IHtcbiAgICAgIHNlbGVjdGlvbjogY29udGFpbmVyLFxuICAgICAgcmVjdDogc3ZnU3BhY2VcbiAgICB9LFxuICAgIHBsb3Q6IHtcbiAgICAgIHNlbGVjdGlvbjogcGxvdCxcbiAgICAgIHJlY3Q6IHBsb3RSZWN0XG4gICAgfSxcbiAgICB4QXhpczoge1xuICAgICAgc2VsZWN0aW9uOiB4QXhpcyxcbiAgICAgIHJlY3Q6IHhBeGlzUmVjdFxuICAgIH0sXG4gICAgeUF4aXM6IHtcbiAgICAgIHNlbGVjdGlvbjogeUF4aXMsXG4gICAgICByZWN0OiB5QXhpc1JlY3RcbiAgICB9LFxuICAgIGxlZ2VuZDoge1xuICAgICAgc2VsZWN0aW9uOiBsZWcsXG4gICAgICByZWN0OiBsZWdSZWN0XG4gICAgfVxuICB9XG59XG5cblxuXG4vKipcbiogQWRkcyBhIGNsaXAtcGF0aCByZWN0IGFuZCBiaW5kcyBpdCB0byBjb250YWluZXJcbiogQHBhcmFtIHtkMy5zZWxlY3Rpb259IGNvbnRhaW5lciBpbiB3aGljaCB0byBhZGQgdGhlIGNsaXAtcGF0aCBhbmQgdG8gd2hpY2ggdG8gYmluZCB0aGUgY2xpcGluZyBwYXRoIHRvXG4qIEBwYXJhbSB7T2JqZWN0fSByZWN0IHRoZSBjb29yZGluYXRlcyAoeCwgeSwgd2lkdGgsIGhlaWdodCkgb2YgdGhlIGNsaXAtcGF0aFxuKiBAcGFyYW0ge3N0cmluZ30gbmFtZXNwYWNlXG4qIEByZXR1cm5zIHtkMy5zZWxlY3Rpb259IG9mIHRoZSBjbGlwLXBhdGggcmVjdFxuKi9cbmV4cG9ydCBmdW5jdGlvbiBjcFJlY3QoY29udGFpbmVyLCByZWN0LCBuYW1lc3BhY2UpIHtcbiAgdmFyIGRlZnMgPSBzYWZlU2VsZWN0KGNvbnRhaW5lciwgJ2RlZnMnLCBoeXBlbmF0ZShuYW1lc3BhY2UsICdkZWZpbml0aW9ucycpKVxuICB2YXIgY3AgPSBzYWZlU2VsZWN0KGRlZnMsICdjbGlwUGF0aCcsIGh5cGVuYXRlKG5hbWVzcGFjZSwgJ2NsaXAtcGF0aCcpKVxuICAuYXR0cignaWQnLCBoeXBlbmF0ZShuYW1lc3BhY2UsICdjbGlwLXBhdGgnKSlcblxuICB2YXIgY3BSZWN0ID0gc2FmZVNlbGVjdChjcCwgJ3JlY3QnKVxuICAuYXR0cigneCcsIHJlY3QueClcbiAgLmF0dHIoJ3knLCByZWN0LnkpXG4gIC5hdHRyKCd3aWR0aCcsIHJlY3Qud2lkdGgpXG4gIC5hdHRyKCdoZWlnaHQnLCByZWN0LmhlaWdodClcblxuICBkZWZzLnJhaXNlKClcbiAgLy8gc2V0IGNsaXBwaW5nIHBhdGggdG8gY29udGFpbmVyXG4gIGNvbnRhaW5lci5hdHRyKCdjbGlwLXBhdGgnLCAndXJsKCMnKyBoeXBlbmF0ZShuYW1lc3BhY2UsICdjbGlwLXBhdGgnKSsnKScpXG5cbiAgcmV0dXJuIGNwUmVjdFxufVxuXG5cbi8qKlxuKiBBZGRzIGEgYmFja2dyb3VuZCByZWN0IHQgdG8gY29udGFpbmVyXG4qIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBjb250YWluZXIgaW4gd2hpY2ggdG8gYWRkIHRoZSBiYWNrZ3JvdW5kIHJlY3RhbmdsZVxuKiBAcGFyYW0ge09iamVjdH0gcmVjdCB0aGUgY29vcmRpbmF0ZXMgKHgsIHksIHdpZHRoLCBoZWlnaHQpIG9mIHRoZSBiYWNrZ3JvdW5kXG4qIEBwYXJhbSB7c3RyaW5nfSBmaWxsIHRoZSBjb2xvciBvZiB0aGUgYmFja2dyb3VuZFxuKiBAcmV0dXJucyB7ZDMuc2VsZWN0aW9ufSBvZiB0aGUgYmFja2dyb3VuZCBmaWxsXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIGJnUmVjdChjb250YWluZXIsIHJlY3QsIGZpbGwpIHtcbiAgcmV0dXJuIHNhZmVTZWxlY3QoY29udGFpbmVyLCAncmVjdCcsICdiZycpXG4gIC5hdHRyKCd4JywgcmVjdC54KVxuICAuYXR0cigneScsIHJlY3QueSlcbiAgLmF0dHIoJ3dpZHRoJywgcmVjdC53aWR0aClcbiAgLmF0dHIoJ2hlaWdodCcsIHJlY3QuaGVpZ2h0KVxuICAuYXR0cignZmlsbCcsIGZpbGwpXG59XG5cblxuLyoqXG4qIFNldHMgdXAgdGhlIGNvbnRhaW5lciBmb3IgbWFraW5nIGNoYXJ0IGVsZW1lbnRzLiBUaGlzIGluY2x1ZGVzIG1ha2luZ1xuKiBhIGNsaXAtcGF0aCByZWN0IGJvdW5kIHRvIHRoZSBwYXNzZWQgY29udGFpbmVyLCBhIGJhY2tncm91bmQgcmVjdCwgYW5kXG4qIGEgZyBlbGVtZW50IHdpdGggY2xhc3MgPG5hbWVzcGFjZT4tb2JqZWN0LWNvbnRhaW5lci5cbiogQHBhcmFtIHtkMy5zZWxlY3Rpb259IGNvbnRhaW5lciBpbiB3aGljaCB0byBhZGQgdGhlIGNsaXAtcGF0aCBhbmQgYmFja2dyb3VuZFxuKiBAcGFyYW0ge3N0cmluZ30gbmFtZXNwYWNlXG4qIEBwYXJhbSB7T2JqZWN0fSByZWN0IHRoZSBjb29yZGluYXRlcyAoeCwgeSwgd2lkdGgsIGhlaWdodCkgb2YgdGhlIGJhY2tncm91bmQgYW5kIGNsaXAtcGF0aFxuKiBAcGFyYW0ge3N0cmluZ30gZmlsbCB0aGUgY29sb3Igb2YgdGhlIGJhY2tncm91bmRcbiogQHJldHVybnMge2QzLnNlbGVjdGlvbn0gb2YgZy48bmFtZXNwYWNlPi1vYmplY3QtY29udGFpbmVyXG4qXG4qIEBzZWV7QGxpbmsgYmdSZWN0fVxuKiBAc2Vle0BsaW5rIGNwUmVjdH1cbiovXG5leHBvcnQgZnVuY3Rpb24gc2V0dXBDb250YWluZXIoc2VsZWN0aW9uLCBuYW1lc3BhY2UsIHJlY3QsIGZpbGwpIHtcbiAgLy8gdGhlIGNvbnRhaW5lciBmb3IgdGhyZWUgbWFpbiBpdGVtcywgYmcsIGRlZnMsIGFuZCBvYmplY3QtY29udGFpbmVyXG4gIHZhclxuICBjb250YWluZXIgPSBzYWZlU2VsZWN0KHNlbGVjdGlvbiwgJ2cnLCBuYW1lc3BhY2UpLFxuICBiZyA9IGJnUmVjdChjb250YWluZXIsIHJlY3QsIGZpbGwpLFxuICBjcCA9IGNwUmVjdChjb250YWluZXIsIHJlY3QsIG5hbWVzcGFjZSksXG4gIG9iamVjdENvbnRhaW5lciA9IHNhZmVTZWxlY3QoY29udGFpbmVyLCAnZycsIGh5cGVuYXRlKG5hbWVzcGFjZSwgJ29iamVjdC1jb250YWluZXInKSlcbiAgcmV0dXJuIG9iamVjdENvbnRhaW5lclxufVxuXG5cbi8qKlxuKiBkZXRlcm1pbmVzIHRoZSB3aWR0aCBvZiBhbiBvYmplY3QgZm9yIHRoZSBjYWxsaW5nIHBsb3R0aW5nIGZ1bmN0aW9uXG4qIEBwYXJhbSB7bnVtYmVyfSBmcmVlU3BhY2UgaG93IG11Y2ggc3BhY2UgaXMgYXZhbGlibGVcbiogQHBhcmFtIHtudW1iZXJ9IG51bWJlck9mT2JqZWN0cyBob3cgbWFueSBvYmplY3QgZG8gd2UgbmVlZFxuKiBAcGFyYW0ge251bWJlcn0gbWluT2JqZWN0V2lkdGggaG93IHNtYWxsIGFyZSB0aGVzZSBvYmplY3RzIGFsbG93ZWQgdG8gYmVcbiogQHBhcmFtIHtudW1iZXJ9IG1heE9iamVjdFdpZHRoIGhvdyBsYXJnZSBhcmUgdGhlc2Ugb2JqZWN0IGFsbG93ZWQgdG8gYmVcbiogQHBhcmFtIHtudW1iZXJ9IHNpemVPZlNwYWNlciBwZXJjZW50IG9mIGZyZWVTcGFjZSB0aGF0IGEgc2luZ2xlIHNwYWNlciBzaG91bGQgdGFrZSB1cCAobmVlZCBudW1iZXJPZk9iamVjdHMgLSAxIHNwYWNlcnMpXG4qIEBwYXJhbSB7Ym9vbGVhbn0gb3ZlcmZsb3dRIGNhbiB3ZSBnbyBiZXlvbmQgYWxsb3RlZCBzcGFjZVxuKiBAcmV0dXJucyB7bnVtYmVyfSBob3cgbGFyZ2Ugb2JqZWN0IHNob3VsZCBiZVxuKiBmdW5jdGlvbiB0cmllcyB0byBrZWVwIG9iamVjdCB3aXRoaW4gbWluIC8gbWF4IHdpZHRoLCBidXQgd2lsIGRlZmF1bHQgdG9cbiogNWUtMTAgKHNtYWxsZXN0IGNvbnNpc3Rlbmx5IHZpc2libGUgYnkgc3ZnIHNpemUgb2YgZWxlbWVudCkgaWYgb3ZlcmZsb3dRIGlzIGZhbHNlXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3QoZnJlZVNwYWNlLCBudW1iZXJPZk9iamVjdHMsIG1pbk9iamVjdFdpZHRoLCBtYXhPYmplY3RXaWR0aCwgc2l6ZU9mU3BhY2VyLCBvdmVyZmxvd1EpIHtcbiAgdmFyIHNpemVPZlNwYWNlciA9XG4gIHNpemVPZlNwYWNlciA9PSAwIHx8IHNpemVPZlNwYWNlciA+IDFcbiAgPyBzaXplT2ZTcGFjZXJcbiAgOiBmcmVlU3BhY2UgKiBzaXplT2ZTcGFjZXJcblxuICB2YXIgbnVtYmVyT2ZTcGFjZXJzID0gbnVtYmVyT2ZPYmplY3RzIC0gMVxuICB2YXIgc3BhY2VUYWtlbkJ5U3BhY2VycyA9IG51bWJlck9mU3BhY2VycyAqIHNpemVPZlNwYWNlclxuICB2YXIgcmVtYWluaW5nU3BhY2UgPSBmcmVlU3BhY2UgLSBzcGFjZVRha2VuQnlTcGFjZXJzXG4gIHJlbWFpbmluZ1NwYWNlID0gcmVtYWluaW5nU3BhY2UgPCAwID8gMCA6IHJlbWFpbmluZ1NwYWNlXG4gIHZhciBvYmplY3RXaWR0aCA9IHJlbWFpbmluZ1NwYWNlIC8gbnVtYmVyT2ZPYmplY3RzXG5cbiAgaWYgKCBvdmVyZmxvd1EgJiYgbWluT2JqZWN0V2lkdGggIT0gdW5kZWZpbmVkICYmIG9iamVjdFdpZHRoIDwgbWluT2JqZWN0V2lkdGggKSB7IG9iamVjdFdpZHRoID0gbWluT2JqZWN0V2lkdGggfVxuICAvLyBpZiAoIG1heE9iamVjdFdpZHRoICE9IHVuZGVmaW5lZCAmJiBvYmplY3RXaWR0aCA+IG1heE9iamVjdFdpZHRoICkgeyBvYmplY3RXaWR0aCA9IG1heE9iamVjdFdpZHRoIH1cbiAgaWYgKCBvdmVyZmxvd1EgJiYgbWF4T2JqZWN0V2lkdGggIT0gdW5kZWZpbmVkICYmIG9iamVjdFdpZHRoIDwgbWF4T2JqZWN0V2lkdGggKSB7IG9iamVjdFdpZHRoID0gbWF4T2JqZWN0V2lkdGggfVxuICByZXR1cm4gTWF0aC5tYXgob2JqZWN0V2lkdGgsIDVlLTEwKVxufVxuXG4vKipcbiogQHBhcmFtIHtBcnJheVtdfSBkYXRhIGxpc3QgZGF0YSAoY2FuIGJlIG5lc3RlZCkuIElmIG5lc3RlZCB3aWxsIGNyZWF0ZSBtb3JlIGNvbXBsZXggc3BhY2VyIHNpemVcbiogQHBhcmFtIHtudW1iZXJ9IGZyZWVTcGFjZSBob3cgbXVjaCBzcGFjZSBpcyBhdmFsaWJsZVxuKiBAcGFyYW0ge251bWJlcn0gb2JqZWN0V2lkdGggQHNlZXtAbGluayBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0fVxuKiBAcGFyYW0ge251bWJlcn0gbnVtYmVyT2ZPYmplY3RzIGhvdyBtYW55IG9iamVjdCBkbyB3ZSBuZWVkXG4qIEBwYXJhbSB7bnVtYmVyfSBiYXNlU3BhY2VyU2l6ZSBwZXJjZW50IG9mIGZyZWVTcGFjZSB0aGF0IGEgc2luZ2xlIHNwYWNlciBzaG91bGQgdGFrZSB1cCAobmVlZCBudW1iZXJPZk9iamVjdHMgLSAxIHNwYWNlcnMpXG4qIEBwYXJhbSB7Ym9vbGVhbn0gb3ZlcmZsb3dRIGNhbiB3ZSBnbyBiZXlvbmQgYWxsb3RlZCBzcGFjZVxuKiBAcmV0dXJucyB7bnVtYmVyfSByZXR1cm5zIHNpemUgdGhhdCBzcGFjZXIgc2hvdWxkIGJlIGF0IGxldmVsPTBcbiovXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlV2lkdGhPZlNwYWNlcihkYXRhLCBmcmVlU3BhY2UsIG9iamVjdFdpZHRoLCBudW1iZXJPZk9iamVjdHMsIGJhc2VTcGFjZXJTaXplLCBvdmVyZmxvd1EpIHtcbiAgaWYgKG92ZXJmbG93USkge1xuICAgIC8vIHZhciBsaW1pdGVkTnVtYmVyT2ZPYmplY3RzID0gbnVtYmVyT2ZPYmplY3RzID4gNiA/IDYgOiBudW1iZXJPZk9iamVjdHNcbiAgICAvLyB2YXIgc3BhY2VMZWZ0ID0gZnJlZVNwYWNlIC0gbGltaXRlZE51bWJlck9mT2JqZWN0cyAqIG9iamVjdFdpZHRoXG4gICAgLy8gcmV0dXJuIHNwYWNlTGVmdCAvIChsaW1pdGVkTnVtYmVyT2ZPYmplY3RzIC0gMSlcbiAgICByZXR1cm4gZnJlZVNwYWNlICogYmFzZVNwYWNlclNpemVcbiAgfVxuICB2YXIgc3BhY2Vyc0F0RWFjaExldmVsID0gc3BhY2Vyc05lZWRlZEF0RWFjaExldmVsKGRhdGEpXG4gIHZhciB0b3RhbFNwYWNlclBlcmNlbnQgPSB0b3RhbChzcGFjZXJzQXRFYWNoTGV2ZWwubWFwKGZ1bmN0aW9uKGUsIGkpIHtyZXR1cm4gZSAqIDEgLyAoaSsxKX0pKVxuICB2YXIgYmFzZVNwYWNlclNpemUgPSAoZnJlZVNwYWNlIC0gKG9iamVjdFdpZHRoICogbnVtYmVyT2ZPYmplY3RzKSkgLyB0b3RhbFNwYWNlclBlcmNlbnRcbiAgLy8gY29uc29sZS5sb2coZnJlZVNwYWNlLCBvYmplY3RXaWR0aCwgbnVtYmVyT2ZPYmplY3RzLCB0b3RhbFNwYWNlclBlcmNlbnQpXG4gIC8vIGNvbnNvbGUubG9nKHRvdGFsU3BhY2VyUGVyY2VudCwgYmFzZVNwYWNlclNpemUsIHRvdGFsU3BhY2VyUGVyY2VudCAqIGJhc2VTcGFjZXJTaXplKVxuICByZXR1cm4gaXNOYU4oYmFzZVNwYWNlclNpemUpID8gMCA6IGJhc2VTcGFjZXJTaXplXG59XG5cblxuLyoqXG4qIENhbGN1bGF0ZXMgbnVtYmVyIG9mIHNwYWNlcnMgbmVlZGVkIHRvIHNlcGVyYXRlIGVsZW1lbnRzIGF0IGVhY2ggbGV2ZWwuXG4qIEBwYXJhbSB7QXJyYXlbXX0gYXJyYXkgbGlzdCBkYXRhIChjYW4gYmUgbmVzdGVkKS4gSWYgbmVzdGVkIHdpbGwgY3JlYXRlIG1vcmUgY29tcGxleCBzcGFjZXIgc2l6ZVxuKiBAcGFyYW0ge251bWJlcn0gW2xldmVsPTBdIGN1cnJlbnQgbGV2ZWwsIHVzZWQgaW4gcmVjdXNyaW9uXG4qIEBwYXJhbSB7QXJyYXl9IFtsZXZlbERhdGE9W11dIGhvdyBtYW55IHNwYWNlcnMgbmVlZGVkIGF0IGEgZ2l2ZW4gbGV2ZWxcbiogQHJldHVybnMge0FycmF5fSBsZXZlbERhdGFcbipcbiogQGV4YW1wbGVcbiogYXJyYXkgPSBbWzEsMl0sIFszLDRdXVxuKiAvLyByZXR1cm5zIFsxLCAyXVxuKiBhcyBhdCBsZXZlbD0wIHRoZSBvbmx5IHNwYWNlciBuZWVkZWQgaXMgYmV0d2VlbiBbMSwyXSBhbmQgWzMsNF1cbiogYW5kIGF0IGxldmVsPTEgdGhlIG9ubHkgdHdvIHNwYWNlcnMgbmVlZGVkIGlzIGJldHdlZW4gMSBhbmQgMiBhcyB3ZWxsIGFzXG4qIDMgYW5kIDQgc2luY2UgdGhlIHNwYWNlciBiZXR3ZWVuIDIgYW5kIDMgaXMgaGFuZGxlZCBhdCBsZXZlbD0wXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIHNwYWNlcnNOZWVkZWRBdEVhY2hMZXZlbCAoYXJyYXksIGxldmVsLCBsZXZlbERhdGEgKSB7XG4gIGlmICggbGV2ZWwgPT0gdW5kZWZpbmVkICkgeyBsZXZlbCA9IDA7ICB9IGVsc2UgeyBsZXZlbCArPSAxIH1cbiAgaWYgKCBsZXZlbERhdGEgPT0gdW5kZWZpbmVkICkgeyBsZXZlbERhdGEgPSBbXTsgfVxuICBpZiAoIGxldmVsID49IGxldmVsRGF0YS5sZW5ndGggKSB7IGxldmVsRGF0YS5wdXNoKGFycmF5Lmxlbmd0aCAtIDEpIH1cbiAgZWxzZSB7IGxldmVsRGF0YVtsZXZlbF0gKz0gYXJyYXkubGVuZ3RoIC0gMSB9XG4gIGFycmF5Lm1hcChmdW5jdGlvbihlLCBpKSB7IGlmIChBcnJheS5pc0FycmF5KGUpKSB7IHNwYWNlcnNOZWVkZWRBdEVhY2hMZXZlbChlLCBsZXZlbCwgbGV2ZWxEYXRhKSB9IH0gKVxuICByZXR1cm4gbGV2ZWxEYXRhXG59XG5cblxuXG5cbi8qKlxuKiBEcmF3cyBhIHdoaXNrZXIgZm9yIEBzZWV7QGxpbmsgYm94d2hpc2tlcn1cbiogQHBhcmFtIHtib29sZWFufSBkaXIgZGlyZWN0aW9uIHRvIGRyYXcgd2hpc2tlciwgc2hvdWxkIGJlIGVpdGhlciB0cnVlICh1cCwgdG9wKSBvciBmYWxzZSAoZG93biBvciBib3R0b20pXG4qIEBwYXJhbSB7bnVtYmVyfSB4IHN0YXJ0aW5nIHggY29vcmRpbmF0ZSBpbiB3aGljaCB0byBkcmF3IHdoaXNrZXJcbiogQHBhcmFtIHtudW1iZXJ9IHkgc3RhcnRpbmcgeSBjb29yZGluYXRlIGluIHdoaWNoIHRvIGRyYXcgd2hpc2tlclxuKiBAcGFyYW0ge251bWJlcn0gdyB3aWR0aCBvZiBzcGFjZSBpbiB3aGljaCB0byBkcmF3IHdoaXNrZXJcbiogQHBhcmFtIHtudW1iZXJ9IGggaGVpZ2h0IG9mIHNwYWNlIGluIHdoaWNoIHRvIGRyYXcgd2hpc2tlclxuKiBAcGFyYW0ge251bWJlcn0gcGVyIHBlcmNlbnRhZ2Ugb2YgdyBvciBoIChkZXBlbmRzIG9uIG8pIHRvIG1ha2Ugd2hpc2tlclxuKiBAcGFyYW0ge2Jvb2xlYW59IG8gb3JpZW50YXRpb24sIHRydWUgaXMgaG9yaXpvbnRhbCBhbmQgZmFsc2UgaXMgdmVydGljYWxcbiogQHJldHVybnMge3N0cmluZ30gcmVwcmVzZW50aW5nIHRoZSBzdmcgcGF0aCAoaS5lLiB0aGUgZCBhdHRyaWJ1dGUgZm9yIGEgcGF0aCB0YWcpXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIHdoaXNrZXJQYXRoKGRpciwgeCwgeSwgdywgaCwgcGVyLCBvKSB7XG4gIC8vIGQgPSBkaXJlY3Rpb24gKHRydWUgaXMgdXApLCBwID0gcGVyY2VudCB3aWR0aFxuICBpZiAoZGlyID09ICd1cCcgfHwgZGlyID09ICd0b3AnIHx8IGRpciA9PSB0cnVlKSB7ZGlyID0gdHJ1ZX1cbiAgaWYgKGRpciA9PSAnZG93bicgfHwgZGlyID09ICdib3R0b20nIHx8IGRpciA9PSBmYWxzZSkge2RpciA9IGZhbHNlfVxuICBvID0gbyA9PSB1bmRlZmluZWQgPyAnaG9yaXpvbnRhbCcgOiBvXG4gIHBlciA9IHBlciA9PSB1bmRlZmluZWQgPyAxIDogcGVyXG4gIGlmIChvICE9IFwiaG9yaXpvbnRhbFwiKSB7XG4gICAgdmFyIGhoID0gaCAqIHBlciAsXG4gICAgdyA9IGRpciA/IHcgOiAtdyAsXG4gICAgYSA9IGRpciA/IHggKyB3IDogeCAsXG4gICAgYiA9IGRpciA/IHggOiB4ICsgdyAsXG4gICAgYyA9IGRpciA/IGEgOiBiXG4gICAgcCA9IFwiTSBcIiArIGEgKyAnICcgKyAoICAgICBoIC8gMiAgICAgICkgKyAnICdcbiAgICAgICsgJ0wgJyArIGIgKyAnICcgKyAoICAgICBoIC8gMiAgICAgICkgKyAnICdcbiAgICAgICsgJ00gJyArIGMgKyAnICcgKyAoIGggLyAyIC0gaGggLyAyICkgKyAnICdcbiAgICAgICsgJ0wgJyArIGMgKyAnICcgKyAoIGggLyAyICsgaGggLyAyICkgKyAnICdcblxuICAgIHJldHVybiBwXG4gIH1cbiAgdmFyIHd3ID0gdyAqIHBlcixcbiAgYSA9IGRpciA/IHkgKyBoIDogeSAgLFxuICBiID0gZGlyID8geSA6IHkgKyBoICAsXG4gIHAgPSBcIk0gXCIgKyAoICB3IC8gMiAgKSArICcgJyArIGEgKyAnICcgLy8gc3RyYWlnaHQgbGluZSBwYXJ0XG4gICAgKyAnTCAnICsgKCAgdyAvIDIgICkgKyAnICcgKyBiICsgJyAnIC8vIHN0cmFpZ2h0IGxpbmUgcGFydFxuICAgICsgJ2ggJyArICggLXd3IC8gMiApICsgJyAnICsgMCArICcgJyAvLyBob3Jpem9udGFsIGxpbmUgcGFydFxuICAgICsgJ2ggJyArICggICAgd3cgICApICsgJyAnICsgMCArICcgJ1xuICByZXR1cm4gcFxufVxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5leHBvcnQgZnVuY3Rpb24gcmVzaXplRGVib3VuY2UoZiwgd2FpdCkge1xuICB2YXIgcmVzaXplID0gZGVib3VuY2UoZnVuY3Rpb24oKXtmKCl9LHdhaXQpXG4gIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCByZXNpemUpXG59XG5cblxuXG5mdW5jdGlvbiBkZWJvdW5jZShmdW5jLCB3YWl0LCBpbW1lZGlhdGUpIHtcbiAgdmFyIHRpbWVvdXQ7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgY29udGV4dCA9IHRoaXMsIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIHZhciBsYXRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGltZW91dCA9IG51bGw7XG4gICAgICAgICAgICBpZiAoIWltbWVkaWF0ZSkgZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNhbGxOb3cgPSBpbW1lZGlhdGUgJiYgIXRpbWVvdXQ7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQpO1xuICAgICAgICBpZiAoY2FsbE5vdykgZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICB9O1xufVxuIiwiaW1wb3J0IHtsb2csIHdhcm4sIGVycm9yLCBpbmZvfSBmcm9tICcuL3V0aWxzJztcbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU1BBQ0VHUk9VUElORyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4vKipcbiAqIFByb2R1Y2VzIGEgZnVuY3Rpb24gZm9yIHNwYWNpbmcgb2JqZWN0cyBieSBhbiBhcmJpdHJhcmx5IGNvbXBsZXggZ3JvdXBpbmdcbiAqIEByZXR1cm5zIHtyZWN1cnNpdmVseVBvc2l0aW9ufSB0aGUgZnVuY3Rpb24gZm9yIG1vdmluZyB0aGUgb2JqZWN0c1xuICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIjcmVjdXJzaXZlbHlQb3NpdGlvbn0pXG4gKiBAbmFtZXNwYWNlIGdyb3VwaW5nU3BhY2VyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBncm91cGluZ1NwYWNlcigpIHtcbiAgdmFyXG4gIC8qQHZhciB7Ym9vbGVhbn0gaG9yaXpvbnRhbFEgQGRlZmF1bHQqL1xuXG4gIC8qKlxuICAqIFdoZXRoZXIgb3Igbm90IHRvIHNwYWNlIG9iamVjdHMgaG9yaXpvbnRhbGx5IG9yIHZlcnRpY2FsbHkuXG4gICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIuaG9yaXpvbnRhbFF9KVxuICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2hvcml6b250YWxRPXRydWVdXG4gICogQG1lbWJlcm9mIGdyb3VwaW5nU3BhY2VyI1xuICAqIEBpbnN0YW5jZVxuICAqL1xuICBob3Jpem9udGFsUSA9IHRydWUsXG4gIC8qKlxuICAqIFRoZSBzY2FsZSB0byB1c2UgdG8gcG9zaXRpb24gZWxlbWVudHMgaWYge0BsaW5rIGdyb3VwaW5nU3BhY2VyI21vdmVieX09XCJzdHJpbmdcIlxuICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyLnNjYWxlfSlcbiAgKiBAcGFyYW0ge2QzLnNjYWxlfSBbc2NhbGU9ZDMuc2NhbGVMaW5lYXIoKV1cbiAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXIjXG4gICogQGluc3RhbmNlXG4gICovXG4gIHNjYWxlID0gZDMuc2NhbGVMaW5lYXIoKSxcbiAgLyoqXG4gICogSG93IGVsZW1lbnRzIGluIHRoZSBjb21wbGV4IGdyb3VwaW5nIHNob3VsZCBiZSBtb3ZlZCBvdmVyIGJ5LlxuICAqIEJ5IGRlZmF1bHQsIG1vdmVieT1cImNhdGVnb3J5XCIsIHdoaWNoIG1vdmVzIG9iamVjdHMgYnkgdGhlIGNvbXBsZXggZ3JvdXBpbmdcbiAgKiBCdXQgb2JqZWN0cyBjYW4gYWxzbyBiZSBtb3ZlZCBvdmVyIGJ5IHNjYWxlLlxuICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyLm1vdmVieX0pXG4gICogQHBhcmFtIHtzdHJpbmd9IFttb3ZlYnk9XCJjYXRlZ29yeVwiXVxuICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlciNcbiAgKiBAaW5zdGFuY2VcbiAgKi9cbiAgbW92ZWJ5ID0gJ2NhdGVnb3J5JyxcbiAgLyoqXG4gICogSG93IG1hbnkgb2JqZWN0cyBhcmUgdGhlcmUgaW4gdG90YWxcbiAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlci5udW1iZXJPZk9iamVjdHN9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbbnVtYmVyT2ZPYmplY3RzPW5vbmVdXG4gICogQG1lbWJlcm9mIGdyb3VwaW5nU3BhY2VyI1xuICAqIEBpbnN0YW5jZVxuICAqL1xuICBudW1iZXJPZk9iamVjdHMsXG4gIC8qKlxuICAqIFRoZSBjbGFzcyBnaXZlbiB0byBhbiBuZXN0ZWQgPGc+IHRhZyB3aG9zZSBwYXJlbnQocykgaGF2ZSB0aGUgY29ycmVjdCB0cmFuc2l0aW9uXG4gICogcHJvcGVydGllc1xuICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyLm51bWJlck9mT2JqZWN0c30pXG4gICogQHBhcmFtIHtzdHJpbmd9IFtudW1iZXJPZk9iamVjdHM9J2Qzc20tZ3JvdXBwZWQtaXRlbSddXG4gICogQG1lbWJlcm9mIGdyb3VwaW5nU3BhY2VyI1xuICAqIEBpbnN0YW5jZVxuICAqL1xuICBvYmplY3RDbGFzcyA9ICdkM3NtLWdyb3VwcGVkLWl0ZW0nLFxuICAvKipcbiAgKiBUaGUgc2l6ZSBvZiB0aGUgb2JqZWN0cyBiZWluZyBwb3NpdGlvbmVkXG4gICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIub2JqZWN0U2l6ZX0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtvYmplY3RTaXplPW5vbmVdXG4gICogQG1lbWJlcm9mIGdyb3VwaW5nU3BhY2VyI1xuICAqIEBpbnN0YW5jZVxuICAqL1xuICBvYmplY3RTaXplLFxuICAvKipcbiAgKiBUaGUgc2l6ZSBvZiB0aGUgdW4tbmVzdGVkIHNwYWNlciBiZXR3ZWVuIG9iamVjdHNcbiAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlci5zcGFjZXJTaXplfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlclNpemU9bm9uZV1cbiAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXIjXG4gICogQGluc3RhbmNlXG4gICovXG4gIHNwYWNlclNpemUsXG4gIC8qKlxuICAqIFRoZSBkdXJhdGlvbiBvZiB0cmFuc2l0aW9ucyBpbiBtc1xuICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyLnRyYW5zaXRpb25EdXJhdGlvbn0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFt0cmFuc2l0aW9uRHVyYXRpb249MTAwMF1cbiAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXIjXG4gICogQGluc3RhbmNlXG4gICovXG4gIHRyYW5zaXRpb25EdXJhdGlvbiA9IDEwMDAsXG4gIC8qKlxuICAqIFRoZSBlYXNlIGZ1bmN0aW9uIGZvciB0aGUgdHJhbnNpdGlvbnNcbiAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlci5lYXNlRnVuY30pXG4gICogQHBhcmFtIHtkMy5lYXNlfSBbZWFzZUZ1bmM9ZDMuZWFzZVNpbl1cbiAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXIjXG4gICogQGluc3RhbmNlXG4gICovXG4gIGVhc2VGdW5jID0gZDMuZWFzZVNpbixcbiAgLyoqXG4gICogVGhlIG5hbWVzcGFjZSBmb3IgdGhlIG9iamVjdHMgYmVpbmcgbW92ZWRcbiAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlci5uYW1lc3BhY2V9KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbbmFtZXNwYWNlPSdzcGFjZXInXVxuICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlciNcbiAgKiBAaW5zdGFuY2VcbiAgKi9cbiAgbmFtZXNwYWNlID0gJ3NwYWNlcicsXG4gIC8qKlxuICAqIFRoZSBhbmltYXRpb24gZm9yIG5ldyBvYmplY3RzIGJlaW5nIGFkZGVkXG4gICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIuZW50ZXJGdW5jdGlvbn0pXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gZW50ZXJGdW5jdGlvblxuICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlciNcbiAgKiBAaW5zdGFuY2VcbiAgKiBAZXhhbXBsZVxuICAqIC8vIGJ5IGRlZmF1bHRcbiAgKiBmdW5jdGlvbihuZXdPYmplY3RTZWxlY3Rpb24pIHtcbiAgKiAgbmV3T2JqZWN0U2VsZWN0aW9uLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQsIGkpe1xuICAqICAgIHZhclxuICAqICAgIHggPSBob3Jpem9udGFsUSA/IG9iamVjdFNpemUgKiBudW1iZXJPZk9iamVjdHMgKyBzcGFjZXJTaXplICogKG51bWJlck9mT2JqZWN0cyAtIDEpIDogMCxcbiAgKiAgICB5ID0gIWhvcml6b250YWxRID8gb2JqZWN0U2l6ZSAqIG51bWJlck9mT2JqZWN0cyArIHNwYWNlclNpemUgKiAobnVtYmVyT2ZPYmplY3RzIC0gMSkgOiAwLFxuICAqICAgIHQgPSAndHJhbnNsYXRlKCcreCsnLCcreSsnKSdcbiAgKiAgICByZXR1cm4gdFxuICAqICB9KVxuICAqIH1cbiAgKi9cbiAgZW50ZXJGdW5jdGlvbiA9IGZ1bmN0aW9uKGN1cikge1xuICAgIGN1ci5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhclxuICAgICAgLy8geCA9IGhvcml6b250YWxRID8gb2JqZWN0U2l6ZSAqIG51bWJlck9mT2JqZWN0cyArIHNwYWNlclNpemUgKiAobnVtYmVyT2ZPYmplY3RzIC0gMSkgOiAwLFxuICAgICAgLy8geSA9ICFob3Jpem9udGFsUSA/IG9iamVjdFNpemUgKiBudW1iZXJPZk9iamVjdHMgKyBzcGFjZXJTaXplICogKG51bWJlck9mT2JqZWN0cyAtIDEpIDogMCxcbiAgICAgIHggPSBob3Jpem9udGFsUSA/IHdpbmRvdy5vdXRlcldpZHRoIDogMCxcbiAgICAgIHkgPSAhaG9yaXpvbnRhbFEgPyB3aW5kb3cub3V0ZXJXaWR0aCA6IDAsXG4gICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICAgICAvLyBpZih5ID09IHVuZGVmaW5lZCkge2NvbnNvbGUubG9nKGN1ci5ub2RlKCksIHksIGQpfVxuICAgICAgcmV0dXJuIHRcbiAgICB9KVxuICB9LFxuICAvKipcbiAgKiBUaGUgYW5pbWF0aW9uIGZvciBvbGQgb2JqZWN0cyBiZWluZyByZW1vdmVkXG4gICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIuZXhpdEZ1bmN0aW9ufSlcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBleGl0RnVuY3Rpb25cbiAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXIjXG4gICogQGluc3RhbmNlXG4gICogQGV4YW1wbGVcbiAgKiAvLyBieSBkZWZhdWx0XG4gICogb2xkT2JqZWN0U2VsZWN0aW9uLnRyYW5zaXRpb24oKS5kdXJhdGlvbih0cmFuc2l0aW9uRHVyYXRpb24pLmVhc2UoZWFzZUZ1bmMpXG4gICogLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQsIGkpe1xuICAqICAgICB2YXJcbiAgKiAgIHggPSBob3Jpem9udGFsUSA/IG9iamVjdFNpemUgKiBudW1iZXJPZk9iamVjdHMgKyBzcGFjZXJTaXplICogKG51bWJlck9mT2JqZWN0cyAtIDEpIDogMCxcbiAgKiAgIHkgPSAhaG9yaXpvbnRhbFEgPyBvYmplY3RTaXplICogbnVtYmVyT2ZPYmplY3RzICsgc3BhY2VyU2l6ZSAqIChudW1iZXJPZk9iamVjdHMgLSAxKSA6IDAsXG4gICogICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICogICByZXR1cm4gdFxuICAqIH0pLnJlbW92ZSgpXG4gICovXG4gIGV4aXRGdW5jdGlvbiA9IGZ1bmN0aW9uKGN1cil7XG4gICAgbG9nKFwiZ3JvdXBpbmdTcGFjZXJcIiwgXCJleGl0aW5nIHdpdGhcIiwge2N1cnJlbnQ6IGN1ciwgY3VycmVudE5vZGU6IGN1ci5ub2RlKCl9KVxuICAgIGN1ci5zZWxlY3RBbGwoJ2cnKS5jbGFzc2VkKCd0by1yZW1vdmUnLCB0cnVlKVxuXG4gICAgY3VyLnRyYW5zaXRpb24oKS5kdXJhdGlvbih0cmFuc2l0aW9uRHVyYXRpb24qMC45KS5lYXNlKGVhc2VGdW5jKVxuICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhclxuICAgICAgLy8geCA9IGhvcml6b250YWxRID8gb2JqZWN0U2l6ZSAqIG51bWJlck9mT2JqZWN0cyArIHNwYWNlclNpemUgKiAobnVtYmVyT2ZPYmplY3RzIC0gMSkgOiAwLFxuICAgICAgLy8geSA9ICFob3Jpem9udGFsUSA/IG9iamVjdFNpemUgKiBudW1iZXJPZk9iamVjdHMgKyBzcGFjZXJTaXplICogKG51bWJlck9mT2JqZWN0cyAtIDEpIDogMCxcbiAgICAgIHggPSBob3Jpem9udGFsUSA/IHdpbmRvdy5vdXRlcldpZHRoIDogMCxcbiAgICAgIHkgPSAhaG9yaXpvbnRhbFEgPyB3aW5kb3cub3V0ZXJXaWR0aCA6IDAsXG4gICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICAgICAvLyBpZih5ID09IHVuZGVmaW5lZCkge2NvbnNvbGUubG9nKGN1ci5ub2RlKCksIHksIGQpfVxuICAgICAgcmV0dXJuIHRcbiAgICB9KS5yZW1vdmUoKVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIGhvcml6b250YWxRICh3aGV0aGVyIG9yIG5vdCB0byBzcGFjZSBvYmplY3RzIGhvcml6b250YWxseSBvciB2ZXJ0aWNhbGx5KS5cbiAgICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIjaG9yaXpvbnRhbFF9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXJcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcmVjdXJzaXZlbHlQb3NpdGlvbi5ob3Jpem9udGFsUSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaG9yaXpvbnRhbFEgPSBfLCByZWN1cnNpdmVseVBvc2l0aW9uKSA6IGhvcml6b250YWxRIH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzY2FsZSB0byB1c2UgdG8gcG9zaXRpb24gZWxlbWVudHMgaWYge0BsaW5rIGdyb3VwaW5nU3BhY2VyI21vdmVieX09XCJzdHJpbmdcIlxuICAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlciNzY2FsZX0pXG4gICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtncm91cGluZ1NwYWNlciB8IGQzLnNjYWxlfVxuICAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXJcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcmVjdXJzaXZlbHlQb3NpdGlvbi5zY2FsZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGUgPSBfLCByZWN1cnNpdmVseVBvc2l0aW9uKSA6IHNjYWxlIH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIG1vdmVieSAod2hldGhlciBvciBub3QgdG8gbW92ZSBieSBzY2FsZSBvciBieSBncm91cGluZykuXG4gICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyI21vdmVieX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Z3JvdXBpbmdTcGFjZXIgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlclxuICAgKiBAc3RhdGljXG4gICAqL1xuICByZWN1cnNpdmVseVBvc2l0aW9uLm1vdmVieSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobW92ZWJ5ID0gXywgcmVjdXJzaXZlbHlQb3NpdGlvbikgOiBtb3ZlYnkgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgbnVtYmVyT2ZPYmplY3RzLlxuICAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlciNudW1iZXJPZk9iamVjdHN9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXJcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcmVjdXJzaXZlbHlQb3NpdGlvbi5udW1iZXJPZk9iamVjdHMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG51bWJlck9mT2JqZWN0cyA9IF8sIHJlY3Vyc2l2ZWx5UG9zaXRpb24pIDogbnVtYmVyT2ZPYmplY3RzIH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RDbGFzcyAod2lsbCBiZSBhcHBsaWVkIHRvIDxnPiBlbGVtZW50cykuXG4gICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyI29iamVjdENsYXNzfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtncm91cGluZ1NwYWNlciB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGdyb3VwaW5nU3BhY2VyXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIHJlY3Vyc2l2ZWx5UG9zaXRpb24ub2JqZWN0Q2xhc3MgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdENsYXNzID0gXywgcmVjdXJzaXZlbHlQb3NpdGlvbikgOiBvYmplY3RDbGFzcyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgb2JqZWN0U2l6ZS5cbiAgICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIjb2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Z3JvdXBpbmdTcGFjZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlclxuICAgKiBAc3RhdGljXG4gICAqL1xuICByZWN1cnNpdmVseVBvc2l0aW9uLm9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNpemUgPSBfLCByZWN1cnNpdmVseVBvc2l0aW9uKSA6IG9iamVjdFNpemUgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHNwYWNlclNpemUuXG4gICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyI3NwYWNlclNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXJcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcmVjdXJzaXZlbHlQb3NpdGlvbi5zcGFjZXJTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZXJTaXplID0gXywgcmVjdXJzaXZlbHlQb3NpdGlvbikgOiBzcGFjZXJTaXplIH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB0cmFuc2l0aW9uRHVyYXRpb24uXG4gICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyI3RyYW5zaXRpb25EdXJhdGlvbn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Z3JvdXBpbmdTcGFjZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlclxuICAgKiBAc3RhdGljXG4gICAqL1xuICByZWN1cnNpdmVseVBvc2l0aW9uLnRyYW5zaXRpb25EdXJhdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodHJhbnNpdGlvbkR1cmF0aW9uID0gXywgcmVjdXJzaXZlbHlQb3NpdGlvbikgOiB0cmFuc2l0aW9uRHVyYXRpb24gfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGVhc2VGdW5jLlxuICAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlciNlYXNlRnVuY30pXG4gICAqIEBwYXJhbSB7ZDMuZWFzZX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgZDMuZWFzZX1cbiAgICogQG1lbWJlcm9mIGdyb3VwaW5nU3BhY2VyXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIHJlY3Vyc2l2ZWx5UG9zaXRpb24uZWFzZUZ1bmMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGVhc2VGdW5jID0gXywgcmVjdXJzaXZlbHlQb3NpdGlvbikgOiBlYXNlRnVuYyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbmFtZXNwYWNlLlxuICAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlciNuYW1lc3BhY2V9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXJcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcmVjdXJzaXZlbHlQb3NpdGlvbi5uYW1lc3BhY2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG5hbWVzcGFjZSA9IF8sIHJlY3Vyc2l2ZWx5UG9zaXRpb24pIDogbmFtZXNwYWNlIH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBlbnRlckZ1bmN0aW9uLlxuICAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlciNlbnRlckZ1bmN0aW9ufSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlclxuICAgKiBAc3RhdGljXG4gICAqL1xuICByZWN1cnNpdmVseVBvc2l0aW9uLmVudGVyRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGVudGVyRnVuY3Rpb24gPSBfLCByZWN1cnNpdmVseVBvc2l0aW9uKSA6IGVudGVyRnVuY3Rpb24gfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGV4aXRGdW5jdGlvbi5cbiAgICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIjZXhpdEZ1bmN0aW9ufSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlclxuICAgKiBAc3RhdGljXG4gICAqL1xuICByZWN1cnNpdmVseVBvc2l0aW9uLmV4aXRGdW5jdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZXhpdEZ1bmN0aW9uID0gXywgcmVjdXJzaXZlbHlQb3NpdGlvbikgOiBleGl0RnVuY3Rpb24gfVxuXG5cbiAgLyoqXG4gICAqIHJlY3Vyc2l2ZWx5IHBvc2l0aW9uIHRoZSBvYmplY3RzIGluc2lkZSBvZiB0aGUgc2VsZWN0aW9uLlxuICAgKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gc2VsZWN0aW9uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhXG4gICAqIEBwYXJhbSB7bGV2ZWx9IFtsZXZlbD0wXSByZWN1cnNpb24gZGVwdGhcbiAgICogQHJldHVybnMge251bWJlcn0gKGhvdyBtdWNoIHRvIG1vdmUgbmV4dCBlbGVtZW50KVxuICAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXIjXG4gICAqL1xuICBmdW5jdGlvbiByZWN1cnNpdmVseVBvc2l0aW9uKHNlbGVjdGlvbiwgZGF0YSwgbGV2ZWwpIHtcbiAgICBpZiAoIGxldmVsID09IHVuZGVmaW5lZCApIHsgbGV2ZWwgPSAwOyAgfVxuXG4gICAgdmFyIGN1cnJlbnRTZWxlY3Rpb24gPSBzZWxlY3Rpb24uc2VsZWN0QWxsKCdnLicrbmFtZXNwYWNlKydbbGV2ZWw9XCInK2xldmVsKydcIl0nKS5kYXRhKGRhdGEpXG4gICAgdmFyIGVudGVyID0gY3VycmVudFNlbGVjdGlvbi5lbnRlcigpLmFwcGVuZCgnZycpLmF0dHIoJ2xldmVsJywgbGV2ZWwpLmF0dHIoJ2NsYXNzJywgbmFtZXNwYWNlKVxuICAgIHZhciBleGl0ID0gY3VycmVudFNlbGVjdGlvbi5leGl0KClcbiAgICBjdXJyZW50U2VsZWN0aW9uID0gY3VycmVudFNlbGVjdGlvbi5tZXJnZShlbnRlcilcblxuXG4gICAgaWYgKHR5cGVvZiBleGl0RnVuY3Rpb24gPT0gJ2Z1bmN0aW9uJyApeyBleGl0LmVhY2goZnVuY3Rpb24oZCwgaSl7IGV4aXRGdW5jdGlvbihkMy5zZWxlY3QodGhpcykpfSkgfVxuICAgIGVsc2V7ZXhpdC5yZW1vdmUoKX1cbiAgICAvLyBzcGFjZXIgZm9yIGN1cnJlbnQgbGV2ZWxcbiAgICB2YXIgbGV2ZWxTcGFjZXIgPSBzcGFjZXJTaXplIC8gKGxldmVsKzEpXG4gICAgLy8gbW92ZW1lbnQgZm9yIGN1cnJlbnQgbGV2ZWxcbiAgICB2YXIgbW92ZSA9IDBcbiAgICBjdXJyZW50U2VsZWN0aW9uLmVhY2goZnVuY3Rpb24oY3VycmVudEVsZW1lbnQsIGluZGV4KSB7XG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgICAgaWYgKHQuYXR0cigndHJhbnNmb3JtJykgPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBlbnRlckZ1bmN0aW9uID09ICdmdW5jdGlvbicpIHsgZW50ZXJGdW5jdGlvbih0KSB9XG5cbiAgICAgIHQudHJhbnNpdGlvbigpLmR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbikuZWFzZShlYXNlRnVuYylcbiAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgIHZhclxuICAgICAgICB4ID0gaG9yaXpvbnRhbFEgPyAobW92ZWJ5ID09XCJzY2FsZVwiID8gc2NhbGUoZCkgOiBtb3ZlKSA6IDAsXG4gICAgICAgIHkgPSAhaG9yaXpvbnRhbFEgPyAobW92ZWJ5ID09XCJzY2FsZVwiID8gc2NhbGUoZCkgOiBtb3ZlKTogMCxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcblxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY3VycmVudEVsZW1lbnQpKSB7XG4gICAgICAgIG1vdmUgKz0gcmVjdXJzaXZlbHlQb3NpdGlvbih0LCBjdXJyZW50RWxlbWVudCwgbGV2ZWwrMSlcbiAgICAgICAgdmFyIHRvUmVtb3ZlID0gdC5zZWxlY3RBbGwoJ2cuJytuYW1lc3BhY2UrJ1tsZXZlbD1cIicrKGxldmVsKSsnXCJdID4gZy4nK29iamVjdENsYXNzKycuJytuYW1lc3BhY2UpXG4gICAgICAgIGlmICh0eXBlb2YgZXhpdEZ1bmN0aW9uID09ICdmdW5jdGlvbicgKXsgdG9SZW1vdmUuZWFjaChmdW5jdGlvbihkLCBpKXsgZXhpdEZ1bmN0aW9uKGQzLnNlbGVjdCh0aGlzKSl9KSB9XG4gICAgICAgIGVsc2V7dG9SZW1vdmUucmVtb3ZlKCl9XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgbW92ZSArPSBvYmplY3RTaXplXG4gICAgICAgIHZhciBvYmogPSB0LnNlbGVjdCgnZy4nK25hbWVzcGFjZSsnW2xldmVsPVwiJytsZXZlbCsnXCJdID4gZy4nK29iamVjdENsYXNzKycuJytuYW1lc3BhY2UpXG4gICAgICAgIGlmIChvYmouZW1wdHkoKSkgeyBvYmogPSB0LmFwcGVuZCgnZycpLmF0dHIoJ2NsYXNzJywgb2JqZWN0Q2xhc3MpLmNsYXNzZWQobmFtZXNwYWNlLCB0cnVlKSB9XG4gICAgICAgIG9iai5hdHRyKCdwYXJlbnQtaW5kZXgnLCBpbmRleClcbiAgICAgICAgdmFyIHRvUmVtb3ZlID0gdC5zZWxlY3RBbGwoJ2cuJytuYW1lc3BhY2UrJ1tsZXZlbD1cIicrKGxldmVsKzEpKydcIl0nKVxuXG4gICAgICAgIGlmICh0eXBlb2YgZXhpdEZ1bmN0aW9uID09ICdmdW5jdGlvbicgKXsgdG9SZW1vdmUuZWFjaChmdW5jdGlvbihkLCBpKXsgZXhpdEZ1bmN0aW9uKGQzLnNlbGVjdCh0aGlzKSl9KSB9XG4gICAgICAgIGVsc2V7dG9SZW1vdmUucmVtb3ZlKCl9XG4gICAgICB9XG4gICAgICBtb3ZlICs9IChpbmRleCA9PSBjdXJyZW50U2VsZWN0aW9uLnNpemUoKS0xKSA/IDAgOiBsZXZlbFNwYWNlclxuICAgIH0pXG4gICAgcmV0dXJuIG1vdmVcbiAgfVxuICByZXR1cm4gcmVjdXJzaXZlbHlQb3NpdGlvblxufVxuIiwiaW1wb3J0IHttb2RpZnlIZXhpZGVjaW1hbENvbG9yTHVtaW5hbmNlfSBmcm9tICcuL2hlbHBlcnMnO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBjb2xvckZ1bmN0aW9uXG4gKiBAY29uc3RydWN0b3IgY29sb3JGdW5jdGlvblxuICogQG5hbWVzcGFjZSBjb2xvckZ1bmN0aW9uXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IGNvbG9yRnVuY3Rpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbG9yRnVuY3Rpb24oKSB7XG4gIHZhclxuICBkYXRhLFxuXG4gIC8qKlxuICAqIERlZmF1bHQgY29sb3JzIHRvIHVzZVxuICAqIEBwYXJhbSB7bnVtYmVyW119IFtjb2xvcnM9W1wiIzJjN2JiNlwiLCBcIiMwMGE2Y2FcIiwgXCIjMDBjY2JjXCIsIFwiIzkwZWI5ZFwiLCBcIiNmZmZmOGNcIiwgXCIjZjlkMDU3XCIsIFwiI2YyOWUyZVwiLCBcIiNlNzY4MThcIiwgXCIjZDcxOTFjXCJdXVxuICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjb2xvcnMgPSBbXCIjMmM3YmI2XCIsIFwiIzAwYTZjYVwiLCBcIiMwMGNjYmNcIiwgXCIjOTBlYjlkXCIsIFwiI2ZmZmY4Y1wiLCBcIiNmOWQwNTdcIiwgXCIjZjI5ZTJlXCIsIFwiI2U3NjgxOFwiLCBcIiNkNzE5MWNcIl0sXG4gIC8qKlxuICAqIEludGVycG9sYXRvciBmb3IgY29sb3JzXG4gICogQHBhcmFtIHtkMy5pbnRlcnBvbGF0aW9ufSBbaW50ZXJwb2xhdGlvbj1kMy5pbnRlcnBvbGF0ZVJnYl1cbiAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgaW50ZXJwb2xhdGlvbiA9IGQzLmludGVycG9sYXRlUmdiLFxuICAvKipcbiAgKiBGdW5jdGlvbiBmb3IgbW9kaWZ5aW5nIGNvbG9yIGx1bWluYW5jZVxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFttb2RpZnlPcGFjaXR5PW1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2VdXG4gICogQG1lbWJlcm9mIGNvbG9yRnVuY3Rpb24jXG4gICogQHByb3BlcnR5XG4gICovXG4gIG1vZGlmeU9wYWNpdHkgPSBtb2RpZnlIZXhpZGVjaW1hbENvbG9yTHVtaW5hbmNlLFxuICAvKipcbiAgKiBIb3cgdG8gbW9kaWZ5IGNvbG9yIGZvciBzdHJva2VcbiAgKiBAcGFyYW0ge251bWJlcn0gW3N0cm9rZU9wYWNpdHk9MF1cbiAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3Ryb2tlT3BhY2l0eSA9IDAsXG4gIC8qKlxuICAqIEhvdyB0byBtb2RpZnkgY29sb3IgZm9yIGZpbGxcbiAgKiBAcGFyYW0ge251bWJlcn0gW2ZpbGxPcGFjaXR5PTAuNF1cbiAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZmlsbE9wYWNpdHkgPSAwLjQsXG4gIC8qKlxuICAqIEhvdyB0byBkZXRlcm1pbmUgdGhlIGNvbG9yIHRvIHVzZVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbY29sb3JCeT0naW5kZXgnXVxuICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjb2xvckJ5ID0gJ2luZGV4JyxcbiAgLyoqXG4gICogU2V0cyB0aGUgc2NhbGUgZm9yIGludGVycG9sYXRpbmcgdGhlIGNvbG9yc1xuICAqIEBwYXJhbSB7bnVtYmVyW119IFtkYXRhRXh0ZW50PVswLCBjb2xvcnMubGVuZ3RoIC0gMV1dXG4gICogQG1lbWJlcm9mIGNvbG9yRnVuY3Rpb24jXG4gICogQHByb3BlcnR5XG4gICovXG4gIGRhdGFFeHRlbnQgPSBbMCwgY29sb3JzLmxlbmd0aCAtIDFdLFxuICAvKipcbiAgKiBFeHRyYWN0cyB0aGUgdmFsdWUgdG8gY29sb3IgYnlcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbdmFsdWVFeHRyYWN0b3I9ZnVuY3Rpb24oaywgdiwgaSkge3JldHVybiB2fV1cbiAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihrLCB2LCBpKSB7cmV0dXJuIHZ9LFxuXG4gIC8qKlxuICAqIEV4dHJhY3RzIHRoZSBjYXRlZ29yeSB0byBjb2xvciBieVxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtjYXRlZ29yeUV4dHJhY3Rvcj1mdW5jdGlvbihrLCB2LCBpKSB7cmV0dXJuIHYuY2F0ZWdvcnl9XVxuICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjYXRlZ29yeUV4dHJhY3RvciA9IGZ1bmN0aW9uKGssIHYsIGkpIHtyZXR1cm4gdi5jYXRlZ29yeX0sXG5cbiAgLyoqXG4gICogVGhlIGRpZmZlcmVudCB0eXBlIG9mIGNhdGVnb3JpZXMgb2Ygd2hpY2ggdG8gY29sb3IgYnlcbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbY2F0ZWdvcmllcz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGNvbG9yRnVuY3Rpb24jXG4gICogQHByb3BlcnR5XG4gICovXG4gIGNhdGVnb3JpZXMsXG5cbiAgLyoqXG4gICogU2NhbGUgZm9yIGludGVycG9sYXRpbmcgdGhlIGNvbG9yc1xuICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtzY2FsZT1kMy5zY2FsZUxpbmVhcigpXVxuICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKClcbiAgLmludGVycG9sYXRlKGludGVycG9sYXRpb24pLmRvbWFpbihkYXRhRXh0ZW50KS5yYW5nZShjb2xvcnMpLFxuICBoZWxwZXJTY2FsZSA9IGQzLnNjYWxlTGluZWFyKClcblxuXG5cbiAgLy8gdmFyIGggPSB4ID0+ICcjJyArIHgubWF0Y2goL1xcZCsvZykubWFwKHkgPSB6ID0+ICgoK3ogPCAxNik/JzAnOicnKSArICgreikudG9TdHJpbmcoMTYpKS5qb2luKCcnKTtcbiAgdmFyIGggPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIFwiI1wiICsgeC5tYXRjaCgvXFxkKy9nKS5tYXAoXG4gICAgICBmdW5jdGlvbih5LCBpKSB7XG4gICAgICAgIHJldHVybiAgKCgreSA8IDE2KT8nMCc6JycpICsgKCt5KS50b1N0cmluZygxNilcbiAgICAgIH0pLmpvaW4oJycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZGVmYXVsdCBjb2xvcnNcbiAgICogKHNlZSB7QGxpbmsgY29sb3JGdW5jdGlvbiNjb2xvcnN9KVxuICAgKiBAcGFyYW0ge251bWJlcltdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Y29sb3JGdW5jdGlvbiB8IG51bWJlcltdfVxuICAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvblxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGNvbG9yRnVuY3Rpb24uY29sb3JzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoXG4gICAgP1xuICAgICAgKFxuICAgICAgICBjb2xvcnMgPSBfLFxuICAgICAgICBzY2FsZS5yYW5nZShjb2xvcnMpLFxuICAgICAgICBjb2xvckZ1bmN0aW9uXG4gICAgICApXG4gICAgOiBjb2xvcnM7XG4gIH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGZ1bmN0aW9uIGZvciBpbnRlcnBvbGF0aW5nIHRoZSBjb2xvcnNcbiAgICogKHNlZSB7QGxpbmsgY29sb3JGdW5jdGlvbiNpbnRlcnBvbGF0aW9ufSlcbiAgICogQHBhcmFtIHtkMy5pbnRlcnBvbGF0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Y29sb3JGdW5jdGlvbiB8IGQzLmludGVycG9sYXRpb259XG4gICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgY29sb3JGdW5jdGlvbi5pbnRlcnBvbGF0aW9uID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoXG4gICAgP1xuICAgIChcbiAgICAgIGludGVycG9sYXRpb24gPSBfLFxuICAgICAgc2NhbGUuaW50ZXJwb2xhdGUoaW50ZXJwb2xhdGlvbikucmFuZ2UoY29sb3JzKSxcbiAgICAgIGNvbG9yRnVuY3Rpb25cbiAgICApXG4gICAgOiBpbnRlcnBvbGF0aW9uO1xuICB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB2YWx1ZXMgZm9yIHRoZSBzY2FsZSB3aGljaCB0cmFuc2Zvcm1zIHRoZSB2YWx1ZSB0byBhIGNvbG9yXG4gICAqIChzZWUge0BsaW5rIGNvbG9yRnVuY3Rpb24jZGF0YUV4dGVudH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtjb2xvckZ1bmN0aW9uIHwgbnVtYmVyW119XG4gICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoXG4gICAgPyAoXG4gICAgICAgIGRhdGFFeHRlbnQgPSBfLFxuICAgICAgICBzY2FsZS5kb21haW4oZGF0YUV4dGVudCkuaW50ZXJwb2xhdGUoc2NhbGUuaW50ZXJwb2xhdGUoKSksXG4gICAgICAgIGNvbG9yRnVuY3Rpb25cbiAgICAgIClcbiAgICA6IGRhdGFFeHRlbnQ7XG4gIH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHZ0aGUgc2NhbGUgd2hpY2ggdHJhbnNmb3JtcyB0aGUgdmFsdWUgdG8gYSBjb2xvclxuICAgKiAoc2VlIHtAbGluayBjb2xvckZ1bmN0aW9uI3NjYWxlfSlcbiAgICogQHBhcmFtIHtkMy5zY2FsZX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2NvbG9yRnVuY3Rpb24gfCBkMy5zY2FsZX1cbiAgICogQG1lbWJlcm9mIGNvbG9yRnVuY3Rpb25cbiAgICogQHByb3BlcnR5XG4gICAqL1xuICBjb2xvckZ1bmN0aW9uLnNjYWxlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoXG4gICAgPyAoXG4gICAgICAgIF8gPSBfLmRvbWFpbihzY2FsZS5kb21haW4oKSkuaW50ZXJwb2xhdGUoc2NhbGUuaW50ZXJwb2xhdGUoKSkucmFuZ2Uoc2NhbGUucmFuZ2UoKSksXG4gICAgICAgIHNjYWxlID0gXyxcbiAgICAgICAgY29sb3JGdW5jdGlvblxuICAgICAgKVxuICAgIDogc2NhbGU7XG4gIH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGZ1bmN0aW9uIGZvciBtb2RpZnkgb3BhY2l0eVxuICAgKiAoc2VlIHtAbGluayBjb2xvckZ1bmN0aW9uI21vZGlmeU9wYWNpdHl9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Y29sb3JGdW5jdGlvbiB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvblxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGNvbG9yRnVuY3Rpb24ubW9kaWZ5T3BhY2l0eSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobW9kaWZ5T3BhY2l0eSA9IF8sIGNvbG9yRnVuY3Rpb24pIDogbW9kaWZ5T3BhY2l0eTsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgdmFsdWUgdG8gbW9kaWZ5IHRoZSBjb2xvciBmb3IgdGhlIHN0cm9rZSB2aWEge0BsaW5rIGNvbG9yRnVuY3Rpb24jbW9kaWZ5T3BhY2l0eX1cbiAgICogKHNlZSB7QGxpbmsgY29sb3JGdW5jdGlvbiNzdHJva2VPcGFjaXR5fSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtjb2xvckZ1bmN0aW9uIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvblxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGNvbG9yRnVuY3Rpb24uc3Ryb2tlT3BhY2l0eSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3Ryb2tlT3BhY2l0eSA9IF8sIGNvbG9yRnVuY3Rpb24pIDogc3Ryb2tlT3BhY2l0eTsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgdmFsdWUgdG8gbW9kaWZ5IHRoZSBjb2xvciBmb3IgdGhlIHN0cm9rZSB2aWEge0BsaW5rIGNvbG9yRnVuY3Rpb24jZmlsbE9wYWNpdHl9XG4gICAqIChzZWUge0BsaW5rIGNvbG9yRnVuY3Rpb24jZmlsbE9wYWNpdHl9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2NvbG9yRnVuY3Rpb24gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgY29sb3JGdW5jdGlvbi5maWxsT3BhY2l0eSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZmlsbE9wYWNpdHkgPSBfLCBjb2xvckZ1bmN0aW9uKSA6IGZpbGxPcGFjaXR5OyB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB2YWx1ZSB0byBjb2xvckJ5XG4gICAqIChzZWUge0BsaW5rIGNvbG9yRnVuY3Rpb24jY29sb3JCeX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Y29sb3JGdW5jdGlvbiB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGNvbG9yRnVuY3Rpb25cbiAgICogQHByb3BlcnR5XG4gICAqL1xuICBjb2xvckZ1bmN0aW9uLmNvbG9yQnkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvbG9yQnkgPSBfLCBjb2xvckZ1bmN0aW9uKSA6IGNvbG9yQnk7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHZhbHVlIG9mIHZhbHVlRXh0cmFjdG9yXG4gICAqIChzZWUge0BsaW5rIGNvbG9yRnVuY3Rpb24jdmFsdWVFeHRyYWN0b3J9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Y29sb3JGdW5jdGlvbiB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvblxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGNvbG9yRnVuY3Rpb24udmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZhbHVlRXh0cmFjdG9yID0gXywgY29sb3JGdW5jdGlvbikgOiB2YWx1ZUV4dHJhY3RvcjsgfTtcblxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB2YWx1ZSBvZiBjYXRlZ29yeUV4dHJhY3RvclxuICAgKiAoc2VlIHtAbGluayBjb2xvckZ1bmN0aW9uI2NhdGVnb3J5RXh0cmFjdG9yfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2NvbG9yRnVuY3Rpb24gfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGNvbG9yRnVuY3Rpb25cbiAgICogQHByb3BlcnR5XG4gICAqL1xuICBjb2xvckZ1bmN0aW9uLmNhdGVnb3J5RXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjYXRlZ29yeUV4dHJhY3RvciA9IF8sIGNvbG9yRnVuY3Rpb24pIDogY2F0ZWdvcnlFeHRyYWN0b3I7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHZhbHVlIG9mIGNhdGVnb3J5RXh0cmFjdG9yXG4gICAqIChzZWUge0BsaW5rIGNvbG9yRnVuY3Rpb24jY2F0ZWdvcmllc30pXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtjb2xvckZ1bmN0aW9uIHwgc3RyaW5nW119XG4gICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgY29sb3JGdW5jdGlvbi5jYXRlZ29yaWVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjYXRlZ29yaWVzID0gXywgY29sb3JGdW5jdGlvbikgOiBjYXRlZ29yaWVzOyB9O1xuXG5cbiAgZnVuY3Rpb24gY29sb3JGdW5jdGlvbihrZXksIHZhbHVlLCBpbmRleCwgdHlwZSwgaG92ZXJRKSB7XG4gICAgdmFyIGMsXG4gICAgb3BhYyA9IHR5cGUgPT0gXCJmaWxsXCIgPyBmaWxsT3BhY2l0eSA6IHN0cm9rZU9wYWNpdHk7XG5cblxuICAgIHVwZGF0ZVNjYWxlKClcblxuICAgIGlmIChjb2xvckJ5ID09IFwiaW5kZXhcIikge1xuICAgICAgYyA9ICh0eXBlICE9IHVuZGVmaW5lZCkgPyBtb2RpZnlPcGFjaXR5KGgoc2NhbGUoaW5kZXgpKSwgb3BhYykgOiBoKHNjYWxlKGluZGV4KSlcbiAgICB9XG5cbiAgICBlbHNlIGlmIChjb2xvckJ5ID09ICd2YWx1ZScpIHtcbiAgICAgIHZhciB2ID0gdmFsdWVFeHRyYWN0b3Ioa2V5LCB2YWx1ZSwgaW5kZXgpO1xuICAgICAgLy8gaWYgKHYgPCBkYXRhRXh0ZW50WzBdKSB7ZGF0YUV4dGVudFswXSA9IHY7IHVwZGF0ZVNjYWxlKCl9XG4gICAgICAvLyBpZiAodiA+IGRhdGFFeHRlbnRbMV0pIHtkYXRhRXh0ZW50WzFdID0gdjsgdXBkYXRlU2NhbGUoKX1cblxuICAgICAgYyA9ICh0eXBlICE9IHVuZGVmaW5lZCkgPyBtb2RpZnlPcGFjaXR5KGgoc2NhbGUodikpLCBvcGFjKSA6IGgoc2NhbGUodikpXG4gICAgfVxuXG4gICAgZWxzZSBpZiAoY29sb3JCeSA9PSAnY2F0ZWdvcnknICl7XG4gICAgICB2YXIgY2F0ID0gY2F0ZWdvcnlFeHRyYWN0b3Ioa2V5LCB2YWx1ZSwgaW5kZXgpO1xuICAgICAgdmFyIHYgPSBjYXRlZ29yaWVzLmluZGV4T2YoY2F0KVxuICAgICAgYyA9ICh0eXBlICE9IHVuZGVmaW5lZCkgPyBtb2RpZnlPcGFjaXR5KGgoc2NhbGUodikpLCBvcGFjKSA6IGgoc2NhbGUodikpXG5cbiAgICB9XG5cbiAgICBlbHNlIHtcbiAgICAgIGMgPSAodHlwZSAhPSB1bmRlZmluZWQpID8gbW9kaWZ5T3BhY2l0eShoKHNjYWxlKGluZGV4KSksIG9wYWMpIDogaChzY2FsZShpbmRleCkpXG4gICAgfVxuXG4gICAgcmV0dXJuIGNcbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZVNjYWxlKCl7XG5cblxuICAgIGhlbHBlclNjYWxlLmRvbWFpbihbMCwgY29sb3JzLmxlbmd0aF0pXG4gICAgaWYgKGNvbG9yQnkgPT0gJ2NhdGVnb3J5JyAmJiBjYXRlZ29yaWVzICE9IHVuZGVmaW5lZCkgeyBoZWxwZXJTY2FsZS5yYW5nZShbMCwgY2F0ZWdvcmllcy5sZW5ndGhdKSB9XG4gICAgZWxzZSB7IGhlbHBlclNjYWxlLnJhbmdlKGRhdGFFeHRlbnQpIH1cblxuXG4gICAgdmFyIGEgPSBBcnJheShjb2xvcnMubGVuZ3RoKS5maWxsKDApLm1hcChmdW5jdGlvbihkLCBpKXsgcmV0dXJuIGhlbHBlclNjYWxlKGkpIH0pXG4gICAgc2NhbGUuZG9tYWluKGEpXG4gIH1cblxuICByZXR1cm4gY29sb3JGdW5jdGlvblxufVxuIiwiaW1wb3J0IHtzYWZlU2VsZWN0LCByb3VuZH0gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7bG9nLCB3YXJuLCBpbmZvLCBlcnJvciwgY29uc29sZUdyb3VwLCBjb25zb2xlR3JvdXBFbmR9IGZyb20gJy4vdXRpbHMnO1xuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUT09MVElQICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbi8qKlxuICogUHJvZHVjZXMgYSBmdW5jdGlvbiBmb3IgaGFuZGxpbmcgdGhlIHRvb2x0aXBcbiAqXG4gKiB7QGxpbmsgaHR0cHM6Ly9zdW1uZXVyb24uZ2l0bGFiLmlvL2Qzc20vZGVtb3MvdG9vbHRpcC1kZXNpZ24vaW5kZXguaHRtbCBEZW1vfVxuICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IHNlbGVjdGlvblxuICogQHJldHVybnMge3Rvb2x0aXB9XG4gKiBAbmFtZXNwYWNlIHRvb2x0aXBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvb2x0aXAoIHNlbGVjdGlvbiApIHtcblxuICB2YXJcbiAga2V5cyxcbiAgdmFsdWVzLFxuICBoZWFkZXIsXG4gIGRhdGEsXG4gIHNlbGVjdGlvblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUga2V5cyB0byBiZSBkaXNwbGF5ZWQgaW4gdGhlIHRvb2x0aXAuXG4gICAqIElmIG5vdCBzZXQsIHVzZXMgZDMua2V5cyhkYXRhW2tleV0pXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt0b29sdGlwIHwgc3RyaW5nW119XG4gICAqIEBtZW1iZXJvZiB0b29sdGlwXG4gICAqL1xuICB0b29sdGlwLmtleXMgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChrZXlzID0gXywgdG9vbHRpcCkgOiBrZXlzfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB2YWx1ZXMgdG8gYmUgZGlzcGxheWVkIG5leHQgdG8gdGhlIGtleXMuXG4gICAqIElmIG5vdCBzZXQsIHVzZXMgZGF0YVtrZXldW2tleXNbaV1dLlxuICAgKiBJZiBhIGZ1bmN0aW9uLCBnZXRzIHBhc3NlZCBjdXJyZW50RGF0YSAoZGF0YVtrZXldKSBhbmQga2V5c1tpXS5cbiAgICogQHBhcmFtIHsqW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt0b29sdGlwIHwgKltdfVxuICAgKiBAbWVtYmVyb2YgdG9vbHRpcFxuICAgKi9cbiAgdG9vbHRpcC52YWx1ZXMgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZXMgPSBfLCB0b29sdGlwKSA6IHZhbHVlc307XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgaGVhZGVyIHRvIGJlIGRpc3BsYXllZCBpbiB0aGUgdG9vbHRpcC5cbiAgICogSWYgbm90IHNldCwgdXNlcyBrZXlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt0b29sdGlwIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgdG9vbHRpcFxuICAgKi9cbiAgdG9vbHRpcC5oZWFkZXIgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChoZWFkZXIgPSBfLCB0b29sdGlwKSA6IGhlYWRlcn07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgZGF0YSAob3ZlciB0aGUgc2VsZWN0aW9uKSB0byBiZSB1c2VkIGZvciB0aGUgdG9vbHRpcFxuICAgKiBAcGFyYW0ge09iamVjdH0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Rvb2x0aXAgfCBPYmplY3R9XG4gICAqIEBtZW1iZXJvZiB0b29sdGlwXG4gICAqL1xuICB0b29sdGlwLmRhdGEgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkYXRhID0gXywgdG9vbHRpcCkgOiBkYXRhfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzZWxlY3Rpb24gZm9yIHRoZSB0b29sdGlwIHRvIGJlIGFwcGxpZWQgb25cbiAgICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt0b29sdGlwIHwgZDMuc2VsZWN0aW9ufVxuICAgKiBAbWVtYmVyb2YgdG9vbHRpcFxuICAgKi9cbiAgdG9vbHRpcC5zZWxlY3Rpb24gPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZWxlY3Rpb24gPSBfLCB0b29sdGlwKSA6IHNlbGVjdGlvbn07XG5cbiAgLyoqXG4gICAqIEJpbmQsIHZpYSBzZWxlY3Rpb24ub24oKSwgdGhlIG1vdXNlbW92ZSBhbmQgbW91c2VvdXQgZXZlbnRzXG4gICAqIEByZXR1cm5zIHVuZGVmaW5lZFxuICAgKi9cbiAgZnVuY3Rpb24gdG9vbHRpcCggKSB7XG4gICAgc2VsZWN0aW9uLm9uKCdtb3VzZW92ZXInLCBtb3VzZW1vdmUpXG4gICAgc2VsZWN0aW9uLm9uKCdtb3VzZW1vdmUnLCBtb3VzZW1vdmUpXG4gICAgc2VsZWN0aW9uLm9uKCdtb3VzZW91dCcsIGZ1bmN0aW9uKCl7IGQzLnNlbGVjdEFsbChcIi5kM3NtLXRvb2x0aXBcIikucmVtb3ZlKCl9KVxuICB9XG5cblxuICAvKipcbiAgICogUHJvZHVjZXMgdGhlIHRvb2x0aXAgb24gbW91c2Vtb3ZlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgb2YgdGhlIG9iamVjdCB0YXJnZXRlZCBieSB0aGUgbW91c2Vtb3ZlXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpIChpbmRleCkgb2YgdGhlIG9iamVjdCB0YXJnZXRlZCBieSBtb3VzZW1vdmVcbiAgICogQG1lbWJlcm9mIHRvb2x0aXBcbiAgICogQHByaXZhdGVcbiAgICovXG4gIGZ1bmN0aW9uIG1vdXNlbW92ZShrZXksIGkpIHtcbiAgICBjb25zb2xlR3JvdXAoJ2Qzc20tdG9vbHRpcCcpXG4gICAgdmFyIGN1cnJlbnREYXRhID0gZGF0YVtrZXldXG5cbiAgICB2YXIgW3gsIHldID0gZDMubW91c2UoZDMuc2VsZWN0KFwiaHRtbFwiKS5ub2RlKCkpXG4gICAgbG9nKCd0b29sdGlwJywgJ21vdXNlbW92ZSBkZXRlY3RlZCcse2tleToga2V5LCBpbmRleDogaSwgeDp4LCB5Onl9KVxuICAgIGxvZygndG9vbHRpcCcsICdjdXJyZW50IGRhdGEnLCBjdXJyZW50RGF0YSlcblxuXG5cbiAgICB2YXIgZGl2ID0gc2FmZVNlbGVjdChkMy5zZWxlY3QoJ2h0bWwnKSwgJ3Rvb2x0aXAnLCAnZDNzbS10b29sdGlwJylcbiAgICAuY2xhc3NlZCgnY2FyZCcsIHRydWUpXG4gICAgLnN0eWxlKCdtYXgtd2lkdGgnLCAnMzAwcHgnKVxuICAgIC5zdHlsZSgnYmFja2dyb3VuZC1jb2xvcicsIFwiIzIxMjUyOVwiKVxuICAgIC5zdHlsZSgnY29sb3InLCAnd2hpdGUnKVxuXG5cblxuICAgIHZhciBjYXJkQm9keSA9IHNhZmVTZWxlY3QoZGl2LCAnZGl2JywgJ2NhcmQtYm9keScpXG4gICAgdmFyIGNhcmRUaXRsZSA9IHNhZmVTZWxlY3QoY2FyZEJvZHksICdoNScsICdjYXJkLXRpdGxlJylcbiAgICAudGV4dChoZWFkZXIgPT0gdW5kZWZpbmVkID8ga2V5IDogdHlwZW9mIGhlYWRlciA9PSAnZnVuY3Rpb24nID8gaGVhZGVyKGtleSwgY3VycmVudERhdGEsIGkpIDogaGVhZGVyKVxuICAgIC5zdHlsZSgnY29sb3InLCAnY3lhbicpXG5cblxuICAgIHZhciB0YWJsZSA9IHNhZmVTZWxlY3QoY2FyZEJvZHksICd0YWJsZScsICd0YWJsZScpLmNsYXNzZWQoJ3RhYmxlLWRhcmsnLCB0cnVlKVxuICAgIHZhciB0Qm9keSA9IHNhZmVTZWxlY3QodGFibGUsICd0Ym9keScpXG5cbiAgICB0Qm9keSA9IHRCb2R5LnNlbGVjdEFsbCgndHInKVxuICAgIHRCb2R5PSB0Qm9keS5kYXRhKGtleXMgPT0gdW5kZWZpbmVkID8gZDMua2V5cyhjdXJyZW50RGF0YSk6IGtleXMpXG4gICAgdEJvZHkuZXhpdCgpLnJlbW92ZSgpXG5cblxuICAgIHZhciB0ciA9IHRCb2R5LmVudGVyKCkuYXBwZW5kKCd0cicpLnN0eWxlKCdtYXgtd2lkdGgnLCAnMzAwcHgnKVxuICAgIHRyLmFwcGVuZCgndGQnKS5hdHRyKCdjbGFzcycsIGZ1bmN0aW9uKGQsIGkpe3JldHVybiAndG9vbHRpcC1rZXknfSlcbiAgICB0ci5hcHBlbmQoJ3RkJykuYXR0cignY2xhc3MnLCAgZnVuY3Rpb24oZCwgaSwgail7cmV0dXJuICd0b29sdGlwLXZhbHVlJ30pXG4gICAgLmF0dHIoJ3Rvb2x0aXAtcm93LWluZGV4JywgZnVuY3Rpb24oZCwgaSl7cmV0dXJuIGl9KVxuXG4gICAgLy8gdEJvZHkgPSB0Qm9keS5tZXJnZSh0cilcbiAgICBjb25zb2xlR3JvdXAoJ3Rvb2x0aXAtcm93cycpXG4gICAgdEJvZHkuc2VsZWN0QWxsKCcudG9vbHRpcC1rZXknKS50ZXh0KGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkfSlcbiAgICB0Qm9keS5zZWxlY3RBbGwoJ3RyIC50b29sdGlwLXZhbHVlJylcbiAgICAudGV4dChmdW5jdGlvbihkLCBpKXtcbiAgICAgIGxvZygndG9vbHRpcCcsICd0cnlpbmcgdG8gc2V0IHZhbHVlJywge3Jvd0tleTogZCwgcm93SW5kZXg6IGl9KVxuICAgICAgdmFyIGkgPSBkMy5zZWxlY3QodGhpcykuYXR0cigndG9vbHRpcC1yb3ctaW5kZXgnKVxuICAgICAgdmFyIHYgPSBjdXJyZW50RGF0YVtkXTtcblxuXG4gICAgICBpZiAodmFsdWVzICE9IHVuZGVmaW5lZCkge3YgPSB2YWx1ZXNbaV07IGlmKHR5cGVvZiB2ID09IFwiZnVuY3Rpb25cIikge3YgPSB2KGN1cnJlbnREYXRhLCBkKX19XG4gICAgICByZXR1cm4gIHR5cGVvZiB2ID09ICdudW1iZXInID8gcm91bmQodiwgNSkgOiB2XG4gICAgfSlcbiAgICBjb25zb2xlR3JvdXBFbmQoKVxuICAgIGNvbnNvbGVHcm91cEVuZCgpXG5cbiAgICB4ICs9IDE1XG4gICAgLy8geCArPSAxNVxuICAgIHZhciBiYm94ID0gZGl2Lm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVxuICAgIGlmICh4ICsgYmJveC53aWR0aCA+IHdpbmRvdy5pbm5lcldpZHRoIC0gd2luZG93LnNjcm9sbFgpIHsgeCA9IGQzLmV2ZW50LnBhZ2VYIC0gYmJveC53aWR0aCAtIDE1IH1cbiAgICBpZiAoeSArIGJib3guaGVpZ2h0ID4gd2luZG93LmlubmVySGVpZ2h0ICAtIHdpbmRvdy5zY3JvbGxZKSB7IHkgPSBkMy5ldmVudC5wYWdlWSAtIGJib3guaGVpZ2h0IC0gMTUgfVxuICAgIGRpdi5zdHlsZSgncG9zaXRpb24nKSA9PSBcInJlbGF0aXZlXCJcbiAgICA/IGRpdi5zdHlsZSgncG9zaXRpb24nLCAnYWJzb2x1dGUnKS5zdHlsZSgnbGVmdCcsIHgrJ3B4Jykuc3R5bGUoJ3RvcCcsIHkrJ3B4JylcbiAgICA6IGRpdi5zdHlsZSgnbGVmdCcsIHgrJ3B4Jykuc3R5bGUoJ3RvcCcsIHkrJ3B4JylcbiAgICAvLyAudHJhbnNpdGlvbigpLmR1cmF0aW9uKDIwMCkuZWFzZShkMy5lYXNlU2luKVxuXG4gICAgLy8gaWYgKGJib3gueCArIGJib3gud2lkdGggPiB3aW5kb3cuaW5uZXJXaWR0aCkge1xuICAgIC8vICAgZGl2LnN0eWxlKCdsZWZ0JywgKGQzLmV2ZW50LnBhZ2VYLTE1LWJib3gud2lkdGgpKydweCcpXG4gICAgLy8gfVxuICAgIC8vIGlmIChiYm94LnkgKyBiYm94LmhlaWdodCA+IHdpbmRvdy5pbm5lckhlaWdodCkge1xuICAgIC8vICAgZGl2LnN0eWxlKCd0b3AnLCAoZDMuZXZlbnQucGFnZVktMTUtYmJveC5oZWlnaHQpKydweCcpXG4gICAgLy8gfVxuXG4gICAgZGl2LmF0dHIoJ3otaW5kZXgnLCAxMDAwMClcbiAgfVxuXG4gIHJldHVybiB0b29sdGlwXG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuXG5leHBvcnQgZnVuY3Rpb24gc2VsZWN0RmlsdGVyKHNlbGVjdGlvbikge1xuXG4gIHZhclxuICBkYXRhLFxuICBuYW1lc3BhY2UgPSAnZDNzbS1zZWxlY3QtZmlsdGVyJyxcbiAgc2VsZWN0aW9uTmFtZSA9ICdTZWxlY3Qgb3B0aW9uczonLFxuICBkZWZhdWx0VmFsdWUgPSB1bmRlZmluZWRcblxuXG5cblxuICB2YXIgbGFzdFZhbHVlID0gdW5kZWZpbmVkXG5cbiAgc2VsZWN0RmlsdGVyLmRhdGEgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRhdGEgPSBfLCBzZWxlY3RGaWx0ZXIpIDogZGF0YX1cbiAgc2VsZWN0RmlsdGVyLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgc2VsZWN0RmlsdGVyKSA6IG5hbWVzcGFjZX1cbiAgc2VsZWN0RmlsdGVyLnNlbGVjdGlvbk5hbWUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNlbGVjdGlvbk5hbWUgPSBfLCBzZWxlY3RGaWx0ZXIpIDogc2VsZWN0aW9uTmFtZX1cbiAgc2VsZWN0RmlsdGVyLmRlZmF1bHRWYWx1ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGVmYXVsdFZhbHVlID0gXywgc2VsZWN0RmlsdGVyKSA6IGRlZmF1bHRWYWx1ZX1cbiAgc2VsZWN0RmlsdGVyLmN1cnJlbnRPcHRpb24gPSBjdXJyZW50T3B0aW9uXG5cbiAgZnVuY3Rpb24gc2VsZWN0RmlsdGVyKCkge1xuICAgIHZhclxuICAgIGNvbnRhaW5lciA9IHNhZmVTZWxlY3Qoc2VsZWN0aW9uLCAnZGl2JywgJ2lucHV0LWdyb3VwJykuY2xhc3NlZChoeXBlbmF0ZShuYW1lc3BhY2UsJ2NvbnRhaW5lcicpLHRydWUpLFxuXG4gICAgICBzZWxlY3RQcmVwZW5kID0gc2FmZVNlbGVjdChjb250YWluZXIsICdkaXYnLCAnc2VsZWN0LXByZXBlbmQnKS5jbGFzc2VkKCdpbnB1dC1ncm91cC1wcmVwZW5kJywgdHJ1ZSksXG4gICAgICAgIHNlbGVjdFByZXBlbmRTcGFuID0gc2FmZVNlbGVjdChzZWxlY3RQcmVwZW5kLCAnc3BhbicsICdpbnB1dC1ncm91cC10ZXh0JykudGV4dChzZWxlY3Rpb25OYW1lKSxcblxuICAgICAgc2VsZWN0ID0gc2FmZVNlbGVjdChjb250YWluZXIsICdzZWxlY3QnLCAnY3VzdG9tLXNlbGVjdCcpLmNsYXNzZWQoaHlwZW5hdGUobmFtZXNwYWNlLCdzZWxlY3QnKSx0cnVlKSxcblxuICAgICAgc2VsZWN0QXBwZW5kID0gc2FmZVNlbGVjdChjb250YWluZXIsICdkaXYnLCAnc2VsZWN0LWFwcGVuZCcpLmNsYXNzZWQoJ2lucHV0LWdyb3VwLXByZXBlbmQnLCB0cnVlKSxcbiAgICAgICAgc2VsZWN0QXBwZW5kQnV0dG9uID0gc2FmZVNlbGVjdChzZWxlY3RBcHBlbmQsICdhJywgJ2ZpbHRlci1idXR0b24nKS5jbGFzc2VkKCdidG4gYnRuLW91dGxpbmUtc2Vjb25kYXJ5JywgdHJ1ZSksXG4gICAgICAgICAgZmlsdGVyQnV0dG9uSWNvbiA9IHNhZmVTZWxlY3Qoc2VsZWN0QXBwZW5kQnV0dG9uLCAnaScsICdmYSBmYS1maWx0ZXInKSxcblxuICAgICAgaW5wdXRHcm91cCA9IHNhZmVTZWxlY3QoY29udGFpbmVyLCAnZGl2JywgJ2ZpbHRlci1pbnB1dC1ncm91cCcpLmNsYXNzZWQoJ2lucHV0LWdyb3VwJyx0cnVlKS5jbGFzc2VkKCdkLW5vbmUnLCB0cnVlKSxcbiAgICAgICAgaW5wdXRQcmVwZW5kID0gc2FmZVNlbGVjdChpbnB1dEdyb3VwLCAnZGl2JywgJ2lucHV0LWdyb3VwLXByZXBlbmQnKSxcbiAgICAgICAgICBpbnB1dFByZXBlbmRTcGFuID0gc2FmZVNlbGVjdChpbnB1dFByZXBlbmQsICdzcGFuJywgJ2lucHV0LWdyb3VwLXRleHQnKS5jbGFzc2VkKCdzZWFyY2gtYnV0dG9uJywgdHJ1ZSksXG4gICAgICAgICAgICBpbnB1dFByZXBlbmRTcGFuSWNvbiA9IHNhZmVTZWxlY3QoaW5wdXRQcmVwZW5kU3BhbiwnaScsJ2ZhIGZhLXNlYXJjaCcpLFxuXG4gICAgICAgIGlucHV0ID0gc2FmZVNlbGVjdChpbnB1dEdyb3VwLCAnaW5wdXQnLCAnZm9ybS1jb250cm9sJykuYXR0cigncGxhY2Vob2xkZXInLCAnYWxsJykuYXR0cigndHlwZScsICd0ZXh0JyksXG4gICAgICAgIGlucHV0QXBwZW5kID0gc2FmZVNlbGVjdChpbnB1dEdyb3VwLCAnZGl2JywgJ2lucHV0LWdyb3VwLWFwcGVuZCcpLFxuICAgICAgICAgIGlucHV0QXBwZW5kQnV0dG9uID0gc2FmZVNlbGVjdChpbnB1dEFwcGVuZCwgJ2EnLCAnY2xvc2UtYnV0dG9uJykuY2xhc3NlZCgnYnRuIGJ0bi1vdXRsaW5lLXNlY29uZGFyeScsIHRydWUpLFxuICAgICAgICAgICAgaW5wdXRBcHBlbmRCdXR0b25JY29uID0gc2FmZVNlbGVjdChpbnB1dEFwcGVuZEJ1dHRvbiwgJ2knLCAnZmEgZmEtY2xvc2UnKVxuXG5cbiAgICB2YXIga2V5cyA9IGQzLmtleXMoZGF0YSksXG4gICAgb3B0aW9ucyA9IHNlbGVjdC5zZWxlY3RBbGwoJ29wdGlvbicpXG5cbiAgICBvcHRpb25zID0gb3B0aW9ucy5kYXRhKGQzLmtleXMoZGF0YSkpXG4gICAgb3B0aW9ucyA9IG9wdGlvbnMubWVyZ2Uob3B0aW9ucy5lbnRlcigpLmFwcGVuZCgnb3B0aW9uJykpXG4gICAgLmF0dHIoJ3ZhbHVlJywgZnVuY3Rpb24oZCwgaSl7cmV0dXJuIGR9KVxuICAgIC50ZXh0KGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkfSlcblxuICAgIHZhclxuICAgIGZpbHRlckJ1dHRvbiA9IHNlbGVjdEFwcGVuZEJ1dHRvbixcbiAgICBjbG9zZUJ1dHRvbiA9IGlucHV0QXBwZW5kQnV0dG9uXG5cbiAgICBmaWx0ZXJCdXR0b24ub24oJ2NsaWNrJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICB2YXIgY3VycmVudFN0eWxlID0gaW5wdXRHcm91cC5jbGFzc2VkKCdkLW5vbmUnKVxuICAgICAgaW5wdXRHcm91cC5jbGFzc2VkKCdkLW5vbmUnLCAhY3VycmVudFN0eWxlKVxuICAgIH0pXG5cbiAgICBjbG9zZUJ1dHRvbi5vbignY2xpY2snLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgIGlucHV0LnByb3BlcnR5KCd2YWx1ZScsICcnKS5kaXNwYXRjaCgnaW5wdXQnKVxuICAgIH0pXG5cbiAgICBpbnB1dC5vbignaW5wdXQnLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhclxuICAgICAgdmFsID0gaW5wdXQucHJvcGVydHkoJ3ZhbHVlJyksXG4gICAgICByZWcgPSBuZXcgUmVnRXhwKHZhbCwgJ2dpJyksXG4gICAgICB1c2VcblxuICAgICAgaWYgKHZhbCA9PSAnJykge3VzZSA9IGtleXN9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdXNlID0gW11cbiAgICAgICAgZDMua2V5cyhkYXRhKS5tYXAoZnVuY3Rpb24ob3B0aW9uLCBqKXtcbiAgICAgICAgICB2YXIgbWF0Y2ggPSBvcHRpb24ubWF0Y2gocmVnKVxuICAgICAgICAgIGlmIChtYXRjaCA9PSBudWxsIHx8IG1hdGNoLmpvaW4oJycpID09ICcnKSB7fVxuICAgICAgICAgIGVsc2UgeyB1c2UucHVzaChvcHRpb24pIH1cbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgb3B0aW9ucyA9IHNlbGVjdC5zZWxlY3RBbGwoJ29wdGlvbicpXG4gICAgICBvcHRpb25zID0gb3B0aW9ucy5kYXRhKHVzZSlcbiAgICAgIG9wdGlvbnMuZXhpdCgpLnJlbW92ZSgpXG4gICAgICBvcHRpb25zID0gb3B0aW9ucy5tZXJnZShvcHRpb25zLmVudGVyKCkuYXBwZW5kKCdvcHRpb24nKSlcbiAgICAgIC5hdHRyKCd2YWx1ZScsIGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkfSlcbiAgICAgIC50ZXh0KGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkfSlcblxuICAgICAgdmFyIGN1cnJlbnQgPSBjdXJyZW50T3B0aW9uKClcbiAgICAgIGlmIChsYXN0VmFsdWUgIT0gY3VycmVudCkge1xuICAgICAgICBsYXN0VmFsdWUgPSBjdXJyZW50XG4gICAgICAgIHNlbGVjdC5kaXNwYXRjaCgnY2hhbmdlJylcbiAgICAgIH1cbiAgICB9KVxuXG5cbiAgfVxuXG4gIGZ1bmN0aW9uIGN1cnJlbnRPcHRpb24oKSB7XG4gICAgdmFyIHZhbCA9IHNlbGVjdGlvbi5zZWxlY3QoXCJzZWxlY3RcIikucHJvcGVydHkoJ3ZhbHVlJylcbiAgICByZXR1cm4gdmFsID09IHVuZGVmaW5lZCB8fCB2YWwgPT0gJydcbiAgICA/IGRlZmF1bHRWYWx1ZSA9PSB1bmRlZmluZWRcbiAgICAgID8gZDMua2V5cyhkYXRhKVswXVxuICAgICAgOiBkZWZhdWx0VmFsdWVcbiAgICA6IHZhbFxuICB9XG5cbiAgcmV0dXJuIHNlbGVjdEZpbHRlclxufVxuIiwiaW1wb3J0IHtoeXBlbmF0ZSwgc2FmZVNlbGVjdCwgZXVjbGlkZWFuRGlzdGFuY2V9IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQge3NldHVwQ29udGFpbmVyLCBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0LCBjYWxjdWxhdGVXaWR0aE9mU3BhY2VyfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7dW5pcXVlLCBoYXNRLCBmbGF0dGVuLCB3aGljaEJpbn0gZnJvbSAnLi9hcnJheS1mdW5jdGlvbnMnO1xuaW1wb3J0IHtncm91cGluZ1NwYWNlcn0gZnJvbSAnLi9ncm91cGluZy1zcGFjZXInO1xuaW1wb3J0IHtjb2xvckZ1bmN0aW9uIGFzIENGfSBmcm9tICcuL2NvbG9yLWZ1bmN0aW9uJztcbmltcG9ydCB7dG9vbHRpcCBhcyBUVGlwfSBmcm9tICcuL3Rvb2x0aXAnO1xuaW1wb3J0ICcuL2QzLXByb3RvdHlwZXMnO1xuXG5mdW5jdGlvbiBnZXRUcmFuc2xhdGlvbihzZWxlY3Rpb24pe1xuICB2YXIgdHJhbnNmb3JtID0gc2VsZWN0aW9uLmF0dHIoJ3RyYW5zZm9ybScpXG4gIHZhciBbanVuaywgeHldID10cmFuc2Zvcm0uc3BsaXQoJ3RyYW5zbGF0ZSgnKVxuICB2YXIgW3gsIHldID0geHkuc3BsaXQoJywnKVxuICB5LCBqdW5rID0geS5zcGxpdCgnKScpXG4gIHJldHVybiBbcGFyc2VGbG9hdCh4KSwgcGFyc2VGbG9hdCh5KV1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxhc3NvKCBzZWxlY3Rpb24gKSB7XG4gIHZhclxuICBzdmcsIC8vIHN2ZyB0aGF0IGlzIHRhcmdldCBvZiBldmVudHNcbiAgb2JqZWN0Q29udGFpbmVyLCAvLyBjb250YWluZXIgd2hpY2ggaG91c2VzIG9iamVjdHMgd2UgYXJlIHNlbGVjdGluZyAoYWxsb3dzIGZvciB0cmFuc2Zvcm0gdG8gYmUgYXBwbGllZCB0byBsYXNzbylcbiAgb2JqZWN0Q2xhc3MsIC8vIGNsYXNzIG9mIG9iamVjdCB3ZSBhcmUgc2VsZWN0aW5nXG4gIG5hbWVzcGFjZT1cImQzc20tbGFzc29cIixcbiAgY2hhcnRDb250YWluZXIsXG4gIGNoYXJ0T2Zmc2V0LFxuICBvYmplY3RzT2Zmc2V0LFxuICBldmVudENhdGNoZXIsXG5cbiAgeFNjYWxlLCAvLyBvcHRpb25hbCBzY2FsZSBmb3IgdGhlIGxhc3NvIGN1cnJlbnRQb2ludHNcbiAgeVNjYWxlLCAvLyBvcHRpb25hbCBzY2FsZSBmb3IgdGhlIGxhc3NvIGN1cnJlbnRQb2ludHNcblxuICBhY3RpdmVRID0gZmFsc2UsIC8vIHdoZXRoZXIgb3Igbm90IGxhc3NvIGlzIGFjdGl2ZVxuXG4gIGN1cnJlbnRQb2ludHM9W10sIC8vIG1vdXNlIHBvaW50cyBmb3IgY3VycmVudCBsYXNzb1xuICBhbGxQb2ludHM9W10sIC8vIGxpc3Qgb2YgbGlzdHMgZm9yIGFsbCBwb2ludHMgb2YgbGFzc29zXG5cbiAgbGluZSA9IGQzLmxpbmUoKVxuICAueChmdW5jdGlvbihkLCBpKXtcbiAgICB2YXIgeFxuICAgIGlmICh4U2NhbGUgIT0gdW5kZWZpbmVkKSB7IHggPSB4U2NhbGUoZFswXSkgfVxuICAgIGVsc2Uge3ggPSBkWzBdfVxuICAgIHJldHVybiB4IC8vLSBjaGFydE9mZnNldFswXS8vIC0gb2JqZWN0c09mZnNldFswXVxuICB9KVxuICAueShmdW5jdGlvbihkLCBpKXtcbiAgICB2YXIgeVxuICAgIGlmICh5U2NhbGUgIT0gdW5kZWZpbmVkKSB7IHk9IHlTY2FsZShkWzFdKSB9XG4gICAgZWxzZSB7eSA9ICBkWzFdfVxuICAgIHJldHVybiB5Ly8gLSBjaGFydE9mZnNldFsxXS8vIC0gb2JqZWN0c09mZnNldFsxXVxuICB9KVxuICAuY3VydmUoZDMuY3VydmVMaW5lYXJDbG9zZWQpLFxuXG4gIGluc3RhbmNlPTAsICAgIC8vIGFuIGluZGVudGlmaWVyIGZvciB3aGljaCBpbnN0YW5jZSB0aGlzIGxhc3NvIGlzIHVuZGVyIHRoZSBjdXJyZW50IHN2Z1xuXG4gIHRpY2tEaXN0YW5jZSA9IDEwLFxuXG4gIC8vIHN0eWxlcyBmb3IgbGFzc28gcGF0aFxuICBjb2xvciA9ICcjMTdhMmI4JyxcbiAgYW5pbWF0aW9uUmF0ZSA9ICcxMHMnLFxuICBvcGFjaXR5PTAuMyxcbiAgZGFzaEFycmF5ID0gJzUsIDEwJyxcbiAgc3Ryb2tlID0gJ2JsYWNrJyxcbiAgc3Ryb2tlV2lkdGg9MixcblxuICAvLyBzdHlsZXMgZm9yIGxhc3NvZWQgb2JqZWN0c1xuICBsYXNzb2VkRmlsbCA9IFwid2hpdGVcIixcbiAgbGFzc29lZFN0cm9rZSA9ICdibGFjaycsXG4gIGxhc3NvZWRTdHJva2VXaWR0aCA9IDMsXG5cbiAgdHJhbnNpdGlvbkR1cmF0aW9uID0gMTAwMCxcbiAgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwXG5cbiAgdmFyIHBhdGhcblxuICBsYXNzby5zdmcgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN2ZyA9IF8sIGxhc3NvKSA6IHN2ZzsgfVxuICBsYXNzby5jaGFydENvbnRhaW5lciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY2hhcnRDb250YWluZXIgPSBfLCBsYXNzbykgOiBjaGFydENvbnRhaW5lcjsgfVxuICBsYXNzby5vYmplY3RDb250YWluZXIgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdENvbnRhaW5lciA9IF8sIGxhc3NvKSA6IG9iamVjdENvbnRhaW5lcjsgfVxuICBsYXNzby5vYmplY3RDbGFzcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q2xhc3MgPSBfLCBsYXNzbykgOiBvYmplY3RDbGFzczsgfVxuICBsYXNzby5uYW1lc3BhY2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG5hbWVzcGFjZSA9IF8sIGxhc3NvKSA6IG5hbWVzcGFjZTsgfVxuICBsYXNzby54U2NhbGUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhTY2FsZSA9IF8sIGxhc3NvKSA6IHhTY2FsZTsgfVxuICBsYXNzby55U2NhbGUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlTY2FsZSA9IF8sIGxhc3NvKSA6IHlTY2FsZTsgfVxuICBsYXNzby5hY3RpdmVRID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChhY3RpdmVRID0gXywgbGFzc28pIDogYWN0aXZlUTsgfVxuICBsYXNzby5jdXJyZW50UG9pbnRzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjdXJyZW50UG9pbnRzID0gXywgbGFzc28pIDogY3VycmVudFBvaW50czsgfVxuICBsYXNzby5hbGxQb2ludHMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGFsbFBvaW50cyA9IF8sIGxhc3NvKSA6IGFsbFBvaW50czsgfVxuICBsYXNzby5pbnN0YW5jZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaW5zdGFuY2UgPSBfLCBsYXNzbykgOiBpbnN0YW5jZTsgfVxuICBsYXNzby50aWNrRGlzdGFuY2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tEaXN0YW5jZSA9IF8sIGxhc3NvKSA6IHRpY2tEaXN0YW5jZTsgfVxuICBsYXNzby5jb2xvciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY29sb3IgPSBfLCBsYXNzbykgOiBjb2xvcjsgfVxuICBsYXNzby5hbmltYXRpb25SYXRlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChhbmltYXRpb25SYXRlID0gXywgbGFzc28pIDogYW5pbWF0aW9uUmF0ZTsgfVxuICBsYXNzby5vcGFjaXR5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvcGFjaXR5ID0gXywgbGFzc28pIDogb3BhY2l0eTsgfVxuICBsYXNzby5kYXNoQXJyYXkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRhc2hBcnJheSA9IF8sIGxhc3NvKSA6IGRhc2hBcnJheTsgfVxuICBsYXNzby5zdHJva2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN0cm9rZSA9IF8sIGxhc3NvKSA6IHN0cm9rZTsgfVxuICBsYXNzby5sYXNzb2VkRmlsbCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobGFzc29lZEZpbGwgPSBfLCBsYXNzbykgOiBsYXNzb2VkRmlsbDsgfVxuICBsYXNzby5sYXNzb2VkU3Ryb2tlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChsYXNzb2VkU3Ryb2tlID0gXywgbGFzc28pIDogbGFzc29lZFN0cm9rZTsgfVxuICBsYXNzby5sYXNzb2VkU3Ryb2tlV2lkdGggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGxhc3NvZWRTdHJva2VXaWR0aCA9IF8sIGxhc3NvKSA6IGxhc3NvZWRTdHJva2VXaWR0aDsgfVxuICBsYXNzby5ldmVudENhdGNoZXIgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGV2ZW50Q2F0Y2hlciA9IF8sIGxhc3NvKSA6IGV2ZW50Q2F0Y2hlcjsgfVxuXG4gIGxhc3NvLmRyYWcgPSBkcmFnXG4gIGxhc3NvLmRyYXcgPSBkcmF3XG4gIGxhc3NvLnRpY2sgPSB0aWNrXG4gIGxhc3NvLmRldGVjdCA9IGRldGVjdFxuICBsYXNzby50b2dnbGUgPSB0b2dnbGVcbiAgbGFzc28ucmVtb3ZlID0gcmVtb3ZlXG4gIGxhc3NvLnJlbmRlciA9IHJlbmRlclxuICBsYXNzby5rZXlGcmFtZXMgPSBrZXlGcmFtZXNcbiAgbGFzc28udXBkYXRlT2JqZWN0cyA9IHVwZGF0ZU9iamVjdHNcbiAgbGFzc28uYXBwbHlQYXRoQXR0cmlidXRlcyA9IGFwcGx5UGF0aEF0dHJpYnV0ZXNcbiAgbGFzc28uYXBwbHlPYmplY3RBdHRyaWJ1dGVzID0gYXBwbHlPYmplY3RBdHRyaWJ1dGVzXG5cbiAga2V5RnJhbWVzKClcblxuICBmdW5jdGlvbiBsYXNzbygpIHtcbiAgICAvLyBhZGQgYSBkYXNoIGFuaW1hdGlvbiBpZiBuZWVkZWRcbiAgICBpZiAoYWN0aXZlUSkgeyB0cmFuc2l0aW9uRHJhdygpIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHRvZ2dsZShzdGF0ZSkge1xuICAgIC8vIHVzZSBvcHRpb25hbCBwYXJhbSB0byBzZXQgc3RhdGUsIG90aGVyd2lzZSB0b2dnbGUgc3RhdGVcbiAgICBhY3RpdmVRID0gKHN0YXRlIT11bmRlZmluZWQpID8gc3RhdGUgOiAhYWN0aXZlUVxuICAgIGNoYXJ0T2Zmc2V0ID0gZ2V0VHJhbnNsYXRpb24oY2hhcnRDb250YWluZXIpXG4gICAgb2JqZWN0c09mZnNldCA9IGdldFRyYW5zbGF0aW9uKG9iamVjdENvbnRhaW5lcilcblxuICAgIGlmIChhY3RpdmVRKSB7XG4gICAgICBzdmcubm9kZSgpLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHJlbmRlciwgdHJ1ZSlcbiAgICB9IGVsc2Uge1xuICAgICAgc3ZnLm5vZGUoKS5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCByZW5kZXIsIHRydWUpXG4gICAgICByZW1vdmUoKVxuICAgIH1cblxuICB9XG5cbiAgZnVuY3Rpb24gZHJhdygpIHtcbiAgICBjaGFydE9mZnNldCA9IGdldFRyYW5zbGF0aW9uKGNoYXJ0Q29udGFpbmVyKVxuICAgIG9iamVjdHNPZmZzZXQgPSBnZXRUcmFuc2xhdGlvbihvYmplY3RDb250YWluZXIpXG5cbiAgICB2YXIgY29udGFpbmVyID0gc2FmZVNlbGVjdChvYmplY3RDb250YWluZXIsICdnJywgJ2xhc3NvLWNvbnRhaW5lcicpXG4gICAgdmFyIHBhdGhzID0gY29udGFpbmVyLnNlbGVjdEFsbCgncGF0aFtpbnN0YW5jZT1cIicraW5zdGFuY2UrJ1wiXScpXG5cbiAgICAvLyB1cGRhdGVcbiAgICBwYXRocyA9IHBhdGhzLmRhdGEoYWxsUG9pbnRzKVxuXG4gICAgLy8gcmVtb3ZlIGV4Y2Vzc1xuICAgIHZhciBwRXhpdCA9IHBhdGhzLmV4aXQoKS5yZW1vdmUoKVxuICAgIC8vIGFkZCBuZWVkZWQgcGF0aHNcbiAgICB2YXIgcEVudGVyID0gcGF0aHMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKVxuXG4gICAgLy8gbWVyZ2VcbiAgICBwYXRocyA9IHBhdGhzLm1lcmdlKHBFbnRlcilcblxuICAgIC8vIGFwcGx5XG4gICAgYXBwbHlQYXRoQXR0cmlidXRlcyhwYXRocylcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbW92ZSgpIHtcbiAgICB2YXIgY29udGFpbmVyID0gc2FmZVNlbGVjdChvYmplY3RDb250YWluZXIsICdnJywgJ2xhc3NvLWNvbnRhaW5lcicpXG4gICAgdmFyIHBhdGhzID0gY29udGFpbmVyLnNlbGVjdEFsbCgncGF0aFtpbnN0YW5jZT1cIicraW5zdGFuY2UrJ1wiXScpLnJlbW92ZSgpXG4gICAgY29udGFpbmVyLnJlbW92ZSgpXG4gICAgb2JqZWN0Q29udGFpbmVyLnNlbGVjdEFsbChvYmplY3RDbGFzcykuY2xhc3NlZChcImluLWxhc3NvXCIsIGZhbHNlKVxuICAgIHVwZGF0ZU9iamVjdHMoKVxuICB9XG5cbiAgZnVuY3Rpb24gcmVuZGVyKCBldmVudCApIHtcbiAgICAvLyBub3RoaW5nIGNhbiBpbnRlcmVmZXIgd2l0aCBkcmF3aW5nIHRoZSBsYXNzb1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgdmFyIGNvbnRhaW5lciA9IHNhZmVTZWxlY3Qob2JqZWN0Q29udGFpbmVyLCAnZycsICdsYXNzby1jb250YWluZXInKVxuXG4gICAgLypcbiAgICBlYWNoIHRpbWUgdGhlIHVzZXIgcHJlc3NlcyBkb3duLCB3aGlsZSB0aGUgc3RhdGUgaXMgYWN0aXZlLCB0aGUgbGFzc29cbiAgICB0aGUgbGFzc28gc2hvdWxkIG1ha2UgYSBzZXBlcmF0ZSBzZWdtZW50LlxuICAgICovXG4gICAgY3VycmVudFBvaW50cyA9IFtdO1xuXG4gICAgc3ZnLm5vZGUoKS5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBkcmFnKVxuICAgIHN2Zy5ub2RlKCkuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICBzdmcubm9kZSgpLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIGRyYWcpXG4gICAgICBhbGxQb2ludHMucHVzaChjdXJyZW50UG9pbnRzKVxuICAgICAgLy8gQlVHOiAgc29tZWhvdyB0aGlzIGlzIHB1c2hpbmcgY3VycmVudFBvaW50cyBuIHRpbWVzIHdoZXJlIG4gaXMgdGhlIG50aCBsYXNzbyBwYXRoIGZvciB0aGUgY3VycmVudCBpbnN0YW5jZVxuICAgICAgLy8gTk9URTogYWxsUG9pbnRzID0gdW5pcXVlKGFsbFBvaW50cykgaXMgYSB0ZW1wb3JhcnkgYW5kIGluZWZmaWNpZW50IGZpeFxuICAgICAgYWxsUG9pbnRzID0gdW5pcXVlKGFsbFBvaW50cylcbiAgICB9KVxuXG4gICAgcGF0aCA9IGNvbnRhaW5lci5hcHBlbmQoJ3BhdGgnKS5kYXRhKFtjdXJyZW50UG9pbnRzXSlcbiAgICBhcHBseVBhdGhBdHRyaWJ1dGVzKHBhdGgpXG4gIH1cblxuICBmdW5jdGlvbiB0cmFuc2l0aW9uRHJhdygpIHtcbiAgICB2YXIgY29udGFpbmVyID0gc2FmZVNlbGVjdChvYmplY3RDb250YWluZXIsICdnJywgJ2xhc3NvLWNvbnRhaW5lcicpXG4gICAgdmFyIHBhdGhzID0gY29udGFpbmVyLnNlbGVjdEFsbCgncGF0aFtpbnN0YW5jZT1cIicraW5zdGFuY2UrJ1wiXScpXG5cbiAgICAvLyB1cGRhdGVcbiAgICBwYXRocyA9IHBhdGhzLmRhdGEoYWxsUG9pbnRzKVxuXG4gICAgLy8gcmVtb3ZlIGV4Y2Vzc1xuICAgIHZhciBwRXhpdCA9IHBhdGhzLmV4aXQoKS5yZW1vdmUoKVxuICAgIC8vIGFkZCBuZWVkZWQgcGF0aHNcbiAgICB2YXIgcEVudGVyID0gcGF0aHMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKVxuXG4gICAgLy8gbWVyZ2VcbiAgICBwYXRocyA9IHBhdGhzLm1lcmdlKHBFbnRlcilcbiAgICAudHJhbnNpdGlvbigpLmR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbilcbiAgICAuZWFzZShlYXNlRnVuYylcbiAgICBhcHBseVBhdGhBdHRyaWJ1dGVzKHBhdGhzKVxuXG4gIH1cblxuICBmdW5jdGlvbiBhcHBseVBhdGhBdHRyaWJ1dGVzKHBhdGgpIHtcbiAgICBwYXRoXG4gICAgLmF0dHIoXCJjbGFzc1wiLCBoeXBlbmF0ZShuYW1lc3BhY2UsIFwibGFzc28tcGF0aFwiKSlcbiAgICAuc3R5bGUoJ29wYWNpdHknLCBvcGFjaXR5KVxuICAgIC5hdHRyKCdmaWxsJywgY29sb3IpXG4gICAgLmF0dHIoXCJkXCIsIGxpbmUpXG4gICAgLmF0dHIoJ2luc3RhbmNlJywgaW5zdGFuY2UpXG4gICAgLnN0eWxlKFwic3Ryb2tlLWRhc2hhcnJheVwiLCBkYXNoQXJyYXkpXG4gICAgLmF0dHIoXCJzdHJva2VcIiwgc3Ryb2tlKVxuICAgIC5hdHRyKFwic3Ryb2tlLXdpZHRoXCIsIHN0cm9rZVdpZHRoKVxuICAgIC5zdHlsZSgnYW5pbWF0aW9uJywgJ2xhc3NvRGFzaCAnK2FuaW1hdGlvblJhdGUrJyBsaW5lYXInKVxuICAgIC5zdHlsZShcImFuaW1hdGlvbi1pdGVyYXRpb24tY291bnRcIiwgXCJpbmZpbml0ZVwiKVxuICB9XG5cbiAgZnVuY3Rpb24gZHJhZyhldmVudCkge1xuICAgIC8qXG4gICAgZWZmZWN0aXZlbHkgY3JlYXRlIGEgbW91c2UgZG93biBhbmQgbW92ZSBldmVudCAod2hpY2ggbm9ybWFsbHkgaXMgaW50ZXBlcmF0ZWRcbiAgICBhcyAnZHJhZycgYnkgdGhlIGJyb3dzZXIpIGJ5IGR5bmFtaWNhbGx5IGFkZGluZyAvIHJlbW92aW5nIHRoaXMgZXZlbnQgb25cbiAgICBtb3VzZSBkb3duIC8gbW91c2UgdXAuXG4gICAgKi9cblxuICAgIGlmIChldmVudENhdGNoZXIgIT0gdW5kZWZpbmVkKSB7ZXZlbnRDYXRjaGVyLmRpc3BhdGNoKGh5cGVuYXRlKG5hbWVzcGFjZSxcImRyYWdcIikpfVxuICAgIC8vIGQzLmRpc3BhdGNoKGh5cGVuYXRlKG5hbWVzcGFjZSxcImRyYWdcIikpXG5cbiAgICBpZiAoZXZlbnQud2hpY2ggIT0gMSkge3JldHVybn0gLy8gZW5zdXJlcyBsZWZ0IG1vdXNlIGJ1dHRvbiBzZXRcbiAgICBkMy5ldmVudCA9IGV2ZW50XG4gICAgdmFyIHB0ID0gZDMubW91c2Uob2JqZWN0Q29udGFpbmVyLm5vZGUoKSk7XG4gICAgdmFyIHB0ID0gZDMubW91c2Uoc3ZnLm5vZGUoKSk7XG5cbiAgICBpZiAoeFNjYWxlICE9IHVuZGVmaW5lZCkge3B0WzBdID0geFNjYWxlLmludmVydChwdFswXSl9XG4gICAgaWYgKHlTY2FsZSAhPSB1bmRlZmluZWQpIHtwdFsxXSA9IHlTY2FsZS5pbnZlcnQocHRbMV0pfVxuICAgIHB0WzBdID0gcHRbMF0gLSBjaGFydE9mZnNldFswXSAtIG9iamVjdHNPZmZzZXRbMF1cbiAgICBwdFsxXSA9IHB0WzFdIC0gY2hhcnRPZmZzZXRbMV0gLSBvYmplY3RzT2Zmc2V0WzFdXG5cbiAgICAvKiBpZiB3ZSBoYXZlIGEgcG9pbnQgYWxyZWFkeSwgdGVzdCBpZiBpdCBwYXNzZXMgYSBtaW5pbXVtIGRpc3RhbmNlIHRvIHByZXZlbnQgb3ZlcndoZWxtaW5nIHdpdGggdG9vIG1hbnkgdGljayBmdW5jdGlvbnMgKi9cbiAgICBpZiAoY3VycmVudFBvaW50cy5sZW5ndGgpIHtcbiAgICAgIHZhciBsYXN0UHQgPSBjdXJyZW50UG9pbnRzW2N1cnJlbnRQb2ludHMubGVuZ3RoIC0gMV1cbiAgICAgIHZhciBhID0gW3B0WzBdLCBwdFsxXV0sIGIgPSBbbGFzdFB0WzBdLCBsYXN0UHRbMV1dXG5cbiAgICAgIGlmICh4U2NhbGUpIHtiWzBdID0geFNjYWxlKGJbMF0pOyBhWzBdID0geFNjYWxlKGFbMF0pfVxuICAgICAgaWYgKHlTY2FsZSkge2JbMV0gPSB5U2NhbGUoYlsxXSk7IGFbMV0gPSB5U2NhbGUoYVsxXSl9XG5cbiAgICAgIHZhciBkaXN0ID0gZXVjbGlkZWFuRGlzdGFuY2UoYiwgYSlcbiAgICAgIGlmIChkaXN0ID4gdGlja0Rpc3RhbmNlKSB7IHRpY2socHQpIH1cbiAgICB9XG4gICAgZWxzZSB7IHRpY2socHQpIH1cbiAgfVxuXG5cbiAgZnVuY3Rpb24gdGljayAocHQpIHtcbiAgICAvKlxuICAgIElmIGEgcG9pbnQgaXMgcHJvdmlkZWQgdXBkYXRlIGRhdGEgYW5kIG9iamVjdHMuXG4gICAgT3RoZXJ3aXNlIGp1c3QgY2FsbCBvbiBkYXRhIHdlIGFscmVhZHkgaGF2ZS5cblxuICAgIFdoeSBsaWtlIHRoaXM/OlxuICAgIDEuIGN1cnJlbnRQb2ludHMgaXMgY3VycmVudCBwb2ludHMgdG8gYWxsb3cgZGlzanVuY3QgbGFzc29zLCBjdXJyZW50UG9pbnRzIGlzIG9ubHkgcHVzaGVkIHRvXG4gICAgYWxsUG9pbnRzIGFmdGVyIG1vdXNldXAuXG4gICAgMi4gdG8gYWxsb3cgcmVuZGVyIG9mIG9iamVjdHMgaW4gdGhlIGxhc3NvIGNsYXNzIC8gdXBkYXRpbmcgdGhlIGRhdGEgbGlzdFxuICAgIGp1c3QgYnkgdG9nZ2xpbmcgdGhlIGJ1dHRvblxuICAgICovXG5cbiAgICBpZiAocHQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICBjdXJyZW50UG9pbnRzLnB1c2gocHQpO1xuICAgICAgcGF0aC5hdHRyKFwiZFwiLCBsaW5lKTtcbiAgICAgIGlmIChjdXJyZW50UG9pbnRzLmxlbmd0aCA8IDMpIHtyZXR1cm59IC8vIG5lZWQgYXQgbGVhc3QgMyBwb2ludHMgdG8gZGV0ZWN0IGFueXRoaW5nLlxuICAgICAgZGV0ZWN0KGFsbFBvaW50cy5jb25jYXQoW2N1cnJlbnRQb2ludHNdKSlcbiAgICB9IGVsc2Uge1xuICAgICAgZGV0ZWN0KGFsbFBvaW50cylcbiAgICB9XG4gIH1cblxuXG4gIGZ1bmN0aW9uIGRldGVjdChsYXNzb3MpIHtcbiAgICBpZiAobGFzc29zID09IHVuZGVmaW5lZCkge2xhc3NvcyA9IGFsbFBvaW50c31cbiAgICBvYmplY3RDb250YWluZXIuc2VsZWN0QWxsKG9iamVjdENsYXNzKS5lYWNoKGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgdmFyIGN1cnJlbnQgPSBkMy5zZWxlY3QodGhpcyksXG5cbiAgICAgIGJveCA9IGN1cnJlbnQuYWJzb2x1dGVQb3NpdGlvbigpLFxuICAgICAgLy8gYm94ID0gY3VycmVudC5yZWxhdGl2ZVBvc2l0aW9uVG8ob2JqZWN0Q29udGFpbmVyLm5vZGUoKSksXG5cbiAgICAgIGJveFB0cyA9IFtcbiAgICAgICAgW1xuICAgICAgICAgIGJveC5sZWZ0IC0gY2hhcnRPZmZzZXRbMF0gLSBvYmplY3RzT2Zmc2V0WzBdLFxuICAgICAgICAgIGJveC50b3AgLSBjaGFydE9mZnNldFsxXSAtIG9iamVjdHNPZmZzZXRbMV1cbiAgICAgICAgXSxcbiAgICAgICAgW1xuICAgICAgICAgIGJveC5yaWdodCAtIGNoYXJ0T2Zmc2V0WzBdIC0gb2JqZWN0c09mZnNldFswXSxcbiAgICAgICAgICBib3gudG9wIC0gY2hhcnRPZmZzZXRbMV0gLSBvYmplY3RzT2Zmc2V0WzFdXG4gICAgICAgIF0sXG4gICAgICAgIFtcbiAgICAgICAgICBib3gubGVmdCAtIGNoYXJ0T2Zmc2V0WzBdIC0gb2JqZWN0c09mZnNldFswXSxcbiAgICAgICAgICBib3guYm90dG9tIC0gY2hhcnRPZmZzZXRbMV0gLSBvYmplY3RzT2Zmc2V0WzFdXG4gICAgICAgIF0sXG4gICAgICAgIFtcbiAgICAgICAgICBib3gucmlnaHQgLSBjaGFydE9mZnNldFswXSAtIG9iamVjdHNPZmZzZXRbMF0sXG4gICAgICAgICAgYm94LmJvdHRvbSAtIGNoYXJ0T2Zmc2V0WzFdIC0gb2JqZWN0c09mZnNldFsxXVxuICAgICAgICBdXG4gICAgICBdXG5cbiAgICAgIGlmICh4U2NhbGUgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGJveFB0c1swXVswXSA9IHhTY2FsZS5pbnZlcnQoYm94UHRzWzBdWzBdKVxuICAgICAgICBib3hQdHNbMV1bMF0gPSB4U2NhbGUuaW52ZXJ0KGJveFB0c1sxXVswXSlcbiAgICAgICAgYm94UHRzWzJdWzBdID0geFNjYWxlLmludmVydChib3hQdHNbMl1bMF0pXG4gICAgICAgIGJveFB0c1szXVswXSA9IHhTY2FsZS5pbnZlcnQoYm94UHRzWzNdWzBdKVxuICAgICAgfVxuICAgICAgaWYgKHlTY2FsZSAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgYm94UHRzWzBdWzFdID0geVNjYWxlLmludmVydChib3hQdHNbMF1bMV0pXG4gICAgICAgIGJveFB0c1sxXVsxXSA9IHlTY2FsZS5pbnZlcnQoYm94UHRzWzFdWzFdKVxuICAgICAgICBib3hQdHNbMl1bMV0gPSB5U2NhbGUuaW52ZXJ0KGJveFB0c1syXVsxXSlcbiAgICAgICAgYm94UHRzWzNdWzFdID0geVNjYWxlLmludmVydChib3hQdHNbM11bMV0pXG4gICAgICB9XG5cblxuICAgICAgLypcbiAgICAgIGZsYWcgbmVlZGVkIGFzIHdlIGhhdmUgdG8gdGVzdCBtdWx0aXBsZSBsYXNzbyBzZWdtZW50cywgYW5kIGlmIHRoZSBwb2ludFxuICAgICAgaXMgbm90IGluIG9uZSBzZWdtZW50LCBpdCBkb2VzIG5vdCBtZWFuIGl0IGlzIG5vdCBpbiBhbnlcbiAgICAgICovXG4gICAgICB2YXIgaW5BbnlMYXNzb1EgPSBmYWxzZTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGFzc29zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBsYXNzb1BvaW50cyA9IGxhc3Nvc1tpXVxuICAgICAgICAvLyAubWFwKGZ1bmN0aW9uKHB0KXtcbiAgICAgICAgLy8gICB2YXIgeCwgeSA9IHB0XG4gICAgICAgIC8vICAgaWYgKHhTY2FsZSE9dW5kZWZpbmVkKSB7eCA9IHhTY2FsZSh4KX1cbiAgICAgICAgLy8gICBpZiAoeVNjYWxlIT11bmRlZmluZWQpIHt5ID0geVNjYWxlKHkpfVxuICAgICAgICAvLyAgIHJldHVybiBbeCwgeV1cbiAgICAgICAgLy8gfSlcbiAgICAgICAgdmFyIGJveEluTGFzc29RID0gYm94UHRzLmV2ZXJ5KGNvb3JkID0+IGQzLnBvbHlnb25Db250YWlucyhsYXNzb1BvaW50cywgY29vcmQpKVxuXG4gICAgICAgIGlmIChib3hJbkxhc3NvUSkgeyBpbkFueUxhc3NvUSA9IHRydWU7IH0gLy8gb25seSB1cGRhdGUgZmxhZyBpbiB0aGUgcG9zaXRpdmUgY2FzZS5cbiAgICAgIH1cblxuICAgICAgY3VycmVudC5jbGFzc2VkKCdpbi1sYXNzbycsIGluQW55TGFzc29RKVxuICAgICAgY3VycmVudC5jbGFzc2VkKCdpbi1sYXNzby0nK2luc3RhbmNlLCBpbkFueUxhc3NvUSlcbiAgICB9KVxuXG4gICAgdXBkYXRlT2JqZWN0cygpXG4gICAgcmV0dXJuIG9iamVjdENvbnRhaW5lci5zZWxlY3RBbGwoJy5pbi1sYXNzby0nK2luc3RhbmNlKVxuICB9XG5cblxuXG4gIGZ1bmN0aW9uIHVwZGF0ZU9iamVjdHMoKSB7XG4gICAgb2JqZWN0Q29udGFpbmVyLnNlbGVjdEFsbChvYmplY3RDbGFzcykuZWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgICAgYXBwbHlPYmplY3RBdHRyaWJ1dGVzKHQsIHQuY2xhc3NlZCgnaW4tbGFzc28nKSlcbiAgICB9KVxuICB9XG5cbiAgZnVuY3Rpb24gYXBwbHlPYmplY3RBdHRyaWJ1dGVzKG9iaiwgc2V0USkge1xuICAgIHZhclxuICAgIHByZUxhc3NvRmlsbCA9IG9iai5hdHRyKCdfcHJlX2xhc3NvX2ZpbGwnKSxcbiAgICBwcmVMYXNzb1N0cm9rZSA9IG9iai5hdHRyKCdfcHJlX2xhc3NvX3N0cm9rZScpLFxuICAgIHByZUxhc3NvU3Ryb2tlV2lkdGggPSBvYmouYXR0cignX3ByZV9sYXNzb19zdHJva2Utd2lkdGgnKVxuXG4gICAgaWYgKHNldFEpIHtcbiAgICAgIG9iai5jbGFzc2VkKFwiaW4tbGFzc29cIiwgdHJ1ZSlcbiAgICAgIG9iai5jbGFzc2VkKCdpbi1sYXNzby0nK2luc3RhbmNlLCB0cnVlKVxuICAgICAgaWYgKHByZUxhc3NvRmlsbCA9PSB1bmRlZmluZWQpIHsgb2JqLmF0dHIoJ19wcmVfbGFzc29fZmlsbCcsIG9iai5hdHRyKCdmaWxsJykpIH1cbiAgICAgIGlmIChwcmVMYXNzb1N0cm9rZSA9PSB1bmRlZmluZWQpIHsgb2JqLmF0dHIoJ19wcmVfbGFzc29fc3Ryb2tlJywgb2JqLmF0dHIoJ3N0cm9rZScpKSB9XG4gICAgICBpZiAocHJlTGFzc29TdHJva2VXaWR0aCA9PSB1bmRlZmluZWQpIHsgb2JqLmF0dHIoJ19wcmVfbGFzc29fc3Ryb2tlLXdpZHRoJywgb2JqLmF0dHIoJ3N0cm9rZS13aWR0aCcpKSB9XG5cbiAgICAgIG9ialxuICAgICAgLy9CVUc6IHdoZW4gLnJhaXNlKClcbiAgICAgIC5hdHRyKCdmaWxsJywgbGFzc29lZEZpbGwpXG4gICAgICAuYXR0cignc3Ryb2tlJywgbGFzc29lZFN0cm9rZSlcbiAgICAgIC5hdHRyKCdzdG9rZS13aWR0aCcsIGxhc3NvZWRTdHJva2VXaWR0aClcblxuICAgIH0gZWxzZSB7XG4gICAgICBvYmouY2xhc3NlZChcImluLWxhc3NvXCIsIGZhbHNlKVxuICAgICAgb2JqLmNsYXNzZWQoJ2luLWxhc3NvLScraW5zdGFuY2UsIGZhbHNlKVxuICAgICAgaWYgKHByZUxhc3NvRmlsbCAhPSB1bmRlZmluZWQpIHsgb2JqLmF0dHIoJ2ZpbGwnLCBwcmVMYXNzb0ZpbGwpIH1cbiAgICAgIGlmIChwcmVMYXNzb1N0cm9rZSAhPSB1bmRlZmluZWQpIHsgb2JqLmF0dHIoJ3N0cm9rZScsIHByZUxhc3NvU3Ryb2tlKSB9XG4gICAgICBpZiAocHJlTGFzc29TdHJva2VXaWR0aCAhPSB1bmRlZmluZWQpIHsgb2JqLmF0dHIoJ3N0cm9rZS13aWR0aCcsIHByZUxhc3NvU3Ryb2tlV2lkdGgpIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBrZXlGcmFtZXMoKSB7XG4gICAgdmFyIHN0eWxlID1cbiAgICBkMy5zZWxlY3QoXCJodG1sXCIpLnNlbGVjdCgnc3R5bGUuJytoeXBlbmF0ZShuYW1lc3BhY2UsXCJsYXNzby1kYXNoXCIpKVxuICAgIGlmIChzdHlsZS5lbXB0eSgpKSB7XG4gICAgICBkMy5zZWxlY3QoXCJodG1sXCIpLmFwcGVuZCgnc3R5bGUnKVxuICAgICAgLmNsYXNzZWQoaHlwZW5hdGUobmFtZXNwYWNlLFwibGFzc28tZGFzaFwiKSwgdHJ1ZSlcbiAgICAgIC5odG1sKFwiQGtleWZyYW1lcyBsYXNzb0Rhc2gge3RvIHsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDEwMDA7fX1cIilcbiAgICB9XG5cbiAgfVxuICByZXR1cm4gbGFzc29cbn1cbiIsImltcG9ydCB7Z2V0Q29udGFpbmluZ1NWR30gZnJvbSBcIi4vaGVscGVyc1wiO1xuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEQzIEVYVEVOU0lPTlMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbi8qKlxuKiBSZWN1cnNpdmVseSBhc2NlbmRzIHBhcmVudHMgb2Ygc2VsZWN0aW9uIHVudGlsIGl0IGZpbmRzIGFuIHN2ZyB0YWdcbiogQGZ1bmN0aW9uIGQzLnNlbGVjdGlvbi50aGlzU1ZHXG4qIEBhdWdtZW50cyBkMy5zZWxlY3Rpb25cbiogQHJldHVybnMge0VsZW1lbnR9IHdoaWNoIGlzIHRoZSBzdmcgdGFnLCBub3QgdGhlIGQzIHNlbGVjdGlvbiBvZiB0aGF0IHRhZ1xuKi9cbmQzLnNlbGVjdGlvbi5wcm90b3R5cGUudGhpc1NWRyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gZ2V0Q29udGFpbmluZ1NWRyh0aGlzLm5vZGUoKSk7IH1cblxuXG4vKipcbiogSGVscGVyIGZvciBnZXR0aW5nIGFic29sdXRlIHBvc2l0aW9uIG9mIHRoZSBtb3VzZVxuKiBAZnVuY3Rpb24gZDMubW91c2UuYWJzb2x1dGVcbiogQGF1Z21lbnRzIGQzLm1vdXNlXG4qIEByZXR1cm5zIHtudW1iZXJbXX0gW3gsIHldIGFzIHRoZXkgcmVsYXRlIHRvIGBodG1sYCBub3QgdG8gbG9jYWwgc2NvcGUuXG4qL1xuZDMubW91c2UuYWJzb2x1dGUgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGh0bWwgPSBkMy5zZWxlY3QoJ2h0bWwnKS5ub2RlKClcbiAgdmFyIFt4LCB5XSA9IHRoaXMoaHRtbClcbiAgcmV0dXJuIFt4LCB5XVxufVxuXG5cbi8qKlxuKiBHZXRzIHBvc2l0aW9uIG9mIHRoZSBzZWxlY3Rpb24gaW4gcmVsYXRpb24gdG8gdGhlIGNvbnRhaW5pbmcgc3ZnXG4qIEBzZWV7QGxpbmsgZ2V0Q29udGFpbmluZ1NWR31cbiogQGZ1bmN0aW9uIGQzLnNlbGVjdGlvbi5hYnNvbHV0ZVBvc2l0aW9uXG4qIEBhdWdtZW50cyBkMy5zZWxlY3Rpb25cbiogQHJldHVybnMge09iamVjdH0gd2l0aCBzdHJ1Y3R1cmUgc2ltaWxhciB0byBnZXRCb3VuZGluZ0NsaWVudFJlY3QsIGUuZy5cbiogdG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0LCBoZWlnaHQsIHdpZHRoXG4qL1xuZDMuc2VsZWN0aW9uLnByb3RvdHlwZS5hYnNvbHV0ZVBvc2l0aW9uID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGVsZW1lbnQgPSB0aGlzLm5vZGUoKTtcbiAgICB2YXIgZWxlbWVudFBvc2l0aW9uID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB2YXIgY29udGFpbmVyU1ZHID0gZ2V0Q29udGFpbmluZ1NWRyhlbGVtZW50KVxuICAgIHZhciBzdmdQb3NpdGlvbiA9IGNvbnRhaW5lclNWRy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHRvcDogICAgZWxlbWVudFBvc2l0aW9uLnRvcCAgICAtIHN2Z1Bvc2l0aW9uLnRvcCxcbiAgICAgICAgbGVmdDogICBlbGVtZW50UG9zaXRpb24ubGVmdCAgIC0gc3ZnUG9zaXRpb24ubGVmdCxcbiAgICAgICAgYm90dG9tOiBlbGVtZW50UG9zaXRpb24uYm90dG9tIC0gc3ZnUG9zaXRpb24udG9wLFxuICAgICAgICByaWdodDogIGVsZW1lbnRQb3NpdGlvbi5yaWdodCAgLSBzdmdQb3NpdGlvbi5sZWZ0LFxuICAgICAgICBoZWlnaHQ6IGVsZW1lbnRQb3NpdGlvbi5oZWlnaHQsXG4gICAgICAgIHdpZHRoOiAgZWxlbWVudFBvc2l0aW9uLndpZHRoXG4gICAgfTtcblxufVxuXG5cbmQzLnNlbGVjdGlvbi5wcm90b3R5cGUucmVsYXRpdmVQb3NpdGlvblRvID0gZnVuY3Rpb24oY29udGFpbmVyKSB7XG4gICAgdmFyIGVsZW1lbnQgPSB0aGlzLm5vZGUoKTtcbiAgICB2YXIgZWxlbWVudFBvc2l0aW9uID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB2YXIgY29udGFpbmVyU1ZHID0gY29udGFpbmVyXG4gICAgdmFyIHN2Z1Bvc2l0aW9uID0gY29udGFpbmVyU1ZHLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdG9wOiAgICBlbGVtZW50UG9zaXRpb24udG9wICAgIC0gc3ZnUG9zaXRpb24udG9wLFxuICAgICAgICBsZWZ0OiAgIGVsZW1lbnRQb3NpdGlvbi5sZWZ0ICAgLSBzdmdQb3NpdGlvbi5sZWZ0LFxuICAgICAgICBib3R0b206IGVsZW1lbnRQb3NpdGlvbi5ib3R0b20gLSBzdmdQb3NpdGlvbi50b3AsXG4gICAgICAgIHJpZ2h0OiAgZWxlbWVudFBvc2l0aW9uLnJpZ2h0ICAtIHN2Z1Bvc2l0aW9uLmxlZnQsXG4gICAgICAgIGhlaWdodDogZWxlbWVudFBvc2l0aW9uLmhlaWdodCxcbiAgICAgICAgd2lkdGg6ICBlbGVtZW50UG9zaXRpb24ud2lkdGhcbiAgICB9O1xuXG59XG4iLCIvLyBJbXBvcnQgc3R5bGVzIChhdXRvbWF0aWNhbGx5IGluamVjdCBpbnRvIDxoZWFkPikuXG4vLyBpbXBvcnQgJy4uL3N0eWxlcy9tYWluLmNzcyc7XG5pbXBvcnQge2F4aXN9IGZyb20gJy4vbW9kdWxlcy9heGlzJztcbmltcG9ydCB7YmFyfSBmcm9tICcuL21vZHVsZXMvYmFyJztcbmltcG9ydCB7YnViYmxlSGVhdG1hcH0gZnJvbSAnLi9tb2R1bGVzL2J1YmJsZS1oZWF0bWFwJztcbmltcG9ydCB7aGVhdG1hcH0gZnJvbSAnLi9tb2R1bGVzL2hlYXRtYXAnO1xuaW1wb3J0IHtib3h3aGlza2VyfSBmcm9tICcuL21vZHVsZXMvYm94LXdoaXNrZXInO1xuaW1wb3J0IHtjb2xvckZ1bmN0aW9ufSBmcm9tICcuL21vZHVsZXMvY29sb3ItZnVuY3Rpb24nO1xuaW1wb3J0IHtkYXRhdG9nZ2xlfSBmcm9tICcuL21vZHVsZXMvZGF0YS10b2dnbGUnO1xuaW1wb3J0IHtncm91cGluZ1NwYWNlcn0gZnJvbSAnLi9tb2R1bGVzL2dyb3VwaW5nLXNwYWNlcic7XG5pbXBvcnQge3Rvb2x0aXB9IGZyb20gJy4vbW9kdWxlcy90b29sdGlwJztcbmltcG9ydCB7c2NhdHRlcn0gZnJvbSAnLi9tb2R1bGVzL3NjYXR0ZXInO1xuaW1wb3J0IHtwbG90Wm9vbX0gZnJvbSAnLi9tb2R1bGVzL3Bsb3Qtem9vbSc7XG5pbXBvcnQge211bHRpUGxvdFpvb219IGZyb20gJy4vbW9kdWxlcy9tdWx0aS1wbG90LXpvb20nO1xuaW1wb3J0IHt2aW9saW59IGZyb20gJy4vbW9kdWxlcy92aW9saW4nO1xuaW1wb3J0IHtudW1lcmljTGVnZW5kfSBmcm9tICcuL21vZHVsZXMvbnVtZXJpYy1sZWdlbmQnO1xuaW1wb3J0IHtjYXRlZ29yaWNMZWdlbmR9IGZyb20gJy4vbW9kdWxlcy9jYXRlZ29yaWNhbC1sZWdlbmQnO1xuaW1wb3J0IHtsYXNzb30gZnJvbSAnLi9tb2R1bGVzL2xhc3NvJztcbmltcG9ydCB7bGFzc29XaWRnZXR9IGZyb20gJy4vbW9kdWxlcy9sYXNzby13aWRnZXQnO1xuaW1wb3J0IHtzZWxlY3RGaWx0ZXJ9IGZyb20gJy4vbW9kdWxlcy9zZWxlY3QtZmlsdGVyJztcbmltcG9ydCB7dXBzZXR9IGZyb20gJy4vbW9kdWxlcy91cHNldCc7XG5pbXBvcnQge2ZpbHRlclRhYmxlfSBmcm9tICcuL21vZHVsZXMvZmlsdGVyLXRhYmxlJztcblxuaW1wb3J0IHt1bmlxdWVFbGVtZW50cywgZ2V0VHJhbnNsYXRpb24sIG1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2UsIHRpY2tSYW5nZSxcbnF1YXJ0aWxlcywgZXh0cmFjdFZpb2xpblZhbHVlcywgaHlwZW5hdGUsIHJvdW5kLCBnZXRDb250YWluaW5nU1ZHLFxuaW50ZXJwb2xhdGVDb2xvcnMsIHRydW5jYXRlVGV4dCwgc2FmZVNlbGVjdH0gZnJvbSAnLi9tb2R1bGVzL2hlbHBlcnMnO1xuXG5pbXBvcnQge1xuICBhbGwsIHRhbGx5LCBoYXNRLCBmaXJzdCwgbGFzdCwgdG90YWwsIHVuaXF1ZSwgZ2V0LCBsaXN0T2ZMaXN0c1EsXG4gIGN1dCwgZ3JvdXBCeSwgYXJyYXlFcXVhbHMsIGVsZW1lbnRzQXRMZXZlbHMsIG51bWJlck9mRWxlbWVudHMsXG4gIGZsYXR0ZW4sIHdoaWNoQmluXG59IGZyb20gJy4vbW9kdWxlcy9hcnJheS1mdW5jdGlvbnMnO1xuXG5cbmltcG9ydCB7XG4gIHNldHVwU3RhbmRhcmRDaGFydENvbnRhaW5lcnMsIGxvZyBhcyBteUxvZywgd2FybiwgaW5mbywgZXJyb3IsXG4gIGNvbnNvbGVHcm91cCwgY29uc29sZUdyb3VwRW5kLCByZXNpemVEZWJvdW5jZVxufSBmcm9tICcuL21vZHVsZXMvdXRpbHMnO1xuXG4vLyAvKiogQG1vZHVsZSBkM3NtICovXG52YXIgZDNzbSA9IHt9O1xuZDNzbS5heGlzID0gYXhpcztcbmQzc20uYmFyID0gYmFyO1xuZDNzbS5idWJibGVIZWF0bWFwID0gYnViYmxlSGVhdG1hcDtcbmQzc20uaGVhdG1hcCA9IGhlYXRtYXA7XG5kM3NtLmJveHdoaXNrZXIgPSBib3h3aGlza2VyO1xuZDNzbS5jb2xvckZ1bmN0aW9uID0gY29sb3JGdW5jdGlvbjtcbmQzc20uZGF0YXRvZ2dsZSA9IGRhdGF0b2dnbGU7XG5kM3NtLmdyb3VwaW5nU3BhY2VyID0gZ3JvdXBpbmdTcGFjZXI7XG5kM3NtLnRvb2x0aXAgPSB0b29sdGlwO1xuZDNzbS5zY2F0dGVyID0gc2NhdHRlcjtcbmQzc20ucGxvdFpvb20gPSBwbG90Wm9vbTtcbmQzc20ubXVsdGlQbG90Wm9vbSA9IG11bHRpUGxvdFpvb207XG5kM3NtLnZpb2xpbiA9IHZpb2xpbjtcbmQzc20ubnVtZXJpY0xlZ2VuZCA9IG51bWVyaWNMZWdlbmQ7XG5kM3NtLmNhdGVnb3JpY0xlZ2VuZCA9IGNhdGVnb3JpY0xlZ2VuZDtcbmQzc20ubGFzc28gPSBsYXNzbztcbmQzc20ubGFzc29XaWRnZXQgPSBsYXNzb1dpZGdldDtcbmQzc20uc2VsZWN0RmlsdGVyID0gc2VsZWN0RmlsdGVyO1xuZDNzbS51cHNldCA9IHVwc2V0O1xuZDNzbS5maWx0ZXJUYWJsZSA9IGZpbHRlclRhYmxlO1xuXG5kM3NtLnVuaXF1ZUVsZW1lbnRzID0gdW5pcXVlRWxlbWVudHM7XG5kM3NtLmdldFRyYW5zbGF0aW9uID0gZ2V0VHJhbnNsYXRpb247XG5kM3NtLm1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2UgPSBtb2RpZnlIZXhpZGVjaW1hbENvbG9yTHVtaW5hbmNlO1xuZDNzbS50aWNrUmFuZ2UgPSB0aWNrUmFuZ2U7XG5kM3NtLnF1YXJ0aWxlcyA9IHF1YXJ0aWxlcztcbmQzc20uZXh0cmFjdFZpb2xpblZhbHVlcyA9IGV4dHJhY3RWaW9saW5WYWx1ZXM7XG5kM3NtLmh5cGVuYXRlID0gaHlwZW5hdGU7XG5kM3NtLnJvdW5kID0gcm91bmQ7XG5kM3NtLmdldENvbnRhaW5pbmdTVkcgPSBnZXRDb250YWluaW5nU1ZHO1xuZDNzbS5pbnRlcnBvbGF0ZUNvbG9ycyA9IGludGVycG9sYXRlQ29sb3JzO1xuZDNzbS50cnVuY2F0ZVRleHQgPSB0cnVuY2F0ZVRleHQ7XG5kM3NtLnNhZmVTZWxlY3QgPSBzYWZlU2VsZWN0O1xuXG5kM3NtLndoaWNoQmluID0gd2hpY2hCaW47XG5kM3NtLnVuaXF1ZSA9IHVuaXF1ZTtcbmQzc20uZmxhdHRlbiA9IGZsYXR0ZW47XG5cbmQzc20uc2V0dXBTdGFuZGFyZENoYXJ0Q29udGFpbmVycyA9IHNldHVwU3RhbmRhcmRDaGFydENvbnRhaW5lcnM7XG5kM3NtLmxvZyA9IG15TG9nO1xuZDNzbS53YXJuID0gd2FybjtcbmQzc20uaW5mbyA9IGluZm87XG5kM3NtLmVycm9yID0gZXJyb3I7XG5kM3NtLmNvbnNvbGVHcm91cCA9IGNvbnNvbGVHcm91cDtcbmQzc20uY29uc29sZUdyb3VwRW5kID0gY29uc29sZUdyb3VwRW5kO1xuZDNzbS5yZXNpemVEZWJvdW5jZSA9IHJlc2l6ZURlYm91bmNlO1xuXG5kM3NtLmRlYnVnUSA9IGZhbHNlXG5cblxuXG4vLyBJbXBvcnQgYSBsb2dnZXIgZm9yIGVhc2llciBkZWJ1Z2dpbmdcbi8vIGltcG9ydCBkZWJ1ZyBmcm9tICdkZWJ1Zyc7XG4vLyBjb25zdCBsb2cgPSBkZWJ1ZygnYXBwOmxvZycpO1xuXG4vLyBUaGUgbG9nZ2VyIHNob3VsZCBvbmx5IGJlIGRpc2FibGVkIGlmIHdlJ3JlIG5vdCBpbiBwcm9kdWN0aW9uLlxuLy8gaWYgKEVOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4vLyAgIC8vIEVuYWJsZSB0aGUgbG9nZ2VyLlxuLy8gICBkZWJ1Zy5lbmFibGUoJyonKTtcbi8vICAgbG9nKCdMb2dnaW5nIGlzIGVuYWJsZWQhJyk7XG4vL1xuLy8gICAvLyBFbmFibGUgTGl2ZVJlbG9hZFxuLy8gICBkb2N1bWVudC53cml0ZShcbi8vICAgICAnPHNjcmlwdCBzcmM9XCJodHRwOi8vJ1xuLy8gICAgICsgKGxvY2F0aW9uLmhvc3QgfHwgJ2xvY2FsaG9zdCcpLnNwbGl0KCc6JylbMF1cbi8vICAgICArICc6MzU3MjkvbGl2ZXJlbG9hZC5qcz9zbmlwdmVyPTFcIj48Lydcbi8vICAgICArICdzY3JpcHQ+J1xuLy8gICApO1xuLy8gfSBlbHNlIHtcbi8vICAgZGVidWcuZGlzYWJsZSgpO1xuLy8gfVxuXG53aW5kb3cuZDNzbSA9IGQzc207XG5cbmV4cG9ydCBkZWZhdWx0IGQzc21cbiIsImltcG9ydCB7XG4gIGh5cGVuYXRlLCBzYWZlU2VsZWN0LCBleHRyYWN0VmlvbGluVmFsdWVzLFxuICB0aWNrUmFuZ2UsIG1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2UsIHRydW5jYXRlVGV4dCxcbiAgdHJ1bmNhdGVTdHJpbmcsXG4gIHJvdW5kXG59IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQge3NldHVwQ29udGFpbmVyLCBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0LCBjYWxjdWxhdGVXaWR0aE9mU3BhY2VyfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7dW5pcXVlLCBoYXNRLCBmbGF0dGVufSBmcm9tICcuL2FycmF5LWZ1bmN0aW9ucyc7XG5pbXBvcnQge2dyb3VwaW5nU3BhY2VyfSBmcm9tICcuL2dyb3VwaW5nLXNwYWNlcic7XG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBWElTICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXhpc1xuICpcbiAqIHtAbGluayBodHRwczovL3N1bW5ldXJvbi5naXRsYWIuaW8vZDNzbS9kZW1vcy9heGVzL2luZGV4Lmh0bWwgRGVtb31cbiAqIEBjb25zdHJ1Y3RvciBheGlzXG4gKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gc2VsZWN0aW9uXG4gKiBAbmFtZXNwYWNlIGF4aXNcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gYXhpc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYXhpcyAoIHNlbGVjdGlvbiApIHtcbiAgdmFyXG4gIC8qKlxuICAqIFRoZSBvcmllbnRhdGlvbiBvZiB0aGUgYXhpc1xuICAqIChzZWUge0BsaW5rIGF4aXMjb3JpZW50fSlcbiAgKiBAcGFyYW0ge3N0cmluZ30gW29yaWVudD0nYm90dG9tJ11cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb3JpZW50ID0gJ2JvdHRvbScsICAgICAgIC8vIGRpcmVjdGlvbiBvZiB0aGUgYXhpc1xuXG4gIC8qKlxuICAqIEFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSBheGlzIGluXG4gICogKHNlZSB7QGxpbmsgYXhpcyNzcGFjZVh9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbc3BhY2VYPTBdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNwYWNlWD0wLFxuICAvKipcbiAgKiBBbW91bnQgb2YgdmVydGljYWwgc3BhY2UgKGluIHBpeGVscykgYXZhaWJsZSB0byByZW5kZXIgdGhlIGF4aXMgaW5cbiAgKiAoc2VlIHtAbGluayBheGlzLnNwYWNlWX0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZVk9MF1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VZPTAsXG5cblxuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0byBhbGxvdyBheGlzIHRvIHJlbmRlciBlbGVtZW50cyBwYXNzIHRoZSBtYWluIHNwYXRpYWwgZGltZW5zaW9uXG4gICogZ2l2ZW4gdGhlIG9yaWVudGF0aW9uIChzZWUge0BsaW5rIGF4aXMjb3JpZW50fSksIHdoZXJlIHtAbGluayBheGlzI29yaWVudH09XCJib3R0b21cIiBvciB7QGxpbmsgYXhpcyNvcmllbnR9PVwidG9wXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGF4aXMjc3BhY2VYfSBhbmQgd2hlcmUge0BsaW5rIGF4aXMjb3JpZW50fT1cImxlZnRcIiBvciB7QGxpbmsgYXhpcyNvcmllbnR9PVwicmlnaHRcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgYXhpcyNzcGFjZVl9XG4gICogQHBhcmFtIHtib29sZWFufSBbb3ZlcmZsb3dRPWZhbHNlXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvdmVyZmxvd1EgPSBmYWxzZSwgICAgLy8gd2hldGhlciBvciBub3QgdG8gYWxsb3cgb3ZlcmZsb3dcbiAgLyoqXG4gICogV2hldGhlciBvciBub3QgdGhlIGF4aXMgbGFiZWxzIGFyZSBmb3IgY2F0ZWdvcmljYWwgZGF0YS4gSWYgZmFsc2UsXG4gICogd2lsbCB1c2Uge0BsaW5rIGF4aXMjc2NhbGV9IHRvIHBvc2l0aW9uIHRpY2tzLlxuICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2NhdGVnb3JpY2FsUT1mYWxzZV1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgY2F0ZWdvcmljYWxRID0gZmFsc2UsIC8vIHdoZXRoZXIgb3Igbm90IHRoZSBheGlzIGlzIHNob3dpbmcgdmFsdWVzIG9yIGdyb3Vwc1xuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0aGUgYXhpcyB0aWNrcyBzaG91bGQgaGF2ZSBndWlkZWxpbmVzXG4gICogQHBhcmFtIHtib29sZWFufSBbY2F0ZWdvcmljYWxRPWZhbHNlXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBndWlkZUxpbmVzUSA9IGZhbHNlLCAgICAvLyB3aGV0aGVyIG9yIG5vdCB0byBhbGxvdyBvdmVyZmxvd1xuXG5cbiAgLyoqXG4gICogSG93IHRvIGdyb3VwIHRoZSB0aWNrIGxhYmVsc1xuICAqIEBwYXJhbSB7QXJyYXlbXX0gW2dyb3VwaW5nPXVuZGVmaW5lZF0gbGlzdCBvZiBwdXRhdGl2ZWx5IG90aGVyIGxpc3RzLCB3aGljaCBzaG91bGQgY29ycmVzcG9uZCB0byB0aWNrTGFiZWxzXG4gICogd2lsbCBzcGFjZSB0aWNrIGxhYmVscyBpbiBuZXN0ZWQgbGlzdHMgY2xvc2VyIHRvZ2V0aGVyIHRoYW4gb3V0ZXIgbGlzdHNcbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZ3JvdXBpbmcsXG5cbiAgLyoqXG4gICogVGhlIHNjYWxlIGZvciB3aGljaCBub24tY2F0ZWdvcmlhbCAoc2VlIHtAbGluayBheGlzI2NhdGVnb3JpY2FsUX0pIHRpY2tzIHNob3VsZCBiZSBzcGFjZWRcbiAgKiBAcGFyYW0ge2QzLnNjYWxlfSBbc2NhbGU9ZDMuc2NhbGVMaW5lYXJdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG5cbiAgc2NhbGUgPSBkMy5zY2FsZUxpbmVhcigpLFxuICAvKipcbiAgKiBUaGUgcGFkZGluZyBmb3IgdGhlIGRvbWFpbiBvZiB0aGUgc2NhbGUgKHNlZSB7QGxpbmsgYXhpcyNzY2FsZX0pXG4gICogQHBhcmFtIHtkMy5zY2FsZX0gW3NjYWxlPWQzLnNjYWxlTGluZWFyXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBkb21haW5QYWRkaW5nID0gMC41LFxuXG5cbiAgLyoqXG4gICogRGVmYXVsdCBzcGFjZSBmb3IgdGhlIHNwYWNlciAocGVyY2VudGFnZSkgb2YgbWFpbiBkaW1lbnNpb24gZ2l2ZW4gdGhlIG9yaWVudGF0aW9uXG4gICogKHNlZSB7QGxpbmsgYXhpcyNvcmllbnR9KSwgd2hlcmUge0BsaW5rIGF4aXMjb3JpZW50fT1cImJvdHRvbVwiIG9yIHtAbGluayBheGlzI29yaWVudH09XCJ0b3BcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgYXhpcyNzcGFjZVh9IGFuZCB3aGVyZSB7QGxpbmsgYXhpcyNvcmllbnR9PVwibGVmdFwiIG9yIHtAbGluayBheGlzI29yaWVudH09XCJyaWdodFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayBheGlzI3NwYWNlWX1iZXR3ZWVuIHRpY2tzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtvYmplY3RTcGFjZXI9MC4wNV1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0U3BhY2VyID0gMC4wNSxcbiAgLyoqXG4gICogVGhlIG1pbmltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmUgaWYge0BsaW5rIGF4aXMjY2F0ZWdvcmljYWxRfSBpcyBzZXQgdG8gdHJ1ZVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbbWluT2JqZWN0U2l6ZT0xNV1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbWluT2JqZWN0U2l6ZSA9IDE1LFxuICAvKipcbiAgKiBUaGUgbWF4aW11bSBzaXplIHRoYXQgYW4gb2JqZWN0IGNhbiBiZSBpZiB7QGxpbmsgYXhpcyNjYXRlZ29yaWNhbFF9IGlzIHNldCB0byB0cnVlXG4gICogQHBhcmFtIHtudW1iZXJ9IFttYXhPYmplY3RTaXplPTE1XVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBtYXhPYmplY3RTaXplID0gNTAsXG5cbiAgLyoqXG4gICogQ29sb3Igb2YgdGhlIGJhY2tncm91bmRcbiAgKiBAcGFyYW0ge3N0cmluZ30gW2JhY2tncm91bmRGaWxsPVwidHJhbnNwYXJlbnRcIl1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgYmFja2dyb3VuZEZpbGwgPSAndHJhbnNwYXJlbnQnLFxuICAvKipcbiAgKiBOYW1lc3BhY2UgZm9yIGFsbCBpdGVtcyBtYWRlIGJ5IHRoaXMgaW5zdGFuY2Ugb2YgYXhpc1xuICAqIEBwYXJhbSB7c3RyaW5nfSBbbmFtZXNwYWNlPVwiZDNzbS1heGlzXCJdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG5hbWVzcGFjZSA9ICdkM3NtLWF4aXMnLFxuICAvKipcbiAgKiBDbGFzcyBuYW1lIGZvciB0aWNrIGNvbnRhaW5lciAoPGc+IGVsZW1lbnQpXG4gICogQHBhcmFtIHtzdHJpbmd9IFtvYmplY3RDbGFzcz1cInRpY2stZ3JvdXBcIl1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0Q2xhc3MgPSAndGljay1ncm91cCcsXG5cbiAgLyoqXG4gICogVmFsdWVzIHRvIHNob3cgYXQgZWFjaCB0aWNrLiBPbmx5IHVzZWQgaWYgY2F0ZWdvcmljYWxRIGlzIHNldCB0cnVlLiBTZWUge0BsaW5rIGF4aXMjY2F0ZWdvcmljYWxRfVxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt0aWNrTGFiZWxzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdGlja0xhYmVscywgICAvLyB3aGF0IHRvIHBsYWNlIGF0IHRpY2tzXG4gIC8qKlxuICAqIFZhbHVlcyB0byBzaG93IGF0IGVhY2ggdGljay4gT25seSB1c2VkIGlmIGNhdGVnb3JpY2FsUSBpcyBzZXQgZmFsc2UuIFNlZSB7QGxpbmsgYXhpcyNjYXRlZ29yaWNhbFF9XG4gICogQHBhcmFtIHtzdHJpbmdbXSB8IG51bWJlcltdfSBbb2JqZWN0Q2xhc3M9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0aWNrVmFsdWVzLCAgIC8vIHdoZXJlIHRvIHBsYWNlIHRpY2tzIGlmIG5vdFxuICAvKipcbiAgKiBOdW1iZXIgb2YgdGlja3MgdG8gZGlzcGxheSBpZiBjYXRlZ29yaWNhbFEgaXMgZmFsc2UuIFNlZSB7QGxpbmsgYXhpcyNjYXRlZ29yaWNhbFF9XG4gICogQHBhcmFtIHtudW1iZXJ9IFtudW1iZXJPZlRpY2tzPTVdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG51bWJlck9mVGlja3MgPSA1LFxuXG5cbiAgLyoqXG4gICogU3Ryb2tlIGNvbG9yIG9mIHRoZSBtYWluIGF4aXMgbGluZVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbbGluZVN0cm9rZT0nYmxhY2snXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBsaW5lU3Ryb2tlID0gJ2JsYWNrJyxcbiAgLyoqXG4gICogU3Ryb2tlIHdpZHRoIG9mIHRoZSBtYWluIGF4aXMgbGluZVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbbGluZVN0cm9rZVdpZHRoPTNdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGxpbmVTdHJva2VXaWR0aCA9IDMsXG5cblxuICAvKipcbiAgKiBTdHJva2UgY29sb3Igb2YgdGlja3NcbiAgKiBAcGFyYW0ge3N0cmluZ30gW3RpY2tTdHJva2U9J2JsYWNrJ11cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdGlja1N0cm9rZSA9ICdibGFjaycsXG4gIC8qKlxuICAqIFN0cm9rZSBudW1iZXIgb2YgdGlja3NcbiAgKiBAcGFyYW0ge3N0cmluZ30gW3RpY2tTdHJva2VXaWR0aD0yXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0aWNrU3Ryb2tlV2lkdGggPSAyLFxuICAvKipcbiAgKiBMZW5ndGggLSBpbiBwaXhlbHMgLSBvZiB0aWNrc1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbdGlja0xlbmd0aD0xMF1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdGlja0xlbmd0aCA9IDEwLFxuXG4gIHRpY2tUaWNrTGFiZWxTcGFjZXIgPSAxMCxcbiAgdGlja0xhYmVsTWFyZ2luID0gMTAsXG5cblxuICAvKipcbiAgKiBGb250IHNpemUgb2YgdGljayBsYWJlbHNcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RpY2tMYWJlbEZvbnRTaXplPTE0XVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0aWNrTGFiZWxGb250U2l6ZSA9IDE0LFxuICAvKipcbiAgKiBNaW4gZm9udCBzaXplIG9mIHRpY2sgbGFiZWxzXG4gICogQHBhcmFtIHtudW1iZXJ9IFt0aWNrTGFiZWxNaW5Gb250U2l6ZT04XVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0aWNrTGFiZWxNaW5Gb250U2l6ZSA9IDgsXG4gIC8qKlxuICAqIE1heCBmb250IHNpemUgb2YgdGljayBsYWJlbHNcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RpY2tMYWJlbE1heEZvbnRTaXplPTIwXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0aWNrTGFiZWxNYXhGb250U2l6ZSA9IDIwLFxuXG5cbiAgLyoqXG4gICogVGV4dCBhbmNob3Igb2YgdGljayBsYWJlbHNcbiAgKiBAcGFyYW0ge3N0cmluZ30gW3RpY2tMYWJlbFRleHRBbmNob3I9XCJtaWRkbGVcIl1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdGlja0xhYmVsVGV4dEFuY2hvcixcbiAgLyoqXG4gICogUm90YXRpb24gb2YgdGljayBsYWJlbHNcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RpY2tMYWJlbFJvdGF0aW9uPTBdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRpY2tMYWJlbFJvdGF0aW9uLFxuICAvKipcbiAgKiBPcHRpb25hbCBmdW5jdGlvbiBmb3IgZXh0cmFjdGluZyB0aGUgdGljayBsYWJlbCBmcm9tIGRhdGFcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbdGlja0xhYmVsRnVuYz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRpY2tMYWJlbEZ1bmMgPSB1bmRlZmluZWQsXG5cbiAgLyoqXG4gICogT3B0aW9uYWwgZnVuY3Rpb24gZm9yIHdoYXQgdG8gZG8gd2hlbiBsYWJlbCBpcyBjbGlja2VkXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3RpY2tMYWJlbE9uQ2xpY2s9ZnVuY3Rpb24oZCwgaSl7fV1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdGlja0xhYmVsT25DbGljayA9IGZ1bmN0aW9uKGQsIGkpe30sXG5cbiAgLyoqXG4gICogT3B0aW9uYWwgZnVuY3Rpb24gZm9yIHdoYXQgdG8gZG8gd2hlbiBsYWJlbCBpcyBob3ZlcmVkXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3RpY2tMYWJlbE9uSG92ZXJGdW5jPWZ1bmN0aW9uKGQsIGkpe31dXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRpY2tMYWJlbE9uSG92ZXJGdW5jID0gZnVuY3Rpb24oZCwgaSl7XG4gICAgcmV0dXJuIFN0cmluZyhkKS5yZXBsYWNlKCctJywgJyAnKS5yZXBsYWNlKCdfJywgJyAnKVxuICB9LFxuXG5cbiAgLyoqXG4gICogTGVuZ3RoIG9mIGd1aWRlbGluZXNcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbZ3VpZGVsaW5lU3BhY2U9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBndWlkZWxpbmVTcGFjZSxcbiAgLyoqXG4gICogU3Ryb2tlIGNvbG9yIG9mIGd1aWRsaW5lc1xuICAqIEBwYXJhbSB7c3RyaW5nfSBbZ3VpZGVsaW5lU3BhY2U9XCIjMzMzMzMzXCJdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGd1aWRlTGluZVN0cm9rZSA9ICcjMzMzMzMzJyxcbiAgLyoqXG4gICogU3Ryb2tlIHdpZHRoIG9mIGd1aWRsaW5lc1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbZ3VpZGVsaW5lU3BhY2U9Ml1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZ3VpZGVMaW5lU3Ryb2tlV2lkdGggPSAyLFxuXG4gIC8qKlxuICAqIER1cmF0aW9uIG9mIGFsbCB0cmFuc2l0aW9ucyBvZiB0aGlzIGVsZW1lbnRcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RyYW5zaXRpb25EdXJhdGlvbj0xMDAwXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwLFxuICAvKipcbiAgKiBFYXNpbmcgZnVuY3Rpb24gZm9yIHRyYW5zaXRpb25zXG4gICogQHBhcmFtIHtkMy5lYXNlfSBbZWFzZUZ1bmM9ZDMuZWFzZUV4cF1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwLFxuXG5cbiAgLyoqXG4gICogQ2xvc3VyZSB2YXJpYWJsZSBmb3IgZ2V0dGluZyBvYmplY3Qgc2l6ZSBhZnRlciBjYWxjdWxhdGlvblxuICAqIEBwYXJhbSB7bnVtYmVyfSBbb2JqZWN0U2l6ZT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdFNpemUsXG4gIC8qKlxuICAqIENsb3N1cmUgdmFyaWFibGUgZm9yIGdldHRpbmcgc3BhY2VyIHNpemUgYWZ0ZXIgY2FsY3VsYXRpb25cbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlclNpemU9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzcGFjZXJTaXplLFxuXG4gIC8qKlxuICAqIERlY2ltYWwgcGVyY2lzaW9uIHRvIHJvdW5kIG51bWVyaWNhbCB0aWNrIGxhYmVscyB0b1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbcm91bmRUbz0yXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICByb3VuZFRvID0gMixcblxuICBsYWJlbCxcblxuXG4gIHJldmVyc2VTY2FsZVEgPSBmYWxzZVxuXG4gIGF4aXMubGFiZWwgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGxhYmVsID0gXywgYXhpcykgOiBsYWJlbDsgfTtcbiAgYXhpcy50aWNrVGlja0xhYmVsU3BhY2VyID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0aWNrVGlja0xhYmVsU3BhY2VyID0gXywgYXhpcykgOiB0aWNrVGlja0xhYmVsU3BhY2VyOyB9O1xuICBheGlzLnRpY2tMYWJlbE1hcmdpbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja0xhYmVsTWFyZ2luID0gXywgYXhpcykgOiB0aWNrTGFiZWxNYXJnaW47IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHNlbGVjdGlvbiBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgZDMuc2VsZWN0aW9ufVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzZWxlY3Rpb24gPSBzZWxlY3Rpb25cbiAgICovXG5cbiAgYXhpcy5zZWxlY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNlbGVjdGlvbiA9IF8sIGF4aXMpIDogc2VsZWN0aW9uOyB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIG9yaWVudGF0aW9uIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBheGlzI29yaWVudH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXSBzaG91bGQgYmUgaG9yaXpvbnRhbCBvciB2ZXJ0aWNhbFxuICAgKiBAcmV0dXJucyB7YXhpcyB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3JpZW50PVwiYm90dG9tXCJcbiAgICovXG4gIGF4aXMub3JpZW50ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvcmllbnQgPSBfLCBheGlzKSA6IG9yaWVudDsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgYW1vdW50IG9mIGhvcml6b250YWwgc3BhY2UgaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIGF4aXMjc3BhY2VYfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge2F4aXMgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlWCA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYXhpcy5zcGFjZVggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWCA9IF8sIGF4aXMpIDogc3BhY2VYOyB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBhbW91bnQgb2YgdmVydGljYWwgc3BhY2UgaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIGF4aXMjc3BhY2VZfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge2F4aXMgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlWSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYXhpcy5zcGFjZVkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWSA9IF8sIGF4aXMpIDogc3BhY2VZOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IGF4aXMgaXMgYWxsb3dlZCB0byBnbyBiZXlvbmQgc3BlY2lmaWVkIGRpbWVuc2lvbnNcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNzcGFjZVh9KVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgYm9vbGVhbn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3ZlcmZsb3dRID0gZmFsc2VcbiAgICovXG4gIGF4aXMub3ZlcmZsb3dRID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvdmVyZmxvd1EgPSBfLCBheGlzKSA6IG92ZXJmbG93UTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IGF4aXMgd2lsbCBkaXNwbGF5IGNhdGVnb3JpYWwgdGlja3Mgb3IgYnkgbnVtZXJpY2FsIHZhbHVlXG4gICAqIChzZWUge0BsaW5rIGF4aXMjY2F0ZWdvcmljYWxRfSlcbiAgICogQHBhcmFtIHtib29sZWFufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IGJvb2xlYW59XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGNhdGVnb3JpY2FsUSA9IGZhbHNlXG4gICAqL1xuICBheGlzLmNhdGVnb3JpY2FsUSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY2F0ZWdvcmljYWxRID0gXywgYXhpcykgOiBjYXRlZ29yaWNhbFE7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB3aGV0aGVyIG9yIG5vdCBheGlzIHRpY2tzIHNob3VsZCBoYXZlIGd1aWRlbGluZXNcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNndWlkZUxpbmVzUX0pXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2F4aXMgfCBib29sZWFufVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBndWlkZUxpbmVzUSA9IGZhbHNlXG4gICAqL1xuICBheGlzLmd1aWRlTGluZXNRID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChndWlkZUxpbmVzUSA9IF8sIGF4aXMpIDogZ3VpZGVMaW5lc1E7IH07XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgaG93IHRpY2tzIHNob3VsZCBiZSBncm91cHBlZFxuICAgKiAoc2VlIHtAbGluayBheGlzI2dyb3VwaW5nfSlcbiAgICogQHBhcmFtIHtBcnJheVtdfSBbXz1ub25lXSBsaXN0IG9mIHB1dGF0aXZlbHkgb3RoZXIgbGlzdHMsIHdoaWNoIHNob3VsZCBjb3JyZXNwb25kIHRvIHRpY2tMYWJlbHNcbiAgICogd2lsbCBzcGFjZSB0aWNrIGxhYmVscyBpbiBuZXN0ZWQgbGlzdHMgY2xvc2VyIHRvZ2V0aGVyIHRoYW4gb3V0ZXIgbGlzdHNcbiAgICogQHJldHVybnMge2F4aXMgfCBBcnJheVtdfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBncm91cGluZyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYXhpcy5ncm91cGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZ3JvdXBpbmcgPSBfLCBheGlzKSA6IGdyb3VwaW5nOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzY2FsZSBmb3Igd2hpY2ggbm9uLWNhdGVnb3JpYWwgIHRpY2tzIHNob3VsZFxuICAgKiBiZSBzcGFjZWRcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNzY2FsZX0pXG4gICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgZDMuc2NhbGV9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNjYWxlID0gZDMuc2NhbGVMaW5lYXIoKVxuICAgKi9cbiAgYXhpcy5zY2FsZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGUgPSBfLCBheGlzKSA6IHNjYWxlOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHBhZGRpbmcgZm9yIHRoZSBkb21haW4gb2YgdGhlIHNjYWxlXG4gICAqIChzZWUge0BsaW5rIGF4aXMjZG9tYWluUGFkZGluZ30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZG9tYWluUGFkZGluZyA9IDAuNVxuICAgKi9cbiAgYXhpcy5kb21haW5QYWRkaW5nID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkb21haW5QYWRkaW5nID0gXywgYXhpcykgOiBkb21haW5QYWRkaW5nOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIG9iamVjdFNwYWNlclxuICAgKiAoc2VlIHtAbGluayBheGlzI29iamVjdFNwYWNlcn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0U3BhY2VyID0gMC4wNVxuICAgKi9cbiAgYXhpcy5vYmplY3RTcGFjZXIgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNwYWNlciA9IF8sIGF4aXMpIDogb2JqZWN0U3BhY2VyOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1pbk9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNtaW5PYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBtaW5PYmplY3RTaXplID0gMTVcbiAgICovXG4gIGF4aXMubWluT2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobWluT2JqZWN0U2l6ZSA9IF8sIGF4aXMpIDogbWluT2JqZWN0U2l6ZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBtYXhPYmplY3RTaXplXG4gICAqIChzZWUge0BsaW5rIGF4aXMjbWF4T2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbWF4T2JqZWN0U2l6ZSA9IDUwXG4gICAqL1xuICBheGlzLm1heE9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1heE9iamVjdFNpemUgPSBfLCBheGlzKSA6IG1heE9iamVjdFNpemU7IH07XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG5hbWVzcGFjZVxuICAgKiAoc2VlIHtAbGluayBheGlzI25hbWVzcGFjZX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbmFtZXNwYWNlID0gJ2Qzc20tYXhpcydcbiAgICovXG4gIGF4aXMubmFtZXNwYWNlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChuYW1lc3BhY2UgPSBfLCBheGlzKSA6IG5hbWVzcGFjZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBiYWNrZ3JvdW5kRmlsbFxuICAgKiAoc2VlIHtAbGluayBheGlzI2JhY2tncm91bmRGaWxsfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCdcbiAgICovXG4gIGF4aXMuYmFja2dyb3VuZEZpbGwgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJhY2tncm91bmRGaWxsID0gXywgYXhpcykgOiBiYWNrZ3JvdW5kRmlsbDsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RDbGFzc1xuICAgKiAoc2VlIHtAbGluayBheGlzI29iamVjdENsYXNzfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RDbGFzcyA9ICd0aWNrLWdyb3VwJ1xuICAgKi9cbiAgYXhpcy5vYmplY3RDbGFzcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q2xhc3MgPSBfLCBheGlzKSA6IG9iamVjdENsYXNzOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB0aWNrTGFiZWxzXG4gICAqIChzZWUge0BsaW5rIGF4aXMjdGlja0xhYmVsc30pXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgc3RyaW5nW119XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRpY2tMYWJlbHMgPSB1bmRlZmluZWRcbiAgICovXG4gIGF4aXMudGlja0xhYmVscyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja0xhYmVscyA9IF8sIGF4aXMpIDogdGlja0xhYmVsczsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB0aWNrVmFsdWVzXG4gICAqIChzZWUge0BsaW5rIGF4aXMjdGlja1ZhbHVlc30pXG4gICAqIEBwYXJhbSB7bnVtYmVyW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgbnVtYmVyW119XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRpY2tWYWx1ZXMgPSB1bmRlZmluZWRcbiAgICovXG4gIGF4aXMudGlja1ZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja1ZhbHVlcyA9IF8sIGF4aXMpIDogdGlja1ZhbHVlczsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB0aWNrVmFsdWVzXG4gICAqIChzZWUge0BsaW5rIGF4aXMjbnVtYmVyT2ZUaWNrc30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbnVtYmVyT2ZUaWNrcyA9IDVcbiAgICovXG4gIGF4aXMubnVtYmVyT2ZUaWNrcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobnVtYmVyT2ZUaWNrcyA9IF8sIGF4aXMpIDogbnVtYmVyT2ZUaWNrczsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbGluZVN0cm9rZVxuICAgKiAoc2VlIHtAbGluayBheGlzI2xpbmVTdHJva2V9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2F4aXMgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGxpbmVTdHJva2UgPSAnYmxhY2snXG4gICAqL1xuICBheGlzLmxpbmVTdHJva2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGxpbmVTdHJva2UgPSBfLCBheGlzKSA6IGxpbmVTdHJva2U7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbGluZVN0cm9rZVdpZHRoXG4gICAqIChzZWUge0BsaW5rIGF4aXMjbGluZVN0cm9rZVdpZHRofSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBsaW5lU3Ryb2tlV2lkdGggPSAzXG4gICAqL1xuICBheGlzLmxpbmVTdHJva2VXaWR0aCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobGluZVN0cm9rZVdpZHRoID0gXywgYXhpcykgOiBsaW5lU3Ryb2tlV2lkdGg7IH07XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRpY2tTdHJva2VcbiAgICogKHNlZSB7QGxpbmsgYXhpcyN0aWNrU3Ryb2tlfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0aWNrU3Ryb2tlID0gJ2JsYWNrJ1xuICAgKi9cbiAgYXhpcy50aWNrU3Ryb2tlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0aWNrU3Ryb2tlID0gXywgYXhpcykgOiB0aWNrU3Ryb2tlOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRpY2tTdHJva2VXaWR0aFxuICAgKiAoc2VlIHtAbGluayBheGlzI3RpY2tTdHJva2VXaWR0aH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdGlja1N0cm9rZVdpZHRoID0gMlxuICAgKi9cbiAgYXhpcy50aWNrU3Ryb2tlV2lkdGggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tTdHJva2VXaWR0aCA9IF8sIGF4aXMpIDogdGlja1N0cm9rZVdpZHRoOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRpY2tMZW5ndGhcbiAgICogKHNlZSB7QGxpbmsgYXhpcyN0aWNrTGVuZ3RofSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0aWNrTGVuZ3RoID0gMTBcbiAgICovXG4gIGF4aXMudGlja0xlbmd0aCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja0xlbmd0aCA9IF8sIGF4aXMpIDogdGlja0xlbmd0aDsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdGlja0xhYmVsRm9udFNpemVcbiAgICogKHNlZSB7QGxpbmsgYXhpcyN0aWNrTGFiZWxGb250U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdGlja0xhYmVsRm9udFNpemUgPSAxNFxuICAgKi9cbiAgYXhpcy50aWNrTGFiZWxGb250U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja0xhYmVsRm9udFNpemUgPSBfLCBheGlzKSA6IHRpY2tMYWJlbEZvbnRTaXplOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRpY2tMYWJlbE1pbkZvbnRTaXplXG4gICAqIChzZWUge0BsaW5rIGF4aXMjdGlja0xhYmVsTWluRm9udFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2F4aXMgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRpY2tMYWJlbE1pbkZvbnRTaXplID0gOFxuICAgKi9cbiAgYXhpcy50aWNrTGFiZWxNaW5Gb250U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja0xhYmVsTWluRm9udFNpemUgPSBfLCBheGlzKSA6IHRpY2tMYWJlbE1pbkZvbnRTaXplOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRpY2tMYWJlbE1heEZvbnRTaXplXG4gICAqIChzZWUge0BsaW5rIGF4aXMjdGlja0xhYmVsTWF4Rm9udFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2F4aXMgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRpY2tMYWJlbE1heEZvbnRTaXplID0gMjBcbiAgICovXG4gIGF4aXMudGlja0xhYmVsTWF4Rm9udFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tMYWJlbE1heEZvbnRTaXplID0gXywgYXhpcykgOiB0aWNrTGFiZWxNYXhGb250U2l6ZTt9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB0aWNrTGFiZWxUZXh0QW5jaG9yXG4gICAqIChzZWUge0BsaW5rIGF4aXMjdGlja0xhYmVsVGV4dEFuY2hvcn0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdGlja0xhYmVsVGV4dEFuY2hvciA9ICdjZW50ZXInXG4gICAqL1xuICBheGlzLnRpY2tMYWJlbFRleHRBbmNob3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tMYWJlbFRleHRBbmNob3IgPSBfLCBheGlzKSA6IHRpY2tMYWJlbFRleHRBbmNob3I7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdGlja0xhYmVsUm90YXRpb25cbiAgICogKHNlZSB7QGxpbmsgYXhpcyN0aWNrTGFiZWxSb3RhdGlvbn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdGlja0xhYmVsUm90YXRpb24gPSAwXG4gICAqL1xuICBheGlzLnRpY2tMYWJlbFJvdGF0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0aWNrTGFiZWxSb3RhdGlvbiA9IF8sIGF4aXMpIDogdGlja0xhYmVsUm90YXRpb247IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdGlja0xhYmVsRnVuY1xuICAgKiAoc2VlIHtAbGluayBheGlzI3RpY2tMYWJlbEZ1bmN9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0aWNrTGFiZWxGdW5jID0gdW5kZWZpbmVkXG4gICAqL1xuICBheGlzLnRpY2tMYWJlbEZ1bmMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tMYWJlbEZ1bmMgPSBfLCBheGlzKSA6IHRpY2tMYWJlbEZ1bmM7IH07XG5cblxuICAvKipcbiAgKiBHZXRzIC8gc2V0cyB0aGUgdGlja0xhYmVsT25DbGlja1xuICAqIChzZWUge0BsaW5rIGF4aXMjdGlja0xhYmVsT25DbGlja30pXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgKiBAcmV0dXJucyB7YXhpcyB8IGZ1bmN0aW9ufVxuICAqIEBtZW1iZXJvZiBheGlzXG4gICogQHByb3BlcnR5XG4gICovXG4gIGF4aXMudGlja0xhYmVsT25DbGljayA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja0xhYmVsT25DbGljayA9IF8sIGF4aXMpIDogdGlja0xhYmVsT25DbGljazsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgZ3VpZGVsaW5lU3BhY2VcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNndWlkZWxpbmVTcGFjZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZ3VpZGVsaW5lU3BhY2UgPSB1bmRlZmluZWRcbiAgICovXG4gIGF4aXMuZ3VpZGVsaW5lU3BhY2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGd1aWRlbGluZVNwYWNlID0gXywgYXhpcykgOiBndWlkZWxpbmVTcGFjZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBndWlkZUxpbmVTdHJva2VcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNndWlkZUxpbmVTdHJva2V9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2F4aXMgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGd1aWRlTGluZVN0cm9rZSA9IFwiIzMzMzMzM1wiXG4gICAqL1xuICBheGlzLmd1aWRlTGluZVN0cm9rZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZ3VpZGVMaW5lU3Ryb2tlID0gXywgYXhpcykgOiBndWlkZUxpbmVTdHJva2U7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgZ3VpZGVMaW5lU3Ryb2tlV2lkdGhcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNndWlkZUxpbmVTdHJva2VXaWR0aH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZ3VpZGVMaW5lU3Ryb2tlV2lkdGggPSAyXG4gICAqL1xuICBheGlzLmd1aWRlTGluZVN0cm9rZVdpZHRoID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChndWlkZUxpbmVTdHJva2VXaWR0aCA9IF8sIGF4aXMpIDogZ3VpZGVMaW5lU3Ryb2tlV2lkdGg7IH07XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRyYW5zaXRpb25EdXJhdGlvblxuICAgKiAoc2VlIHtAbGluayBheGlzI3RyYW5zaXRpb25EdXJhdGlvbn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdHJhbnNpdGlvbkR1cmF0aW9uID0gMTAwMFxuICAgKi9cbiAgYXhpcy50cmFuc2l0aW9uRHVyYXRpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRyYW5zaXRpb25EdXJhdGlvbiA9IF8sIGF4aXMpIDogdHJhbnNpdGlvbkR1cmF0aW9uOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGVhc2VGdW5jXG4gICAqIChzZWUge0BsaW5rIGF4aXMjZWFzZUZ1bmN9KVxuICAgKiBAcGFyYW0ge2QzLmVhc2V9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgZDMuZWFzZX1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwXG4gICAqL1xuICBheGlzLmVhc2VGdW5jID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChlYXNlRnVuYyA9IF8sIGF4aXMpIDogZWFzZUZ1bmM7IH07XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNvYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RTaXplID0gdW5kZWZpbmVkXG4gICAqL1xuICBheGlzLm9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNpemUgPSBfLCBheGlzKSA6IG9iamVjdFNpemU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgc3BhY2VyU2l6ZVxuICAgKiAoc2VlIHtAbGluayBheGlzI3NwYWNlclNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2F4aXMgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlclNpemUgPSB1bmRlZmluZWRcbiAgICovXG4gIGF4aXMuc3BhY2VyU2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3BhY2VyU2l6ZSA9IF8sIGF4aXMpIDogc3BhY2VyU2l6ZTsgfTtcblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHJvdW5kVG9cbiAgICogKHNlZSB7QGxpbmsgYXhpcyNyb3VuZFRvfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCByb3VuZFRvID0gMlxuICAgKi9cbiAgIGF4aXMucm91bmRUbyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocm91bmRUbyA9IF8sIGF4aXMpIDogcm91bmRUbzsgfTtcbiAgIGF4aXMucmV2ZXJzZVNjYWxlUSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocmV2ZXJzZVNjYWxlUSA9IF8sIGF4aXMpIDogcmV2ZXJzZVNjYWxlUTsgfTtcblxuXG4gICBheGlzLnRpY2tMYWJlbE9uSG92ZXJGdW5jID0gZnVuY3Rpb24oXykge3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tMYWJlbE9uSG92ZXJGdW5jID0gXywgYXhpcykgOiB0aWNrTGFiZWxPbkhvdmVyRnVuYzsgfTtcblxuXG4gIGZ1bmN0aW9uIGF4aXMgKCkge1xuICAgIC8vIGZvciBjb252ZW5pZW5jZSBpbiBoYW5kbGluZyBvcmllbnRhdGlvbiBzcGVjaWZpYyB2YWx1ZXNcbiAgICB2YXIgaG9yaXpvbnRhbFEgPSBoYXNRKFsndG9wJywgJ2JvdHRvbScsICdob3Jpem9udGFsJ10sIG9yaWVudCkgPyB0cnVlIDogZmFsc2VcbiAgICB2YXIgdmVydGljYWxRID0gIWhvcml6b250YWxRXG5cbiAgICAvLyBiYWNrZ3JvdW5kIGNsaXBpbmcgcmVjdGFuZ2xlXG4gICAgdmFyIGJnY3BSZWN0ID0ge3g6MCwgeTowLCB3aWR0aDogc3BhY2VYLCBoZWlnaHQ6c3BhY2VZfVxuICAgIC8vIG1vZGlmeSB0aGUgcmVjdCBiYXNlZCBvbiBheGlzIG9yaWVudGF0aW9uXG4gICAgaWYgKG9yaWVudCA9PSBcImxlZnRcIikge1xuICAgICAgYmdjcFJlY3QueCAtPSBzcGFjZVg7XG4gICAgICBpZihndWlkZUxpbmVzUSkgeyBiZ2NwUmVjdC53aWR0aCArPSBndWlkZWxpbmVTcGFjZSB9O1xuICAgICAgLyogdGhlc2UgdHdvIGxpbmVzIGluY3JlYXNlIHRoZSBjbGlwcGluZyByZWN0IHRvIGFsbG93IGZvciB0ZXh0IGF0IHRoZSBlZGdlIG9mIHRoZSBheGlzICovXG4gICAgICBiZ2NwUmVjdC55IC09IHRpY2tMYWJlbE1heEZvbnRTaXplO1xuICAgICAgYmdjcFJlY3QuaGVpZ2h0ICs9IDIqdGlja0xhYmVsTWF4Rm9udFNpemVcbiAgICB9XG4gICAgaWYgKG9yaWVudCA9PSBcImJvdHRvbVwiKXtcbiAgICAgIGJnY3BSZWN0LnkgPSBiZ2NwUmVjdC55O1xuICAgICAgaWYoZ3VpZGVMaW5lc1EpIHsgYmdjcFJlY3QueSAtPSBndWlkZWxpbmVTcGFjZTsgYmdjcFJlY3QuaGVpZ2h0ICs9IGd1aWRlbGluZVNwYWNlOyB9O1xuICAgICAgLyogdGhlc2UgdHdvIGxpbmVzIGluY3JlYXNlIHRoZSBjbGlwcGluZyByZWN0IHRvIGFsbG93IGZvciB0ZXh0IGF0IHRoZSBlZGdlIG9mIHRoZSBheGlzICovXG4gICAgICBiZ2NwUmVjdC54IC09IHRpY2tMYWJlbE1heEZvbnRTaXplO1xuICAgICAgYmdjcFJlY3Qud2lkdGggKz0gMip0aWNrTGFiZWxNYXhGb250U2l6ZVxuICAgIH1cbiAgICBpZiAob3JpZW50ID09IFwidG9wXCIpIHtcbiAgICAgIGJnY3BSZWN0LnkgLT0gc3BhY2VZO1xuICAgICAgaWYoZ3VpZGVMaW5lc1EpIHsgYmdjcFJlY3QuaGVpZ2h0ICs9IGd1aWRlbGluZVNwYWNlIH07XG4gICAgICAvKiB0aGVzZSB0d28gbGluZXMgaW5jcmVhc2UgdGhlIGNsaXBwaW5nIHJlY3QgdG8gYWxsb3cgZm9yIHRleHQgYXQgdGhlIGVkZ2Ugb2YgdGhlIGF4aXMgKi9cbiAgICAgIGJnY3BSZWN0LnkgLT0gdGlja0xhYmVsTWF4Rm9udFNpemU7XG4gICAgICBiZ2NwUmVjdC5oZWlnaHQgKz0gMip0aWNrTGFiZWxNYXhGb250U2l6ZVxuICAgIH1cbiAgICBpZiAob3JpZW50ID09IFwicmlnaHRcIikgeyBiZ2NwUmVjdC54ID0gMDtcbiAgICAgIGlmKGd1aWRlTGluZXNRKSB7IGJnY3BSZWN0LndpZHRoICs9IGd1aWRlbGluZVNwYWNlOyBiZ2NwUmVjdC54IC09IGd1aWRlbGluZVNwYWNlIH07XG4gICAgICAvKiB0aGVzZSB0d28gbGluZXMgaW5jcmVhc2UgdGhlIGNsaXBwaW5nIHJlY3QgdG8gYWxsb3cgZm9yIHRleHQgYXQgdGhlIGVkZ2Ugb2YgdGhlIGF4aXMgKi9cbiAgICAgIGJnY3BSZWN0LnkgLT0gdGlja0xhYmVsTWF4Rm9udFNpemU7XG4gICAgICBiZ2NwUmVjdC5oZWlnaHQgKz0gMip0aWNrTGFiZWxNYXhGb250U2l6ZVxuICAgIH1cblxuXG4gICAgdmFyIGNvbnRhaW5lciA9IHNldHVwQ29udGFpbmVyKCBzZWxlY3Rpb24sIG5hbWVzcGFjZSwgYmdjcFJlY3QsIGJhY2tncm91bmRGaWxsICk7XG5cbiAgICAvLyBkZWZhdWx0cyBmb3IgdGV4dC1hbmNob3IgYW5kIHRleHQgcm90YXRpb25cbiAgICBpZiAob3JpZW50ID09ICd0b3AnKSB7XG4gICAgICB0aWNrTGFiZWxUZXh0QW5jaG9yID0gdGlja0xhYmVsVGV4dEFuY2hvciA9PSB1bmRlZmluZWQgPyAnc3RhcnQnIDogdGlja0xhYmVsVGV4dEFuY2hvclxuICAgICAgdGlja0xhYmVsUm90YXRpb24gPSB0aWNrTGFiZWxSb3RhdGlvbiA9PSB1bmRlZmluZWQgPyAtOTAgOiB0aWNrTGFiZWxSb3RhdGlvblxuICAgIH1cbiAgICBpZiAob3JpZW50ID09ICdib3R0b20nKSB7XG4gICAgICB0aWNrTGFiZWxUZXh0QW5jaG9yID0gdGlja0xhYmVsVGV4dEFuY2hvciA9PSB1bmRlZmluZWQgPyAnZW5kJyA6IHRpY2tMYWJlbFRleHRBbmNob3JcbiAgICAgIHRpY2tMYWJlbFJvdGF0aW9uID0gdGlja0xhYmVsUm90YXRpb24gPT0gdW5kZWZpbmVkID8gLTkwIDogdGlja0xhYmVsUm90YXRpb25cbiAgICB9XG4gICAgaWYgKG9yaWVudCA9PSAnbGVmdCcpIHtcbiAgICAgIHRpY2tMYWJlbFRleHRBbmNob3IgPSB0aWNrTGFiZWxUZXh0QW5jaG9yID09IHVuZGVmaW5lZCA/ICdlbmQnIDogdGlja0xhYmVsVGV4dEFuY2hvclxuICAgICAgdGlja0xhYmVsUm90YXRpb24gPSB0aWNrTGFiZWxSb3RhdGlvbiA9PSB1bmRlZmluZWQgPyAwIDogdGlja0xhYmVsUm90YXRpb25cbiAgICB9XG4gICAgaWYgKG9yaWVudCA9PSAncmlnaHQnKSB7XG4gICAgICB0aWNrTGFiZWxUZXh0QW5jaG9yID0gdGlja0xhYmVsVGV4dEFuY2hvciA9PSB1bmRlZmluZWQgPyAnc3RhcnQnIDogdGlja0xhYmVsVGV4dEFuY2hvclxuICAgICAgdGlja0xhYmVsUm90YXRpb24gPSB0aWNrTGFiZWxSb3RhdGlvbiA9PSB1bmRlZmluZWQgPyAwIDogdGlja0xhYmVsUm90YXRpb25cbiAgICB9XG5cbiAgICAvKlxuICAgIElmIGNhdGVnb3JpY2FsOlxuICAgICAgLT4gdXNlIGdyb3VwaW5nIGlmIGRlZmluZWQsXG4gICAgICAtPiBlbHNlIHVzZSB0aGUgbGFiZWxzIHByb3ZpZGVkXG4gICAgZWxzZTpcbiAgICAgIGlmIGdyb3VwaW5nIHVuZGVmaW5lZFxuICAgICAgICBhbmQgbm8gc3BlY2lmaWVkIG51bWJlciBvZiB0aWNrZXNcbiAgICAgICAgICAtPiBtYWtlIG51bWJlck9mVGljayB0aWNrc1xuICAgICAgICAgIC0+IGVsc2UgdXNlIHByb3ZpZGVkIHRpY2sgdmFsdWVzXG4gICAgICAgIC0+IHVzZSBncm91cGluZ1xuICAgICovXG4gICAgdmFyIHRpY2tEYXRhID0gY2F0ZWdvcmljYWxRXG4gICAgPyAoZ3JvdXBpbmcgPT0gdW5kZWZpbmVkKVxuICAgICAgPyB0aWNrTGFiZWxzXG4gICAgICA6IGdyb3VwaW5nXG4gICAgOiAoZ3JvdXBpbmcgPT0gdW5kZWZpbmVkKVxuICAgICAgPyAobnVtYmVyT2ZUaWNrcyAhPSB1bmRlZmluZWQpXG4gICAgICAvLyA/ICh0aWNrVmFsdWVzLmxlbmd0aCA8IG51bWJlck9mVGlja3MpXG4gICAgICAgID8gKHRpY2tSYW5nZSguLi5kMy5leHRlbnQodGlja1ZhbHVlcyksIG51bWJlck9mVGlja3MpKVxuICAgICAgICA6IHRpY2tWYWx1ZXNcbiAgICAgIDogZ3JvdXBpbmdcblxuXG4gICAgdmFyIGZsYXRUaWNrRGF0YSA9IGZsYXR0ZW4odGlja0RhdGEpXG4gICAgdmFyIG51bWJlck9mT2JqZWN0cyA9IGZsYXRUaWNrRGF0YS5sZW5ndGhcbiAgICB2YXIgc3BhY2UgPSBob3Jpem9udGFsUSA/IHNwYWNlWCA6IHNwYWNlWVxuICAgIHZhciBleHRlbnQgPSBkMy5leHRlbnQoZmxhdFRpY2tEYXRhKVxuXG5cbiAgICBpZiAocmV2ZXJzZVNjYWxlUSkge2V4dGVudC5yZXZlcnNlKCl9XG4gICAgdmFyIGRvbWFpbiA9IHJldmVyc2VTY2FsZVFcbiAgICA/IFtleHRlbnRbMF0gKyBkb21haW5QYWRkaW5nLCBleHRlbnRbMV0gLSBkb21haW5QYWRkaW5nXVxuICAgIDogW2V4dGVudFswXSAtIGRvbWFpblBhZGRpbmcsIGV4dGVudFsxXSArIGRvbWFpblBhZGRpbmddXG5cbiAgICBzY2FsZVxuICAgIC5kb21haW4oZG9tYWluKVxuICAgIC5yYW5nZShbaG9yaXpvbnRhbFEgPyAwIDogc3BhY2VZLCBob3Jpem9udGFsUSA/IHNwYWNlWCA6IDBdKVxuXG5cbiAgICAvKlxuICAgIFNjYWxlcyBhcmUgYmFzZWQgb24gdGhlIHZhbHVlcyBvZiB0aGUgY2hhcnQgYW5kIGNvcnJlc3BvbmQgdG8gdGhlIHNwYWNpbmdzIG9mIHRoZVxuICAgIGNoYXJ0LiBJZiB0aGUgY2hhcnQgaGFzIGFscmVhZHkgYmVlbiByZW5kZXJlZCwgdGhlc2UgdmFsdWVzIChleHBlbnNpdmUgdG8gY2FsdWNsYXRlKSBjYW5cbiAgICBiZSBwYXNzZWQgdG8gYXhpcyB0byBwcmV2ZW50IHJlY2FsY3VsYXRpb24uXG4gICAgKi9cblxuICAgIC8vIGNhbGN1bGF0ZSBvYmplY3Qgc2l6ZSBpZiBuZWVkZWRcbiAgICBvYmplY3RTaXplID0gKG9iamVjdFNpemUgPT0gdW5kZWZpbmVkKVxuICAgID8gY2FsY3VsYXRlV2lkdGhPZk9iamVjdChzcGFjZSwgbnVtYmVyT2ZPYmplY3RzLCBtaW5PYmplY3RTaXplLCBtYXhPYmplY3RTaXplLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICA6IG9iamVjdFNpemVcblxuICAgIC8vIGNhbGN1bGF0ZSBzcGFjZXIgc2l6ZSBpZiBuZWVkZWRcbiAgICBzcGFjZXJTaXplID0gKHNwYWNlclNpemUgPT0gdW5kZWZpbmVkKVxuICAgID8gY2FsY3VsYXRlV2lkdGhPZlNwYWNlcihmbGF0VGlja0RhdGEsIHNwYWNlLCBvYmplY3RTaXplLCBudW1iZXJPZk9iamVjdHMsIG9iamVjdFNwYWNlciwgb3ZlcmZsb3dRKVxuICAgIDogc3BhY2VyU2l6ZVxuXG5cbiAgICB2YXIgb2JqQ2xhc3MgPSBoeXBlbmF0ZShuYW1lc3BhY2UsIGNhdGVnb3JpY2FsUSA/IG9iamVjdENsYXNzKyctY2F0ZWdvcmljYWwnIDogb2JqZWN0Q2xhc3MpXG5cbiAgICB2YXIgc3BhY2VyRnVuY3Rpb24gPSBncm91cGluZ1NwYWNlcigpXG4gICAgLmhvcml6b250YWxRKGhvcml6b250YWxRKS5zY2FsZShzY2FsZSkubW92ZWJ5KChjYXRlZ29yaWNhbFE/J2NhdGVnb3J5Jzonc2NhbGUnKSkubnVtYmVyT2ZPYmplY3RzKG51bWJlck9mT2JqZWN0cylcbiAgICAub2JqZWN0Q2xhc3Mob2JqQ2xhc3MpLm9iamVjdFNpemUob2JqZWN0U2l6ZSkuc3BhY2VyU2l6ZShzcGFjZXJTaXplKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlRnVuYyhlYXNlRnVuYylcbiAgICAubmFtZXNwYWNlKG5hbWVzcGFjZSlcblxuICAgIHZhciB0aWNrRW50ZXJBbmltYXRpb24gPSBmdW5jdGlvbihzZWwpe1xuICAgICAgdmFyIG10ID0gc2NhbGUoc2VsLmRhdHVtKCkpLFxuICAgICAgZGlzdCA9IHNjYWxlKGV4dGVudFsxXSkgKiAyLFxuICAgICAgayA9IChtdCA8IGV4dGVudFsxXSAvIDIpID8gMSA6IC0xXG4gICAgICBrID0gaG9yaXpvbnRhbFEgPyBrICogLTEgOiBrXG4gICAgICBzZWwuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24gKGQsIGkpIHtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBob3Jpem9udGFsUSA/ICBkaXN0ICogayA6IDAsXG4gICAgICAgIHkgPSAhaG9yaXpvbnRhbFEgPyBkaXN0ICogayA6IDAsXG4gICAgICAgIHQgPSAndHJhbnNsYXRlKCcreCsnLCcreSsnKSdcbiAgICAgICAgcmV0dXJuIHRcbiAgICAgIH0pXG4gICAgfVxuICAgIHZhciB0aWNrRXhpdEFuaW1hdGlvbiA9IGZ1bmN0aW9uKHNlbCkge1xuICAgICAgdmFyIG10ID0gc2NhbGUoc2VsLmRhdHVtKCkpLFxuICAgICAgZGlzdCA9IHNjYWxlKGV4dGVudFsxXSkgKiAyLFxuICAgICAgayA9IChtdCA8IGV4dGVudFsxXSAvIDIpID8gMSA6IC0xXG4gICAgICBrID0gaG9yaXpvbnRhbFEgPyBrICogLTEgOiBrXG4gICAgICBzZWwudHJhbnNpdGlvbigpLmR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbikuZWFzZShlYXNlRnVuYylcbiAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDApXG4gICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24gKGQsIGkpIHtcbiAgICAgICAgdmFyXG5cbiAgICAgICAgeCA9IGhvcml6b250YWxRID8gIGRpc3QgKiBrICA6IDAsXG4gICAgICAgIHkgPSAhaG9yaXpvbnRhbFEgPyBkaXN0ICogayA6IDAsXG4gICAgICAgIHQgPSAndHJhbnNsYXRlKCcreCsnLCcreSsnKSdcbiAgICAgICAgcmV0dXJuIHRcbiAgICAgIH0pLnJlbW92ZSgpXG4gICAgfVxuXG4gICAgaWYgKCFjYXRlZ29yaWNhbFEpe1xuICAgICAgc3BhY2VyRnVuY3Rpb24uZW50ZXJGdW5jdGlvbih0aWNrRW50ZXJBbmltYXRpb24pXG4gICAgICBzcGFjZXJGdW5jdGlvbi5leGl0RnVuY3Rpb24odGlja0V4aXRBbmltYXRpb24pXG4gICAgfVxuXG4gICAgLy8gbW92ZSB0aWNrIGNvbnRhaW5lcnNcbiAgICBzcGFjZXJGdW5jdGlvbihjb250YWluZXIsIHRpY2tEYXRhLCAwKVxuXG4gICAgLy8gbW92ZSBieSBmb3IgeCBhbmQgeSBuZWVkZWQgdG8gY2VudGVyIGNhdGVnb3JpY2FsIHRpY2tzLCBsYWJlbHMsIGFuZCBndWlkZWxpbmVzXG4gICAgZnVuY3Rpb24gbW92ZVhCeShkLCBpLCBob3Jpem9udGFsUSwgY2F0ZWdvcmljYWxRLCBvYmplY3RTaXplKXtcbiAgICAgIHJldHVybiAoaG9yaXpvbnRhbFEpXG4gICAgICA/IChjYXRlZ29yaWNhbFEpXG4gICAgICAgID8gb2JqZWN0U2l6ZSAvIDJcbiAgICAgICAgOiAwXG4gICAgICA6IDBcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb3ZlWUJ5KGQsIGksIHZlcnRpY2FsUSwgY2F0ZWdvcmljYWxRLCBvYmplY3RTaXplKXtcbiAgICAgIHJldHVybiAodmVydGljYWxRKVxuICAgICAgPyAoY2F0ZWdvcmljYWxRKVxuICAgICAgICA/IG9iamVjdFNpemUgLyAyXG4gICAgICAgIDogMFxuICAgICAgOiAwXG4gICAgfVxuXG5cblxuICAgIHZhciBsYWJlbE5hbWVHcm91cCA9IHNhZmVTZWxlY3Qoc2VsZWN0aW9uLCAnZycsIGh5cGVuYXRlKG5hbWVzcGFjZSwnYXhpcy1uYW1lJykpXG5cblxuXG4gICAgdmFyIGxhYmVsRWxlbWVudCA9IHNhZmVTZWxlY3QobGFiZWxOYW1lR3JvdXAsICd0ZXh0JywgaHlwZW5hdGUobmFtZXNwYWNlLCAnbmFtZScpKVxuICAgIGlmIChsYWJlbEVsZW1lbnQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICBsYWJlbEVsZW1lbnQudGV4dChsYWJlbClcblxuICAgICAgaWYgKG9yaWVudCA9PSAnbGVmdCcgfHwgb3JpZW50ID09ICdyaWdodCcpIHtcbiAgICAgICAgbGFiZWxFbGVtZW50LmF0dHIoJ3RyYW5zZm9ybScsICdyb3RhdGUoLTkwKScpXG4gICAgICB9XG5cbiAgICAgIHZhciBiYm94ID0gbGFiZWxFbGVtZW50Lm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVxuICAgICAgbGFiZWxOYW1lR3JvdXAuYXR0cigndHJhbnNmb3JtJyxmdW5jdGlvbihkLCBpKXtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSAwLFxuICAgICAgICB5ID0gMCxcbiAgICAgICAgdFxuXG4gICAgICAgIGlmIChvcmllbnQgPT0gJ2JvdHRvbScpIHtcbiAgICAgICAgICB4ID0gc3BhY2VYIC0gYmJveC53aWR0aCAtIHRpY2tMYWJlbE1hcmdpblxuICAgICAgICAgIHkgPSAtIHRpY2tUaWNrTGFiZWxTcGFjZXJcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChvcmllbnQgPT0gJ3RvcCcpIHtcbiAgICAgICAgICB4ID0gc3BhY2VYIC0gYmJveC53aWR0aCAtIHRpY2tMYWJlbE1hcmdpblxuICAgICAgICAgIHggPSB0aWNrTGFiZWxNYXJnaW5cbiAgICAgICAgICB5ID0gYmJveC5oZWlnaHQgKyB0aWNrVGlja0xhYmVsU3BhY2VyXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob3JpZW50ID09ICdsZWZ0Jykge1xuICAgICAgICAgIHggPSBiYm94LndpZHRoICsgdGlja1RpY2tMYWJlbFNwYWNlclxuICAgICAgICAgIHkgPSBiYm94LmhlaWdodCArIHRpY2tMYWJlbE1hcmdpblxuICAgICAgICB9IGVsc2UgaWYgKG9yaWVudCA9PSAncmlnaHQnKSB7XG4gICAgICAgICAgeCA9IC0oYmJveC53aWR0aCArIHRpY2tUaWNrTGFiZWxTcGFjZXIpXG4gICAgICAgICAgeSA9IGJib3guaGVpZ2h0ICsgdGlja0xhYmVsTWFyZ2luXG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgfVxuICAgICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICAgICAgIHJldHVybiB0XG4gICAgICB9KVxuXG5cblxuICAgIH0gZWxzZSB7XG4gICAgICBsYWJlbEVsZW1lbnQucmVtb3ZlKClcbiAgICB9XG4gICAgLypcbiAgICBJZGVhIGZyb20gU3RhY2sgT3ZlcmZsb3dcbiAgICBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy81MDU3OTUzNS9kMy1qcy12NC10cnVuY2F0ZS10ZXh0LXRvLWZpdC1pbi1maXhlZC1zcGFjZS81MDU4NTAyMj9ub3JlZGlyZWN0PTEjY29tbWVudDg4MjM1NTYyXzUwNTg1MDIyXG4gICAgdG8gdXNlIGNsaXAgcGF0aCB0byBtYWtlIHRoaW5ncyBmaXQgaW4gZml4ZWQgc2l6ZS4gSGF2ZSB5ZXQgZ290IHRoaXMgdG8gd29yayBuaWNlbHkuXG4gICAgKi9cbiAgICAvLyB2YXIgZGVmcyA9IGQzLnNlbGVjdChjb250YWluZXIubm9kZSgpLnBhcmVudE5vZGUpLnNlbGVjdCgnZGVmcycpXG4gICAgLy8gdmFyIHRpY2tMYWJlbENsaXBQYXRoID0gc2FmZVNlbGVjdChkZWZzLCAnY2xpcFBhdGgnLCBoeXBlbmF0ZShuYW1lc3BhY2UsJ3RpY2stbGFiZWwtY2xpcC1wYXRoJykpLmF0dHIoJ2lkJywgIGh5cGVuYXRlKG5hbWVzcGFjZSwndGljay1sYWJlbC1jbGlwLXBhdGgnKSlcbiAgICAvLyB2YXIgdGlja0xhYmVsQ2xpcFBhdGhSZWN0ID0gc2FmZVNlbGVjdCh0aWNrTGFiZWxDbGlwUGF0aCwgJ3JlY3QnLCAgaHlwZW5hdGUobmFtZXNwYWNlLCd0aWNrLWxhYmVsLWNsaXAtcGF0aC1yZWN0JykpXG4gICAgLy8gLmF0dHIoJ3gnLCAwKVxuICAgIC8vIC5hdHRyKCd5JywgMClcbiAgICAvLyAuYXR0cignd2lkdGgnLCBmdW5jdGlvbihkLCBpKXtcbiAgICAvLyAgIGlmIChob3Jpem9udGFsUSkgeyByZXR1cm4gdGlja0xhYmVsRm9udFNpemUgfVxuICAgIC8vICAgaWYgKHZlcnRpY2FsUSkgeyByZXR1cm4gc3BhY2VYIC0gdGlja0xlbmd0aCB9XG4gICAgLy8gfSlcbiAgICAvLyAuYXR0cignaGVpZ2h0JywgZnVuY3Rpb24oZCwgaSl7XG4gICAgLy8gICBpZiAodmVydGljYWxRKSB7IHJldHVybiB0aWNrTGFiZWxGb250U2l6ZSB9XG4gICAgLy8gICBpZiAoaG9yaXpvbnRhbFEpIHsgcmV0dXJuIHNwYWNlWSAtIHRpY2tMZW5ndGggfVxuICAgIC8vIH0pXG5cblxuICAgIC8vIGZvciBlYWNoIHRpY2sgY29udGFpbmVyXG4gICAgdmFyIHRpY2tzID0gY29udGFpbmVyLnNlbGVjdEFsbCgnZzpub3QoLnRvLXJlbW92ZSkuJytvYmpDbGFzcykuZWFjaChmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhciB0aGF0ID0gZDMuc2VsZWN0KHRoaXMpLnN0eWxlKCdvcGFjaXR5JywgMSlcblxuICAgICAgLy8gbWFrZSBhbmQgbW92ZSB0aWNrXG4gICAgICB2YXIgdGljayA9IHNhZmVTZWxlY3QodGhhdCwgJ2xpbmUnLCBoeXBlbmF0ZShuYW1lc3BhY2UsJ3RpY2snKSlcbiAgICAgIC5hdHRyKFwieDFcIiwgMClcbiAgICAgIC5hdHRyKFwieDJcIiwgaG9yaXpvbnRhbFEgPyAwIDogb3JpZW50ID09IFwibGVmdFwiID8gLXRpY2tMZW5ndGggOiB0aWNrTGVuZ3RoKVxuICAgICAgLmF0dHIoXCJ5MVwiLCAwKVxuICAgICAgLmF0dHIoJ3kyJywgIHZlcnRpY2FsUSA/IDAgOiBvcmllbnQgPT0gXCJ0b3BcIiA/IC10aWNrTGVuZ3RoIDogdGlja0xlbmd0aClcbiAgICAgIC5hdHRyKCdzdHJva2UnLCB0aWNrU3Ryb2tlKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIHRpY2tTdHJva2VXaWR0aClcbiAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgIHZhclxuICAgICAgICB4ID0gbW92ZVhCeShkLCBpLCBob3Jpem9udGFsUSwgY2F0ZWdvcmljYWxRLCBvYmplY3RTaXplKSxcbiAgICAgICAgeSA9IG1vdmVZQnkoZCwgaSwgdmVydGljYWxRLCBjYXRlZ29yaWNhbFEsIG9iamVjdFNpemUpLFxuICAgICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICAgICAgIHJldHVybiB0XG4gICAgICB9KVxuXG4gICAgICAvLyBtYWtlIGFuZCBtb3ZlIGxhYmVsXG4gICAgICB2YXIgbGFiZWwgPSBzYWZlU2VsZWN0KHRoYXQsICd0ZXh0JywgaHlwZW5hdGUobmFtZXNwYWNlLCdsYWJlbCcpKVxuICAgICAgLnRleHQoZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIHZhciBzID0gdHlwZW9mIGQgPT0gJ251bWJlcicgPyByb3VuZChkLCByb3VuZFRvKSA6IGRcbiAgICAgICAgcyA9IHRydW5jYXRlU3RyaW5nKFN0cmluZyhzKSwgKGhvcml6b250YWxRID8gc3BhY2VZIDogc3BhY2VYKSAtIHRpY2tMZW5ndGgtdGlja0xhYmVsTWFyZ2luLXRpY2tUaWNrTGFiZWxTcGFjZXIsIHRpY2tMYWJlbEZvbnRTaXplICogMC40NSlcbiAgICAgICAgcmV0dXJuIHNcbiAgICAgIH0pXG4gICAgICAuYXR0cignZm9udC1zaXplJywgdGlja0xhYmVsRm9udFNpemUpXG4gICAgICAuYXR0cigndGV4dC1hbmNob3InLCB0aWNrTGFiZWxUZXh0QW5jaG9yKVxuICAgICAgLy8gdHJ1bmNhdGVUZXh0KGxhYmVsLCBsYWJlbC50ZXh0KCksIG9yaWVudCwgdGlja0xlbmd0aCwgaG9yaXpvbnRhbFEgPyBzcGFjZVkgOiBzcGFjZVgsIG92ZXJmbG93USlcblxuICAgICAgbGFiZWwuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICB2YXJcbiAgICAgICAgcmVjdCA9IGQzLnNlbGVjdCh0aGlzKS5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksXG4gICAgICAgIGxlbmcgPSBkMy5zZWxlY3QodGhpcykubm9kZSgpLmdldENvbXB1dGVkVGV4dExlbmd0aCgpLFxuICAgICAgICB4ID0gbW92ZVhCeShkLCBpLCBob3Jpem9udGFsUSwgY2F0ZWdvcmljYWxRLCBvYmplY3RTaXplKSxcbiAgICAgICAgeSA9IG1vdmVZQnkoZCwgaSwgdmVydGljYWxRLCBjYXRlZ29yaWNhbFEsIG9iamVjdFNpemUpXG4gICAgICAgIC8vIG9uIHJlY2FsbCwgcmVjdCBjaGFuZ2VzIGJlY2F1c2Ugb2Ygcm90YXRpb24gc28gbmVlZCBNYXRoLm1pbihyZWN0LmhlaWdodCwgcmVjdC53aWR0aClcblxuICAgICAgICB2YXIgcyA9IE1hdGguc2luKHRpY2tMYWJlbFJvdGF0aW9uKSAqIGxlbmcgKiAwXG5cbiAgICAgICAgaWYgKG9yaWVudCA9PSAndG9wJykge1xuICAgICAgICAgIHkgPSAtKHRpY2tMZW5ndGgrdGlja1RpY2tMYWJlbFNwYWNlcik7XG4gICAgICAgICAgLy8geSA9IHRpY2tMZW5ndGgrdGlja1RpY2tMYWJlbFNwYWNlcjtcblxuICAgICAgICAgIC8vIHkgLT0gTWF0aC5tYXgocmVjdC5oZWlnaHQsIHJlY3Qud2lkdGgpO1xuICAgICAgICAgIHggKz0gTWF0aC5taW4ocmVjdC5oZWlnaHQsIHJlY3Qud2lkdGgpICogMC4yNVxuICAgICAgICAgIC8vIHggLT0gbGVuZyAqIDAuMjUgKyBzXG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9yaWVudCA9PSAnYm90dG9tJykge1xuICAgICAgICAgIHkgPSB0aWNrTGVuZ3RoK3RpY2tUaWNrTGFiZWxTcGFjZXI7XG4gICAgICAgICAgeCArPSBNYXRoLm1pbihyZWN0LmhlaWdodCwgcmVjdC53aWR0aCkgKiAwLjI1XG4gICAgICAgICAgLy8geCArPSBsZW5nICogMC4yNSAtIHNcbiAgICAgICAgfVxuICAgICAgICBpZiAob3JpZW50ID09ICdsZWZ0Jykge1xuICAgICAgICAgIHggLT0gKHRpY2tMZW5ndGgrdGlja1RpY2tMYWJlbFNwYWNlcik7XG4gICAgICAgICAgLy8geSArPSByZWN0LmhlaWdodCAqIDAuNTsgeS09IHJlY3QuaGVpZ2h0LzRcbiAgICAgICAgICB5ICs9IE1hdGgubWluKHJlY3QuaGVpZ2h0LCByZWN0LndpZHRoKSAqIDAuMjVcbiAgICAgICAgICAvLyB5ICs9IGxlbmcgKiAwLjI1XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9yaWVudCA9PSAncmlnaHQnKSB7XG4gICAgICAgICAgeCArPSAodGlja0xlbmd0aCt0aWNrVGlja0xhYmVsU3BhY2VyKTtcbiAgICAgICAgICAvLyB5ICs9IE1hdGgubWluKHJlY3QuaGVpZ2h0LCByZWN0LndpZHRoKSAqIDAuMjVcbiAgICAgICAgICAvLyB5ICs9IGxlbmcgKiAwLjI1XG4gICAgICAgICAgeSArPSByZWN0LmhlaWdodCAqIDAuNTsgeS09IHJlY3QuaGVpZ2h0LzRcbiAgICAgICAgfVxuXG4gICAgICAgIHZhclxuICAgICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknLFxuICAgICAgICByID0gJ3JvdGF0ZSgnK3RpY2tMYWJlbFJvdGF0aW9uKycpJ1xuICAgICAgICByZXR1cm4gdCArIHJcbiAgICAgIH0pXG4gICAgICAub24oJ21vdXNlbW92ZScsIGxhYmVsSG92ZXIpXG4gICAgICAub24oJ21vdXNlb3V0JywgbGFiZWxIb3Zlck9mZilcbiAgICAgIC5vbignY2xpY2snLCB0aWNrTGFiZWxPbkNsaWNrKVxuICAgICAgLy8gLmF0dHIoJ2NsaXAtcGF0aCcsICd1cmwoIycraHlwZW5hdGUobmFtZXNwYWNlLCd0aWNrLWxhYmVsLWNsaXAtcGF0aCcpKycpJylcblxuICAgICAgLy8gYWRkIGd1aWRsaW5lcyBhcyBuZWVkZWRcbiAgICAgICBpZiAoZ3VpZGVMaW5lc1EpIHtcbiAgICAgICAgIHZhciBnbGluZSA9IHNhZmVTZWxlY3QodGhhdCwgJ2xpbmUnLCBoeXBlbmF0ZShuYW1lc3BhY2UsICdndWlkZWxpbmUnKSlcbiAgICAgICAgIC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgICAgLmF0dHIoXCJ4MVwiLCAwKVxuICAgICAgICAgLmF0dHIoXCJ4MlwiLCBob3Jpem9udGFsUSA/IDAgOiBvcmllbnQgPT0gXCJsZWZ0XCIgPyBndWlkZWxpbmVTcGFjZSA6IC1ndWlkZWxpbmVTcGFjZSlcbiAgICAgICAgIC5hdHRyKFwieTFcIiwgMClcbiAgICAgICAgIC5hdHRyKCd5MicsICB2ZXJ0aWNhbFEgPyAwIDogb3JpZW50ID09IFwidG9wXCIgPyBndWlkZWxpbmVTcGFjZSA6IC1ndWlkZWxpbmVTcGFjZSlcbiAgICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgIHZhclxuICAgICAgICAgICB4ID0gbW92ZVhCeShkLCBpLCBob3Jpem9udGFsUSwgY2F0ZWdvcmljYWxRLCBvYmplY3RTaXplKSxcbiAgICAgICAgICAgeSA9IG1vdmVZQnkoZCwgaSwgdmVydGljYWxRLCBjYXRlZ29yaWNhbFEsIG9iamVjdFNpemUpLFxuICAgICAgICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICAgICAgICAgIHJldHVybiB0XG4gICAgICAgICB9KVxuICAgICAgIH0gZWxzZSB7IHRoYXQuc2VsZWN0KCdsaW5lLicraHlwZW5hdGUobmFtZXNwYWNlLCAnZ3VpZGVsaW5lJykpLnJlbW92ZSgpIH1cblxuICAgIH0pXG5cbiAgICAvLyBhcHBseSBhbHRlcm5hdGluZyBndWlkbGluZSB0aGlja25lc3NcbiAgICBpZiAoZ3VpZGVMaW5lc1EpIHtcbiAgICAgIGNvbnRhaW5lci5zZWxlY3RBbGwoJy4nK2h5cGVuYXRlKG5hbWVzcGFjZSwnZ3VpZGVsaW5lJykpXG4gICAgICAuYXR0cignc3Ryb2tlJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIGlmIChpICUgMiA9PSAwKSB7IHJldHVybiBtb2RpZnlIZXhpZGVjaW1hbENvbG9yTHVtaW5hbmNlKGd1aWRlTGluZVN0cm9rZSwgMC44KSB9XG4gICAgICAgIHJldHVybiBndWlkZUxpbmVTdHJva2VcbiAgICAgIH0pXG4gICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIGlmIChpICUgMiA9PSAwKSB7IHJldHVybiBndWlkZUxpbmVTdHJva2VXaWR0aCAqMC44fVxuICAgICAgICByZXR1cm4gZ3VpZGVMaW5lU3Ryb2tlV2lkdGhcbiAgICAgIH0pXG4gICAgICAuYXR0cignbWlub3InLCBmdW5jdGlvbihkLCBpKXtyZXR1cm4gaSUyID09IDB9KVxuICAgIH1cblxuXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICoqIE1ha2UgdGhlIGxpbmUgb2YgdGhlIGF4aXNcbiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4gICAgdmFyIGxpbmUgPSBzYWZlU2VsZWN0KHNlbGVjdGlvbiwgJ3BhdGgnLCBoeXBlbmF0ZShuYW1lc3BhY2UsJ2xpbmUnKSlcbiAgICAvLyAuYXR0cigneDEnLCAwKVxuICAgIC8vIC5hdHRyKCd4MicsIGhvcml6b250YWxRID8gc3BhY2VYIDogMClcbiAgICAvLyAuYXR0cigneTEnLCAwKVxuICAgIC8vIC5hdHRyKCd5MicsIGhvcml6b250YWxRID8gMCA6IHNwYWNlWSlcbiAgICAuYXR0cignZCcsXG4gICAgICBob3Jpem9udGFsUVxuICAgICAgPyAnTSAwLDAgSCcgKyBzcGFjZVggKyAnLDAnXG4gICAgICA6ICdNIDAsMCBWIDAsJyArIHNwYWNlWVxuICAgIClcbiAgICAuYXR0cignc3Ryb2tlJywgbGluZVN0cm9rZSlcbiAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgbGluZVN0cm9rZVdpZHRoKVxuICAgIC5jbGFzc2VkKCdheGlzLWxpbmUnLCB0cnVlKVxuXG5cbiAgfVxuXG4gIC8vIGhvdmVyIG9mIGxhYmVsIHNob3cgZnVsbCB0ZXh0IGxhYmVsIGluIGNhc2UgaXQgaXMgdHJ1bmNhdGVkXG4gIGZ1bmN0aW9uIGxhYmVsSG92ZXIoZCwgaSl7XG4gICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcykuc3R5bGUoJ2ZpbGwnLCAncmVkJylcbiAgICBkMy5zZWxlY3QodC5ub2RlKCkucGFyZW50Tm9kZSkuc2VsZWN0KFwibGluZS5cIitoeXBlbmF0ZShuYW1lc3BhY2UsJ3RpY2snKSlcbiAgICAuYXR0cihcInN0cm9rZVwiLCAncmVkJylcbiAgICAuYXR0cihcInN0cm9rZS13aWR0aFwiLCB0aWNrU3Ryb2tlV2lkdGgqMilcblxuICAgIGlmIChndWlkZUxpbmVzUSkge1xuICAgICAgZDMuc2VsZWN0KHQubm9kZSgpLnBhcmVudE5vZGUpLnNlbGVjdCgnbGluZS4nK2h5cGVuYXRlKG5hbWVzcGFjZSwgJ2d1aWRlbGluZScpKVxuICAgICAgLmF0dHIoJ3N0cm9rZScsICdyZWQnKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGd1aWRlTGluZVN0cm9rZVdpZHRoKjIpXG4gICAgfVxuXG4gICAgdmFyIHMgPSB0eXBlb2YgZCA9PSAnbnVtYmVyJyA/IHJvdW5kKGQsIHJvdW5kVG8pIDogZFxuXG4gICAgdmFyIG0gPSBkMy5tb3VzZShkMy5zZWxlY3QoJ2h0bWwnKS5ub2RlKCkpXG4gICAgdmFyIGRpdiA9IHNhZmVTZWxlY3QoZDMuc2VsZWN0KCdib2R5JyksICdkaXYnLCBoeXBlbmF0ZShuYW1lc3BhY2UsJ2d1aWRlbGluZS10b29sdGlwJykpXG4gICAgLmF0dHIoJ2lkJywgaHlwZW5hdGUobmFtZXNwYWNlLCdndWlkZWxpbmUtdG9vbHRpcCcpKVxuICAgIC5zdHlsZSgncG9zaXRpb24nLCAnYWJzb2x1dGUnKVxuICAgIC5zdHlsZSgnbGVmdCcsIChkMy5ldmVudC5wYWdlWCsxNSkrJ3B4JylcbiAgICAuc3R5bGUoJ3RvcCcsIChkMy5ldmVudC5wYWdlWSsxNSkrJ3B4JylcbiAgICAuc3R5bGUoJ2JhY2tncm91bmQtY29sb3InLCAnd2hpdGUnKVxuICAgIC5zdHlsZSgnYm9yZGVyLWNvbG9yJywgJ2JsYWNrJylcbiAgICAvLyAuc3R5bGUoJ21pbi13aWR0aCcsICh0aWNrTGFiZWxGb250U2l6ZSAqIChTdHJpbmcocykuc3BsaXQoJy4nKVswXS5sZW5ndGgrMykpKydweCcpXG4gICAgLy8gLnN0eWxlKCdtaW4taGVpZ2h0JywgKHRpY2tMYWJlbEZvbnRTaXplICogKFN0cmluZyhzKS5zcGxpdCgnLicpWzBdLmxlbmd0aCszKSkrJ3B4JylcbiAgICAuc3R5bGUoJ2JvcmRlci1yYWRpdXMnLCAnMTBweCcpXG4gICAgLnN0eWxlKCdkaXNwbGF5JywgJ2ZsZXgnKVxuICAgIC5zdHlsZSgnanVzdGlmeS1jb250ZW50JywgJ2NlbnRlcicpXG4gICAgLnN0eWxlKCd0ZXh0LWFsaWduJywgJ21pZGRsZScpXG4gICAgLnN0eWxlKCdwYWRkaW5nJywgNCtcInB4XCIpXG5cbiAgICAuc3R5bGUoJ2JvcmRlci1zdHlsZScsICdzb2xpZCcpXG4gICAgLnN0eWxlKCdib3JkZXItd2lkdGgnLCAyKVxuXG4gICAgdmFyIHRleHQgPSBzYWZlU2VsZWN0KGRpdiwgJ2RpdicpXG4gICAgLnRleHQodGlja0xhYmVsT25Ib3ZlckZ1bmMocywgaSkpXG4gICAgLnN0eWxlKCdjb2xvcicsICdibGFjaycpXG4gICAgLnN0eWxlKCdhbGlnbi1zZWxmJywgJ2NlbnRlcicpXG5cbiAgICB2YXIgYmJveCA9IGRpdi5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClcbiAgICBpZiAoYmJveC54ICsgYmJveC53aWR0aCA+IHdpbmRvdy5pbm5lcldpZHRoKSB7XG4gICAgICBkaXYuc3R5bGUoJ2xlZnQnLCAoZDMuZXZlbnQucGFnZVgtMTUtMzAwKSsncHgnKVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGxhYmVsSG92ZXJPZmYoZCwgaSl7XG4gICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcykuc3R5bGUoJ2ZpbGwnLCAnYmxhY2snKVxuICAgIGQzLnNlbGVjdCh0Lm5vZGUoKS5wYXJlbnROb2RlKS5zZWxlY3QoXCJsaW5lLlwiK2h5cGVuYXRlKG5hbWVzcGFjZSwndGljaycpKVxuICAgIC5hdHRyKFwic3Ryb2tlXCIsIHRpY2tTdHJva2UpXG4gICAgLmF0dHIoXCJzdHJva2Utd2lkdGhcIiwgdGlja1N0cm9rZVdpZHRoKVxuXG4gICAgaWYgKGd1aWRlTGluZXNRKSB7XG4gICAgICB2YXIgZ2xpbmUgPSBkMy5zZWxlY3QodC5ub2RlKCkucGFyZW50Tm9kZSkuc2VsZWN0KCdsaW5lLicraHlwZW5hdGUobmFtZXNwYWNlLCAnZ3VpZGVsaW5lJykpXG4gICAgICB2YXIgbWlub3JRID0gZ2xpbmUuYXR0cignbWlub3InKVxuICAgICAgZ2xpbmUuYXR0cignc3Ryb2tlJywgZnVuY3Rpb24oZCwgaWkpe1xuICAgICAgICBpZiAobWlub3JRID09ICd0cnVlJykgeyByZXR1cm4gbW9kaWZ5SGV4aWRlY2ltYWxDb2xvckx1bWluYW5jZShndWlkZUxpbmVTdHJva2UsIDAuOCkgfVxuICAgICAgICByZXR1cm4gZ3VpZGVMaW5lU3Ryb2tlXG4gICAgICB9KVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGZ1bmN0aW9uKGQsIGlpKXtcbiAgICAgICAgaWYgKG1pbm9yUSA9PSAndHJ1ZScpIHsgcmV0dXJuIGd1aWRlTGluZVN0cm9rZVdpZHRoICowLjh9XG4gICAgICAgIHJldHVybiBndWlkZUxpbmVTdHJva2VXaWR0aFxuICAgICAgfSlcbiAgICB9XG4gICAgZDMuc2VsZWN0KFwiI1wiK2h5cGVuYXRlKG5hbWVzcGFjZSwnZ3VpZGVsaW5lLXRvb2x0aXAnKSkucmVtb3ZlKClcbiAgfVxuXG5cblxuICByZXR1cm4gYXhpc1xufVxuIiwiaW1wb3J0IHtoeXBlbmF0ZSwgc2FmZVNlbGVjdH0gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7c2V0dXBDb250YWluZXIsIGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3QsIGNhbGN1bGF0ZVdpZHRoT2ZTcGFjZXJ9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHt1bmlxdWUsIGZsYXR0ZW59IGZyb20gJy4vYXJyYXktZnVuY3Rpb25zJztcbmltcG9ydCB7Z3JvdXBpbmdTcGFjZXJ9IGZyb20gJy4vZ3JvdXBpbmctc3BhY2VyJztcbmltcG9ydCB7Y29sb3JGdW5jdGlvbiBhcyBDRn0gZnJvbSAnLi9jb2xvci1mdW5jdGlvbic7XG5pbXBvcnQge3Rvb2x0aXAgYXMgVFRpcH0gZnJvbSAnLi90b29sdGlwJztcbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCQVIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbi8qKlxuICogQ3JlYXRlcyBhIGJhclxuICpcbiAqIHtAbGluayBodHRwczovL3N1bW5ldXJvbi5naXRsYWIuaW8vZDNzbS9kZW1vcy9iYXItY2hhcnQtc2FtZS1kYXRhLWNvbXBsZXgtZ3JvdXBpbmcvaW5kZXguaHRtbCBEZW1vfVxuICogQGNvbnN0cnVjdG9yIGJhclxuICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IHNlbGVjdGlvblxuICogQG5hbWVzcGFjZSBiYXJcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gYmFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBiYXIgKCBzZWxlY3Rpb24gKSB7XG4gIC8qXG4gIEFzc3VtZXMgdGhhdCBkYXRhIGlzIGxpc3QgYW4gb2JqZWN0LlxuXG4gIFRoZSBrZXlzIG9mIGRhdGEgd2lsbCBiZSBib3VuZCB0byB0aGUgYmFycy5cbiAgVGhlIHZhbHVlRXh0cmFjdG9yIGZ1bmN0aW9uIHdpbGwgZXh0cmFjdCB0aGUgdmFsdWUgZnJvbSBkYXRhW2tleV0uXG5cbiAgR3JvdXBpbmcgY2FuIGJlIHVzZWQgaWYgZGVzaXJlZC4gSXQgc2hvdWxkIGJlIGFuIGFyYml0cmFyeSBjb21wbGV4IGxpc3Qgd2hlcmVcbiAgdGhlIHZhbHVlcyBhcmUgc3RyaW5ncyBtYXRjaGluZyBrZXlzIGluIGRhdGEuXG4gICovXG4gIHZhclxuICAvKipcbiAgKiBEYXRhIHRvIHBsb3QuIEFzc3VtZWQgdG8gYmUgYSBvYmplY3QsIHdoZXJlIGVhY2gga2V5IGNvcnJlc3BvbmRzIHRvIGEgYmFyXG4gICogKHNlZSB7QGxpbmsgYmFyI2RhdGF9KVxuICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZGF0YSxcbiAgLyoqXG4gICogV2hpY2ggZGlyZWN0aW9uIHRvIHJlbmRlciB0aGUgYmFycyBpblxuICAqIChzZWUge0BsaW5rIGJhciNvcmllbnR9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbb3JpZW50PSdob3Jpem9udGFsJ11cbiAgKiBAbWVtYmVyb2YgYmFyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvcmllbnQ9J2hvcml6b250YWwnLFxuICAvKipcbiAgKiBBbW91bnQgb2YgaG9yaXpvbnRhbCBzcGFjZSAoaW4gcGl4ZWxzKSBhdmFpYmxlIHRvIHJlbmRlciB0aGUgYmFyIGluXG4gICogKHNlZSB7QGxpbmsgYmFyI3NwYWNlWH0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZVg9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNwYWNlWCxcbiAgLyoqXG4gICogQW1vdW50IG9mIHZlcnRpY2FsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSBiYXIgaW5cbiAgKiAoc2VlIHtAbGluayBiYXIuc3BhY2VZfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlWT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VZLFxuXG4gIC8qKlxuICAqIFdoZXRoZXIgb3Igbm90IHRvIGFsbG93IGJhciB0byByZW5kZXIgZWxlbWVudHMgcGFzcyB0aGUgbWFpbiBzcGF0aWFsIGRpbWVuc2lvblxuICAqIGdpdmVuIHRoZSBvcmllbnRhdGlvbiAoc2VlIHtAbGluayBiYXIjb3JpZW50fSksIHdoZXJlIHtAbGluayBiYXIjb3JpZW50fT1cImhvcml6b250YWxcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgYmFyI3NwYWNlWH0gYW5kIHdoZXJlIHtAbGluayBiYXIjb3JpZW50fT1cInZlcnRpY2FsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJhciNzcGFjZVl9XG4gICogQHBhcmFtIHtib29sZWFufSBbb3ZlcmZsb3dRPWZhbHNlXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG92ZXJmbG93USA9IGZhbHNlLFxuXG4gIC8qKlxuICAqIEFuIGFycmF5IC0gcHV0YXRpdmVseSBvZiBvdGhlciBhcnJheXMgLSBkZXBpY3RpbmcgaG93IGJhcnMgc2hvdWxkIGJlIGFycmFuZ2VkXG4gICogQHBhcmFtIHtBcnJheVtdfSBbZ3JvdXBpbmc9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGdyb3VwaW5nLFxuXG4gIC8qKlxuICAqIEhvdyB0byBnZXQgdGhlIHZhbHVlIG9mIHRoZSBiYXJcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbdmFsdWVFeHRyYWN0b3I9ZnVuY3Rpb24oa2V5LCBpbmRleCkgeyByZXR1cm4gZGF0YVtrZXldIH1dXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGluZGV4KSB7IHJldHVybiBkYXRhW2tleV0gfSxcbiAgLyoqXG4gICogSG93IHRvIHNvcnQgdGhlIGJhcnMgLSBpZiB7QGxpbmsgYmFyI2dyb3VwaW5nfSBpcyBub3QgcHJvdmlkZWQuXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3NvcnRpbmdGdW5jdGlvbj1mdW5jdGlvbihrZXlBLCBrZXlCKSB7cmV0dXJuIGQzLmRlc2NlbmRpbmcoZGF0YVtrZXlBXSwgZGF0YVtrZXlCXSl9XVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKGtleUEsIGtleUIpIHtyZXR1cm4gZDMuZGVzY2VuZGluZyhkYXRhW2tleUFdLCBkYXRhW2tleUJdKX0sXG5cbiAgLyoqXG4gICogVGhlIHNjYWxlIGZvciB3aGljaCBiYXIgdmFsdWVzIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBieVxuICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtzY2FsZT1kMy5zY2FsZUxpbmVhcl1cbiAgKiBAbWVtYmVyb2YgYmFyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKCksXG4gIC8qKlxuICAqIFRoZSBwYWRkaW5nIGZvciB0aGUgZG9tYWluIG9mIHRoZSBzY2FsZSAoc2VlIHtAbGluayBiYXIjc2NhbGV9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbZG9tYWluUGFkZGluZz0wLjVdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZG9tYWluUGFkZGluZyA9IDAuNSxcblxuICAvKipcbiAgKiBEZWZhdWx0IHNwYWNlIGZvciB0aGUgc3BhY2VyIChwZXJjZW50YWdlKSBvZiBtYWluIGRpbWVuc2lvbiBnaXZlbiB0aGUgb3JpZW50YXRpb25cbiAgKiAoc2VlIHtAbGluayBiYXIjb3JpZW50fSksIHdoZXJlIHtAbGluayBiYXIjb3JpZW50fT1cImhvcml6b250YWxcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgYmFyI3NwYWNlWH0gYW5kIHdoZXJlIHtAbGluayBiYXIjb3JpZW50fT1cInZlcnRpY2FsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJhciNzcGFjZVl9IGJldHdlZW4gYmFyc1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbb2JqZWN0U3BhY2VyPTAuMDVdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0U3BhY2VyID0gMC4wNSxcbiAgLyoqXG4gICogVGhlIG1pbmltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmVcbiAgKiBAcGFyYW0ge251bWJlcn0gW21pbk9iamVjdFNpemU9NTBdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbWluT2JqZWN0U2l6ZSA9IDUwLFxuICAvKipcbiAgKiBUaGUgbWF4aW11bSBzaXplIHRoYXQgYW4gb2JqZWN0IGNhbiBiZVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbbWF4T2JqZWN0U2l6ZT0xMDBdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbWF4T2JqZWN0U2l6ZSA9IDEwMCxcblxuICAvKipcbiAgKiBUaGUgc3Ryb2tlIHdpZHRoIG9mIHRoZSBiYXJzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtiYXJTdHJva2VXaWR0aD0yXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJhclN0cm9rZVdpZHRoID0gMixcbiAgLyoqXG4gICogSW5zdGFuY2Ugb2YgQ29sb3JGdW5jdGlvblxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtjb2xvckZ1bmN0aW9uID0gY29sb3JGdW5jdGlvbigpXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGNvbG9yRnVuY3Rpb24gPSBDRigpLFxuXG5cbiAgLyoqXG4gICogQ29sb3Igb2YgdGhlIGJhY2tncm91bmRcbiAgKiBAcGFyYW0ge3N0cmluZ30gW2JhY2tncm91bmRGaWxsPVwidHJhbnNwYXJlbnRcIl1cbiAgKiBAbWVtYmVyb2YgYmFyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCcsXG4gIC8qKlxuICAqIE5hbWVzcGFjZSBmb3IgYWxsIGl0ZW1zIG1hZGUgYnkgdGhpcyBpbnN0YW5jZSBvZiBiYXJcbiAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWVzcGFjZT1cImQzc20tYmFyXCJdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbmFtZXNwYWNlID0gJ2Qzc20tYmFyJyxcbiAgLyoqXG4gICogQ2xhc3MgbmFtZSBmb3IgYmFyIGNvbnRhaW5lciAoPGc+IGVsZW1lbnQpXG4gICogQHBhcmFtIHtzdHJpbmd9IFtvYmplY3RDbGFzcz1cImJhclwiXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdENsYXNzID0gJ2JhcicsXG5cbiAgLyoqXG4gICogRHVyYXRpb24gb2YgYWxsIHRyYW5zaXRpb25zIG9mIHRoaXMgZWxlbWVudFxuICAqIEBwYXJhbSB7bnVtYmVyfSBbdHJhbnNpdGlvbkR1cmF0aW9uPTEwMDBdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdHJhbnNpdGlvbkR1cmF0aW9uID0gMTAwMCxcbiAgLyoqXG4gICogRWFzaW5nIGZ1bmN0aW9uIGZvciB0cmFuc2l0aW9uc1xuICAqIEBwYXJhbSB7ZDMuZWFzZX0gW2Vhc2VGdW5jPWQzLmVhc2VFeHBdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwLFxuXG4gIC8vIHVzZWZ1bCB2YWx1ZXMgdG8gZXh0cmFjdCB0byBwcmV2ZW50IHJlLWNhbGN1bGF0aW9uXG4gIC8qKlxuICAqIFRoZSBrZXlzIG9mIHRoZSBiYXJzXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW2JhcktleXM9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJhcktleXMsXG4gIC8qKlxuICAqIFRoZSB2YWx1ZXMgb2YgdGhlIGJhcnNcbiAgKiBAcGFyYW0ge251bWJlcltdfSBbYmFyVmFsdWVzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYmFyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBiYXJWYWx1ZXMsXG4gIC8qKlxuICAqIFRoZSBvYmplY3RTaXplIChhY3R1YWwgd2lkdGgpIHVzZWQgYnkgdGhlIGJhcnNcbiAgKiBAcGFyYW0ge251bWJlcn0gW29iamVjdFNpemU9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdFNpemUsXG4gIC8qKlxuICAqIFRoZSBzcGFjZXJTaXplIChhY3R1YWwgd2lkdGgpIHVzZWQgYnkgdGhlIHNwYWNlcnMgYmV0d2VlbiB0aGUgYmFyc1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbc3BhY2VyU2l6ZT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VyU2l6ZSxcbiAgLyoqXG4gICogSW5zdGFuY2Ugb2YgVG9vbHRpcFxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFt0b29sdGlwPXRvb2x0aXAoKV1cbiAgKiBAbWVtYmVyb2YgYmFyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0b29sdGlwID0gVFRpcCgpLFxuICBiYXJQZXJjZW50ID0gMVxuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHNlbGVjdGlvbiBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBkMy5zZWxlY3Rpb259XG4gICAqIEBtZW1iZXJvZiBiYXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc2VsZWN0aW9uID0gc2VsZWN0aW9uXG4gICAqL1xuICBiYXIuc2VsZWN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZWxlY3Rpb24gPSBfLCBiYXIpIDogc2VsZWN0aW9uOyB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBkYXRhXG4gICAqIChzZWUge0BsaW5rIGJhciNkYXRhfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBvYmplY3R9XG4gICAqIEBtZW1iZXJvZiBiYXJcbiAgICogQHByb3BlcnR5XG4gICAqL1xuICBiYXIuZGF0YSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGF0YSA9IF8sIGJhcikgOiBkYXRhOyB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBvcmllbnQgb2YgdGhlIGJhcnNcbiAgICogKHNlZSB7QGxpbmsgYmFyI29yaWVudH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YmFyIHwgb2JqZWN0fVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgYmFyLm9yaWVudCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3JpZW50ID0gXywgYmFyKSA6IG9yaWVudDsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgYW1vdW50IG9mIGhvcml6b250YWwgc3BhY2UgaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIGJhciNzcGFjZVh9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV0gc2hvdWxkIGJlIGEgbnVtYmVyID4gMFxuICAgKiBAcmV0dXJucyB7YmFyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlWCA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmFyLnNwYWNlWCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3BhY2VYID0gXywgYmFyKSA6IHNwYWNlWDsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgYW1vdW50IG9mIHZlcnRpY2FsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBiYXIjc3BhY2VZfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge2JhciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVkgPSB1bmRlZmluZWRcbiAgICovXG4gIGJhci5zcGFjZVkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWSA9IF8sIGJhcikgOiBzcGFjZVk7IH07XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IGJhciBpcyBhbGxvd2VkIHRvIGdvIGJleW9uZCBzcGVjaWZpZWQgZGltZW5zaW9uc1xuICAgKiAoc2VlIHtAbGluayBiYXIjc3BhY2VYfSlcbiAgICogQHBhcmFtIHtib29sZWFufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YmFyIHwgYm9vbGVhbn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvdmVyZmxvd1EgPSBmYWxzZVxuICAgKi9cbiAgYmFyLm92ZXJmbG93USA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3ZlcmZsb3dRID0gXywgYmFyKSA6IG92ZXJmbG93UTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBncm91cGluZyBvZiB0aGUgYmFyc1xuICAgKiAoc2VlIHtAbGluayBiYXIjZ3JvdXBpbmd9KVxuICAgKiBAcGFyYW0ge0FycmF5W119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBBcnJheVtdfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGdyb3VwaW5nID0gdW5kZWZpbmVkXG4gICAqL1xuICBiYXIuZ3JvdXBpbmcgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGdyb3VwaW5nID0gXywgYmFyKSA6IGdyb3VwaW5nOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHZhbHVlRXh0cmFjdG9yXG4gICAqIChzZWUge0BsaW5rIGJhciN2YWx1ZUV4dHJhY3Rvcn0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB2YWx1ZUV4dHJhY3RvciA9IGZ1bmN0aW9uKGtleSwgaW5kZXgpIHsgcmV0dXJuIGRhdGFba2V5XSB9LFxuICAgKi9cbiAgYmFyLnZhbHVlRXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZUV4dHJhY3RvciA9IF8sIGJhcikgOiB2YWx1ZUV4dHJhY3RvcjsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzb3J0aW5nRnVuY3Rpb25cbiAgICogKHNlZSB7QGxpbmsgYmFyI3NvcnRpbmdGdW5jdGlvbn0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihrZXlBLCBrZXlCKSB7cmV0dXJuIGQzLmRlc2NlbmRpbmcoZGF0YVtrZXlBXSwgZGF0YVtrZXlCXSl9LFxuICAgKi9cbiAgYmFyLnNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc29ydGluZ0Z1bmN0aW9uID0gXywgYmFyKSA6IHNvcnRpbmdGdW5jdGlvbjsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzY2FsZSBmb3Igd2hpY2ggdGhlIGJhciB2YWx1ZXMgc2hvdWxkIGJlIHRyYW5zZm9ybWVkIGJ5XG4gICAqIChzZWUge0BsaW5rIGJhciNzY2FsZX0pXG4gICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBkMy5zY2FsZX1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKClcbiAgICovXG4gIGJhci5zY2FsZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGUgPSBfLCBiYXIpIDogc2NhbGU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcGFkZGluZyBmb3IgdGhlIGRvbWFpbiBvZiB0aGUgc2NhbGVcbiAgICogKHNlZSB7QGxpbmsgYmFyI2RvbWFpblBhZGRpbmd9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBkb21haW5QYWRkaW5nID0gMC41XG4gICAqL1xuICBiYXIuZG9tYWluUGFkZGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluUGFkZGluZyA9IF8sIGJhcikgOiBkb21haW5QYWRkaW5nOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgb2JqZWN0U3BhY2VyXG4gICAqIChzZWUge0BsaW5rIGJhciNvYmplY3RTcGFjZXJ9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RTcGFjZXIgPSAwLjA1XG4gICAqL1xuICBiYXIub2JqZWN0U3BhY2VyID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvYmplY3RTcGFjZXIgPSBfLCBiYXIpIDogb2JqZWN0U3BhY2VyOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1pbk9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgYmFyI21pbk9iamVjdFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBtaW5PYmplY3RTaXplID0gNTBcbiAgICovXG4gIGJhci5taW5PYmplY3RTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChtaW5PYmplY3RTaXplID0gXywgYmFyKSA6IG1pbk9iamVjdFNpemU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbWF4T2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayBiYXIjbWF4T2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YmFyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1heE9iamVjdFNpemUgPSAxMDBcbiAgICovXG4gIGJhci5tYXhPYmplY3RTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChtYXhPYmplY3RTaXplID0gXywgYmFyKSA6IG1heE9iamVjdFNpemU7IH07XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBiYXJTdHJva2VXaWR0aFxuICAgKiAoc2VlIHtAbGluayBiYXIjYmFyU3Ryb2tlV2lkdGh9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBiYXJTdHJva2VXaWR0aCA9IDJcbiAgICovXG4gIGJhci5iYXJTdHJva2VXaWR0aCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFyU3Ryb2tlV2lkdGggPSBfLCBiYXIpIDogYmFyU3Ryb2tlV2lkdGg7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgY29sb3JGdW5jdGlvblxuICAgKiAoc2VlIHtAbGluayBiYXIjY29sb3JGdW5jdGlvbn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YmFyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGNvbG9yRnVuY3Rpb24gPSBjb2xvckZ1bmN0aW9uKClcbiAgICovXG4gIGJhci5jb2xvckZ1bmN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjb2xvckZ1bmN0aW9uID0gXywgYmFyKSA6IGNvbG9yRnVuY3Rpb247IH07XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBiYWNrZ3JvdW5kRmlsbFxuICAgKiAoc2VlIHtAbGluayBiYXIjYmFja2dyb3VuZEZpbGx9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCdcbiAgICovXG4gIGJhci5iYWNrZ3JvdW5kRmlsbCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFja2dyb3VuZEZpbGwgPSBfLCBiYXIpIDogYmFja2dyb3VuZEZpbGw7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbmFtZXNwYWNlXG4gICAqIChzZWUge0BsaW5rIGJhciNuYW1lc3BhY2V9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBuYW1lc3BhY2UgPSAnZDNzbS1iYXInXG4gICAqL1xuICBiYXIubmFtZXNwYWNlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChuYW1lc3BhY2UgPSBfLCBiYXIpIDogbmFtZXNwYWNlOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG9iamVjdENsYXNzXG4gICAqIChzZWUge0BsaW5rIGJhciNvYmplY3RDbGFzc30pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YmFyIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG9iamVjdENsYXNzID0gJ3RpY2stZ3JvdXAnXG4gICAqL1xuICBiYXIub2JqZWN0Q2xhc3MgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdENsYXNzID0gXywgYmFyKSA6IG9iamVjdENsYXNzOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRyYW5zaXRpb25EdXJhdGlvblxuICAgKiAoc2VlIHtAbGluayBiYXIjdHJhbnNpdGlvbkR1cmF0aW9ufSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBiYXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdHJhbnNpdGlvbkR1cmF0aW9uID0gMTAwMFxuICAgKi9cbiAgYmFyLnRyYW5zaXRpb25EdXJhdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodHJhbnNpdGlvbkR1cmF0aW9uID0gXywgYmFyKSA6IHRyYW5zaXRpb25EdXJhdGlvbjsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBlYXNlRnVuY1xuICAgKiAoc2VlIHtAbGluayBiYXIjZWFzZUZ1bmN9KVxuICAgKiBAcGFyYW0ge2QzLmVhc2V9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBkMy5lYXNlfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGVhc2VGdW5jID0gZDMuZWFzZUV4cFxuICAgKi9cbiAgYmFyLmVhc2VGdW5jID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChlYXNlRnVuYyA9IF8sIGJhcikgOiBlYXNlRnVuYzsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYmFyS2V5c1xuICAgKiAoc2VlIHtAbGluayBiYXIjYmFyS2V5c30pXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBzdHJpbmdbXX1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBiYXJLZXlzID0gdW5kZWZpbmVkXG4gICAqL1xuICBiYXIuYmFyS2V5cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFyS2V5cyA9IF8sIGJhcikgOiBiYXJLZXlzOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGJhclZhbHVlc1xuICAgKiAoc2VlIHtAbGluayBiYXIjYmFyVmFsdWVzfSlcbiAgICogQHBhcmFtIHtudW1iZXJbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IG51bWJlcltdfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGJhclZhbHVlcyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmFyLmJhclZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFyVmFsdWVzID0gXywgYmFyKSA6IGJhclZhbHVlczsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RTaXplXG4gICAqIChzZWUge0BsaW5rIGJhciNvYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBiYXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0U2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmFyLm9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNpemUgPSBfLCBiYXIpIDogb2JqZWN0U2l6ZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzcGFjZXJTaXplXG4gICAqIChzZWUge0BsaW5rIGJhciNzcGFjZXJTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBiYXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc3BhY2VyU2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmFyLnNwYWNlclNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlclNpemUgPSBfLCBiYXIpIDogc3BhY2VyU2l6ZTsgfTtcblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRvb2x0aXBcbiAgICogKHNlZSB7QGxpbmsgYmFyI3Rvb2x0aXB9KVxuICAgKiBAcGFyYW0ge3Rvb2x0aXB9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCB0b29sdGlwfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRvb2x0aXAgPSB0b29sdGlwKClcbiAgICovXG4gIGJhci50b29sdGlwID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0b29sdGlwID0gXywgYmFyKSA6IHRvb2x0aXA7IH07XG5cbiAgYmFyLmJhclBlcmNlbnQgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJhclBlcmNlbnQgPSBfLCBiYXIpIDogYmFyUGVyY2VudDsgfTtcblxuICBmdW5jdGlvbiBiYXIoKSB7XG4gICAgLy8gZm9yIGNvbnZlbmllbmNlIGluIGhhbmRsaW5nIG9yaWVudGF0aW9uIHNwZWNpZmljIHZhbHVlc1xuICAgIHZhciBob3Jpem9udGFsUSA9IChvcmllbnQgPT0gJ2hvcml6b250YWwnIHx8IG9yaWVudCA9PSAnYm90dG9tJyB8fCBvcmllbnQgPT0gJ3RvcCcpID8gdHJ1ZSA6IGZhbHNlXG4gICAgdmFyIHZlcnRpY2FsUSA9ICFob3Jpem9udGFsUVxuXG4gICAgLy8gYmFja2dyb3VuZCBjbGlwaW5nIHJlY3RhbmdsZVxuICAgIHZhciBiZ2NwUmVjdCA9IHt4OjAsIHk6MCwgd2lkdGg6IHNwYWNlWCwgaGVpZ2h0OnNwYWNlWX1cbiAgICB2YXIgY29udGFpbmVyID0gc2V0dXBDb250YWluZXIoIHNlbGVjdGlvbiwgbmFtZXNwYWNlLCBiZ2NwUmVjdCwgYmFja2dyb3VuZEZpbGwgKTtcblxuICAgIC8vIHRvIHByZXZlbnQgcmUtY2FsY3VsYXRpb24gYW5kIGdldHRlcnMgdG8gYmUgcGFzc2VkIHRvIGF4ZXNcbiAgICBiYXJLZXlzID0gZDMua2V5cyhkYXRhKVxuICAgIGJhclZhbHVlcyA9IGJhcktleXMubWFwKHZhbHVlRXh0cmFjdG9yKVxuXG4gICAgLy8gaWYgZ3JvdXBpbmcgaXMgdW5kZWZpbmVkIHNvcnQgYmFyS2V5cyBieSBzb3J0aW5nRnVuY3Rpb25cbiAgICB2YXIgb3JkZXJlZCA9IChncm91cGluZyA9PSB1bmRlZmluZWQpID8gYmFyS2V5cy5zb3J0KHNvcnRpbmdGdW5jdGlvbikgOiBncm91cGluZ1xuICAgIC8vIG9yZGVyZWQgbWlnaHQgYmUgbmVzdGVkIGRlcGVuZGluZyBvbiBncm91cGluZ1xuICAgIGJhcktleXMgPSBmbGF0dGVuKG9yZGVyZWQpXG5cbiAgICB2YXIgbnVtYmVyT2ZPYmplY3RzID0gYmFyS2V5cy5sZW5ndGhcbiAgICB2YXIgZXh0ZW50ID0gW01hdGgubWluKC4uLmJhclZhbHVlcykgLSBkb21haW5QYWRkaW5nLE1hdGgubWF4KC4uLmJhclZhbHVlcykgKyBkb21haW5QYWRkaW5nXTtcblxuXG5cbiAgICAvLyBzZXQgdGhlIHNjYWxlXG5cbiAgICBzY2FsZS5kb21haW4oZXh0ZW50KS5yYW5nZShob3Jpem9udGFsUVxuICAgICAgPyBbMCxzcGFjZVldXG4gICAgICA6IG9yaWVudCA9PSAncmlnaHQnXG4gICAgICAgID8gWzAsIHNwYWNlWF1cbiAgICAgICAgOiBbc3BhY2VYLCAwXVxuICAgIClcbiAgICB2YXIgc3BhY2UgPSBob3Jpem9udGFsUSA/IHNwYWNlWCA6IHNwYWNlWVxuICAgIC8vIGNhbGN1bGF0ZSBvYmplY3Qgc2l6ZVxuICAgIG9iamVjdFNpemUgPSAgKG9iamVjdFNpemUgPT0gdW5kZWZpbmVkKVxuICAgID8gY2FsY3VsYXRlV2lkdGhPZk9iamVjdChzcGFjZSwgbnVtYmVyT2ZPYmplY3RzLCBtaW5PYmplY3RTaXplLCBtYXhPYmplY3RTaXplLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICA6IG9iamVjdFNpemVcblxuICAgIC8vIGNhbGN1bGF0ZSBzcGFjZXIgc2l6ZSBpZiBuZWVkZWRcbiAgICBzcGFjZXJTaXplID0gKHNwYWNlclNpemUgPT0gdW5kZWZpbmVkKVxuICAgID8gY2FsY3VsYXRlV2lkdGhPZlNwYWNlcihiYXJLZXlzLCBzcGFjZSwgb2JqZWN0U2l6ZSwgbnVtYmVyT2ZPYmplY3RzLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICA6IHNwYWNlclNpemVcbiAgICAvLyBtYWtlIHRoZSBuZXN0ZWQgZ3JvdXBzXG4gICAgdmFyIHNwYWNlckZ1bmN0aW9uID0gZ3JvdXBpbmdTcGFjZXIoKVxuICAgIC5ob3Jpem9udGFsUShob3Jpem9udGFsUSkuc2NhbGUoc2NhbGUpLm1vdmVieSgnY2F0ZWdvcnknKS5udW1iZXJPZk9iamVjdHMobnVtYmVyT2ZPYmplY3RzKVxuICAgIC5vYmplY3RDbGFzcyhvYmplY3RDbGFzcykub2JqZWN0U2l6ZShvYmplY3RTaXplKS5zcGFjZXJTaXplKHNwYWNlclNpemUpXG4gICAgLnRyYW5zaXRpb25EdXJhdGlvbih0cmFuc2l0aW9uRHVyYXRpb24pLmVhc2VGdW5jKGVhc2VGdW5jKVxuICAgIC5uYW1lc3BhY2UobmFtZXNwYWNlKVxuICAgIC8vIHNhZmUgZGVmYXVsdCBmdW5jdGlvblxuICAgIHZhciBkZWZhdWx0RXhpdCA9IHNwYWNlckZ1bmN0aW9uLmV4aXRGdW5jdGlvbigpXG5cbiAgICBzcGFjZXJGdW5jdGlvbi5leGl0RnVuY3Rpb24oZnVuY3Rpb24oc2VsKXtcbiAgICAgIC8vIHVzZSBkZWZhdWx0IHRvIG1vdmUgb2JqZWN0cyBvZmYgc2NyZWVuXG4gICAgICAvLyBjb25zb2xlLmxvZyhcIkVYSVRcIiwgc2VsLm5vZGVzKCksIG9iamVjdFNpemUsIHNjYWxlKGV4dGVudFsxXSkpXG4gICAgICBpZiAob2JqZWN0U2l6ZSA9PSB1bmRlZmluZWQpIHtjb25zb2xlLmxvZyhzZWwubm9kZXMoKSwgb2JqZWN0U2l6ZSl9XG4gICAgICBkZWZhdWx0RXhpdChzZWwpXG4gICAgICBzZWwuc2VsZWN0QWxsKCdnJykuY2xhc3NlZChcInRvLXJlbW92ZVwiLCB0cnVlKVxuICAgICAgLy8gc2hyaW5rIHJlY3RhbmdsZXMgaW4gYWRkaXRpb25cbiAgICAgIHNlbC5zZWxlY3RBbGwoJyogPiByZWN0JylcbiAgICAgIC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKVxuICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBob3Jpem9udGFsUVxuICAgICAgICAgID8gMFxuICAgICAgICAgIDogMFxuICAgICAgICAsXG4gICAgICAgIHkgPSB2ZXJ0aWNhbFFcbiAgICAgICAgICA/IDBcbiAgICAgICAgICA6IHNjYWxlKGV4dGVudFsxXSlcbiAgICAgICAgLFxuICAgICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICAgICAgIHJldHVybiB0XG4gICAgICB9KVxuICAgICAgLmF0dHIoJ3dpZHRoJywgaG9yaXpvbnRhbFEgPyBvYmplY3RTaXplIDogMClcbiAgICAgIC5hdHRyKCdoZWlnaHQnLCB2ZXJ0aWNhbFEgPyBvYmplY3RTaXplIDogMClcbiAgICAgIC5yZW1vdmUoKVxuICAgIH0pXG5cblxuICAgIC8vIG1vdmUgc3R1ZmZcbiAgICBzcGFjZXJGdW5jdGlvbihjb250YWluZXIsIG9yZGVyZWQsIDApXG5cblxuXG5cblxuICAgIHZhciBwYXJlbnRJbmRleEFycmF5ID0gW11cbiAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnOm5vdCgudG8tcmVtb3ZlKS4nK29iamVjdENsYXNzKVxuICAgIC5lYWNoKGZ1bmN0aW9uKGQsIGkpe3BhcmVudEluZGV4QXJyYXkucHVzaChOdW1iZXIoZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ3BhcmVudC1pbmRleCcpKSl9KVxuXG5cbiAgICBjb2xvckZ1bmN0aW9uID0gY29sb3JGdW5jdGlvbi5jb2xvckJ5KCkgPT0gJ2luZGV4J1xuICAgID8gY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50KFswLCBNYXRoLm1heCguLi5wYXJlbnRJbmRleEFycmF5KV0pXG4gICAgOiBjb2xvckZ1bmN0aW9uLmRhdGFFeHRlbnQoZXh0ZW50KVxuXG5cblxuICAgIGNvbnRhaW5lci5zZWxlY3RBbGwoJ2cuJytvYmplY3RDbGFzcysnOm5vdCgudG8tcmVtb3ZlKScpLmVhY2goZnVuY3Rpb24oa2V5LCBpKSB7XG4gICAgICAvLyBjb25zb2xlLmxvZyhrZXksIHNjYWxlKGV4dGVudFsxXSkgLSBzY2FsZSh2YWx1ZUV4dHJhY3RvcihrZXksIGkpKSlcbiAgICAgIHZhciB0ID0gZDMuc2VsZWN0KHRoaXMpLFxuICAgICAgY3VycmVudERhdGEgPSBkYXRhW2tleV0sXG4gICAgICB2YWx1ZSA9IHZhbHVlRXh0cmFjdG9yKGtleSwgaSksXG4gICAgICBpID0gdC5hdHRyKCdwYXJlbnQtaW5kZXgnKSA9PSB1bmRlZmluZWQgPyBpIDogdC5hdHRyKCdwYXJlbnQtaW5kZXgnKSxcbiAgICAgIGZpbGxDb2xvciA9IGNvbG9yRnVuY3Rpb24oa2V5LCB2YWx1ZSwgaSwgJ2ZpbGwnKSwgLy8gcHJldmVudCBkdXBsaWNhdGUgY29tcHV0YXRpb25cbiAgICAgIHN0cm9rZUNvbG9yID0gY29sb3JGdW5jdGlvbihrZXksIHZhbHVlLCBpLCAgJ3N0cm9rZScpXG5cblxuICAgICAgdmFyIGJhciA9IHNhZmVTZWxlY3QodCwgJ3JlY3QnLCAnYmFyLXJlY3QnKVxuXG4gICAgICBpZiAoYmFyLmF0dHIoJ3RyYW5zZm9ybScpID09IHVuZGVmaW5lZCkge1xuICAgICAgICBiYXIuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgIHZhclxuICAgICAgICAgIHggPSBob3Jpem9udGFsUVxuICAgICAgICAgICAgPyAwXG4gICAgICAgICAgICA6IDBcbiAgICAgICAgICAsXG4gICAgICAgICAgeSA9IHZlcnRpY2FsUVxuICAgICAgICAgICAgPyAwXG4gICAgICAgICAgICA6IHNjYWxlKGV4dGVudFsxXSlcbiAgICAgICAgICAsXG4gICAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICAgIHJldHVybiB0XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIGhvcml6b250YWxRID8gb2JqZWN0U2l6ZSA6IDApXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCB2ZXJ0aWNhbFEgPyBvYmplY3RTaXplIDogMClcblxuICAgICAgfVxuXG5cbiAgICAgIGJhci50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBob3Jpem9udGFsUVxuICAgICAgICAgID8gb2JqZWN0U2l6ZSAtIG9iamVjdFNpemUgKiBiYXJQZXJjZW50XG4gICAgICAgICAgOiBvcmllbnQgPT0gJ3JpZ2h0J1xuICAgICAgICAgICAgPyBzY2FsZShleHRlbnRbMV0pIC0gc2NhbGUodmFsdWUpXG4gICAgICAgICAgICA6IG9iamVjdFNpemUgLSBvYmplY3RTaXplICogYmFyUGVyY2VudFxuICAgICAgICAgICxcbiAgICAgICAgeSA9IHZlcnRpY2FsUVxuICAgICAgICAgID8gb2JqZWN0U2l6ZSAtIG9iamVjdFNpemUgKiBiYXJQZXJjZW50XG4gICAgICAgICAgOiBzY2FsZShleHRlbnRbMV0pIC0gc2NhbGUodmFsdWUpXG4gICAgICAgICxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcbiAgICAgIC5hdHRyKCd3aWR0aCcsIGhvcml6b250YWxRID8gb2JqZWN0U2l6ZSAqIGJhclBlcmNlbnQgOiBzY2FsZSh2YWx1ZSkpXG4gICAgICAuYXR0cignaGVpZ2h0JywgdmVydGljYWxRID8gb2JqZWN0U2l6ZSAqIGJhclBlcmNlbnQ6IHNjYWxlKHZhbHVlKSlcbiAgICAgIC5hdHRyKCdmaWxsJywgZmlsbENvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZScsIHN0cm9rZUNvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGJhclN0cm9rZVdpZHRoKVxuXG5cblxuICAgICAgdC5vbignbW91c2VvdmVyJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIGNvbnRhaW5lci5zZWxlY3RBbGwoJ2cuJytvYmplY3RDbGFzcykuc3R5bGUoJ29wYWNpdHknLCAwLjIpXG4gICAgICAgIHQuc3R5bGUoJ29wYWNpdHknLCAxKVxuICAgICAgICBiYXIuYXR0cignc3Ryb2tlLXdpZHRoJyxiYXJTdHJva2VXaWR0aCoyKVxuXG4gICAgICB9KVxuICAgICAgdC5vbignbW91c2VvdXQnLCBmdW5jdGlvbigpe1xuICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnLicrb2JqZWN0Q2xhc3MpLnN0eWxlKCdvcGFjaXR5JywgMSlcbiAgICAgICAgYmFyLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGJhclN0cm9rZVdpZHRoKVxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgdG9vbHRpcC5zZWxlY3Rpb24oY29udGFpbmVyLnNlbGVjdEFsbCgnLmJhci1yZWN0JykpXG4gICAgLmRhdGEoZGF0YSlcblxuICAgIHRvb2x0aXAoKVxuXG4gIH1cbiAgcmV0dXJuIGJhclxufVxuIiwiaW1wb3J0IHtoeXBlbmF0ZSwgc2FmZVNlbGVjdH0gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7c2V0dXBDb250YWluZXIsIGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3QsIGNhbGN1bGF0ZVdpZHRoT2ZTcGFjZXIsIGxvZ30gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQge3VuaXF1ZX0gZnJvbSAnLi9hcnJheS1mdW5jdGlvbnMnO1xuaW1wb3J0IHtncm91cGluZ1NwYWNlcn0gZnJvbSAnLi9ncm91cGluZy1zcGFjZXInO1xuaW1wb3J0IHtjb2xvckZ1bmN0aW9uIGFzIENGfSBmcm9tICcuL2NvbG9yLWZ1bmN0aW9uJztcbmltcG9ydCB7dG9vbHRpcCBhcyBUVGlwfSBmcm9tICcuL3Rvb2x0aXAnO1xuXG5cbi8qKlxuICogQ3JlYXRlcyBhIGJ1YmJsZUhlYXRtYXBcbiAqXG4gKiB7QGxpbmsgaHR0cHM6Ly9zdW1uZXVyb24uZ2l0bGFiLmlvL2Qzc20vZGVtb3MvYnViYmxlLWhlYXRtYXAvaW5kZXguaHRtbCBEZW1vfVxuICogQGNvbnN0cnVjdG9yIGJ1YmJsZUhlYXRtYXBcbiAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBzZWxlY3Rpb25cbiAqIEBuYW1lc3BhY2UgYnViYmxlSGVhdG1hcFxuICogQHJldHVybnMge2Z1bmN0aW9ufSBidWJibGVIZWF0bWFwXG4gKi9cbmZ1bmN0aW9uIGJ1YmJsZUhlYXRtYXAoIHNlbGVjdGlvbiApIHtcbiAgdmFyXG4gIC8qKlxuICAqIERhdGEgdG8gcGxvdC4gQXNzdW1lZCB0byBiZSBhIG9iamVjdCwgd2hlcmUgZWFjaCBrZXkgY29ycmVzcG9uZHMgdG8gYSBjZWxsXG4gICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNkYXRhfSlcbiAgKiBAcGFyYW0ge09iamVjdH0gW2RhdGE9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBkYXRhLFxuXG4gIC8qKlxuICAqIEFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSBidWJibGVIZWF0bWFwIGluXG4gICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNzcGFjZVh9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbc3BhY2VYPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VYLFxuICAvKipcbiAgKiBBbW91bnQgb2YgdmVydGljYWwgc3BhY2UgKGluIHBpeGVscykgYXZhaWJsZSB0byByZW5kZXIgdGhlIGJ1YmJsZUhlYXRtYXAgaW5cbiAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwLnNwYWNlWX0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZVk9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzcGFjZVksXG5cbiAgLyoqXG4gICogVGhlIGludGVybmFsIGtleSBvZiB0aGUgY2VsbCBzcGVjaWZpeWluZyB0byB3aGljaCB4IGF4aXMga2V5IGl0IGJlbG9uZ3NcbiAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwLnhLZXl9KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbeEtleT0neCddXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhLZXkgPSAneCcsXG4gIC8qKlxuICAqIFRoZSBpbnRlcm5hbCBrZXkgb2YgdGhlIGNlbGwgc3BlY2lmaXlpbmcgdG8gd2hpY2ggeSBheGlzIGtleSBpdCBiZWxvbmdzXG4gICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcC55S2V5fSlcbiAgKiBAcGFyYW0ge3N0cmluZ30gW3lLZXk9J3knXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB5S2V5ID0gJ3knLFxuICAvKipcbiAgKiBUaGUgaW50ZXJuYWwga2V5IG9mIHRoZSBjZWxsIHNwZWNpZml5aW5nIHdoYXQgdmFsdWUgdG8gdXNlIHRvIGRldGVybWluZSB0aGUgcmFkaXVzXG4gICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcC5yS2V5fSlcbiAgKiBAcGFyYW0ge3N0cmluZ30gW3JLZXk9J3InXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICByS2V5ID0gJ3InLFxuICAvKipcbiAgKiBUaGUgaW50ZXJuYWwga2V5IG9mIHRoZSBjZWxsIHNwZWNpZml5aW5nIHdoYXQgdmFsdWUgdG8gdXNlIHRvIGRldGVybWluZSB0aGUgY29sb3JcbiAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwLnZLZXl9KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbdktleT0ndiddXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHZLZXkgPSAndicsXG5cbiAgLyoqXG4gICogRnVuY3Rpb24gZm9yIGV4dHJhY3RpbmcgdGhlIHRoZSB2YWx1ZSBmcm9tIHhLZXkuXG4gICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcC54RXh0cmFjdG9yfSlcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbeEV4dHJhY3Rvcj1mdW5jdGlvbihrZXksIGkpIHsgcmV0dXJuIGRhdGFba2V5XVt4S2V5XSB9XVxuICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGkpIHtyZXR1cm4gZGF0YVtrZXldW3hLZXldIH0sXG4gIC8qKlxuICAqIEZ1bmN0aW9uIGZvciBleHRyYWN0aW5nIHRoZSB0aGUgdmFsdWUgZnJvbSB5S2V5LlxuICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAueUV4dHJhY3Rvcn0pXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3lFeHRyYWN0b3I9ZnVuY3Rpb24oa2V5LCBpKSB7IHJldHVybiBkYXRhW2tleV1beUtleV0gfV1cbiAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB5RXh0cmFjdG9yID0gZnVuY3Rpb24oa2V5LCBpKSB7IHJldHVybiBkYXRhW2tleV1beUtleV0gfSxcbiAgLyoqXG4gICogRnVuY3Rpb24gZm9yIGV4dHJhY3RpbmcgdGhlIHRoZSB2YWx1ZSBmcm9tIHJLZXkuXG4gICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcC5yRXh0cmFjdG9yfSlcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbckV4dHJhY3Rvcj1mdW5jdGlvbihrZXksIGkpIHsgcmV0dXJuIGRhdGFba2V5XVtyS2V5XSB9XVxuICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHJFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGkpIHsgcmV0dXJuIGRhdGFba2V5XVtyS2V5XSB9LFxuICAvKipcbiAgKiBGdW5jdGlvbiBmb3IgZXh0cmFjdGluZyB0aGUgdGhlIHZhbHVlIGZyb20gdktleS5cbiAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwLnZFeHRyYWN0b3J9KVxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFt2RXh0cmFjdG9yPWZ1bmN0aW9uKGtleSwgaSkgeyByZXR1cm4gZGF0YVtrZXldW3ZLZXldIH1dXG4gICogQHJldHVybnMge251bWJlcn1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdkV4dHJhY3RvciA9IGZ1bmN0aW9uKGtleSwgaSkgeyByZXR1cm4gZGF0YVtrZXldW3ZLZXldIH0sXG5cblxuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0byBhbGxvdyBidWJibGVIZWF0bWFwIHRvIHJlbmRlciBlbGVtZW50cyBwYXNzIHRoZSBtYWluIHNwYXRpYWwgZGltZW5zaW9uXG4gICogZ2l2ZW4gdGhlIG9yaWVudGF0aW9uIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjb3JpZW50fSksIHdoZXJlIHtAbGluayBidWJibGVIZWF0bWFwI29yaWVudH09XCJib3R0b21cIiBvciB7QGxpbmsgYnViYmxlSGVhdG1hcCNvcmllbnR9PVwidG9wXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJ1YmJsZUhlYXRtYXAjc3BhY2VYfSBhbmQgd2hlcmUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjb3JpZW50fT1cImxlZnRcIiBvciB7QGxpbmsgYnViYmxlSGVhdG1hcCNvcmllbnR9PVwicmlnaHRcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgYnViYmxlSGVhdG1hcCNzcGFjZVl9XG4gICogQHBhcmFtIHtib29sZWFufSBbb3ZlcmZsb3dRPWZhbHNlXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvdmVyZmxvd1EgPSBmYWxzZSxcblxuICAvKipcbiAgKiBUaGUgc2NhbGUgZm9yIHdoaWNoIHRoZSByYWRpdXMgdmFsdWVzIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBieVxuICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtzY2FsZT1kMy5zY2FsZUxpbmVhcl1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc2NhbGUgPSBkMy5zY2FsZUxpbmVhcigpLFxuICAvKipcbiAgKiBUaGUgcGFkZGluZyBmb3IgdGhlIGRvbWFpbiBvZiB0aGUgc2NhbGUgKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNzY2FsZX0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtkb21haW5QYWRkaW5nPTAuNV1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZG9tYWluUGFkZGluZyA9IDAuNSxcblxuICAvKipcbiAgKiBEZWZhdWx0IHNwYWNlIGZvciB0aGUgc3BhY2VyIChwZXJjZW50YWdlKSBvZiBtYWluIGRpbWVuc2lvbiBnaXZlbiB0aGUgb3JpZW50YXRpb25cbiAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI29yaWVudH0pLCB3aGVyZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNvcmllbnR9PVwiaG9yaXpvbnRhbFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayBidWJibGVIZWF0bWFwI3NwYWNlWH0gYW5kIHdoZXJlIHtAbGluayBidWJibGVIZWF0bWFwI29yaWVudH09XCJ2ZXJ0aWNhbFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayBidWJibGVIZWF0bWFwI3NwYWNlWX0gYmV0d2VlbiBidWJibGVzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtvYmplY3RTcGFjZXI9MC4wXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvYmplY3RTcGFjZXIgPSAwLjAsXG4gIC8qKlxuICAqIFRoZSBtaW5pbXVtIHNpemUgdGhhdCBhbiBvYmplY3QgY2FuIGJlXG4gICogQHBhcmFtIHtudW1iZXJ9IFttaW5PYmplY3RTaXplPTUwXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBtaW5PYmplY3RTaXplID0gNTAsXG4gIC8qKlxuICAqIFRoZSBtYXhpbXVtIHNpemUgdGhhdCBhbiBvYmplY3QgY2FuIGJlXG4gICogQHBhcmFtIHtudW1iZXJ9IFttYXhPYmplY3RTaXplPTEwMF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbWF4T2JqZWN0U2l6ZSA9IDEwMCxcblxuXG4gIC8qKlxuICAqIFRoZSBzdHJva2Ugd2lkdGggb2YgdGhlIGJ1YmJsZXNcbiAgKiBAcGFyYW0ge251bWJlcn0gW2J1YmJsZVN0cm9rZVdpZHRoPTJdXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJ1YmJsZVN0cm9rZVdpZHRoID0gMixcbiAgLy8gY29sb3JGdW5jID0gY29sb3JGdW5jdGlvbigpLFxuXG4gIC8qKlxuICAqIENvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kXG4gICogQHBhcmFtIHtzdHJpbmd9IFtiYWNrZ3JvdW5kRmlsbD1cInRyYW5zcGFyZW50XCJdXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJhY2tncm91bmRGaWxsID0gJ3RyYW5zcGFyZW50JyxcbiAgLyoqXG4gICogTmFtZXNwYWNlIGZvciBhbGwgaXRlbXMgbWFkZSBieSB0aGlzIGluc3RhbmNlIG9mIGJ1YmJsZUhlYXRtYXBcbiAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWVzcGFjZT1cImQzc20tYnViYmxlXCJdXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG5hbWVzcGFjZSA9ICdkM3NtLWJ1YmJsZScsXG4gIC8qKlxuICAqIENsYXNzIG5hbWUgZm9yIGJ1YmJsZSBjb250YWluZXIgKDxnPiBlbGVtZW50KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbb2JqZWN0Q2xhc3M9XCJidWJibGVcIl1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0Q2xhc3MgPSAnYnViYmxlJyxcbiAgLyoqXG4gICogRHVyYXRpb24gb2YgYWxsIHRyYW5zaXRpb25zIG9mIHRoaXMgZWxlbWVudFxuICAqIEBwYXJhbSB7bnVtYmVyfSBbdHJhbnNpdGlvbkR1cmF0aW9uPTEwMDBdXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRyYW5zaXRpb25EdXJhdGlvbiA9IDEwMDAsXG4gIC8qKlxuICAqIEVhc2luZyBmdW5jdGlvbiBmb3IgdHJhbnNpdGlvbnNcbiAgKiBAcGFyYW0ge2QzLmVhc2V9IFtlYXNlRnVuYz1kMy5lYXNlRXhwXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBlYXNlRnVuYyA9IGQzLmVhc2VFeHAsXG5cbiAgLyoqXG4gICogU3RvcmVzIHRoZSBrZXlzIG9mIGFsbCB0aGUgY2VsbHNcbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGJ1YmJsZUhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFtjZWxsS2V5cz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGNlbGxLZXlzLFxuICAvKipcbiAgKiBTdG9yZXMgdGhlIGxpc3Qgb2YgdW5pcXVlIHhWYWx1ZXNcbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGJ1YmJsZUhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt4VmFsdWVzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeFZhbHVlcyxcbiAgLyoqXG4gICogU3RvcmVzIHRoZSBsaXN0IG9mIHVuaXF1ZSB5VmFsdWVzXG4gICogQ2FsY3VsYXRlZCBhZnRlciBidWJibGVIZWF0bWFwIGNhbGxlZC5cbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbeVZhbHVlcz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHlWYWx1ZXMsXG4gIC8qKlxuICAqIFN0b3JlcyB0aGUgbGlzdCBvZiB1bmlxdWUgclZhbHVlc1xuICAqIENhbGN1bGF0ZWQgYWZ0ZXIgYnViYmxlSGVhdG1hcCBjYWxsZWQuXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW3JWYWx1ZXM9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICByVmFsdWVzLFxuICAvKipcbiAgKiBTdG9yZXMgdGhlIGxpc3Qgb2YgdW5pcXVlIHZWYWx1ZXNcbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGJ1YmJsZUhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt2VmFsdWVzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdlZhbHVlcyxcblxuICB4S2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4geEV4dHJhY3RvcihhKSAtIHhFeHRyYWN0b3IoYikgfSxcbiAgeUtleVNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIHlFeHRyYWN0b3IoYSkgLSB5RXh0cmFjdG9yKGIpIH0sXG4gIHJLZXlTb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihhLCBiKSB7IHJldHVybiByRXh0cmFjdG9yKGEpIC0gckV4dHJhY3RvcihiKSB9LFxuICB2S2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gdkV4dHJhY3RvcihhKSAtIHZFeHRyYWN0b3IoYikgfSxcblxuICAvKipcbiAgKiBJbnN0YW5jZSBvZiBDb2xvckZ1bmN0aW9uIHdpdGggLmNvbG9yQnkgc2V0IHRvICdjYXRlZ29yeSdcbiAgKiBAZnVuY3Rpb24gY29sb3JGdW5jdGlvblxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjb2xvckZ1bmN0aW9uID0gQ0YoKS5jb2xvckJ5KCd2YWx1ZScpLFxuICAvKipcbiAgKiBJbnN0YW5jZSBvZiBUb29sdGlwXG4gICogQGZ1bmN0aW9uIHRvb2x0aXBcbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdG9vbHRpcCA9IFRUaXAoKSxcblxuICAvKipcbiAgKiBzdG9yZSB0aGUgc2l6ZSB0aGUgYnViYmxlIGNvdWxkIGJlIGluIHRoZSB4IGRpbWVuc2lvblxuICAqIHRoZSBhY3R1YWxsIHNpemUgb2YgdGhlIGJ1YmJsZSB3aWxsIGJlIHRoZSBtaW4gb2YgeFNpemUgYW5kIHtAbGluayBidWJibGVIZWF0bWFwI3lTaXplfVxuICAqIENhbGN1bGF0ZWQgYWZ0ZXIgYnViYmxlSGVhdG1hcCBjYWxsZWQuXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW3hTaXplPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeFNpemUsXG4gIC8qKlxuICAqIHN0b3JlIHRoZSBzaXplIG9mIHRoZSBzcGFjZXIgaW4gdGhlIHggZGltZW5zaW9uXG4gICogQ2FsY3VsYXRlZCBhZnRlciBidWJibGVIZWF0bWFwIGNhbGxlZC5cbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbeFNwYWNlclNpemU9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB4U3BhY2VyU2l6ZSxcblxuICAvKipcbiAgKiBzdG9yZSB0aGUgc2l6ZSB0aGUgYnViYmxlIGNvdWxkIGJlIGluIHRoZSB5IGRpbWVuc2lvblxuICAqIHRoZSBhY3R1YWxsIHNpemUgb2YgdGhlIGJ1YmJsZSB3aWxsIGJlIHRoZSBtaW4gb2YgeFNpemUgYW5kIHtAbGluayBidWJibGVIZWF0bWFwI3hTaXplfVxuICAqIENhbGN1bGF0ZWQgYWZ0ZXIgYnViYmxlSGVhdG1hcCBjYWxsZWQuXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW3lTaXplPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeVNpemUsXG4gIC8qKlxuICAqIHN0b3JlIHRoZSBzaXplIG9mIHRoZSBzcGFjZXIgaW4gdGhlIHkgZGltZW5zaW9uLlxuICAqIENhbGN1bGF0ZWQgYWZ0ZXIgYnViYmxlSGVhdG1hcCBjYWxsZWQuXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW3hTcGFjZXJTaXplPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeVNwYWNlclNpemVcblxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBzZWxlY3Rpb24gaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IGQzLnNlbGVjdGlvbn1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc2VsZWN0aW9uID0gc2VsZWN0aW9uXG4gICAqL1xuICBiaG0uc2VsZWN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZWxlY3Rpb24gPSBfLCBiaG0pIDogc2VsZWN0aW9uOyB9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGRhdGFcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNkYXRhfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgb2JqZWN0fVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGJobS5kYXRhID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkYXRhID0gXywgYmhtKSA6IGRhdGE7IH1cbiAgLy8gYmhtLm9yaWVudCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3JpZW50ID0gXywgYmhtKSA6IG9yaWVudDsgfVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBhbW91bnQgb2YgaG9yaXpvbnRhbCBzcGFjZSBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNzcGFjZVh9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV0gc2hvdWxkIGJlIGEgbnVtYmVyID4gMFxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc3BhY2VYID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0uc3BhY2VYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVggPSBfLCBiaG0pIDogc3BhY2VYOyB9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiB2ZXJ0aWNhbCBzcGFjZSBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNzcGFjZVl9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV0gc2hvdWxkIGJlIGEgbnVtYmVyID4gMFxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc3BhY2VZID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0uc3BhY2VZID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVkgPSBfLCBiaG0pIDogc3BhY2VZOyB9XG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeEtleVxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3hLZXl9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHhLZXkgPSAneCdcbiAgICovXG4gIGJobS54S2V5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4S2V5ID0gXywgYmhtKSA6IHhLZXk7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeUtleVxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3lLZXl9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHlLZXkgPSAneSdcbiAgICovXG4gIGJobS55S2V5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5S2V5ID0gXywgYmhtKSA6IHlLZXk7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgcktleVxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3JLZXl9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHJLZXkgPSAncidcbiAgICovXG4gIGJobS5yS2V5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChyS2V5ID0gXywgYmhtKSA6IHJLZXk7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgdktleVxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3ZLZXl9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZLZXkgPSAneSdcbiAgICovXG4gIGJobS52S2V5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2S2V5ID0gXywgYmhtKSA6IHZLZXk7IH1cblxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBjZWxsS2V5c1xuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI2NlbGxLZXlzfSlcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmdbXX1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgY2VsbEtleXMgPSB1bmRlZmluZWRcbiAgICovXG4gIGJobS5jZWxsS2V5cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY2VsbEtleXMgPSBfLCBiaG0pIDogY2VsbEtleXM7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeFZhbHVlc1xuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3hWYWx1ZXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB4VmFsdWVzID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0ueFZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeFZhbHVlcyA9IF8sIGJobSkgOiB4VmFsdWVzOyB9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHlWYWx1ZXNcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCN5VmFsdWVzfSlcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmdbXX1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgeVZhbHVlcyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmhtLnlWYWx1ZXMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlWYWx1ZXMgPSBfLCBiaG0pIDogeVZhbHVlczsgfVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSByVmFsdWVzXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjclZhbHVlc30pXG4gICAqIEBwYXJhbSB7bnVtYmVyW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgbnVtYmVyW119XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHJWYWx1ZXMgPSB1bmRlZmluZWRcbiAgICovXG4gIGJobS5yVmFsdWVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChyVmFsdWVzID0gXywgYmhtKSA6IHJWYWx1ZXM7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgdlZhbHVlc1xuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3ZWYWx1ZXN9KVxuICAgKiBAcGFyYW0ge251bWJlcltdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IG51bWJlcltdfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB2VmFsdWVzID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0udlZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodlZhbHVlcyA9IF8sIGJobSkgOiB2VmFsdWVzOyB9XG5cblxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB4RXh0cmFjdG9yXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjeEV4dHJhY3Rvcn0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHhFeHRyYWN0b3IgPSB1bmRlZmluZWRcbiAgICovXG4gIGJobS54RXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4RXh0cmFjdG9yID0gXywgYmhtKSA6IHhFeHRyYWN0b3I7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeUV4dHJhY3RvclxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3lFeHRyYWN0b3J9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5RXh0cmFjdG9yID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0ueUV4dHJhY3RvciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeUV4dHJhY3RvciA9IF8sIGJobSkgOiB5RXh0cmFjdG9yOyB9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHJFeHRyYWN0b3JcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNyRXh0cmFjdG9yfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgckV4dHJhY3RvciA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmhtLnJFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHJFeHRyYWN0b3IgPSBfLCBiaG0pIDogckV4dHJhY3RvcjsgfVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB2RXh0cmFjdG9yXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjdkV4dHJhY3Rvcn0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZFeHRyYWN0b3IgPSB1bmRlZmluZWRcbiAgICovXG4gIGJobS52RXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2RXh0cmFjdG9yID0gXywgYmhtKSA6IHZFeHRyYWN0b3I7IH1cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgd2hldGhlciBvciBub3QgYnViYmxlSGVhdG1hcCBpcyBhbGxvd2VkIHRvIGdvIGJleW9uZCBzcGVjaWZpZWQgZGltZW5zaW9uc1xuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3NwYWNlWH0pXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBib29sZWFufVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvdmVyZmxvd1EgPSBmYWxzZVxuICAgKi9cbiAgYmhtLm92ZXJmbG93USA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3ZlcmZsb3dRID0gXywgYmhtKSA6IG92ZXJmbG93UTsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHNjYWxlIGZvciB3aGljaCB0aGUgcmFkaXVzIG9mIGJ1YmJsZXMgc2hvdWxkIGJlIHRyYW5zZm9ybWVkIGJ5XG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjc2NhbGV9KVxuICAgKiBAcGFyYW0ge2QzLnNjYWxlfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IGQzLnNjYWxlfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKClcbiAgICovXG4gIGJobS5zY2FsZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGUgPSBfLCBiaG0pIDogc2NhbGU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcGFkZGluZyBmb3IgdGhlIGRvbWFpbiBvZiB0aGUgc2NhbGVcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNkb21haW5QYWRkaW5nfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBkb21haW5QYWRkaW5nID0gMC41XG4gICAqL1xuICBiaG0uZG9tYWluUGFkZGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluUGFkZGluZyA9IF8sIGJobSkgOiBkb21haW5QYWRkaW5nOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgb2JqZWN0U3BhY2VyXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjb2JqZWN0U3BhY2VyfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RTcGFjZXIgPSAwLjBcbiAgICovXG4gIGJobS5vYmplY3RTcGFjZXIgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNwYWNlciA9IF8sIG9iamVjdFNwYWNlcikgOiBkYXRhOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbWluT2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI21pbk9iamVjdFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1pbk9iamVjdFNpemUgPSA1MFxuICAgKi9cbiAgYmhtLm1pbk9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1pbk9iamVjdFNpemUgPSBfLCBiaG0pIDogbWluT2JqZWN0U2l6ZTsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1heE9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNtYXhPYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBtYXhPYmplY3RTaXplID0gMTAwXG4gICAqL1xuICBiaG0ubWF4T2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobWF4T2JqZWN0U2l6ZSA9IF8sIGJobSkgOiBtYXhPYmplY3RTaXplOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYnViYmxlU3Ryb2tlV2lkdGhcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNidWJibGVTdHJva2VXaWR0aH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYnViYmxlU3Ryb2tlV2lkdGggPSAyXG4gICAqL1xuICBiaG0uYnViYmxlU3Ryb2tlV2lkdGggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJ1YmJsZVN0cm9rZVdpZHRoID0gXywgYmhtKSA6IGJ1YmJsZVN0cm9rZVdpZHRoOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYmFja2dyb3VuZEZpbGxcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNiYWNrZ3JvdW5kRmlsbH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYmFja2dyb3VuZEZpbGwgPSAndHJhbnNwYXJlbnQnXG4gICAqL1xuICBiaG0uYmFja2dyb3VuZEZpbGwgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJhY2tncm91bmRGaWxsID0gXywgYmhtKSA6IGJhY2tncm91bmRGaWxsOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbmFtZXNwYWNlXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjbmFtZXNwYWNlfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBuYW1lc3BhY2UgPSAnZDNzbS1idWJibGVIZWF0bWFwJ1xuICAgKi9cbiAgYmhtLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgYmhtKSA6IG5hbWVzcGFjZTsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG9iamVjdENsYXNzXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjb2JqZWN0Q2xhc3N9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG9iamVjdENsYXNzID0gJ3RpY2stZ3JvdXAnXG4gICAqL1xuICBiaG0ub2JqZWN0Q2xhc3MgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdENsYXNzID0gXywgYmhtKSA6IG9iamVjdENsYXNzOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdHJhbnNpdGlvbkR1cmF0aW9uXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjdHJhbnNpdGlvbkR1cmF0aW9ufSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwXG4gICAqL1xuICBiaG0udHJhbnNpdGlvbkR1cmF0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0cmFuc2l0aW9uRHVyYXRpb24gPSBfLCBiaG0pIDogdHJhbnNpdGlvbkR1cmF0aW9uOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgZWFzZUZ1bmNcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNlYXNlRnVuY30pXG4gICAqIEBwYXJhbSB7ZDMuZWFzZX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBkMy5lYXNlfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBlYXNlRnVuYyA9IGQzLmVhc2VFeHBcbiAgICovXG4gIGJobS5lYXNlRnVuYyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZWFzZUZ1bmMgPSBfLCBiaG0pIDogZWFzZUZ1bmM7IH1cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRvb2x0aXBcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCN0b29sdGlwfSlcbiAgICogQHBhcmFtIHt0b29sdGlwfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IHRvb2x0aXB9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRvb2x0aXAgPSB0b29sdGlwKClcbiAgICovXG4gIGJobS50b29sdGlwID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0b29sdGlwID0gXywgYmhtKSA6IHRvb2x0aXA7IH1cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGNvbG9yRnVuY3Rpb25cbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNjb2xvckZ1bmN0aW9ufSlcbiAgICogQHBhcmFtIHtjb2xvckZ1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IGNvbG9yRnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGNvbG9yRnVuY3Rpb24gPSBjb2xvckZ1bmN0aW9uKClcbiAgICovXG4gIGJobS5jb2xvckZ1bmN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjb2xvckZ1bmN0aW9uID0gXywgYmhtKSA6IGNvbG9yRnVuY3Rpb247IH1cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHhTaXplXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjeFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHhTaXplID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0ueFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhTaXplID0gXywgYmhtKSA6IHhTaXplOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgeFNwYWNlclNpemVcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCN4U3BhY2VyU2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgeFNwYWNlclNpemUgPSB1bmRlZmluZWRcbiAgICovXG4gIGJobS54U3BhY2VyU2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeFNwYWNlclNpemUgPSBfLCBiaG0pIDogeFNwYWNlclNpemU7IH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB5U2l6ZVxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3lTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5U2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmhtLnlTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5U2l6ZSA9IF8sIGJobSkgOiB5U2l6ZTsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHlTcGFjZXJTaXplXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjeVNwYWNlclNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHlTcGFjZXJTaXplID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0ueVNwYWNlclNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlTcGFjZXJTaXplID0gXywgYmhtKSA6IHlTcGFjZXJTaXplOyB9XG4gIC8vIGJobS55S2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5S2V5U29ydGluZ0Z1bmN0aW9uID0gXywgYmhtKSA6IHlLZXlTb3J0aW5nRnVuY3Rpb247IH1cbiAgLy8gYmhtLnhLZXlTb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhLZXlTb3J0aW5nRnVuY3Rpb24gPSBfLCBiaG0pIDogeEtleVNvcnRpbmdGdW5jdGlvbjsgfVxuXG5cblxuICBmdW5jdGlvbiBiaG0oKSB7XG4gICAgdmFyIGhvcml6b250YWxRID0gdHJ1ZTsgLy8gbm8gb3JpZW50YXRpb24gaW4gaGVhdG1hcHMuIEFpZHMgYXMgcGxhY2Vob2xkZXIgaW4gZnVuY3Rpb25zIHRoYXQgdGFrZSBvcmllbnQgYXMgYSBwYXJhbWV0ZXJcbiAgICB2YXIgYmdjcFJlY3QgPSB7eDowLCB5OjAsIHdpZHRoOiBzcGFjZVgsIGhlaWdodDpzcGFjZVl9XG4gICAgdmFyIGNvbnRhaW5lciA9IHNldHVwQ29udGFpbmVyKCBzZWxlY3Rpb24sIG5hbWVzcGFjZSwgYmdjcFJlY3QsIGJhY2tncm91bmRGaWxsICk7XG5cbiAgICBjZWxsS2V5cyA9IGQzLmtleXMoZGF0YSk7XG4gICAgY2VsbEtleXMuc29ydChmdW5jdGlvbihhLCBiKXsgcmV0dXJuIHhLZXlTb3J0aW5nRnVuY3Rpb24oYSwgYikgfHwgeUtleVNvcnRpbmdGdW5jdGlvbihhLCBiKSB9KVxuICAgIGxvZygnYnViYmxlSGVhdG1hcCcsICdjZWxscyBhcmUgc29ydGVkIGJ5JywgY2VsbEtleXMpXG5cblxuXG4gICAgeFZhbHVlcyA9IHVuaXF1ZShjZWxsS2V5cy5tYXAoeEV4dHJhY3RvcikpO1xuICAgIHlWYWx1ZXMgPSB1bmlxdWUoY2VsbEtleXMubWFwKHlFeHRyYWN0b3IpKTtcbiAgICByVmFsdWVzID0gdW5pcXVlKGNlbGxLZXlzLm1hcChyRXh0cmFjdG9yKSk7XG4gICAgdlZhbHVlcyA9IHVuaXF1ZShjZWxsS2V5cy5tYXAodkV4dHJhY3RvcikpO1xuICAgIGxvZygnYnViYmxlSGVhdG1hcCcsICd4IGFuZCB5IGtleXMgYXJlJywge3g6IHhWYWx1ZXMsIHk6eVZhbHVlc30pXG5cblxuICAgIHZhciB4RGltID0geFZhbHVlcy5sZW5ndGgsIHlEaW0gPSB5VmFsdWVzLmxlbmd0aDtcblxuXG4gICAgdmFyIGV4dGVudCA9IFtNYXRoLm1pbiguLi5yVmFsdWVzKSAtIGRvbWFpblBhZGRpbmcsTWF0aC5tYXgoLi4uclZhbHVlcykgKyBkb21haW5QYWRkaW5nXTtcblxuXG4gICAgeVNpemUgPSBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0KHNwYWNlWSwgeURpbSwgbWluT2JqZWN0U2l6ZSwgbWF4T2JqZWN0U2l6ZSwgb2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgeFNpemUgPSBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0KHNwYWNlWCwgeERpbSwgbWluT2JqZWN0U2l6ZSwgbWF4T2JqZWN0U2l6ZSwgb2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgeVNwYWNlclNpemUgPSBjYWxjdWxhdGVXaWR0aE9mU3BhY2VyKHlWYWx1ZXMsIHNwYWNlWSwgeVNpemUsIHlEaW0sIG9iamVjdFNwYWNlciwgb3ZlcmZsb3dRKVxuICAgIHhTcGFjZXJTaXplID0gY2FsY3VsYXRlV2lkdGhPZlNwYWNlcih4VmFsdWVzLCBzcGFjZVgsIHhTaXplLCB4RGltLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICBsb2coJ2J1YmJsZUhlYXRtYXAnLCAnc2l6ZSBvZicsIHt4OiB4U2l6ZSwgeTogeVNpemV9KVxuXG5cbiAgICBzY2FsZS5kb21haW4oZXh0ZW50KS5yYW5nZShbTWF0aC5taW4obWluT2JqZWN0U2l6ZS8yLCAgIE1hdGgubWluKHlTaXplLCB4U2l6ZSkvMiksIE1hdGgubWluKHlTaXplLCB4U2l6ZSkvMl0pXG5cbiAgICB2YXIgeVNwYWNlciA9IGdyb3VwaW5nU3BhY2VyKClcbiAgICAuaG9yaXpvbnRhbFEoZmFsc2UpXG4gICAgLm1vdmVieSgnY2F0ZWdvcnknKS5udW1iZXJPZk9iamVjdHMoeURpbSlcbiAgICAub2JqZWN0Q2xhc3MoaHlwZW5hdGUob2JqZWN0Q2xhc3MsICdyb3cnKSlcbiAgICAub2JqZWN0U2l6ZSh5U2l6ZSkuc3BhY2VyU2l6ZSh5U3BhY2VyU2l6ZSlcbiAgICAudHJhbnNpdGlvbkR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbikuZWFzZUZ1bmMoZWFzZUZ1bmMpXG4gICAgLm5hbWVzcGFjZSgncm93JylcblxuICAgIHZhciB4U3BhY2VyID0gZ3JvdXBpbmdTcGFjZXIoKVxuICAgIC5ob3Jpem9udGFsUSh0cnVlKVxuICAgIC5tb3ZlYnkoJ2NhdGVnb3J5JykubnVtYmVyT2ZPYmplY3RzKHhEaW0pXG4gICAgLm9iamVjdENsYXNzKG9iamVjdENsYXNzKVxuICAgIC5vYmplY3RTaXplKHhTaXplKS5zcGFjZXJTaXplKHhTcGFjZXJTaXplKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlRnVuYyhlYXNlRnVuYylcblxuXG4gICAgeVNwYWNlcihjb250YWluZXIsIHlWYWx1ZXMsIDApXG4gICAgY29udGFpbmVyLnNlbGVjdEFsbCgnZy4nK2h5cGVuYXRlKG9iamVjdENsYXNzLCAncm93JykpXG4gICAgLmVhY2goZnVuY3Rpb24oZCwgaSl7XG4gICAgICB4U3BhY2VyKGQzLnNlbGVjdCh0aGlzKSwgeFZhbHVlcywgMClcbiAgICB9KVxuICAgIHZhciBjZWxscyA9IGNvbnRhaW5lci5zZWxlY3RBbGwoJ2c6bm90KC50by1yZW1vdmUpLicrb2JqZWN0Q2xhc3MpLmRhdGEoY2VsbEtleXMpO1xuXG4gICAgdmFyIHBhcmVudEluZGV4QXJyYXkgPSBbXVxuICAgIGNlbGxzLmVhY2goZnVuY3Rpb24oZCwgaSl7IHBhcmVudEluZGV4QXJyYXkucHVzaChOdW1iZXIoZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ3BhcmVudC1pbmRleCcpKSkgfSlcblxuXG4gICAgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24uY29sb3JCeSgpID09ICdpbmRleCdcbiAgICA/IGNvbG9yRnVuY3Rpb24uZGF0YUV4dGVudChbMCwgTWF0aC5tYXgoLi4ucGFyZW50SW5kZXhBcnJheSldKVxuICAgIDogY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50KFswLCBNYXRoLm1heCguLi52VmFsdWVzKV0pXG5cbiAgICBjZWxscy5lYWNoKGZ1bmN0aW9uKGtleSwgaSkge1xuICAgICAgbG9nKCdidWJibGVIZWF0bWFwJywgJ2VhY2ggY2VsbCcsIHtrZXk6IGtleSwgaW5kZXg6IGksIG5vZGU6IGQzLnNlbGVjdCh0aGlzKS5ub2RlKCl9KVxuXG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKSxcbiAgICAgIGN1cnJlbnREYXRhID0gZGF0YVtrZXldLFxuICAgICAgdmFsdWUgPSB2RXh0cmFjdG9yKGtleSwgaSksXG4gICAgICByYWRpdXM9IHJFeHRyYWN0b3Ioa2V5LCBpKSxcbiAgICAgIGkgPSB0LmF0dHIoJ3BhcmVudC1pbmRleCcpID09IHVuZGVmaW5lZCA/IGkgOiB0LmF0dHIoJ3BhcmVudC1pbmRleCcpLFxuICAgICAgZmlsbENvbG9yID0gY29sb3JGdW5jdGlvbihrZXksIHZhbHVlLCBpLCAnZmlsbCcpLCAvLyBwcmV2ZW50IGR1cGxpY2F0ZSBjb21wdXRhdGlvblxuICAgICAgc3Ryb2tlQ29sb3IgPSBjb2xvckZ1bmN0aW9uKGtleSwgdmFsdWUsIGksICAnc3Ryb2tlJylcblxuICAgICAgbG9nKCdidWJibGVIZWF0bWFwJywgJ3JhZGl1cycse3JhZGl1czogcmFkaXVzLCBzY2FsZWQ6IHNjYWxlKHJhZGl1cyksIGV4dGVudDogZXh0ZW50LCByYW5nZTpzY2FsZS5yYW5nZSgpfSlcblxuICAgICAgdmFyIGMgPSBzYWZlU2VsZWN0KHQsICdjaXJjbGUnLCBoeXBlbmF0ZShvYmplY3RDbGFzcywnY2lyY2xlJykpXG4gICAgICBjLmF0dHIoJ2N4JywgeFNpemUgLyAyKVxuICAgICAgLmF0dHIoJ2N5JywgeVNpemUgLyAyIClcbiAgICAgIC5hdHRyKCdyJywgc2NhbGUocmFkaXVzKSlcbiAgICAgIC5hdHRyKCdmaWxsJywgZmlsbENvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZScsIHN0cm9rZUNvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGJ1YmJsZVN0cm9rZVdpZHRoKVxuXG4gICAgfSlcblxuICAgIHRvb2x0aXAuc2VsZWN0aW9uKGNlbGxzLnNlbGVjdEFsbCgnY2lyY2xlLicraHlwZW5hdGUob2JqZWN0Q2xhc3MsICdjaXJjbGUnKSkpXG4gICAgLmRhdGEoZGF0YSlcbiAgICAvLyAua2V5cyhbJ3InLCAndiddKVxuICAgIC8vIC5oZWFkZXIoZnVuY3Rpb24oZCwgaSl7cmV0dXJuIGh5cGVuYXRlKGRhdGFbZF1beEtleV0sIGRhdGFbZF1beUtleV0pIH0pXG5cbiAgICB0b29sdGlwKClcblxuXG4gIH1cblxuICByZXR1cm4gYmhtO1xufVxuXG5leHBvcnQge2J1YmJsZUhlYXRtYXB9XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtzZXR1cENvbnRhaW5lciwgY2FsY3VsYXRlV2lkdGhPZk9iamVjdCwgY2FsY3VsYXRlV2lkdGhPZlNwYWNlciwgbG9nfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7dW5pcXVlfSBmcm9tICcuL2FycmF5LWZ1bmN0aW9ucyc7XG5pbXBvcnQge2dyb3VwaW5nU3BhY2VyfSBmcm9tICcuL2dyb3VwaW5nLXNwYWNlcic7XG5pbXBvcnQge2NvbG9yRnVuY3Rpb24gYXMgQ0Z9IGZyb20gJy4vY29sb3ItZnVuY3Rpb24nO1xuaW1wb3J0IHt0b29sdGlwIGFzIFRUaXB9IGZyb20gJy4vdG9vbHRpcCc7XG5cblxuLyoqXG4gKiBDcmVhdGVzIGEgaGVhdG1hcFxuICpcbiAqIHtAbGluayBodHRwczovL3N1bW5ldXJvbi5naXRsYWIuaW8vZDNzbS9kZW1vcy9oZWF0bWFwLWhlYXRtYXAvaW5kZXguaHRtbCBEZW1vfVxuICogQGNvbnN0cnVjdG9yIGhlYXRtYXBcbiAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBzZWxlY3Rpb25cbiAqIEBuYW1lc3BhY2UgaGVhdG1hcFxuICogQHJldHVybnMge2Z1bmN0aW9ufSBoZWF0bWFwXG4gKi9cbmZ1bmN0aW9uIGhlYXRtYXAoIHNlbGVjdGlvbiApIHtcbiAgdmFyXG4gIC8qKlxuICAqIERhdGEgdG8gcGxvdC4gQXNzdW1lZCB0byBiZSBhIG9iamVjdCwgd2hlcmUgZWFjaCBrZXkgY29ycmVzcG9uZHMgdG8gYSBjZWxsXG4gICogKHNlZSB7QGxpbmsgaGVhdG1hcCNkYXRhfSlcbiAgKiBAcGFyYW0ge09iamVjdH0gW2RhdGE9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBkYXRhLFxuXG4gIC8qKlxuICAqIEFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSBoZWF0bWFwIGluXG4gICogKHNlZSB7QGxpbmsgaGVhdG1hcCNzcGFjZVh9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbc3BhY2VYPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VYLFxuICAvKipcbiAgKiBBbW91bnQgb2YgdmVydGljYWwgc3BhY2UgKGluIHBpeGVscykgYXZhaWJsZSB0byByZW5kZXIgdGhlIGhlYXRtYXAgaW5cbiAgKiAoc2VlIHtAbGluayBoZWF0bWFwLnNwYWNlWX0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZVk9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzcGFjZVksXG5cbiAgLyoqXG4gICogVGhlIGludGVybmFsIGtleSBvZiB0aGUgY2VsbCBzcGVjaWZpeWluZyB0byB3aGljaCB4IGF4aXMga2V5IGl0IGJlbG9uZ3NcbiAgKiAoc2VlIHtAbGluayBoZWF0bWFwLnhLZXl9KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbeEtleT0neCddXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhLZXkgPSAneCcsXG4gIC8qKlxuICAqIFRoZSBpbnRlcm5hbCBrZXkgb2YgdGhlIGNlbGwgc3BlY2lmaXlpbmcgdG8gd2hpY2ggeSBheGlzIGtleSBpdCBiZWxvbmdzXG4gICogKHNlZSB7QGxpbmsgaGVhdG1hcC55S2V5fSlcbiAgKiBAcGFyYW0ge3N0cmluZ30gW3lLZXk9J3knXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB5S2V5ID0gJ3knLFxuXG4gIC8qKlxuICAqIFRoZSBpbnRlcm5hbCBrZXkgb2YgdGhlIGNlbGwgc3BlY2lmaXlpbmcgd2hhdCB2YWx1ZSB0byB1c2UgdG8gZGV0ZXJtaW5lIHRoZSBjb2xvclxuICAqIChzZWUge0BsaW5rIGhlYXRtYXAudktleX0pXG4gICogQHBhcmFtIHtzdHJpbmd9IFt2S2V5PSd2J11cbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdktleSA9ICd2JyxcblxuICAvKipcbiAgKiBGdW5jdGlvbiBmb3IgZXh0cmFjdGluZyB0aGUgdGhlIHZhbHVlIGZyb20geEtleS5cbiAgKiAoc2VlIHtAbGluayBoZWF0bWFwLnhFeHRyYWN0b3J9KVxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFt4RXh0cmFjdG9yPWZ1bmN0aW9uKGtleSwgaSkgeyByZXR1cm4gZGF0YVtrZXldW3hLZXldIH1dXG4gICogQHJldHVybnMge3N0cmluZ31cbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeEV4dHJhY3RvciA9IGZ1bmN0aW9uKGtleSwgaSkge3JldHVybiBkYXRhW2tleV1beEtleV0gfSxcbiAgLyoqXG4gICogRnVuY3Rpb24gZm9yIGV4dHJhY3RpbmcgdGhlIHRoZSB2YWx1ZSBmcm9tIHlLZXkuXG4gICogKHNlZSB7QGxpbmsgaGVhdG1hcC55RXh0cmFjdG9yfSlcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbeUV4dHJhY3Rvcj1mdW5jdGlvbihrZXksIGkpIHsgcmV0dXJuIGRhdGFba2V5XVt5S2V5XSB9XVxuICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHlFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGkpIHsgcmV0dXJuIGRhdGFba2V5XVt5S2V5XSB9LFxuXG4gIC8qKlxuICAqIEZ1bmN0aW9uIGZvciBleHRyYWN0aW5nIHRoZSB0aGUgdmFsdWUgZnJvbSB2S2V5LlxuICAqIChzZWUge0BsaW5rIGhlYXRtYXAudkV4dHJhY3Rvcn0pXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3ZFeHRyYWN0b3I9ZnVuY3Rpb24oa2V5LCBpKSB7IHJldHVybiBkYXRhW2tleV1bdktleV0gfV1cbiAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2RXh0cmFjdG9yID0gZnVuY3Rpb24oa2V5LCBpKSB7IHJldHVybiBkYXRhW2tleV1bdktleV0gfSxcblxuXG4gIC8qKlxuICAqIFdoZXRoZXIgb3Igbm90IHRvIGFsbG93IGhlYXRtYXAgdG8gcmVuZGVyIGVsZW1lbnRzIHBhc3MgdGhlIG1haW4gc3BhdGlhbCBkaW1lbnNpb25cbiAgKiBnaXZlbiB0aGUgb3JpZW50YXRpb24gKHNlZSB7QGxpbmsgaGVhdG1hcCNvcmllbnR9KSwgd2hlcmUge0BsaW5rIGhlYXRtYXAjb3JpZW50fT1cImJvdHRvbVwiIG9yIHtAbGluayBoZWF0bWFwI29yaWVudH09XCJ0b3BcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgaGVhdG1hcCNzcGFjZVh9IGFuZCB3aGVyZSB7QGxpbmsgaGVhdG1hcCNvcmllbnR9PVwibGVmdFwiIG9yIHtAbGluayBoZWF0bWFwI29yaWVudH09XCJyaWdodFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayBoZWF0bWFwI3NwYWNlWX1cbiAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvdmVyZmxvd1E9ZmFsc2VdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG92ZXJmbG93USA9IGZhbHNlLFxuXG4gIC8qKlxuICAqIERlZmF1bHQgc3BhY2UgZm9yIHRoZSBzcGFjZXIgKHBlcmNlbnRhZ2UpIG9mIG1haW4gZGltZW5zaW9uIGdpdmVuIHRoZSBvcmllbnRhdGlvblxuICAqIChzZWUge0BsaW5rIGhlYXRtYXAjb3JpZW50fSksIHdoZXJlIHtAbGluayBoZWF0bWFwI29yaWVudH09XCJob3Jpem9udGFsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGhlYXRtYXAjc3BhY2VYfSBhbmQgd2hlcmUge0BsaW5rIGhlYXRtYXAjb3JpZW50fT1cInZlcnRpY2FsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGhlYXRtYXAjc3BhY2VZfSBiZXR3ZWVuIGJ1YmJsZXNcbiAgKiBAcGFyYW0ge251bWJlcn0gW29iamVjdFNwYWNlcj0wLjBdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdFNwYWNlciA9IDAuMCxcbiAgLyoqXG4gICogVGhlIG1pbmltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmUgaW4gdGhlIHkgZGltZW5zaW9uXG4gICogQHBhcmFtIHtudW1iZXJ9IFttaW5PYmplY3RTaXplPTUwXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB5TWluT2JqZWN0U2l6ZSA9IDUwLFxuICAvKipcbiAgKiBUaGUgbWluaW11bSBzaXplIHRoYXQgYW4gb2JqZWN0IGNhbiBiZSBpbiB0aGUgeCBkaW1lbnNpb25cbiAgKiBAcGFyYW0ge251bWJlcn0gW21pbk9iamVjdFNpemU9NTBdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhNaW5PYmplY3RTaXplID0gNTAsXG4gIC8qKlxuICAqIFRoZSBtYXhpbXVtIHNpemUgdGhhdCBhbiBvYmplY3QgY2FuIGJlIGluIHRoZSB4IGRpbWVuc2lvblxuICAqIEBwYXJhbSB7bnVtYmVyfSBbbWF4T2JqZWN0U2l6ZT0xMDBdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhNYXhPYmplY3RTaXplID0gMTAwLFxuICAvKipcbiAgKiBUaGUgbWF4aW11bSBzaXplIHRoYXQgYW4gb2JqZWN0IGNhbiBiZSBpbiB0aGUgeSBkaW1lbnNpb25cbiAgKiBAcGFyYW0ge251bWJlcn0gW21heE9iamVjdFNpemU9MTAwXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB5TWF4T2JqZWN0U2l6ZSA9IDEwMCxcblxuXG4gIC8qKlxuICAqIFRoZSBzdHJva2Ugd2lkdGggb2YgdGhlIGJ1YmJsZXNcbiAgKiBAcGFyYW0ge251bWJlcn0gW29iamVjdFN0cm9rZVdpZHRoPTJdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdFN0cm9rZVdpZHRoID0gMixcbiAgLy8gY29sb3JGdW5jID0gY29sb3JGdW5jdGlvbigpLFxuXG4gIC8qKlxuICAqIENvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kXG4gICogQHBhcmFtIHtzdHJpbmd9IFtiYWNrZ3JvdW5kRmlsbD1cInRyYW5zcGFyZW50XCJdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJhY2tncm91bmRGaWxsID0gJ3RyYW5zcGFyZW50JyxcbiAgLyoqXG4gICogTmFtZXNwYWNlIGZvciBhbGwgaXRlbXMgbWFkZSBieSB0aGlzIGluc3RhbmNlIG9mIGhlYXRtYXBcbiAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWVzcGFjZT1cImQzc20taGVhdG1hcFwiXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBuYW1lc3BhY2UgPSAnZDNzbS1oZWF0bWFwJyxcbiAgLyoqXG4gICogQ2xhc3MgbmFtZSBmb3IgaGVhdG1hcCBjb250YWluZXIgKDxnPiBlbGVtZW50KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbb2JqZWN0Q2xhc3M9XCJoZWF0bWFwXCJdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdENsYXNzID0gJ2hlYXRtYXAnLFxuICAvKipcbiAgKiBEdXJhdGlvbiBvZiBhbGwgdHJhbnNpdGlvbnMgb2YgdGhpcyBlbGVtZW50XG4gICogQHBhcmFtIHtudW1iZXJ9IFt0cmFuc2l0aW9uRHVyYXRpb249MTAwMF1cbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdHJhbnNpdGlvbkR1cmF0aW9uID0gMTAwMCxcbiAgLyoqXG4gICogRWFzaW5nIGZ1bmN0aW9uIGZvciB0cmFuc2l0aW9uc1xuICAqIEBwYXJhbSB7ZDMuZWFzZX0gW2Vhc2VGdW5jPWQzLmVhc2VFeHBdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGVhc2VGdW5jID0gZDMuZWFzZUV4cCxcblxuICAvKipcbiAgKiBTdG9yZXMgdGhlIGtleXMgb2YgYWxsIHRoZSBjZWxsc1xuICAqIENhbGN1bGF0ZWQgYWZ0ZXIgaGVhdG1hcCBjYWxsZWQuXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW2NlbGxLZXlzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgY2VsbEtleXMsXG4gIC8qKlxuICAqIFN0b3JlcyB0aGUgbGlzdCBvZiB1bmlxdWUgeFZhbHVlc1xuICAqIENhbGN1bGF0ZWQgYWZ0ZXIgaGVhdG1hcCBjYWxsZWQuXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW3hWYWx1ZXM9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB4VmFsdWVzLFxuICAvKipcbiAgKiBTdG9yZXMgdGhlIGxpc3Qgb2YgdW5pcXVlIHlWYWx1ZXNcbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt5VmFsdWVzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeVZhbHVlcyxcbiAgLyoqXG4gICogU3RvcmVzIHRoZSBsaXN0IG9mIHVuaXF1ZSB2VmFsdWVzXG4gICogQ2FsY3VsYXRlZCBhZnRlciBoZWF0bWFwIGNhbGxlZC5cbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbdlZhbHVlcz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHZWYWx1ZXMsXG5cbiAgeEtleVNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIHhWYWx1ZXMuaW5kZXhPZih4RXh0cmFjdG9yKGEpKSAtIHhWYWx1ZXMuaW5kZXhPZih4RXh0cmFjdG9yKGIpKSB9LFxuICB5S2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4geVZhbHVlcy5pbmRleE9mKHlFeHRyYWN0b3IoYSkpIC0geVZhbHVlcy5pbmRleE9mKHlFeHRyYWN0b3IoYikpIH0sXG4gIHZLZXlTb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihhLCBiKSB7IHJldHVybiB2VmFsdWVzLmluZGV4T2YodkV4dHJhY3RvcihhKSkgLSB5VmFsdWVzLmluZGV4T2YodkV4dHJhY3RvcihiKSkgfSxcblxuICAvKipcbiAgKiBJbnN0YW5jZSBvZiBDb2xvckZ1bmN0aW9uIHdpdGggLmNvbG9yQnkgc2V0IHRvICdjYXRlZ29yeSdcbiAgKiBAZnVuY3Rpb24gY29sb3JGdW5jdGlvblxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjb2xvckZ1bmN0aW9uID0gQ0YoKS5jb2xvckJ5KCdjYXRlZ29yeScpLFxuICAvKipcbiAgKiBJbnN0YW5jZSBvZiBUb29sdGlwXG4gICogQGZ1bmN0aW9uIHRvb2x0aXBcbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdG9vbHRpcCA9IFRUaXAoKSxcblxuICAvKipcbiAgKiBzdG9yZSB0aGUgc2l6ZSB0aGUgaGVhdG1hcCBjb3VsZCBiZSBpbiB0aGUgeCBkaW1lbnNpb25cbiAgKiB0aGUgYWN0dWFsbCBzaXplIG9mIHRoZSBoZWF0bWFwIHdpbGwgYmUgdGhlIG1pbiBvZiB4U2l6ZSBhbmQge0BsaW5rIGhlYXRtYXAjeVNpemV9XG4gICogQ2FsY3VsYXRlZCBhZnRlciBoZWF0bWFwIGNhbGxlZC5cbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbeFNpemU9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB4U2l6ZSxcbiAgLyoqXG4gICogc3RvcmUgdGhlIHNpemUgb2YgdGhlIHNwYWNlciBpbiB0aGUgeCBkaW1lbnNpb25cbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt4U3BhY2VyU2l6ZT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhTcGFjZXJTaXplLFxuXG4gIC8qKlxuICAqIHN0b3JlIHRoZSBzaXplIHRoZSBoZWF0bWFwIGNvdWxkIGJlIGluIHRoZSB5IGRpbWVuc2lvblxuICAqIHRoZSBhY3R1YWxsIHNpemUgb2YgdGhlIGhlYXRtYXAgd2lsbCBiZSB0aGUgbWluIG9mIHhTaXplIGFuZCB7QGxpbmsgaGVhdG1hcCN4U2l6ZX1cbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt5U2l6ZT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHlTaXplLFxuICAvKipcbiAgKiBzdG9yZSB0aGUgc2l6ZSBvZiB0aGUgc3BhY2VyIGluIHRoZSB5IGRpbWVuc2lvbi5cbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt4U3BhY2VyU2l6ZT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHlTcGFjZXJTaXplXG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgc2VsZWN0aW9uIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBkMy5zZWxlY3Rpb259XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNlbGVjdGlvbiA9IHNlbGVjdGlvblxuICAgKi9cbiAgaG0uc2VsZWN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZWxlY3Rpb24gPSBfLCBobSkgOiBzZWxlY3Rpb247IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZGF0YVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI2RhdGF9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBvYmplY3R9XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgaG0uZGF0YSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGF0YSA9IF8sIGhtKSA6IGRhdGE7IH1cbiAgLy8gaG0ub3JpZW50ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvcmllbnQgPSBfLCBobSkgOiBvcmllbnQ7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgYW1vdW50IG9mIGhvcml6b250YWwgc3BhY2UgaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjc3BhY2VYfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlWCA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0uc3BhY2VYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVggPSBfLCBobSkgOiBzcGFjZVg7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgYW1vdW50IG9mIHZlcnRpY2FsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3NwYWNlWX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBudW1iZXIgPiAwXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVkgPSB1bmRlZmluZWRcbiAgICovXG4gIGhtLnNwYWNlWSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3BhY2VZID0gXywgaG0pIDogc3BhY2VZOyB9XG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeEtleVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3hLZXl9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHhLZXkgPSAneCdcbiAgICovXG4gIGhtLnhLZXkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhLZXkgPSBfLCBobSkgOiB4S2V5OyB9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHlLZXlcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCN5S2V5fSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5S2V5ID0gJ3knXG4gICAqL1xuICBobS55S2V5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5S2V5ID0gXywgaG0pIDogeUtleTsgfVxuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHZLZXlcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCN2S2V5fSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB2S2V5ID0gJ3knXG4gICAqL1xuICBobS52S2V5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2S2V5ID0gXywgaG0pIDogdktleTsgfVxuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGNlbGxLZXlzXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjY2VsbEtleXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBjZWxsS2V5cyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0uY2VsbEtleXMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNlbGxLZXlzID0gXywgaG0pIDogY2VsbEtleXM7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeFZhbHVlc1xuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3hWYWx1ZXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB4VmFsdWVzID0gdW5kZWZpbmVkXG4gICAqL1xuICBobS54VmFsdWVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4VmFsdWVzID0gXywgaG0pIDogeFZhbHVlczsgfVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB5VmFsdWVzXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjeVZhbHVlc30pXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgc3RyaW5nW119XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHlWYWx1ZXMgPSB1bmRlZmluZWRcbiAgICovXG4gIGhtLnlWYWx1ZXMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlWYWx1ZXMgPSBfLCBobSkgOiB5VmFsdWVzOyB9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHZWYWx1ZXNcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCN2VmFsdWVzfSlcbiAgICogQHBhcmFtIHtudW1iZXJbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBudW1iZXJbXX1cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdlZhbHVlcyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0udlZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodlZhbHVlcyA9IF8sIGhtKSA6IHZWYWx1ZXM7IH1cblxuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHhFeHRyYWN0b3JcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCN4RXh0cmFjdG9yfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgeEV4dHJhY3RvciA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0ueEV4dHJhY3RvciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeEV4dHJhY3RvciA9IF8sIGhtKSA6IHhFeHRyYWN0b3I7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeUV4dHJhY3RvclxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3lFeHRyYWN0b3J9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5RXh0cmFjdG9yID0gdW5kZWZpbmVkXG4gICAqL1xuICBobS55RXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5RXh0cmFjdG9yID0gXywgaG0pIDogeUV4dHJhY3RvcjsgfVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB2RXh0cmFjdG9yXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjdkV4dHJhY3Rvcn0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZFeHRyYWN0b3IgPSB1bmRlZmluZWRcbiAgICovXG4gIGhtLnZFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZFeHRyYWN0b3IgPSBfLCBobSkgOiB2RXh0cmFjdG9yOyB9XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IGhlYXRtYXAgaXMgYWxsb3dlZCB0byBnbyBiZXlvbmQgc3BlY2lmaWVkIGRpbWVuc2lvbnNcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCNzcGFjZVh9KVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgYm9vbGVhbn1cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3ZlcmZsb3dRID0gZmFsc2VcbiAgICovXG4gIGhtLm92ZXJmbG93USA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3ZlcmZsb3dRID0gXywgaG0pIDogb3ZlcmZsb3dROyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyBvYmplY3RTcGFjZXJcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCNvYmplY3RTcGFjZXJ9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG9iamVjdFNwYWNlciA9IDAuMFxuICAgKi9cbiAgaG0ub2JqZWN0U3BhY2VyID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvYmplY3RTcGFjZXIgPSBfLCBvYmplY3RTcGFjZXIpIDogZGF0YTsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1pbk9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCNtaW5PYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBtaW5PYmplY3RTaXplID0gNTBcbiAgICovXG4gIGhtLnlNaW5PYmplY3RTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5TWluT2JqZWN0U2l6ZSA9IF8sIGhtKSA6IHlNaW5PYmplY3RTaXplOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbWF4T2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI21heE9iamVjdFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1heE9iamVjdFNpemUgPSAxMDBcbiAgICovXG4gIGhtLnlNYXhPYmplY3RTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5TWF4T2JqZWN0U2l6ZSA9IF8sIGhtKSA6IHlNYXhPYmplY3RTaXplOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbWluT2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI21pbk9iamVjdFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1pbk9iamVjdFNpemUgPSA1MFxuICAgKi9cbiAgaG0ueE1pbk9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhNaW5PYmplY3RTaXplID0gXywgaG0pIDogeE1pbk9iamVjdFNpemU7IH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBtYXhPYmplY3RTaXplXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjbWF4T2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbWF4T2JqZWN0U2l6ZSA9IDEwMFxuICAgKi9cbiAgaG0ueE1heE9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhNYXhPYmplY3RTaXplID0gXywgaG0pIDogeE1heE9iamVjdFNpemU7IH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RTdHJva2VXaWR0aFxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI29iamVjdFN0cm9rZVdpZHRofSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RTdHJva2VXaWR0aCA9IDJcbiAgICovXG4gIGhtLm9iamVjdFN0cm9rZVdpZHRoID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvYmplY3RTdHJva2VXaWR0aCA9IF8sIGhtKSA6IG9iamVjdFN0cm9rZVdpZHRoOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYmFja2dyb3VuZEZpbGxcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCNiYWNrZ3JvdW5kRmlsbH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYmFja2dyb3VuZEZpbGwgPSAndHJhbnNwYXJlbnQnXG4gICAqL1xuICBobS5iYWNrZ3JvdW5kRmlsbCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFja2dyb3VuZEZpbGwgPSBfLCBobSkgOiBiYWNrZ3JvdW5kRmlsbDsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG5hbWVzcGFjZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI25hbWVzcGFjZX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbmFtZXNwYWNlID0gJ2Qzc20taGVhdG1hcCdcbiAgICovXG4gIGhtLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgaG0pIDogbmFtZXNwYWNlOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgb2JqZWN0Q2xhc3NcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCNvYmplY3RDbGFzc30pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0Q2xhc3MgPSAndGljay1ncm91cCdcbiAgICovXG4gIGhtLm9iamVjdENsYXNzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvYmplY3RDbGFzcyA9IF8sIGhtKSA6IG9iamVjdENsYXNzOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdHJhbnNpdGlvbkR1cmF0aW9uXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjdHJhbnNpdGlvbkR1cmF0aW9ufSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwXG4gICAqL1xuICBobS50cmFuc2l0aW9uRHVyYXRpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRyYW5zaXRpb25EdXJhdGlvbiA9IF8sIGhtKSA6IHRyYW5zaXRpb25EdXJhdGlvbjsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGVhc2VGdW5jXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjZWFzZUZ1bmN9KVxuICAgKiBAcGFyYW0ge2QzLmVhc2V9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgZDMuZWFzZX1cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwXG4gICAqL1xuICBobS5lYXNlRnVuYyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZWFzZUZ1bmMgPSBfLCBobSkgOiBlYXNlRnVuYzsgfVxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdG9vbHRpcFxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3Rvb2x0aXB9KVxuICAgKiBAcGFyYW0ge3Rvb2x0aXB9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgdG9vbHRpcH1cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdG9vbHRpcCA9IHRvb2x0aXAoKVxuICAgKi9cbiAgaG0udG9vbHRpcCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodG9vbHRpcCA9IF8sIGhtKSA6IHRvb2x0aXA7IH1cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGNvbG9yRnVuY3Rpb25cbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCNjb2xvckZ1bmN0aW9ufSlcbiAgICogQHBhcmFtIHtjb2xvckZ1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IGNvbG9yRnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGNvbG9yRnVuY3Rpb24gPSBjb2xvckZ1bmN0aW9uKClcbiAgICovXG4gIGhtLmNvbG9yRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvbG9yRnVuY3Rpb24gPSBfLCBobSkgOiBjb2xvckZ1bmN0aW9uOyB9XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB4U2l6ZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3hTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB4U2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0ueFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhTaXplID0gXywgaG0pIDogeFNpemU7IH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB4U3BhY2VyU2l6ZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3hTcGFjZXJTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB4U3BhY2VyU2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0ueFNwYWNlclNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhTcGFjZXJTaXplID0gXywgaG0pIDogeFNwYWNlclNpemU7IH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB5U2l6ZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3lTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5U2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0ueVNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlTaXplID0gXywgaG0pIDogeVNpemU7IH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB5U3BhY2VyU2l6ZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3lTcGFjZXJTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5U3BhY2VyU2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0ueVNwYWNlclNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlTcGFjZXJTaXplID0gXywgaG0pIDogeVNwYWNlclNpemU7IH1cbiAgLy8gaG0ueUtleVNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeUtleVNvcnRpbmdGdW5jdGlvbiA9IF8sIGhtKSA6IHlLZXlTb3J0aW5nRnVuY3Rpb247IH1cbiAgLy8gaG0ueEtleVNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeEtleVNvcnRpbmdGdW5jdGlvbiA9IF8sIGhtKSA6IHhLZXlTb3J0aW5nRnVuY3Rpb247IH1cblxuXG5cbiAgZnVuY3Rpb24gaG0oKSB7XG4gICAgdmFyIGhvcml6b250YWxRID0gdHJ1ZTsgLy8gbm8gb3JpZW50YXRpb24gaW4gaGVhdG1hcHMuIEFpZHMgYXMgcGxhY2Vob2xkZXIgaW4gZnVuY3Rpb25zIHRoYXQgdGFrZSBvcmllbnQgYXMgYSBwYXJhbWV0ZXJcbiAgICB2YXIgYmdjcFJlY3QgPSB7eDowLCB5OjAsIHdpZHRoOiBzcGFjZVgsIGhlaWdodDpzcGFjZVl9XG4gICAgdmFyIGNvbnRhaW5lciA9IHNldHVwQ29udGFpbmVyKCBzZWxlY3Rpb24sIG5hbWVzcGFjZSwgYmdjcFJlY3QsIGJhY2tncm91bmRGaWxsICk7XG5cbiAgICBjZWxsS2V5cyA9IGQzLmtleXMoZGF0YSk7XG5cbiAgICB4VmFsdWVzID0gdW5pcXVlKGNlbGxLZXlzLm1hcCh4RXh0cmFjdG9yKSk7XG4gICAgeVZhbHVlcyA9IHVuaXF1ZShjZWxsS2V5cy5tYXAoeUV4dHJhY3RvcikpO1xuICAgIHZWYWx1ZXMgPSB1bmlxdWUoY2VsbEtleXMubWFwKHZFeHRyYWN0b3IpKTtcblxuICAgIGNlbGxLZXlzLnNvcnQoZnVuY3Rpb24oYSwgYil7IHJldHVybiB4S2V5U29ydGluZ0Z1bmN0aW9uKGEsIGIpIHx8IHlLZXlTb3J0aW5nRnVuY3Rpb24oYSwgYikgfSlcbiAgICBsb2coJ2hlYXRtYXAnLCAnY2VsbHMgYXJlIHNvcnRlZCBieScsIGNlbGxLZXlzKVxuXG5cblxuICAgIGxvZygnaGVhdG1hcCcsICd4IGFuZCB5IGtleXMgYXJlJywge3g6IHhWYWx1ZXMsIHk6eVZhbHVlc30pXG5cblxuICAgIHZhciB4RGltID0geFZhbHVlcy5sZW5ndGgsIHlEaW0gPSB5VmFsdWVzLmxlbmd0aDtcblxuXG4gICAgeVNpemUgPSBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0KHNwYWNlWSwgeURpbSwgeU1pbk9iamVjdFNpemUsIHlNYXhPYmplY3RTaXplLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICB4U2l6ZSA9IGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3Qoc3BhY2VYLCB4RGltLCB4TWluT2JqZWN0U2l6ZSwgeE1heE9iamVjdFNpemUsIG9iamVjdFNwYWNlciwgb3ZlcmZsb3dRKVxuICAgIHlTcGFjZXJTaXplID0gY2FsY3VsYXRlV2lkdGhPZlNwYWNlcih5VmFsdWVzLCBzcGFjZVksIHlTaXplLCB5RGltLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICB4U3BhY2VyU2l6ZSA9IGNhbGN1bGF0ZVdpZHRoT2ZTcGFjZXIoeFZhbHVlcywgc3BhY2VYLCB4U2l6ZSwgeERpbSwgb2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgLy8gY29uc29sZS50YWJsZSh7XG4gICAgLy8gICAgIHg6e1xuICAgIC8vICAgICAgIG9iamVjdDogeFNpemUsXG4gICAgLy8gICAgICAgc3BhY2VyOiB4U3BhY2VyU2l6ZSxcbiAgICAvLyAgICAgICBkaW06IHhEaW1cbiAgICAvLyAgICAgfSxcbiAgICAvLyAgICAgeTp7XG4gICAgLy8gICAgICAgb2JqZWN0OiB5U2l6ZSxcbiAgICAvLyAgICAgICBzcGFjZXI6IHlTcGFjZXJTaXplLFxuICAgIC8vICAgICAgIGRpbTogeURpbVxuICAgIC8vICAgICB9XG4gICAgLy9cbiAgICAvLyB9KVxuICAgIGxvZygnaGVhdG1hcCcsICdzaXplIG9mJywge3g6IHhTaXplLCB5OiB5U2l6ZX0pXG5cblxuXG4gICAgdmFyIHlTcGFjZXIgPSBncm91cGluZ1NwYWNlcigpXG4gICAgLmhvcml6b250YWxRKGZhbHNlKVxuICAgIC5tb3ZlYnkoJ2NhdGVnb3J5JylcbiAgICAubnVtYmVyT2ZPYmplY3RzKHlEaW0pXG4gICAgLm9iamVjdENsYXNzKGh5cGVuYXRlKG9iamVjdENsYXNzLCAncm93JykpXG4gICAgLm9iamVjdFNpemUoeVNpemUgKyB5U3BhY2VyU2l6ZSlcbiAgICAuc3BhY2VyU2l6ZSgwKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKVxuICAgIC5lYXNlRnVuYyhlYXNlRnVuYylcbiAgICAubmFtZXNwYWNlKCdyb3cnKVxuXG4gICAgdmFyIHhTcGFjZXIgPSBncm91cGluZ1NwYWNlcigpXG4gICAgLmhvcml6b250YWxRKHRydWUpXG4gICAgLm1vdmVieSgnY2F0ZWdvcnknKVxuICAgIC5udW1iZXJPZk9iamVjdHMoeERpbSlcbiAgICAub2JqZWN0Q2xhc3Mob2JqZWN0Q2xhc3MpXG4gICAgLm9iamVjdFNpemUoeFNpemUgKyB4U3BhY2VyU2l6ZSlcbiAgICAuc3BhY2VyU2l6ZSgwKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKVxuICAgIC5lYXNlRnVuYyhlYXNlRnVuYylcblxuXG4gICAgeVNwYWNlcihjb250YWluZXIsIHlWYWx1ZXMsIDApXG4gICAgY29udGFpbmVyLnNlbGVjdEFsbCgnZy4nK2h5cGVuYXRlKG9iamVjdENsYXNzLCAncm93JykpXG4gICAgLmVhY2goZnVuY3Rpb24oZCwgaSl7IHhTcGFjZXIoZDMuc2VsZWN0KHRoaXMpLCB4VmFsdWVzLCAwKSB9KVxuXG4gICAgdmFyIGNlbGxzID0gY29udGFpbmVyLnNlbGVjdEFsbCgnZzpub3QoLnRvLXJlbW92ZSkuJytvYmplY3RDbGFzcylcblxuXG4gICAgaWYgKGNlbGxLZXlzLmxlbmd0aCAhPSB5VmFsdWVzLmxlbmd0aCAqIHhWYWx1ZXMubGVuZ3RoKSB7XG4gICAgICB2YXIgbG9va3VwID0ge31cbiAgICAgIGNlbGxLZXlzLm1hcChmdW5jdGlvbihrLCBpKXtcbiAgICAgICAgbG9va3VwW3hFeHRyYWN0b3IoaykrJzo6Jyt5RXh0cmFjdG9yKGspXSA9IGtcbiAgICAgIH0pXG5cbiAgICAgIHZhciBwb3NpdGlvbmVkQ2VsbEtleXMgPSBbXVxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB5VmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgeFZhbHVlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgIHZhciBsb29rdXBWYWx1ZSA9IGxvb2t1cFt4VmFsdWVzW2pdK1wiOjpcIit5VmFsdWVzW2ldXVxuICAgICAgICAgIGlmIChsb29rdXBWYWx1ZSA9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHBvc2l0aW9uZWRDZWxsS2V5cy5wdXNoKHVuZGVmaW5lZClcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcG9zaXRpb25lZENlbGxLZXlzLnB1c2gobG9va3VwVmFsdWUpXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNlbGxzLmRhdGEocG9zaXRpb25lZENlbGxLZXlzKTtcblxuICAgICAgLy8gbWF5YmUgYnJlYWtzIHRoaXNcbiAgICAgIC8vICEhISEhISBJTVBPUlRBTlQgTk9URSBUT0RPIExPT0sgSEVSRSBCVUdcbiAgICAgIGNlbGxLZXlzID0gcG9zaXRpb25lZENlbGxLZXlzXG4gICAgfSBlbHNlIHtcbiAgICAgIGNlbGxzLmRhdGEoY2VsbEtleXMpO1xuICAgIH1cblxuXG5cbiAgICB2YXIgcGFyZW50SW5kZXhBcnJheSA9IFtdXG4gICAgY2VsbHMuZWFjaChmdW5jdGlvbihkLCBpKXsgcGFyZW50SW5kZXhBcnJheS5wdXNoKE51bWJlcihkMy5zZWxlY3QodGhpcykuYXR0cigncGFyZW50LWluZGV4JykpKSB9KVxuXG4gICAgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24uY29sb3JCeSgpID09ICdpbmRleCdcbiAgICA/IGNvbG9yRnVuY3Rpb24uZGF0YUV4dGVudChbMCwgTWF0aC5tYXgoLi4ucGFyZW50SW5kZXhBcnJheSldKVxuICAgIDogY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50KFswLCBNYXRoLm1heCguLi52VmFsdWVzKV0pXG5cbiAgICBjZWxscy5lYWNoKGZ1bmN0aW9uKGtleSwgaSkge1xuICAgICAgbG9nKCdoZWF0bWFwJywgJ2VhY2ggY2VsbCcsIHtrZXk6IGtleSwgaW5kZXg6IGksIG5vZGU6IGQzLnNlbGVjdCh0aGlzKS5ub2RlKCl9KVxuXG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgICAgaWYgKGtleSA9PSB1bmRlZmluZWQpIHtyZXR1cm59XG4gICAgICB2YXIgY3VycmVudERhdGEgPSBkYXRhW2tleV0sXG4gICAgICB2YWx1ZSA9IHZFeHRyYWN0b3Ioa2V5LCBpKSxcbiAgICAgIGkgPSB0LmF0dHIoJ3BhcmVudC1pbmRleCcpID09IHVuZGVmaW5lZCA/IGkgOiB0LmF0dHIoJ3BhcmVudC1pbmRleCcpLFxuICAgICAgZmlsbENvbG9yID0gY29sb3JGdW5jdGlvbihrZXksIHZhbHVlLCBpLCAnZmlsbCcpLCAvLyBwcmV2ZW50IGR1cGxpY2F0ZSBjb21wdXRhdGlvblxuICAgICAgc3Ryb2tlQ29sb3IgPSBjb2xvckZ1bmN0aW9uKGtleSwgdmFsdWUsIGksICAnc3Ryb2tlJylcblxuICAgICAgdmFyIGMgPSBzYWZlU2VsZWN0KHQsICdyZWN0JywgaHlwZW5hdGUob2JqZWN0Q2xhc3MsJ3JlY3QnKSlcbiAgICAgIGMuYXR0cignd2lkdGgnLCB4U2l6ZSArIHhTcGFjZXJTaXplIC0gb2JqZWN0U3Ryb2tlV2lkdGgpXG4gICAgICAuYXR0cignaGVpZ2h0JywgeVNpemUgKyB5U3BhY2VyU2l6ZSAtIG9iamVjdFN0cm9rZVdpZHRoKVxuICAgICAgLmF0dHIoJ2ZpbGwnLCBmaWxsQ29sb3IpXG4gICAgICAuYXR0cigneCcsIG9iamVjdFN0cm9rZVdpZHRoLzIpXG4gICAgICAuYXR0cigneScsIG9iamVjdFN0cm9rZVdpZHRoLzIpXG4gICAgICAuYXR0cignc3Ryb2tlJywgXCIjMDAwXCIpXG4gICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgb2JqZWN0U3Ryb2tlV2lkdGgpXG5cbiAgICB9KVxuXG4gICAgdG9vbHRpcC5zZWxlY3Rpb24oY2VsbHMuc2VsZWN0QWxsKCdyZWN0LicraHlwZW5hdGUob2JqZWN0Q2xhc3MsICdyZWN0JykpKVxuICAgIC5kYXRhKGRhdGEpXG4gICAgLy8gLmtleXMoWydyJywgJ3YnXSlcbiAgICAvLyAuaGVhZGVyKGZ1bmN0aW9uKGQsIGkpe3JldHVybiBoeXBlbmF0ZShkYXRhW2RdW3hLZXldLCBkYXRhW2RdW3lLZXldKSB9KVxuXG4gICAgdG9vbHRpcCgpXG5cblxuICB9XG5cbiAgcmV0dXJuIGhtO1xufVxuXG5leHBvcnQge2hlYXRtYXB9XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtzZXR1cENvbnRhaW5lciwgY2FsY3VsYXRlV2lkdGhPZk9iamVjdCwgY2FsY3VsYXRlV2lkdGhPZlNwYWNlciwgd2hpc2tlclBhdGh9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHt1bmlxdWUsIGhhc1EsIGZsYXR0ZW59IGZyb20gJy4vYXJyYXktZnVuY3Rpb25zJztcbmltcG9ydCB7Z3JvdXBpbmdTcGFjZXJ9IGZyb20gJy4vZ3JvdXBpbmctc3BhY2VyJztcbmltcG9ydCB7Y29sb3JGdW5jdGlvbiBhcyBDRn0gZnJvbSAnLi9jb2xvci1mdW5jdGlvbic7XG5pbXBvcnQge3Rvb2x0aXAgYXMgVFRpcH0gZnJvbSAnLi90b29sdGlwJztcbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCT1ggQU5EIFdISVNLRVIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4vKipcbiAqIENyZWF0ZXMgYSBib3h3aGlza2VyXG4gKlxuICoge0BsaW5rIGh0dHBzOi8vc3VtbmV1cm9uLmdpdGxhYi5pby9kM3NtL2RlbW9zL2JveC13aGlza2Vycy9pbmRleC5odG1sIERlbW99XG4gKiBAY29uc3RydWN0b3IgYm94d2hpc2tlclxuICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IHNlbGVjdGlvblxuICogQG5hbWVzcGFjZSBib3h3aGlza2VyXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IGJveHdoaXNrZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJveHdoaXNrZXIoIHNlbGVjdGlvbiApIHtcbiAgdmFyXG4gIC8qKlxuICAqIERhdGEgdG8gcGxvdC4gQXNzdW1lZCB0byBiZSBhIG9iamVjdCwgd2hlcmUgZWFjaCBrZXkgY29ycmVzcG9uZHMgdG8gYSBib3hcbiAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI2RhdGF9KVxuICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGRhdGEsXG4gIC8qKlxuICAqIFdoaWNoIGRpcmVjdGlvbiB0byByZW5kZXIgdGhlIGJveGVzIGluXG4gICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNvcmllbnR9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbb3JpZW50PSdob3Jpem9udGFsJ11cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb3JpZW50ID0gJ2hvcml6b250YWwnLFxuICAvKipcbiAgKiBBbW91bnQgb2YgaG9yaXpvbnRhbCBzcGFjZSAoaW4gcGl4ZWxzKSBhdmFpYmxlIHRvIHJlbmRlciB0aGUgYm94d2hpc2tlciBpblxuICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjc3BhY2VYfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlWD11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNwYWNlWCxcbiAgLyoqXG4gICogQW1vdW50IG9mIHZlcnRpY2FsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSBib3h3aGlza2VyIGluXG4gICogKHNlZSB7QGxpbmsgYm94d2hpc2tlci5zcGFjZVl9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbc3BhY2VZPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VZLFxuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0byBhbGxvdyBib3h3aGlza2VyIHRvIHJlbmRlciBlbGVtZW50cyBwYXNzIHRoZSBtYWluIHNwYXRpYWwgZGltZW5zaW9uXG4gICogZ2l2ZW4gdGhlIG9yaWVudGF0aW9uIChzZWUge0BsaW5rIGJveHdoaXNrZXIjb3JpZW50fSksIHdoZXJlIHtAbGluayBib3h3aGlza2VyI29yaWVudH09XCJob3Jpem9udGFsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJveHdoaXNrZXIjc3BhY2VYfSBhbmQgd2hlcmUge0BsaW5rIGJveHdoaXNrZXIjb3JpZW50fT1cInZlcnRpY2FsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJveHdoaXNrZXIjc3BhY2VZfVxuICAqIEBwYXJhbSB7Ym9vbGVhbn0gW292ZXJmbG93UT1mYWxzZV1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb3ZlcmZsb3dRID0gdHJ1ZSxcblxuICAvKipcbiAgKiBBbiBhcnJheSAtIHB1dGF0aXZlbHkgb2Ygb3RoZXIgYXJyYXlzIC0gZGVwaWN0aW5nIGhvdyBib3hlcyBzaG91bGQgYmUgYXJyYW5nZWRcbiAgKiBAcGFyYW0ge0FycmF5W119IFtncm91cGluZz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGdyb3VwaW5nLFxuICBxdWFydGlsZXNLZXkgPSAncXVhcnRpbGVzJywgLy8ga2V5IGluIG9iamVjdCB3aGVyZSBxdWFydGlsZXMgYXJlIHN0b3JlZFxuICBxdWFydGlsZXNLZXlzID0gW1wiMC4wMFwiLCBcIjAuMjVcIiwgXCIwLjUwXCIsIFwiMC43NVwiLCBcIjEuMDBcIl0sIC8vIGtleXMgaW4gcXVhcnRpbGVzIG9iamVjdCBtYXBwaW5nIHZhbHVlcyB0byBtaW4sIHExLCBxMiwgcTMgYW5kIG1heFxuXG5cbiAgLyoqXG4gICogSG93IHRvIGdldCB0aGUgdmFsdWUgb2YgdGhlIGJveHdoaXNrZXJcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbdmFsdWVFeHRyYWN0b3I9ZnVuY3Rpb24oa2V5LCBpbmRleCkgeyByZXR1cm4gZGF0YVtrZXldW3F1YXJ0aWxlc0tleV0gfV1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGluZGV4KSB7IHJldHVybiBkYXRhW2tleV1bcXVhcnRpbGVzS2V5XSB9LFxuICAvKipcbiAgKiBIb3cgdG8gc29ydCB0aGUgYm94ZXMgLSBpZiB7QGxpbmsgYm94d2hpc2tlciNncm91cGluZ30gaXMgbm90IHByb3ZpZGVkLlxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtzb3J0aW5nRnVuY3Rpb249ZGVzY2VuZGluZ11cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKiBkZWZhdWx0XG4gICogZnVuY3Rpb24oa2V5QSwga2V5Qikge3JldHVybiBkMy5kZXNjZW5kaW5nKFxuICAqICAgdmFsdWVFeHRyYWN0b3Ioa2V5QSlbcXVhcnRpbGVzS2V5c1s0XV0sXG4gICogICB2YWx1ZUV4dHJhY3RvcihrZXlCKVtxdWFydGlsZXNLZXlzWzRdXVxuICAqICl9XG4gICovXG4gIHNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKGtleUEsIGtleUIpIHtyZXR1cm4gZDMuZGVzY2VuZGluZyhcbiAgICB2YWx1ZUV4dHJhY3RvcihrZXlBKVtxdWFydGlsZXNLZXlzWzRdXSxcbiAgICB2YWx1ZUV4dHJhY3RvcihrZXlCKVtxdWFydGlsZXNLZXlzWzRdXVxuICApfSxcbiAgLyoqXG4gICogVGhlIHNjYWxlIGZvciB3aGljaCBib3h3aGlza2VyIHZhbHVlcyBzaG91bGQgYmUgdHJhbnNmb3JtZWQgYnlcbiAgKiBAcGFyYW0ge2QzLnNjYWxlfSBbc2NhbGU9ZDMuc2NhbGVMaW5lYXJdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNjYWxlID0gZDMuc2NhbGVMaW5lYXIoKSxcbiAgLyoqXG4gICogVGhlIHBhZGRpbmcgZm9yIHRoZSBkb21haW4gb2YgdGhlIHNjYWxlIChzZWUge0BsaW5rIGJveHdoaXNrZXIjc2NhbGV9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbZG9tYWluUGFkZGluZz0wLjVdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGRvbWFpblBhZGRpbmcgPSAwLjUsXG4gIC8qKlxuICAqIERlZmF1bHQgc3BhY2UgZm9yIHRoZSBzcGFjZXIgKHBlcmNlbnRhZ2UpIG9mIG1haW4gZGltZW5zaW9uIGdpdmVuIHRoZSBvcmllbnRhdGlvblxuICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjb3JpZW50fSksIHdoZXJlIHtAbGluayBib3h3aGlza2VyI29yaWVudH09XCJob3Jpem9udGFsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJveHdoaXNrZXIjc3BhY2VYfSBhbmQgd2hlcmUge0BsaW5rIGJveHdoaXNrZXIjb3JpZW50fT1cInZlcnRpY2FsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJveHdoaXNrZXIjc3BhY2VZfSBiZXR3ZWVuIGJveGVzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtvYmplY3RTcGFjZXI9MC4wNV1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0U3BhY2VyID0gMC4wNSxcbiAgLyoqXG4gICogVGhlIG1pbmltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmVcbiAgKiBAcGFyYW0ge251bWJlcn0gW21pbk9iamVjdFNpemU9MTVdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG1pbk9iamVjdFNpemUgPSAxNSxcbiAgLyoqXG4gICogVGhlIG1heGltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmVcbiAgKiBAcGFyYW0ge251bWJlcn0gW21heE9iamVjdFNpemU9NTBdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG1heE9iamVjdFNpemUgPSA1MCxcbiAgLyoqXG4gICogUGVyY2VudCBvZiBib3ggYW5kIHdoaXNrZXIgc2l6ZSB0aGF0IHdoaXNrZXJzIHdpbGwgYmUgcmVuZGVyZWRcbiAgKiBzZWUge0BsaW5rIGJveHdoaXNrZXIjb2JqZWN0U2l6ZX1cbiAgKiBAcGFyYW0ge251bWJlcn0gW3doaXNrZXJXaWR0aFBlcmNlbnQ9MC42XVxuICAqIEBtZW1iZXJvZiBib3h3aGlza2VyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB3aGlza2VyV2lkdGhQZXJjZW50ID0gLjYsXG4gIC8qKlxuICAqIEluc3RhbmNlIG9mIENvbG9yRnVuY3Rpb25cbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24oKV1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgY29sb3JGdW5jdGlvbiA9IENGKCksXG4gIC8qKlxuICAqIFRoZSBzdHJva2Ugd2lkdGggb2YgdGhlIGJveGVzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtib3hTdHJva2VXaWR0aD0yXVxuICAqIEBtZW1iZXJvZiBib3h3aGlza2VyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBib3hTdHJva2VXaWR0aCA9IDIsXG4gIC8qKlxuICAqIFRoZSBzdHJva2Ugd2lkdGggb2YgdGhlIHdoaXNrZXJzXG4gICogQHBhcmFtIHtudW1iZXJ9IFt3aGlza2VyU3Ryb2tlV2lkdGg9Ml1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgd2hpc2tlclN0cm9rZVdpZHRoID0gMixcblxuICAvKipcbiAgKiBDb2xvciBvZiB0aGUgYmFja2dyb3VuZFxuICAqIEBwYXJhbSB7c3RyaW5nfSBbYmFja2dyb3VuZEZpbGw9XCJ0cmFuc3BhcmVudFwiXVxuICAqIEBtZW1iZXJvZiBib3h3aGlza2VyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCcsXG4gIC8qKlxuICAqIE5hbWVzcGFjZSBmb3IgYWxsIGl0ZW1zIG1hZGUgYnkgdGhpcyBpbnN0YW5jZSBvZiBib3h3aGlza2VyXG4gICogQHBhcmFtIHtzdHJpbmd9IFtuYW1lc3BhY2U9XCJkM3NtLWJveC13aGlza2VyXCJdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG5hbWVzcGFjZSA9ICdkM3NtLWJveC13aGlza2VyJyxcbiAgLyoqXG4gICogQ2xhc3MgbmFtZSBmb3IgYm94d2hpc2tlciBjb250YWluZXIgKDxnPiBlbGVtZW50KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbb2JqZWN0Q2xhc3M9XCJib3gtd2hpc2tcIl1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0Q2xhc3MgPSAnYm94LXdoaXNrJyxcblxuICAvKipcbiAgKiBEdXJhdGlvbiBvZiBhbGwgdHJhbnNpdGlvbnMgb2YgdGhpcyBlbGVtZW50XG4gICogQHBhcmFtIHtudW1iZXJ9IFt0cmFuc2l0aW9uRHVyYXRpb249MTAwMF1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdHJhbnNpdGlvbkR1cmF0aW9uID0gMTAwMCxcbiAgLyoqXG4gICogRWFzaW5nIGZ1bmN0aW9uIGZvciB0cmFuc2l0aW9uc1xuICAqIEBwYXJhbSB7ZDMuZWFzZX0gW2Vhc2VGdW5jPWQzLmVhc2VFeHBdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGVhc2VGdW5jID0gZDMuZWFzZUV4cCxcblxuICAvKipcbiAgKiBUaGUga2V5cyBvZiB0aGUgYm94ZXNcbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbYm94S2V5cz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJveEtleXMsXG4gIC8qKlxuICAqIFRoZSB2YWx1ZXMgb2YgdGhlIGJveGVzXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW2JveFZhbHVlcz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJveFZhbHVlcyxcbiAgLyoqXG4gICogVGhlIG9iamVjdFNpemUgKGFjdHVhbCB3aWR0aCkgdXNlZCBieSB0aGUgYm94ZXNcbiAgKiBAcGFyYW0ge251bWJlcn0gW29iamVjdFNpemU9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBib3h3aGlza2VyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvYmplY3RTaXplLFxuICAvKipcbiAgKiBUaGUgc3BhY2VyU2l6ZSAoYWN0dWFsIHdpZHRoKSB1c2VkIGJ5IHRoZSBzcGFjZXJzIGJldHdlZW4gdGhlIGJveGVzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZXJTaXplPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VyU2l6ZSxcbiAgLyoqXG4gICogSW5zdGFuY2Ugb2YgVG9vbHRpcFxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFt0b29sdGlwPXRvb2x0aXAoKV1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdG9vbHRpcCA9IFRUaXAoKVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBzZWxlY3Rpb24gaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IGQzLnNlbGVjdGlvbn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc2VsZWN0aW9uID0gc2VsZWN0aW9uXG4gICAqL1xuICBib3h3aGlza2VyLnNlbGVjdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2VsZWN0aW9uID0gXywgYm94d2hpc2tlcikgOiBzZWxlY3Rpb247IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGRhdGFcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNkYXRhfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgb2JqZWN0fVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGJveHdoaXNrZXIuZGF0YSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGF0YSA9IF8sIGJveHdoaXNrZXIpIDogZGF0YTsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgb3JpZW50IG9mIHRoZSBib3hlc1xuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI29yaWVudH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IG9iamVjdH1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqL1xuICBib3h3aGlza2VyLm9yaWVudCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3JpZW50ID0gXywgYm94d2hpc2tlcikgOiBvcmllbnQ7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI3NwYWNlWH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBudW1iZXIgPiAwXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVggPSB1bmRlZmluZWRcbiAgICovXG4gIGJveHdoaXNrZXIuc3BhY2VYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVggPSBfLCBib3h3aGlza2VyKSA6IHNwYWNlWDsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgYW1vdW50IG9mIHZlcnRpY2FsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI3NwYWNlWX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBudW1iZXIgPiAwXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVkgPSB1bmRlZmluZWRcbiAgICovXG4gIGJveHdoaXNrZXIuc3BhY2VZID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVkgPSBfLCBib3h3aGlza2VyKSA6IHNwYWNlWTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IGJveHdoaXNrZXIgaXMgYWxsb3dlZCB0byBnbyBiZXlvbmQgc3BlY2lmaWVkIGRpbWVuc2lvbnNcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNvdmVyZmxvd1F9KVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgYm9vbGVhbn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3ZlcmZsb3dRID0gZmFsc2VcbiAgICovXG4gIGJveHdoaXNrZXIub3ZlcmZsb3dRID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvdmVyZmxvd1EgPSBfLCBib3h3aGlza2VyKSA6IG92ZXJmbG93UTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBncm91cGluZyBvZiB0aGUgYm94ZXNcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNncm91cGluZ30pXG4gICAqIEBwYXJhbSB7QXJyYXlbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBBcnJheVtdfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBncm91cGluZyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYm94d2hpc2tlci5ncm91cGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZ3JvdXBpbmcgPSBfLCBib3h3aGlza2VyKSA6IGdyb3VwaW5nOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHF1YXJ0aWxlc0tleVxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI3F1YXJ0aWxlc0tleX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgcXVhcnRpbGVzS2V5ID0gcXVhcnRpbGVzXG4gICAqL1xuICBib3h3aGlza2VyLnF1YXJ0aWxlc0tleSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocXVhcnRpbGVzS2V5ID0gXywgYm94d2hpc2tlcikgOiBxdWFydGlsZXNLZXk7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcXVhcnRpbGVzS2V5c1xuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI3F1YXJ0aWxlc0tleXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBxdWFydGlsZXNLZXlzID0gW1EwLCBRMSwgUTIsIFEzLCBRNF1cbiAgICovXG4gIGJveHdoaXNrZXIucXVhcnRpbGVzS2V5cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocXVhcnRpbGVzS2V5cyA9IF8sIGJveHdoaXNrZXIpIDogcXVhcnRpbGVzS2V5czsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB2YWx1ZUV4dHJhY3RvclxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI3ZhbHVlRXh0cmFjdG9yfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGluZGV4KSB7IHJldHVybiBkYXRhW2tleV1bcXVhcnRpbGVzS2V5XSB9LFxuICAgKi9cblxuICBib3h3aGlza2VyLnZhbHVlRXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZUV4dHJhY3RvciA9IF8sIGJveHdoaXNrZXIpIDogdmFsdWVFeHRyYWN0b3I7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgc29ydGluZ0Z1bmN0aW9uXG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjc29ydGluZ0Z1bmN0aW9ufSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oa2V5QSwga2V5Qikge3JldHVybiBkMy5kZXNjZW5kaW5nKFxuICAgKiAgIHZhbHVlRXh0cmFjdG9yKGtleUEpW3F1YXJ0aWxlc0tleXNbNF1dLFxuICAgKiAgIHZhbHVlRXh0cmFjdG9yKGtleUIpW3F1YXJ0aWxlc0tleXNbNF1dXG4gICAqICl9LFxuICAgKi9cbiAgYm94d2hpc2tlci5zb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNvcnRpbmdGdW5jdGlvbiA9IF8sIGJveHdoaXNrZXIpIDogc29ydGluZ0Z1bmN0aW9uOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHNjYWxlIGZvciB3aGljaCB0aGUgYm94d2hpc2tlciB2YWx1ZXMgc2hvdWxkIGJlIHRyYW5zZm9ybWVkIGJ5XG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjc2NhbGV9KVxuICAgKiBAcGFyYW0ge2QzLnNjYWxlfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IGQzLnNjYWxlfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKClcbiAgICovXG4gIGJveHdoaXNrZXIuc2NhbGUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNjYWxlID0gXywgYm94d2hpc2tlcikgOiBzY2FsZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBwYWRkaW5nIGZvciB0aGUgZG9tYWluIG9mIHRoZSBzY2FsZVxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI2RvbWFpblBhZGRpbmd9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGRvbWFpblBhZGRpbmcgPSAwLjVcbiAgICovXG4gIGJveHdoaXNrZXIuZG9tYWluUGFkZGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluUGFkZGluZyA9IF8sIGJveHdoaXNrZXIpIDogZG9tYWluUGFkZGluZzsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIG9iamVjdFNwYWNlclxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI29iamVjdFNwYWNlcn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0U3BhY2VyID0gMC4wNVxuICAgKi9cbiAgYm94d2hpc2tlci5vYmplY3RTcGFjZXIgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNwYWNlciA9IF8sIGJveHdoaXNrZXIpIDogb2JqZWN0U3BhY2VyOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1pbk9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNtaW5PYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBtaW5PYmplY3RTaXplID0gMTVcbiAgICovXG4gIGJveHdoaXNrZXIubWluT2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobWluT2JqZWN0U2l6ZSA9IF8sIGJveHdoaXNrZXIpIDogbWluT2JqZWN0U2l6ZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBtYXhPYmplY3RTaXplXG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjbWF4T2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbWF4T2JqZWN0U2l6ZSA9IDUwXG4gICAqL1xuICBib3h3aGlza2VyLm1heE9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1heE9iamVjdFNpemUgPSBfLCBib3h3aGlza2VyKSA6IG1heE9iamVjdFNpemU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgd2hpc2tlcldpZHRoUGVyY2VudFxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI3doaXNrZXJXaWR0aFBlcmNlbnR9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1heE9iamVjdFNpemUgPSAwLjZcbiAgICovXG4gIGJveHdoaXNrZXIud2hpc2tlcldpZHRoUGVyY2VudCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAod2hpc2tlcldpZHRoUGVyY2VudCA9IF8sIGJveHdoaXNrZXIpIDogd2hpc2tlcldpZHRoUGVyY2VudDsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBjb2xvckZ1bmN0aW9uXG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjY29sb3JGdW5jdGlvbn0pXG4gICAqIEBwYXJhbSB7Y29sb3JGdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBjb2xvckZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBjb2xvckZ1bmN0aW9uID0gY29sb3JGdW5jdGlvbigpXG4gICAqL1xuICBib3h3aGlza2VyLmNvbG9yRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvbG9yRnVuY3Rpb24gPSBfLCBib3h3aGlza2VyKSA6IGNvbG9yRnVuY3Rpb247IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYm94U3Ryb2tlV2lkdGhcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNib3hTdHJva2VXaWR0aH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYm94U3Ryb2tlV2lkdGggPSAyXG4gICAqL1xuICBib3h3aGlza2VyLmJveFN0cm9rZVdpZHRoID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChib3hTdHJva2VXaWR0aCA9IF8sIGJveHdoaXNrZXIpIDogYm94U3Ryb2tlV2lkdGg7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgd2hpc2tlclN0cm9rZVdpZHRoXG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjd2hpc2tlclN0cm9rZVdpZHRofSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB3aGlza2VyU3Ryb2tlV2lkdGggPSAyXG4gICAqL1xuICBib3h3aGlza2VyLndoaXNrZXJTdHJva2VXaWR0aCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAod2hpc2tlclN0cm9rZVdpZHRoID0gXywgYm94d2hpc2tlcikgOiB3aGlza2VyU3Ryb2tlV2lkdGg7IH07XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBiYWNrZ3JvdW5kRmlsbFxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI2JhY2tncm91bmRGaWxsfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCdcbiAgICovXG4gIGJveHdoaXNrZXIuYmFja2dyb3VuZEZpbGwgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJhY2tncm91bmRGaWxsID0gXywgYm94d2hpc2tlcikgOiBiYWNrZ3JvdW5kRmlsbDsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBuYW1lc3BhY2VcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNuYW1lc3BhY2V9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG5hbWVzcGFjZSA9ICdkM3NtLWJveHdoaXNrZXInXG4gICAqL1xuICBib3h3aGlza2VyLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgYm94d2hpc2tlcikgOiBuYW1lc3BhY2U7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgb2JqZWN0Q2xhc3NcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNvYmplY3RDbGFzc30pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0Q2xhc3MgPSAndGljay1ncm91cCdcbiAgICovXG4gIGJveHdoaXNrZXIub2JqZWN0Q2xhc3MgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdENsYXNzID0gXywgYm94d2hpc2tlcikgOiBvYmplY3RDbGFzczsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB0cmFuc2l0aW9uRHVyYXRpb25cbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciN0cmFuc2l0aW9uRHVyYXRpb259KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRyYW5zaXRpb25EdXJhdGlvbiA9IDEwMDBcbiAgICovXG4gIGJveHdoaXNrZXIudHJhbnNpdGlvbkR1cmF0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0cmFuc2l0aW9uRHVyYXRpb24gPSBfLCBib3h3aGlza2VyKSA6IHRyYW5zaXRpb25EdXJhdGlvbjsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBlYXNlRnVuY1xuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI2Vhc2VGdW5jfSlcbiAgICogQHBhcmFtIHtkMy5lYXNlfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IGQzLmVhc2V9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGVhc2VGdW5jID0gZDMuZWFzZUV4cFxuICAgKi9cbiAgYm94d2hpc2tlci5lYXNlRnVuYyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZWFzZUZ1bmMgPSBfLCBib3h3aGlza2VyKSA6IGVhc2VGdW5jOyB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYmFyS2V5c1xuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI2JveEtleXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBib3hLZXlzID0gdW5kZWZpbmVkXG4gICAqL1xuICBib3h3aGlza2VyLmJveEtleXMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJveEtleXMgPSBfLCBib3h3aGlza2VyKSA6IGJveEtleXM7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYm94VmFsdWVzXG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjYm94VmFsdWVzfSlcbiAgICogQHBhcmFtIHtudW1iZXJbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBudW1iZXJbXX1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYm94VmFsdWVzID0gdW5kZWZpbmVkXG4gICAqL1xuICBib3h3aGlza2VyLmJveFZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYm94VmFsdWVzID0gXywgYm94d2hpc2tlcikgOiBib3hWYWx1ZXM7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgb2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI29iamVjdFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG9iamVjdFNpemUgPSB1bmRlZmluZWRcbiAgICovXG4gIGJveHdoaXNrZXIub2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0U2l6ZSA9IF8sIGJveHdoaXNrZXIpIDogb2JqZWN0U2l6ZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzcGFjZXJTaXplXG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjc3BhY2VyU2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc3BhY2VyU2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYm94d2hpc2tlci5zcGFjZXJTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZXJTaXplID0gXywgYm94d2hpc2tlcikgOiBzcGFjZXJTaXplOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRvb2x0aXBcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciN0b29sdGlwfSlcbiAgICogQHBhcmFtIHt0b29sdGlwfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IHRvb2x0aXB9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRvb2x0aXAgPSB0b29sdGlwKClcbiAgICovXG4gIGJveHdoaXNrZXIudG9vbHRpcCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodG9vbHRpcCA9IF8sIGJveHdoaXNrZXIpIDogdG9vbHRpcDsgfTtcblxuXG4gIGZ1bmN0aW9uIGJveHdoaXNrZXIoKSB7XG4gICAgLy8gZm9yIGNvbnZlbmllbmNlIGluIGhhbmRsaW5nIG9yaWVudGF0aW9uIHNwZWNpZmljIHZhbHVlc1xuICAgIHZhciBob3Jpem9udGFsUSA9IChvcmllbnQgPT0gJ2hvcml6b250YWwnKSA/IHRydWUgOiBmYWxzZVxuICAgIHZhciB2ZXJ0aWNhbFEgPSAhaG9yaXpvbnRhbFFcblxuICAgIC8vIGJhY2tncm91bmQgY2xpcGluZyByZWN0YW5nbGVcbiAgICB2YXIgYmdjcFJlY3QgPSB7eDowLCB5OjAsIHdpZHRoOiBzcGFjZVgsIGhlaWdodDpzcGFjZVl9XG4gICAgdmFyIGNvbnRhaW5lciA9IHNldHVwQ29udGFpbmVyKCBzZWxlY3Rpb24sIG5hbWVzcGFjZSwgYmdjcFJlY3QsIGJhY2tncm91bmRGaWxsICk7XG5cbiAgICAvLyBpZiBncm91cGluZyBpcyB1bmRlZmluZWQgc29ydCBrZXlzIGJ5IHNvcnRpbmcgZnVuY3RcbiAgICB2YXIgb3JkZXJlZCA9IChncm91cGluZyA9PSB1bmRlZmluZWQpID8gZDMua2V5cyhkYXRhKS5zb3J0KHNvcnRpbmdGdW5jdGlvbikgOiBncm91cGluZ1xuICAgIC8vIHRvIHByZXZlbnQgcmUtY2FsY3VsYXRpb24gYW5kIGdldHRlcnMgdG8gYmUgcGFzc2VkIHRvIGF4ZXNcbiAgICBib3hLZXlzID0gZmxhdHRlbihvcmRlcmVkKVxuICAgIGJveFZhbHVlcyA9IGJveEtleXMubWFwKHZhbHVlRXh0cmFjdG9yKVxuXG5cbiAgICB2YXIgbnVtYmVyT2ZPYmplY3RzID0gYm94S2V5cy5sZW5ndGhcbiAgICB2YXIgZXh0ZW50ID0gW1xuICAgICAgTWF0aC5taW4oLi4uYm94VmFsdWVzLm1hcChmdW5jdGlvbihkLGkpe3JldHVybiBkW3F1YXJ0aWxlc0tleXNbMF1dfSkpIC0gZG9tYWluUGFkZGluZyxcbiAgICAgIE1hdGgubWF4KC4uLmJveFZhbHVlcy5tYXAoZnVuY3Rpb24oZCxpKXtyZXR1cm4gZFtxdWFydGlsZXNLZXlzWzRdXX0pKSArIGRvbWFpblBhZGRpbmdcbiAgICBdO1xuXG4gICAgLy8gc2V0IHRoZSBzY2FsZVxuICAgIHNjYWxlLmRvbWFpbihleHRlbnQpLnJhbmdlKGhvcml6b250YWxRID8gWzAsc3BhY2VZXSA6IFtzcGFjZVgsIDBdKVxuICAgIHZhciBzcGFjZSA9IGhvcml6b250YWxRID8gc3BhY2VYIDogc3BhY2VZXG4gICAgLy8gY2FsY3VsYXRlIG9iamVjdCBzaXplXG4gICAgb2JqZWN0U2l6ZSA9IGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3Qoc3BhY2UsIG51bWJlck9mT2JqZWN0cywgbWluT2JqZWN0U2l6ZSwgbWF4T2JqZWN0U2l6ZSwgb2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgLy8gY2FsY3VsYXRlIHNwYWNlciBzaXplIGlmIG5lZWRlZFxuICAgIHNwYWNlclNpemUgPSBjYWxjdWxhdGVXaWR0aE9mU3BhY2VyKGJveEtleXMsIHNwYWNlLCBvYmplY3RTaXplLCBudW1iZXJPZk9iamVjdHMsIG9iamVjdFNwYWNlciwgb3ZlcmZsb3dRKVxuICAgIC8vIG1ha2UgdGhlIG5lc3RlZCBncm91cHNcbiAgICB2YXIgc3BhY2VyRnVuY3Rpb24gPSBncm91cGluZ1NwYWNlcigpXG4gICAgLmhvcml6b250YWxRKGhvcml6b250YWxRKS5zY2FsZShzY2FsZSkubW92ZWJ5KCdjYXRlZ29yeScpLm51bWJlck9mT2JqZWN0cyhudW1iZXJPZk9iamVjdHMpXG4gICAgLm9iamVjdENsYXNzKG9iamVjdENsYXNzKS5vYmplY3RTaXplKG9iamVjdFNpemUpLnNwYWNlclNpemUoc3BhY2VyU2l6ZSlcbiAgICAudHJhbnNpdGlvbkR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbikuZWFzZUZ1bmMoZWFzZUZ1bmMpXG4gICAgLm5hbWVzcGFjZShuYW1lc3BhY2UpXG5cbiAgICAvLyBtb3ZlIHN0dWZmXG4gICAgc3BhY2VyRnVuY3Rpb24oY29udGFpbmVyLCBvcmRlcmVkLCAwKVxuXG4gICAgdmFyIHBhcmVudEluZGV4QXJyYXkgPSBbXVxuICAgIGNvbnRhaW5lci5zZWxlY3RBbGwoJ2c6bm90KC50by1yZW1vdmUpLicrb2JqZWN0Q2xhc3MpXG4gICAgLmVhY2goZnVuY3Rpb24oZCwgaSl7aWYgKGhhc1EoYm94S2V5cywgZCkpeyBwYXJlbnRJbmRleEFycmF5LnB1c2goTnVtYmVyKGQzLnNlbGVjdCh0aGlzKS5hdHRyKCdwYXJlbnQtaW5kZXgnKSkpfX0pXG5cblxuXG4gICAgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24uY29sb3JCeSgpID09ICdpbmRleCdcbiAgICA/IGNvbG9yRnVuY3Rpb24uZGF0YUV4dGVudChbMCwgTWF0aC5tYXgoLi4ucGFyZW50SW5kZXhBcnJheSldKVxuICAgIDogY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50KGV4dGVudClcblxuXG4gICAgLy8gc2V0IGF0dHJpYnV0ZXMgZm9yIGJveCBhbmQgd2hpc2tlcnNcbiAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnOm5vdCgudG8tcmVtb3ZlKS4nK29iamVjdENsYXNzKS5lYWNoKGZ1bmN0aW9uKGtleSwgaSkge1xuICAgICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcyksXG4gICAgICBjdXJyZW50RGF0YSA9IGRhdGFba2V5XSxcblxuICAgICAgcXVhcnRpbGVzID0gdmFsdWVFeHRyYWN0b3Ioa2V5LCBpKSxcbiAgICAgIHEwID0gcXVhcnRpbGVzW3F1YXJ0aWxlc0tleXNbMF1dLFxuICAgICAgcTEgPSBxdWFydGlsZXNbcXVhcnRpbGVzS2V5c1sxXV0sXG4gICAgICBxMiA9IHF1YXJ0aWxlc1txdWFydGlsZXNLZXlzWzJdXSxcbiAgICAgIHEzID0gcXVhcnRpbGVzW3F1YXJ0aWxlc0tleXNbM11dLFxuICAgICAgcTQgPSBxdWFydGlsZXNbcXVhcnRpbGVzS2V5c1s0XV1cblxuICAgICAgdmFyIGkgPSB0LmF0dHIoJ3BhcmVudC1pbmRleCcpID09IHVuZGVmaW5lZCA/IGkgOiB0LmF0dHIoJ3BhcmVudC1pbmRleCcpLFxuICAgICAgZmlsbENvbG9yID0gY29sb3JGdW5jdGlvbihrZXksIHEyLCBpLCAnZmlsbCcpLCAvLyBwcmV2ZW50IGR1cGxpY2F0ZSBjb21wdXRhdGlvblxuICAgICAgc3Ryb2tlQ29sb3IgPSBjb2xvckZ1bmN0aW9uKGtleSwgcTIsIGksICAnc3Ryb2tlJylcblxuXG4gICAgICB2YXJcbiAgICAgIHdoaXNrID0gc2FmZVNlbGVjdCh0LCAnZycsICd3aGlza2VyJyksXG4gICAgICB1V2hpc2sgPSBzYWZlU2VsZWN0KHdoaXNrLCAncGF0aCcsICd1cHBlcicpLFxuICAgICAgbFdoaXNrID0gc2FmZVNlbGVjdCh3aGlzaywgJ3BhdGgnLCAnbG93ZXInKSxcbiAgICAgIHF1YXJ0ID0gc2FmZVNlbGVjdCh0LCAnZycsICdxdWFydGlsZScpLFxuICAgICAgdVF1YXJ0ID0gc2FmZVNlbGVjdChxdWFydCwgJ3JlY3QnLCAndXBwZXInKSxcbiAgICAgIGxRdWFydCA9IHNhZmVTZWxlY3QocXVhcnQsICdyZWN0JywgJ2xvd2VyJyksXG4gICAgICBtUXVhcnQgPSBzYWZlU2VsZWN0KHF1YXJ0LCAnY2lyY2xlJywgJ21lZGlhbicpXG5cblxuICAgICAgLy8gc2V0IHVwcGVyIHF1YXJ0aWxlIChxMylcbiAgICAgIHVRdWFydC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ3dpZHRoJywgaG9yaXpvbnRhbFEgPyBvYmplY3RTaXplIDogc2NhbGUocTMpIC0gc2NhbGUocTIpKVxuICAgICAgLmF0dHIoJ2hlaWdodCcsIHZlcnRpY2FsUSA/IG9iamVjdFNpemUgOiBzY2FsZShxMykgLSBzY2FsZShxMikpXG4gICAgICAuYXR0cignZmlsbCcsIGZpbGxDb2xvcilcbiAgICAgIC5hdHRyKCdzdHJva2UnLCBzdHJva2VDb2xvcilcbiAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCBib3hTdHJva2VXaWR0aClcbiAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBob3Jpem9udGFsUSA/IDAgOiBzY2FsZShxMiksXG4gICAgICAgIHkgPSB2ZXJ0aWNhbFEgPyAwIDogc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKHEzKSxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcblxuICAgICAgLy8gc2V0IGxvd2VyIHF1YXJ0aWxlIChxMSlcbiAgICAgIGxRdWFydC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ3dpZHRoJywgaG9yaXpvbnRhbFEgPyBvYmplY3RTaXplIDogc2NhbGUocTIpIC0gc2NhbGUocTEpKVxuICAgICAgLmF0dHIoJ2hlaWdodCcsIHZlcnRpY2FsUSA/IG9iamVjdFNpemUgOiBzY2FsZShxMikgLSBzY2FsZShxMSkpXG4gICAgICAuYXR0cignZmlsbCcsIGZpbGxDb2xvcilcbiAgICAgIC5hdHRyKCdzdHJva2UnLCBzdHJva2VDb2xvcilcbiAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCBib3hTdHJva2VXaWR0aClcbiAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBob3Jpem9udGFsUSA/IDAgOiBzY2FsZShxMSksXG4gICAgICAgIHkgPSB2ZXJ0aWNhbFEgPyAwIDogc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKHEyKSxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcblxuXG4gICAgICAvLyBzZXQgbWVkaWFuIChxMilcbiAgICAgIG1RdWFydC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ3InLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgICAgdmFyIHIgPSBvYmplY3RTaXplIC8gMlxuICAgICAgICB2YXIgZGlmID0gKHNjYWxlKHEzKSAtIHNjYWxlKHExKSkgLyAyXG4gICAgICAgIHJldHVybiAociA+IGRpZikgPyBkaWYgOiByXG4gICAgICB9KVxuICAgICAgLmF0dHIoJ2ZpbGwnLCBmaWxsQ29sb3IpXG4gICAgICAuYXR0cignc3Ryb2tlJywgc3Ryb2tlQ29sb3IpXG4gICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgYm94U3Ryb2tlV2lkdGgpXG4gICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIHZhclxuICAgICAgICB4ID0gaG9yaXpvbnRhbFEgPyBvYmplY3RTaXplIC8gMiA6IHNjYWxlKHEyKSxcbiAgICAgICAgeSA9IHZlcnRpY2FsUSA/IG9iamVjdFNpemUgLyAyIDogc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKHEyKSxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcblxuICAgICAgLy8gc2V0IGxvd2VyIHdoaXNrZXIgKG1pbilcbiAgICAgIGxXaGlzay50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ2QnLCBmdW5jdGlvbihkZCwgaWkpe1xuICAgICAgICB2YXJcbiAgICAgICAgZGlyID0gZmFsc2UsXG4gICAgICAgIHggPSAwLFxuICAgICAgICB5ID0gMCxcbiAgICAgICAgaCA9IGhvcml6b250YWxRID8gc2NhbGUocTEpIC0gc2NhbGUocTApIDogb2JqZWN0U2l6ZSxcbiAgICAgICAgdyA9IHZlcnRpY2FsUSA/IHNjYWxlKHExKSAtIHNjYWxlKHEwKSA6IG9iamVjdFNpemVcbiAgICAgICAgcmV0dXJuIHdoaXNrZXJQYXRoKGRpciwgeCwgeSwgdywgaCwgd2hpc2tlcldpZHRoUGVyY2VudCwgb3JpZW50KVxuICAgICAgfSlcbiAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBob3Jpem9udGFsUSA/IDAgOiBzY2FsZShxMSksXG4gICAgICAgIHkgPSB2ZXJ0aWNhbFEgPyAwIDogc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKHExKSxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcbiAgICAgIC5hdHRyKCdzdHJva2UnLCAnYmxhY2snKS5hdHRyKCdzdHJva2Utd2lkdGgnLCB3aGlza2VyU3Ryb2tlV2lkdGgpXG4gICAgICAuYXR0cignZmlsbCcsICdub25lJylcblxuICAgICAgLy8gc2V0IHVwcGVyIHdoaXNrZXIgKG1heClcbiAgICAgIHVXaGlzay50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ2QnLCBmdW5jdGlvbihkZCwgaWkpe1xuICAgICAgICB2YXJcbiAgICAgICAgZGlyID0gdHJ1ZSxcbiAgICAgICAgeCA9IDAsXG4gICAgICAgIHkgPSAwLFxuICAgICAgICBoID0gaG9yaXpvbnRhbFEgPyBzY2FsZShxNCkgLSBzY2FsZShxMykgOiBvYmplY3RTaXplLFxuICAgICAgICB3ID0gdmVydGljYWxRID8gc2NhbGUocTQpIC0gc2NhbGUocTMpIDogb2JqZWN0U2l6ZVxuICAgICAgICByZXR1cm4gd2hpc2tlclBhdGgoZGlyLCB4LCB5LCB3LCBoLCB3aGlza2VyV2lkdGhQZXJjZW50LCBvcmllbnQpXG4gICAgICB9KVxuICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgICB2YXJcbiAgICAgICAgeCA9IGhvcml6b250YWxRID8gMCA6IHNjYWxlKHEzKSxcbiAgICAgICAgeSA9IHZlcnRpY2FsUSA/IDAgOiAgc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKHE0KSxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcbiAgICAgIC5hdHRyKCdzdHJva2UnLCAnYmxhY2snKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIHdoaXNrZXJTdHJva2VXaWR0aClcbiAgICAgIC5hdHRyKCdmaWxsJywgJ25vbmUnKVxuXG4gICAgfSlcblxuICAgIHRvb2x0aXAuc2VsZWN0aW9uKGNvbnRhaW5lci5zZWxlY3RBbGwoJ2c6bm90KC50by1yZW1vdmUpLicrb2JqZWN0Q2xhc3MpKVxuICAgIC5kYXRhKGRhdGEpXG4gICAgdG9vbHRpcCgpXG5cblxuICB9XG5cbiAgcmV0dXJuIGJveHdoaXNrZXJcbn1cbiIsImltcG9ydCB7aHlwZW5hdGUsIHNhZmVTZWxlY3R9IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQge3NlbGVjdEZpbHRlcn0gZnJvbSAnLi9zZWxlY3QtZmlsdGVyJztcblxuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERBVEFUT0dHTEUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbi8qKlxuICogQ3JlYXRlcyBhIGRhdGF0b2dnbGVcbiAqIEBjb25zdHJ1Y3RvciBkYXRhdG9nZ2xlXG4gKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gc2VsZWN0aW9uXG4gKiBAbmFtZXNwYWNlIGRhdGF0b2dnbGVcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gZGF0YXRvZ2dsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGF0YXRvZ2dsZSggc2VsZWN0aW9uICkge1xuICB2YXJcbiAgLyoqXG4gICogS2V5cyB0byBtYWtlIHRvZ2dsZS1hYmxlIG9wdGlvbnNcbiAgKiAoc2VlIHtAbGluayBkYXRhdG9nZ2xlI2tleXN9KVxuICAqIEBwYXJhbSB7c3RyaW5nW119IFtrZXlzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgZGF0YXRvZ2dsZSNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAga2V5cyxcbiAgLyoqXG4gICogV2hhdCB0byBkbyB3aGVuIGEgZGlmZmVyZW50IGtleSBpcyBjbGlja2VkXG4gICogKHNlZSB7QGxpbmsgZGF0YXRvZ2dsZSN1cGRhdGVGdW5jdGlvbn0pXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3VwZGF0ZUZ1bmN0aW9uPWZ1bmN0aW9uKCl7fV1cbiAgKiBAbWVtYmVyb2YgZGF0YXRvZ2dsZSNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdXBkYXRlRnVuY3Rpb24gPSBmdW5jdGlvbigpe30sXG4gIC8qKlxuICAqIE5hbWVzcGFjZSBmb3IgYWxsIGl0ZW1zIG1hZGUgYnkgdGhpcyBpbnN0YW5jZSBvZiBkYXRhdG9nZ2xlXG4gICogQHBhcmFtIHtzdHJpbmd9IFtuYW1lc3BhY2U9XCJkM3NtLWRhdGFiYXJcIl1cbiAgKiBAbWVtYmVyb2YgZGF0YXRvZ2dsZSNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbmFtZXNwYWNlPSdkM3NtLWRhdGFiYXInLFxuICAvKipcbiAgKiBDdXJyZW50bHkgdG9nZ2xlZCBrZXlcbiAgKiBAcGFyYW0ge3N0cmluZ30gW2N1cnJlbnRLZXk9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBkYXRhdG9nZ2xlI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjdXJyZW50S2V5LFxuXG4gIHhBeGlzU2VsZWN0USA9IGZhbHNlLFxuICB4QXhpc09wdGlvbnMsXG4gIHlBeGlzU2VsZWN0USA9IGZhbHNlLFxuICB5QXhpc09wdGlvbnMsXG4gIGRhdGFcbiAgdG9nZ2xlLnhBeGlzU2VsZWN0USA9IGZ1bmN0aW9uKF8pe3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhBeGlzU2VsZWN0USA9IF8sIHRvZ2dsZSkgOiB4QXhpc1NlbGVjdFF9XG4gIHRvZ2dsZS55QXhpc1NlbGVjdFEgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5QXhpc1NlbGVjdFEgPSBfLCB0b2dnbGUpIDogeUF4aXNTZWxlY3RRfVxuICB0b2dnbGUueEF4aXNPcHRpb25zID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeEF4aXNPcHRpb25zID0gXywgdG9nZ2xlKSA6IHhBeGlzT3B0aW9uc31cbiAgdG9nZ2xlLnlBeGlzT3B0aW9ucyA9IGZ1bmN0aW9uKF8pe3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlBeGlzT3B0aW9ucyA9IF8sIHRvZ2dsZSkgOiB5QXhpc09wdGlvbnN9XG4gIHRvZ2dsZS5kYXRhID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGF0YSA9IF8sIHRvZ2dsZSkgOiBkYXRhfVxuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB1cGRhdGVGdW5jdGlvblxuICAgKiAoc2VlIHtAbGluayBkYXRhdG9nZ2xlI3VwZGF0ZUZ1bmN0aW9ufSlcbiAgICogQGZ1bmN0aW9uIGRhdGF0b2dnbGUudXBkYXRlRnVuY3Rpb25cbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2RhdGF0b2dnbGUgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGRhdGF0b2dnbGVcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdXBkYXRlRnVuY3Rpb24gPSBmdW5jdGlvbigpe31cbiAgICovXG4gIHRvZ2dsZS51cGRhdGVGdW5jdGlvbiA9IGZ1bmN0aW9uKF8pe3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHVwZGF0ZUZ1bmN0aW9uID0gXywgdG9nZ2xlKSA6IHVwZGF0ZUZ1bmN0aW9ufVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG5hbWVzcGFjZVxuICAgKiAoc2VlIHtAbGluayBkYXRhdG9nZ2xlI25hbWVzcGFjZX0pXG4gICAqIEBmdW5jdGlvbiBkYXRhdG9nZ2xlLm5hbWVzcGFjZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2RhdGF0b2dnbGUgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBkYXRhdG9nZ2xlXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG5hbWVzcGFjZSA9ICdkM3NtLWRhdGFiYXInXG4gICAqL1xuICB0b2dnbGUubmFtZXNwYWNlID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgdG9nZ2xlKSA6IG5hbWVzcGFjZX1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBjdXJyZW50S2V5XG4gICAqIChzZWUge0BsaW5rIGRhdGF0b2dnbGUjY3VycmVudEtleX0pXG4gICAqIEBmdW5jdGlvbiBkYXRhdG9nZ2xlLmN1cnJlbnRLZXlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtkYXRhdG9nZ2xlIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgZGF0YXRvZ2dsZVxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBjdXJyZW50S2V5ID0gdW5kZWZpbmVkXG4gICAqL1xuICB0b2dnbGUuY3VycmVudEtleXMgPVxuICBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHZhbHMgPSB7fVxuICAgIGQzLmtleXMoZmlsdGVyU2VsZWN0cykubWFwKGZ1bmN0aW9uKGssIGkpe1xuICAgICAgdmFsc1trXT0gZmlsdGVyU2VsZWN0c1trXS5jdXJyZW50T3B0aW9uKClcbiAgICB9KVxuICAgIHJldHVybiB2YWxzXG4gIH1cblxuICB2YXIgZmlsdGVyU2VsZWN0cyA9IHt9XG4gIGZ1bmN0aW9uIHRvZ2dsZSgpIHtcbiAgICAvLyBzZWxlY3Rpb24gb3B0aW9uc1xuXG4gICAgLy8gc2VsZWN0aW9uLmNsYXNzZWQoJ2QtZmxleCBmbGV4LXJvdycsIHRydWUpXG4gICAgLy8gdmFyIGZpbHRlckJ1dHRvbiA9IHNhZmVTZWxlY3Qoc2VsZWN0aW9uLCAnYScsICdzbGlkZXItYnV0dG9ucycpXG4gICAgLy8gdmFyIGZpbHRlckkgPSBzYWZlU2VsZWN0KGZpbHRlckJ1dHRvbiwgJ2knLCAnZmEgZmEtc2xpZGVycycpXG5cbiAgICAvKkJVRzogdW5leHBlY3RlZCBiZWhhdmlvci5cbiAgICAgIC0gd2hlbiB1c2luZyBib290c3RyYXAtZXF1ZSB3YXkgZm9yIGNvbGxhcHNlLCBjbGlja2luZyBidXR0b24gc3VibWl0cyB0b1xuICAgICAgdGhlIHNhbWUgcGFnZSBpbiBhcHBsaWNhdGlvbnMgKGJ1dCBub3QgaW4gZGVtbyksIHNvIHVzaW5nIGFuY2hvciAoPGE+KVxuICAgICAgLSB3aGVuIHVzaW5nIGFuY2hvciwgY2F1c2UgcGFnZSB0byBqdW1wIHRvIHRoYXQgbG9jYXRpb25cbiAgICAgIC0gd2hlbiB1c2luZyBzaG93LCB0aGUgZmlyc3Qgb3BlbiB3b3JrcywgYnV0IHRoZSBjbG9zZSBkb2VzIG5vdC5cbiAgICAqL1xuICAgIC8vIGZpbHRlckJ1dHRvbi5hdHRyKCdjbGFzcycsICdidG4gYnRuLXNlY29uZGFyeScpXG4gICAgLy8gLmF0dHIoJ2RhdGEtdG9nZ2xlJywgJ2NvbGxhcHNlJylcbiAgICAvLyAuYXR0cignaHJlZicsICcjJytoeXBlbmF0ZShuYW1lc3BhY2UsICdkYXRhLXRvZ2dsZScpKVxuICAgIC8vIC5hdHRyKCd0YXJnZXQnLCAnX2JsYW5rJylcbiAgICAvLyAuaHRtbChmaWx0ZXJCdXR0b24uaHRtbCgpKycgRmlsdGVycycpXG4gICAgLy8gLm9uKCdjbGljaycsIGZ1bmN0aW9uKGQsIGkpe1xuICAgIC8vICAgZDMuZXZlbnQucHJldmVudERlZmF1bHQoKVxuICAgIC8vICAgZDMuZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcbiAgICAvLyAgIHZhciBkdCA9IGQzLnNlbGVjdChcIiNcIitoeXBlbmF0ZShuYW1lc3BhY2UsICdkYXRhLXRvZ2dsZScpKVxuICAgIC8vICAgZHQuY2xhc3NlZCgnc2hvdycsICFkdC5jbGFzc2VkKCdzaG93JykpXG4gICAgLy8gICBkdC5jbGFzc2VkKCdkLWlubGluZS1mbGV4JywgZHQuY2xhc3NlZCgnc2hvdycpKVxuICAgIC8vXG4gICAgLy8gICBmaWx0ZXJCdXR0b24uY2xhc3NlZCgnYnRuLXByaW1hcnknLCBkdC5jbGFzc2VkKCdzaG93JykpXG4gICAgLy8gICBmaWx0ZXJCdXR0b24uY2xhc3NlZCgnYnRuLXNlY29uZGFyeScsICFkdC5jbGFzc2VkKCdzaG93JykpXG4gICAgLy8gfSlcbiAgICAvLyAuY2xhc3NlZCgnZC1pbmxpbmUtZmxleCcsIHRydWUpXG4gICAgLy8gLnN0eWxlKFwibWFyZ2luLXJpZ2h0XCIsICcxMHB4JylcblxuXG5cbiAgICAvLyB2YXIgZGF0YXRvZ2dsZUNvbGxhcHNlID0gc2FmZVNlbGVjdChzZWxlY3Rpb24sICdkaXYnLCBoeXBlbmF0ZShuYW1lc3BhY2UsJ2NvbGxhcHNlJykpXG4gICAgLy8gLmF0dHIoJ2lkJywgaHlwZW5hdGUobmFtZXNwYWNlLCAnZGF0YS10b2dnbGUnKSlcbiAgICAvLyAuY2xhc3NlZCgnY29sbGFwc2UnLCB0cnVlKVxuXG4gICAgLy8gdmFyIGZsZXhSb3cgPSBzYWZlU2VsZWN0KGRhdGF0b2dnbGVDb2xsYXBzZSwgJ2RpdicsICdkLWlubGluZS1mbGV4IGZsZXgtcm93IGZsZXgtd3JhcCcpXG4gICAgdmFyIGZsZXhSb3cgPSBzYWZlU2VsZWN0KHNlbGVjdGlvbiwgJ2RpdicsICdkLWlubGluZS1mbGV4IGZsZXgtcm93IGZsZXgtd3JhcCcpXG5cbiAgICB2YXIgZGF0YW9wdHMgPSBmbGV4Um93LnNlbGVjdEFsbCgnZGl2LicraHlwZW5hdGUobmFtZXNwYWNlLCdzZWxlY3QtZmlsdGVyJykpXG4gICAgLy8gcmVtb3ZlIGV4Y2Vzc1xuICAgIGRhdGFvcHRzLmV4aXQoKS5yZW1vdmUoKVxuICAgIC8vIGJpbmQgZGF0YVxuICAgIGRhdGFvcHRzID0gZGF0YW9wdHMuZGF0YShkMy5rZXlzKGRhdGEpKVxuICAgIC8vZW50ZXJcbiAgICB2YXIgZG9FbnRlciA9IGRhdGFvcHRzLmVudGVyKCkuYXBwZW5kKCdkaXYnKVxuICAgIC5hdHRyKCdjbGFzcycsICdzZWxlY3QtZmlsdGVyJylcblxuICAgIGRhdGFvcHRzID0gZGF0YW9wdHMubWVyZ2UoZG9FbnRlcikuc3R5bGUoJ21hcmdpbi1yaWdodCcsIFwiMTBweFwiKVxuXG4gICAgZGF0YW9wdHMuZWFjaChmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhciB0ID0gZDMuc2VsZWN0KHRoaXMpXG4gICAgICB2YXIgc2YgPSBzZWxlY3RGaWx0ZXIodClcbiAgICAgIC5kYXRhKGRhdGFbZF0pXG4gICAgICAubmFtZXNwYWNlKGh5cGVuYXRlKG5hbWVzcGFjZSwgZCkpXG4gICAgICAuc2VsZWN0aW9uTmFtZShkKVxuICAgICAgc2YoKVxuICAgICAgZmlsdGVyU2VsZWN0c1tkXSA9IHNmXG4gICAgfSlcblxuXG4gICAgc2VsZWN0aW9uLnNlbGVjdEFsbCgnc2VsZWN0JylcbiAgICAub24oJ2NoYW5nZScsIGZ1bmN0aW9uKCl7dXBkYXRlRnVuY3Rpb24oKX0pXG4gICAgLy8gYmluZCB1cGRhdGUgZnVuY3Rpb25cbiAgICAvLyBkMy5zZWxlY3RBbGxcbiAgICByZXR1cm4gdG9nZ2xlXG4gIH1cblxuXG4gIGZ1bmN0aW9uIG9ubHlPbmUoKSB7XG4gICAgLy8gZDMuZXZlbnQucHJldmVudERlZmF1bHQoKVxuICAgIC8vIGQzLmV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXG4gICAgdmFyIGRhdGFvcHRzID0gc2VsZWN0aW9uLnNlbGVjdEFsbCgnZGl2LmRhdGEtb3B0aW9uJylcbiAgICBjdXJyZW50S2V5ID0gZGF0YW9wdHMuc2VsZWN0KCc6Y2hlY2tlZCcpLmRhdHVtKClcbiAgICB1cGRhdGVGdW5jdGlvbigpXG5cbiAgfVxuXG4gIGZ1bmN0aW9uIGF4aXNTZWxlY3RGaWx0ZXIoc2VsZWN0aW9uLCBheGlzPVwieC1heGlzXCIsIGF4aXNEYXRhKSB7XG4gICAgaWYgKGF4aXNEYXRhID09IHVuZGVmaW5lZCkge1xuICAgICAgYXhpc0RhdGEgPSB7XG4gICAgICAgICdsaW5lYXInOiBkMy5zY2FsZUxpbmVhcigpLFxuICAgICAgICAnbG9nJzogZDMuc2NhbGVMb2coKSxcbiAgICAgICAgJ3Bvdyc6IGQzLnNjYWxlUG93KCksXG4gICAgICAgICdzcXJ0JzogZDMuc2NhbGVTcXJ0KClcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc2YgPSBzZWxlY3RGaWx0ZXIoc2VsZWN0aW9uKVxuICAgIC5kYXRhKGF4aXNEYXRhKVxuICAgIC5uYW1lc3BhY2UoYXhpcylcbiAgICAuc2VsZWN0aW9uTmFtZShheGlzKycgc2NhbGUnKVxuICAgIC5kZWZhdWx0VmFsdWUoZDMuc2NhbGVMaW5lYXIoKSlcblxuXG4gICAgc2YoKVxuXG4gIH1cblxuICByZXR1cm4gdG9nZ2xlXG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtzZXR1cENvbnRhaW5lciwgY2FsY3VsYXRlV2lkdGhPZk9iamVjdCwgY2FsY3VsYXRlV2lkdGhPZlNwYWNlcn0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQge3VuaXF1ZSwgZmxhdHRlbn0gZnJvbSAnLi9hcnJheS1mdW5jdGlvbnMnO1xuaW1wb3J0IHtncm91cGluZ1NwYWNlcn0gZnJvbSAnLi9ncm91cGluZy1zcGFjZXInO1xuaW1wb3J0IHtjb2xvckZ1bmN0aW9uIGFzIENGfSBmcm9tICcuL2NvbG9yLWZ1bmN0aW9uJztcbmltcG9ydCB7dG9vbHRpcCBhcyBUVGlwfSBmcm9tICcuL3Rvb2x0aXAnO1xuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTQ0FUVEVSICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbi8qKlxuICogQ3JlYXRlcyBhIHNjYXR0ZXJcbiAqXG4gKiB7QGxpbmsgaHR0cHM6Ly9zdW1uZXVyb24uZ2l0bGFiLmlvL2Qzc20vZGVtb3Mvc2NhdHRlci9pbmRleC5odG1sIERlbW99XG4gKiBAY29uc3RydWN0b3Igc2NhdHRlclxuICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IHNlbGVjdGlvblxuICogQG5hbWVzcGFjZSBzY2F0dGVyXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IHNjYXR0ZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjYXR0ZXIgKCBzZWxlY3Rpb24gKSB7XG5cbiAgdmFyXG4gIC8qKlxuICAqIERhdGEgdG8gcGxvdC4gQXNzdW1lZCB0byBiZSBhIG9iamVjdCwgd2hlcmUgZWFjaCBrZXkgY29ycmVzcG9uZHMgdG8gYSBwb2ludFxuICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjZGF0YX0pXG4gICogQHBhcmFtIHtPYmplY3R9IFtkYXRhPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZGF0YSxcbiAgLyoqXG4gICogQW1vdW50IG9mIGhvcml6b250YWwgc3BhY2UgKGluIHBpeGVscykgYXZhaWJsZSB0byByZW5kZXIgdGhlIHNjYXR0ZXIgaW5cbiAgKiAoc2VlIHtAbGluayBzY2F0dGVyI3NwYWNlWH0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZVg9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzcGFjZVgsXG4gIC8qKlxuICAqIEFtb3VudCBvZiB2ZXJ0aWNhbCBzcGFjZSAoaW4gcGl4ZWxzKSBhdmFpYmxlIHRvIHJlbmRlciB0aGUgc2NhdHRlciBpblxuICAqIChzZWUge0BsaW5rIHNjYXR0ZXIuc3BhY2VZfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlWT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNwYWNlWSxcblxuICAvKipcbiAgKiBUaGUgc2NhbGUgZm9yIHdoaWNoIHNjYXR0ZXIgeCB2YWx1ZXMgc2hvdWxkIGJlIHRyYW5zZm9ybWVkIGJ5XG4gICogQHBhcmFtIHtkMy5zY2FsZX0gW3NjYWxlWD1kMy5zY2FsZUxpbmVhcl1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc2NhbGVYID0gZDMuc2NhbGVMaW5lYXIoKSxcbiAgLyoqXG4gICogVGhlIHBhZGRpbmcgZm9yIHRoZSBkb21haW4gb2YgdGhlIHNjYWxlWCAoc2VlIHtAbGluayBzY2F0dGVyI3NjYWxlWH0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtkb21haW5QYWRkaW5nWD0wLjVdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGRvbWFpblBhZGRpbmdYID0gMC41LFxuICAvKipcbiAgKiBUaGUgZnVuY3Rpb24gZm9yIGdldHRpbmcgdGhlIHggdmFsdWUgb2YgdGhlIGN1cnJlbnQgcG9pbnRcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbdmFsdWVFeHRyYWN0b3JYPWZ1bmN0aW9uKGQsIGkpe3JldHVybiBkYXRhW2RdWyd4J119XVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2YWx1ZUV4dHJhY3RvclggPSBmdW5jdGlvbihkLCBpKSB7cmV0dXJuIGRhdGFbZF1bJ3gnXX0sXG5cbiAgLyoqXG4gICogVGhlIHNjYWxlIGZvciB3aGljaCBzY2F0dGVyIHkgdmFsdWVzIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBieVxuICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtzY2FsZVk9ZDMuc2NhbGVMaW5lYXJdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNjYWxlWSA9IGQzLnNjYWxlTGluZWFyKCksXG4gIC8qKlxuICAqIFRoZSBwYWRkaW5nIGZvciB0aGUgZG9tYWluIG9mIHRoZSBzY2FsZVkgKHNlZSB7QGxpbmsgc2NhdHRlciNzY2FsZVl9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbZG9tYWluUGFkZGluZ1k9MC41XVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBkb21haW5QYWRkaW5nWSA9IDAuNSxcbiAgLyoqXG4gICogVGhlIGZ1bmN0aW9uIGZvciBnZXR0aW5nIHRoZSB5IHZhbHVlIG9mIHRoZSBjdXJyZW50IHBvaW50XG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3ZhbHVlRXh0cmFjdG9yWT1mdW5jdGlvbihkLCBpKXtyZXR1cm4gZGF0YVtkXVsneSddfV1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmFsdWVFeHRyYWN0b3JZID0gZnVuY3Rpb24oZCwgaSkge3JldHVybiBkYXRhW2RdWyd5J119LFxuXG5cbiAgLyoqXG4gICogVGhlIHNjYWxlIGZvciB3aGljaCBzY2F0dGVyIHIgdmFsdWVzIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBieVxuICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtzY2FsZVI9ZDMuc2NhbGVMaW5lYXJdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNjYWxlUiA9IGQzLnNjYWxlTGluZWFyKCksXG4gIC8qKlxuICAqIFRoZSBwYWRkaW5nIGZvciB0aGUgZG9tYWluIG9mIHRoZSBzY2FsZVIgKHNlZSB7QGxpbmsgc2NhdHRlciNzY2FsZVJ9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbZG9tYWluUGFkZGluZ1I9MC41XVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBkb21haW5QYWRkaW5nUiA9IDAuNSxcbiAgLyoqXG4gICogVGhlIGZ1bmN0aW9uIGZvciBnZXR0aW5nIHRoZSByIHZhbHVlIG9mIHRoZSBjdXJyZW50IHBvaW50XG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3ZhbHVlRXh0cmFjdG9yUj1mdW5jdGlvbihkLCBpKXtyZXR1cm4gMn1dXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHZhbHVlRXh0cmFjdG9yUiA9IGZ1bmN0aW9uKGQsIGkpIHtyZXR1cm4gMn0sXG4gIC8qKlxuICAqIFRoZSBtaW4gcmFkaXVzIGEgcG9pbnQgY2FuIGhhdmVcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbbWluUmFkaXVzPTJdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG1pblJhZGl1cyA9IDIsXG4gIC8qKlxuICAqIFRoZSBtaW4gcmFkaXVzIGEgcG9pbnQgY2FuIGhhdmVcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbbWF4UmFkaXVzPTEwXVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBtYXhSYWRpdXMgPSAxMCxcblxuICAvKipcbiAgKiBUaGUgc3Ryb2tlIHdpZHRoIG9mIHRoZSBwb2ludHNcbiAgKiBAcGFyYW0ge251bWJlcn0gW3BvaW50U3Ryb2tlV2lkdGg9Ml1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgcG9pbnRTdHJva2VXaWR0aCA9IDIsXG4gIC8qKlxuICAqIEluc3RhbmNlIG9mIENvbG9yRnVuY3Rpb25cbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24oKV1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgY29sb3JGdW5jdGlvbiA9IENGKCksXG4gIC8qKlxuICAqIENvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kXG4gICogQHBhcmFtIHtzdHJpbmd9IFtiYWNrZ3JvdW5kRmlsbD1cInRyYW5zcGFyZW50XCJdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJhY2tncm91bmRGaWxsID0gJ3RyYW5zcGFyZW50JyxcbiAgLyoqXG4gICogTmFtZXNwYWNlIGZvciBhbGwgaXRlbXMgbWFkZSBieSB0aGlzIGluc3RhbmNlIG9mIHNjYXR0ZXJcbiAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWVzcGFjZT1cImQzc20tc2NhdHRlclwiXVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBuYW1lc3BhY2UgPSAnZDNzbS1zY2F0dGVyJyxcbiAgLyoqXG4gICogQ2xhc3MgbmFtZSBmb3Igc2NhdHRlciBjb250YWluZXIgKDxjaXJjbGU+IGVsZW1lbnQpXG4gICogQHBhcmFtIHtzdHJpbmd9IFtvYmplY3RDbGFzcz1cInNjYXR0ZXItcG9pbnRcIl1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0Q2xhc3MgPSAnc2NhdHRlci1wb2ludCcsXG4gIC8qKlxuICAqIER1cmF0aW9uIG9mIGFsbCB0cmFuc2l0aW9ucyBvZiB0aGlzIGVsZW1lbnRcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RyYW5zaXRpb25EdXJhdGlvbj0xMDAwXVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwLFxuICAvKipcbiAgKiBFYXNpbmcgZnVuY3Rpb24gZm9yIHRyYW5zaXRpb25zXG4gICogQHBhcmFtIHtkMy5lYXNlfSBbZWFzZUZ1bmM9ZDMuZWFzZUV4cF1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwLFxuXG4gIC8vIHVzZWZ1bCB2YWx1ZXMgdG8gZXh0cmFjdCB0byBwcmV2ZW50IHJlLWNhbGN1bGF0aW9uXG4gIC8qKlxuICAqIFRoZSBrZXlzIG9mIHRoZSBwb2ludHNcbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbcG9pbnRLZXlzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgcG9pbnRLZXlzLFxuICAvKipcbiAgKiBUaGUgeCB2YWx1ZXMgb2YgdGhlIHBvaW50c1xuICAqIEBwYXJhbSB7bnVtYmVyW119IFt2YWx1ZXNYPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmFsdWVzWCxcbiAgLyoqXG4gICogVGhlIHkgdmFsdWVzIG9mIHRoZSBwb2ludHNcbiAgKiBAcGFyYW0ge251bWJlcltdfSBbdmFsdWVzWT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHZhbHVlc1ksXG4gIC8qKlxuICAqIFRoZSByIHZhbHVlcyBvZiB0aGUgcG9pbnRzXG4gICogQHBhcmFtIHtudW1iZXJbXX0gW3ZhbHVlc1I9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2YWx1ZXNSLFxuXG4gIC8qKlxuICAqIEluc3RhbmNlIG9mIFRvb2x0aXBcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbdG9vbHRpcD10b29sdGlwKCldXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRvb2x0aXAgPSBUVGlwKClcblxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBzZWxlY3Rpb24gaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IGQzLnNlbGVjdGlvbn1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc2VsZWN0aW9uID0gc2VsZWN0aW9uXG4gICAqL1xuICBzY2F0dGVyLnNlbGVjdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2VsZWN0aW9uID1fLCBzY2F0dGVyKSA6IHNlbGVjdGlvbn1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZGF0YVxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI2RhdGF9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBvYmplY3R9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgc2NhdHRlci5kYXRhID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkYXRhID1fLCBzY2F0dGVyKSA6IGRhdGF9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI3NwYWNlWH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBudW1iZXIgPiAwXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVggPSB1bmRlZmluZWRcbiAgICovXG4gIHNjYXR0ZXIuc3BhY2VYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVggPV8sIHNjYXR0ZXIpIDogc3BhY2VYfVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBhbW91bnQgb2YgdmVydGljYWwgc3BhY2UgaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjc3BhY2VZfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlWSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgc2NhdHRlci5zcGFjZVkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWSA9Xywgc2NhdHRlcikgOiBzcGFjZVl9XG5cblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgeCBzY2FsZSBmb3Igd2hpY2ggdGhlIHNjYXR0ZXIgeCB2YWx1ZXMgc2hvdWxkIGJlIHRyYW5zZm9ybWVkIGJ5XG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjc2NhbGVYfSlcbiAgICogQHBhcmFtIHtkMy5zY2FsZX0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBkMy5zY2FsZX1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc2NhbGVYID0gZDMuc2NhbGVMaW5lYXIoKVxuICAgKi9cbiAgc2NhdHRlci5zY2FsZVggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNjYWxlWCA9Xywgc2NhdHRlcikgOiBzY2FsZVh9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcGFkZGluZyBmb3IgdGhlIGRvbWFpbiBvZiB0aGUgeCBzY2FsZVxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI2RvbWFpblBhZGRpbmdYfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBkb21haW5QYWRkaW5nWCA9IDAuNVxuICAgKi9cbiAgc2NhdHRlci5kb21haW5QYWRkaW5nWCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluUGFkZGluZ1ggPV8sIHNjYXR0ZXIpIDogZG9tYWluUGFkZGluZ1h9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdmFsdWVFeHRyYWN0b3JYXG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjdmFsdWVFeHRyYWN0b3JYfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdmFsdWVFeHRyYWN0b3JYID0gZnVuY3Rpb24oa2V5LCBpbmRleCkgeyByZXR1cm4gZGF0YVtrZXldWyd4J10gfVxuICAgKi9cbiAgc2NhdHRlci52YWx1ZUV4dHJhY3RvclggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZhbHVlRXh0cmFjdG9yWCA9Xywgc2NhdHRlcikgOiB2YWx1ZUV4dHJhY3Rvclh9XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHkgc2NhbGUgZm9yIHdoaWNoIHRoZSBzY2F0dGVyIHkgdmFsdWVzIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBieVxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI3NjYWxlWX0pXG4gICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgZDMuc2NhbGV9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNjYWxlWSA9IGQzLnNjYWxlTGluZWFyKClcbiAgICovXG4gIHNjYXR0ZXIuc2NhbGVZID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzY2FsZVkgPV8sIHNjYXR0ZXIpIDogc2NhbGVZfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHBhZGRpbmcgZm9yIHRoZSBkb21haW4gb2YgdGhlIHkgc2NhbGVcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciNkb21haW5QYWRkaW5nWX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZG9tYWluUGFkZGluZ1kgPSAwLjVcbiAgICovXG4gIHNjYXR0ZXIuZG9tYWluUGFkZGluZ1kgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRvbWFpblBhZGRpbmdZID1fLCBzY2F0dGVyKSA6IGRvbWFpblBhZGRpbmdZfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHZhbHVlRXh0cmFjdG9yWVxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI3ZhbHVlRXh0cmFjdG9yWX0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZhbHVlRXh0cmFjdG9yWSA9IGZ1bmN0aW9uKGtleSwgaW5kZXgpIHsgcmV0dXJuIGRhdGFba2V5XVsneSddIH1cbiAgICovXG4gIHNjYXR0ZXIudmFsdWVFeHRyYWN0b3JZID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZUV4dHJhY3RvclkgPV8sIHNjYXR0ZXIpIDogdmFsdWVFeHRyYWN0b3JZfVxuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSByIHNjYWxlIGZvciB3aGljaCB0aGUgc2NhdHRlciByIHZhbHVlcyBzaG91bGQgYmUgdHJhbnNmb3JtZWQgYnlcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciNzY2FsZVJ9KVxuICAgKiBAcGFyYW0ge2QzLnNjYWxlfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IGQzLnNjYWxlfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzY2FsZVIgPSBkMy5zY2FsZUxpbmVhcigpXG4gICAqL1xuICBzY2F0dGVyLnNjYWxlUiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGVSID1fLCBzY2F0dGVyKSA6IHNjYWxlUn1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBwYWRkaW5nIGZvciB0aGUgZG9tYWluIG9mIHRoZSByIHNjYWxlXG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjZG9tYWluUGFkZGluZ1J9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGRvbWFpblBhZGRpbmdSID0gMC41XG4gICAqL1xuICBzY2F0dGVyLmRvbWFpblBhZGRpbmdSID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkb21haW5QYWRkaW5nUiA9Xywgc2NhdHRlcikgOiBkb21haW5QYWRkaW5nUn1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB2YWx1ZUV4dHJhY3RvclJcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciN2YWx1ZUV4dHJhY3RvclJ9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB2YWx1ZUV4dHJhY3RvclIgPSBmdW5jdGlvbihrZXksIGluZGV4KSB7IHJldHVybiBkYXRhW2tleV1bJ3InXSB9XG4gICAqL1xuICBzY2F0dGVyLnZhbHVlRXh0cmFjdG9yUiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodmFsdWVFeHRyYWN0b3JSID1fLCBzY2F0dGVyKSA6IHZhbHVlRXh0cmFjdG9yUn1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBtaW5SYWRpdXNcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciNtaW5SYWRpdXN9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1pblJhZGl1cyA9IDJcbiAgICovXG4gIHNjYXR0ZXIubWluUmFkaXVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChtaW5SYWRpdXMgPV8sIHNjYXR0ZXIpIDogbWluUmFkaXVzfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1heFJhZGl1c1xuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI21heFJhZGl1c30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbWF4UmFkaXVzID0gMTBcbiAgICovXG4gIHNjYXR0ZXIubWF4UmFkaXVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChtYXhSYWRpdXMgPV8sIHNjYXR0ZXIpIDogbWF4UmFkaXVzfVxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcG9pbnRTdHJva2VXaWR0aFxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI3BvaW50U3Ryb2tlV2lkdGh9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHBvaW50U3Ryb2tlV2lkdGggPSAyXG4gICAqL1xuICBzY2F0dGVyLnBvaW50U3Ryb2tlV2lkdGggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBvaW50U3Ryb2tlV2lkdGggPV8sIHNjYXR0ZXIpIDogcG9pbnRTdHJva2VXaWR0aH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBjb2xvckZ1bmN0aW9uXG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjY29sb3JGdW5jdGlvbn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24oKVxuICAgKi9cbiAgc2NhdHRlci5jb2xvckZ1bmN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjb2xvckZ1bmN0aW9uID1fLCBzY2F0dGVyKSA6IGNvbG9yRnVuY3Rpb259XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYmFja2dyb3VuZEZpbGxcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciNiYWNrZ3JvdW5kRmlsbH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYmFja2dyb3VuZEZpbGwgPSAndHJhbnNwYXJlbnQnXG4gICAqL1xuICBzY2F0dGVyLmJhY2tncm91bmRGaWxsID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChiYWNrZ3JvdW5kRmlsbCA9Xywgc2NhdHRlcikgOiBiYWNrZ3JvdW5kRmlsbH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBuYW1lc3BhY2VcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciNuYW1lc3BhY2V9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG5hbWVzcGFjZSA9ICdkM3NtLXNjYXR0ZXInXG4gICAqL1xuICBzY2F0dGVyLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID1fLCBzY2F0dGVyKSA6IG5hbWVzcGFjZX1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RDbGFzc1xuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI29iamVjdENsYXNzfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RDbGFzcyA9ICd0aWNrLWdyb3VwJ1xuICAgKi9cbiAgc2NhdHRlci5vYmplY3RDbGFzcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q2xhc3MgPV8sIHNjYXR0ZXIpIDogb2JqZWN0Q2xhc3N9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdHJhbnNpdGlvbkR1cmF0aW9uXG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjdHJhbnNpdGlvbkR1cmF0aW9ufSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwXG4gICAqL1xuICBzY2F0dGVyLnRyYW5zaXRpb25EdXJhdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodHJhbnNpdGlvbkR1cmF0aW9uID1fLCBzY2F0dGVyKSA6IHRyYW5zaXRpb25EdXJhdGlvbn1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBlYXNlRnVuY1xuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI2Vhc2VGdW5jfSlcbiAgICogQHBhcmFtIHtkMy5lYXNlfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IGQzLmVhc2V9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGVhc2VGdW5jID0gZDMuZWFzZUV4cFxuICAgKi9cbiAgc2NhdHRlci5lYXNlRnVuYyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZWFzZUZ1bmMgPV8sIHNjYXR0ZXIpIDogZWFzZUZ1bmN9XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBwb2ludEtleXNcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciNwb2ludEtleXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBwb2ludEtleXMgPSB1bmRlZmluZWRcbiAgICovXG4gIHNjYXR0ZXIucG9pbnRLZXlzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwb2ludEtleXMgPV8sIHNjYXR0ZXIpIDogcG9pbnRLZXlzfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHZhbHVlc1hcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciN2YWx1ZXNYfSlcbiAgICogQHBhcmFtIHtudW1iZXJbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBudW1iZXJbXX1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdmFsdWVzWCA9IHVuZGVmaW5lZFxuICAgKi9cbiAgc2NhdHRlci52YWx1ZXNYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZXNYID1fLCBzY2F0dGVyKSA6IHZhbHVlc1h9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdmFsdWVzWVxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI3ZhbHVlc1l9KVxuICAgKiBAcGFyYW0ge251bWJlcltdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IG51bWJlcltdfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB2YWx1ZXNZID0gdW5kZWZpbmVkXG4gICAqL1xuICBzY2F0dGVyLnZhbHVlc1kgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZhbHVlc1kgPV8sIHNjYXR0ZXIpIDogdmFsdWVzWX1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB2YWx1ZXNSXG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjdmFsdWVzUn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgbnVtYmVyW119XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZhbHVlc1IgPSB1bmRlZmluZWRcbiAgICovXG4gIHNjYXR0ZXIudmFsdWVzUiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodmFsdWVzUiA9Xywgc2NhdHRlcikgOiB2YWx1ZXNSfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRvb2x0aXBcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciN0b29sdGlwfSlcbiAgICogQHBhcmFtIHt0b29sdGlwfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IHRvb2x0aXB9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRvb2x0aXAgPSB0b29sdGlwKClcbiAgICovXG5cbiAgc2NhdHRlci50b29sdGlwID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0b29sdGlwID1fLCBzY2F0dGVyKSA6IHRvb2x0aXB9XG5cblxuICBmdW5jdGlvbiBzY2F0dGVyKCkge1xuICAgIC8vIGJhY2tncm91bmQgY2xpcGluZyByZWN0YW5nbGVcbiAgICB2YXIgYmdjcFJlY3QgPSB7eDowLCB5OjAsIHdpZHRoOiBzcGFjZVgsIGhlaWdodDpzcGFjZVl9XG4gICAgdmFyIGNvbnRhaW5lciA9IHNldHVwQ29udGFpbmVyKCBzZWxlY3Rpb24sIG5hbWVzcGFjZSwgYmdjcFJlY3QsIGJhY2tncm91bmRGaWxsICk7XG5cblxuICAgIHBvaW50S2V5cyA9IGQzLmtleXMoZGF0YSlcbiAgICB2YWx1ZXNYID0gcG9pbnRLZXlzLm1hcCh2YWx1ZUV4dHJhY3RvclgpXG4gICAgdmFsdWVzWSA9IHBvaW50S2V5cy5tYXAodmFsdWVFeHRyYWN0b3JZKVxuICAgIHZhbHVlc1IgPSBwb2ludEtleXMubWFwKHZhbHVlRXh0cmFjdG9yUilcblxuICAgIHZhciBudW1iZXJPZk9iamVjdHMgPSBwb2ludEtleXMubGVuZ3RoXG4gICAgdmFyIGV4dGVudFggPSBbTWF0aC5taW4oLi4udmFsdWVzWCkgLSBkb21haW5QYWRkaW5nWCwgTWF0aC5tYXgoLi4udmFsdWVzWCkgKyBkb21haW5QYWRkaW5nWF1cbiAgICB2YXIgZXh0ZW50WSA9IFtNYXRoLm1pbiguLi52YWx1ZXNZKSAtIGRvbWFpblBhZGRpbmdZLCBNYXRoLm1heCguLi52YWx1ZXNZKSArIGRvbWFpblBhZGRpbmdZXVxuICAgIHZhciBleHRlbnRSID0gW01hdGgubWluKC4uLnZhbHVlc1IpIC0gZG9tYWluUGFkZGluZ1IsIE1hdGgubWF4KC4uLnZhbHVlc1IpICsgZG9tYWluUGFkZGluZ1JdXG5cbiAgICBzY2FsZVguZG9tYWluKGV4dGVudFgpLnJhbmdlKFswLCBzcGFjZVhdKVxuICAgIHNjYWxlWS5kb21haW4oZXh0ZW50WSkucmFuZ2UoW3NwYWNlWSwgMF0pXG4gICAgc2NhbGVSLmRvbWFpbihleHRlbnRSKS5yYW5nZShbbWluUmFkaXVzLCBtYXhSYWRpdXNdKVxuXG4gICAgdmFyIHBvaW50cyA9IGNvbnRhaW5lci5zZWxlY3RBbGwoJy4nK29iamVjdENsYXNzKVxuICAgIHBvaW50cyA9IHBvaW50cy5kYXRhKHBvaW50S2V5cylcbiAgICB2YXIgcEVudGVyID0gcG9pbnRzLmVudGVyKCkuYXBwZW5kKCdjaXJjbGUnKVxuICAgIC5hdHRyKCdjbGFzcycsIG9iamVjdENsYXNzKVxuICAgIC5hdHRyKCdjeCcsIDApLmF0dHIoJ2N5Jywgc3BhY2VZKS5hdHRyKCdyJywgMClcblxuICAgIHZhciBwRXhpdCA9IHBvaW50cy5leGl0KClcblxuICAgIHBvaW50cyA9IHBvaW50cy5tZXJnZShwRW50ZXIpXG5cbiAgICBwb2ludHMuZWFjaChmdW5jdGlvbihrZXksIGkpe1xuICAgICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcyksXG4gICAgICBjdXJyZW50RGF0YSA9IGRhdGFba2V5XSxcbiAgICAgIHggPSB2YWx1ZXNYW2ldLFxuICAgICAgeSA9IHZhbHVlc1lbaV0sXG4gICAgICByID0gdmFsdWVzUltpXSxcbiAgICAgIGZpbGxDb2xvciA9IGNvbG9yRnVuY3Rpb24oa2V5LCBjdXJyZW50RGF0YSwgaSwgJ2ZpbGwnKSxcbiAgICAgIHN0cm9rZUNvbG9yID0gY29sb3JGdW5jdGlvbihrZXksIGN1cnJlbnREYXRhLCBpLCAnc3Ryb2tlJylcblxuICAgICAgdC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ2N4Jywgc2NhbGVYKHgpKVxuICAgICAgLmF0dHIoJ2N5Jywgc2NhbGVZKHkpKVxuICAgICAgLmF0dHIoJ3InLCBzY2FsZVIocikpXG4gICAgICAuYXR0cignZmlsbCcsIGZpbGxDb2xvcilcbiAgICAgIC5hdHRyKCdzdHJva2UnLCBzdHJva2VDb2xvcilcbiAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCBwb2ludFN0cm9rZVdpZHRoKVxuXG5cblxuICAgICAgdC5vbignbW91c2VvdmVyJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIHBvaW50cy5zdHlsZSgnb3BhY2l0eScsIDAuMilcbiAgICAgICAgdC5zdHlsZSgnb3BhY2l0eScsIDEpXG4gICAgICAgIHQudHJhbnNpdGlvbigpLmR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbi8yKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgcG9pbnRTdHJva2VXaWR0aCoyKVxuICAgICAgICAuYXR0cigncicsIHNjYWxlUihyKSAqIDEuNSlcblxuICAgICAgfSlcbiAgICAgIHQubm9kZSgpLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3V0JywgZnVuY3Rpb24oKXtcbiAgICAgICAgY29udGFpbmVyLnNlbGVjdEFsbCgnLicrb2JqZWN0Q2xhc3MpLnN0eWxlKCdvcGFjaXR5JywgMSlcbiAgICAgICAgdC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uLzIpLmVhc2UoZWFzZUZ1bmMpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCBwb2ludFN0cm9rZVdpZHRoKVxuICAgICAgICAuYXR0cigncicsIHNjYWxlUihyKSlcblxuICAgICAgfSlcblxuICAgIH0pXG5cblxuXG4gICAgcEV4aXQudHJhbnNpdGlvbigpLmR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbikuZWFzZShlYXNlRnVuYylcbiAgICAuYXR0cignY3gnLCAwKS5hdHRyKCdjeScsIHNwYWNlWSkuYXR0cigncicsIDApXG4gICAgLnJlbW92ZSgpXG5cbiAgICB0b29sdGlwLnNlbGVjdGlvbihwb2ludHMpXG4gICAgLmRhdGEoZGF0YSlcblxuICAgIHRvb2x0aXAoKVxuICB9XG5cblxuICByZXR1cm4gc2NhdHRlclxufVxuIiwiaW1wb3J0IHtoeXBlbmF0ZSwgc2FmZVNlbGVjdCwgZ2V0VHJhbnNsYXRpb259IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQge2xvZywgd2FybiwgZXJyb3IsIGluZm99IGZyb20gJy4vdXRpbHMnO1xuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcblxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUExPVFpPT00gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuLyoqXG4gKiBDcmVhdGVzIGFuIHBsb3Rab29tIGluc3RhbmNlLCB3aGljaCBjYW4gaGFuZGxlIGRyYWcgYW5kIHNjcm9sbCBldmVudHNcbiAqIEBjb25zdHJ1Y3RvciBwbG90Wm9vbVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2hhcnQgYSBmdW5jdGlvbiBpbnN0YW5jZSBvZiBvbmUgb2YgdGhlIGQzc20gcGxvdHMgKGUuZy4gYmFyLCBib3h3aGlza2VyLCBidWJibGVIZWF0bWFwLCB2aW9saW4sIGV0YylcbiAqIEBwYXJhbSB7YXhpc30gIHhBeGlzIHRoZSBheGlzIGluc3RhbmNlIHJlc3BvbnNpYmxlIGZvciB0aGUgeCBheGlzXG4gKiBAcGFyYW0ge2F4aXN9IHlBeGlzIHRoZSBheGlzIGluc3RhbmNlIHJlc3BvbnNpYmxlIGZvciB0aGUgeSBheGlzXG4gKiBAbmFtZXNwYWNlIHBsb3Rab29tXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IHpvb21cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBsb3Rab29tKCBjaGFydCwgeEF4aXMsIHlBeGlzICkge1xuICB2YXJcbiAgLyoqXG4gICogVGhlIGV2ZW50IG9uIHdoaWNoIHRvIGZpcmVcbiAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSNldmVudFR5cGV9KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFR5cGUgd2hpY2ggZXZlbnQgaXQgc2hvdWxkIGhhbmRsZS4gQ3VycmVudGx5IHN1cHBvcnRzIHNjcm9sbCBhbmQgd2hlZWxcbiAgKiBAbWVtYmVyb2YgcGxvdFpvb20jXG4gICogQHByb3BlcnR5XG4gICovXG4gIGV2ZW50VHlwZSxcbiAgLyoqXG4gICogQSBzY2FsaW5nIGZhY3RvciBmb3IgdGhlIHdoZWVsIFwic3BlZWRcIlxuICAqIChzZWUge0BsaW5rIHBsb3Rab29tI3doZWVsU3BlZWR9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbd2hlZWxTcGVlZD0yMF0gc2NhbGVzIHRoZSB3aGVlbCB0cmFuc2xhdGlvbiBieSB3aGVlbFNwZWVkXG4gICogQG1lbWJlcm9mIHBsb3Rab29tI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB3aGVlbFNwZWVkID0gMjAsXG4gIC8qKlxuICAqIFRoZSBvcmllbnRhdGlvbiBpbiB3aGljaCB0byBhbGxvdyBzY3JvbGxpbmc6ICdob3Jpem9udGFsJywgJ3ZlcnRpY2FsJywgb3IgJzJEJ1xuICAqIChzZWUge0BsaW5rIHBsb3Rab29tI29yaWVudH0pXG4gICogQHBhcmFtIHtzdHJpbmd9IFtvcmllbnQ9Y2hhcnQub3JpZW50KCkgfHwgJ2hvcml6b250YWwnXVxuICAqIEBtZW1iZXJvZiBwbG90Wm9vbSNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb3JpZW50ID0gKGNoYXJ0Lm9yaWVudCA9PSB1bmRlZmluZWQpID8gJ2hvcml6b250YWwnIDogY2hhcnQub3JpZW50KCksXG4gIC8qKlxuICAqIFRoZSBtYXggZGlzdGFuY2UgYWxsb3dlZCB0byBzY3JvbGwgaW4gdGhlIHggZGlyZWN0aW9uXG4gICogKHNlZSB7QGxpbmsgcGxvdFpvb20jeExvY2t9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbeExvY2s9Y2hhcnQuc3BhY2VYKCldIGlkZWFsbHkgY2hhcnQub3ZlcmZsb3dRKCkgPT0gdHJ1ZSBhbmQgdGhpcyB2YWx1ZSBpcyB0aGVcbiAgKiBib3VuZGluZyByZWN0IGFjcm9zcyBhbGwgZWxlbWVudHMgaW4gdGhlIGNoYXJ0ICBtaW51cyB0aGUgc3BhY2UgaW4gd2hpY2ggdG8gc2hvdy5cbiAgKiBAbWVtYmVyb2YgcGxvdFpvb20jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhMb2NrPWNoYXJ0LnNwYWNlWCgpLFxuICAvKipcbiAgKiBUaGUgbWF4IGRpc3RhbmNlIGFsbG93ZWQgdG8gc2Nyb2xsIGluIHRoZSB5IGRpcmVjdGlvblxuICAqIChzZWUge0BsaW5rIHBsb3Rab29tI3lMb2NrfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3lMb2NrPWNoYXJ0LnNwYWNlWSgpXSBpZGVhbGx5IGNoYXJ0Lm92ZXJmbG93USgpID09IHRydWUgYW5kIHRoaXMgdmFsdWUgaXMgdGhlXG4gICogYm91bmRpbmcgcmVjdCBhY3Jvc3MgYWxsIGVsZW1lbnRzIGluIHRoZSBjaGFydCAgbWludXMgdGhlIHNwYWNlIGluIHdoaWNoIHRvIHNob3cuXG4gICogQG1lbWJlcm9mIHBsb3Rab29tI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB5TG9jaz1jaGFydC5zcGFjZVkoKSxcblxuICBjaGFydFNlbCA9IGNoYXJ0LnNlbGVjdGlvbigpLFxuICB4QXhpc1NlbCA9IHhBeGlzLnNlbGVjdGlvbigpLFxuICB5QXhpc1NlbCA9IHlBeGlzLnNlbGVjdGlvbigpLFxuICBzdmcgPSBkMy5zZWxlY3QoY2hhcnRTZWwudGhpc1NWRygpKVxuXG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZXZlbnQgdHlwZSBpbiB3aGljaCB0byByZXNwb25kXG4gICAqIChzZWUge0BsaW5rIHBsb3Rab29tI2V2ZW50VHlwZX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXSBzaG91bGQgYmUgJ2RyYWcnIG9yICd3aGVlbCdcbiAgICogQHJldHVybnMge3pvb20gfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBwbG90Wm9vbVxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBwbG90Wm9vbT11bmRlZmluZWRcbiAgICovXG4gIHpvb20uZXZlbnRUeXBlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChldmVudFR5cGUgPSBfLCB6b29tKSA6IGV2ZW50VHlwZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgd2hlZWwgc3BlZWQgaW4gd2hpY2ggdG8gc2NhbGUgdGhlIHdoZWVsIHNjcm9sbCB0cmFuc2Zvcm1cbiAgICogKHNlZSB7QGxpbmsgcGxvdFpvb20jd2hlZWxTcGVlZH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7em9vbSB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHBsb3Rab29tXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHdoZWVsU3BlZWQ9MjBcbiAgICovXG4gIHpvb20ud2hlZWxTcGVlZCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAod2hlZWxTcGVlZCA9IF8sIHpvb20pIDogd2hlZWxTcGVlZDsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgb3JpZW50YXRpb24gaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIHBsb3Rab29tI29yaWVudH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXSBzaG91bGQgYmUgaG9yaXpvbnRhbCwgdmVydGljYWwsIG9yIDJEXG4gICAqIEByZXR1cm5zIHt6b29tIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgcGxvdFpvb21cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3JpZW50PWNoYXJ0Lm9yaWVudCgpIHx8ICdob3Jpem9udGFsJ1xuICAgKi9cbiAgem9vbS5vcmllbnQgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9yaWVudCA9IF8sIHpvb20pIDogb3JpZW50OyB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIG1heCBkaXN0YW5jZSBpbiB3aGljaCB0byBzY3JvbGwgWFxuICAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN4TG9ja30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBwb3NpdGl2ZSB2YWx1ZVxuICAgKiBAcmV0dXJucyB7em9vbSB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHBsb3Rab29tXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHhMb2NrPWNoYXJ0LnNwYWNlWCgpXG4gICAqL1xuICB6b29tLnhMb2NrID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4TG9jayA9IF8sIHpvb20pIDogeExvY2s7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIG1heCBkaXN0YW5jZSBpbiB3aGljaCB0byBzY3JvbGwgWVxuICAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN5TG9ja30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSAgc2hvdWxkIGJlIGEgcG9zaXRpdmUgdmFsdWVcbiAgICogQHJldHVybnMge3pvb20gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBwbG90Wm9vbVxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5TG9jaz1jaGFydC5zcGFjZVkoKVxuICAgKi9cbiAgem9vbS55TG9jayA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeUxvY2sgPSBfLCB6b29tKSA6IHlMb2NrOyB9O1xuXG5cbiAgZnVuY3Rpb24gc2V0TG9ja3MoKSB7XG4gICAgdmFyIGNoYXJ0T2JqU2VsID0gY2hhcnRTZWwuc2VsZWN0KCcuJytoeXBlbmF0ZShjaGFydC5uYW1lc3BhY2UoKSwnb2JqZWN0LWNvbnRhaW5lcicpKVxuICAgIHZhciBjaGFydE9ialRyYW5zID0gZ2V0VHJhbnNsYXRpb24oY2hhcnRPYmpTZWwuYXR0cigndHJhbnNmb3JtJykpXG4gICAgdmFyIGNvcyA9IGNoYXJ0T2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoMCwwKScpXG4gICAgeExvY2sgPSBjaGFydFNlbC5ub2RlKCkuZ2V0QkJveCgpLndpZHRoIC0gY2hhcnQuc3BhY2VYKCkgKiAuOVxuICAgIHlMb2NrID0gY2hhcnRTZWwubm9kZSgpLmdldEJCb3goKS5oZWlnaHQgLSBjaGFydC5zcGFjZVkoKSAqIC45XG4gICAgY29zLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJytjaGFydE9ialRyYW5zWzBdKycsJytjaGFydE9ialRyYW5zWzFdKycpJylcbiAgICBsb2coJ3Bsb3Rab29tJywgJ3NldExvY2tzJywge3hMb2NrOnhMb2NrLCB5TG9jazp5TG9ja30pXG4gIH1cblxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSB4IGFuZCB5IGxvY2tzIChob3cgZmFyIG9uZSBjYW4gc2Nyb2xsKVxuICAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN4TG9ja30gYW5kIHtAbGluayBwbG90Wm9vbSN5TG9ja30pXG4gICAqIEBmdW5jdGlvbiBwbG90Wm9vbS5zZXRMb2Nrc1xuICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICAgKiBAbWVtYmVyb2YgcGxvdFpvb21cbiAgICogQHByb3BlcnR5XG4gICAqL1xuICB6b29tLnNldExvY2tzID0gc2V0TG9ja3NcblxuICBmdW5jdGlvbiB6b29tKCkge1xuICAgIHNldExvY2tzKClcblxuICAgIHZhciBob3Jpem9udGFsUSwgdmVydGljYWxRXG4gICAgaWYgKG9yaWVudCA9PSAnMkQnKSB7aG9yaXpvbnRhbFEgPSB0cnVlOyB2ZXJ0aWNhbFEgPSB0cnVlO31cbiAgICBpZiAob3JpZW50ID09ICdob3Jpem9udGFsJykge2hvcml6b250YWxRID0gdHJ1ZTsgdmVydGljYWxRID0gZmFsc2U7fVxuICAgIGlmIChvcmllbnQgPT0gJ3ZlcnRpY2FsJykge3ZlcnRpY2FsUSA9IHRydWU7IGhvcml6b250YWxRID0gZmFsc2U7fVxuXG4gICAgLy8gY2FwdHVyZSB0cmFuc2Zvcm0gZXZlbnRcbiAgICB2YXIgdHJhbnNmb3JtID0gZDMuZXZlbnQudHJhbnNmb3JtXG5cbiAgICB2YXIgY2hhcnRCb3ggPSBjaGFydFNlbC5ub2RlKCkuZ2V0QkJveCgpXG4gICAgdmFyIHhBeGlzQm94ID0geEF4aXNTZWwubm9kZSgpLmdldEJCb3goKVxuICAgIHZhciB5QXhpc0JveCA9IHhBeGlzU2VsLm5vZGUoKS5nZXRCQm94KClcblxuICAgIHZhciBjaGFydFdpZHRoID0gY2hhcnRCb3gud2lkdGggLSBjaGFydEJveC54XG4gICAgdmFyIGNoYXJ0SGVpZ2h0ID0gY2hhcnRCb3guaGVpZ2h0IC0gY2hhcnRCb3gueVxuICAgIHZhciB4QXhpc1dpZHRoID0geEF4aXNCb3gud2lkdGgvLyAtIHhBeGlzQm94LnhcbiAgICB2YXIgeEF4aXNIZWlnaHQgPSB4QXhpc0JveC5oZWlnaHQvLyAtIHhBeGlzQm94LnlcbiAgICB2YXIgeUF4aXNXaWR0aCA9IHlBeGlzQm94LndpZHRoLy8gLSB5QXhpc0JveC54XG4gICAgdmFyIHlBeGlzSGVpZ2h0ID0geUF4aXNCb3guaGVpZ2h0Ly8gLXlBeGlzQm94LnlcblxuICAgIC8vIGVuYWJsZSB3aGVlbCBldmVudFxuICAgIGlmIChldmVudFR5cGUgPT0gXCJ3aGVlbFwiKSB7XG4gICAgICB2YXIgZSA9IGQzLmV2ZW50XG4gICAgICAvLyBwcmV2ZW50IHBhZ2Ugc2Nyb2xsaW5nXG4gICAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICAgIC8vIGV2ZW50IGRlbHRhIGlzIHZlcnkgdmVyeSBzbG93LCBzbyBzcGVlZCBpdCB1cCB3aXRoIHdoZWVsIHNwZWVkXG4gICAgICB2YXIgdyA9IGQzLmV2ZW50LmRlbHRhWSAqIHdoZWVsU3BlZWRcbiAgICAgIHZhciBzaGlmdFEgPSBkMy5ldmVudC5zaGlmdEtleVxuXG4gICAgICAvLyBkMyBoYXMgbm8gd2F5IHRvIG1ha2UgY3VzdG9tIHRyYW5zZm9ybSwgc28gbWFrZSBhbiBvYmplY3QgYW5kIGFkZFxuICAgICAgLy8gdGhlIG5lY2Vzc2FyeSBmdW5jdGlvbnMgdG8gbWFrZSB3aGVlbCBldmVudCBjb21wYXRpYmxlIHdpdGggZHJhZyBldmVudHNcbiAgICAgIGlmIChvcmllbnQgPT0gJzJEJykge1xuICAgICAgICB0cmFuc2Zvcm0gPSBzaGlmdFEgPyB7azogMSwgeDogdywgeTogMH0gOiB7azogMSwgeDogMCwgeTogd31cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyYW5zZm9ybSA9IGhvcml6b250YWxRID8ge2s6IDEsIHg6IHcsIHk6IDB9IDoge2s6IDEsIHg6IDAsIHk6IHd9XG4gICAgICB9XG4gICAgICAvLyB0aGUgKiAtMSBpbnZlcnRzIHRoZSBkaXJlY3Rpb25cbiAgICAgIHRyYW5zZm9ybS5hcHBseVggPSBmdW5jdGlvbih4KSB7IHJldHVybiB4ICogdGhpcy5rICsgdGhpcy54ICogLTE7IH1cbiAgICAgIHRyYW5zZm9ybS5hcHBseVkgPSAgZnVuY3Rpb24oeSkgeyByZXR1cm4geSAqIHRoaXMuayArIHRoaXMueSAqIC0xOyB9XG4gICAgfVxuXG5cblxuICAgIHZhciBjaGFydE9ialNlbCA9IGNoYXJ0U2VsLnNlbGVjdCgnLicraHlwZW5hdGUoY2hhcnQubmFtZXNwYWNlKCksJ29iamVjdC1jb250YWluZXInKSlcbiAgICB2YXIgeEF4aXNPYmpTZWwgPSB4QXhpc1NlbC5zZWxlY3QoJy4nK2h5cGVuYXRlKHhBeGlzLm5hbWVzcGFjZSgpLCdvYmplY3QtY29udGFpbmVyJykpXG4gICAgdmFyIHlBeGlzT2JqU2VsID0geUF4aXNTZWwuc2VsZWN0KCcuJytoeXBlbmF0ZSh5QXhpcy5uYW1lc3BhY2UoKSwnb2JqZWN0LWNvbnRhaW5lcicpKVxuXG4gICAgLy8geExvY2sgPSBjaGFydFNlbC5ub2RlKCkuZ2V0QkJveCgpLndpZHRoIC0gY2hhcnQuc3BhY2VYKCkgLSBjaGFydFNlbC5ub2RlKCkuZ2V0QkJveCgpLnhcbiAgICAvLyB5TG9jayA9IGNoYXJ0U2VsLm5vZGUoKS5nZXRCQm94KCkuaGVpZ2h0IC0gY2hhcnQuc3BhY2VZKClcbiAgICAvLyBjb25zb2xlLnRhYmxlKHsneExvY2snOnhMb2NrLCBcInlMb2NrXCI6eUxvY2t9KVxuICAgIC8vIGJobS5zZWxlY3Rpb24oKS5ub2RlKCkuZ2V0QkJveCgpLndpZHRoIC0gYmhtLnNwYWNlWCgpXG5cblxuICAgIHZhciBjaGFydE9ialRyYW5zID0gZ2V0VHJhbnNsYXRpb24oY2hhcnRPYmpTZWwuYXR0cigndHJhbnNmb3JtJykpXG4gICAgdmFyIHhBeGlzT2JqVHJhbnMgPSBnZXRUcmFuc2xhdGlvbih4QXhpc09ialNlbC5hdHRyKCd0cmFuc2Zvcm0nKSlcbiAgICB2YXIgeUF4aXNPYmpUcmFucyA9IGdldFRyYW5zbGF0aW9uKHlBeGlzT2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScpKVxuXG5cbiAgICB2YXIgeCA9IGhvcml6b250YWxRID8gdHJhbnNmb3JtLmFwcGx5WChjaGFydE9ialRyYW5zWzBdKSA6IDBcbiAgICBpZiAoaG9yaXpvbnRhbFEpIHt4ID0geCA8IC14TG9jayA/ICh0cmFuc2Zvcm0ueCA9IDAsIC14TG9jaykgOiAodHJhbnNmb3JtLnggPSAwLCBNYXRoLm1pbih4LCAwKSkgfVxuXG4gICAgdmFyIHkgPSB2ZXJ0aWNhbFEgPyB0cmFuc2Zvcm0uYXBwbHlZKGNoYXJ0T2JqVHJhbnNbMV0pIDogMFxuICAgIGlmICh2ZXJ0aWNhbFEpIHt5ID0geSA8IC15TG9jayA/ICh0cmFuc2Zvcm0ueSA9IDAsIC15TG9jayk6ICh0cmFuc2Zvcm0ueSA9IDAsIE1hdGgubWluKHksIDApKX1cblxuICAgIGNoYXJ0T2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJylcbiAgICBpZiAoaG9yaXpvbnRhbFEpIHsgeEF4aXNPYmpTZWwuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnK3grJywnKzArJyknKSB9XG4gICAgaWYgKHZlcnRpY2FsUSkgeyB5QXhpc09ialNlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcrMCsnLCcreSsnKScpIH1cblxuICAgIC8vIHZhciBsYXNzbyA9IHN2Zy5zZWxlY3QoXCIubGFzc28tY29udGFpbmVyXCIpXG4gICAgLy8gaWYgKCFsYXNzby5lbXB0eSgpKSB7XG4gICAgLy8gICBsYXNzby5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcreCsnLCcreSsnKScpXG4gICAgLy8gfVxuXG4gIH1cblxuICB6b29tLnJlc2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGhvcml6b250YWxRLCB2ZXJ0aWNhbFFcbiAgICBpZiAob3JpZW50ID09ICcyRCcpIHtob3Jpem9udGFsUSA9IHRydWU7IHZlcnRpY2FsUSA9IHRydWU7fVxuICAgIGlmIChvcmllbnQgPT0gJ2hvcml6b250YWwnKSB7aG9yaXpvbnRhbFEgPSB0cnVlOyB2ZXJ0aWNhbFEgPSBmYWxzZTt9XG4gICAgaWYgKG9yaWVudCA9PSAndmVydGljYWwnKSB7dmVydGljYWxRID0gdHJ1ZTsgaG9yaXpvbnRhbFEgPSBmYWxzZTt9XG5cbiAgICB2YXIgY2hhcnRPYmpTZWwgPSBjaGFydFNlbC5zZWxlY3QoJy4nK2h5cGVuYXRlKGNoYXJ0Lm5hbWVzcGFjZSgpLCdvYmplY3QtY29udGFpbmVyJykpXG4gICAgdmFyIHhBeGlzT2JqU2VsID0geEF4aXNTZWwuc2VsZWN0KCcuJytoeXBlbmF0ZSh4QXhpcy5uYW1lc3BhY2UoKSwnb2JqZWN0LWNvbnRhaW5lcicpKVxuICAgIHZhciB5QXhpc09ialNlbCA9IHlBeGlzU2VsLnNlbGVjdCgnLicraHlwZW5hdGUoeUF4aXMubmFtZXNwYWNlKCksJ29iamVjdC1jb250YWluZXInKSlcbiAgICBjaGFydE9ialNlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcrMCsnLCcrMCsnKScpXG4gICAgeEF4aXNPYmpTZWwuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnKzArJywnKzArJyknKVxuICAgIHlBeGlzT2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyswKycsJyswKycpJylcbiAgfVxuXG4gIHJldHVybiB6b29tXG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0LCBnZXRUcmFuc2xhdGlvbn0gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7bG9nLCB3YXJuLCBlcnJvciwgaW5mb30gZnJvbSAnLi91dGlscyc7XG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQTE9UWk9PTSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4vKipcbiAqIENyZWF0ZXMgYW4gcGxvdFpvb20gaW5zdGFuY2UsIHdoaWNoIGNhbiBoYW5kbGUgZHJhZyBhbmQgc2Nyb2xsIGV2ZW50c1xuICogQGNvbnN0cnVjdG9yIHBsb3Rab29tXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjaGFydCBhIGZ1bmN0aW9uIGluc3RhbmNlIG9mIG9uZSBvZiB0aGUgZDNzbSBwbG90cyAoZS5nLiBiYXIsIGJveHdoaXNrZXIsIGJ1YmJsZUhlYXRtYXAsIHZpb2xpbiwgZXRjKVxuICogQHBhcmFtIHtheGlzfSAgeEF4aXMgdGhlIGF4aXMgaW5zdGFuY2UgcmVzcG9uc2libGUgZm9yIHRoZSB4IGF4aXNcbiAqIEBwYXJhbSB7YXhpc30geUF4aXMgdGhlIGF4aXMgaW5zdGFuY2UgcmVzcG9uc2libGUgZm9yIHRoZSB5IGF4aXNcbiAqIEBuYW1lc3BhY2UgcGxvdFpvb21cbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gem9vbVxuICovXG5leHBvcnQgZnVuY3Rpb24gbXVsdGlQbG90Wm9vbSggY2hhcnQgKSB7XG4gIHZhclxuICAvKipcbiAgKiBUaGUgZXZlbnQgb24gd2hpY2ggdG8gZmlyZVxuICAqIChzZWUge0BsaW5rIHBsb3Rab29tI2V2ZW50VHlwZX0pXG4gICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50VHlwZSB3aGljaCBldmVudCBpdCBzaG91bGQgaGFuZGxlLiBDdXJyZW50bHkgc3VwcG9ydHMgc2Nyb2xsIGFuZCB3aGVlbFxuICAqIEBtZW1iZXJvZiBwbG90Wm9vbSNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZXZlbnRUeXBlLFxuICAvKipcbiAgKiBBIHNjYWxpbmcgZmFjdG9yIGZvciB0aGUgd2hlZWwgXCJzcGVlZFwiXG4gICogKHNlZSB7QGxpbmsgcGxvdFpvb20jd2hlZWxTcGVlZH0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFt3aGVlbFNwZWVkPTIwXSBzY2FsZXMgdGhlIHdoZWVsIHRyYW5zbGF0aW9uIGJ5IHdoZWVsU3BlZWRcbiAgKiBAbWVtYmVyb2YgcGxvdFpvb20jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHdoZWVsU3BlZWQgPSAyMCxcbiAgLyoqXG4gICogVGhlIG9yaWVudGF0aW9uIGluIHdoaWNoIHRvIGFsbG93IHNjcm9sbGluZzogJ2hvcml6b250YWwnLCAndmVydGljYWwnLCBvciAnMkQnXG4gICogKHNlZSB7QGxpbmsgcGxvdFpvb20jb3JpZW50fSlcbiAgKiBAcGFyYW0ge3N0cmluZ30gW29yaWVudD1jaGFydC5vcmllbnQoKSB8fCAnaG9yaXpvbnRhbCddXG4gICogQG1lbWJlcm9mIHBsb3Rab29tI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvcmllbnQgPSAoY2hhcnQub3JpZW50ID09IHVuZGVmaW5lZCkgPyAnaG9yaXpvbnRhbCcgOiBjaGFydC5vcmllbnQoKSxcbiAgLyoqXG4gICogVGhlIG1heCBkaXN0YW5jZSBhbGxvd2VkIHRvIHNjcm9sbCBpbiB0aGUgeCBkaXJlY3Rpb25cbiAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN4TG9ja30pXG4gICogQHBhcmFtIHtudW1iZXJ9IFt4TG9jaz1jaGFydC5zcGFjZVgoKV0gaWRlYWxseSBjaGFydC5vdmVyZmxvd1EoKSA9PSB0cnVlIGFuZCB0aGlzIHZhbHVlIGlzIHRoZVxuICAqIGJvdW5kaW5nIHJlY3QgYWNyb3NzIGFsbCBlbGVtZW50cyBpbiB0aGUgY2hhcnQgIG1pbnVzIHRoZSBzcGFjZSBpbiB3aGljaCB0byBzaG93LlxuICAqIEBtZW1iZXJvZiBwbG90Wm9vbSNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeExvY2s9Y2hhcnQuc3BhY2VYKCksXG4gIC8qKlxuICAqIFRoZSBtYXggZGlzdGFuY2UgYWxsb3dlZCB0byBzY3JvbGwgaW4gdGhlIHkgZGlyZWN0aW9uXG4gICogKHNlZSB7QGxpbmsgcGxvdFpvb20jeUxvY2t9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbeUxvY2s9Y2hhcnQuc3BhY2VZKCldIGlkZWFsbHkgY2hhcnQub3ZlcmZsb3dRKCkgPT0gdHJ1ZSBhbmQgdGhpcyB2YWx1ZSBpcyB0aGVcbiAgKiBib3VuZGluZyByZWN0IGFjcm9zcyBhbGwgZWxlbWVudHMgaW4gdGhlIGNoYXJ0ICBtaW51cyB0aGUgc3BhY2UgaW4gd2hpY2ggdG8gc2hvdy5cbiAgKiBAbWVtYmVyb2YgcGxvdFpvb20jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHlMb2NrPWNoYXJ0LnNwYWNlWSgpLFxuXG4gIGNoYXJ0U2VsID0gY2hhcnQuc2VsZWN0aW9uKCksXG5cbiAgc3ZnID0gZDMuc2VsZWN0KGNoYXJ0U2VsLnRoaXNTVkcoKSksXG5cbiAgeENvbXBvbmVudHMgPSBbXSxcbiAgeUNvbXBvbmVudHMgPSBbXVxuXG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZXZlbnQgdHlwZSBpbiB3aGljaCB0byByZXNwb25kXG4gICAqIChzZWUge0BsaW5rIHBsb3Rab29tI2V2ZW50VHlwZX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXSBzaG91bGQgYmUgJ2RyYWcnIG9yICd3aGVlbCdcbiAgICogQHJldHVybnMge3pvb20gfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBwbG90Wm9vbVxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBwbG90Wm9vbT11bmRlZmluZWRcbiAgICovXG4gIHpvb20uZXZlbnRUeXBlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChldmVudFR5cGUgPSBfLCB6b29tKSA6IGV2ZW50VHlwZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgd2hlZWwgc3BlZWQgaW4gd2hpY2ggdG8gc2NhbGUgdGhlIHdoZWVsIHNjcm9sbCB0cmFuc2Zvcm1cbiAgICogKHNlZSB7QGxpbmsgcGxvdFpvb20jd2hlZWxTcGVlZH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7em9vbSB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHBsb3Rab29tXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHdoZWVsU3BlZWQ9MjBcbiAgICovXG4gIHpvb20ud2hlZWxTcGVlZCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAod2hlZWxTcGVlZCA9IF8sIHpvb20pIDogd2hlZWxTcGVlZDsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgb3JpZW50YXRpb24gaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIHBsb3Rab29tI29yaWVudH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXSBzaG91bGQgYmUgaG9yaXpvbnRhbCwgdmVydGljYWwsIG9yIDJEXG4gICAqIEByZXR1cm5zIHt6b29tIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgcGxvdFpvb21cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3JpZW50PWNoYXJ0Lm9yaWVudCgpIHx8ICdob3Jpem9udGFsJ1xuICAgKi9cbiAgem9vbS5vcmllbnQgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9yaWVudCA9IF8sIHpvb20pIDogb3JpZW50OyB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIG1heCBkaXN0YW5jZSBpbiB3aGljaCB0byBzY3JvbGwgWFxuICAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN4TG9ja30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBwb3NpdGl2ZSB2YWx1ZVxuICAgKiBAcmV0dXJucyB7em9vbSB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHBsb3Rab29tXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHhMb2NrPWNoYXJ0LnNwYWNlWCgpXG4gICAqL1xuICB6b29tLnhMb2NrID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4TG9jayA9IF8sIHpvb20pIDogeExvY2s7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIG1heCBkaXN0YW5jZSBpbiB3aGljaCB0byBzY3JvbGwgWVxuICAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN5TG9ja30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSAgc2hvdWxkIGJlIGEgcG9zaXRpdmUgdmFsdWVcbiAgICogQHJldHVybnMge3pvb20gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBwbG90Wm9vbVxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5TG9jaz1jaGFydC5zcGFjZVkoKVxuICAgKi9cbiAgem9vbS55TG9jayA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeUxvY2sgPSBfLCB6b29tKSA6IHlMb2NrOyB9O1xuXG4gIHpvb20ueENvbXBvbmVudHMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhDb21wb25lbnRzID0gXywgem9vbSkgOiB4Q29tcG9uZW50czsgfTtcbiAgem9vbS55Q29tcG9uZW50cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeUNvbXBvbmVudHMgPSBfLCB6b29tKSA6IHlDb21wb25lbnRzOyB9O1xuXG5cbiAgZnVuY3Rpb24gc2V0TG9ja3MoKSB7XG4gICAgdmFyIGNoYXJ0T2JqU2VsID0gY2hhcnRTZWwuc2VsZWN0KCcuJytoeXBlbmF0ZShjaGFydC5uYW1lc3BhY2UoKSwnb2JqZWN0LWNvbnRhaW5lcicpKVxuICAgIHZhciBjaGFydE9ialRyYW5zID0gZ2V0VHJhbnNsYXRpb24oY2hhcnRPYmpTZWwuYXR0cigndHJhbnNmb3JtJykpXG4gICAgdmFyIGNvcyA9IGNoYXJ0T2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoMCwwKScpXG5cbiAgICB4TG9jayA9IGNoYXJ0U2VsLm5vZGUoKS5nZXRCQm94KCkud2lkdGggLSBjaGFydC5zcGFjZVgoKS8vICogLjlcbiAgICB5TG9jayA9IGNoYXJ0U2VsLm5vZGUoKS5nZXRCQm94KCkuaGVpZ2h0IC0gY2hhcnQuc3BhY2VZKCkvLyAqIC45XG4gICAgY29zLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJytjaGFydE9ialRyYW5zWzBdKycsJytjaGFydE9ialRyYW5zWzFdKycpJylcbiAgICBsb2coJ3Bsb3Rab29tJywgJ3NldExvY2tzJywge3hMb2NrOnhMb2NrLCB5TG9jazp5TG9ja30pXG4gIH1cblxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSB4IGFuZCB5IGxvY2tzIChob3cgZmFyIG9uZSBjYW4gc2Nyb2xsKVxuICAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN4TG9ja30gYW5kIHtAbGluayBwbG90Wm9vbSN5TG9ja30pXG4gICAqIEBmdW5jdGlvbiBwbG90Wm9vbS5zZXRMb2Nrc1xuICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICAgKiBAbWVtYmVyb2YgcGxvdFpvb21cbiAgICogQHByb3BlcnR5XG4gICAqL1xuICB6b29tLnNldExvY2tzID0gc2V0TG9ja3NcblxuICBmdW5jdGlvbiB6b29tKCkge1xuICAgIHNldExvY2tzKClcblxuICAgIHZhclxuICAgIHhDb21wb25lbnRzU2VsID0geENvbXBvbmVudHMubWFwKGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkLnNlbGVjdGlvbigpfSksXG4gICAgeUNvbXBvbmVudHNTZWwgPSB5Q29tcG9uZW50cy5tYXAoZnVuY3Rpb24oZCwgaSl7cmV0dXJuIGQuc2VsZWN0aW9uKCl9KVxuXG4gICAgdmFyIGhvcml6b250YWxRLCB2ZXJ0aWNhbFFcbiAgICBpZiAob3JpZW50ID09ICcyRCcpIHtob3Jpem9udGFsUSA9IHRydWU7IHZlcnRpY2FsUSA9IHRydWU7fVxuICAgIGlmIChvcmllbnQgPT0gJ2hvcml6b250YWwnKSB7aG9yaXpvbnRhbFEgPSB0cnVlOyB2ZXJ0aWNhbFEgPSBmYWxzZTt9XG4gICAgaWYgKG9yaWVudCA9PSAndmVydGljYWwnKSB7dmVydGljYWxRID0gdHJ1ZTsgaG9yaXpvbnRhbFEgPSBmYWxzZTt9XG5cbiAgICAvLyBjYXB0dXJlIHRyYW5zZm9ybSBldmVudFxuICAgIHZhciB0cmFuc2Zvcm0gPSBkMy5ldmVudC50cmFuc2Zvcm1cblxuICAgIHZhciBjaGFydEJveCA9IGNoYXJ0U2VsLm5vZGUoKS5nZXRCQm94KClcbiAgICB2YXIgeENvbXBvbmVudHNCb3ggPSB4Q29tcG9uZW50c1NlbC5tYXAoZnVuY3Rpb24oZCwgaSl7cmV0dXJuIGQubm9kZSgpLmdldEJCb3goKX0pXG4gICAgdmFyIHlDb21wb25lbnRzQm94ID0geENvbXBvbmVudHNTZWwubWFwKGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkLm5vZGUoKS5nZXRCQm94KCl9KVxuXG5cbiAgICB2YXIgY2hhcnRXaWR0aCA9IGNoYXJ0Qm94LndpZHRoIC0gY2hhcnRCb3gueFxuICAgIHZhciBjaGFydEhlaWdodCA9IGNoYXJ0Qm94LmhlaWdodCAtIGNoYXJ0Qm94LnlcblxuICAgIC8vIGVuYWJsZSB3aGVlbCBldmVudFxuICAgIGlmIChldmVudFR5cGUgPT0gXCJ3aGVlbFwiKSB7XG4gICAgICB2YXIgZSA9IGQzLmV2ZW50XG4gICAgICAvLyBwcmV2ZW50IHBhZ2Ugc2Nyb2xsaW5nXG4gICAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICAgIC8vIGV2ZW50IGRlbHRhIGlzIHZlcnkgdmVyeSBzbG93LCBzbyBzcGVlZCBpdCB1cCB3aXRoIHdoZWVsIHNwZWVkXG4gICAgICB2YXIgdyA9IGQzLmV2ZW50LmRlbHRhWSAqIHdoZWVsU3BlZWRcbiAgICAgIHZhciBzaGlmdFEgPSBkMy5ldmVudC5zaGlmdEtleVxuXG4gICAgICAvLyBkMyBoYXMgbm8gd2F5IHRvIG1ha2UgY3VzdG9tIHRyYW5zZm9ybSwgc28gbWFrZSBhbiBvYmplY3QgYW5kIGFkZFxuICAgICAgLy8gdGhlIG5lY2Vzc2FyeSBmdW5jdGlvbnMgdG8gbWFrZSB3aGVlbCBldmVudCBjb21wYXRpYmxlIHdpdGggZHJhZyBldmVudHNcbiAgICAgIGlmIChvcmllbnQgPT0gJzJEJykge1xuICAgICAgICB0cmFuc2Zvcm0gPSBzaGlmdFEgPyB7azogMSwgeDogdywgeTogMH0gOiB7azogMSwgeDogMCwgeTogd31cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyYW5zZm9ybSA9IGhvcml6b250YWxRID8ge2s6IDEsIHg6IHcsIHk6IDB9IDoge2s6IDEsIHg6IDAsIHk6IHd9XG4gICAgICB9XG4gICAgICAvLyAqIC0xIGlzIGludmVydFxuICAgICAgdHJhbnNmb3JtLmFwcGx5WCA9IGZ1bmN0aW9uKHgpIHsgcmV0dXJuIHggKiB0aGlzLmsgKyB0aGlzLnggKi0xOyB9XG4gICAgICB0cmFuc2Zvcm0uYXBwbHlZID0gIGZ1bmN0aW9uKHkpIHsgcmV0dXJuIHkgKiB0aGlzLmsgKyB0aGlzLnkgKi0xOyB9XG4gICAgfVxuXG5cblxuICAgIHZhciBjaGFydE9ialNlbCA9IGNoYXJ0U2VsLnNlbGVjdCgnLicraHlwZW5hdGUoY2hhcnQubmFtZXNwYWNlKCksJ29iamVjdC1jb250YWluZXInKSlcbiAgICB2YXIgeENvbXBvbmVudE9ialNlbCA9IHhDb21wb25lbnRzU2VsLm1hcChmdW5jdGlvbihkLCBpKXtcbiAgICAgIHJldHVybiBkLnNlbGVjdCgnLicraHlwZW5hdGUoeENvbXBvbmVudHNbaV0ubmFtZXNwYWNlKCksJ29iamVjdC1jb250YWluZXInKSlcbiAgICB9KVxuICAgIHZhciB5Q29tcG9uZW50T2JqU2VsID0geUNvbXBvbmVudHNTZWwubWFwKGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgcmV0dXJuIGQuc2VsZWN0KCcuJytoeXBlbmF0ZSh5Q29tcG9uZW50c1tpXS5uYW1lc3BhY2UoKSwnb2JqZWN0LWNvbnRhaW5lcicpKVxuICAgIH0pXG5cbiAgICB2YXIgY2hhcnRPYmpUcmFucyA9IGdldFRyYW5zbGF0aW9uKGNoYXJ0T2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScpKVxuICAgIHZhciB4Q29tcG9uZW50c09ialRyYW5zID0geENvbXBvbmVudE9ialNlbC5tYXAoZnVuY3Rpb24oZCwgaSl7XG4gICAgICByZXR1cm4gZ2V0VHJhbnNsYXRpb24oZC5hdHRyKCd0cmFuc2Zvcm0nKSlcbiAgICB9KVxuICAgIHZhciB5Q29tcG9uZW50c09ialRyYW5zID0geUNvbXBvbmVudE9ialNlbC5tYXAoZnVuY3Rpb24oZCwgaSl7XG4gICAgICByZXR1cm4gZ2V0VHJhbnNsYXRpb24oZC5hdHRyKCd0cmFuc2Zvcm0nKSlcbiAgICB9KVxuXG4gICAgdmFyIHggPSBob3Jpem9udGFsUSA/IHRyYW5zZm9ybS5hcHBseVgoY2hhcnRPYmpUcmFuc1swXSkgOiAwXG4gICAgaWYgKGhvcml6b250YWxRKSB7eCA9IHggPCAteExvY2sgPyAodHJhbnNmb3JtLnggPSAwLCAteExvY2spIDogKHRyYW5zZm9ybS54ID0gMCwgTWF0aC5taW4oeCwgMCkpIH1cblxuICAgIHZhciB5ID0gdmVydGljYWxRID8gdHJhbnNmb3JtLmFwcGx5WShjaGFydE9ialRyYW5zWzFdKSA6IDBcbiAgICBpZiAodmVydGljYWxRKSB7eSA9IHkgPCAteUxvY2sgPyAodHJhbnNmb3JtLnkgPSAwLCAteUxvY2spOiAodHJhbnNmb3JtLnkgPSAwLCBNYXRoLm1pbih5LCAwKSl9XG5cbiAgICBjaGFydE9ialNlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcreCsnLCcreSsnKScpXG4gICAgaWYgKGhvcml6b250YWxRKSB7XG4gICAgICAvLyB4QXhpc09ialNlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcreCsnLCcrMCsnKScpXG4gICAgICB4Q29tcG9uZW50T2JqU2VsLm1hcChmdW5jdGlvbihkLCBpKXsgZC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcreCsnLCcrMCsnKScpICB9KVxuICAgIH1cbiAgICBpZiAodmVydGljYWxRKSB7XG4gICAgICAvLyB5QXhpc09ialNlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcrMCsnLCcreSsnKScpXG4gICAgICB5Q29tcG9uZW50T2JqU2VsLm1hcChmdW5jdGlvbihkLCBpKXsgZC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcrMCsnLCcreSsnKScpICB9KVxuXG4gICAgfVxuXG5cbiAgfVxuXG4gIHpvb20ucmVzZXQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgaG9yaXpvbnRhbFEsIHZlcnRpY2FsUVxuICAgIGlmIChvcmllbnQgPT0gJzJEJykge2hvcml6b250YWxRID0gdHJ1ZTsgdmVydGljYWxRID0gdHJ1ZTt9XG4gICAgaWYgKG9yaWVudCA9PSAnaG9yaXpvbnRhbCcpIHtob3Jpem9udGFsUSA9IHRydWU7IHZlcnRpY2FsUSA9IGZhbHNlO31cbiAgICBpZiAob3JpZW50ID09ICd2ZXJ0aWNhbCcpIHt2ZXJ0aWNhbFEgPSB0cnVlOyBob3Jpem9udGFsUSA9IGZhbHNlO31cblxuICAgIHZhciBjaGFydE9ialNlbCA9IGNoYXJ0U2VsLnNlbGVjdCgnLicraHlwZW5hdGUoY2hhcnQubmFtZXNwYWNlKCksJ29iamVjdC1jb250YWluZXInKSlcbiAgICB2YXIgeEF4aXNPYmpTZWwgPSB4QXhpc1NlbC5zZWxlY3QoJy4nK2h5cGVuYXRlKHhBeGlzLm5hbWVzcGFjZSgpLCdvYmplY3QtY29udGFpbmVyJykpXG4gICAgdmFyIHlBeGlzT2JqU2VsID0geUF4aXNTZWwuc2VsZWN0KCcuJytoeXBlbmF0ZSh5QXhpcy5uYW1lc3BhY2UoKSwnb2JqZWN0LWNvbnRhaW5lcicpKVxuICAgIGNoYXJ0T2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyswKycsJyswKycpJylcbiAgICB4QXhpc09ialNlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcrMCsnLCcrMCsnKScpXG4gICAgeUF4aXNPYmpTZWwuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnKzArJywnKzArJyknKVxuICB9XG5cbiAgcmV0dXJuIHpvb21cbn1cbiIsImltcG9ydCB7aHlwZW5hdGUsIHNhZmVTZWxlY3QsIG1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2UsIGV4dHJhY3RWaW9saW5WYWx1ZXMsIHF1YXJ0aWxlc30gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7c2V0dXBDb250YWluZXIsIGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3QsIGNhbGN1bGF0ZVdpZHRoT2ZTcGFjZXJ9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHt1bmlxdWUsIGhhc1EsIGZsYXR0ZW4sIHdoaWNoQmlufSBmcm9tICcuL2FycmF5LWZ1bmN0aW9ucyc7XG5pbXBvcnQge2dyb3VwaW5nU3BhY2VyfSBmcm9tICcuL2dyb3VwaW5nLXNwYWNlcic7XG5pbXBvcnQge2NvbG9yRnVuY3Rpb24gYXMgQ0Z9IGZyb20gJy4vY29sb3ItZnVuY3Rpb24nO1xuaW1wb3J0IHt0b29sdGlwIGFzIFRUaXB9IGZyb20gJy4vdG9vbHRpcCc7XG5cbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVklPTElOICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbi8qKlxuICogQ3JlYXRlcyBhIHZpb2xpblxuICpcbiAqIHtAbGluayBodHRwczovL3N1bW5ldXJvbi5naXRsYWIuaW8vZDNzbS9kZW1vcy9iYXNpYy12aW9saW5zL2luZGV4Lmh0bWwgRGVtb31cbiAqIEBjb25zdHJ1Y3RvciB2aW9saW5cbiAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBzZWxlY3Rpb25cbiAqIEBuYW1lc3BhY2UgdmlvbGluXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IHZpb2xpblxuICovXG5leHBvcnQgZnVuY3Rpb24gdmlvbGluKCBzZWxlY3Rpb24gKSB7XG4gIHZhclxuICAvKipcbiAgKiBEYXRhIHRvIHBsb3QuIEFzc3VtZWQgdG8gYmUgYSBvYmplY3QsIHdoZXJlIGVhY2gga2V5IGNvcnJlc3BvbmRzIHRvIGEgdmlvbGluXG4gICogKHNlZSB7QGxpbmsgdmlvbGluI2RhdGF9KVxuICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZGF0YSxcbiAgLyoqXG4gICogV2hpY2ggZGlyZWN0aW9uIHRvIHJlbmRlciB0aGUgYmFycyBpblxuICAqIChzZWUge0BsaW5rIHZpb2xpbiNvcmllbnR9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbb3JpZW50PSdob3Jpem9udGFsJ11cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvcmllbnQ9J2hvcml6b250YWwnLFxuICAvKipcbiAgKiBBbW91bnQgb2YgaG9yaXpvbnRhbCBzcGFjZSAoaW4gcGl4ZWxzKSBhdmFpYmxlIHRvIHJlbmRlciB0aGUgdmlvbGluIGluXG4gICogKHNlZSB7QGxpbmsgdmlvbGluI3NwYWNlWH0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZVg9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNwYWNlWCxcbiAgLyoqXG4gICogQW1vdW50IG9mIHZlcnRpY2FsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSB2aW9saW4gaW5cbiAgKiAoc2VlIHtAbGluayB2aW9saW4uc3BhY2VZfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlWT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VZLFxuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0byBhbGxvdyB2aW9saW4gdG8gcmVuZGVyIGVsZW1lbnRzIHBhc3MgdGhlIG1haW4gc3BhdGlhbCBkaW1lbnNpb25cbiAgKiBnaXZlbiB0aGUgb3JpZW50YXRpb24gKHNlZSB7QGxpbmsgdmlvbGluI29yaWVudH0pLCB3aGVyZSB7QGxpbmsgdmlvbGluI29yaWVudH09XCJob3Jpem9udGFsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIHZpb2xpbiNzcGFjZVh9IGFuZCB3aGVyZSB7QGxpbmsgdmlvbGluI29yaWVudH09XCJ2ZXJ0aWNhbFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayB2aW9saW4jc3BhY2VZfVxuICAqIEBwYXJhbSB7Ym9vbGVhbn0gW292ZXJmbG93UT1mYWxzZV1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvdmVyZmxvd1EgPSB0cnVlLFxuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0byBkaXNwbGF5IHBvaW50cyBpbnNpZGUgdGhlIHBvaW50c1xuICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3BvaW50c1E9ZmFsc2VdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgcG9pbnRzUSA9IHRydWUsXG4gIC8qKlxuICAqIEFuIGFycmF5IC0gcHV0YXRpdmVseSBvZiBvdGhlciBhcnJheXMgLSBkZXBpY3RpbmcgaG93IGJhcnMgc2hvdWxkIGJlIGFycmFuZ2VkXG4gICogQHBhcmFtIHtBcnJheVtdfSBbZ3JvdXBpbmc9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIGdyb3VwaW5nLFxuICAvKipcbiAgKiBIb3cgdG8gZ2V0IHRoZSB2YWx1ZSBvZiB0aGUgdmlvbGluXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3ZhbHVlRXh0cmFjdG9yPWZ1bmN0aW9uKGtleSwgaW5kZXgpIHsgcmV0dXJuIGRhdGFba2V5XSB9XVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHZhbHVlRXh0cmFjdG9yID0gZnVuY3Rpb24oa2V5LCBpbmRleCkge3JldHVybiBkYXRhW2tleV0gfSxcbiAgLyoqXG4gICogSG93IHRvIHNvcnQgdGhlIGJhcnMgLSBpZiB7QGxpbmsgdmlvbGluI2dyb3VwaW5nfSBpcyBub3QgcHJvdmlkZWQuXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3NvcnRpbmdGdW5jdGlvbj1mdW5jdGlvbihrZXlBLCBrZXlCKSB7cmV0dXJuIGQzLmRlc2NlbmRpbmcoZGF0YVtrZXlBXSwgZGF0YVtrZXlCXSl9XVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKGtleUEsIGtleUIpIHtyZXR1cm4gZDMuZGVzY2VuZGluZyhkYXRhW2tleUFdLCBkYXRhW2tleUJdKX0sXG5cbiAgLyoqXG4gICogVGhlIHNjYWxlIGZvciB3aGljaCB2aW9saW4gdmFsdWVzIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBieVxuICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtzY2FsZT1kMy5zY2FsZUxpbmVhcl1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKCksXG4gIC8qKlxuICAqIFRoZSBwYWRkaW5nIGZvciB0aGUgZG9tYWluIG9mIHRoZSBzY2FsZSAoc2VlIHtAbGluayB2aW9saW4jc2NhbGV9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbZG9tYWluUGFkZGluZz0wLjVdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZG9tYWluUGFkZGluZyA9IDAuNSxcbiAgLyoqXG4gICogRGVmYXVsdCBzcGFjZSBmb3IgdGhlIHNwYWNlciAocGVyY2VudGFnZSkgb2YgbWFpbiBkaW1lbnNpb24gZ2l2ZW4gdGhlIG9yaWVudGF0aW9uXG4gICogKHNlZSB7QGxpbmsgdmlvbGluI29yaWVudH0pLCB3aGVyZSB7QGxpbmsgdmlvbGluI29yaWVudH09XCJob3Jpem9udGFsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIHZpb2xpbiNzcGFjZVh9IGFuZCB3aGVyZSB7QGxpbmsgdmlvbGluI29yaWVudH09XCJ2ZXJ0aWNhbFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayB2aW9saW4jc3BhY2VZfSBiZXR3ZWVuIGJhcnNcbiAgKiBAcGFyYW0ge251bWJlcn0gW29iamVjdFNwYWNlcj0wLjA1XVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdFNwYWNlciA9IDAuMDUsXG4gIC8qKlxuICAqIFRoZSBtaW5pbXVtIHNpemUgdGhhdCBhbiBvYmplY3QgY2FuIGJlXG4gICogQHBhcmFtIHtudW1iZXJ9IFttaW5PYmplY3RTaXplPTUwXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIG1pbk9iamVjdFNpemUgPSA1MCxcbiAgLyoqXG4gICogVGhlIG1heGltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmVcbiAgKiBAcGFyYW0ge251bWJlcn0gW21heE9iamVjdFNpemU9MTAwXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIG1heE9iamVjdFNpemUgPSAxMDAsXG5cbiAgLyoqXG4gICogVGhlIHN0cm9rZSB3aWR0aCBvZiB0aGUgYmFyc1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbYmFyU3Ryb2tlV2lkdGg9Ml1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvYmplY3RTdHJva2VXaWR0aCA9IDIsXG4gIC8qKlxuICAqIEluc3RhbmNlIG9mIENvbG9yRnVuY3Rpb25cbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24oKV1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjb2xvckZ1bmN0aW9uID0gQ0YoKSxcbiAgLyoqXG4gICogSW5zdGFuY2Ugb2YgQ29sb3JGdW5jdGlvbiBtb2RpZmllZCBieSBhIHNjYWxlIGZvciB0aGUgcG9pbnRzXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3BvaW50Q29sb3JGdW5jID0gY29sb3JGdW5jdGlvbigpXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHBvaW50Q29sb3JGdW5jID0gZnVuY3Rpb24gKGQsIHR5cGUsIGJhc2UsIG1pbiwgbWF4KSB7XG4gICAgdmFyIG1pbk1heEhleFNjYWxlID0gZDMuc2NhbGVMaW5lYXIoKS5kb21haW4oW21pbiwgbWF4XSkucmFuZ2UoWy0wLjI1LCAwLjA1XSlcbiAgICB2YXIgc2NhbGVkQ29sb3IgPSBtb2RpZnlIZXhpZGVjaW1hbENvbG9yTHVtaW5hbmNlKGJhc2UucmVwbGFjZSgnIycsICcnKSwgbWluTWF4SGV4U2NhbGUoZCkpXG4gICAgdmFyIG1vZCA9IHR5cGUgPT0gXCJzdHJva2VcIiA/IDAgOiAwLjI1XG4gICAgcmV0dXJuIG1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2Uoc2NhbGVkQ29sb3IucmVwbGFjZSgnIycsICcnKSwgbW9kKVxuICB9LFxuXG4gIC8qKlxuICAqIFRoZSByYWRpdXMgb2YgYSBwb2ludFxuICAqIEBwYXJhbSB7bnVtYmVyfSBbcG9pbnRSYWRpdXM9M11cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBwb2ludFJhZGl1cyA9IDMsXG4gIC8qKlxuICAqIFRoZSBzdHJva2Ugd2lkdGggb2YgdGhlIG9pbnRzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtwb2ludFN0cm9rZVdpZHRoPTJdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgcG9pbnRTdHJva2VXaWR0aCA9IDIsXG5cbiAgLyoqXG4gICogQ29sb3Igb2YgdGhlIGJhY2tncm91bmRcbiAgKiBAcGFyYW0ge3N0cmluZ30gW2JhY2tncm91bmRGaWxsPVwidHJhbnNwYXJlbnRcIl1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCcsXG4gIC8qKlxuICAqIE5hbWVzcGFjZSBmb3IgYWxsIGl0ZW1zIG1hZGUgYnkgdGhpcyBpbnN0YW5jZSBvZiB2aW9saW5cbiAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWVzcGFjZT1cImQzc20tdmlvbGluXCJdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbmFtZXNwYWNlID0gJ2Qzc20tdmlvbGluJyxcbiAgLyoqXG4gICogQ2xhc3MgbmFtZSBmb3IgdmlvbGluIGNvbnRhaW5lciAoPGc+IGVsZW1lbnQpXG4gICogQHBhcmFtIHtzdHJpbmd9IFtvYmplY3RDbGFzcz1cInZpb2xpblwiXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdENsYXNzID0gJ3Zpb2xpbicsXG4gIC8qKlxuICAqIER1cmF0aW9uIG9mIGFsbCB0cmFuc2l0aW9ucyBvZiB0aGlzIGVsZW1lbnRcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RyYW5zaXRpb25EdXJhdGlvbj0xMDAwXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRyYW5zaXRpb25EdXJhdGlvbiA9IDEwMDAsXG4gIC8qKlxuICAqIEVhc2luZyBmdW5jdGlvbiBmb3IgdHJhbnNpdGlvbnNcbiAgKiBAcGFyYW0ge2QzLmVhc2V9IFtlYXNlRnVuYz1kMy5lYXNlRXhwXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIGVhc2VGdW5jID0gZDMuZWFzZUV4cCxcblxuICAvKipcbiAgKiBUaGUga2V5IGNvbnRhaW5pbmcgdGhlIHF1YXJ0aWxlc1xuICAqIEBwYXJhbSB7c3RyaW5nfSBbcXVhcnRpbGVzS2V5PXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBxdWFydGlsZXNLZXkgPSBcInF1YXJ0aWxlc1wiLFxuICAvKipcbiAgKiBUaGUga2V5cyBjb3JyZXNwb25kaW5nIHRvIGVhY2ggcXVhcnRpbGVcbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbcXVhcnRpbGVLZXlzPVtcIlEwXCIsIFwiUTFcIiwgXCJRMlwiLCBcIlEzXCIsIFwiUTRcIl1dXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgcXVhcnRpbGVLZXlzID0gW1wiUTBcIiwgXCJRMVwiLCBcIlEyXCIsIFwiUTNcIiwgXCJRNFwiXSxcblxuICAvKipcbiAgKiBUaGUga2V5cyBvZiB0aGUgYmFyc1xuICAqIEBwYXJhbSB7c3RyaW5nW119IFt2aW9saW5LZXlzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2aW9saW5LZXlzLFxuICAvKipcbiAgKiBUaGUgdmFsdWVzIG9mIHRoZSBiYXJzXG4gICogQHBhcmFtIHtudW1iZXJbXX0gW3Zpb2xpblZhbHVlcz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmlvbGluVmFsdWVzLFxuICAvKipcbiAgKiBUaGUgb2JqZWN0U2l6ZSAoYWN0dWFsIHdpZHRoKSB1c2VkIGJ5IHRoZSBiYXJzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtvYmplY3RTaXplPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvYmplY3RTaXplLFxuICAvKipcbiAgKiBUaGUgc3BhY2VyU2l6ZSAoYWN0dWFsIHdpZHRoKSB1c2VkIGJ5IHRoZSBzcGFjZXJzIGJldHdlZW4gdGhlIGJhcnNcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlclNpemU9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNwYWNlclNpemUsXG5cbiAgLyoqXG4gICogSW5zdGFuY2Ugb2YgVG9vbHRpcFxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFt0b29sdGlwPXRvb2x0aXAoKV1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0b29sdGlwID0gVFRpcCgpLmtleXMoW3F1YXJ0aWxlS2V5c1s0XSwgcXVhcnRpbGVLZXlzWzNdLCBxdWFydGlsZUtleXNbMl0sIHF1YXJ0aWxlS2V5c1sxXSwgcXVhcnRpbGVLZXlzWzBdXSksXG4gIHBvaW50c1Rvb2x0aXAgPSBUVGlwKCksXG4gIC8vIHBvaW50S2V5RXh0cmFjdG9yID0gZnVuY3Rpb24odmlvbGluS2V5LCB2aW9saW5EYXRhLCB2aW9saW5WYWx1ZXMpIHtyZXR1cm4gZDMua2V5cyh2aW9saW5WYWx1ZXNbdmlvbGluS2V5XS52YWx1ZXMpfSxcbiAgLy8gcG9pbnRWYWx1ZUV4dHJhY3RvciA9IGZ1bmN0aW9uKHBvaW50S2V5LCB2aW9saW5LZXksIHZpb2xpbkRhdGEsIHZpb2xpblZhbHVlcykge3JldHVybiB2aW9saW5WYWx1ZXNbdmlvbGluS2V5XS52YWx1ZXNbcG9pbnRLZXldfSxcblxuXG4gIC8qKlxuICAqIEZ1bmN0aW9uIHdoaWNoIGdpdmVuIHRoZSBrZXkgb2YgdGhlIHZpb2xpbiBhbmQgdGhhdCBrZXkncyBhc3NvY2lhdGVkIHZhbHVlXG4gICogcmV0dXJucyB0aGUgb2JqZWN0IGNvbnNpdGluZyBvZiB0aGUgcG9pbnRzIG9mIHRoZSB2aW9saW5cbiAgKiAoc2VlIHtAbGluayB2aW9saW4jdmlvbGluUG9pbnRzRXh0cmFjdG9yfSlcbiAgKiBAcGFyYW0ge09iamVjdH0gW3Zpb2xpblBvaW50c0V4dHJhY3Rvcj1mdW5jdGlvbih2aW9saW5LZXksIHZpb2xpbkRhdGEpIHsgcmV0dXJuIHZpb2xpbkRhdGEucG9pbnRzIH1dXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmlvbGluUG9pbnRzRXh0cmFjdG9yID0gZnVuY3Rpb24gKHZpb2xpbktleSwgdmlvbGluRGF0YSkge3JldHVybiB2aW9saW5EYXRhLnBvaW50cyB9LFxuICAvKipcbiAgKiBGdW5jdGlvbiB3aGljaCBnaXZlbiB0aGUga2V5IG9mIHRoZSBjdXJyZW50IHBvaW50IGFuZCB0aGUgb2JqZWN0IG9mIHBvaW50cyBmb3IgdGhlXG4gICogdmlvbGluLCByZXR1cm5zIHRoZSBudW1lcmljYWwgdmFsdWUgb2YgdGhlIHBvaW50XG4gICogKHNlZSB7QGxpbmsgdmlvbGluI3Zpb2xpblBvaW50VmFsdWVFeHRyYWN0b3J9KVxuICAqIEBwYXJhbSB7T2JqZWN0fSBbdmlvbGluUG9pbnRWYWx1ZUV4dHJhY3Rvcj1mdW5jdGlvbih2aW9saW5Qb2ludEtleSwgdmlvbGluUG9pbnREYXRhKSB7IHJldHVybiB2aW9saW5Qb2ludERhdGFbdmlvbGluUG9pbnRLZXldLnZhbHVlIH1dXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmlvbGluUG9pbnRWYWx1ZUV4dHJhY3RvciA9IGZ1bmN0aW9uKHZpb2xpblBvaW50S2V5LCB2aW9saW5Qb2ludERhdGEpIHsgcmV0dXJuIHZpb2xpblBvaW50RGF0YVt2aW9saW5Qb2ludEtleV0udmFsdWUgfVxuXG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgdmlvbGluUG9pbnRzRXh0cmFjdG9yXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB2aW9saW5Qb2ludHNFeHRyYWN0b3IgPSBmdW5jdGlvbih2aW9saW5LZXksIHZpb2xpbkRhdGEpIHsgcmV0dXJuIHZpb2xpbkRhdGEucG9pbnRzIH1cbiAgICovXG4gIHZpb2xpbi52aW9saW5Qb2ludHNFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZpb2xpblBvaW50c0V4dHJhY3RvciA9IF8sIHZpb2xpbikgOiB2aW9saW5Qb2ludHNFeHRyYWN0b3I7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3JcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZpb2xpblBvaW50c0V4dHJhY3RvciA9IGZ1bmN0aW9uKHBvaW50S2V5LCB2aW9saW5LZXksIHZpb2xpbkRhdGEsIHZpb2xpblZhbHVlcykge3JldHVybiB2aW9saW5WYWx1ZXNbdmlvbGluS2V5XS52YWx1ZXNbcG9pbnRLZXldfVxuICAgKi9cbiAgdmlvbGluLnZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3IgPSBfLCB2aW9saW4pIDogdmlvbGluUG9pbnRWYWx1ZUV4dHJhY3RvcjsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHNlbGVjdGlvbiBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBkMy5zZWxlY3Rpb259XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc2VsZWN0aW9uID0gc2VsZWN0aW9uXG4gICAqL1xuICB2aW9saW4uc2VsZWN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZWxlY3Rpb24gPSBfLCB2aW9saW4pIDogc2VsZWN0aW9uOyB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBkYXRhXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNkYXRhfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBvYmplY3R9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqL1xuICB2aW9saW4uZGF0YSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGF0YSA9IF8sIHZpb2xpbikgOiBkYXRhOyB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBvcmllbnQgb2YgdGhlIGJveGVzXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNvcmllbnR9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG9iamVjdH1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIHZpb2xpbi5vcmllbnQgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9yaWVudCA9IF8sIHZpb2xpbikgOiBvcmllbnQ7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jc3BhY2VYfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVggPSB1bmRlZmluZWRcbiAgICovXG4gIHZpb2xpbi5zcGFjZVggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWCA9IF8sIHZpb2xpbikgOiBzcGFjZVg7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiB2ZXJ0aWNhbCBzcGFjZSBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3NwYWNlWX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBudW1iZXIgPiAwXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc3BhY2VZID0gdW5kZWZpbmVkXG4gICAqL1xuICB2aW9saW4uc3BhY2VZID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVkgPSBfLCB2aW9saW4pIDogc3BhY2VZOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IHZpb2xpbiBpcyBhbGxvd2VkIHRvIGdvIGJleW9uZCBzcGVjaWZpZWQgZGltZW5zaW9uc1xuICAgKiAoc2VlIHtAbGluayB2aW9saW4jb3ZlcmZsb3dRfSlcbiAgICogQHBhcmFtIHtib29sZWFufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7dmlvbGluIHwgYm9vbGVhbn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvdmVyZmxvd1EgPSBmYWxzZVxuICAgKi9cbiAgdmlvbGluLm92ZXJmbG93USA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3ZlcmZsb3dRID0gXywgdmlvbGluKSA6IG92ZXJmbG93UTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IHRvIHBsb3QgcG9pbnRzIHdpdGggdGhlIHZpb2xpbnNcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3BvaW50c1F9KVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBib29sZWFufVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHBvaW50c1EgPSBmYWxzZVxuICAgKi9cbiAgdmlvbGluLnBvaW50c1EgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBvaW50c1EgPSBfLCB2aW9saW4pIDogcG9pbnRzUTsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgZ3JvdXBpbmcgb2YgdGhlIGJveGVzXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNncm91cGluZ30pXG4gICAqIEBwYXJhbSB7QXJyYXlbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IEFycmF5W119XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZ3JvdXBpbmcgPSB1bmRlZmluZWRcbiAgICovXG4gIHZpb2xpbi5ncm91cGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZ3JvdXBpbmcgPSBfLCB2aW9saW4pIDogZ3JvdXBpbmc7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdmFsdWVFeHRyYWN0b3JcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3ZhbHVlRXh0cmFjdG9yfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgdmlvbGluLnZhbHVlRXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZUV4dHJhY3RvciA9IF8sIHZpb2xpbikgOiB2YWx1ZUV4dHJhY3RvcjsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzb3J0aW5nRnVuY3Rpb25cbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3NvcnRpbmdGdW5jdGlvbn0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIHZpb2xpbi5zb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNvcnRpbmdGdW5jdGlvbiA9IF8sIHZpb2xpbikgOiBzb3J0aW5nRnVuY3Rpb247IH07XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzY2FsZSBmb3Igd2hpY2ggdGhlIHZpb2xpbiB2YWx1ZXMgc2hvdWxkIGJlIHRyYW5zZm9ybWVkIGJ5XG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNzY2FsZX0pXG4gICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBkMy5zY2FsZX1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKClcbiAgICovXG4gIHZpb2xpbi5zY2FsZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGUgPSBfLCB2aW9saW4pIDogc2NhbGU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcGFkZGluZyBmb3IgdGhlIGRvbWFpbiBvZiB0aGUgc2NhbGVcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI2RvbWFpblBhZGRpbmd9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBkb21haW5QYWRkaW5nID0gMC41XG4gICAqL1xuICB2aW9saW4uZG9tYWluUGFkZGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluUGFkZGluZyA9IF8sIHZpb2xpbikgOiBkb21haW5QYWRkaW5nOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIG9iamVjdFNwYWNlclxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jb2JqZWN0U3BhY2VyfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0U3BhY2VyID0gMC4wNVxuICAgKi9cbiAgdmlvbGluLm9iamVjdFNwYWNlciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0U3BhY2VyID0gXywgdmlvbGluKSA6IG9iamVjdFNwYWNlcjsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBtaW5PYmplY3RTaXplXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNtaW5PYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbWluT2JqZWN0U2l6ZSA9IDE1XG4gICAqL1xuICB2aW9saW4ubWluT2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobWluT2JqZWN0U2l6ZSA9IF8sIHZpb2xpbikgOiBtaW5PYmplY3RTaXplOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1heE9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI21heE9iamVjdFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBtYXhPYmplY3RTaXplID0gNTBcbiAgICovXG4gIHZpb2xpbi5tYXhPYmplY3RTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChtYXhPYmplY3RTaXplID0gXywgdmlvbGluKSA6IG1heE9iamVjdFNpemU7IH07XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RTdHJva2VXaWR0aFxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jb2JqZWN0U3Ryb2tlV2lkdGh9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RTdHJva2VXaWR0aCA9IDJcbiAgICovXG4gIHZpb2xpbi5vYmplY3RTdHJva2VXaWR0aCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0U3Ryb2tlV2lkdGggPSBfLCB2aW9saW4pIDogb2JqZWN0U3Ryb2tlV2lkdGg7IH07XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGNvbG9yRnVuY3Rpb25cbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI2NvbG9yRnVuY3Rpb259KVxuICAgKiBAcGFyYW0ge2NvbG9yRnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBjb2xvckZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGNvbG9yRnVuY3Rpb24gPSBjb2xvckZ1bmN0aW9uKClcbiAgICovXG4gIHZpb2xpbi5jb2xvckZ1bmN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjb2xvckZ1bmN0aW9uID0gXywgdmlvbGluKSA6IGNvbG9yRnVuY3Rpb247IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgY29sb3JGdW5jdGlvblxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jY29sb3JGdW5jdGlvbn0pXG4gICAqIEBwYXJhbSB7Y29sb3JGdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IGNvbG9yRnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24oKVxuICAgKi9cbiAgdmlvbGluLnBvaW50Q29sb3JGdW5jID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwb2ludENvbG9yRnVuYyA9IF8sIHZpb2xpbikgOiBwb2ludENvbG9yRnVuYzsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcG9pbnRSYWRpdXNcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3BvaW50UmFkaXVzfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgcG9pbnRSYWRpdXMgPSAyXG4gICAqL1xuICB2aW9saW4ucG9pbnRSYWRpdXMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBvaW50UmFkaXVzID0gXywgdmlvbGluKSA6IHBvaW50UmFkaXVzOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHBvaW50U3Ryb2tlV2lkdGhcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3BvaW50U3Ryb2tlV2lkdGh9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBwb2ludFN0cm9rZVdpZHRoID0gMlxuICAgKi9cbiAgdmlvbGluLnBvaW50U3Ryb2tlV2lkdGggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBvaW50U3Ryb2tlV2lkdGggPSBfLCB2aW9saW4pIDogcG9pbnRTdHJva2VXaWR0aDsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYmFja2dyb3VuZEZpbGxcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI2JhY2tncm91bmRGaWxsfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYmFja2dyb3VuZEZpbGwgPSAndHJhbnNwYXJlbnQnXG4gICAqL1xuICB2aW9saW4uYmFja2dyb3VuZEZpbGwgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJhY2tncm91bmRGaWxsID0gXywgdmlvbGluKSA6IGJhY2tncm91bmRGaWxsOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG5hbWVzcGFjZVxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jbmFtZXNwYWNlfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbmFtZXNwYWNlID0gJ2Qzc20tdmlvbGluJ1xuICAgKi9cbiAgdmlvbGluLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgdmlvbGluKSA6IG5hbWVzcGFjZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RDbGFzc1xuICAgKiAoc2VlIHtAbGluayB2aW9saW4jb2JqZWN0Q2xhc3N9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RDbGFzcyA9ICd0aWNrLWdyb3VwJ1xuICAgKi9cbiAgdmlvbGluLm9iamVjdENsYXNzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvYmplY3RDbGFzcyA9IF8sIHZpb2xpbikgOiBvYmplY3RDbGFzczsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdHJhbnNpdGlvbkR1cmF0aW9uXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiN0cmFuc2l0aW9uRHVyYXRpb259KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwXG4gICAqL1xuICB2aW9saW4udHJhbnNpdGlvbkR1cmF0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0cmFuc2l0aW9uRHVyYXRpb24gPSBfLCB2aW9saW4pIDogdHJhbnNpdGlvbkR1cmF0aW9uOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGVhc2VGdW5jXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNlYXNlRnVuY30pXG4gICAqIEBwYXJhbSB7ZDMuZWFzZX0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IGQzLmVhc2V9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwXG4gICAqL1xuICB2aW9saW4uZWFzZUZ1bmMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGVhc2VGdW5jID0gXywgdmlvbGluKSA6IGVhc2VGdW5jOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBxdWFydGlsZUtleVxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jcXVhcnRpbGVLZXl9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBxdWFydGlsZUtleSA9IFwicXVhcnRpbGVzXCJcbiAgICovXG4gIHZpb2xpbi5xdWFydGlsZUtleSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocXVhcnRpbGVLZXkgPSBfLCB2aW9saW4pIDogcXVhcnRpbGVLZXk7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcXVhcnRpbGVLZXlzXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNxdWFydGlsZUtleXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7dmlvbGluIHwgc3RyaW5nW119XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgcXVhcnRpbGVLZXlzID0gW1wiUTBcIixcIlExXCIsXCJRMlwiLFwiUTNcIixcIlE0XCJdXG4gICAqL1xuICB2aW9saW4ucXVhcnRpbGVLZXlzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChxdWFydGlsZUtleXMgPSBfLCB2aW9saW4pIDogcXVhcnRpbGVLZXlzOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB2aW9saW5LZXlzXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiN2aW9saW5LZXlzfSlcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZpb2xpbktleXMgPSB1bmRlZmluZWRcbiAgICovXG4gIHZpb2xpbi52aW9saW5LZXlzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2aW9saW5LZXlzID0gXywgdmlvbGluKSA6IHZpb2xpbktleXM7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdmlvbGluVmFsdWVzXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiN2aW9saW5WYWx1ZXN9KVxuICAgKiBAcGFyYW0ge09iamVjdFtdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7dmlvbGluIHwgT2JqZWN0W119XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdmlvbGluVmFsdWVzID0gdW5kZWZpbmVkXG4gICAqL1xuICB2aW9saW4udmlvbGluVmFsdWVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2aW9saW5WYWx1ZXMgPSBfLCB2aW9saW4pIDogdmlvbGluVmFsdWVzOyB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgb2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jb2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7dmlvbGluIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG9iamVjdFNpemUgPSB1bmRlZmluZWRcbiAgICovXG4gIHZpb2xpbi5vYmplY3RTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvYmplY3RTaXplID0gXywgdmlvbGluKSA6IG9iamVjdFNpemU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgc3BhY2VyU2l6ZVxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jc3BhY2VyU2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7dmlvbGluIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlclNpemUgPSB1bmRlZmluZWRcbiAgICovXG4gIHZpb2xpbi5zcGFjZXJTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZXJTaXplID0gXywgdmlvbGluKSA6IHNwYWNlclNpemU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdG9vbHRpcFxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jdG9vbHRpcH0pXG4gICAqIEBwYXJhbSB7dG9vbHRpcH0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IHRvb2x0aXB9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdG9vbHRpcCA9IHRvb2x0aXAoKVxuICAgKi9cbiAgdmlvbGluLnRvb2x0aXAgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRvb2x0aXAgPSBfLCB2aW9saW4pIDogdG9vbHRpcDsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBwb2ludHNUb29sdGlwXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNwb2ludHNUb29sdGlwfSlcbiAgICogQHBhcmFtIHt0b29sdGlwfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7dmlvbGluIHwgdG9vbHRpcH1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBwb2ludHNUb29sdGlwID0gdG9vbHRpcCgpXG4gICAqL1xuICB2aW9saW4ucG9pbnRzVG9vbHRpcCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocG9pbnRzVG9vbHRpcCA9IF8sIHZpb2xpbikgOiBwb2ludHNUb29sdGlwOyB9O1xuXG5cblxuXG5cbiAgZnVuY3Rpb24gdmlvbGluICgpIHtcbiAgICAvLyBmb3IgY29udmVuaWVuY2UgaW4gaGFuZGxpbmcgb3JpZW50YXRpb24gc3BlY2lmaWMgdmFsdWVzXG4gICAgdmFyIGhvcml6b250YWxRID0gKG9yaWVudCA9PSAnaG9yaXpvbnRhbCcpID8gdHJ1ZSA6IGZhbHNlXG4gICAgdmFyIHZlcnRpY2FsUSA9ICFob3Jpem9udGFsUVxuXG4gICAgLy8gYmFja2dyb3VuZCBjbGlwaW5nIHJlY3RhbmdsZVxuICAgIHZhciBiZ2NwUmVjdCA9IHt4OjAsIHk6MCwgd2lkdGg6IHNwYWNlWCwgaGVpZ2h0OnNwYWNlWX1cbiAgICB2YXIgY29udGFpbmVyID0gc2V0dXBDb250YWluZXIoIHNlbGVjdGlvbiwgbmFtZXNwYWNlLCBiZ2NwUmVjdCwgYmFja2dyb3VuZEZpbGwgKTtcblxuICAgIC8vIGlmIGdyb3VwaW5nIGlzIHVuZGVmaW5lZCBzb3J0IHZpb2xpbktleXMgYnkgc29ydGluZ0Z1bmN0aW9uXG4gICAgdmFyIG9yZGVyZWQgPSAoZ3JvdXBpbmcgPT0gdW5kZWZpbmVkKSA/IGQzLmtleXMoZGF0YSkuc29ydChzb3J0aW5nRnVuY3Rpb24pIDogZ3JvdXBpbmdcblxuICAgIC8vIGNvbnNvbGUubG9nKG9yZGVyZWQpXG5cbiAgICB2aW9saW5LZXlzID0gZmxhdHRlbihvcmRlcmVkKVxuXG5cbiAgICB2YXIgY2FsY1ZhbHVlcyA9IG5lZWRlZFZpb2xpblZhbHVlcygpXG4gICAgLmhvcml6b250YWxRKGhvcml6b250YWxRKVxuICAgIC5xdWFydGlsZUtleXMocXVhcnRpbGVLZXlzKVxuICAgIC52aW9saW5Qb2ludHNFeHRyYWN0b3IodmlvbGluUG9pbnRzRXh0cmFjdG9yKVxuICAgIC52aW9saW5Qb2ludFZhbHVlRXh0cmFjdG9yKHZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3IpXG5cblxuXG4gICAgLy8gYXVnbWVudCB2YWx1c1xuICAgIHZpb2xpbktleXMubWFwKGZ1bmN0aW9uKHZrLCBpKXsgY2FsY1ZhbHVlcyh2aywgZGF0YSkgfSlcblxuICAgIHZhciBudW1iZXJPZk9iamVjdHMgPSB2aW9saW5LZXlzLmxlbmd0aFxuXG4gICAgdmFyIG1pbiA9IFtdLmNvbmNhdCguLi52aW9saW5LZXlzLm1hcChmdW5jdGlvbihrLCBpKXtyZXR1cm4gZGF0YVtrXS5xdWFydGlsZXNbcXVhcnRpbGVLZXlzWzBdXX0pKVxuICAgIHZhciBtYXggPSBbXS5jb25jYXQoLi4udmlvbGluS2V5cy5tYXAoZnVuY3Rpb24oaywgaSl7cmV0dXJuIGRhdGFba10ucXVhcnRpbGVzW3F1YXJ0aWxlS2V5c1txdWFydGlsZUtleXMubGVuZ3RoIC0gMV1dfSkpXG4gICAgdmFyIGV4dGVudCA9IFtNYXRoLm1pbiguLi5taW4pIC0gZG9tYWluUGFkZGluZywgTWF0aC5tYXgoLi4ubWF4KSArIGRvbWFpblBhZGRpbmddXG4gICAgLy8gY29uc29sZS5sb2coZXh0ZW50LCB2aW9saW5WYWx1ZXMsIG9yZGVyZWQpXG5cbiAgICAvLyBzZXQgdGhlIHNjYWxlXG4gICAgc2NhbGUuZG9tYWluKGV4dGVudCkucmFuZ2UoaG9yaXpvbnRhbFEgPyBbMCxzcGFjZVldIDogWzAsIHNwYWNlWF0pXG4gICAgdmFyIHNwYWNlID0gaG9yaXpvbnRhbFEgPyBzcGFjZVggOiBzcGFjZVlcbiAgICAvLyBjYWxjdWxhdGUgb2JqZWN0IHNpemVcbiAgICBvYmplY3RTaXplID0gY2FsY3VsYXRlV2lkdGhPZk9iamVjdChzcGFjZSwgbnVtYmVyT2ZPYmplY3RzLCBtaW5PYmplY3RTaXplLCBtYXhPYmplY3RTaXplLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICAvLyBjYWxjdWxhdGUgc3BhY2VyIHNpemUgaWYgbmVlZGVkXG4gICAgc3BhY2VyU2l6ZSA9IGNhbGN1bGF0ZVdpZHRoT2ZTcGFjZXIob3JkZXJlZCwgc3BhY2UsIG9iamVjdFNpemUsIG51bWJlck9mT2JqZWN0cywgb2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgLy8gbWFrZSB0aGUgbmVzdGVkIGdyb3Vwc1xuICAgIHZhciBzcGFjZXJGdW5jdGlvbiA9IGdyb3VwaW5nU3BhY2VyKClcbiAgICAuaG9yaXpvbnRhbFEoaG9yaXpvbnRhbFEpLnNjYWxlKHNjYWxlKS5tb3ZlYnkoJ2NhdGVnb3J5JykubnVtYmVyT2ZPYmplY3RzKG51bWJlck9mT2JqZWN0cylcbiAgICAub2JqZWN0Q2xhc3Mob2JqZWN0Q2xhc3MpLm9iamVjdFNpemUob2JqZWN0U2l6ZSkuc3BhY2VyU2l6ZShzcGFjZXJTaXplKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlRnVuYyhlYXNlRnVuYylcbiAgICAubmFtZXNwYWNlKG5hbWVzcGFjZSlcblxuICAgIC8vIG1vdmUgc3R1ZmZcbiAgICBzcGFjZXJGdW5jdGlvbihjb250YWluZXIsIG9yZGVyZWQsIDApXG4gICAgLy8gY29uc29sZS5sb2codmlvbGluS2V5cywgb3JkZXJlZCwgY29udGFpbmVyLnNlbGVjdEFsbCgnZzpub3QoLnRvLXJlbW92ZSkuJytvYmplY3RDbGFzcykubm9kZXMoKSlcblxuICAgIC8vIGZvciBjb2xvciBmdW5jdGlvblxuICAgIHZhciBwYXJlbnRJbmRleEFycmF5ID0gW11cbiAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnOm5vdCgudG8tcmVtb3ZlKS4nK29iamVjdENsYXNzKVxuICAgIC5lYWNoKGZ1bmN0aW9uKGQsIGkpe2lmIChoYXNRKHZpb2xpbktleXMsIGQpKXsgcGFyZW50SW5kZXhBcnJheS5wdXNoKE51bWJlcihkMy5zZWxlY3QodGhpcykuYXR0cigncGFyZW50LWluZGV4JykpKX19KVxuXG4gICAgLy8gdXBkYXRlIGNvbG9yIGZ1bmN0aW9uXG4gICAgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24uY29sb3JCeSgpID09ICdpbmRleCdcbiAgICA/IGNvbG9yRnVuY3Rpb24uZGF0YUV4dGVudChbMCwgTWF0aC5tYXgoLi4ucGFyZW50SW5kZXhBcnJheSldKVxuICAgIDogY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50KGV4dGVudClcblxuICAgIC8qIHZpb2xpaW4gc3BlY2lmaWMgbmVlZHMgKi9cblxuXG4gICAgdmFyIGZyZXF1ZW5jeU1heCA9IE1hdGgubWF4KC4uLltdLmNvbmNhdCguLi52aW9saW5LZXlzLm1hcChmdW5jdGlvbihrLCBpKXtyZXR1cm4gZDMubWF4KGRhdGFba10uZnJlcXVlbmNpZXMpfSkpKVxuICAgIHZhciB2U2NhbGUgPSBkMy5zY2FsZUxpbmVhcigpLmRvbWFpbihbMCwgZnJlcXVlbmN5TWF4XSkucmFuZ2UoWzAsIG9iamVjdFNpemUgLyAyXSlcblxuICAgIHZhciBsQXJlYSA9IGQzLmxpbmUoKVxuICAgIC54KGZ1bmN0aW9uKGQsIGkpeyByZXR1cm4gaG9yaXpvbnRhbFEgPyAtdlNjYWxlKGQueCkgOiBzY2FsZShkLngpfSlcbiAgICAueShmdW5jdGlvbihkLCBpKXsgcmV0dXJuIGhvcml6b250YWxRID8gc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKGQueSkgOiAtdlNjYWxlKGQueSl9KVxuICAgIC5jdXJ2ZShkMy5jdXJ2ZUJhc2lzKVxuICAgIHZhciByQXJlYSA9IGQzLmxpbmUoKVxuICAgIC54KGZ1bmN0aW9uKGQsIGkpeyByZXR1cm4gaG9yaXpvbnRhbFEgPyB2U2NhbGUoZC54KSA6IHNjYWxlKGQueCl9KVxuICAgIC55KGZ1bmN0aW9uKGQsIGkpeyByZXR1cm4gaG9yaXpvbnRhbFEgPyBzY2FsZShleHRlbnRbMV0pIC0gc2NhbGUoZC55KSA6IHZTY2FsZShkLnkpfSlcbiAgICAuY3VydmUoZDMuY3VydmVCYXNpcylcblxuXG5cblxuXG5cbiAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnOm5vdCgudG8tcmVtb3ZlKS4nK29iamVjdENsYXNzKS5lYWNoKGZ1bmN0aW9uKGtleSwgaSl7XG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKSxcbiAgICAgIGN1cnJlbnREYXRhID0gZGF0YVtrZXldXG4gICAgICAvLyBuZWVkZWQgYmVjYXVzZSBidWcgaW4gc2VsZWN0aW5nIC50by1yZW1vdmVcbiAgICAgIGlmICghaGFzUSh2aW9saW5LZXlzLCBrZXkpKSB7cmV0dXJufVxuICAgICAgdmFyXG4gICAgICBpID0gdC5hdHRyKCdwYXJlbnQtaW5kZXgnKSA9PSB1bmRlZmluZWQgPyBpIDogdC5hdHRyKCdwYXJlbnQtaW5kZXgnKSxcbiAgICAgIGZpbGxDb2xvciA9IGNvbG9yRnVuY3Rpb24oa2V5LCBjdXJyZW50RGF0YSwgaSwgJ2ZpbGwnKSwgLy8gcHJldmVudCBkdXBsaWNhdGUgY29tcHV0YXRpb25cbiAgICAgIHN0cm9rZUNvbG9yID0gY29sb3JGdW5jdGlvbihrZXksIGN1cnJlbnREYXRhLCBpLCAnc3Ryb2tlJyksXG4gICAgICBhcmVhID0gc2FmZVNlbGVjdCh0LCAnZycsICdhcmVhJyksXG4gICAgICBsYSA9IHNhZmVTZWxlY3QoYXJlYSwgJ3BhdGgnLCAnbGVmdCcpLFxuICAgICAgcmEgPSBzYWZlU2VsZWN0KGFyZWEsICdwYXRoJywgJ3JpZ2h0JyksXG4gICAgICBxdWFydHMgPSBzYWZlU2VsZWN0KHQsICdnJywgJ3F1YXJ0cycpLFxuICAgICAgbHEzID0gc2FmZVNlbGVjdChxdWFydHMsICdsaW5lJywgJ3EzJyksXG4gICAgICBscTEgPSBzYWZlU2VsZWN0KHF1YXJ0cywgJ2xpbmUnLCAncTEnKSxcbiAgICAgIHEzID0gY3VycmVudERhdGEucXVhcnRpbGVzW3F1YXJ0aWxlS2V5c1szXV0sXG4gICAgICBxMiA9IGN1cnJlbnREYXRhLnF1YXJ0aWxlc1txdWFydGlsZUtleXNbMl1dLFxuICAgICAgcTEgPSBjdXJyZW50RGF0YS5xdWFydGlsZXNbcXVhcnRpbGVLZXlzWzFdXVxuXG4gICAgICB0LmF0dHIoJ3RyYW5zZm9ybScsIGhvcml6b250YWxRID8gJ3RyYW5zbGF0ZSgnK29iamVjdFNpemUgLyAyKycsMCknIDogJ3RyYW5zbGF0ZSgwLCcrb2JqZWN0U2l6ZSAvIDIrJyknICApXG4gICAgICAvLyBkcmF3IGN1cnZlXG4gICAgICBsYS50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5hdHRyKCdkJywgZnVuY3Rpb24oZGQsIGlpKXsgcmV0dXJuIGxBcmVhKGN1cnJlbnREYXRhLmNvbnRvdXIpfSlcbiAgICAgIC5hdHRyKCdmaWxsJywgZmlsbENvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZScsIHN0cm9rZUNvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIG9iamVjdFN0cm9rZVdpZHRoKVxuXG4gICAgICByYS50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5hdHRyKCdkJywgZnVuY3Rpb24oZGQsIGlpKXsgcmV0dXJuIHJBcmVhKGN1cnJlbnREYXRhLmNvbnRvdXIpfSlcbiAgICAgIC5hdHRyKCdmaWxsJywgZmlsbENvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZScsIHN0cm9rZUNvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIG9iamVjdFN0cm9rZVdpZHRoKVxuXG4gICAgICBhcmVhLm5vZGUoKS5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW92ZXInLCBmdW5jdGlvbihkZCwgaWkpe1xuICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnLicrb2JqZWN0Q2xhc3MpLnN0eWxlKCdvcGFjaXR5JywgMC4yKVxuICAgICAgICB0LnN0eWxlKCdvcGFjaXR5JywgMSlcbiAgICAgICAgbGEuYXR0cignc3Ryb2tlLXdpZHRoJyxvYmplY3RTdHJva2VXaWR0aCoyKVxuICAgICAgICByYS5hdHRyKCdzdHJva2Utd2lkdGgnLG9iamVjdFN0cm9rZVdpZHRoKjIpXG4gICAgICB9KVxuICAgICAgYXJlYS5ub2RlKCkuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VvdXQnLCBmdW5jdGlvbihkZCwgaWkpe1xuICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnLicrb2JqZWN0Q2xhc3MpLnN0eWxlKCdvcGFjaXR5JywgMSlcbiAgICAgICAgbGEuYXR0cignc3Ryb2tlLXdpZHRoJyxvYmplY3RTdHJva2VXaWR0aClcbiAgICAgICAgcmEuYXR0cignc3Ryb2tlLXdpZHRoJyxvYmplY3RTdHJva2VXaWR0aClcbiAgICAgIH0pXG5cbiAgICAgIGlmIChwb2ludHNRKSB7XG4gICAgICAgIHZhciBwdHNDb250YWluZXIgPSBzYWZlU2VsZWN0KHQsICdnJywgJ3BvaW50cycpXG4gICAgICAgIHZhciBwdHMgPSBwdHNDb250YWluZXIuc2VsZWN0QWxsKCcucG9pbnQnKS5kYXRhKGN1cnJlbnREYXRhLnBvaW50S2V5cylcbiAgICAgICAgcHRzLm9uKCdtb3VzZW92ZXInLCBudWxsKVxuXG5cbiAgICAgICAgdmFyIHB0c0V4aXQgPSBwdHMuZXhpdCgpLnRyYW5zaXRpb24oKS5lYXNlKGVhc2VGdW5jKS5kdXJhdGlvbih0cmFuc2l0aW9uRHVyYXRpb24pXG4gICAgICAgIC5hdHRyKCdyJywgMClcbiAgICAgICAgLmF0dHIoJ2N5JywgaG9yaXpvbnRhbFEgPyBzY2FsZShleHRlbnRbMV0pIC0gc2NhbGUocTIpIDogdlNjYWxlKDApKVxuICAgICAgICAuYXR0cignY3gnLCBob3Jpem9udGFsUSA/IHZTY2FsZSgwKSA6IHNjYWxlKHEyKSkucmVtb3ZlKClcblxuICAgICAgICB2YXIgcHRzRW50ZXIgPSBwdHMuZW50ZXIoKS5hcHBlbmQoJ2NpcmNsZScpLmF0dHIoJ2NsYXNzJywgJ3BvaW50JykuYXR0cigncicsIDApXG4gICAgICAgIC5hdHRyKCdjeCcsIGhvcml6b250YWxRID8gMCA6IHNjYWxlKHEyKSlcbiAgICAgICAgLmF0dHIoJ2N5JywgaG9yaXpvbnRhbFEgPyBzY2FsZShxMikgOiAwKVxuXG4gICAgICAgIHB0cyA9IHB0cy5tZXJnZShwdHNFbnRlcilcblxuICAgICAgICAvLyBjb25zb2xlLmxvZyhwb2ludHNUb29sdGlwLmhlYWRlcigpKVxuXG4gICAgICAgIHZhciBwVFRpcHMgPSBUVGlwKCkuc2VsZWN0aW9uKHB0cykuZGF0YSh2aW9saW5Qb2ludHNFeHRyYWN0b3Ioa2V5LCBjdXJyZW50RGF0YSkpXG4gICAgICAgIC5oZWFkZXIocG9pbnRzVG9vbHRpcC5oZWFkZXIoKSlcbiAgICAgICAgLmtleXMocG9pbnRzVG9vbHRpcC5rZXlzKCkpXG4gICAgICAgIC52YWx1ZXMocG9pbnRzVG9vbHRpcC52YWx1ZXMoKSlcblxuICAgICAgICBwVFRpcHMoKVxuXG4gICAgICAgIHZhciBwTWluID0gZDMubWluKGN1cnJlbnREYXRhLnBvaW50VmFsdWVzKSwgcE1heCA9IGQzLm1heChjdXJyZW50RGF0YS5wb2ludFZhbHVlcylcblxuXG5cbiAgICAgICAgcHRzLnRyYW5zaXRpb24oKS5kdXJhdGlvbih0cmFuc2l0aW9uRHVyYXRpb24pLmVhc2UoZWFzZUZ1bmMpLmF0dHIoJ3InLCBwb2ludFJhZGl1cylcbiAgICAgICAgLmF0dHIoJ2N5JywgZnVuY3Rpb24ocG9pbnRLZXksIGlpKXtcbiAgICAgICAgICB2YXIgZGQgPSBjdXJyZW50RGF0YS5wb2ludFZhbHVlc1tpaV1cbiAgICAgICAgICBpZiAoaG9yaXpvbnRhbFEpIHsgcmV0dXJuIHNjYWxlKGV4dGVudFsxXSkgLSBzY2FsZShkZCkgfVxuICAgICAgICAgIHZhciBqID0gd2hpY2hCaW4oY3VycmVudERhdGEuYmlubmVkLCBkZClcbiAgICAgICAgICB2YXIgciA9IE1hdGgucmFuZG9tKClcbiAgICAgICAgICB2YXIgbiA9IHZTY2FsZShyICogY3VycmVudERhdGEuZnJlcXVlbmNpZXNbal0gKiAwLjUpXG4gICAgICAgICAgdmFyIGsgPSBNYXRoLnJhbmRvbSgpID4gMC41ID8gbiA6IC1uXG4gICAgICAgICAgcmV0dXJuIGtcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ2N4JywgZnVuY3Rpb24ocG9pbnRLZXksIGlpKXtcbiAgICAgICAgICB2YXIgZGQgPSBjdXJyZW50RGF0YS5wb2ludFZhbHVlc1tpaV1cbiAgICAgICAgICBpZiAoaG9yaXpvbnRhbFEpIHtcbiAgICAgICAgICAgIHZhciBqID0gd2hpY2hCaW4oY3VycmVudERhdGEuYmlubmVkLCBkZClcbiAgICAgICAgICAgIHZhciByID0gTWF0aC5yYW5kb20oKVxuICAgICAgICAgICAgdmFyIG4gPSB2U2NhbGUociAqIGN1cnJlbnREYXRhLmZyZXF1ZW5jaWVzW2pdICogMC41KVxuICAgICAgICAgICAgdmFyIGsgPSBNYXRoLnJhbmRvbSgpID4gMC41ID8gbiA6IC1uXG4gICAgICAgICAgICByZXR1cm4ga1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gc2NhbGUoZGQpXG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCdzdHJva2UnLCBmdW5jdGlvbihkZCwgaWkpIHsgdmFyIGRkID0gY3VycmVudERhdGEucG9pbnRWYWx1ZXNbaWldOyByZXR1cm4gcG9pbnRDb2xvckZ1bmMoZGQsICdzdHJva2UnLCBzdHJva2VDb2xvciwgcE1pbiwgcE1heCkgfSlcbiAgICAgICAgLmF0dHIoJ2ZpbGwnICAsIGZ1bmN0aW9uKGRkLCBpaSkgeyB2YXIgZGQgPSBjdXJyZW50RGF0YS5wb2ludFZhbHVlc1tpaV07IHJldHVybiBwb2ludENvbG9yRnVuYyhkZCwgJ2ZpbGwnICAsIHN0cm9rZUNvbG9yLCBwTWluLCBwTWF4KSB9KVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgcG9pbnRTdHJva2VXaWR0aClcblxuICAgICAgICBwdHNDb250YWluZXIuc2VsZWN0QWxsKCdjaXJjbGUucG9pbnQnKS5vbignbW91c2VvdmVyJywgZnVuY3Rpb24oZGQsIGlpKXtcbiAgICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnLicrb2JqZWN0Q2xhc3MpLnN0eWxlKCdvcGFjaXR5JywgMC4yKVxuICAgICAgICAgIHQuc3R5bGUoJ29wYWNpdHknLCAxKVxuICAgICAgICAgIGxhLmF0dHIoJ3N0cm9rZS13aWR0aCcsb2JqZWN0U3Ryb2tlV2lkdGgqMilcbiAgICAgICAgICByYS5hdHRyKCdzdHJva2Utd2lkdGgnLG9iamVjdFN0cm9rZVdpZHRoKjIpXG5cbiAgICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCcucG9pbnQnKS5zdHlsZSgnb3BhY2l0eScsIDAuMilcbiAgICAgICAgICBkMy5zZWxlY3QodGhpcykuc3R5bGUoJ29wYWNpdHknLCAxKS5hdHRyKCdyJywgcG9pbnRSYWRpdXMgKiAyKS5hdHRyKCdzdHJva2Utd2lkdGgnLHBvaW50U3Ryb2tlV2lkdGgqMilcbiAgICAgICAgfSlcbiAgICAgICAgcHRzQ29udGFpbmVyLnNlbGVjdEFsbCgnY2lyY2xlLnBvaW50Jykub24oJ21vdXNlb3V0JywgZnVuY3Rpb24oZGQsIGlpKXtcbiAgICAgICAgICB2YXIgZSA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdTVkdFdmVudHMnKVxuICAgICAgICAgIGUuaW5pdEV2ZW50KCdtb3VzZW91dCcsdHJ1ZSx0cnVlKTtcbiAgICAgICAgICBhcmVhLm5vZGUoKS5kaXNwYXRjaEV2ZW50KGUpXG5cbiAgICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCcucG9pbnQnKS5zdHlsZSgnb3BhY2l0eScsIDEpXG4gICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ3N0cm9rZS13aWR0aCcsIHBvaW50U3Ryb2tlV2lkdGgpLmF0dHIoJ3InLCBwb2ludFJhZGl1cylcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBjVi5zZWxlY3RBbGwoJy5wb2ludCcpXG4gICAgICAgIC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgICAuYXR0cigncicsIDApXG4gICAgICAgIC5hdHRyKCdjeScsIGhvcml6b250YWxRID8gc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKHEyKSA6IHZTY2FsZSgwKSlcbiAgICAgICAgLmF0dHIoJ2N4JywgaG9yaXpvbnRhbFEgPyB2U2NhbGUoMCkgOiBzY2FsZShxMikpXG4gICAgICAgIC5yZW1vdmUoKVxuICAgICAgfVxuXG5cbiAgICB9KVxuXG5cbiAgICB0b29sdGlwLnNlbGVjdGlvbihjb250YWluZXIuc2VsZWN0QWxsKCdnOm5vdCgudG8tcmVtb3ZlKS4nK29iamVjdENsYXNzICsgJyAuYXJlYScpKVxuICAgIGlmICh0b29sdGlwLmRhdGEoKSA9PSB1bmRlZmluZWQpIHt0b29sdGlwLmRhdGEoZGF0YSl9XG4gICAgdG9vbHRpcCgpXG4gICAgaWYgKHRvb2x0aXAudmFsdWVzKCkgPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0b29sdGlwLnZhbHVlcyhbXG4gICAgICAgIGZ1bmN0aW9uKGN1cnJlbnREYXRhLCB0b29sdGlwS2V5KXsgcmV0dXJuIGN1cnJlbnREYXRhWydxdWFydGlsZXMnXVt0b29sdGlwS2V5XSB9LFxuICAgICAgICBmdW5jdGlvbihjdXJyZW50RGF0YSwgdG9vbHRpcEtleSl7IHJldHVybiBjdXJyZW50RGF0YVsncXVhcnRpbGVzJ11bdG9vbHRpcEtleV0gfSxcbiAgICAgICAgZnVuY3Rpb24oY3VycmVudERhdGEsIHRvb2x0aXBLZXkpeyByZXR1cm4gY3VycmVudERhdGFbJ3F1YXJ0aWxlcyddW3Rvb2x0aXBLZXldIH0sXG4gICAgICAgIGZ1bmN0aW9uKGN1cnJlbnREYXRhLCB0b29sdGlwS2V5KXsgcmV0dXJuIGN1cnJlbnREYXRhWydxdWFydGlsZXMnXVt0b29sdGlwS2V5XSB9LFxuICAgICAgICBmdW5jdGlvbihjdXJyZW50RGF0YSwgdG9vbHRpcEtleSl7IHJldHVybiBjdXJyZW50RGF0YVsncXVhcnRpbGVzJ11bdG9vbHRpcEtleV0gfVxuICAgICAgXSlcblxuICAgIH1cblxuICB9XG5cbiAgcmV0dXJuIHZpb2xpblxufVxuXG5cblxuXG5cbi8qKlxuKiBQcm9kdWNlcyB0aGUgZnVuY3Rpb24gd2hpY2ggbWFuaXB1bGF0ZXMgdGhlIHZpb2xpbiBkYXRhIHRvIGhhdmUgdmFsdWVzIG5lZWRlZFxuKiBmb3IgcmVuZGVyaW5nIHRoZSB2aW9saW5zIGFzIHN2Zy5cbiogQHJldHVybnMge2Z1bmN0aW9ufSBjYWxjdWxhdGVWaW9saW5WYWx1ZXNcbiogQG5hbWVzcGFjZSBuZWVkZWRWaW9saW5WYWx1ZXNcbiovXG5mdW5jdGlvbiBuZWVkZWRWaW9saW5WYWx1ZXMoKSB7XG4gIHZhclxuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0aGUgb3JpZW50YXRpb24gb2YgdGhlIHZpb2xpbnMgYXJlIGhvcml6b250YWxcbiAgKiAoc2VlIHtAbGluayB2aW9saW4jb3JpZW50fSlcbiAgKiBAcGFyYW0ge09iamVjdH0gW2hvcml6b250YWxRPXRydWVdXG4gICogQG1lbWJlcm9mIG5lZWRlZFZpb2xpblZhbHVlcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgaG9yaXpvbnRhbFEgPSB0cnVlLFxuICAvKipcbiAgKiBLZXlzIHRvIGJlIHB1dCBpbnRvIHRoZSBxdWFydGlsZXMgaWYgdGhleSBuZWVkIHRvIGJlIGNhbGN1bGF0ZWQuXG4gICogKHNlZSB7QGxpbmsgdmlvbGluI3F1YXJ0aWxlS2V5c30pXG4gICogQHBhcmFtIHtPYmplY3R9IFtxdWFydGlsZUtleXM9WydRMCcsICdRMScsICdRMicsICdRMycsICdRNCddXVxuICAqIEBtZW1iZXJvZiBuZWVkZWRWaW9saW5WYWx1ZXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHF1YXJ0aWxlS2V5cyA9IFsnUTAnLCAnUTEnLCAnUTInLCAnUTMnLCAnUTQnXSxcbiAgLyoqXG4gICogRnVuY3Rpb24gd2hpY2ggZ2l2ZW4gdGhlIGtleSBvZiB0aGUgdmlvbGluIGFuZCB0aGF0IGtleSdzIGFzc29jaWF0ZWQgdmFsdWVcbiAgKiByZXR1cm5zIHRoZSBvYmplY3QgY29uc2l0aW5nIG9mIHRoZSBwb2ludHMgb2YgdGhlIHZpb2xpblxuICAqIChzZWUge0BsaW5rIHZpb2xpbiN2aW9saW5Qb2ludHNFeHRyYWN0b3J9KVxuICAqIEBwYXJhbSB7T2JqZWN0fSBbdmlvbGluUG9pbnRzRXh0cmFjdG9yPWZ1bmN0aW9uKHZpb2xpbktleSwgdmlvbGluRGF0YSkgeyByZXR1cm4gdmlvbGluRGF0YS5wb2ludHMgfV1cbiAgKiBAbWVtYmVyb2YgbmVlZGVkVmlvbGluVmFsdWVzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2aW9saW5Qb2ludHNFeHRyYWN0b3IsXG4gIC8qKlxuICAqIEZ1bmN0aW9uIHdoaWNoIGdpdmVuIHRoZSBrZXkgb2YgdGhlIGN1cnJlbnQgcG9pbnQgYW5kIHRoZSBvYmplY3Qgb2YgcG9pbnRzIGZvciB0aGVcbiAgKiB2aW9saW4sIHJldHVybnMgdGhlIG51bWVyaWNhbCB2YWx1ZSBvZiB0aGUgcG9pbnRcbiAgKiAoc2VlIHtAbGluayB2aW9saW4jdmlvbGluUG9pbnRWYWx1ZUV4dHJhY3Rvcn0pXG4gICogQHBhcmFtIHtPYmplY3R9IFt2aW9saW5Qb2ludFZhbHVlRXh0cmFjdG9yPWZ1bmN0aW9uKHZpb2xpblBvaW50S2V5LCB2aW9saW5Qb2ludERhdGEpIHsgcmV0dXJuIHZpb2xpblBvaW50RGF0YVt2aW9saW5Qb2ludEtleV0udmFsdWUgfV1cbiAgKiBAbWVtYmVyb2YgbmVlZGVkVmlvbGluVmFsdWVzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2aW9saW5Qb2ludFZhbHVlRXh0cmFjdG9yXG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGhvcml6b250YWxRXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNvcmllbnR9KVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtjYWxjdWxhdGVWaW9saW5WYWx1ZXMgfCBib29sZWFufVxuICAgKiBAbWVtYmVyb2YgY2FsY3VsYXRlVmlvbGluVmFsdWVzXG4gICAqIEBwcm9wZXJ0eVxuICAgKlxuICAgKiBieSBkZWZhdWx0IGhvcml6b250YWxRID0gdHJ1ZVxuICAgKi9cbiAgY2FsY3VsYXRlVmlvbGluVmFsdWVzLmhvcml6b250YWxRID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChob3Jpem9udGFsUT1fLCBjYWxjdWxhdGVWaW9saW5WYWx1ZXMpIDogaG9yaXpvbnRhbFEgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHF1YXJ0aWxlS2V5c1xuICAgKiAoc2VlIHtAbGluayB2aW9saW4jcXVhcnRpbGVLZXlzfSlcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2NhbGN1bGF0ZVZpb2xpblZhbHVlcyB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgY2FsY3VsYXRlVmlvbGluVmFsdWVzXG4gICAqIEBwcm9wZXJ0eVxuICAgKlxuICAgKiBieSBkZWZhdWx0IHF1YXJ0aWxlS2V5cyA9IFtcIlEwXCIsXCJRMVwiLFwiUTJcIixcIlEzXCIsXCJRNFwiXVxuICAgKi9cbiAgY2FsY3VsYXRlVmlvbGluVmFsdWVzLnF1YXJ0aWxlS2V5cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocXVhcnRpbGVLZXlzPV8sIGNhbGN1bGF0ZVZpb2xpblZhbHVlcykgOiBxdWFydGlsZUtleXMgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHZpb2xpblBvaW50c0V4dHJhY3RvclxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jdmlvbGluUG9pbnRzRXh0cmFjdG9yfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2NhbGN1bGF0ZVZpb2xpblZhbHVlcyB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgY2FsY3VsYXRlVmlvbGluVmFsdWVzXG4gICAqIEBwcm9wZXJ0eVxuICAgKlxuICAgKiBieSBkZWZhdWx0IHZpb2xpblBvaW50c0V4dHJhY3RvciA9IGZ1bmN0aW9uKHZpb2xpbktleSwgdmlvbGluRGF0YSkgeyByZXR1cm4gdmlvbGluRGF0YS5wb2ludHMgfVxuICAgKi9cbiAgY2FsY3VsYXRlVmlvbGluVmFsdWVzLnZpb2xpblBvaW50c0V4dHJhY3RvciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodmlvbGluUG9pbnRzRXh0cmFjdG9yPV8sIGNhbGN1bGF0ZVZpb2xpblZhbHVlcykgOiB2aW9saW5Qb2ludHNFeHRyYWN0b3IgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3JcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3Zpb2xpblBvaW50VmFsdWVFeHRyYWN0b3J9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Y2FsY3VsYXRlVmlvbGluVmFsdWVzIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBjYWxjdWxhdGVWaW9saW5WYWx1ZXNcbiAgICogQHByb3BlcnR5XG4gICAqXG4gICAqIGJ5IGRlZmF1bHQgdmlvbGluUG9pbnRWYWx1ZUV4dHJhY3RvciA9IGZ1bmN0aW9uKHZpb2xpblBvaW50S2V5LCB2aW9saW5Qb2ludERhdGEpIHsgcmV0dXJuIHZpb2xpblBvaW50RGF0YVt2aW9saW5Qb2ludEtleV0udmFsdWUgfVxuICAgKi9cbiAgY2FsY3VsYXRlVmlvbGluVmFsdWVzLnZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3I9XywgY2FsY3VsYXRlVmlvbGluVmFsdWVzKSA6IHZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3IgfVxuXG5cbiAgLyoqXG4gICogVGhlIGZ1bmN0aW9uIHByb2R1Y2VkIGJ5IG5lZWRlZFZpb2xpblZhbHVlcy5cbiAgKlxuICAqIEFkZHMgdGhlIGRhdGEgbmVlZCB0byByZW5kZXIgdGhlIHZpb2xpbiBhcyBhbiBzdmdcbiAgKiBAcGFyYW0ge3N0cmluZ30gdmlvbGluS2V5IHRoZSBrZXkgb2YgdGhlIGN1cnJlbnQgdmlvbGluXG4gICogQHBhcmFtIHtvYmplY3R9IGRhdGEgdGhlIG9iamVjdCBjb25zaXN0aW5nIG9mIHZpb2xpbktleSAtIHZhbHVlcyAodmlvbGluIGRhdGEpIHBhaXJzXG4gICogQHJldHVybnMge25vbmV9IHRoaXMgZnVuY3Rpb24gbWFuaXB1bGF0ZXMgdGhlIHBhc3NlZCBkYXRhIG9iamVjdCBhZGRpbmcgdGhlIGZvbGxvd2luZyBrZXlzXG4gICpcbiAgKiBkYXRhW3Zpb2xpbktleV0uYmlubmVkIC8vIHRoZSBiaW5uZWQgdmFsdWVzIG9mIHRoZSBwb2ludHNcbiAgKlxuICAqIGRhdGFbdmlvbGluS2V5XS5mcmVxdWVuY2llcyAvLyB0aGUgbGlzdCBjb25zaXN0aW5nIG9mIHRoZSBsZW5ndGggb2YgZWFjaCBiaW5cbiAgKlxuICAqIGRhdGFbdmlvbGluS2V5XS5jb250b3VyIC8vIHRoZSBwb2ludHMgZGVwaWN0aW5nIHRoZSBjb250b3VyIG9mIDEvMiBvZiB0aGUgdmlvbGluXG4gICpcbiAgKiBkYXRhW3Zpb2xpbktleV0ucXVhcnRpbGVzIC8vIHRoZSBxdWFydGlsZXMgb2YgdGhlIHBvaW50cycgdmFsdWVzXG4gICpcbiAgKiBkYXRhW3Zpb2xpbktleV0ucG9pbnRLZXlzIC8vIHRoZSBrZXlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgcG9pbnRzXG4gICpcbiAgKiBkYXRhW3Zpb2xpbktleV0ucG9pbnRWYWx1ZXMgLy8gdGhlIG51bWVyaWNhbCB2YWx1ZXMgb2YgdGhlIHBvaW50c1xuICAqXG4gICogQG1lbWJlcm9mIG5lZWRlZFZpb2xpblZhbHVlcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZnVuY3Rpb24gY2FsY3VsYXRlVmlvbGluVmFsdWVzKHZpb2xpbktleSwgZGF0YSkge1xuICAgIC8vIGRhdGEgZm9yIHRoZSBjdXJyZW50IHZpb2xpblxuICAgIHZhciB2aW9saW5EYXRhID0gZGF0YVt2aW9saW5LZXldO1xuICAgIC8vIHRoZSBvYmplY3Qgb2YgcG9pbnRzXG4gICAgdmFyIHZpb2xpblBvaW50cyA9IHZpb2xpblBvaW50c0V4dHJhY3Rvcih2aW9saW5LZXksIHZpb2xpbkRhdGEpO1xuICAgIC8vXG4gICAgdmFyIHZpb2xpblBvaW50c0tleXMgPSBkMy5rZXlzKHZpb2xpblBvaW50cyk7XG4gICAgLy8gdGhlIG51bWVyaWNhbCB2YWx1ZXMgb2YgdGhvc2UgcG9pbnRzXG4gICAgdmFyIHZpb2xpblBvaW50c1ZhbHVlcyA9IHZpb2xpblBvaW50c0tleXMubWFwKGZ1bmN0aW9uKHBrLCBpKXtyZXR1cm4gdmlvbGluUG9pbnRWYWx1ZUV4dHJhY3RvcihwaywgdmlvbGluUG9pbnRzKX0pXG5cbiAgICAvLyBxdWFydGlsZXMgb2YgdGhvc2UgcG9pbnRzXG4gICAgdmFyIHBvaW50UXVhcnRpbGVzID0gcXVhcnRpbGVzKHZpb2xpblBvaW50c1ZhbHVlcywgcXVhcnRpbGVLZXlzKVxuXG4gICAgLy8gYmlubmVkIHBvaW50c1xuICAgIHZhciBiaW5uZWQgPSBkMy5oaXN0b2dyYW0oKSh2aW9saW5Qb2ludHNWYWx1ZXMpXG4gICAgLy8gbGVuZ3RoIG9mIGJpbnNcbiAgICB2YXIgZnJlcXVlbmNpZXMgPSBiaW5uZWQubWFwKGJpbj0+YmluLmxlbmd0aClcbiAgICAvLyBtaW4gYW5kIG1heCBjb3VudG91ciBwb2ludHMgZm9yIG5pY2UgZHJhd2luZ3NcbiAgICB2YXIgbWluQ29udG91clBvaW50ID0gaG9yaXpvbnRhbFEgPyB7eDogMCwgeTogZDMubWluKHZpb2xpblBvaW50c1ZhbHVlcyl9IDogIHt4OiBkMy5taW4odmlvbGluUG9pbnRzVmFsdWVzKSwgeTogMH1cbiAgICB2YXIgbWF4Q29udG91clBvaW50ID0gaG9yaXpvbnRhbFEgPyB7eDogMCwgeTogZDMubWF4KHZpb2xpblBvaW50c1ZhbHVlcyl9IDogIHt4OiBkMy5tYXgodmlvbGluUG9pbnRzVmFsdWVzKSwgeTogMH1cbiAgICB2YXIgdmlvbGluQ29udG91clBvaW50cyA9IGJpbm5lZC5tYXAoZnVuY3Rpb24oYmluLCBpKSB7XG4gICAgICAgIHJldHVybiBob3Jpem9udGFsUVxuICAgICAgICA/IHt5OiAoYmluLmxlbmd0aCkgPyBkMy5tZWRpYW4oYmluKTogZDMubWVkaWFuKFtiaW4ueDAsIGJpbi54MV0pLCB4OiBmcmVxdWVuY2llc1tpXX1cbiAgICAgICAgOiB7eDogKGJpbi5sZW5ndGgpID8gZDMubWVkaWFuKGJpbik6IGQzLm1lZGlhbihbYmluLngwLCBiaW4ueDFdKSwgeTogZnJlcXVlbmNpZXNbaV19XG4gICAgICB9KVxuICAgIC8vIHBvaW50cyBhbG9uZyB3aGljaCB0byBkcmF3IHRoZSB2aW9saW4gc2hwZVxuICAgIHZpb2xpbkNvbnRvdXJQb2ludHMgPSBbbWluQ29udG91clBvaW50XS5jb25jYXQodmlvbGluQ29udG91clBvaW50cykuY29uY2F0KFttYXhDb250b3VyUG9pbnRdKVxuXG4gICAgLy8gc2V0IGRhdGFcbiAgICB2aW9saW5EYXRhLmJpbm5lZCA9IGJpbm5lZDtcbiAgICB2aW9saW5EYXRhLmZyZXF1ZW5jaWVzID0gZnJlcXVlbmNpZXNcbiAgICB2aW9saW5EYXRhLmNvbnRvdXIgPSB2aW9saW5Db250b3VyUG9pbnRzXG4gICAgdmlvbGluRGF0YS5xdWFydGlsZXMgPSBwb2ludFF1YXJ0aWxlc1xuICAgIHZpb2xpbkRhdGEucG9pbnRLZXlzID0gdmlvbGluUG9pbnRzS2V5c1xuICAgIHZpb2xpbkRhdGEucG9pbnRWYWx1ZXMgPSB2aW9saW5Qb2ludHNWYWx1ZXNcbiAgfVxuXG4gIHJldHVybiBjYWxjdWxhdGVWaW9saW5WYWx1ZXNcbn1cbiIsImltcG9ydCB7aHlwZW5hdGUsIHNhZmVTZWxlY3QsIHJvdW5kLCBpbnRlcnBvbGF0ZUNvbG9yc30gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7c2V0dXBDb250YWluZXJ9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHtjb2xvckZ1bmN0aW9uIGFzIENGfSBmcm9tICcuL2NvbG9yLWZ1bmN0aW9uJztcblxuXG5leHBvcnQgZnVuY3Rpb24gbnVtZXJpY0xlZ2VuZCggc2VsZWN0aW9uICkge1xuXG4gIHZhclxuICBtaW49MCxcbiAgbWF4PTEsXG4gIHNwYWNlWCxcbiAgc3BhY2VZLFxuICBjb2xvckZ1bmN0aW9uID0gQ0YoKSxcbiAgbmFtZXNwYWNlPSdkM3NtLWxpbmVhci12ZXJ0aWNhbC1ncmFkaWVudCcsXG4gIGZvbnRTaXplID0gMTIsXG4gIGJhY2tncm91bmRGaWxsID0gJ3RyYW5zcGFyZW50JyxcbiAgdGV4dENvbG9yID0gJ2JsYWNrJyxcbiAgcm91bmRUbyA9IDJcblxuXG4gIGxlZ2VuZC5taW4gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1pbj1fLCBsZWdlbmQpIDogbWluIH1cbiAgbGVnZW5kLm1heCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobWF4PV8sIGxlZ2VuZCkgOiBtYXggfVxuICBsZWdlbmQuc3BhY2VYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVg9XywgbGVnZW5kKSA6IHNwYWNlWCB9XG4gIGxlZ2VuZC5zcGFjZVkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWT1fLCBsZWdlbmQpIDogc3BhY2VZIH1cbiAgbGVnZW5kLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlPV8sIGxlZ2VuZCkgOiBuYW1lc3BhY2UgfVxuICBsZWdlbmQuZm9udFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGZvbnRTaXplPV8sIGxlZ2VuZCkgOiBmb250U2l6ZSB9XG4gIGxlZ2VuZC5iYWNrZ3JvdW5kRmlsbCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFja2dyb3VuZEZpbGw9XywgbGVnZW5kKSA6IGJhY2tncm91bmRGaWxsIH1cbiAgbGVnZW5kLmNvbG9yRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvbG9yRnVuY3Rpb249XywgbGVnZW5kKSA6IGNvbG9yRnVuY3Rpb24gfVxuICBsZWdlbmQudGV4dENvbG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0ZXh0Q29sb3I9XywgbGVnZW5kKSA6IHRleHRDb2xvciB9XG4gIGxlZ2VuZC5yb3VuZFRvID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChyb3VuZFRvPV8sIGxlZ2VuZCkgOiByb3VuZFRvIH1cblxuICBmdW5jdGlvbiBsZWdlbmQoKSB7XG4gICAgLy8gYmFja2dyb3VuZCBjbGlwaW5nIHJlY3RhbmdsZVxuICAgIHZhciBiZ2NwUmVjdCA9IHt4OjAsIHk6MCwgd2lkdGg6IHNwYWNlWCwgaGVpZ2h0OnNwYWNlWX1cbiAgICB2YXIgY29udGFpbmVyID0gc2V0dXBDb250YWluZXIoIHNlbGVjdGlvbiwgbmFtZXNwYWNlLCBiZ2NwUmVjdCwgYmFja2dyb3VuZEZpbGwgKTtcblxuICAgIHZhciBkZWZzID0gc2FmZVNlbGVjdChzZWxlY3Rpb24sICdkZWZzJylcbiAgICB2YXIgbGluZWFyR3JhZGllbnQgPSBzYWZlU2VsZWN0KGRlZnMsICdsaW5lYXJHcmFkaWVudCcpXG4gICAgLmF0dHIoXCJ4MVwiLCBcIjAlXCIpXG4gICAgLmF0dHIoXCJ5MVwiLCBcIjEwMCVcIilcbiAgICAuYXR0cihcIngyXCIsIFwiMCVcIilcbiAgICAuYXR0cihcInkyXCIsIFwiMCVcIilcbiAgICAuYXR0cignaWQnLCBoeXBlbmF0ZShuYW1lc3BhY2UsJ251bWVyaWNhbC1sZWdlbmQtZ3JhZGllbnQnKSlcblxuXG4gICAgY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50KFttaW4sIG1heF0pXG4gICAgLmNvbG9yQnkoJ3ZhbHVlJylcbiAgICAudmFsdWVFeHRyYWN0b3IoZnVuY3Rpb24oaywgdiwgaSl7cmV0dXJuIHZ9KVxuXG5cbiAgICBsaW5lYXJHcmFkaWVudC5zZWxlY3RBbGwoJ3N0b3AnKVxuICAgIC5kYXRhKCBjb2xvckZ1bmN0aW9uLmNvbG9ycygpIClcbiAgICAuZW50ZXIoKVxuICAgIC5hcHBlbmQoJ3N0b3AnKVxuICAgIC5hdHRyKFwib2Zmc2V0XCIsIGZ1bmN0aW9uKGQsIGkpeyByZXR1cm4gaSAvIChjb2xvckZ1bmN0aW9uLmNvbG9ycygpLmxlbmd0aCAtIDEpIH0pXG4gICAgLmF0dHIoJ3N0b3AtY29sb3InLCBmdW5jdGlvbihkKSB7cmV0dXJuIGR9KVxuXG5cblxuXG4gICAgdmFyIHJlY3QgPSBzYWZlU2VsZWN0KGNvbnRhaW5lciwgJ3JlY3QnLCAnbGVnZW5kJylcbiAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgwLCcrZm9udFNpemUrJyknKVxuICAgIC5zdHlsZShcImZpbGxcIiwgXCJ1cmwoI1wiK2h5cGVuYXRlKG5hbWVzcGFjZSwnbnVtZXJpY2FsLWxlZ2VuZC1ncmFkaWVudCcpK1wiKVwiKVxuICAgIC5hdHRyKCd4JywgMClcbiAgICAuYXR0cigneScsIDApXG4gICAgLmF0dHIoJ3dpZHRoJywgc3BhY2VYKVxuICAgIC5hdHRyKCdoZWlnaHQnLCBzcGFjZVkgLSBmb250U2l6ZSoyKVxuICAgIC5vbignbW91c2Vtb3ZlJywgZnVuY3Rpb24oZCwgaSl7bGVnZW5kTW91c2Vtb3ZlKGQsIGksIHJlY3QsIGQzLnNlbGVjdCh0aGlzKSl9KVxuICAgIC5vbignbW91c2VvdXQnLCBmdW5jdGlvbihkLCBpKXsgZDMuc2VsZWN0KFwiI1wiK2h5cGVuYXRlKG5hbWVzcGFjZSwnbGVnZW5kLXRvb2x0aXAnKSkucmVtb3ZlKCkgfSlcblxuICAgIHZhciBtaW5UZXh0ID0gc2FmZVNlbGVjdChjb250YWluZXIsICd0ZXh0JywgJ21pbicpXG4gICAgLnRleHQocm91bmQobWluLCAyKSlcbiAgICAuYXR0cigndGV4dC1hbmNob3InLCAnbWlkZGxlJylcbiAgICAuYXR0cihcImZvbnQtc2l6ZVwiLCBmb250U2l6ZSsncHgnKVxuICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhclxuICAgICAgeCA9IHNwYWNlWCAvIDIsXG4gICAgICB5ID0gc3BhY2VZIC0gZm9udFNpemUgLyA0LFxuICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgcmV0dXJuIHRcbiAgICB9KVxuXG4gICAgdmFyIG1heFRleHQgPSBzYWZlU2VsZWN0KGNvbnRhaW5lciwgJ3RleHQnLCAnbWF4JylcbiAgICAudGV4dChyb3VuZChtYXgsIDIpKVxuICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsICdtaWRkbGUnKVxuICAgIC5hdHRyKFwiZm9udC1zaXplXCIsIGZvbnRTaXplKydweCcpXG4gICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgdmFyXG4gICAgICB4ID0gc3BhY2VYIC8gMixcbiAgICAgIHkgPSBmb250U2l6ZSxcbiAgICAgIHQgPSAndHJhbnNsYXRlKCcreCsnLCcreSsnKSdcbiAgICAgIHJldHVybiB0XG4gICAgfSlcblxuXG5cblxuICB9XG5cbiAgZnVuY3Rpb24gbGVnZW5kTW91c2Vtb3ZlKGQsIGksIHJlY3QsIHQpIHtcbiAgICB2YXIgcyA9IGQzLnNjYWxlTGluZWFyKClcbiAgICAuZG9tYWluKFswLCByZWN0LmF0dHIoJ2hlaWdodCcpXSlcbiAgICAucmFuZ2UoW21heCwgbWluXSlcbiAgICB2YXIgbSA9IGQzLm1vdXNlKHJlY3Qubm9kZSgpKVxuICAgIHZhciB2ID0gcm91bmQocyhtWzFdKSxyb3VuZFRvKVxuXG4gICAgdmFyIHN0cm9rZUNvbG9yID0gY29sb3JGdW5jdGlvbih1bmRlZmluZWQsIHYsIHVuZGVmaW5lZCwgJ3N0cm9rZScpXG4gICAgdmFyIGZpbGxDb2xvciA9IGNvbG9yRnVuY3Rpb24odW5kZWZpbmVkLCB2LCB1bmRlZmluZWQsICdmaWxsJylcblxuICAgIHZhciBkaXYgPSBzYWZlU2VsZWN0KGQzLnNlbGVjdCgnYm9keScpLCAnZGl2JywgaHlwZW5hdGUobmFtZXNwYWNlLCdsZWdlbmQtdG9vbHRpcCcpKVxuICAgIC5hdHRyKCdpZCcsIGh5cGVuYXRlKG5hbWVzcGFjZSwnbGVnZW5kLXRvb2x0aXAnKSlcbiAgICAuc3R5bGUoJ3Bvc2l0aW9uJywgJ2Fic29sdXRlJylcbiAgICAuc3R5bGUoJ2xlZnQnLCAoZDMuZXZlbnQucGFnZVgrMTUpKydweCcpXG4gICAgLnN0eWxlKCd0b3AnLCAoZDMuZXZlbnQucGFnZVkrMTUpKydweCcpXG4gICAgLnN0eWxlKCdiYWNrZ3JvdW5kLWNvbG9yJywgZmlsbENvbG9yKVxuICAgIC5zdHlsZSgnYm9yZGVyLWNvbG9yJywgc3Ryb2tlQ29sb3IpXG5cbiAgICAuc3R5bGUoJ21pbi13aWR0aCcsIChmb250U2l6ZSAqIChTdHJpbmcobWF4KS5zcGxpdCgnLicpWzBdLmxlbmd0aCszKSkrJ3B4JylcbiAgICAuc3R5bGUoJ21pbi1oZWlnaHQnLCAoZm9udFNpemUgKiAoU3RyaW5nKG1heCkuc3BsaXQoJy4nKVswXS5sZW5ndGgrMykpKydweCcpXG4gICAgLnN0eWxlKCdib3JkZXItcmFkaXVzJywgJzUwJScpXG4gICAgLnN0eWxlKCdib3JkZXItcmFkaXVzJywgJzUwMDBweCcpXG5cbiAgICAuc3R5bGUoJ2Rpc3BsYXknLCAnZmxleCcpXG4gICAgLnN0eWxlKCdqdXN0aWZ5LWNvbnRlbnQnLCAnY2VudGVyJylcbiAgICAuc3R5bGUoJ3RleHQtYWxpZ24nLCAnbWlkZGxlJylcbiAgICAuc3R5bGUoJ3BhZGRpbmcnLCAyK1wicHhcIilcblxuICAgIC5zdHlsZSgnYm9yZGVyLXN0eWxlJywgJ3NvbGlkJylcbiAgICAuc3R5bGUoJ2JvcmRlci13aWR0aCcsIDIpXG5cbiAgICB2YXIgdGV4dCA9IHNhZmVTZWxlY3QoZGl2LCAnZGl2JylcbiAgICAudGV4dCh2KVxuICAgIC5zdHlsZSgnY29sb3InLCB0ZXh0Q29sb3IpXG4gICAgLnN0eWxlKCdhbGlnbi1zZWxmJywgJ2NlbnRlcicpXG4gIH1cblxuICByZXR1cm4gbGVnZW5kXG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0LCByb3VuZCwgaW50ZXJwb2xhdGVDb2xvcnN9IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQge3NldHVwQ29udGFpbmVyLCBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0LCBjYWxjdWxhdGVXaWR0aE9mU3BhY2VyfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7Y29sb3JGdW5jdGlvbiBhcyBDRn0gZnJvbSAnLi9jb2xvci1mdW5jdGlvbic7XG5pbXBvcnQge2dyb3VwaW5nU3BhY2VyfSBmcm9tICcuL2dyb3VwaW5nLXNwYWNlcic7XG5pbXBvcnQge3VuaXF1ZSwgZmxhdHRlbn0gZnJvbSAnLi9hcnJheS1mdW5jdGlvbnMnO1xuXG5leHBvcnQgZnVuY3Rpb24gY2F0ZWdvcmljTGVnZW5kKCBzZWxlY3Rpb24gKSB7XG4gIHZhclxuICBjYXRlZ29yaWVzLFxuXG4gIC8qKlxuICAqIERhdGEgdG8gcGxvdC4gQXNzdW1lZCB0byBiZSBhIG9iamVjdCwgd2hlcmUgZWFjaCBrZXkgY29ycmVzcG9uZHMgdG8gYSBsZWdlbmRcbiAgKiAoc2VlIHtAbGluayBsZWdlbmQjZGF0YX0pXG4gICogQHBhcmFtIHtPYmplY3R9IFtkYXRhPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgbGVnZW5kI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBkYXRhLFxuICAvKipcbiAgKiBXaGljaCBkaXJlY3Rpb24gdG8gcmVuZGVyIHRoZSBiYXJzIGluXG4gICogKHNlZSB7QGxpbmsgbGVnZW5kI29yaWVudH0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtvcmllbnQ9J2hvcml6b250YWwnXVxuICAqIEBtZW1iZXJvZiBsZWdlbmQjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9yaWVudD0naG9yaXpvbnRhbCcsXG4gIC8qKlxuICAqIEFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSBsZWdlbmQgaW5cbiAgKiAoc2VlIHtAbGluayBsZWdlbmQjc3BhY2VYfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlWD11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VYLFxuICAvKipcbiAgKiBBbW91bnQgb2YgdmVydGljYWwgc3BhY2UgKGluIHBpeGVscykgYXZhaWJsZSB0byByZW5kZXIgdGhlIGxlZ2VuZCBpblxuICAqIChzZWUge0BsaW5rIGxlZ2VuZC5zcGFjZVl9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbc3BhY2VZPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgbGVnZW5kI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzcGFjZVksXG5cbiAgLyoqXG4gICogV2hldGhlciBvciBub3QgdG8gYWxsb3cgbGVnZW5kIHRvIHJlbmRlciBlbGVtZW50cyBwYXNzIHRoZSBtYWluIHNwYXRpYWwgZGltZW5zaW9uXG4gICogZ2l2ZW4gdGhlIG9yaWVudGF0aW9uIChzZWUge0BsaW5rIGxlZ2VuZCNvcmllbnR9KSwgd2hlcmUge0BsaW5rIGxlZ2VuZCNvcmllbnR9PVwiaG9yaXpvbnRhbFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayBsZWdlbmQjc3BhY2VYfSBhbmQgd2hlcmUge0BsaW5rIGxlZ2VuZCNvcmllbnR9PVwidmVydGljYWxcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgbGVnZW5kI3NwYWNlWX1cbiAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvdmVyZmxvd1E9ZmFsc2VdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb3ZlcmZsb3dRID0gZmFsc2UsXG5cbiAgLyoqXG4gICogQW4gYXJyYXkgLSBwdXRhdGl2ZWx5IG9mIG90aGVyIGFycmF5cyAtIGRlcGljdGluZyBob3cgYmFycyBzaG91bGQgYmUgYXJyYW5nZWRcbiAgKiBAcGFyYW0ge0FycmF5W119IFtncm91cGluZz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZ3JvdXBpbmcsXG5cbiAgLyoqXG4gICogSG93IHRvIGdldCB0aGUgdmFsdWUgb2YgdGhlIGxlZ2VuZFxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFt2YWx1ZUV4dHJhY3Rvcj1mdW5jdGlvbihrZXksIGluZGV4KSB7IHJldHVybiBkYXRhW2tleV0gfV1cbiAgKiBAbWVtYmVyb2YgbGVnZW5kI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2YWx1ZUV4dHJhY3RvciA9IGZ1bmN0aW9uKGtleSwgaW5kZXgpIHsgcmV0dXJuIGRhdGFba2V5XSB9LFxuICAvKipcbiAgKiBIb3cgdG8gc29ydCB0aGUgYmFycyAtIGlmIHtAbGluayBiYXIjZ3JvdXBpbmd9IGlzIG5vdCBwcm92aWRlZC5cbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbc29ydGluZ0Z1bmN0aW9uPWZ1bmN0aW9uKGtleUEsIGtleUIpIHtyZXR1cm4gZDMuZGVzY2VuZGluZyhkYXRhW2tleUFdLCBkYXRhW2tleUJdKX1dXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oa2V5QSwga2V5Qikge3JldHVybiBkMy5hc2NlbmRpbmcoa2V5QSwga2V5Qil9LFxuICAvKipcbiAgKiBEZWZhdWx0IHNwYWNlIGZvciB0aGUgc3BhY2VyIChwZXJjZW50YWdlKSBvZiBtYWluIGRpbWVuc2lvbiBnaXZlbiB0aGUgb3JpZW50YXRpb25cbiAgKiAoc2VlIHtAbGluayBsZWdlbmQjb3JpZW50fSksIHdoZXJlIHtAbGluayBsZWdlbmQjb3JpZW50fT1cImhvcml6b250YWxcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgbGVnZW5kI3NwYWNlWH0gYW5kIHdoZXJlIHtAbGluayBsZWdlbmQjb3JpZW50fT1cInZlcnRpY2FsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGxlZ2VuZCNzcGFjZVl9IGJldHdlZW4gYmFyc1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbb2JqZWN0U3BhY2VyPTAuMDVdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0U3BhY2VyID0gMC4wNSxcbiAgLyoqXG4gICogVGhlIG1pbmltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmVcbiAgKiBAcGFyYW0ge251bWJlcn0gW21pbk9iamVjdFNpemU9NTBdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbWluT2JqZWN0U2l6ZSA9IDEwLFxuICAvKipcbiAgKiBUaGUgbWF4aW11bSBzaXplIHRoYXQgYW4gb2JqZWN0IGNhbiBiZVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbbWF4T2JqZWN0U2l6ZT0xMDBdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbWF4T2JqZWN0U2l6ZSA9IDEwMCxcblxuICAvKipcbiAgKiBUaGUgc3Ryb2tlIHdpZHRoIG9mIHRoZSBiYXJzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtiYXJTdHJva2VXaWR0aD0yXVxuICAqIEBtZW1iZXJvZiBsZWdlbmQjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJ1YmJsZVN0cm9rZVdpZHRoID0gMixcbiAgLyoqXG4gICogSW5zdGFuY2Ugb2YgQ29sb3JGdW5jdGlvblxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtjb2xvckZ1bmN0aW9uID0gY29sb3JGdW5jdGlvbigpXVxuICAqIEBtZW1iZXJvZiBsZWdlbmQjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGNvbG9yRnVuY3Rpb24gPSBDRigpLFxuXG4gIC8qKlxuICAqIENvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kXG4gICogQHBhcmFtIHtzdHJpbmd9IFtiYWNrZ3JvdW5kRmlsbD1cInRyYW5zcGFyZW50XCJdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgYmFja2dyb3VuZEZpbGwgPSAndHJhbnNwYXJlbnQnLFxuICAvKipcbiAgKiBOYW1lc3BhY2UgZm9yIGFsbCBpdGVtcyBtYWRlIGJ5IHRoaXMgaW5zdGFuY2Ugb2YgbGVnZW5kXG4gICogQHBhcmFtIHtzdHJpbmd9IFtuYW1lc3BhY2U9XCJkM3NtLWxlZ2VuZFwiXVxuICAqIEBtZW1iZXJvZiBsZWdlbmQjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG5hbWVzcGFjZSA9ICdkM3NtLWxlZ2VuZCcsXG4gIC8qKlxuICAqIENsYXNzIG5hbWUgZm9yIGxlZ2VuZCBjb250YWluZXIgKDxnPiBlbGVtZW50KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbb2JqZWN0Q2xhc3M9XCJsZWdlbmRcIl1cbiAgKiBAbWVtYmVyb2YgbGVnZW5kI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvYmplY3RDbGFzcyA9ICdsZWdlbmQnLFxuXG4gIC8qKlxuICAqIER1cmF0aW9uIG9mIGFsbCB0cmFuc2l0aW9ucyBvZiB0aGlzIGVsZW1lbnRcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RyYW5zaXRpb25EdXJhdGlvbj0xMDAwXVxuICAqIEBtZW1iZXJvZiBsZWdlbmQjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRyYW5zaXRpb25EdXJhdGlvbiA9IDEwMDAsXG4gIC8qKlxuICAqIEVhc2luZyBmdW5jdGlvbiBmb3IgdHJhbnNpdGlvbnNcbiAgKiBAcGFyYW0ge2QzLmVhc2V9IFtlYXNlRnVuYz1kMy5lYXNlRXhwXVxuICAqIEBtZW1iZXJvZiBsZWdlbmQjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGVhc2VGdW5jID0gZDMuZWFzZUV4cFxuXG5cbiAgbGVnZW5kLmNhdGVnb3JpZXMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNhdGVnb3JpZXM9XywgbGVnZW5kKSA6IGNhdGVnb3JpZXMgfTtcblxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBzZWxlY3Rpb24gaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgZDMuc2VsZWN0aW9ufVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNlbGVjdGlvbiA9IHNlbGVjdGlvblxuICAgKi9cbiAgbGVnZW5kLnNlbGVjdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2VsZWN0aW9uID0gXywgbGVnZW5kKSA6IHNlbGVjdGlvbjsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZGF0YVxuICAgKiAoc2VlIHtAbGluayBsZWdlbmQjZGF0YX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgb2JqZWN0fVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgbGVnZW5kLmRhdGEgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRhdGEgPSBfLCBsZWdlbmQpIDogZGF0YTsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgb3JpZW50IG9mIHRoZSBiYXJzXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCNvcmllbnR9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2xlZ2VuZCB8IG9iamVjdH1cbiAgICogQG1lbWJlcm9mIGxlZ2VuZFxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGxlZ2VuZC5vcmllbnQgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9yaWVudCA9IF8sIGxlZ2VuZCkgOiBvcmllbnQ7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBsZWdlbmQjc3BhY2VYfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge2xlZ2VuZCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGxlZ2VuZFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVggPSB1bmRlZmluZWRcbiAgICovXG4gIGxlZ2VuZC5zcGFjZVggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWCA9IF8sIGxlZ2VuZCkgOiBzcGFjZVg7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiB2ZXJ0aWNhbCBzcGFjZSBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogKHNlZSB7QGxpbmsgbGVnZW5kI3NwYWNlWX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBudW1iZXIgPiAwXG4gICAqIEByZXR1cm5zIHtsZWdlbmQgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc3BhY2VZID0gdW5kZWZpbmVkXG4gICAqL1xuICBsZWdlbmQuc3BhY2VZID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVkgPSBfLCBsZWdlbmQpIDogc3BhY2VZOyB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB3aGV0aGVyIG9yIG5vdCBsZWdlbmQgaXMgYWxsb3dlZCB0byBnbyBiZXlvbmQgc3BlY2lmaWVkIGRpbWVuc2lvbnNcbiAgICogKHNlZSB7QGxpbmsgbGVnZW5kI3NwYWNlWH0pXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2xlZ2VuZCB8IGJvb2xlYW59XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3ZlcmZsb3dRID0gZmFsc2VcbiAgICovXG4gIGxlZ2VuZC5vdmVyZmxvd1EgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG92ZXJmbG93USA9IF8sIGxlZ2VuZCkgOiBvdmVyZmxvd1E7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgZ3JvdXBpbmcgb2YgdGhlIGJhcnNcbiAgICogKHNlZSB7QGxpbmsgbGVnZW5kI2dyb3VwaW5nfSlcbiAgICogQHBhcmFtIHtBcnJheVtdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgQXJyYXlbXX1cbiAgICogQG1lbWJlcm9mIGxlZ2VuZFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBncm91cGluZyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgbGVnZW5kLmdyb3VwaW5nID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChncm91cGluZyA9IF8sIGxlZ2VuZCkgOiBncm91cGluZzsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB2YWx1ZUV4dHJhY3RvclxuICAgKiAoc2VlIHtAbGluayBsZWdlbmQjdmFsdWVFeHRyYWN0b3J9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGluZGV4KSB7IHJldHVybiBkYXRhW2tleV0gfSxcbiAgICovXG4gIGxlZ2VuZC52YWx1ZUV4dHJhY3RvciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodmFsdWVFeHRyYWN0b3IgPSBfLCBsZWdlbmQpIDogdmFsdWVFeHRyYWN0b3I7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgc29ydGluZ0Z1bmN0aW9uXG4gICAqIChzZWUge0BsaW5rIGJhciNzb3J0aW5nRnVuY3Rpb259KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YmFyIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBiYXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oa2V5QSwga2V5Qikge3JldHVybiBkMy5kZXNjZW5kaW5nKGRhdGFba2V5QV0sIGRhdGFba2V5Ql0pfSxcbiAgICovXG4gIGxlZ2VuZC5zb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNvcnRpbmdGdW5jdGlvbiA9IF8sIGxlZ2VuZCkgOiBzb3J0aW5nRnVuY3Rpb247IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyBvYmplY3RTcGFjZXJcbiAgICogKHNlZSB7QGxpbmsgbGVnZW5kI29iamVjdFNwYWNlcn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG9iamVjdFNwYWNlciA9IDAuMDVcbiAgICovXG4gIGxlZ2VuZC5vYmplY3RTcGFjZXIgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNwYWNlciA9IF8sIGxlZ2VuZCkgOiBvYmplY3RTcGFjZXI7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbWluT2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayBsZWdlbmQjbWluT2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1pbk9iamVjdFNpemUgPSA1MFxuICAgKi9cbiAgbGVnZW5kLm1pbk9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1pbk9iamVjdFNpemUgPSBfLCBsZWdlbmQpIDogbWluT2JqZWN0U2l6ZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBtYXhPYmplY3RTaXplXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCNtYXhPYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtsZWdlbmQgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbWF4T2JqZWN0U2l6ZSA9IDEwMFxuICAgKi9cbiAgbGVnZW5kLm1heE9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1heE9iamVjdFNpemUgPSBfLCBsZWdlbmQpIDogbWF4T2JqZWN0U2l6ZTsgfTtcblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGJhclN0cm9rZVdpZHRoXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCNiYXJTdHJva2VXaWR0aH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGJhclN0cm9rZVdpZHRoID0gMlxuICAgKi9cbiAgbGVnZW5kLmJ1YmJsZVN0cm9rZVdpZHRoID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChidWJibGVTdHJva2VXaWR0aCA9IF8sIGxlZ2VuZCkgOiBidWJibGVTdHJva2VXaWR0aDsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBjb2xvckZ1bmN0aW9uXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCNjb2xvckZ1bmN0aW9ufSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtsZWdlbmQgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24oKVxuICAgKi9cbiAgbGVnZW5kLmNvbG9yRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvbG9yRnVuY3Rpb24gPSBfLCBsZWdlbmQpIDogY29sb3JGdW5jdGlvbjsgfTtcblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGJhY2tncm91bmRGaWxsXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCNiYWNrZ3JvdW5kRmlsbH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGJhY2tncm91bmRGaWxsID0gJ3RyYW5zcGFyZW50J1xuICAgKi9cbiAgbGVnZW5kLmJhY2tncm91bmRGaWxsID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChiYWNrZ3JvdW5kRmlsbCA9IF8sIGxlZ2VuZCkgOiBiYWNrZ3JvdW5kRmlsbDsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBuYW1lc3BhY2VcbiAgICogKHNlZSB7QGxpbmsgbGVnZW5kI25hbWVzcGFjZX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG5hbWVzcGFjZSA9ICdkM3NtLWxlZ2VuZCdcbiAgICovXG4gIGxlZ2VuZC5uYW1lc3BhY2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG5hbWVzcGFjZSA9IF8sIGxlZ2VuZCkgOiBuYW1lc3BhY2U7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgb2JqZWN0Q2xhc3NcbiAgICogKHNlZSB7QGxpbmsgbGVnZW5kI29iamVjdENsYXNzfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtsZWdlbmQgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0Q2xhc3MgPSAndGljay1ncm91cCdcbiAgICovXG4gIGxlZ2VuZC5vYmplY3RDbGFzcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q2xhc3MgPSBfLCBsZWdlbmQpIDogb2JqZWN0Q2xhc3M7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdHJhbnNpdGlvbkR1cmF0aW9uXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCN0cmFuc2l0aW9uRHVyYXRpb259KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2xlZ2VuZCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGxlZ2VuZFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwXG4gICAqL1xuICBsZWdlbmQudHJhbnNpdGlvbkR1cmF0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0cmFuc2l0aW9uRHVyYXRpb24gPSBfLCBsZWdlbmQpIDogdHJhbnNpdGlvbkR1cmF0aW9uOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGVhc2VGdW5jXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCNlYXNlRnVuY30pXG4gICAqIEBwYXJhbSB7ZDMuZWFzZX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2xlZ2VuZCB8IGQzLmVhc2V9XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwXG4gICAqL1xuICBsZWdlbmQuZWFzZUZ1bmMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGVhc2VGdW5jID0gXywgbGVnZW5kKSA6IGVhc2VGdW5jOyB9O1xuXG5cbiAgZnVuY3Rpb24gbGVnZW5kKCkge1xuICAgIHZhciBob3Jpem9udGFsUSA9IChvcmllbnQgPT0gJ2hvcml6b250YWwnKSA/IHRydWUgOiBmYWxzZVxuICAgIHZhciB2ZXJ0aWNhbFEgPSAhaG9yaXpvbnRhbFFcbiAgICAvLyBiYWNrZ3JvdW5kIGNsaXBpbmcgcmVjdGFuZ2xlXG4gICAgdmFyIGJnY3BSZWN0ID0ge3g6MCwgeTowLCB3aWR0aDogc3BhY2VYLCBoZWlnaHQ6c3BhY2VZfVxuICAgIHZhciBjb250YWluZXIgPSBzZXR1cENvbnRhaW5lciggc2VsZWN0aW9uLCBuYW1lc3BhY2UsIGJnY3BSZWN0LCBiYWNrZ3JvdW5kRmlsbCApO1xuXG5cbiAgICBjb2xvckZ1bmN0aW9uLmRhdGFFeHRlbnQoWzAsIGNhdGVnb3JpZXMubGVuZ3RoIC0gMV0pXG4gICAgLmNvbG9yQnkoJ2NhdGVnb3JpZXMnKVxuICAgIC5jYXRlZ29yeUV4dHJhY3RvcihmdW5jdGlvbihrLCB2LCBpKXtyZXR1cm4gdn0pXG5cbiAgICB2YXIgciA9IE1hdGgubWluKHNwYWNlWCwgc3BhY2VZKSAvIDJcbiAgICB2YXIgbnVtYmVyT2ZPYmplY3RzID0gY2F0ZWdvcmllcy5sZW5ndGhcblxuICAgIC8vIGlmIGdyb3VwaW5nIGlzIHVuZGVmaW5lZCBzb3J0IGJhcktleXMgYnkgc29ydGluZ0Z1bmN0aW9uXG4gICAgdmFyIG9yZGVyZWQgPSAoZ3JvdXBpbmcgPT0gdW5kZWZpbmVkKSA/IGNhdGVnb3JpZXMuc29ydChzb3J0aW5nRnVuY3Rpb24pIDogZ3JvdXBpbmdcbiAgICAvLyBvcmRlcmVkIG1pZ2h0IGJlIG5lc3RlZCBkZXBlbmRpbmcgb24gZ3JvdXBpbmdcbiAgICB2YXIgY2F0S2V5cyA9IGZsYXR0ZW4ob3JkZXJlZClcblxuICAgIHZhciBzcGFjZSA9IGhvcml6b250YWxRID8gc3BhY2VYIDogc3BhY2VZXG4gICAgLy8gY2FsY3VsYXRlIG9iamVjdCBzaXplXG4gICAgdmFyIG9iamVjdFNpemUgPSBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0KHNwYWNlLCBudW1iZXJPZk9iamVjdHMsIG1pbk9iamVjdFNpemUsIG1heE9iamVjdFNpemUsIG9iamVjdFNwYWNlciwgb3ZlcmZsb3dRKVxuICAgIC8vIGNhbGN1bGF0ZSBzcGFjZXIgc2l6ZSBpZiBuZWVkZWRcbiAgICB2YXIgc3BhY2VyU2l6ZSA9IGNhbGN1bGF0ZVdpZHRoT2ZTcGFjZXIoY2F0S2V5cywgc3BhY2UsIG9iamVjdFNpemUsIG51bWJlck9mT2JqZWN0cywgb2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgLy8gbWFrZSB0aGUgbmVzdGVkIGdyb3Vwc1xuICAgIHZhciBzcGFjZXJGdW5jdGlvbiA9IGdyb3VwaW5nU3BhY2VyKClcbiAgICAuaG9yaXpvbnRhbFEoaG9yaXpvbnRhbFEpLnNjYWxlKHNjYWxlKS5tb3ZlYnkoJ2NhdGVnb3J5JykubnVtYmVyT2ZPYmplY3RzKG51bWJlck9mT2JqZWN0cylcbiAgICAub2JqZWN0Q2xhc3Mob2JqZWN0Q2xhc3MpLm9iamVjdFNpemUob2JqZWN0U2l6ZSkuc3BhY2VyU2l6ZShzcGFjZXJTaXplKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlRnVuYyhlYXNlRnVuYylcbiAgICAubmFtZXNwYWNlKG5hbWVzcGFjZSlcblxuICAgIHNwYWNlckZ1bmN0aW9uKGNvbnRhaW5lciwgb3JkZXJlZCwgMClcbiAgICB2YXIgciA9IE1hdGgubWluKG9iamVjdFNpemUsIHNwYWNlWCwgc3BhY2VZKSAvIDIgLSBidWJibGVTdHJva2VXaWR0aFxuXG4gICAgY29udGFpbmVyLnNlbGVjdEFsbCgnZzpub3QoLnRvLXJlbW92ZSkuJytvYmplY3RDbGFzcykuZWFjaChmdW5jdGlvbihjYXQsIGkpIHtcbiAgICAgIHZhciB0ID0gZDMuc2VsZWN0KHRoaXMpXG4gICAgICB2YXIgYyA9IHNhZmVTZWxlY3QodCwgJ2NpcmNsZScpXG4gICAgICB2YXIgZmlsbENvbG9yID0gY29sb3JGdW5jdGlvbih1bmRlZmluZWQsIGNhdCwgaSwgJ2ZpbGwnKSwgLy8gcHJldmVudCBkdXBsaWNhdGUgY29tcHV0YXRpb25cbiAgICAgIHN0cm9rZUNvbG9yID0gY29sb3JGdW5jdGlvbih1bmRlZmluZWQsIGNhdCwgaSwgICdzdHJva2UnKVxuXG4gICAgICB2YXIgY3ggPSBob3Jpem9udGFsUVxuICAgICAgICA/IHIrYnViYmxlU3Ryb2tlV2lkdGhcbiAgICAgICAgOiAoc3BhY2VYIC0gcioyKSAvIDIgKyByXG4gICAgICB2YXIgY3kgPSB2ZXJ0aWNhbFFcbiAgICAgICAgPyByK2J1YmJsZVN0cm9rZVdpZHRoXG4gICAgICAgIDogKHNwYWNlWCAtIHIqMikgLyAyICsgclxuXG4gICAgICBjLmF0dHIoXCJyXCIsIHIpXG4gICAgICAuYXR0cignY3gnLCBjeClcbiAgICAgIC5hdHRyKCdjeScsIGN5KVxuICAgICAgLmF0dHIoJ2ZpbGwnLCBmaWxsQ29sb3IpXG4gICAgICAuYXR0cignc3Ryb2tlJywgc3Ryb2tlQ29sb3IpXG4gICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgYnViYmxlU3Ryb2tlV2lkdGgpXG5cbiAgICAgIHZhciB0ZXh0ID0gc2FmZVNlbGVjdCh0LCAndGV4dCcpXG4gICAgICB0ZXh0LnRleHQoY2F0KVxuICAgICAgLmF0dHIoJ3RleHQtYW5jaG9yJywgJ21pZGRsZScpXG4gICAgICAuYXR0cihcInRyYW5zZm9ybVwiLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBjeCxcbiAgICAgICAgeSA9IGN5ICsgdGV4dC5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0IC8gNCxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcblxuICAgIH0pXG5cblxuICB9XG5cbiAgcmV0dXJuIGxlZ2VuZFxufVxuIiwiaW1wb3J0IHtoeXBlbmF0ZSwgc2FmZVNlbGVjdCwgbW9kaWZ5SGV4aWRlY2ltYWxDb2xvckx1bWluYW5jZSwgZXh0cmFjdFZpb2xpblZhbHVlcywgcXVhcnRpbGVzfSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtzZXR1cENvbnRhaW5lciwgY2FsY3VsYXRlV2lkdGhPZk9iamVjdCwgY2FsY3VsYXRlV2lkdGhPZlNwYWNlcn0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQge3VuaXF1ZSwgaGFzUSwgZmxhdHRlbiwgd2hpY2hCaW59IGZyb20gJy4vYXJyYXktZnVuY3Rpb25zJztcbmltcG9ydCB7Z3JvdXBpbmdTcGFjZXJ9IGZyb20gJy4vZ3JvdXBpbmctc3BhY2VyJztcbmltcG9ydCB7Y29sb3JGdW5jdGlvbiBhcyBDRn0gZnJvbSAnLi9jb2xvci1mdW5jdGlvbic7XG5pbXBvcnQge3Rvb2x0aXAgYXMgVFRpcH0gZnJvbSAnLi90b29sdGlwJztcbmltcG9ydCB7bGFzc299IGZyb20gJy4vbGFzc28nO1xuaW1wb3J0ICcuL2QzLXByb3RvdHlwZXMnO1xuXG5leHBvcnQgZnVuY3Rpb24gbGFzc29XaWRnZXQoIHNlbGVjdGlvbiApIHtcbiAgdmFyXG4gIG5hbWVzcGFjZSA9ICdkM3NtLWxhc3NvJyxcbiAgc2VsZWN0aW9uID0gc2VsZWN0aW9uLFxuICBzdmcsXG4gIGNoYXJ0Q29udGFpbmVyLFxuICBvYmplY3RDb250YWluZXIsXG4gIG9iamVjdENsYXNzLFxuICBsYXNzb0xpbmUgPSBkMy5saW5lKClcbiAgLngoZnVuY3Rpb24oZCwgaSl7cmV0dXJuIGRbMF19KVxuICAueShmdW5jdGlvbihkLCBpKXtyZXR1cm4gZFsxXX0pXG4gIC5jdXJ2ZShkMy5jdXJ2ZUxpbmVhckNsb3NlZCksXG4gIHBhdGgsXG4gIGNvbG9yRnVuY3Rpb24gPSBDRigpLFxuICBtYXhOdW1iZXJPZkdyb3VwcyxcbiAgZGF0YUV4dHJhY3RvcixcbiAgeFNjYWxlLFxuICB5U2NhbGVcblxuICBmdW5jdGlvbiBvbkVycm9yKG1zZywgc3R5bGUpe1xuICAgIGNvbnNvbGUubG9nKG1zZywgc3R5bGUpXG4gIH1cbiAgLy8gc2V0dXAgdGhlIGNvbnRhaW5lclxuICBzZXR1cERhdGFzZWxlY3RDb250YWluZXIoKVxuXG4gIGxhc3NvV2lkZ2V0Lm9iamVjdENsYXNzID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q2xhc3M9Jy4nK18ucmVwbGFjZSgnLicsJycpLCBsYXNzb1dpZGdldCkgOiBvYmplY3RDbGFzc31cbiAgbGFzc29XaWRnZXQuc3ZnID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3ZnPV8sIGxhc3NvV2lkZ2V0KSA6IHN2Z31cbiAgbGFzc29XaWRnZXQuc3VibWl0ID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3VibWl0PV8sIGxhc3NvV2lkZ2V0KSA6IHN1Ym1pdH1cbiAgbGFzc29XaWRnZXQubWF4TnVtYmVyT2ZHcm91cHMgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChtYXhOdW1iZXJPZkdyb3Vwcz1fLCBsYXNzb1dpZGdldCkgOiBtYXhOdW1iZXJPZkdyb3Vwc31cbiAgbGFzc29XaWRnZXQub25FcnJvciA9IGZ1bmN0aW9uKF8pe3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9uRXJyb3I9XywgbGFzc29XaWRnZXQpIDogb25FcnJvcn1cbiAgbGFzc29XaWRnZXQub2JqZWN0Q29udGFpbmVyID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q29udGFpbmVyPV8sIGxhc3NvV2lkZ2V0KSA6IG9iamVjdENvbnRhaW5lcn1cbiAgbGFzc29XaWRnZXQuY2hhcnRDb250YWluZXIgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjaGFydENvbnRhaW5lcj1fLCBsYXNzb1dpZGdldCkgOiBjaGFydENvbnRhaW5lcn1cbiAgbGFzc29XaWRnZXQuZGF0YUV4dHJhY3RvciA9IGZ1bmN0aW9uKF8pe3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRhdGFFeHRyYWN0b3I9XywgbGFzc29XaWRnZXQpIDogZGF0YUV4dHJhY3Rvcn1cbiAgbGFzc29XaWRnZXQueFNjYWxlID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeFNjYWxlPV8sIGxhc3NvV2lkZ2V0KSA6IHhTY2FsZX1cbiAgbGFzc29XaWRnZXQueVNjYWxlID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeVNjYWxlPV8sIGxhc3NvV2lkZ2V0KSA6IHlTY2FsZX1cblxuICBmdW5jdGlvbiBzdHlsZXMoKSB7XG4gICAgdmFyIHMgPSBkMy5zZWxlY3QoXCJodG1sXCIpLnNlbGVjdChcInN0eWxlLlwiK25hbWVzcGFjZSsnbGFzc28td2lkZ2V0JylcbiAgICBpZiAocy5lbXB0eSgpKSB7XG4gICAgICBkMy5zZWxlY3QoXCJodG1sXCIpLmFwcGVuZChcInN0eWxlXCIpXG4gICAgICAuY2xhc3NlZChuYW1lc3BhY2UrJ2xhc3NvLXdpZGdldCcsIHRydWUpXG4gICAgICAuaHRtbChcbiAgICAgICAgXCIuXCIraHlwZW5hdGUobmFtZXNwYWNlLCBcImRhdGEtdGFibGVcIikgKyBcIntcXFxuICAgICAgICAgIGhlaWdodDoxMDBweDtcXFxuICAgICAgICAgIG92ZXJmbG93OmF1dG87XFxcbiAgICAgICAgfVwiXG4gICAgICApXG4gICAgfVxuICB9XG5cblxuICBmdW5jdGlvbiBsYXNzb1dpZGdldCgpIHtcbiAgICBzdHlsZXMoKVxuXG4gIH1cblxuICBmdW5jdGlvbiBzdWJtaXQoZGF0YSkge1xuICAgIGNvbnNvbGUubG9nKGRhdGEpXG4gIH1cblxuICBmdW5jdGlvbiBwbHVzVGFiKHRhYkxpc3QpIHtcbiAgICB2YXIgdGFiID0gc2FmZVNlbGVjdCh0YWJMaXN0LCAnbGknLCBoeXBlbmF0ZShuYW1lc3BhY2UsICdwbHVzLXRhYicpKVxuICAgIC5jbGFzc2VkKCdtbC1hdXRvJywgdHJ1ZSlcbiAgICAuY2xhc3NlZCgnbmF2LWl0ZW0nLCB0cnVlKVxuICAgIC5vbignY2xpY2snLCBtYWtlTmV3R3JvdXApLFxuXG4gICAgYW5jaG9yID0gc2FmZVNlbGVjdCh0YWIsICdhJywgJ25hdi1saW5rJyksXG4gICAgaWNvbiA9IHNhZmVTZWxlY3QoYW5jaG9yLCAnaScsICdmYScpXG4gICAgLmNsYXNzZWQoJ2ZhLXBsdXMgZmEtMnggdGV4dC1zdWNjZXNzJywgdHJ1ZSlcbiAgfVxuXG4gIGZ1bmN0aW9uIHNlbmRUYWIodGFiTGlzdCkge1xuICAgIHZhciB0YWIgPSBzYWZlU2VsZWN0KHRhYkxpc3QsICdsaScsIGh5cGVuYXRlKG5hbWVzcGFjZSwgJ3NlbmQtdGFiJykpXG4gICAgLmNsYXNzZWQoJ21sLWF1dG8nLCB0cnVlKVxuICAgIC5jbGFzc2VkKCduYXYtaXRlbScsIHRydWUpXG4gICAgLm9uKCdjbGljaycsIGNsaWNrU2VuZClcbiAgICAsXG5cbiAgICBhbmNob3IgPSBzYWZlU2VsZWN0KHRhYiwgJ2EnLCAnbmF2LWxpbmsnKSxcbiAgICBpY29uID0gc2FmZVNlbGVjdChhbmNob3IsICdpJywgJ2ZhJylcbiAgICAuY2xhc3NlZCgnZmEtcGFwZXItcGxhbmUtbyBmYS0yeCB0ZXh0LXByaW1hcnknLCB0cnVlKVxuICB9XG5cbiAgZnVuY3Rpb24gY2xpY2tTZW5kKCkge1xuICAgIHZhciBkYXRhID0gZ2F0aGVyRGF0YUxpc3RzKClcbiAgICBzdWJtaXQoZGF0YSlcbiAgfVxuXG4gIGZ1bmN0aW9uIGNsb3NlVGFiKHRhYkxpc3QpIHtcbiAgICB2YXIgdGFiID0gc2FmZVNlbGVjdCh0YWJMaXN0LCAnbGknLCBoeXBlbmF0ZShuYW1lc3BhY2UsICdjbG9zZS10YWInKSlcbiAgICAuY2xhc3NlZCgnbWwtYXV0bycsIHRydWUpXG4gICAgLmNsYXNzZWQoJ25hdi1pdGVtJywgdHJ1ZSlcbiAgICAub24oJ2NsaWNrJywgZnVuY3Rpb24oKXtcbiAgICAgIHZhciBtID0gZDMubW91c2UoZDMuc2VsZWN0KFwiaHRtbFwiKS5ub2RlKCkpXG4gICAgICBzZWxlY3Rpb24uc2VsZWN0KCdkaXYuY2FyZCcpLnN0eWxlKFwicG9zaXRpb25cIiwgJ3JlbGF0aXZlJylcbiAgICAgIC50cmFuc2l0aW9uKCkuZHVyYXRpb24oMTAwMClcbiAgICAgIC5lYXNlKGQzLmVhc2VCYWNrKVxuICAgICAgLnN0eWxlKCdsZWZ0Jywgd2luZG93Lm91dGVyV2lkdGggKydweCcpXG4gICAgICAucmVtb3ZlKClcbiAgICB9KVxuICAgICxcblxuICAgIGFuY2hvciA9IHNhZmVTZWxlY3QodGFiLCAnYScsICduYXYtbGluaycpLFxuICAgIGljb24gPSBzYWZlU2VsZWN0KGFuY2hvciwgJ2knLCAnZmEnKVxuICAgIC5jbGFzc2VkKCdmYS13aW5kb3ctY2xvc2UtbyBmYS0yeCB0ZXh0LWRhbmdlcicsIHRydWUpXG4gIH1cblxuXG5cbiAgZnVuY3Rpb24gc2V0dXBEYXRhc2VsZWN0Q29udGFpbmVyKCkge1xuICAgIHZhclxuICAgIGNhcmQgPSBzYWZlU2VsZWN0KHNlbGVjdGlvbiwgJ2RpdicsICdjYXJkJyksXG4gICAgY2FyZEhlYWRlciA9IHNhZmVTZWxlY3QoY2FyZCwgJ2RpdicsICdjYXJkLWhlYWRlcicpLFxuXG4gICAgdGFiTGlzdCA9IHNhZmVTZWxlY3QoY2FyZEhlYWRlciwgJ3VsJywgJ25hdicpXG4gICAgLmNsYXNzZWQoJ25hdi10YWJzIGNhcmQtaGVhZGVyLXRhYnMnLCB0cnVlKVxuICAgIC5jbGFzc2VkKGh5cGVuYXRlKG5hbWVzcGFjZSwgJ3RhYi1saXN0JyksIHRydWUpXG4gICAgLmF0dHIoJ3JvbGUnLCAndGFibGlzdCcpLFxuXG4gICAgY2FyZEJvZHkgPSBzYWZlU2VsZWN0KGNhcmQsICdkaXYnLCAnY2FyZC1ib2R5JyksXG4gICAgdGFiQ29udGVudCA9IHNhZmVTZWxlY3QoY2FyZEJvZHksICdkaXYnLCAndGFiLWNvbnRlbnQnKVxuICAgIC5jbGFzc2VkKGh5cGVuYXRlKG5hbWVzcGFjZSwgJ3RhYi1jb250ZW50JyksIHRydWUpLFxuXG4gICAgLy8gbGVmdFRhYnMgPSBzYWZlU2VsZWN0KHRhYkxpc3QsICdkaXYnLCAnbmF2IG1yLWF1dG8gbGVmdC1hbGlnbmVkLXRhYnMnKVxuICAgIHJpZ2h0VGFicyA9IHNhZmVTZWxlY3QodGFiTGlzdCwgJ2RpdicsICdyaWdodC1hbGlnbmVkLXRhYnMnKS5jbGFzc2VkKCduYXYgbWwtYXV0byAnLCB0cnVlKVxuXG4gICAgcGx1c1RhYihyaWdodFRhYnMpXG4gICAgc2VuZFRhYihyaWdodFRhYnMpXG4gICAgY2xvc2VUYWIocmlnaHRUYWJzKVxuICAgIHZhclxuICAgIGRlZmF1bHRUYWIgPSBzYWZlU2VsZWN0KHRhYkNvbnRlbnQsICdkaXYnLCAndGFiLXBhbmUnKVxuICAgIC5jbGFzc2VkKGh5cGVuYXRlKG5hbWVzcGFjZSwnZGVmYXVsdC10YWInKSwgdHJ1ZSlcbiAgICAuY2xhc3NlZChcImFjdGl2ZVwiLCB0cnVlKVxuICAgIC5jbGFzc2VkKCd0ZXh0LWxlZnQnLCB0cnVlKSxcblxuICAgIHAgPSBzYWZlU2VsZWN0KGRlZmF1bHRUYWIsICdkaXYnKVxuICAgIC5odG1sKFxuICAgICAgXCJDbGljayA8a2JkPjxpIGNsYXNzPSdmYSBmYS1wbHVzIHRleHQtc3VjY2Vzcyc+PC9pPjwva2JkPiB0byBhZGQgYSBuZXcgZ3JvdXAuPGJyPlwiK1xuICAgICAgXCJDbGljayA8a2JkPjxpIGNsYXNzPSdmYSBmYS1wYXBlci1wbGFuZS1vIHRleHQtcHJpbWFyeSc+PC9pPjwva2JkPiB0byBzdWJtaXQgZm9yIHJlLWFuYWx5c2lzLjxicj5cIitcbiAgICAgIFwiQ2xpY2sgPGtiZD48aSBjbGFzcz0nZmEgZmEtd2luZG93LWNsb3NlLW8gdGV4dC1kYW5nZXInPjwvaT48L2tiZD4gdG8gY2xvc2UgdGhlIGRhdGFzZWxlY3Qgd2lkZ2V0LlwiXG4gICAgKVxuICAgIC8vIC50ZXh0KCdDbGljayB0aGUgZ3JlZW4gcGx1cyB0byBhZGQgYSBuZXcgZ3JvdXAuJylcbiAgfVxuXG5cbiAgZnVuY3Rpb24gbWFrZVJlbW92ZUJ1dHRvbihwYW5lQnRuTGlzdCkge1xuICAgIHZhclxuICAgIGJ0biA9IHNhZmVTZWxlY3QocGFuZUJ0bkxpc3QsICdidXR0b24nLCAncmVtb3ZlLWJ0bicpXG4gICAgLmNsYXNzZWQoJ2J0biBidG4tZGFuZ2VyJywgdHJ1ZSlcbiAgICAub24oJ2NsaWNrJywgcmVtb3ZlQnRuQ2xpY2tUb1JlbW92ZSksXG4gICAgaSA9IHNhZmVTZWxlY3QoYnRuLCAnaScsICdmYScpLmNsYXNzZWQoJ2ZhLXRyYXNoLW8nLCB0cnVlKSxcbiAgICBzID0gc2FmZVNlbGVjdChidG4sICdzcGFuJykudGV4dCgnUmVtb3ZlIGdyb3VwJylcbiAgICByZXR1cm4gYnRuXG4gIH1cblxuICBmdW5jdGlvbiByZW1vdmVCdG5DbGlja1RvUmVtb3ZlKGQsIGkpIHtcbiAgICB2YXJcbiAgICB0YWIgPSBzZWxlY3Rpb24uc2VsZWN0KCcjJytoeXBlbmF0ZShuYW1lc3BhY2UsJ3RhYicsZCkpLFxuICAgIHBhbmUgPSBzZWxlY3Rpb24uc2VsZWN0KCcjJytoeXBlbmF0ZShuYW1lc3BhY2UsJ3RhYicsJ3BhbmUnLGQpKVxuXG4gICAgdGFiLnJlbW92ZSgpXG4gICAgcGFuZS5yZW1vdmUoKVxuXG4gICAgc2hvd1JlbWFpbmluZ1BhbmVzKClcbiAgICB1cGRhdGVUYWJBbmRQYW5lTnVtYmVycygpXG4gIH1cblxuXG4gIGZ1bmN0aW9uIHRvZ2dsZVBhbmVCeUlkKGlkKSB7XG4gICAgdmFyIHBhbmVzID0gc2VsZWN0aW9uLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCAndGFiLWNvbnRlbnQnKSlcbiAgICBwYW5lcy5zZWxlY3RBbGwoJ2Rpdi50YWItcGFuZScpXG4gICAgLmVhY2goZnVuY3Rpb24oZCwgaSl7XG4gICAgICBkMy5zZWxlY3QodGhpcykuY2xhc3NlZCgnYWN0aXZlIHNob3cnLCBkMy5zZWxlY3QodGhpcykuYXR0cignaWQnKSA9PSBpZClcbiAgICB9KVxuICB9XG5cbiAgZnVuY3Rpb24gaW5zZXJ0VGFiKHRhYnMsIG4pIHtcblxuICAgIC8vIHZhciBsaSA9IHRhYnMuaW5zZXJ0KFwibGlcIiwgJzpudGgtY2hpbGQoJysobikrJyknKVxuICAgIHZhciBsaSA9IHRhYnMuaW5zZXJ0KFwibGlcIiwgJy5yaWdodC1hbGlnbmVkLXRhYnMnKVxuICAgIC5jbGFzc2VkKCduYXYtaXRlbScsIHRydWUpXG4gICAgLmNsYXNzZWQoJ2FsZXJ0JywgdHJ1ZSlcbiAgICAuY2xhc3NlZCgnYWxlcnQtc2Vjb25kYXJ5JywgdHJ1ZSlcbiAgICAuY2xhc3NlZCgnYWxlcnQtZGlzbWlzc2FibGUnLCB0cnVlKVxuICAgIC5jbGFzc2VkKCdmYWRlJywgdHJ1ZSlcbiAgICAuY2xhc3NlZCgnc2hvdycsIHRydWUpXG4gICAgLy8gLmNsYXNzZWQoJ21yLWF1dG8nLCB0cnVlKVxuICAgIC5hdHRyKFwicm9sZVwiLCAnYWxlcnQnKVxuICAgIC5hdHRyKFwiaWRcIiwgaHlwZW5hdGUobmFtZXNwYWNlLCd0YWInLG4pKVxuICAgIC5jbGFzc2VkKGh5cGVuYXRlKG5hbWVzcGFjZSwndGFiJyksIHRydWUpXG5cbiAgICB2YXIgYSA9IHNhZmVTZWxlY3QobGksICdhJylcbiAgICAuYXR0cignZGF0YS10b2dnbGUnLCAndGFiJylcbiAgICAudGV4dCgnR3JvdXAgJyArIG4pXG4gICAgLmF0dHIoJ2hyZWYnLCAnIycraHlwZW5hdGUobmFtZXNwYWNlLCd0YWInLCdwYW5lJyxuKSlcbiAgICAub24oJ2RibGNsaWNrJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgICAgdC5hdHRyKCdjb250ZW50ZWRpdGFibGUnLCB0cnVlKVxuICAgICAgZDMuc2VsZWN0KHQubm9kZSgpLnBhcmVudE5vZGUpXG4gICAgICAuY2xhc3NlZCgnYWxlcnQtc2Vjb25kYXJ5JywgZmFsc2UpXG4gICAgICAuY2xhc3NlZCgnYWxlcnQtd2FybmluZycsIHRydWUpXG5cbiAgICAgIC8vIGQzLnNlbGVjdChcImh0bWxcIikub24oXCJjbGlja1wiLCBkaXNwYXRjaEJsdXIpXG4gICAgICAvL1xuICAgICAgLy8gZnVuY3Rpb24gZGlzcGF0Y2hCbHVyKGQsIGkpIHtcbiAgICAgIC8vICAgaWYgKGQzLmV2ZW50LnRhcmdldCAhPSBkMy5zZWxlY3QodGhpcykpIHtcbiAgICAgIC8vICAgICBkMy5zZWxlY3QodGhpcykuZGlzcGF0Y2goXCJibHVyXCIpXG4gICAgICAvLyAgIH1cbiAgICAgIC8vIH1cblxuXG4gICAgfSlcbiAgICAub24oJ2JsdXInLCBmdW5jdGlvbihkLCBpKXtcblxuICAgICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcylcbiAgICAgIHQuYXR0cignY29udGVudGVkaXRhYmxlJywgZmFsc2UpXG4gICAgICBkMy5zZWxlY3QodC5ub2RlKCkucGFyZW50Tm9kZSlcbiAgICAgIC5jbGFzc2VkKCdhbGVydC1zZWNvbmRhcnknLCB0cnVlKVxuICAgICAgLmNsYXNzZWQoJ2FsZXJ0LXdhcm5pbmcnLCBmYWxzZSlcblxuICAgIH0pXG4gICAgLm9uKCdpbnB1dCcsIGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcylcbiAgICAgIHZhciB0eHQgPSB0LnRleHQoKVxuICAgICAgZDMuc2VsZWN0KHQuYXR0cignaHJlZicpKS5zZWxlY3QoXCJwLmxlYWRcIikudGV4dCh0eHQpXG4gICAgfSlcblxuXG4gICAgcmV0dXJuIGxpXG4gIH1cblxuICBmdW5jdGlvbiBtYWtlVGFiUGFuZShwYW5lcywgbikge1xuICAgIHZhciBwYW5lID0gcGFuZXMuYXBwZW5kKCdkaXYnKVxuICAgIC5kYXR1bShuKVxuICAgIC5hdHRyKCdyb2xlJywgJ3RhYnBhbmVsJylcbiAgICAuY2xhc3NlZCgndGFiLXBhbmUnLCB0cnVlKVxuICAgIC5jbGFzc2VkKCd0ZXh0LWxlZnQnLCB0cnVlKVxuICAgIC5jbGFzc2VkKGh5cGVuYXRlKG5hbWVzcGFjZSwndGFiJywncGFuZScpLCB0cnVlKVxuICAgIC5hdHRyKCdpZCcsIGh5cGVuYXRlKG5hbWVzcGFjZSwndGFiJywncGFuZScsbikpXG4gICAgcmV0dXJuIHBhbmVcbiAgfVxuXG4gIGZ1bmN0aW9uIHBvcHVsYXRlUGFuZShwYW5lLCBuKSB7XG4gICAgdmFyXG4gICAgbGVhZCA9IHNhZmVTZWxlY3QocGFuZSwgJ3AnLCAnbGVhZCcpLnRleHQoJ0dyb3VwICcrbiksXG5cbiAgICB0YWJsZUNvbnRhaW5lciA9IHNhZmVTZWxlY3QocGFuZSwgJ2RpdicsICd0YWJsZS1yZXNwb25zaXZlJylcbiAgICAuYXR0cihcImNsYXNzXCIsIGh5cGVuYXRlKG5hbWVzcGFjZSwgXCJkYXRhLXRhYmxlXCIpKSxcblxuICAgIHRhYmxlID0gc2FmZVNlbGVjdCh0YWJsZUNvbnRhaW5lciwgXCJ0YWJsZVwiLCBcInRhYmxlXCIpXG4gICAgLmNsYXNzZWQoXCJ0YWJsZS1zbVwiLCB0cnVlKS5jbGFzc2VkKFwidGFibGUtaG92ZXJcIiwgdHJ1ZSksXG5cbiAgICBjYXB0aW9uID0gc2FmZVNlbGVjdCh0YWJsZSwgXCJjYXB0aW9uXCIsIFwiY2FwdGlvblwiKS5odG1sKFwiTGlzdCBvZiBzZWxlY3RlZFwiKSxcblxuICAgIGJ0bnMgPSBzYWZlU2VsZWN0KHBhbmUsICdkaXYnLCAndGV4dC1yaWdodCcpLFxuXG4gICAgY04gPSBuICUgY29sb3JGdW5jdGlvbi5jb2xvcnMoKS5sZW5ndGhcbiAgICBpZiAobiAlIDIgIT0gMCkgeyBjTiA9IChjb2xvckZ1bmN0aW9uLmNvbG9ycygpLmxlbmd0aCAtIDEpIC0gY04gfVxuXG5cblxuXG5cbiAgICB2YXIgbGFzc29CdG4gPSBtYWtlTGFzc29CdXR0b24oYnRucylcbiAgICB2YXIgY3VycmVudExhc3NvID0gbWFrZUxhc3NvRnVuY3Rpb24obiwgY29sb3JGdW5jdGlvbi5jb2xvcnMoKVtjTl0pXG4gICAgdmFyIGNsZWFyQnRuID0gbWFrZUNsZWFyQnV0dG9uKGJ0bnMpXG5cbiAgICBiaW5kQnV0dG9ucyhsYXNzb0J0biwgY2xlYXJCdG4sIGN1cnJlbnRMYXNzbywgdGFibGUpXG5cbiAgICB2YXIgcmVtb3ZlQnRuID0gbWFrZVJlbW92ZUJ1dHRvbihidG5zKVxuXG4gICAgbGVhZC5vbihcIm1vdXNlb3ZlclwiLCBmdW5jdGlvbigpe1xuICAgICAgY3VycmVudExhc3NvLmRyYXcoKVxuICAgIH0pXG4gICAgbGVhZC5vbihcIm1vdXNlb3V0XCIsIGZ1bmN0aW9uKCl7XG4gICAgICBjdXJyZW50TGFzc28ucmVtb3ZlKClcbiAgICB9KVxuXG4gIH1cblxuICBmdW5jdGlvbiBtYWtlTGFzc29CdXR0b24oYnRucykge1xuICAgIHZhciBidG4gPSBzYWZlU2VsZWN0KGJ0bnMsICdidXR0b24nLCAnbGFzc28tYnRuJylcbiAgICAuY2xhc3NlZCgnYnRuIGJ0bi1pbmZvJywgdHJ1ZSlcbiAgICAuY2xhc3NlZChuYW1lc3BhY2UsIHRydWUpXG4gICAgLy8gLmRhdHVtKFtsYXNzb10pXG4gICAgdmFyIGkgPSBzYWZlU2VsZWN0KGJ0biwgJ2knLCAnZmEnKS5jbGFzc2VkKCdmYS1oYW5kLXBvaW50ZXItbycsIHRydWUpXG4gICAgdmFyIHMgPSBzYWZlU2VsZWN0KGJ0biwgJ3NwYW4nKS50ZXh0KCdMYXNzbyBzZWxlY3QnKVxuICAgIHJldHVybiBidG5cblxuICB9XG5cbiAgZnVuY3Rpb24gbWFrZUNsZWFyQnV0dG9uKGJ0bnMpIHtcbiAgICB2YXIgYnRuID0gc2FmZVNlbGVjdChidG5zLCAnYnV0dG9uJywgJ2NsZWFyLWJ0bicpXG4gICAgLmNsYXNzZWQoJ2J0biBidG4tbGlnaHQnLCB0cnVlKVxuICAgIC5jbGFzc2VkKG5hbWVzcGFjZSwgdHJ1ZSlcbiAgICB2YXIgaSA9IHNhZmVTZWxlY3QoYnRuLCAnaScsICdmYScpLmNsYXNzZWQoJ2ZhLWVyYXNlcicsIHRydWUpXG4gICAgdmFyIHMgPSBzYWZlU2VsZWN0KGJ0biwgJ3NwYW4nKS50ZXh0KCdDbGVhciBzZWxlY3Rpb24nKVxuICAgIHJldHVybiBidG5cbiAgfVxuXG4gIGZ1bmN0aW9uIG1ha2VMYXNzb0Z1bmN0aW9uKGluc3RhbmNlLCBjb2xvcikge1xuICAgIHZhciBjdXJyZW50TGFzc28gPSBsYXNzbygpXG4gICAgLm5hbWVzcGFjZShuYW1lc3BhY2UpXG4gICAgLnN2ZyhzdmcpXG4gICAgLm9iamVjdENsYXNzKG9iamVjdENsYXNzKVxuICAgIC5jaGFydENvbnRhaW5lcihjaGFydENvbnRhaW5lcilcbiAgICAub2JqZWN0Q29udGFpbmVyKG9iamVjdENvbnRhaW5lcilcbiAgICAuaW5zdGFuY2UoaW5zdGFuY2UpXG4gICAgLmNvbG9yKGNvbG9yKVxuICAgIC55U2NhbGUoeVNjYWxlKVxuICAgIC54U2NhbGUoeFNjYWxlKVxuXG4gICAgcmV0dXJuIGN1cnJlbnRMYXNzb1xuICB9XG5cbiAgZnVuY3Rpb24gYmluZEJ1dHRvbnMobGFzc29CdG4sIGNsZWFyQnRuLCBjdXJyZW50TGFzc28sIHRhYmxlKSB7XG4gICAgY3VycmVudExhc3NvLmV2ZW50Q2F0Y2hlcihsYXNzb0J0bilcbiAgICBsYXNzb0J0bi5ub2RlKCkuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGxhc3NvQnRuVG9nZ2xlKVxuXG4gICAgbGFzc29CdG4uZGF0dW0oW2N1cnJlbnRMYXNzb10pXG4gICAgLm9uKGh5cGVuYXRlKG5hbWVzcGFjZSwncmVuZGVyJyksIGZ1bmN0aW9uKCl7XG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKS5kYXR1bSgpWzBdLmRyYXcoKVxuICAgIH0pXG4gICAgLm9uKGh5cGVuYXRlKG5hbWVzcGFjZSxcImRyYWdcIiksIGZ1bmN0aW9uKGxhcyl7XG4gICAgICB2YXIgbm9kZXMgPSBjaGFydENvbnRhaW5lci5zZWxlY3RBbGwoXCIuaW4tbGFzc28tXCIrbGFzWzBdLmluc3RhbmNlKCkpLm5vZGVzKClcbiAgICAgIHZhciB0YWJsZURhdGEgPSBub2Rlcy5tYXAoZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIHZhciBleHRyYWN0ZWQgPSBkYXRhRXh0cmFjdG9yKGQzLnNlbGVjdChkKS5kYXR1bSgpKVxuICAgICAgICBleHRyYWN0ZWRbXCJfX25vZGVcIl0gPSBkXG4gICAgICAgIHJldHVybiBleHRyYWN0ZWRcbiAgICAgIH0pXG5cblxuICAgICAgbWFrZVRhYmxlKHRhYmxlLCB0YWJsZURhdGEsIGN1cnJlbnRMYXNzbylcbiAgICB9KVxuXG4gICAgY2xlYXJCdG4ub24oJ2NsaWNrJywgZnVuY3Rpb24oKXtcbiAgICAgIGN1cnJlbnRMYXNzby5hbGxQb2ludHMoW10pXG4gICAgICBjdXJyZW50TGFzc28uY3VycmVudFBvaW50cyhbXSlcbiAgICAgIGxhc3NvQnRuLmRpc3BhdGNoKGh5cGVuYXRlKG5hbWVzcGFjZSxcImRyYWdcIikpXG5cbiAgICB9KVxuXG4gIH1cblxuICBmdW5jdGlvbiBsYXNzb0J0blRvZ2dsZSgpIHtcbiAgICB2YXIgdGhhdCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgIHZhciBsYXMgPSB0aGF0LmRhdHVtKClbMF1cblxuICAgIGxhcy50b2dnbGUoKVxuICAgIHZhciBhY3RpdmVRID0gbGFzLmFjdGl2ZVEoKVxuXG4gICAgaWYgKGxhcy5hY3RpdmVRKCkpIHtcbiAgICAgIHRoYXQuY2xhc3NlZCgnYnRuLWluZm8nLCAhYWN0aXZlUSlcbiAgICAgIHRoYXQuY2xhc3NlZCgnYnRuLXdhcm5pbmcnLCBhY3RpdmVRKVxuICAgICAgdGhhdC5zZWxlY3QoXCJzcGFuXCIpLnRleHQoXCJMYXNzbyBzZWxlY3QgKGFjdGl2ZSlcIilcbiAgICAgIHNlbGVjdGlvbi5zZWxlY3RBbGwoXCIuXCIrbmFtZXNwYWNlK1wiLmxhc3NvLWJ0blwiKS5kaXNwYXRjaChoeXBlbmF0ZShuYW1lc3BhY2UsJ3JlbmRlcicpKVxuICAgICAgZDMuc2VsZWN0KFwiaHRtbFwiKS5ub2RlKCkuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgbW9uaXRvckxhc3NvQnV0dG9uU3RhdGUpXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoYXQuY2xhc3NlZCgnYnRuLWluZm8nLCAhYWN0aXZlUSlcbiAgICAgIHRoYXQuY2xhc3NlZCgnYnRuLXdhcm5pbmcnLCBhY3RpdmVRKVxuICAgICAgdGhhdC5zZWxlY3QoXCJzcGFuXCIpLnRleHQoXCJMYXNzbyBzZWxlY3RcIilcbiAgICAgIGQzLnNlbGVjdChcImh0bWxcIikubm9kZSgpLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIG1vbml0b3JMYXNzb0J1dHRvblN0YXRlKVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1vbml0b3JMYXNzb0J1dHRvblN0YXRlKGV2ZW50KSB7XG4gICAgICAvKlxuICAgICAgYWN0aXZlTGFzc28gc3RvcHMgZXZlbnQgc3RvcFByb3BhZ2F0aW9uLCBzbyB0aGlzIGV2ZW50IHdpbGwgbm90IHJlZ2lzdGVyIGluXG4gICAgICB0aGF0IGNhc2UuIFRodXMgd2Ugb25seSBuZWVkIHRvIGVuc3VyZSB0aGF0IHRoZSB1c3JlIGlzIGNsaWNraW5nIG9uIHRoZSBsYXNzbyBidXR0b25cbiAgICAgIG90aGVyd2lzZSwgZGUtc3Bhd24gbGFzc28uXG4gICAgICAqL1xuICAgICAgaWYgKFxuICAgICAgICBldmVudC50YXJnZXQgIT0gdGhhdC5ub2RlKCkgJiZcbiAgICAgICAgZXZlbnQudGFyZ2V0ICE9IHRoYXQuc2VsZWN0KFwic3BhblwiKS5ub2RlKCkgJiZcbiAgICAgICAgZXZlbnQudGFyZ2V0ICE9IHRoYXQuc2VsZWN0KFwiaVwiKS5ub2RlKClcbiAgICAgICkge1xuICAgICAgICAvLyBldmVudC5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICAgIC8vIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXG4gICAgICAgIGxhcy50b2dnbGUoZmFsc2UpXG4gICAgICAgIHRoYXQuY2xhc3NlZCgnYnRuLWluZm8nLCB0cnVlKVxuICAgICAgICB0aGF0LmNsYXNzZWQoJ2J0bi13YXJuaW5nJywgZmFsc2UpXG4gICAgICAgIHRoYXQuc2VsZWN0KFwic3BhblwiKS50ZXh0KFwiTGFzc28gc2VsZWN0XCIpXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHRoYXQsIHRoYXQubm9kZSgpKVxuICAgICAgICAvLyB0aGF0LmRpc3BhdGNoKFwiZm9jdXNvdXRcIilcbiAgICAgIH1cbiAgICB9XG5cbiAgfVxuXG5cbiAgZnVuY3Rpb24gdXBkYXRlVGFibGVIZWFkZXJDb2x1bW5zKGhlYWRSLCB0YWJsZURhdGEpIHtcbiAgICB2YXIgaGVhZGVyS2V5cyA9IGQzLmtleXModGFibGVEYXRhWzBdKS5maWx0ZXIoaz0+ayE9XCJfX25vZGVcIilcbiAgICBpZiAoaGVhZGVyS2V5cy5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBoZWFkZXJLZXlzID0gW1wicmVtb3ZlXCJdLmNvbmNhdChoZWFkZXJLZXlzKVxuICAgICAgaGVhZGVyS2V5cy5wdXNoKFwicmVtb3ZlXCIpXG4gICAgfVxuXG4gICAgdmFyIGhlYWRlckNvbHMgPSBoZWFkUi5zZWxlY3RBbGwoXCJ0aFwiKVxuXG4gICAgaGVhZGVyQ29scyA9IGhlYWRlckNvbHMuZGF0YShoZWFkZXJLZXlzKVxuICAgIGhlYWRlckNvbHMuZXhpdCgpLnJlbW92ZSgpXG4gICAgaGVhZGVyQ29scyA9IGhlYWRlckNvbHMubWVyZ2UoaGVhZGVyQ29scy5lbnRlcigpLmFwcGVuZChcInRoXCIpLmF0dHIoXCJzY29wZVwiLFwiY29sXCIpKVxuICAgIC50ZXh0KGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkfSlcblxuICAgIHJldHVybiBoZWFkZXJLZXlzXG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVUYWJsZVJvd3MoYm9keSwgdGFibGVEYXRhKSB7XG4gICAgdmFyIGJvZHlSb3dzID0gYm9keS5zZWxlY3RBbGwoXCJ0clwiKVxuXG4gICAgYm9keVJvd3MgPSBib2R5Um93cy5kYXRhKHRhYmxlRGF0YSlcbiAgICBib2R5Um93cy5leGl0KCkucmVtb3ZlKClcbiAgICBib2R5Um93cyA9IGJvZHlSb3dzLm1lcmdlKGJvZHlSb3dzLmVudGVyKCkuYXBwZW5kKFwidHJcIikpXG5cbiAgICByZXR1cm4gYm9keVJvd3NcbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZVRhYmxlUm93Q29sdW1ucyhjb2xzLCBoZWFkZXJLZXlzLCByb3dEYXRhLCB0YWJsZURhdGEsIGxhc3NvLCB0YWJsZSkge1xuICAgIGNvbHMgPSBjb2xzLmRhdGEoaGVhZGVyS2V5cylcbiAgICBjb2xzLmV4aXQoKS5yZW1vdmUoKVxuICAgIGNvbHMgPSBjb2xzLm1lcmdlKGNvbHMuZW50ZXIoKS5hcHBlbmQoXCJ0ZFwiKSlcblxuICAgIGNvbHMuaHRtbChmdW5jdGlvbihkLCBpKXtcbiAgICAgIGlmIChkICE9IFwicmVtb3ZlXCIpIHsgcmV0dXJuIHJvd0RhdGFbZF0gfVxuICAgICAgcmV0dXJuIFwiPGkgY2xhc3M9J2ZhIGZhLWNsb3NlJz48L2k+XCJcbiAgICB9KS5jbGFzc2VkKFwidGV4dC1sZWZ0XCIsIGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgaWYgKGQgIT0gXCJyZW1vdmVcIikgeyByZXR1cm4gZmFsc2UgfVxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9KVxuICAgIC8vIC5hdHRyKFwic2NvcGVcIixmdW5jdGlvbihkLCBpKXtcbiAgICAvLyAgIGlmIChkICE9IFwicmVtb3ZlXCIpIHsgcmV0dXJuIGZhbHNlIH1cbiAgICAvLyAgIHJldHVybiB0cnVlXG4gICAgLy8gfSlcblxuICAgIGNvbHMuc2VsZWN0KFwiaS5mYS1jbG9zZVwiKS5vbihcImNsaWNrXCIsIGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgdmFyIG5vZGUgPSByb3dEYXRhW1wiX19ub2RlXCJdLFxuICAgICAgbiA9IGQzLnNlbGVjdChub2RlKVxuICAgICAgbi5jbGFzc2VkKFwiaW4tbGFzc29cIiwgZmFsc2UpXG4gICAgICBuLmNsYXNzZWQoXCJpbi1sYXNzby1cIitsYXNzby5pbnN0YW5jZSgpLCBmYWxzZSlcblxuICAgICAgdGFibGVEYXRhLm1hcChmdW5jdGlvbihkZCwgail7XG4gICAgICAgIGlmIChkZFtcIl9fbm9kZVwiXSA9PSBub2RlKSB7XG4gICAgICAgICAgdGFibGVEYXRhLnNwbGljZShqLCAxKVxuICAgICAgICAgIG1ha2VUYWJsZSh0YWJsZSwgdGFibGVEYXRhLCBsYXNzbylcbiAgICAgICAgfVxuICAgICAgfSlcblxuICAgIH0pXG4gIH1cblxuICBmdW5jdGlvbiBtYWtlVGFibGUodGFibGUsIHRhYmxlRGF0YSwgbGFzc28pIHtcbiAgICB2YXJcbiAgICBoZWFkID0gc2FmZVNlbGVjdCh0YWJsZSwgXCJ0aGVhZFwiKSxcbiAgICBoZWFkUiA9IHNhZmVTZWxlY3QoaGVhZCwgXCJ0clwiKSxcbiAgICBib2R5ID0gc2FmZVNlbGVjdCh0YWJsZSwgXCJ0Ym9keVwiKSxcblxuICAgIGhlYWRlcktleXMgPSB1cGRhdGVUYWJsZUhlYWRlckNvbHVtbnMoaGVhZFIsIHRhYmxlRGF0YSksXG5cbiAgICBib2R5Um93cyA9IHVwZGF0ZVRhYmxlUm93cyhib2R5LCB0YWJsZURhdGEpXG5cbiAgICBib2R5Um93cy5lYWNoKGZ1bmN0aW9uKHJvd0RhdGEsIGkpe1xuICAgICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcylcbiAgICAgIHZhciBjb2xzID0gdC5zZWxlY3RBbGwoXCJ0ZFwiKVxuXG4gICAgICB1cGRhdGVUYWJsZVJvd0NvbHVtbnMoY29scywgaGVhZGVyS2V5cywgcm93RGF0YSwgdGFibGVEYXRhLCBsYXNzbywgdGFibGUpXG5cbiAgICAgIHQub24oXCJtb3VzZW92ZXJcIiwgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICBsYXNzby5hcHBseU9iamVjdEF0dHJpYnV0ZXMoZDMuc2VsZWN0KGRbXCJfX25vZGVcIl0pLHRydWUpXG4gICAgICB9KVxuICAgICAgLm9uKFwibW91c2VvdXRcIiwgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICBsYXNzby5hcHBseU9iamVjdEF0dHJpYnV0ZXMoZDMuc2VsZWN0KGRbXCJfX25vZGVcIl0pLGZhbHNlKVxuICAgICAgfSlcbiAgICB9KVxuXG5cbiAgfVxuXG5cblxuXG5cblxuXG4gIGZ1bmN0aW9uIG1ha2VOZXdHcm91cChkLCBpKSB7XG5cbiAgICB2YXIgdGFicyA9IHNlbGVjdGlvbi5zZWxlY3QoJy4nK2h5cGVuYXRlKG5hbWVzcGFjZSwgJ3RhYi1saXN0JykpLFxuICAgIHBhbmVzID0gc2VsZWN0aW9uLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCAndGFiLWNvbnRlbnQnKSksXG4gICAgbiA9IG5ld0dyb3VwTnVtYmVyKClcblxuICAgIGlmICh0YWJzLnNlbGVjdEFsbCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCd0YWInKSkuc2l6ZSgpID09IG1heE51bWJlck9mR3JvdXBzKSB7XG4gICAgICBvbkVycm9yKCdvbmx5ICcrbWF4TnVtYmVyT2ZHcm91cHMrJyBhbGxvd2VkLicsICd3YXJuaW5nJylcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHZhclxuICAgIHRhYiA9IGluc2VydFRhYih0YWJzLCBuKSxcbiAgICBwYW5lID0gbWFrZVRhYlBhbmUocGFuZXMsIG4pXG5cbiAgICBwb3B1bGF0ZVBhbmUocGFuZSwgbilcbiAgICB0b2dnbGVQYW5lQnlJZChwYW5lLmF0dHIoJ2lkJykpXG5cbiAgfVxuXG4gIGZ1bmN0aW9uIG5ld0dyb3VwTnVtYmVyKCkge1xuICAgIHZhciB0YWJzID0gc2VsZWN0aW9uLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCAndGFiLWxpc3QnKSkvLyxcbiAgICB2YXJcbiAgICBuID0gdGFicy5zZWxlY3RBbGwoJ2xpJykuc2l6ZSgpIC0gMywgLy8gbWludXMgMSBmb3IgcGx1cyB0YWJcbiAgICBzID0gJ0dyb3VwICcgKyBuLFxuICAgIGdzID0gW11cbiAgICB0YWJzLmVhY2goZnVuY3Rpb24oZCwgaSl7IHJldHVybiBncy5wdXNoKGQzLnNlbGVjdCh0aGlzKS5zZWxlY3QoXCJhXCIpLnRleHQoKSkgfSlcbiAgICB3aGlsZSAoZ3MuaW5jbHVkZXMocykpIHsgbis9MTsgcyA9ICdHcm91cCAnICsgbjsgfVxuICAgIHJldHVybiBuXG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVUYWJBbmRQYW5lTnVtYmVycygpIHtcbiAgICB2YXJcbiAgICB0YWJzID0gc2VsZWN0aW9uLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCAndGFiLWxpc3QnKSksXG4gICAgcGFuZXMgPSBzZWxlY3Rpb24uc2VsZWN0KCcuJytoeXBlbmF0ZShuYW1lc3BhY2UsICd0YWItY29udGVudCcpKVxuXG4gICAgdGFicyA9IHRhYnMuc2VsZWN0QWxsKCcuJytoeXBlbmF0ZShuYW1lc3BhY2UsJ3RhYicpKVxuICAgIHBhbmVzID0gcGFuZXMuc2VsZWN0QWxsKCcuJytoeXBlbmF0ZShuYW1lc3BhY2UsJ3RhYicsICdwYW5lJykpXG5cbiAgICB0YWJzLmVhY2goZnVuY3Rpb24oZCwgaSl7XG4gICAgICBkMy5zZWxlY3QodGhpcykuZGF0dW0oaSlcbiAgICAgIC5hdHRyKFwiaWRcIiwgaHlwZW5hdGUobmFtZXNwYWNlLCd0YWInLGkpKVxuICAgICAgLnNlbGVjdCgnYScpXG4gICAgICAuYXR0cignaHJlZicsICcjJytoeXBlbmF0ZShuYW1lc3BhY2UsJ3RhYicsJ3BhbmUnLGkpKVxuICAgICAgLnRleHQoZnVuY3Rpb24oZGQsIGlpKXtcbiAgICAgICAgdmFyIGN1clRleHQgPSBkMy5zZWxlY3QodGhpcykudGV4dCgpO1xuICAgICAgICBpZiAoY3VyVGV4dC5zcGxpdCgnICcpWzBdID09ICdHcm91cCcpIHtcbiAgICAgICAgICAgIHJldHVybiAnR3JvdXAgJyArIGlcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY3VyVGV4dFxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgcGFuZXMuZWFjaChmdW5jdGlvbihkLCBpKXtcbiAgICAgIGQzLnNlbGVjdCh0aGlzKS5kYXR1bShpKVxuICAgICAgLmF0dHIoJ2lkJywgaHlwZW5hdGUobmFtZXNwYWNlLCd0YWInLCdwYW5lJyxpKSlcbiAgICAgIHNhZmVTZWxlY3QoZDMuc2VsZWN0KHRoaXMpLCAncCcsICdsZWFkJylcbiAgICAgIC50ZXh0KGZ1bmN0aW9uKGRkLCBpaSl7XG4gICAgICAgIHZhciBjdXJUZXh0ID0gZDMuc2VsZWN0KHRoaXMpLnRleHQoKTtcbiAgICAgICAgaWYgKGN1clRleHQuc3BsaXQoJyAnKVswXSA9PSAnR3JvdXAnKSB7XG4gICAgICAgICAgICByZXR1cm4gJ0dyb3VwICcgKyBpXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGN1clRleHRcbiAgICAgIH0pXG4gICAgICBzYWZlU2VsZWN0KGQzLnNlbGVjdCh0aGlzKSwgJ2J1dHRvbicsICdyZW1vdmUtYnRuJylcbiAgICAgIC5vbignY2xpY2snLCByZW1vdmVCdG5DbGlja1RvUmVtb3ZlKVxuICAgIH0pXG5cbiAgfVxuXG4gIGZ1bmN0aW9uIGdhdGhlckRhdGFMaXN0cygpIHtcbiAgICB2YXIgdGFicyA9IHNlbGVjdGlvbi5zZWxlY3QoJy4nK2h5cGVuYXRlKG5hbWVzcGFjZSwgJ3RhYi1saXN0JykpXG4gICAgdmFyIHBhbmVzID0gc2VsZWN0aW9uLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCAndGFiLWNvbnRlbnQnKSlcbiAgICB2YXIgdGFibGVzID0gcGFuZXMuc2VsZWN0QWxsKCcuJytoeXBlbmF0ZShuYW1lc3BhY2UsIFwiZGF0YS10YWJsZVwiKSlcbiAgICB2YXIgZGF0YSA9IHt9XG5cbiAgICB2YXIgdGV4dEdyb3VwcyA9IHRhYnMuc2VsZWN0QWxsKCdsaS4nK2h5cGVuYXRlKG5hbWVzcGFjZSwndGFiJykgKyAnID4gYScpXG4gICAgLm5vZGVzKCkubWFwKGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkMy5zZWxlY3QoZCkudGV4dCgpfSlcblxuICAgIHRleHRHcm91cHMubWFwKGZ1bmN0aW9uKGUsIGkpe1xuICAgICAgZGF0YVtlXSA9IFtdXG4gICAgfSlcblxuXG4gICAgdGFibGVzLmVhY2goZnVuY3Rpb24oZCwgaSl7XG4gICAgICB2YXIgdGFibGUgPSBkMy5zZWxlY3QodGhpcykuc2VsZWN0KFwidGJvZHlcIilcbiAgICAgIGRhdGFbdGV4dEdyb3Vwc1tpXV0gPSB0YWJsZS5zZWxlY3RBbGwoJ3RyJykuZGF0YSgpXG4gICAgfSlcblxuICAgIHJldHVybiBkYXRhXG4gIH1cblxuICBmdW5jdGlvbiBzaG93UmVtYWluaW5nUGFuZXMoKSB7XG4gICAgdmFyXG4gICAgdGFicyA9IHNlbGVjdGlvbi5zZWxlY3QoJy4nK2h5cGVuYXRlKG5hbWVzcGFjZSwgJ3RhYi1saXN0JykpLFxuICAgIHBhbmVzID0gc2VsZWN0aW9uLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCAndGFiLWNvbnRlbnQnKSksXG4gICAgcmVtYWluaW5nVGFicyA9IHRhYnMuc2VsZWN0QWxsKCcuJytoeXBlbmF0ZShuYW1lc3BhY2UsJ3RhYicpKVxuXG4gICAgaWYgKHJlbWFpbmluZ1RhYnMuc2l6ZSgpID09IDApIHtcbiAgICAgIHBhbmVzLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCdkZWZhdWx0LXRhYicpKVxuICAgICAgLmNsYXNzZWQoXCJhY3RpdmVcIiwgdHJ1ZSlcbiAgICAgIC5jbGFzc2VkKCd0ZXh0LWxlZnQnLCB0cnVlKVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHZhciBsYXN0VGFiID0gcmVtYWluaW5nVGFicy5ub2RlcygpW3JlbWFpbmluZ1RhYnMuc2l6ZSgpLTFdLFxuICAgICAgbGFzdFBhbmVJZCA9IGQzLnNlbGVjdChsYXN0VGFiKS5zZWxlY3QoJ2EnKS5hdHRyKCdocmVmJylcbiAgICAgIHBhbmVzLnNlbGVjdChsYXN0UGFuZUlkKVxuICAgICAgLmNsYXNzZWQoXCJhY3RpdmVcIiwgdHJ1ZSlcbiAgICAgIC5jbGFzc2VkKCd0ZXh0LWxlZnQnLCB0cnVlKVxuICAgIH1cbiAgfVxuXG5cbiAgcmV0dXJuIGxhc3NvV2lkZ2V0XG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtzZXR1cENvbnRhaW5lciwgY2FsY3VsYXRlV2lkdGhPZk9iamVjdCwgY2FsY3VsYXRlV2lkdGhPZlNwYWNlciwgbG9nfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7dW5pcXVlLCBmbGF0dGVufSBmcm9tICcuL2FycmF5LWZ1bmN0aW9ucyc7XG5pbXBvcnQge2dyb3VwaW5nU3BhY2VyfSBmcm9tICcuL2dyb3VwaW5nLXNwYWNlcic7XG5pbXBvcnQge2NvbG9yRnVuY3Rpb24gYXMgQ0Z9IGZyb20gJy4vY29sb3ItZnVuY3Rpb24nO1xuaW1wb3J0IHt0b29sdGlwIGFzIFRUaXB9IGZyb20gJy4vdG9vbHRpcCc7XG5leHBvcnQgZnVuY3Rpb24gdXBzZXQgKCBzZWxlY3Rpb24gKSB7XG4gIHZhclxuICBkYXRhLFxuICBvcmllbnQ9J2hvcml6b250YWwnLFxuICBzcGFjZVgsXG4gIHNwYWNlWSxcbiAgb3ZlcmZsb3dRPWZhbHNlLFxuICBtaW5PYmplY3RTaXplPTIwLFxuICBtYXhPYmplY3RTaXplPTUwLFxuICBjaXJjbGVTdHJva2VXaWR0aD0yLFxuICAvLyBjb2xvckZ1bmN0aW9uPVxuICBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCcsXG4gIG5hbWVzcGFjZT0nZDNzbS11cHNldCcsXG4gIG9iamVjdENsYXNzID0gJ3Vwc2V0JyxcblxuICB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwLFxuICBlYXNlRnVuYyA9IGQzLmVhc2VFeHAsXG5cbiAgc2V0S2V5ID0gXCJzZXRcIixcbiAgaW50ZXJzZWN0aW9uS2V5ID0gXCJpbnRlcnNlY3Rpb25cIixcbiAgZWxlbWVudHNLZXkgPSBcImVsZW1lbnRzXCIsXG5cbiAgc2V0RXh0cmFjdG9yID0gZnVuY3Rpb24oa2V5LCBpKSB7cmV0dXJuIGRhdGFba2V5XVtzZXRLZXldfSxcbiAgaW50ZXJzZWN0aW9uRXh0cmFjdG9yID0gZnVuY3Rpb24oa2V5LCBpKSB7cmV0dXJuIGRhdGFba2V5XVtpbnRlcnNlY3Rpb25LZXldfSxcbiAgZWxlbWVudEV4dHJhY3RvciA9IGZ1bmN0aW9uKGtleSwgaSkge3JldHVybiBkYXRhW2tleV1bZWxlbWVudHNLZXldfSxcblxuICBjZWxsS2V5cyxcbiAgc2V0VmFsdWVzLFxuICBpbnRlcnNlY3Rpb25WYWx1ZXMsXG4gIGVsZW1lbnRWYWx1ZXMsXG5cbiAgeE9iamVjdFNwYWNlciA9IDAuMDUsXG4gIHlPYmplY3RTcGFjZXIgPSAwLjA1LFxuICByYWRpdXMsXG5cbiAgLy8gbGlzdERlbGltID0gJzsnXG5cbiAgeU9iamVjdFNpemUsXG4gIHlTcGFjZXJTaXplLFxuICB4T2JqZWN0U2l6ZSxcbiAgeFNwYWNlclNpemUsXG5cbiAgc2V0S2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gc2V0VmFsdWVzLmluZGV4T2Yoc2V0RXh0cmFjdG9yKGEpKSAtIHNldFZhbHVlcy5pbmRleE9mKHNldEV4dHJhY3RvcihiKSkgfSxcbiAgaW50ZXJzZWN0aW9uS2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gaW50ZXJzZWN0aW9uVmFsdWVzLmluZGV4T2YoaW50ZXJzZWN0aW9uRXh0cmFjdG9yKGEpKSAtIGludGVyc2VjdGlvblZhbHVlcy5pbmRleE9mKGludGVyc2VjdGlvbkV4dHJhY3RvcihiKSkgfVxuXG5cbiAgdXBzZXQuc2VsZWN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZWxlY3Rpb24gPSBfLCB1cHNldCkgOiBzZWxlY3Rpb247IH07XG4gIHVwc2V0LmRhdGEgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRhdGEgPSBfLCB1cHNldCkgOiBkYXRhOyB9O1xuICB1cHNldC5vcmllbnQgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9yaWVudCA9IF8sIHVwc2V0KSA6IG9yaWVudDsgfTtcbiAgdXBzZXQuc3BhY2VYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVggPSBfLCB1cHNldCkgOiBzcGFjZVg7IH07XG4gIHVwc2V0LnNwYWNlWSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3BhY2VZID0gXywgdXBzZXQpIDogc3BhY2VZOyB9O1xuICB1cHNldC5vdmVyZmxvd1EgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG92ZXJmbG93USA9IF8sIHVwc2V0KSA6IG92ZXJmbG93UTsgfTtcbiAgdXBzZXQubWluT2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobWluT2JqZWN0U2l6ZSA9IF8sIHVwc2V0KSA6IG1pbk9iamVjdFNpemU7IH07XG4gIHVwc2V0Lm1heE9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1heE9iamVjdFNpemUgPSBfLCB1cHNldCkgOiBtYXhPYmplY3RTaXplOyB9O1xuICB1cHNldC5jaXJjbGVTdHJva2VXaWR0aCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY2lyY2xlU3Ryb2tlV2lkdGggPSBfLCB1cHNldCkgOiBjaXJjbGVTdHJva2VXaWR0aDsgfTtcbiAgdXBzZXQuYmFja2dyb3VuZEZpbGwgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJhY2tncm91bmRGaWxsID0gXywgdXBzZXQpIDogYmFja2dyb3VuZEZpbGw7IH07XG4gIHVwc2V0Lm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgdXBzZXQpIDogbmFtZXNwYWNlOyB9O1xuICB1cHNldC5vYmplY3RDbGFzcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q2xhc3MgPSBfLCB1cHNldCkgOiBvYmplY3RDbGFzczsgfTtcbiAgdXBzZXQudHJhbnNpdGlvbkR1cmF0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0cmFuc2l0aW9uRHVyYXRpb24gPSBfLCB1cHNldCkgOiB0cmFuc2l0aW9uRHVyYXRpb247IH07XG4gIHVwc2V0LmVhc2VGdW5jID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChlYXNlRnVuYyA9IF8sIHVwc2V0KSA6IGVhc2VGdW5jOyB9O1xuICB1cHNldC5jZWxsS2V5cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY2VsbEtleXMgPSBfLCB1cHNldCkgOiBjZWxsS2V5czsgfTtcbiAgdXBzZXQuc2V0VmFsdWVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZXRWYWx1ZXMgPSBfLCB1cHNldCkgOiBzZXRWYWx1ZXM7IH07XG4gIHVwc2V0LmludGVyc2VjdGlvblZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaW50ZXJzZWN0aW9uVmFsdWVzID0gXywgdXBzZXQpIDogaW50ZXJzZWN0aW9uVmFsdWVzOyB9O1xuICB1cHNldC54T2JqZWN0U3BhY2VyID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4T2JqZWN0U3BhY2VyID0gXywgdXBzZXQpIDogeE9iamVjdFNwYWNlcjsgfTtcbiAgdXBzZXQueU9iamVjdFNwYWNlciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeU9iamVjdFNwYWNlciA9IF8sIHVwc2V0KSA6IHlPYmplY3RTcGFjZXI7IH07XG4gIHVwc2V0LnJhZGl1cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocmFkaXVzID0gXywgdXBzZXQpIDogcmFkaXVzOyB9O1xuICB1cHNldC5zZXRFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNldEV4dHJhY3RvciA9IF8sIHVwc2V0KSA6IHNldEV4dHJhY3RvcjsgfTtcbiAgdXBzZXQuaW50ZXJzZWN0aW9uRXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChpbnRlcnNlY3Rpb25FeHRyYWN0b3IgPSBfLCB1cHNldCkgOiBpbnRlcnNlY3Rpb25FeHRyYWN0b3I7IH07XG4gIHVwc2V0LmVsZW1lbnRFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGVsZW1lbnRFeHRyYWN0b3IgPSBfLCB1cHNldCkgOiBlbGVtZW50RXh0cmFjdG9yOyB9O1xuICB1cHNldC5zZXRLZXlTb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNldEtleVNvcnRpbmdGdW5jdGlvbiA9IF8sIHVwc2V0KSA6IHNldEtleVNvcnRpbmdGdW5jdGlvbjsgfTtcbiAgdXBzZXQuaW50ZXJzZWN0aW9uS2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChpbnRlcnNlY3Rpb25LZXlTb3J0aW5nRnVuY3Rpb24gPSBfLCB1cHNldCkgOiBpbnRlcnNlY3Rpb25LZXlTb3J0aW5nRnVuY3Rpb247IH07XG5cbiAgdXBzZXQueU9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlPYmplY3RTaXplID0gXywgdXBzZXQpIDogeU9iamVjdFNpemU7IH07XG4gIHVwc2V0LnlTcGFjZXJTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5U3BhY2VyU2l6ZSA9IF8sIHVwc2V0KSA6IHlTcGFjZXJTaXplOyB9O1xuICB1cHNldC54T2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeE9iamVjdFNpemUgPSBfLCB1cHNldCkgOiB4T2JqZWN0U2l6ZTsgfTtcbiAgdXBzZXQueFNwYWNlclNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhTcGFjZXJTaXplID0gXywgdXBzZXQpIDogeFNwYWNlclNpemU7IH07XG5cbiAgZnVuY3Rpb24gdXBzZXQoKSB7XG4gICAgLy8gZm9yIGNvbnZlbmllbmNlIGluIGhhbmRsaW5nIG9yaWVudGF0aW9uIHNwZWNpZmljIHZhbHVlc1xuICAgIHZhciBob3Jpem9udGFsUSA9IChvcmllbnQgPT0gJ2hvcml6b250YWwnKSA/IHRydWUgOiBmYWxzZVxuICAgIHZhciB2ZXJ0aWNhbFEgPSAhaG9yaXpvbnRhbFFcblxuICAgIC8vIGJhY2tncm91bmQgY2xpcGluZyByZWN0YW5nbGVcbiAgICB2YXIgYmdjcFJlY3QgPSB7eDowLCB5OjAsIHdpZHRoOiBzcGFjZVgsIGhlaWdodDpzcGFjZVl9XG4gICAgdmFyIGNvbnRhaW5lciA9IHNldHVwQ29udGFpbmVyKCBzZWxlY3Rpb24sIG5hbWVzcGFjZSwgYmdjcFJlY3QsIGJhY2tncm91bmRGaWxsICk7XG5cblxuICAgIGNlbGxLZXlzID0gZDMua2V5cyhkYXRhKVxuICAgIHNldFZhbHVlcyA9IHVuaXF1ZShjZWxsS2V5cy5tYXAoc2V0RXh0cmFjdG9yKSkuc29ydCgpXG4gICAgaW50ZXJzZWN0aW9uVmFsdWVzID0gdW5pcXVlKGNlbGxLZXlzLm1hcChpbnRlcnNlY3Rpb25FeHRyYWN0b3IpKS5zb3J0KCkuc29ydChmdW5jdGlvbihhLCBiKXtcbiAgICAgIHJldHVybiBhLnNwbGl0KCc7JykubGVuZ3RoIC0gYi5zcGxpdCgnOycpLmxlbmd0aFxuICAgIH0pXG5cbiAgICBpZiAoIWhvcml6b250YWxRKSB7XG4gICAgICBjZWxsS2V5cy5zb3J0KGZ1bmN0aW9uKGEsIGIpeyByZXR1cm4gc2V0S2V5U29ydGluZ0Z1bmN0aW9uKGEsIGIpIHx8IGludGVyc2VjdGlvbktleVNvcnRpbmdGdW5jdGlvbihhLCBiKSB9KVxuICAgIH0gZWxzZSB7XG4gICAgICBjZWxsS2V5cy5zb3J0KGZ1bmN0aW9uKGEsIGIpeyByZXR1cm4gaW50ZXJzZWN0aW9uS2V5U29ydGluZ0Z1bmN0aW9uKGEsIGIpIHx8IHNldEtleVNvcnRpbmdGdW5jdGlvbihhLCBiKSB9KVxuICAgIH1cblxuXG5cblxuICAgIHZhclxuICAgIHhWYWx1ZXMgPSBob3Jpem9udGFsUSA/IGludGVyc2VjdGlvblZhbHVlcyA6IHNldFZhbHVlcyxcbiAgICB5VmFsdWVzID0gaG9yaXpvbnRhbFEgPyBzZXRWYWx1ZXMgOiBpbnRlcnNlY3Rpb25WYWx1ZXMsXG4gICAgeERpbSA9IGhvcml6b250YWxRID8geFZhbHVlcy5sZW5ndGggOiB5VmFsdWVzLmxlbmd0aCxcbiAgICB5RGltID0gaG9yaXpvbnRhbFEgPyB5VmFsdWVzLmxlbmd0aCA6IHhWYWx1ZXMubGVuZ3RoXG5cbiAgICAvLyBjb25zb2xlLmxvZyh4VmFsdWVzLCB5VmFsdWVzKVxuXG5cbiAgICB4T2JqZWN0U2l6ZSA9IGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3Qoc3BhY2VYLCB4RGltLCBtaW5PYmplY3RTaXplLCBtYXhPYmplY3RTaXplLCB4T2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgeU9iamVjdFNpemUgPSBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0KHNwYWNlWSwgeURpbSwgbWluT2JqZWN0U2l6ZSwgbWF4T2JqZWN0U2l6ZSwgeU9iamVjdFNwYWNlciwgb3ZlcmZsb3dRKVxuICAgIHhTcGFjZXJTaXplID0gY2FsY3VsYXRlV2lkdGhPZlNwYWNlcih4VmFsdWVzLCBzcGFjZVgsIHhPYmplY3RTaXplLCB4RGltLCB4T2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgeVNwYWNlclNpemUgPSBjYWxjdWxhdGVXaWR0aE9mU3BhY2VyKHlWYWx1ZXMsIHNwYWNlWSwgeU9iamVjdFNpemUsIHlEaW0sIHlPYmplY3RTcGFjZXIsIG92ZXJmbG93USlcblxuICAgIHZhciB5U3BhY2VyID0gZ3JvdXBpbmdTcGFjZXIoKVxuICAgIC5ob3Jpem9udGFsUShmYWxzZSlcbiAgICAubW92ZWJ5KCdjYXRlZ29yeScpLm51bWJlck9mT2JqZWN0cyh5RGltKVxuICAgIC5vYmplY3RTaXplKHlPYmplY3RTaXplKS5zcGFjZXJTaXplKHlTcGFjZXJTaXplKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlRnVuYyhlYXNlRnVuYylcblxuICAgIHZhciB4U3BhY2VyID0gZ3JvdXBpbmdTcGFjZXIoKVxuICAgIC5ob3Jpem9udGFsUSh0cnVlKVxuICAgIC5tb3ZlYnkoJ2NhdGVnb3J5JykubnVtYmVyT2ZPYmplY3RzKHhEaW0pXG4gICAgLm9iamVjdENsYXNzKG9iamVjdENsYXNzKVxuICAgIC5vYmplY3RTaXplKHhPYmplY3RTaXplKS5zcGFjZXJTaXplKHhTcGFjZXJTaXplKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlRnVuYyhlYXNlRnVuYylcblxuXG5cbiAgICBpZiAodmVydGljYWxRKSB7XG4gICAgICB4U3BhY2VyLm9iamVjdENsYXNzKG9iamVjdENsYXNzKVxuICAgICAgeVNwYWNlci5uYW1lc3BhY2UoJ2Fjcm9zcycpLm9iamVjdENsYXNzKGh5cGVuYXRlKG9iamVjdENsYXNzLCAnYWNyb3NzJykpXG5cbiAgICAgIHlTcGFjZXIoY29udGFpbmVyLCB5VmFsdWVzLCAwKVxuICAgICAgY29udGFpbmVyLnNlbGVjdEFsbCgnZy4nK2h5cGVuYXRlKG9iamVjdENsYXNzLCAnYWNyb3NzJykpXG4gICAgICAuZWFjaChmdW5jdGlvbihkLCBpKXsgeFNwYWNlcihkMy5zZWxlY3QodGhpcyksIHhWYWx1ZXMsIDApIH0pXG4gICAgfSBlbHNlIHtcbiAgICAgIHhTcGFjZXIubmFtZXNwYWNlKCdhY3Jvc3MnKS5vYmplY3RDbGFzcyhoeXBlbmF0ZShvYmplY3RDbGFzcywgJ2Fjcm9zcycpKVxuICAgICAgeVNwYWNlci5vYmplY3RDbGFzcyhvYmplY3RDbGFzcylcblxuICAgICAgeFNwYWNlcihjb250YWluZXIsIHhWYWx1ZXMsIDApXG4gICAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnLicraHlwZW5hdGUob2JqZWN0Q2xhc3MsICdhY3Jvc3MnKSlcbiAgICAgIC5lYWNoKGZ1bmN0aW9uKGQsIGkpeyB5U3BhY2VyKGQzLnNlbGVjdCh0aGlzKSwgeVZhbHVlcywgMCkgfSlcbiAgICB9XG5cblxuICAgIHZhciBjZWxscyA9IGNvbnRhaW5lci5zZWxlY3RBbGwoJ2c6bm90KC50by1yZW1vdmUpLicrb2JqZWN0Q2xhc3MpXG4gICAgdmFyIGxvb2t1cCA9IHt9XG4gICAgY2VsbEtleXMubWFwKGZ1bmN0aW9uKGssIGkpe1xuICAgICAgbG9va3VwW3NldEV4dHJhY3RvcihrKSsnOjonK2ludGVyc2VjdGlvbkV4dHJhY3RvcihrKV0gPSBrXG4gICAgfSlcblxuICAgIC8vIHZhciBwb3NpdGlvbmVkQ2VsbEtleXMgPSBbXVxuICAgIC8vIGZvciAodmFyIGkgPSAwOyBpIDwgc2V0VmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgLy8gICBmb3IgKHZhciBqID0gMDsgaiA8IGludGVyc2VjdGlvblZhbHVlcy5sZW5ndGg7IGorKykge1xuICAgIC8vICAgICB2YXIgbG9va3VwVmFsdWUgPSBsb29rdXBbc2V0VmFsdWVzW2pdK1wiOjpcIitpbnRlcnNlY3Rpb25WYWx1ZXNbaV1dXG4gICAgLy8gICAgIGlmIChsb29rdXBWYWx1ZSA9PSB1bmRlZmluZWQpIHtcbiAgICAvLyAgICAgICBwb3NpdGlvbmVkQ2VsbEtleXMucHVzaCh1bmRlZmluZWQpXG4gICAgLy8gICAgIH0gZWxzZSB7XG4gICAgLy8gICAgICAgcG9zaXRpb25lZENlbGxLZXlzLnB1c2gobG9va3VwVmFsdWUpXG4gICAgLy8gICAgIH1cbiAgICAvLyAgICAgY29uc29sZS5sb2coaSwgaiwgbG9va3VwVmFsdWUpXG4gICAgLy8gICB9XG4gICAgLy8gfVxuICAgIC8vXG4gICAgLy8gLy8gY29uc29sZS5sb2cocG9zaXRpb25lZENlbGxLZXlzKVxuICAgIC8vXG4gICAgLy8gY2VsbHMuZGF0YShwb3NpdGlvbmVkQ2VsbEtleXMpO1xuXG5cbiAgICBjZWxscy5kYXRhKGNlbGxLZXlzKTtcblxuICAgIGNlbGxzLmVhY2goZnVuY3Rpb24oa2V5LCBpKSB7XG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgICAgaWYgKGtleSA9PSB1bmRlZmluZWQpIHtyZXR1cm4gfVxuICAgICAgdmFyXG4gICAgICBjdXJyZW50RGF0YSA9IGRhdGFba2V5XVxuICAgICAgLy8gY29uc29sZS5sb2coa2V5LCBjdXJyZW50RGF0YSlcbiAgICAgIHZhclxuICAgICAgc2V0ID0gc2V0RXh0cmFjdG9yKGtleSwgaSksXG4gICAgICBpbnRlcnNlY3Rpb24gPSBpbnRlcnNlY3Rpb25FeHRyYWN0b3Ioa2V5LCBpKVxuXG4gICAgICAvLyBjb25zb2xlLmxvZyhzZXQsIGludGVyc2VjdGlvbilcblxuICAgICAgdC5jbGFzc2VkKGludGVyc2VjdGlvbiwgdHJ1ZSlcbiAgICAgIHQuY2xhc3NlZChzZXQsIHRydWUpXG5cbiAgICAgIHZhciBjID0gc2FmZVNlbGVjdCh0LCAnY2lyY2xlJywgaHlwZW5hdGUob2JqZWN0Q2xhc3MsJ2NpcmNsZScpKVxuICAgICAgYy5hdHRyKCdjeCcsIHhPYmplY3RTaXplIC8gMilcbiAgICAgIC5hdHRyKCdjeScsIHlPYmplY3RTaXplIC8gMiApXG4gICAgICAuYXR0cigncicsIHJhZGl1cyA9PSB1bmRlZmluZWQgPyBNYXRoLm1pbih4T2JqZWN0U2l6ZSwgeU9iamVjdFNpemUpIC8gMiA6IHJhZGl1cylcbiAgICAgIC5hdHRyKCdmaWxsJywgaW50ZXJzZWN0aW9uLmluY2x1ZGVzKHNldCkgPyBcImJsYWNrXCI6ICdyZ2IoMjMzLDIzMywyMzMpJylcbiAgICAgIC5hdHRyKCdzdHJva2UnLCBcImJsYWNrXCIpXG4gICAgICAuYXR0cihcImluLWludGVyc2VjdGlvblwiLCBpbnRlcnNlY3Rpb24uaW5jbHVkZXMoc2V0KSlcbiAgICB9KVxuXG5cblxuICB9XG5cbiAgZnVuY3Rpb24gaW50ZXJzZWN0aW9uVG90YWxzKCkge1xuICAgIHZhciB0b3RhbHMgPSB7fVxuICAgIC8vIGludGVyc2VjdGlvblZhbHVlcy5zb3J0KGZ1bmN0aW9uKGEsIGIpeyByZXR1cm4gaW50ZXJzZWN0aW9uS2V5U29ydGluZ0Z1bmN0aW9uKGEsIGIpIH0pXG5cbiAgICBpbnRlcnNlY3Rpb25WYWx1ZXMubWFwKGZ1bmN0aW9uKGssIGkpeyB0b3RhbHNba10gPSB7J3RvdGFsJzogMH0gfSlcbiAgICBjZWxsS2V5cy5tYXAoZnVuY3Rpb24oaywgaSl7XG4gICAgICB2YXIgZSA9IGVsZW1lbnRFeHRyYWN0b3IoaywgaSk7XG4gICAgICBpZiAodG90YWxzW2ludGVyc2VjdGlvbkV4dHJhY3RvcihrLCBpKV1bJ3RvdGFsJ10gPT0gMCkge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShlKSkge1xuICAgICAgICAgIHRvdGFsc1tpbnRlcnNlY3Rpb25FeHRyYWN0b3IoaywgaSldWyd0b3RhbCddKz0gZS5sZW5ndGhcbiAgICAgICAgICB0b3RhbHNbaW50ZXJzZWN0aW9uRXh0cmFjdG9yKGssIGkpXVsndmFsdWVzJ10gPSBlXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdG90YWxzW2ludGVyc2VjdGlvbkV4dHJhY3RvcihrLCBpKV1bJ3RvdGFsJ10rPSBlXG4gICAgICAgIH1cblxuICAgICAgfVxuICAgIH0pXG4gICAgcmV0dXJuIHRvdGFsc1xuICB9XG5cbiAgZnVuY3Rpb24gc2V0VG90YWxzKCl7XG4gICAgdmFyIHRvdGFscyA9IHt9XG4gICAgLy8gaW50ZXJzZWN0aW9uVmFsdWVzLnNvcnQoZnVuY3Rpb24oYSwgYil7IHJldHVybiBpbnRlcnNlY3Rpb25LZXlTb3J0aW5nRnVuY3Rpb24oYSwgYikgfSlcblxuICAgIHNldFZhbHVlcy5tYXAoZnVuY3Rpb24oaywgaSl7IHRvdGFsc1trXSA9IHsndG90YWwnOiAwfSB9KVxuXG4gICAgY2VsbEtleXMubWFwKGZ1bmN0aW9uKGssIGkpe1xuICAgICAgdmFyIGUgPSBlbGVtZW50RXh0cmFjdG9yKGssIGkpO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZSkpIHtcbiAgICAgICAgdG90YWxzW3NldEV4dHJhY3RvcihrLCBpKV1bJ3RvdGFsJ10rPSBlLmxlbmd0aFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdG90YWxzW3NldEV4dHJhY3RvcihrLCBpKV1bJ3RvdGFsJ10rPSBlXG4gICAgICB9XG4gICAgfSlcbiAgICByZXR1cm4gdG90YWxzXG4gIH1cblxuICB1cHNldC5pbnRlcnNlY3Rpb25Ub3RhbHMgPSBpbnRlcnNlY3Rpb25Ub3RhbHNcbiAgdXBzZXQuc2V0VG90YWxzID0gc2V0VG90YWxzXG5cbiAgcmV0dXJuIHVwc2V0XG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlclRhYmxlKHNlbGVjdGlvbikge1xuICB2YXJcbiAgZGF0YSxcbiAgbmFtZXNwYWNlID0gJ2Qzc20tZmlsdGVyLXRhYmxlJyxcbiAgc29ydFEgPSBmYWxzZSxcbiAgZmllbGRGdW5jdGlvbiA9IGZ1bmN0aW9uKHJlY29yZCwgY29sdW1uS2V5LCByZWNvcmRWYWx1ZSkge3JldHVybiByZWNvcmRWYWx1ZX1cblxuICBmaWx0ZXJUYWJsZS5kYXRhID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkYXRhID0gXywgZmlsdGVyVGFibGUpIDogZGF0YX1cbiAgZmlsdGVyVGFibGUubmFtZXNwYWNlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChuYW1lc3BhY2UgPSBfLCBmaWx0ZXJUYWJsZSkgOiBuYW1lc3BhY2V9XG4gIGZpbHRlclRhYmxlLmZpZWxkRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGZpZWxkRnVuY3Rpb24gPSBfLCBmaWx0ZXJUYWJsZSkgOiBmaWVsZEZ1bmN0aW9ufVxuXG4gIGZ1bmN0aW9uIGZpbHRlclRhYmxlICgpIHtcblxuICAgIHZhclxuICAgIGNvbnRhaW5lciA9IHNhZmVTZWxlY3Qoc2VsZWN0aW9uLCAnZGl2JywgJ2ZpbHRlci10YWJsZScpLmNsYXNzZWQoaHlwZW5hdGUobmFtZXNwYWNlLCdjb250YWluZXInKSx0cnVlKSxcblxuICAgIGlucHV0R3JvdXAgPSBzYWZlU2VsZWN0KGNvbnRhaW5lciwgJ2RpdicsICdmaWx0ZXItaW5wdXQtZ3JvdXAnKS5jbGFzc2VkKCdpbnB1dC1ncm91cCcsdHJ1ZSksXG4gICAgICBpbnB1dFByZXBlbmQgPSBzYWZlU2VsZWN0KGlucHV0R3JvdXAsICdkaXYnLCAnaW5wdXQtZ3JvdXAtcHJlcGVuZCcpLFxuICAgICAgICBpbnB1dFByZXBlbmRTcGFuID0gc2FmZVNlbGVjdChpbnB1dFByZXBlbmQsICdzcGFuJywgJ2lucHV0LWdyb3VwLXRleHQnKS5jbGFzc2VkKCdzZWFyY2gtYnV0dG9uJywgdHJ1ZSksXG4gICAgICAgICAgaW5wdXRQcmVwZW5kU3Bhbkljb24gPSBzYWZlU2VsZWN0KGlucHV0UHJlcGVuZFNwYW4sJ2knLCdmYSBmYS1zZWFyY2gnKSxcblxuICAgICAgaW5wdXQgPSBzYWZlU2VsZWN0KGlucHV0R3JvdXAsICdpbnB1dCcsICdmb3JtLWNvbnRyb2wnKS5hdHRyKCdwbGFjZWhvbGRlcicsICdmaWx0ZXInKS5hdHRyKCd0eXBlJywgJ3RleHQnKSxcbiAgICAgIGlucHV0QXBwZW5kID0gc2FmZVNlbGVjdChpbnB1dEdyb3VwLCAnZGl2JywgJ2lucHV0LWdyb3VwLWFwcGVuZCcpLFxuICAgICAgICBpbnB1dEFwcGVuZEJ1dHRvbiA9IHNhZmVTZWxlY3QoaW5wdXRBcHBlbmQsICdhJywgJ2Nsb3NlLWJ1dHRvbicpLmNsYXNzZWQoJ2J0biBidG4tb3V0bGluZS1zZWNvbmRhcnknLCB0cnVlKSxcbiAgICAgICAgICBpbnB1dEFwcGVuZEJ1dHRvbkljb24gPSBzYWZlU2VsZWN0KGlucHV0QXBwZW5kQnV0dG9uLCAnaScsICdmYSBmYS1jbG9zZScpLFxuXG5cbiAgICBjbG9zZUJ1dHRvbiA9IGlucHV0QXBwZW5kQnV0dG9uLFxuXG4gICAgclRhYmxlID0gc2FmZVNlbGVjdChjb250YWluZXIsICdkaXYnLCAndGFibGUtcmVzcG9uc2l2ZScpLFxuICAgICAgdGFibGUgPSBzYWZlU2VsZWN0KHJUYWJsZSwgJ3RhYmxlJywgJ3RhYmxlJylcbiAgICAgIC5jbGFzc2VkKCd0YWJsZS1ob3ZlcicsIHRydWUpXG4gICAgICAuY2xhc3NlZCgndGFibGUtYm9yZGVyZWQnLCB0cnVlKVxuICAgICAgLmNsYXNzZWQoXCJ0YWJsZS1zdHJpcGVkXCIsIHRydWUpLFxuICAgICAgICB0SGVhZCA9IHNhZmVTZWxlY3QodGFibGUsICd0aGVhZCcpXG4gICAgICAgIC5jbGFzc2VkKFwidGhlYWQtZGFya1wiLCB0cnVlKSxcbiAgICAgICAgICBoZWFkZXIgPSBzYWZlU2VsZWN0KHRIZWFkLCAndHInKSxcbiAgICAgICAgdEJvZHkgPSBzYWZlU2VsZWN0KHRhYmxlLCAndGJvZHknKVxuXG5cbiAgICB2YXJcbiAgICByb3dzID0gZDMua2V5cyhkYXRhKSxcbiAgICBjb2xzID0gZDMua2V5cyhkYXRhW3Jvd3NbMF1dKVxuXG4gICAgdmFyIHRoID0gbWFrZUNvbHVtbnMoaGVhZGVyLCBjb2xzKVxuICAgIHZhciB0ciA9IG1ha2VSb3dzKHRCb2R5LCByb3dzKVxuICAgIHZhciB0ciA9IHBvcHVsYXRlUmVjb3Jkcyh0ciwgY29scylcblxuXG5cbiAgICBpbnB1dC5vbignaW5wdXQnLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhclxuICAgICAgdmFsID0gaW5wdXQucHJvcGVydHkoJ3ZhbHVlJyksXG4gICAgICByZWcgPSBuZXcgUmVnRXhwKHZhbCwgJ2dpJyksXG4gICAgICB1c2VcbiAgICAgIGlmICh2YWwgPT0gJycpIHt1c2UgPSByb3dzfSBlbHNlIHtcbiAgICAgICAgdXNlID0gW11cbiAgICAgICAgcm93cy5tYXAoZnVuY3Rpb24ociwgaSl7XG4gICAgICAgICAgdmFyIHJvdyA9IGRhdGFbcl1cbiAgICAgICAgICB2YXIgZmllbGRKb2luID0gY29scy5tYXAoZnVuY3Rpb24oYywgail7XG4gICAgICAgICAgICByZXR1cm4gZmllbGRGdW5jdGlvbihyb3csIGMsIHJvd1tjXSlcbiAgICAgICAgICAgIC8vIHJldHVybiByb3dbY11cbiAgICAgICAgICB9KS5qb2luKCcnKVxuICAgICAgICAgIHZhciBtYXRjaCA9IGZpZWxkSm9pbi5tYXRjaChyZWcpXG4gICAgICAgICAgaWYgKG1hdGNoID09IG51bGwgfHwgbWF0Y2guam9pbignJykgPT0gJycpIHt9XG4gICAgICAgICAgZWxzZSB7IHVzZS5wdXNoKHIpIH1cbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgdHIgPSBtYWtlUm93cyh0Qm9keSwgdXNlKVxuICAgICAgdHIgPSBwb3B1bGF0ZVJlY29yZHModHIsIGNvbHMpXG4gICAgfSlcblxuICAgIGNsb3NlQnV0dG9uLm9uKCdjbGljaycsIGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgaW5wdXQucHJvcGVydHkoJ3ZhbHVlJywgJycpLmRpc3BhdGNoKCdpbnB1dCcpXG4gICAgfSlcblxuICB9XG5cbiAgZnVuY3Rpb24gbWFrZUNvbHVtbnMoaGVhZGVyLCBjb2xzKSB7XG4gICAgdmFyIHRoID0gaGVhZGVyLnNlbGVjdEFsbCgndGgnKVxuICAgIHRoID0gdGguZGF0YShjb2xzKVxuICAgIHRoLmV4aXQoKS5yZW1vdmUoKVxuICAgIHRoID0gdGgubWVyZ2UodGguZW50ZXIoKS5hcHBlbmQoJ3RoJykpXG4gICAgdGguYXR0cignc2NvcGUnLCAnY29sJykudGV4dChmdW5jdGlvbihkLCBpKXtyZXR1cm4gZH0pXG4gICAgcmV0dXJuIHRoXG4gIH1cblxuICBmdW5jdGlvbiBtYWtlUm93cyhib2R5LCByb3dzKSB7XG4gICAgdmFyIHRyID0gYm9keS5zZWxlY3RBbGwoJ3RyJylcbiAgICB0ciA9IHRyLmRhdGEocm93cylcbiAgICB0ci5leGl0KCkucmVtb3ZlKClcbiAgICB0ciA9IHRyLm1lcmdlKHRyLmVudGVyKCkuYXBwZW5kKCd0cicpKVxuICAgIHJldHVybiB0clxuICB9XG5cbiAgZnVuY3Rpb24gcG9wdWxhdGVSZWNvcmRzKHJvd3MsIGNvbHMpIHtcbiAgICByb3dzLmVhY2goZnVuY3Rpb24ociwgaSl7XG4gICAgICB2YXIgcmVjb3JkID0gZGF0YVtyXSxcbiAgICAgIHQgPSBkMy5zZWxlY3QodGhpcylcblxuICAgICAgdmFyIGZpZWxkcyA9IHQuc2VsZWN0QWxsKCd0ZCcpXG4gICAgICBmaWVsZHMgPSBmaWVsZHMuZGF0YShjb2xzKVxuICAgICAgZmllbGRzLmV4aXQoKS5yZW1vdmUoKVxuICAgICAgZmllbGRzID0gZmllbGRzLm1lcmdlKGZpZWxkcy5lbnRlcigpLmFwcGVuZCgndGQnKSlcblxuICAgICAgZmllbGRzLmF0dHIoJ3Njb3BlJywgZnVuY3Rpb24oZiwgail7IHJldHVybiBqID09IDAgfSlcbiAgICAgIC5odG1sKGZ1bmN0aW9uKGYsIGopeyByZXR1cm4gZmllbGRGdW5jdGlvbihyZWNvcmQsIGYsIHJlY29yZFtmXSkgfSlcblxuICAgIH0pXG4gICAgcmV0dXJuIHJvd3NcbiAgfVxuXG5cblxuICByZXR1cm4gZmlsdGVyVGFibGVcbn1cbiJdLCJuYW1lcyI6WyJ1bmlxdWVFbGVtZW50cyIsInZhbHVlIiwiaW5kZXgiLCJzZWxmIiwiaW5kZXhPZiIsImdldFRyYW5zbGF0aW9uIiwidHJhbnNmb3JtIiwiZyIsImRvY3VtZW50IiwiY3JlYXRlRWxlbWVudE5TIiwidW5kZWZpbmVkIiwic2V0QXR0cmlidXRlTlMiLCJtYXRyaXgiLCJiYXNlVmFsIiwiY29uc29saWRhdGUiLCJlIiwiZiIsIm1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2UiLCJoZXgiLCJsdW0iLCJTdHJpbmciLCJyZXBsYWNlIiwibGVuZ3RoIiwiYyIsImkiLCJyZ2IiLCJwYXJzZUludCIsInN1YnN0ciIsIk1hdGgiLCJyb3VuZCIsIm1pbiIsIm1heCIsInRvU3RyaW5nIiwicXVhcnRpbGVzIiwiZGF0YSIsInFLZXlzIiwicTIiLCJkMyIsIm1lZGlhbiIsImxvd2VyIiwiZmlsdGVyIiwieCIsInVwcGVyIiwicTEiLCJxMCIsInEzIiwicTQiLCJrMCIsImsxIiwiazIiLCJrMyIsIms0Iiwib2JqIiwiaHlwZW5hdGUiLCJBcnJheSIsInByb3RvdHlwZSIsInNsaWNlIiwiY2FsbCIsImFyZ3VtZW50cyIsImpvaW4iLCJudW1iZXIiLCJwcmVjaXNpb24iLCJzaGlmdCIsInJldmVyc2VTaGlmdCIsIm51bUFycmF5Iiwic3BsaXQiLCJnZXRDb250YWluaW5nU1ZHIiwiZWxlbWVudCIsInBhcmVudCIsInBhcmVudEVsZW1lbnQiLCJ0YWciLCJ0YWdOYW1lIiwidG9Mb3dlckNhc2UiLCJzYWZlU2VsZWN0Iiwic2VsIiwiY2xzIiwiY2xzU3RyIiwic1NlbCIsInNlbGVjdCIsImVtcHR5IiwiYXBwZW5kIiwiY2xhc3NlZCIsImF0dHIiLCJ0aWNrUmFuZ2UiLCJuIiwiYSIsInMiLCJwdXNoIiwiaGFzUSIsImFycmF5IiwiaXRlbSIsImluY2x1ZGVzIiwidW5pcXVlIiwiZmxhdHRlbiIsImZsYXQiLCJtYXAiLCJpc0FycmF5IiwiY29uY2F0Iiwid2hpY2hCaW4iLCJiaW5zIiwiaiIsImNvbnNvbGVHcm91cCIsIm5hbWUiLCJ3aW5kb3ciLCJkM3NtIiwiZGVidWdRIiwiZ3JvdXAiLCJjb25zb2xlR3JvdXBFbmQiLCJncm91cEVuZCIsImxvZyIsImZ1bmMiLCJtc2ciLCJ0YWJsZSIsInNldHVwQ29udGFpbmVyIiwic2VsZWN0aW9uIiwibmFtZXNwYWNlIiwicmVjdCIsImZpbGwiLCJjb250YWluZXIiLCJ5Iiwid2lkdGgiLCJoZWlnaHQiLCJiZ1JlY3QiLCJkZWZzIiwiY3BSZWN0IiwicmFpc2UiLCJjYWxjdWxhdGVXaWR0aE9mT2JqZWN0IiwiZnJlZVNwYWNlIiwibnVtYmVyT2ZPYmplY3RzIiwibWluT2JqZWN0V2lkdGgiLCJtYXhPYmplY3RXaWR0aCIsInNpemVPZlNwYWNlciIsIm92ZXJmbG93USIsInJlbWFpbmluZ1NwYWNlIiwib2JqZWN0V2lkdGgiLCJjYWxjdWxhdGVXaWR0aE9mU3BhY2VyIiwiYmFzZVNwYWNlclNpemUiLCJzcGFjZXJzQXRFYWNoTGV2ZWwiLCJzcGFjZXJzTmVlZGVkQXRFYWNoTGV2ZWwiLCJsZXZlbCIsImxldmVsRGF0YSIsInJlZHVjZSIsImIiLCJpc05hTiIsIndoaXNrZXJQYXRoIiwiZGlyIiwidyIsImgiLCJwZXIiLCJvIiwiaGgiLCJ3dyIsInAiLCJncm91cGluZ1NwYWNlciIsInNjYWxlTGluZWFyIiwiZWFzZVNpbiIsImN1ciIsImQiLCJob3Jpem9udGFsUSIsIm91dGVyV2lkdGgiLCJjdXJyZW50IiwiY3VycmVudE5vZGUiLCJub2RlIiwic2VsZWN0QWxsIiwidHJhbnNpdGlvbiIsImR1cmF0aW9uIiwidHJhbnNpdGlvbkR1cmF0aW9uIiwiZWFzZSIsImVhc2VGdW5jIiwicmVtb3ZlIiwicmVjdXJzaXZlbHlQb3NpdGlvbiIsImN1cnJlbnRTZWxlY3Rpb24iLCJlbnRlciIsImV4aXQiLCJtZXJnZSIsImV4aXRGdW5jdGlvbiIsImVhY2giLCJ0aGlzIiwibGV2ZWxTcGFjZXIiLCJzcGFjZXJTaXplIiwibW92ZSIsImN1cnJlbnRFbGVtZW50IiwidCIsImVudGVyRnVuY3Rpb24iLCJtb3ZlYnkiLCJzY2FsZSIsInRvUmVtb3ZlIiwib2JqZWN0Q2xhc3MiLCJvYmplY3RTaXplIiwic2l6ZSIsIl8iLCJjb2xvckZ1bmN0aW9uIiwiaW50ZXJwb2xhdGVSZ2IiLCJjb2xvcnMiLCJrIiwidiIsImNhdGVnb3J5IiwiaW50ZXJwb2xhdGUiLCJpbnRlcnBvbGF0aW9uIiwiZG9tYWluIiwiZGF0YUV4dGVudCIsInJhbmdlIiwiaGVscGVyU2NhbGUiLCJtYXRjaCIsImtleSIsInR5cGUiLCJob3ZlclEiLCJvcGFjIiwiZmlsbE9wYWNpdHkiLCJzdHJva2VPcGFjaXR5IiwiY29sb3JCeSIsImNhdGVnb3JpZXMiLCJtb2RpZnlPcGFjaXR5IiwidmFsdWVFeHRyYWN0b3IiLCJjYXQiLCJjYXRlZ29yeUV4dHJhY3RvciIsInRvb2x0aXAiLCJrZXlzIiwidmFsdWVzIiwiaGVhZGVyIiwib24iLCJtb3VzZW1vdmUiLCJjdXJyZW50RGF0YSIsIm1vdXNlIiwiZGl2Iiwic3R5bGUiLCJjYXJkQm9keSIsInRCb2R5IiwidGV4dCIsInRyIiwicm93S2V5Iiwicm93SW5kZXgiLCJiYm94IiwiZ2V0Qm91bmRpbmdDbGllbnRSZWN0IiwiaW5uZXJXaWR0aCIsInNjcm9sbFgiLCJldmVudCIsInBhZ2VYIiwiaW5uZXJIZWlnaHQiLCJzY3JvbGxZIiwicGFnZVkiLCJzZWxlY3RGaWx0ZXIiLCJzZWxlY3Rpb25OYW1lIiwiZGVmYXVsdFZhbHVlIiwibGFzdFZhbHVlIiwic2VsZWN0QXBwZW5kQnV0dG9uIiwiaW5wdXRHcm91cCIsImlucHV0IiwiaW5wdXRBcHBlbmRCdXR0b24iLCJvcHRpb25zIiwiY2xvc2VCdXR0b24iLCJjdXJyZW50U3R5bGUiLCJwcm9wZXJ0eSIsImRpc3BhdGNoIiwidXNlIiwidmFsIiwicmVnIiwiUmVnRXhwIiwib3B0aW9uIiwiY3VycmVudE9wdGlvbiIsInBhcnNlRmxvYXQiLCJsYXNzbyIsInN2ZyIsImNoYXJ0Q29udGFpbmVyIiwiY2hhcnRPZmZzZXQiLCJvYmplY3RzT2Zmc2V0IiwiZXZlbnRDYXRjaGVyIiwieFNjYWxlIiwicGF0aCIsImxpbmUiLCJ5U2NhbGUiLCJjdXJ2ZSIsImN1cnZlTGluZWFyQ2xvc2VkIiwiaW5zdGFuY2UiLCJhbmltYXRpb25SYXRlIiwib3BhY2l0eSIsImRhc2hBcnJheSIsInN0cm9rZSIsInN0cm9rZVdpZHRoIiwibGFzc29lZFN0cm9rZSIsImxhc3NvZWRTdHJva2VXaWR0aCIsImVhc2VFeHAiLCJwYXRocyIsInBFbnRlciIsImFjdGl2ZVEiLCJvYmplY3RDb250YWluZXIiLCJhbGxQb2ludHMiLCJyZW5kZXIiLCJwcmV2ZW50RGVmYXVsdCIsInN0b3BQcm9wYWdhdGlvbiIsImFkZEV2ZW50TGlzdGVuZXIiLCJkcmFnIiwicmVtb3ZlRXZlbnRMaXN0ZW5lciIsImN1cnJlbnRQb2ludHMiLCJhcHBseVBhdGhBdHRyaWJ1dGVzIiwiY29sb3IiLCJ3aGljaCIsInB0IiwiaW52ZXJ0IiwibGFzdFB0IiwicDEiLCJwMiIsInNxcnQiLCJldWNsaWRlYW5EaXN0YW5jZSIsInRpY2tEaXN0YW5jZSIsInRpY2siLCJkZXRlY3QiLCJsYXNzb3MiLCJib3giLCJhYnNvbHV0ZVBvc2l0aW9uIiwibGVmdCIsInRvcCIsInJpZ2h0IiwiYm90dG9tIiwiYm94UHRzIiwiaW5BbnlMYXNzb1EiLCJsYXNzb1BvaW50cyIsImV2ZXJ5IiwicG9seWdvbkNvbnRhaW5zIiwiY29vcmQiLCJ1cGRhdGVPYmplY3RzIiwiYXBwbHlPYmplY3RBdHRyaWJ1dGVzIiwic2V0USIsInByZUxhc3NvRmlsbCIsInByZUxhc3NvU3Ryb2tlIiwicHJlTGFzc29TdHJva2VXaWR0aCIsImxhc3NvZWRGaWxsIiwia2V5RnJhbWVzIiwiaHRtbCIsImRyYXciLCJ0b2dnbGUiLCJzdGF0ZSIsInRoaXNTVkciLCJhYnNvbHV0ZSIsImVsZW1lbnRQb3NpdGlvbiIsInN2Z1Bvc2l0aW9uIiwicmVsYXRpdmVQb3NpdGlvblRvIiwiYXhpcyIsImxhYmVsIiwidGlja1RpY2tMYWJlbFNwYWNlciIsInRpY2tMYWJlbE1hcmdpbiIsInJldmVyc2VTY2FsZVEiLCJvcmllbnQiLCJ2ZXJ0aWNhbFEiLCJiZ2NwUmVjdCIsInNwYWNlWCIsInNwYWNlWSIsImd1aWRlTGluZXNRIiwiZ3VpZGVsaW5lU3BhY2UiLCJ0aWNrTGFiZWxNYXhGb250U2l6ZSIsImJhY2tncm91bmRGaWxsIiwidGlja0xhYmVsVGV4dEFuY2hvciIsInRpY2tMYWJlbFJvdGF0aW9uIiwidGlja0RhdGEiLCJjYXRlZ29yaWNhbFEiLCJncm91cGluZyIsInRpY2tMYWJlbHMiLCJudW1iZXJPZlRpY2tzIiwiZXh0ZW50IiwidGlja1ZhbHVlcyIsImZsYXRUaWNrRGF0YSIsInNwYWNlIiwicmV2ZXJzZSIsImRvbWFpblBhZGRpbmciLCJtaW5PYmplY3RTaXplIiwibWF4T2JqZWN0U2l6ZSIsIm9iamVjdFNwYWNlciIsIm9iakNsYXNzIiwic3BhY2VyRnVuY3Rpb24iLCJtb3ZlWEJ5IiwibW92ZVlCeSIsIm10IiwiZGF0dW0iLCJkaXN0IiwibGFiZWxOYW1lR3JvdXAiLCJsYWJlbEVsZW1lbnQiLCJ0aGF0IiwidGlja0xlbmd0aCIsInRpY2tTdHJva2UiLCJ0aWNrU3Ryb2tlV2lkdGgiLCJzdHJpbmciLCJjaGFycyIsInJvdW5kVG8iLCJ0aWNrTGFiZWxGb250U2l6ZSIsImdldENvbXB1dGVkVGV4dExlbmd0aCIsImxhYmVsSG92ZXIiLCJsYWJlbEhvdmVyT2ZmIiwidGlja0xhYmVsT25DbGljayIsImd1aWRlTGluZVN0cm9rZSIsImd1aWRlTGluZVN0cm9rZVdpZHRoIiwibGluZVN0cm9rZSIsImxpbmVTdHJva2VXaWR0aCIsInBhcmVudE5vZGUiLCJ0aWNrTGFiZWxPbkhvdmVyRnVuYyIsImdsaW5lIiwibWlub3JRIiwiaWkiLCJ0aWNrTGFiZWxNaW5Gb250U2l6ZSIsInRpY2tMYWJlbEZ1bmMiLCJiYXIiLCJrZXlBIiwia2V5QiIsImRlc2NlbmRpbmciLCJDRiIsIlRUaXAiLCJiYXJQZXJjZW50IiwiYmFyS2V5cyIsIm9yZGVyZWQiLCJzb3J0Iiwic29ydGluZ0Z1bmN0aW9uIiwiYmFyVmFsdWVzIiwiZGVmYXVsdEV4aXQiLCJub2RlcyIsInBhcmVudEluZGV4QXJyYXkiLCJOdW1iZXIiLCJmaWxsQ29sb3IiLCJzdHJva2VDb2xvciIsImJhclN0cm9rZVdpZHRoIiwiYnViYmxlSGVhdG1hcCIsInhLZXkiLCJ5S2V5IiwicktleSIsInZLZXkiLCJ4S2V5U29ydGluZ0Z1bmN0aW9uIiwieEV4dHJhY3RvciIsInlLZXlTb3J0aW5nRnVuY3Rpb24iLCJ5RXh0cmFjdG9yIiwiYmhtIiwiY2VsbEtleXMiLCJyRXh0cmFjdG9yIiwidkV4dHJhY3RvciIsInhWYWx1ZXMiLCJ5VmFsdWVzIiwieERpbSIsInlEaW0iLCJyVmFsdWVzIiwieVNpemUiLCJ4U2l6ZSIsInlTcGFjZXIiLCJ5U3BhY2VyU2l6ZSIsInhTcGFjZXIiLCJ4U3BhY2VyU2l6ZSIsImNlbGxzIiwidlZhbHVlcyIsInJhZGl1cyIsInNjYWxlZCIsImJ1YmJsZVN0cm9rZVdpZHRoIiwiaGVhdG1hcCIsImhtIiwieU1pbk9iamVjdFNpemUiLCJ5TWF4T2JqZWN0U2l6ZSIsInhNaW5PYmplY3RTaXplIiwieE1heE9iamVjdFNpemUiLCJsb29rdXAiLCJwb3NpdGlvbmVkQ2VsbEtleXMiLCJsb29rdXBWYWx1ZSIsIm9iamVjdFN0cm9rZVdpZHRoIiwiYm94d2hpc2tlciIsInF1YXJ0aWxlc0tleSIsInF1YXJ0aWxlc0tleXMiLCJib3hLZXlzIiwiYm94VmFsdWVzIiwid2hpc2siLCJ1V2hpc2siLCJsV2hpc2siLCJxdWFydCIsInVRdWFydCIsImxRdWFydCIsIm1RdWFydCIsImJveFN0cm9rZVdpZHRoIiwiciIsImRpZiIsImRkIiwid2hpc2tlcldpZHRoUGVyY2VudCIsIndoaXNrZXJTdHJva2VXaWR0aCIsImRhdGF0b2dnbGUiLCJ4QXhpc09wdGlvbnMiLCJ5QXhpc09wdGlvbnMiLCJ5QXhpc1NlbGVjdFEiLCJ4QXhpc1NlbGVjdFEiLCJ1cGRhdGVGdW5jdGlvbiIsImN1cnJlbnRLZXlzIiwidmFscyIsImZpbHRlclNlbGVjdHMiLCJkYXRhb3B0cyIsImRvRW50ZXIiLCJzZiIsInNjYXR0ZXIiLCJwb2ludEtleXMiLCJ2YWx1ZUV4dHJhY3RvclgiLCJ2YWx1ZUV4dHJhY3RvclkiLCJ2YWx1ZUV4dHJhY3RvclIiLCJleHRlbnRYIiwidmFsdWVzWCIsImRvbWFpblBhZGRpbmdYIiwiZXh0ZW50WSIsInZhbHVlc1kiLCJkb21haW5QYWRkaW5nWSIsImV4dGVudFIiLCJ2YWx1ZXNSIiwiZG9tYWluUGFkZGluZ1IiLCJtaW5SYWRpdXMiLCJtYXhSYWRpdXMiLCJwb2ludHMiLCJwRXhpdCIsInNjYWxlWCIsInNjYWxlWSIsInNjYWxlUiIsInBvaW50U3Ryb2tlV2lkdGgiLCJwbG90Wm9vbSIsImNoYXJ0IiwieEF4aXMiLCJ5QXhpcyIsImNoYXJ0U2VsIiwieEF4aXNTZWwiLCJ5QXhpc1NlbCIsInNldExvY2tzIiwiY2hhcnRPYmpTZWwiLCJjaGFydE9ialRyYW5zIiwiY29zIiwiZ2V0QkJveCIsInhMb2NrIiwieUxvY2siLCJ6b29tIiwiY2hhcnRCb3giLCJ4QXhpc0JveCIsInlBeGlzQm94IiwiZXZlbnRUeXBlIiwiZGVsdGFZIiwid2hlZWxTcGVlZCIsInNoaWZ0USIsInNoaWZ0S2V5IiwiYXBwbHlYIiwiYXBwbHlZIiwieEF4aXNPYmpTZWwiLCJ5QXhpc09ialNlbCIsInJlc2V0IiwibXVsdGlQbG90Wm9vbSIsInhDb21wb25lbnRzIiwieUNvbXBvbmVudHMiLCJ4Q29tcG9uZW50c1NlbCIsInlDb21wb25lbnRzU2VsIiwieENvbXBvbmVudE9ialNlbCIsInlDb21wb25lbnRPYmpTZWwiLCJ2aW9saW4iLCJiYXNlIiwibWluTWF4SGV4U2NhbGUiLCJzY2FsZWRDb2xvciIsIm1vZCIsInF1YXJ0aWxlS2V5cyIsInBvaW50c1Rvb2x0aXAiLCJ2aW9saW5LZXkiLCJ2aW9saW5EYXRhIiwidmlvbGluUG9pbnRLZXkiLCJ2aW9saW5Qb2ludERhdGEiLCJjYWxjVmFsdWVzIiwiY2FsY3VsYXRlVmlvbGluVmFsdWVzIiwidmlvbGluUG9pbnRzIiwidmlvbGluUG9pbnRzRXh0cmFjdG9yIiwidmlvbGluUG9pbnRzS2V5cyIsInZpb2xpblBvaW50c1ZhbHVlcyIsInBrIiwidmlvbGluUG9pbnRWYWx1ZUV4dHJhY3RvciIsInBvaW50UXVhcnRpbGVzIiwiYmlubmVkIiwiaGlzdG9ncmFtIiwiZnJlcXVlbmNpZXMiLCJiaW4iLCJtaW5Db250b3VyUG9pbnQiLCJtYXhDb250b3VyUG9pbnQiLCJ2aW9saW5Db250b3VyUG9pbnRzIiwieDAiLCJ4MSIsImNvbnRvdXIiLCJwb2ludFZhbHVlcyIsIm5lZWRlZFZpb2xpblZhbHVlcyIsInZrIiwidmlvbGluS2V5cyIsImZyZXF1ZW5jeU1heCIsInZTY2FsZSIsImxBcmVhIiwiY3VydmVCYXNpcyIsInJBcmVhIiwiYXJlYSIsImxhIiwicmEiLCJxdWFydHMiLCJwb2ludHNRIiwicHRzQ29udGFpbmVyIiwicHRzIiwicHRzRW50ZXIiLCJwTWluIiwicE1heCIsInBvaW50UmFkaXVzIiwicG9pbnRLZXkiLCJyYW5kb20iLCJwb2ludENvbG9yRnVuYyIsImNyZWF0ZUV2ZW50IiwiaW5pdEV2ZW50IiwiZGlzcGF0Y2hFdmVudCIsInRvb2x0aXBLZXkiLCJxdWFydGlsZUtleSIsInZpb2xpblZhbHVlcyIsIm51bWVyaWNMZWdlbmQiLCJmb250U2l6ZSIsInRleHRDb2xvciIsImxlZ2VuZCIsImxpbmVhckdyYWRpZW50IiwibSIsImNhdGVnb3JpY0xlZ2VuZCIsImFzY2VuZGluZyIsImNhdEtleXMiLCJjeCIsImN5IiwibGFzc29XaWRnZXQiLCJtYXhOdW1iZXJPZkdyb3VwcyIsImRhdGFFeHRyYWN0b3IiLCJvbkVycm9yIiwic3VibWl0IiwiY2xpY2tTZW5kIiwicmVtb3ZlQnRuQ2xpY2tUb1JlbW92ZSIsInRhYnMiLCJwYW5lcyIsInJlbWFpbmluZ1RhYnMiLCJsYXN0VGFiIiwiY3VyVGV4dCIsInBvcHVsYXRlUGFuZSIsInBhbmUiLCJsZWFkIiwiYnRucyIsImNOIiwiYnRuIiwibGFzc29CdG4iLCJtYWtlTGFzc29CdXR0b24iLCJjdXJyZW50TGFzc28iLCJjbGVhckJ0biIsImxhc3NvQnRuVG9nZ2xlIiwibGFzIiwidGFibGVEYXRhIiwiZXh0cmFjdGVkIiwibWFrZUNsZWFyQnV0dG9uIiwibW9uaXRvckxhc3NvQnV0dG9uU3RhdGUiLCJ0YXJnZXQiLCJtYWtlVGFibGUiLCJoZWFkUiIsImJvZHkiLCJoZWFkZXJLZXlzIiwiaGVhZGVyQ29scyIsInVwZGF0ZVRhYmxlSGVhZGVyQ29sdW1ucyIsImJvZHlSb3dzIiwidXBkYXRlVGFibGVSb3dzIiwicm93RGF0YSIsImNvbHMiLCJzcGxpY2UiLCJtYWtlTmV3R3JvdXAiLCJncyIsIm5ld0dyb3VwTnVtYmVyIiwibGkiLCJpbnNlcnQiLCJ0eHQiLCJpbnNlcnRUYWIiLCJtYWtlVGFiUGFuZSIsImNhcmQiLCJ0YWJMaXN0IiwidGFiQ29udGVudCIsInJpZ2h0VGFicyIsInVwc2V0Iiwic2V0VmFsdWVzIiwiaW50ZXJzZWN0aW9uVmFsdWVzIiwieE9iamVjdFNpemUiLCJjaXJjbGVTdHJva2VXaWR0aCIsInNldEV4dHJhY3RvciIsImludGVyc2VjdGlvbkV4dHJhY3RvciIsImVsZW1lbnRFeHRyYWN0b3IiLCJlbGVtZW50VmFsdWVzIiwieU9iamVjdFNwYWNlciIsInNldEtleVNvcnRpbmdGdW5jdGlvbiIsImludGVyc2VjdGlvbktleVNvcnRpbmdGdW5jdGlvbiIsInhPYmplY3RTcGFjZXIiLCJ5T2JqZWN0U2l6ZSIsInNldCIsImludGVyc2VjdGlvbiIsImludGVyc2VjdGlvblRvdGFscyIsInRvdGFscyIsInRvdGFsIiwic2V0VG90YWxzIiwiZmlsdGVyVGFibGUiLCJzb3J0USIsInJlY29yZCIsImNvbHVtbktleSIsInJlY29yZFZhbHVlIiwicm93cyIsInRoIiwibWFrZUNvbHVtbnMiLCJwb3B1bGF0ZVJlY29yZHMiLCJtYWtlUm93cyIsInJvdyIsImZpZWxkRnVuY3Rpb24iLCJmaWVsZHMiLCJleHRyYWN0VmlvbGluVmFsdWVzIiwidmFsdWVFeHRyYWN0b3JGdW5jdGlvbiIsInFLZXkiLCJtaW5Qb2ludCIsIm1heFBvaW50IiwiaW50ZXJwb2xhdGVDb2xvcnMiLCJpbnRlcnBvbGF0ZVJnYkJhc2lzIiwidHJ1bmNhdGVUZXh0Iiwic2V0dXBTdGFuZGFyZENoYXJ0Q29udGFpbmVycyIsIm1hcmdpbnMiLCJheGVzIiwibGVnIiwibWFyZ2luIiwicG9zIiwiSGVpZ2h0Iiwic3ZnU3BhY2UiLCJtYXJnUHgiLCJjaGFydFNwYWNlIiwiYXhlc1NwYWNlIiwibGVnUmVjdCIsImRyYXdpbmdTcGFjZSIsInlBeGlzUmVjdCIsInBsb3RSZWN0IiwieEF4aXNSZWN0IiwibXlMb2ciLCJ3YXJuIiwiY29uc29sZSIsImluZm8iLCJlcnJvciIsInJlc2l6ZURlYm91bmNlIiwid2FpdCIsInJlc2l6ZSIsImltbWVkaWF0ZSIsInRpbWVvdXQiLCJjb250ZXh0IiwiYXJncyIsImNhbGxOb3ciLCJzZXRUaW1lb3V0IiwiYXBwbHkiLCJkZWJvdW5jZSJdLCJtYXBwaW5ncyI6ImtDQWVPLFNBQVNBLEVB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 diff --git a/build/js/d3sm.min.v0.0.4.js b/build/js/d3sm.min.v0.0.4.js deleted file mode 100644 index b4ca54b6623e33c3a6a7b2a02c43fff5e354bca6..0000000000000000000000000000000000000000 --- a/build/js/d3sm.min.v0.0.4.js +++ /dev/null @@ -1,2 +0,0 @@ -var d3sm=function(t){"use strict";function e(t,e,n){return n.indexOf(t)===e}function n(t){var e=document.createElementNS("http://www.w3.org/2000/svg","g");t=void 0==t?"translate(0,0)":t,e.setAttributeNS(null,"transform",t);var n=e.transform.baseVal.consolidate().matrix;return[n.e,n.f]}function r(t,e){(t=String(t).replace(/[^0-9a-f]/gi,"")).length<6&&(t=t[0]+t[0]+t[1]+t[1]+t[2]+t[2]),e=e||0;var n,r,o="#";for(r=0;r<3;r++)n=parseInt(t.substr(2*r,2),16),o+=("00"+(n=Math.round(Math.min(Math.max(0,n+n*e),255)).toString(16))).substr(n.length);return o}function o(t,e){var n=d3.median(t),r=t.filter(function(t){return tn}),a=void 0==(a=d3.median(r))?n:a,i=void 0==(i=d3.min(r))?a:i,l=void 0==(l=d3.median(o))?n:l,c=void 0==(c=d3.max(o))?l:c,u="q0",s="q1",d="q2",f="q3",h="q4",g={};return void 0!=e&&5==e.length&&(u=e[0],s=e[1],d=e[2],f=e[3],h=e[4]),g[u]=i,g[s]=a,g[d]=n,g[f]=l,g[h]=c,g}function a(){return Array.prototype.slice.call(arguments).join("-")}function i(t,e){var n=function(t,e,n){n&&(e=-e);var r=(""+t).split("e");return+(r[0]+"e"+(r[1]?+r[1]+e:e))};return n(Math.round(n(t,e,!1)),e,!0)}function l(t){var e=t.parentElement,n=e.tagName.toLowerCase();return"svg"===n?e:"html"!==n?l(e):void 0}function c(t,e,n){var r=void 0==n?"":"."+n,o=t.select(e+r).empty()?t.append(e):t.select(e+r);return o.classed(r.replace(".",""),!0).attr("transform",void 0==o.attr("transform")?"translate(0,0)":o.attr("transform"))}function u(t,e,n){for(var r=[t],o=(e-t)/(n-1),a=0;a1?o:t*o),l=(i=i<0?0:i)/e;return a&&void 0!=n&&l=r.length?r.push(e.length-1):r[n]+=e.length-1;e.map(function(e,o){Array.isArray(e)&&t(e,n,r)});return r}(t);o=(e-n*r)/i.map(function(t,e){return 1*t/(e+1)}).reduce(function(t,e){return t+e},0);return isNaN(o)?0:o}function b(t,e,n,r,o,a,i){if("up"!=t&&"top"!=t&&1!=t||(t=!0),"down"!=t&&"bottom"!=t&&0!=t||(t=!1),i=void 0==i?"horizontal":i,a=void 0==a?1:a,"horizontal"!=i){var l=o*a,c=(r=t?r:-r,t?e+r:e),u=t?e:e+r,s=t?c:u;return f="M "+c+" "+o/2+" L "+u+" "+o/2+" M "+s+" "+(o/2-l/2)+" L "+s+" "+(o/2+l/2)+" "}var d=r*a,f="M "+r/2+" "+(c=t?n+o:n)+" L "+r/2+" "+(u=t?n:n+o)+" h "+-d/2+" 0 h "+d+" 0 ";return f}function k(){var t,e,n,r=!0,o=d3.scaleLinear(),a="category",i="d3sm-groupped-item",l=1e3,c=d3.easeSin,u="spacer",s=function(t){t.attr("transform",function(t,e){return"translate("+(r?window.outerWidth:0)+","+(r?0:window.outerWidth)+")"})},d=function(t){m("groupingSpacer","exiting with",{current:t,currentNode:t.node()}),t.selectAll("g").classed("to-remove",!0),t.transition().duration(.9*l).ease(c).attr("transform",function(t,e){return"translate("+(r?window.outerWidth:0)+","+(r?0:window.outerWidth)+")"}).remove()};function f(t,h,g){void 0==g&&(g=0);var p=t.selectAll("g."+u+'[level="'+g+'"]').data(h),m=p.enter().append("g").attr("level",g).attr("class",u),v=p.exit();p=p.merge(m),"function"==typeof d?v.each(function(t,e){d(d3.select(this))}):v.remove();var y=n/(g+1),x=0;return p.each(function(t,n){var h=d3.select(this);if(void 0==h.attr("transform")&&"function"==typeof s&&s(h),h.transition().duration(l).ease(c).attr("transform",function(t,e){return"translate("+(r?"scale"==a?o(t):x:0)+","+(r?0:"scale"==a?o(t):x)+")"}),Array.isArray(t)){x+=f(h,t,g+1);var m=h.selectAll("g."+u+'[level="'+g+'"] > g.'+i+"."+u);"function"==typeof d?m.each(function(t,e){d(d3.select(this))}):m.remove()}else{x+=e;var v=h.select("g."+u+'[level="'+g+'"] > g.'+i+"."+u);v.empty()&&(v=h.append("g").attr("class",i).classed(u,!0)),v.attr("parent-index",n);m=h.selectAll("g."+u+'[level="'+(g+1)+'"]');"function"==typeof d?m.each(function(t,e){d(d3.select(this))}):m.remove()}x+=n==p.size()-1?0:y}),x}return f.horizontalQ=function(t){return arguments.length?(r=t,f):r},f.scale=function(t){return arguments.length?(o=t,f):o},f.moveby=function(t){return arguments.length?(a=t,f):a},f.numberOfObjects=function(e){return arguments.length?(t=e,f):t},f.objectClass=function(t){return arguments.length?(i=t,f):i},f.objectSize=function(t){return arguments.length?(e=t,f):e},f.spacerSize=function(t){return arguments.length?(n=t,f):n},f.transitionDuration=function(t){return arguments.length?(l=t,f):l},f.easeFunc=function(t){return arguments.length?(c=t,f):c},f.namespace=function(t){return arguments.length?(u=t,f):u},f.enterFunction=function(t){return arguments.length?(s=t,f):s},f.exitFunction=function(t){return arguments.length?(d=t,f):d},f}var w=function(){return function(t,e){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return function(t,e){var n=[],r=!0,o=!1,a=void 0;try{for(var i,l=t[Symbol.iterator]();!(r=(i=l.next()).done)&&(n.push(i.value),!e||n.length!==e);r=!0);}catch(t){o=!0,a=t}finally{try{!r&&l.return&&l.return()}finally{if(o)throw a}}return n}(t,e);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),S=function(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);ewindow.innerWidth-window.scrollX&&(d=d3.event.pageX-b.width-15),f+b.height>window.innerHeight-window.scrollY&&(f=d3.event.pageY-b.height-15),"relative"==h.style("position")?h.style("position","absolute").style("left",d+"px").style("top",f+"px"):h.style("left",d+"px").style("top",f+"px"),h.attr("z-index",1e4)}return a.keys=function(t){return arguments.length?(e=t,a):e},a.values=function(t){return arguments.length?(n=t,a):n},a.header=function(t){return arguments.length?(r=t,a):r},a.data=function(t){return arguments.length?(o=t,a):o},a.selection=function(e){return arguments.length?(t=e,a):t},a}function A(t){var e,n="d3sm-select-filter",r="Select options:",o=void 0,i=void 0;function l(){var o=c(t,"div","input-group").classed(a(n,"container"),!0),l=(c(c(o,"div","select-prepend").classed("input-group-prepend",!0),"span","input-group-text").text(r),c(o,"select","custom-select").classed(a(n,"select"),!0)),s=c(c(o,"div","select-append").classed("input-group-prepend",!0),"a","filter-button").classed("btn btn-outline-secondary",!0),d=(c(s,"i","fa fa-filter"),c(o,"div","filter-input-group").classed("input-group",!0).classed("d-none",!0)),f=(c(c(c(d,"div","input-group-prepend"),"span","input-group-text").classed("search-button",!0),"i","fa fa-search"),c(d,"input","form-control").attr("placeholder","all").attr("type","text")),h=c(c(d,"div","input-group-append"),"a","close-button").classed("btn btn-outline-secondary",!0),g=(c(h,"i","fa fa-close"),d3.keys(e)),p=l.selectAll("option");p=(p=p.data(d3.keys(e))).merge(p.enter().append("option")).attr("value",function(t,e){return t}).text(function(t,e){return t});var m=h;s.on("click",function(t,e){var n=d.classed("d-none");d.classed("d-none",!n)}),m.on("click",function(t,e){f.property("value","").dispatch("input")}),f.on("input",function(t,n){var r,o=f.property("value"),a=new RegExp(o,"gi");""==o?r=g:(r=[],d3.keys(e).map(function(t,e){var n=t.match(a);null==n||""==n.join("")||r.push(t)})),(p=(p=l.selectAll("option")).data(r)).exit().remove(),p=p.merge(p.enter().append("option")).attr("value",function(t,e){return t}).text(function(t,e){return t});var c=u();i!=c&&(i=c,l.dispatch("change"))})}function u(){var n=t.select("select").property("value");return void 0==n||""==n?void 0==o?d3.keys(e)[0]:o:n}return l.data=function(t){return arguments.length?(e=t,l):e},l.namespace=function(t){return arguments.length?(n=t,l):n},l.selectionName=function(t){return arguments.length?(r=t,l):r},l.defaultValue=function(t){return arguments.length?(o=t,l):o},l.currentOption=u,l}function M(t){var e=t.attr("transform").split("translate("),n=w(e,2),r=(n[0],n[1].split(",")),o=w(r,2),a=o[0],i=o[1];return i.split(")"),[parseFloat(a),parseFloat(i)]}function E(t){var e,n,r,o,i,l,u,s,f,h,g="d3sm-lasso",p=!1,m=[],v=[],y=d3.line().x(function(t,e){return void 0!=s?s(t[0]):t[0]}).y(function(t,e){return void 0!=f?f(t[1]):t[1]}).curve(d3.curveLinearClosed),x=0,b=10,k="#17a2b8",w="10s",S=.3,j="5, 10",z="black",A=2,E="white",O="black",L=3,C=1e3,F=d3.easeExp;function Q(){var t,e;p&&((t=(t=c(n,"g","lasso-container").selectAll('path[instance="'+x+'"]')).data(v)).exit().remove(),e=t.enter().append("path"),V(t=t.merge(e).transition().duration(C).ease(F)))}function B(){var t=c(n,"g","lasso-container");t.selectAll('path[instance="'+x+'"]').remove();t.remove(),n.selectAll(r).classed("in-lasso",!1),Y()}function q(t){t.preventDefault(),t.stopPropagation();var r=c(n,"g","lasso-container");m=[],e.node().addEventListener("mousemove",D),e.node().addEventListener("mouseup",function(t){e.node().removeEventListener("mousemove",D),v.push(m),v=d(v)}),V(h=r.append("path").data([m]))}function V(t){t.attr("class",a(g,"lasso-path")).style("opacity",S).attr("fill",k).attr("d",y).attr("instance",x).style("stroke-dasharray",j).attr("stroke",z).attr("stroke-width",A).style("animation","lassoDash "+w+" linear").style("animation-iteration-count","infinite")}function D(t){if(void 0!=u&&u.dispatch(a(g,"drag")),1==t.which){d3.event=t;var r=d3.mouse(n.node());r=d3.mouse(e.node());if(void 0!=s&&(r[0]=s.invert(r[0])),void 0!=f&&(r[1]=f.invert(r[1])),r[0]=r[0]-i[0]-l[0],r[1]=r[1]-i[1]-l[1],m.length){var o=m[m.length-1],c=[r[0],r[1]],d=[o[0],o[1]];s&&(d[0]=s(d[0]),c[0]=s(c[0])),f&&(d[1]=f(d[1]),c[1]=f(c[1])),function(t,e){var n=t[0]-e[0],r=t[1]-e[1];return Math.sqrt(n*n+r*r)}(d,c)>b&&_(r)}else _(r)}}function _(t){if(void 0!=t){if(m.push(t),h.attr("d",y),m.length<3)return;K(v.concat([m]))}else K(v)}function K(t){return void 0==t&&(t=v),n.selectAll(r).each(function(e,n){var r=d3.select(this),o=r.absolutePosition(),a=[[o.left-i[0]-l[0],o.top-i[1]-l[1]],[o.right-i[0]-l[0],o.top-i[1]-l[1]],[o.left-i[0]-l[0],o.bottom-i[1]-l[1]],[o.right-i[0]-l[0],o.bottom-i[1]-l[1]]];void 0!=s&&(a[0][0]=s.invert(a[0][0]),a[1][0]=s.invert(a[1][0]),a[2][0]=s.invert(a[2][0]),a[3][0]=s.invert(a[3][0])),void 0!=f&&(a[0][1]=f.invert(a[0][1]),a[1][1]=f.invert(a[1][1]),a[2][1]=f.invert(a[2][1]),a[3][1]=f.invert(a[3][1]));var c=!1;for(n=0;nwindow.innerWidth&&o.style("left",d3.event.pageX-15-300+"px")}function ot(t,e){var n=d3.select(this).style("fill","black");if(d3.select(n.node().parentNode).select("line."+a(B,"tick")).attr("stroke",K).attr("stroke-width",Y),M){var o=d3.select(n.node().parentNode).select("line."+a(B,"guideline")),i=o.attr("minor");o.attr("stroke",function(t,e){return"true"==i?r(I,.8):I}).attr("stroke-width",function(t,e){return"true"==i?.8*J:J})}d3.select("#"+a(B,"guideline-tooltip")).remove()}return nt.label=function(t){return arguments.length?(m=t,nt):m},nt.tickTickLabelSpacer=function(t){return arguments.length?(X=t,nt):X},nt.tickLabelMargin=function(t){return arguments.length?(R=t,nt):R},nt.selection=function(e){return arguments.length?(t=e,nt):t},nt.orient=function(t){return arguments.length?(b=t,nt):b},nt.spaceX=function(t){return arguments.length?(w=t,nt):w},nt.spaceY=function(t){return arguments.length?(j=t,nt):j},nt.overflowQ=function(t){return arguments.length?(z=t,nt):z},nt.categoricalQ=function(t){return arguments.length?(A=t,nt):A},nt.guideLinesQ=function(t){return arguments.length?(M=t,nt):M},nt.grouping=function(t){return arguments.length?(e=t,nt):e},nt.scale=function(t){return arguments.length?(E=t,nt):E},nt.domainPadding=function(t){return arguments.length?(O=t,nt):O},nt.objectSpacer=function(t){return arguments.length?(L=t,nt):L},nt.minObjectSize=function(t){return arguments.length?(C=t,nt):C},nt.maxObjectSize=function(t){return arguments.length?(F=t,nt):F},nt.namespace=function(t){return arguments.length?(B=t,nt):B},nt.backgroundFill=function(t){return arguments.length?(Q=t,nt):Q},nt.objectClass=function(t){return arguments.length?(q=t,nt):q},nt.tickLabels=function(t){return arguments.length?(n=t,nt):n},nt.tickValues=function(t){return arguments.length?(o=t,nt):o},nt.numberOfTicks=function(t){return arguments.length?(V=t,nt):V},nt.lineStroke=function(t){return arguments.length?(D=t,nt):D},nt.lineStrokeWidth=function(t){return arguments.length?(_=t,nt):_},nt.tickStroke=function(t){return arguments.length?(K=t,nt):K},nt.tickStrokeWidth=function(t){return arguments.length?(Y=t,nt):Y},nt.tickLength=function(t){return arguments.length?(P=t,nt):P},nt.tickLabelFontSize=function(t){return arguments.length?(W=t,nt):W},nt.tickLabelMinFontSize=function(t){return arguments.length?(N=t,nt):N},nt.tickLabelMaxFontSize=function(t){return arguments.length?(T=t,nt):T},nt.tickLabelTextAnchor=function(t){return arguments.length?(l=t,nt):l},nt.tickLabelRotation=function(t){return arguments.length?(d=t,nt):d},nt.tickLabelFunc=function(t){return arguments.length?(G=t,nt):G},nt.tickLabelOnClick=function(t){return arguments.length?(H=t,nt):H},nt.guidelineSpace=function(t){return arguments.length?(h=t,nt):h},nt.guideLineStroke=function(t){return arguments.length?(I=t,nt):I},nt.guideLineStrokeWidth=function(t){return arguments.length?(J=t,nt):J},nt.transitionDuration=function(t){return arguments.length?(U=t,nt):U},nt.easeFunc=function(t){return arguments.length?($=t,nt):$},nt.objectSize=function(t){return arguments.length?(g=t,nt):g},nt.spacerSize=function(t){return arguments.length?(p=t,nt):p},nt.roundTo=function(t){return arguments.length?(tt=t,nt):tt},nt.reverseScaleQ=function(t){return arguments.length?(et=t,nt):et},nt.tickLabelOnHoverFunc=function(t){return arguments.length?(Z=t,nt):Z},nt},O.bar=function(t){var e,n,r,o,a,i,l,u,s="horizontal",d=!1,h=function(t,n){return e[t]},g=function(t,n){return d3.descending(e[t],e[n])},p=d3.scaleLinear(),m=.5,b=.05,w=50,A=100,M=2,E=j(),O="transparent",L="d3sm-bar",C="bar",F=1e3,Q=d3.easeExp,B=z(),q=1;function V(){var j="horizontal"==s||"bottom"==s||"top"==s,z=!j,V=v(t,L,{x:0,y:0,width:n,height:r},O);a=d3.keys(e),i=a.map(h);var D=void 0==o?a.sort(g):o,_=(a=f(D)).length,K=[Math.min.apply(Math,S(i))-m,Math.max.apply(Math,S(i))+m];p.domain(K).range(j?[0,r]:"right"==s?[0,n]:[n,0]);var Y=j?n:r;l=void 0==l?y(Y,_,w,A,b,d):l,u=void 0==u?x(a,Y,l,_,b,d):u;var P=k().horizontalQ(j).scale(p).moveby("category").numberOfObjects(_).objectClass(C).objectSize(l).spacerSize(u).transitionDuration(F).easeFunc(Q).namespace(L),X=P.exitFunction();P.exitFunction(function(t){void 0==l&&console.log(t.nodes(),l),X(t),t.selectAll("g").classed("to-remove",!0),t.selectAll("* > rect").transition().duration(F).attr("transform",function(t,e){return"translate(0,"+(z?0:p(K[1]))+")"}).attr("width",j?l:0).attr("height",z?l:0).remove()}),P(V,D,0);var R=[];V.selectAll("g:not(.to-remove)."+C).each(function(t,e){R.push(Number(d3.select(this).attr("parent-index")))}),E="index"==E.colorBy()?E.dataExtent([0,Math.max.apply(Math,R)]):E.dataExtent(K),V.selectAll("g."+C+":not(.to-remove)").each(function(t,n){var r=d3.select(this),o=(e[t],h(t,n)),a=(n=void 0==r.attr("parent-index")?n:r.attr("parent-index"),E(t,o,n,"fill")),i=E(t,o,n,"stroke"),u=c(r,"rect","bar-rect");void 0==u.attr("transform")&&u.attr("transform",function(t,e){return"translate(0,"+(z?0:p(K[1]))+")"}).attr("width",j?l:0).attr("height",z?l:0),u.transition().duration(F).ease(Q).attr("transform",function(t,e){return"translate("+(j?l-l*q:"right"==s?p(K[1])-p(o):l-l*q)+","+(z?l-l*q:p(K[1])-p(o))+")"}).attr("width",j?l*q:p(o)).attr("height",z?l*q:p(o)).attr("fill",a).attr("stroke",i).attr("stroke-width",M),r.on("mouseover",function(t,e){V.selectAll("g."+C).style("opacity",.2),r.style("opacity",1),u.attr("stroke-width",2*M)}),r.on("mouseout",function(){V.selectAll("g."+C).style("opacity",1),u.attr("stroke-width",M)})}),B.selection(V.selectAll(".bar-rect")).data(e),B()}return V.selection=function(e){return arguments.length?(t=e,V):t},V.data=function(t){return arguments.length?(e=t,V):e},V.orient=function(t){return arguments.length?(s=t,V):s},V.spaceX=function(t){return arguments.length?(n=t,V):n},V.spaceY=function(t){return arguments.length?(r=t,V):r},V.overflowQ=function(t){return arguments.length?(d=t,V):d},V.grouping=function(t){return arguments.length?(o=t,V):o},V.valueExtractor=function(t){return arguments.length?(h=t,V):h},V.sortingFunction=function(t){return arguments.length?(g=t,V):g},V.scale=function(t){return arguments.length?(p=t,V):p},V.domainPadding=function(t){return arguments.length?(m=t,V):m},V.objectSpacer=function(t){return arguments.length?(b=t,V):b},V.minObjectSize=function(t){return arguments.length?(w=t,V):w},V.maxObjectSize=function(t){return arguments.length?(A=t,V):A},V.barStrokeWidth=function(t){return arguments.length?(M=t,V):M},V.colorFunction=function(t){return arguments.length?(E=t,V):E},V.backgroundFill=function(t){return arguments.length?(O=t,V):O},V.namespace=function(t){return arguments.length?(L=t,V):L},V.objectClass=function(t){return arguments.length?(C=t,V):C},V.transitionDuration=function(t){return arguments.length?(F=t,V):F},V.easeFunc=function(t){return arguments.length?(Q=t,V):Q},V.barKeys=function(t){return arguments.length?(a=t,V):a},V.barValues=function(t){return arguments.length?(i=t,V):i},V.objectSize=function(t){return arguments.length?(l=t,V):l},V.spacerSize=function(t){return arguments.length?(u=t,V):u},V.tooltip=function(t){return arguments.length?(B=t,V):B},V.barPercent=function(t){return arguments.length?(q=t,V):q},V},O.bubbleHeatmap=function(t){var e,n,r,o,i,l,u,s,f,h,g,p,b="x",w="y",A="r",M="v",E=function(t,n){return e[t][b]},O=function(t,n){return e[t][w]},L=function(t,n){return e[t][A]},C=function(t,n){return e[t][M]},F=!1,Q=d3.scaleLinear(),B=.5,q=0,V=50,D=100,_=2,K="transparent",Y="d3sm-bubble",P="bubble",X=1e3,R=d3.easeExp,W=function(t,e){return E(t)-E(e)},N=function(t,e){return O(t)-O(e)},T=j().colorBy("value"),G=z();function H(){var b=v(t,Y,{x:0,y:0,width:n,height:r},K);(o=d3.keys(e)).sort(function(t,e){return W(t,e)||N(t,e)}),m("bubbleHeatmap","cells are sorted by",o),i=d(o.map(E)),l=d(o.map(O)),u=d(o.map(L)),s=d(o.map(C)),m("bubbleHeatmap","x and y keys are",{x:i,y:l});var w=i.length,j=l.length,z=[Math.min.apply(Math,S(u))-B,Math.max.apply(Math,S(u))+B];g=y(r,j,V,D,q,F),f=y(n,w,V,D,q,F),p=x(l,r,g,j,q,F),h=x(i,n,f,w,q,F),m("bubbleHeatmap","size of",{x:f,y:g}),Q.domain(z).range([Math.min(V/2,Math.min(g,f)/2),Math.min(g,f)/2]);var A=k().horizontalQ(!1).moveby("category").numberOfObjects(j).objectClass(a(P,"row")).objectSize(g).spacerSize(p).transitionDuration(X).easeFunc(R).namespace("row"),M=k().horizontalQ(!0).moveby("category").numberOfObjects(w).objectClass(P).objectSize(f).spacerSize(h).transitionDuration(X).easeFunc(R);A(b,l,0),b.selectAll("g."+a(P,"row")).each(function(t,e){M(d3.select(this),i,0)});var H=b.selectAll("g:not(.to-remove)."+P).data(o),Z=[];H.each(function(t,e){Z.push(Number(d3.select(this).attr("parent-index")))}),T="index"==T.colorBy()?T.dataExtent([0,Math.max.apply(Math,Z)]):T.dataExtent([0,Math.max.apply(Math,S(s))]),H.each(function(t,n){m("bubbleHeatmap","each cell",{key:t,index:n,node:d3.select(this).node()});var r=d3.select(this),o=(e[t],C(t,n)),i=L(t,n),l=(n=void 0==r.attr("parent-index")?n:r.attr("parent-index"),T(t,o,n,"fill")),u=T(t,o,n,"stroke");m("bubbleHeatmap","radius",{radius:i,scaled:Q(i),extent:z,range:Q.range()}),c(r,"circle",a(P,"circle")).attr("cx",f/2).attr("cy",g/2).attr("r",Q(i)).attr("fill",l).attr("stroke",u).attr("stroke-width",_)}),G.selection(H.selectAll("circle."+a(P,"circle"))).data(e),G()}return H.selection=function(e){return arguments.length?(t=e,H):t},H.data=function(t){return arguments.length?(e=t,H):e},H.spaceX=function(t){return arguments.length?(n=t,H):n},H.spaceY=function(t){return arguments.length?(r=t,H):r},H.xKey=function(t){return arguments.length?(b=t,H):b},H.yKey=function(t){return arguments.length?(w=t,H):w},H.rKey=function(t){return arguments.length?(A=t,H):A},H.vKey=function(t){return arguments.length?(M=t,H):M},H.cellKeys=function(t){return arguments.length?(o=t,H):o},H.xValues=function(t){return arguments.length?(i=t,H):i},H.yValues=function(t){return arguments.length?(l=t,H):l},H.rValues=function(t){return arguments.length?(u=t,H):u},H.vValues=function(t){return arguments.length?(s=t,H):s},H.xExtractor=function(t){return arguments.length?(E=t,H):E},H.yExtractor=function(t){return arguments.length?(O=t,H):O},H.rExtractor=function(t){return arguments.length?(L=t,H):L},H.vExtractor=function(t){return arguments.length?(C=t,H):C},H.overflowQ=function(t){return arguments.length?(F=t,H):F},H.scale=function(t){return arguments.length?(Q=t,H):Q},H.domainPadding=function(t){return arguments.length?(B=t,H):B},H.objectSpacer=function(t){return arguments.length?q=t:e},H.minObjectSize=function(t){return arguments.length?(V=t,H):V},H.maxObjectSize=function(t){return arguments.length?(D=t,H):D},H.bubbleStrokeWidth=function(t){return arguments.length?(_=t,H):_},H.backgroundFill=function(t){return arguments.length?(K=t,H):K},H.namespace=function(t){return arguments.length?(Y=t,H):Y},H.objectClass=function(t){return arguments.length?(P=t,H):P},H.transitionDuration=function(t){return arguments.length?(X=t,H):X},H.easeFunc=function(t){return arguments.length?(R=t,H):R},H.tooltip=function(t){return arguments.length?(G=t,H):G},H.colorFunction=function(t){return arguments.length?(T=t,H):T},H.xSize=function(t){return arguments.length?(f=t,H):f},H.xSpacerSize=function(t){return arguments.length?(h=t,H):h},H.ySize=function(t){return arguments.length?(g=t,H):g},H.ySpacerSize=function(t){return arguments.length?(p=t,H):p},H},O.heatmap=function(t){var e,n,r,o,i,l,u,s,f,h,g,p="x",b="y",w="v",A=function(t,n){return e[t][p]},M=function(t,n){return e[t][b]},E=function(t,n){return e[t][w]},O=!1,L=0,C=50,F=50,Q=100,B=100,q=2,V="transparent",D="d3sm-heatmap",_="heatmap",K=1e3,Y=d3.easeExp,P=function(t,e){return i.indexOf(A(t))-i.indexOf(A(e))},X=function(t,e){return l.indexOf(M(t))-l.indexOf(M(e))},R=j().colorBy("category"),W=z();function N(){var p=v(t,D,{x:0,y:0,width:n,height:r},V);o=d3.keys(e),i=d(o.map(A)),l=d(o.map(M)),u=d(o.map(E)),o.sort(function(t,e){return P(t,e)||X(t,e)}),m("heatmap","cells are sorted by",o),m("heatmap","x and y keys are",{x:i,y:l});var b=i.length,w=l.length;h=y(r,w,C,B,L,O),s=y(n,b,F,Q,L,O),g=x(l,r,h,w,L,O),f=x(i,n,s,b,L,O),m("heatmap","size of",{x:s,y:h});var j=k().horizontalQ(!1).moveby("category").numberOfObjects(w).objectClass(a(_,"row")).objectSize(h+g).spacerSize(0).transitionDuration(K).easeFunc(Y).namespace("row"),z=k().horizontalQ(!0).moveby("category").numberOfObjects(b).objectClass(_).objectSize(s+f).spacerSize(0).transitionDuration(K).easeFunc(Y);j(p,l,0),p.selectAll("g."+a(_,"row")).each(function(t,e){z(d3.select(this),i,0)});var N=p.selectAll("g:not(.to-remove)."+_);if(o.length!=l.length*i.length){var T={};o.map(function(t,e){T[A(t)+"::"+M(t)]=t});for(var G=[],H=0;Hr?r:n}).attr("fill",h).attr("stroke",v).attr("stroke-width",Q).attr("transform",function(t,e){return"translate("+(g?l/2:A(u))+","+(j?l/2:A(R[1])-A(u))+")"}),k.transition().duration(_).ease(K).attr("d",function(t,e){var n=g?A(i)-A(a):l;return b(!1,0,0,j?A(i)-A(a):l,n,C,d)}).attr("transform",function(t,e){return"translate("+(g?0:A(i))+","+(j?0:A(R[1])-A(i))+")"}).attr("stroke","black").attr("stroke-width",B).attr("fill","none"),x.transition().duration(_).ease(K).attr("d",function(t,e){var n=g?A(f)-A(s):l;return b(!0,0,0,j?A(f)-A(s):l,n,C,d)}).attr("transform",function(t,e){return"translate("+(g?0:A(s))+","+(j?0:A(R[1])-A(f))+")"}).attr("stroke","black").attr("stroke-width",B).attr("fill","none")}),Y.selection(z.selectAll("g:not(.to-remove)."+D)).data(e),Y()}return P.selection=function(e){return arguments.length?(t=e,P):t},P.data=function(t){return arguments.length?(e=t,P):e},P.orient=function(t){return arguments.length?(d=t,P):d},P.spaceX=function(t){return arguments.length?(n=t,P):n},P.spaceY=function(t){return arguments.length?(r=t,P):r},P.overflowQ=function(t){return arguments.length?(h=t,P):h},P.grouping=function(t){return arguments.length?(o=t,P):o},P.quartilesKey=function(t){return arguments.length?(g=t,P):g},P.quartilesKeys=function(t){return arguments.length?(p=t,P):p},P.valueExtractor=function(t){return arguments.length?(m=t,P):m},P.sortingFunction=function(t){return arguments.length?(w=t,P):w},P.scale=function(t){return arguments.length?(A=t,P):A},P.domainPadding=function(t){return arguments.length?(M=t,P):M},P.objectSpacer=function(t){return arguments.length?(E=t,P):E},P.minObjectSize=function(t){return arguments.length?(O=t,P):O},P.maxObjectSize=function(t){return arguments.length?(L=t,P):L},P.whiskerWidthPercent=function(t){return arguments.length?(C=t,P):C},P.colorFunction=function(t){return arguments.length?(F=t,P):F},P.boxStrokeWidth=function(t){return arguments.length?(Q=t,P):Q},P.whiskerStrokeWidth=function(t){return arguments.length?(B=t,P):B},P.backgroundFill=function(t){return arguments.length?(q=t,P):q},P.namespace=function(t){return arguments.length?(V=t,P):V},P.objectClass=function(t){return arguments.length?(D=t,P):D},P.transitionDuration=function(t){return arguments.length?(_=t,P):_},P.easeFunc=function(t){return arguments.length?(K=t,P):K},P.boxKeys=function(t){return arguments.length?(a=t,P):a},P.boxValues=function(t){return arguments.length?(i=t,P):i},P.objectSize=function(t){return arguments.length?(l=t,P):l},P.spacerSize=function(t){return arguments.length?(u=t,P):u},P.tooltip=function(t){return arguments.length?(Y=t,P):Y},P},O.colorFunction=j,O.datatoggle=function(t){var e,n,r,o=function(){},i="d3sm-databar",l=!1,u=!1;d.xAxisSelectQ=function(t){return arguments.length?(l=t,d):l},d.yAxisSelectQ=function(t){return arguments.length?(u=t,d):u},d.xAxisOptions=function(t){return arguments.length?(e=t,d):e},d.yAxisOptions=function(t){return arguments.length?(n=t,d):n},d.data=function(t){return arguments.length?(r=t,d):r},d.updateFunction=function(t){return arguments.length?(o=t,d):o},d.namespace=function(t){return arguments.length?(i=t,d):i},d.currentKeys=function(){var t={};return d3.keys(s).map(function(e,n){t[e]=s[e].currentOption()}),t};var s={};function d(){var e=c(t,"div","d-inline-flex flex-row flex-wrap").selectAll("div."+a(i,"select-filter"));e.exit().remove();var n=(e=e.data(d3.keys(r))).enter().append("div").attr("class","select-filter");return(e=e.merge(n).style("margin-right","10px")).each(function(t,e){var n=A(d3.select(this)).data(r[t]).namespace(a(i,t)).selectionName(t);n(),s[t]=n}),t.selectAll("select").on("change",function(){o()}),d}return d},O.groupingSpacer=k,O.tooltip=z,O.scatter=function(t){var e,n,r,o,a,i,l,c=d3.scaleLinear(),u=.5,s=function(t,n){return e[t].x},d=d3.scaleLinear(),f=.5,h=function(t,n){return e[t].y},g=d3.scaleLinear(),p=.5,m=function(t,e){return 2},y=2,x=10,b=2,k=j(),w="transparent",A="d3sm-scatter",M="scatter-point",E=1e3,O=d3.easeExp,L=z();function C(){var j=v(t,A,{x:0,y:0,width:n,height:r},w);o=d3.keys(e),a=o.map(s),i=o.map(h),l=o.map(m),o.length;var z=[Math.min.apply(Math,S(a))-u,Math.max.apply(Math,S(a))+u],C=[Math.min.apply(Math,S(i))-f,Math.max.apply(Math,S(i))+f],F=[Math.min.apply(Math,S(l))-p,Math.max.apply(Math,S(l))+p];c.domain(z).range([0,n]),d.domain(C).range([r,0]),g.domain(F).range([y,x]);var Q=j.selectAll("."+M),B=(Q=Q.data(o)).enter().append("circle").attr("class",M).attr("cx",0).attr("cy",r).attr("r",0),q=Q.exit();(Q=Q.merge(B)).each(function(t,n){var r=d3.select(this),o=e[t],u=a[n],s=i[n],f=l[n],h=k(t,o,n,"fill"),p=k(t,o,n,"stroke");r.transition().duration(E).ease(O).attr("cx",c(u)).attr("cy",d(s)).attr("r",g(f)).attr("fill",h).attr("stroke",p).attr("stroke-width",b),r.on("mouseover",function(t,e){Q.style("opacity",.2),r.style("opacity",1),r.transition().duration(E/2).ease(O).attr("stroke-width",2*b).attr("r",1.5*g(f))}),r.node().addEventListener("mouseout",function(){j.selectAll("."+M).style("opacity",1),r.transition().duration(E/2).ease(O).attr("stroke-width",b).attr("r",g(f))})}),q.transition().duration(E).ease(O).attr("cx",0).attr("cy",r).attr("r",0).remove(),L.selection(Q).data(e),L()}return C.selection=function(e){return arguments.length?(t=e,C):t},C.data=function(t){return arguments.length?(e=t,C):e},C.spaceX=function(t){return arguments.length?(n=t,C):n},C.spaceY=function(t){return arguments.length?(r=t,C):r},C.scaleX=function(t){return arguments.length?(c=t,C):c},C.domainPaddingX=function(t){return arguments.length?(u=t,C):u},C.valueExtractorX=function(t){return arguments.length?(s=t,C):s},C.scaleY=function(t){return arguments.length?(d=t,C):d},C.domainPaddingY=function(t){return arguments.length?(f=t,C):f},C.valueExtractorY=function(t){return arguments.length?(h=t,C):h},C.scaleR=function(t){return arguments.length?(g=t,C):g},C.domainPaddingR=function(t){return arguments.length?(p=t,C):p},C.valueExtractorR=function(t){return arguments.length?(m=t,C):m},C.minRadius=function(t){return arguments.length?(y=t,C):y},C.maxRadius=function(t){return arguments.length?(x=t,C):x},C.pointStrokeWidth=function(t){return arguments.length?(b=t,C):b},C.colorFunction=function(t){return arguments.length?(k=t,C):k},C.backgroundFill=function(t){return arguments.length?(w=t,C):w},C.namespace=function(t){return arguments.length?(A=t,C):A},C.objectClass=function(t){return arguments.length?(M=t,C):M},C.transitionDuration=function(t){return arguments.length?(E=t,C):E},C.easeFunc=function(t){return arguments.length?(O=t,C):O},C.pointKeys=function(t){return arguments.length?(o=t,C):o},C.valuesX=function(t){return arguments.length?(a=t,C):a},C.valuesY=function(t){return arguments.length?(i=t,C):i},C.valuesR=function(t){return arguments.length?(l=t,C):l},C.tooltip=function(t){return arguments.length?(L=t,C):L},C},O.plotZoom=function(t,e,r){var o,i=20,l=void 0==t.orient?"horizontal":t.orient(),c=t.spaceX(),u=t.spaceY(),s=t.selection(),d=e.selection(),f=r.selection();function h(){var e=s.select("."+a(t.namespace(),"object-container")),r=n(e.attr("transform")),o=e.attr("transform","translate(0,0)");c=s.node().getBBox().width-.9*t.spaceX(),u=s.node().getBBox().height-.9*t.spaceY(),o.attr("transform","translate("+r[0]+","+r[1]+")"),m("plotZoom","setLocks",{xLock:c,yLock:u})}function g(){var g,p;h(),"2D"==l&&(g=!0,p=!0),"horizontal"==l&&(g=!0,p=!1),"vertical"==l&&(p=!0,g=!1);var m=d3.event.transform,v=s.node().getBBox(),y=d.node().getBBox(),x=d.node().getBBox();if(v.width,v.x,v.height,v.y,y.width,y.height,x.width,x.height,"wheel"==o){d3.event.preventDefault();var b=d3.event.deltaY*i,k=d3.event.shiftKey;(m="2D"==l?k?{k:1,x:b,y:0}:{k:1,x:0,y:b}:g?{k:1,x:b,y:0}:{k:1,x:0,y:b}).applyX=function(t){return t*this.k+-1*this.x},m.applyY=function(t){return t*this.k+-1*this.y}}var w=s.select("."+a(t.namespace(),"object-container")),S=d.select("."+a(e.namespace(),"object-container")),j=f.select("."+a(r.namespace(),"object-container")),z=n(w.attr("transform")),A=(n(S.attr("transform")),n(j.attr("transform")),g?m.applyX(z[0]):0);g&&(A=A<-c?(m.x=0,-c):(m.x=0,Math.min(A,0)));var M=p?m.applyY(z[1]):0;p&&(M=M<-u?(m.y=0,-u):(m.y=0,Math.min(M,0))),w.attr("transform","translate("+A+","+M+")"),g&&S.attr("transform","translate("+A+",0)"),p&&j.attr("transform","translate(0,"+M+")")}return d3.select(s.thisSVG()),g.eventType=function(t){return arguments.length?(o=t,g):o},g.wheelSpeed=function(t){return arguments.length?(i=t,g):i},g.orient=function(t){return arguments.length?(l=t,g):l},g.xLock=function(t){return arguments.length?(c=t,g):c},g.yLock=function(t){return arguments.length?(u=t,g):u},g.setLocks=h,g.reset=function(){var n=s.select("."+a(t.namespace(),"object-container")),o=d.select("."+a(e.namespace(),"object-container")),i=f.select("."+a(r.namespace(),"object-container"));n.attr("transform","translate(0,0)"),o.attr("transform","translate(0,0)"),i.attr("transform","translate(0,0)")},g},O.multiPlotZoom=function(t){var e,r=20,o=void 0==t.orient?"horizontal":t.orient(),i=t.spaceX(),l=t.spaceY(),c=t.selection(),u=(d3.select(c.thisSVG()),[]),s=[];function d(){var e=c.select("."+a(t.namespace(),"object-container")),r=n(e.attr("transform")),o=e.attr("transform","translate(0,0)");i=c.node().getBBox().width-t.spaceX(),l=c.node().getBBox().height-t.spaceY(),o.attr("transform","translate("+r[0]+","+r[1]+")"),m("plotZoom","setLocks",{xLock:i,yLock:l})}function f(){d();var f,h,g=u.map(function(t,e){return t.selection()}),p=s.map(function(t,e){return t.selection()});"2D"==o&&(f=!0,h=!0),"horizontal"==o&&(f=!0,h=!1),"vertical"==o&&(h=!0,f=!1);var m=d3.event.transform,v=c.node().getBBox();if(g.map(function(t,e){return t.node().getBBox()}),g.map(function(t,e){return t.node().getBBox()}),v.width,v.x,v.height,v.y,"wheel"==e){d3.event.preventDefault();var y=d3.event.deltaY*r,x=d3.event.shiftKey;(m="2D"==o?x?{k:1,x:y,y:0}:{k:1,x:0,y:y}:f?{k:1,x:y,y:0}:{k:1,x:0,y:y}).applyX=function(t){return t*this.k+-1*this.x},m.applyY=function(t){return t*this.k+-1*this.y}}var b=c.select("."+a(t.namespace(),"object-container")),k=g.map(function(t,e){return t.select("."+a(u[e].namespace(),"object-container"))}),w=p.map(function(t,e){return t.select("."+a(s[e].namespace(),"object-container"))}),S=n(b.attr("transform")),j=(k.map(function(t,e){return n(t.attr("transform"))}),w.map(function(t,e){return n(t.attr("transform"))}),f?m.applyX(S[0]):0);f&&(j=j<-i?(m.x=0,-i):(m.x=0,Math.min(j,0)));var z=h?m.applyY(S[1]):0;h&&(z=z<-l?(m.y=0,-l):(m.y=0,Math.min(z,0))),b.attr("transform","translate("+j+","+z+")"),f&&k.map(function(t,e){t.attr("transform","translate("+j+",0)")}),h&&w.map(function(t,e){t.attr("transform","translate(0,"+z+")")})}return f.eventType=function(t){return arguments.length?(e=t,f):e},f.wheelSpeed=function(t){return arguments.length?(r=t,f):r},f.orient=function(t){return arguments.length?(o=t,f):o},f.xLock=function(t){return arguments.length?(i=t,f):i},f.yLock=function(t){return arguments.length?(l=t,f):l},f.xComponents=function(t){return arguments.length?(u=t,f):u},f.yComponents=function(t){return arguments.length?(s=t,f):s},f.setLocks=d,f.reset=function(){var e=c.select("."+a(t.namespace(),"object-container")),n=xAxisSel.select("."+a(xAxis.namespace(),"object-container")),r=yAxisSel.select("."+a(yAxis.namespace(),"object-container"));e.attr("transform","translate(0,0)"),n.attr("transform","translate(0,0)"),r.attr("transform","translate(0,0)")},f},O.violin=function(t){var e,n,a,i,l,u,d,g,p="horizontal",m=!0,b=!0,w=function(t,n){return e[t]},A=function(t,n){return d3.descending(e[t],e[n])},M=d3.scaleLinear(),E=.5,O=.05,L=50,C=100,F=2,Q=j(),B=function(t,e,n,o,a){var i=d3.scaleLinear().domain([o,a]).range([-.25,.05]),l=r(n.replace("#",""),i(t)),c="stroke"==e?0:.25;return r(l.replace("#",""),c)},q=3,V=2,D="transparent",_="d3sm-violin",K="violin",Y=1e3,P=d3.easeExp,X=["Q0","Q1","Q2","Q3","Q4"],R=z().keys([X[4],X[3],X[2],X[1],X[0]]),W=z(),N=function(t,e){return e.points},T=function(t,e){return e[t].value};function G(){var r,u,w,j="horizontal"==p,G=v(t,_,{x:0,y:0,width:n,height:a},D),H=void 0==i?d3.keys(e).sort(A):i;l=f(H);var Z=function(){var t,e,n=!0,r=["Q0","Q1","Q2","Q3","Q4"];function a(a,i){var l=i[a],c=t(a,l),u=d3.keys(c),s=u.map(function(t,n){return e(t,c)}),d=o(s,r),f=d3.histogram()(s),h=f.map(function(t){return t.length}),g=n?{x:0,y:d3.min(s)}:{x:d3.min(s),y:0},p=n?{x:0,y:d3.max(s)}:{x:d3.max(s),y:0},m=f.map(function(t,e){return n?{y:t.length?d3.median(t):d3.median([t.x0,t.x1]),x:h[e]}:{x:t.length?d3.median(t):d3.median([t.x0,t.x1]),y:h[e]}});m=[g].concat(m).concat([p]),l.binned=f,l.frequencies=h,l.contour=m,l.quartiles=d,l.pointKeys=u,l.pointValues=s}return a.horizontalQ=function(t){return arguments.length?(n=t,a):n},a.quartileKeys=function(t){return arguments.length?(r=t,a):r},a.violinPointsExtractor=function(e){return arguments.length?(t=e,a):t},a.violinPointValueExtractor=function(t){return arguments.length?(e=t,a):e},a}().horizontalQ(j).quartileKeys(X).violinPointsExtractor(N).violinPointValueExtractor(T);l.map(function(t,n){Z(t,e)});var I=l.length,J=(r=[]).concat.apply(r,S(l.map(function(t,n){return e[t].quartiles[X[0]]}))),U=(u=[]).concat.apply(u,S(l.map(function(t,n){return e[t].quartiles[X[X.length-1]]}))),$=[Math.min.apply(Math,S(J))-E,Math.max.apply(Math,S(U))+E];M.domain($).range(j?[0,a]:[0,n]);var tt=j?n:a;d=y(tt,I,L,C,O,m),g=x(H,tt,d,I,O,m),k().horizontalQ(j).scale(M).moveby("category").numberOfObjects(I).objectClass(K).objectSize(d).spacerSize(g).transitionDuration(Y).easeFunc(P).namespace(_)(G,H,0);var et=[];G.selectAll("g:not(.to-remove)."+K).each(function(t,e){s(l,t)&&et.push(Number(d3.select(this).attr("parent-index")))}),Q="index"==Q.colorBy()?Q.dataExtent([0,Math.max.apply(Math,et)]):Q.dataExtent($);var nt=Math.max.apply(Math,S((w=[]).concat.apply(w,S(l.map(function(t,n){return d3.max(e[t].frequencies)}))))),rt=d3.scaleLinear().domain([0,nt]).range([0,d/2]),ot=d3.line().x(function(t,e){return j?-rt(t.x):M(t.x)}).y(function(t,e){return j?M($[1])-M(t.y):-rt(t.y)}).curve(d3.curveBasis),at=d3.line().x(function(t,e){return j?rt(t.x):M(t.x)}).y(function(t,e){return j?M($[1])-M(t.y):rt(t.y)}).curve(d3.curveBasis);G.selectAll("g:not(.to-remove)."+K).each(function(t,n){var r=d3.select(this),o=e[t];if(s(l,t)){n=void 0==r.attr("parent-index")?n:r.attr("parent-index");var a=Q(t,o,n,"fill"),i=Q(t,o,n,"stroke"),u=c(r,"g","area"),f=c(u,"path","left"),g=c(u,"path","right"),p=c(r,"g","quarts"),m=(c(p,"line","q3"),c(p,"line","q1"),o.quartiles[X[3]],o.quartiles[X[2]]);if(o.quartiles[X[1]],r.attr("transform",j?"translate("+d/2+",0)":"translate(0,"+d/2+")"),f.transition().duration(Y).attr("d",function(t,e){return ot(o.contour)}).attr("fill",a).attr("stroke",i).attr("stroke-width",F),g.transition().duration(Y).attr("d",function(t,e){return at(o.contour)}).attr("fill",a).attr("stroke",i).attr("stroke-width",F),u.node().addEventListener("mouseover",function(t,e){G.selectAll("g."+K).style("opacity",.2),r.style("opacity",1),f.attr("stroke-width",2*F),g.attr("stroke-width",2*F)}),u.node().addEventListener("mouseout",function(t,e){G.selectAll("g."+K).style("opacity",1),f.attr("stroke-width",F),g.attr("stroke-width",F)}),b){var v=c(r,"g","points"),y=v.selectAll(".point").data(o.pointKeys);y.on("mouseover",null),y.exit().transition().ease(P).duration(Y).attr("r",0).attr("cy",j?M($[1])-M(m):rt(0)).attr("cx",j?rt(0):M(m)).remove();var x=y.enter().append("circle").attr("class","point").attr("r",0).attr("cx",j?0:M(m)).attr("cy",j?M(m):0);y=y.merge(x),z().selection(y).data(N(t,o)).header(W.header()).keys(W.keys()).values(W.values())();var k=d3.min(o.pointValues),w=d3.max(o.pointValues);y.transition().duration(Y).ease(P).attr("r",q).attr("cy",function(t,e){var n=o.pointValues[e];if(j)return M($[1])-M(n);var r=h(o.binned,n),a=Math.random(),i=rt(a*o.frequencies[r]*.5);return Math.random()>.5?i:-i}).attr("cx",function(t,e){var n=o.pointValues[e];if(j){var r=h(o.binned,n),a=Math.random(),i=rt(a*o.frequencies[r]*.5);return Math.random()>.5?i:-i}return M(n)}).attr("stroke",function(t,e){return t=o.pointValues[e],B(t,"stroke",i,k,w)}).attr("fill",function(t,e){return t=o.pointValues[e],B(t,"fill",i,k,w)}).attr("stroke-width",V),v.selectAll("circle.point").on("mouseover",function(t,e){G.selectAll("g."+K).style("opacity",.2),r.style("opacity",1),f.attr("stroke-width",2*F),g.attr("stroke-width",2*F),G.selectAll(".point").style("opacity",.2),d3.select(this).style("opacity",1).attr("r",2*q).attr("stroke-width",2*V)}),v.selectAll("circle.point").on("mouseout",function(t,e){var n=document.createEvent("SVGEvents");n.initEvent("mouseout",!0,!0),u.node().dispatchEvent(n),G.selectAll(".point").style("opacity",1),d3.select(this).attr("stroke-width",V).attr("r",q)})}else cV.selectAll(".point").transition().duration(Y).ease(P).attr("r",0).attr("cy",j?M($[1])-M(m):rt(0)).attr("cx",j?rt(0):M(m)).remove()}}),R.selection(G.selectAll("g:not(.to-remove)."+K+" .area")),void 0==R.data()&&R.data(e),R(),void 0==R.values()&&R.values([function(t,e){return t.quartiles[e]},function(t,e){return t.quartiles[e]},function(t,e){return t.quartiles[e]},function(t,e){return t.quartiles[e]},function(t,e){return t.quartiles[e]}])}return G.violinPointsExtractor=function(t){return arguments.length?(N=t,G):N},G.violinPointValueExtractor=function(t){return arguments.length?(T=t,G):T},G.selection=function(e){return arguments.length?(t=e,G):t},G.data=function(t){return arguments.length?(e=t,G):e},G.orient=function(t){return arguments.length?(p=t,G):p},G.spaceX=function(t){return arguments.length?(n=t,G):n},G.spaceY=function(t){return arguments.length?(a=t,G):a},G.overflowQ=function(t){return arguments.length?(m=t,G):m},G.pointsQ=function(t){return arguments.length?(b=t,G):b},G.grouping=function(t){return arguments.length?(i=t,G):i},G.valueExtractor=function(t){return arguments.length?(w=t,G):w},G.sortingFunction=function(t){return arguments.length?(A=t,G):A},G.scale=function(t){return arguments.length?(M=t,G):M},G.domainPadding=function(t){return arguments.length?(E=t,G):E},G.objectSpacer=function(t){return arguments.length?(O=t,G):O},G.minObjectSize=function(t){return arguments.length?(L=t,G):L},G.maxObjectSize=function(t){return arguments.length?(C=t,G):C},G.objectStrokeWidth=function(t){return arguments.length?(F=t,G):F},G.colorFunction=function(t){return arguments.length?(Q=t,G):Q},G.pointColorFunc=function(t){return arguments.length?(B=t,G):B},G.pointRadius=function(t){return arguments.length?(q=t,G):q},G.pointStrokeWidth=function(t){return arguments.length?(V=t,G):V},G.backgroundFill=function(t){return arguments.length?(D=t,G):D},G.namespace=function(t){return arguments.length?(_=t,G):_},G.objectClass=function(t){return arguments.length?(K=t,G):K},G.transitionDuration=function(t){return arguments.length?(Y=t,G):Y},G.easeFunc=function(t){return arguments.length?(P=t,G):P},G.quartileKey=function(t){return arguments.length?(quartileKey=t,G):quartileKey},G.quartileKeys=function(t){return arguments.length?(X=t,G):X},G.violinKeys=function(t){return arguments.length?(l=t,G):l},G.violinValues=function(t){return arguments.length?(u=t,G):u},G.objectSize=function(t){return arguments.length?(d=t,G):d},G.spacerSize=function(t){return arguments.length?(g=t,G):g},G.tooltip=function(t){return arguments.length?(R=t,G):R},G.pointsTooltip=function(t){return arguments.length?(W=t,G):W},G},O.numericLegend=function(t){var e,n,r=0,o=1,l=j(),u="d3sm-linear-vertical-gradient",s=12,d="transparent",f="black",h=2;function g(){var g=v(t,u,{x:0,y:0,width:e,height:n},d),p=c(c(t,"defs"),"linearGradient").attr("x1","0%").attr("y1","100%").attr("x2","0%").attr("y2","0%").attr("id",a(u,"numerical-legend-gradient"));l.dataExtent([r,o]).colorBy("value").valueExtractor(function(t,e,n){return e}),p.selectAll("stop").data(l.colors()).enter().append("stop").attr("offset",function(t,e){return e/(l.colors().length-1)}).attr("stop-color",function(t){return t});var m=c(g,"rect","legend").attr("transform","translate(0,"+s+")").style("fill","url(#"+a(u,"numerical-legend-gradient")+")").attr("x",0).attr("y",0).attr("width",e).attr("height",n-2*s).on("mousemove",function(t,e){!function(t,e,n,d){var g=d3.scaleLinear().domain([0,n.attr("height")]).range([o,r]),p=d3.mouse(n.node()),m=i(g(p[1]),h),v=l(void 0,m,void 0,"stroke"),y=l(void 0,m,void 0,"fill");c(c(d3.select("body"),"div",a(u,"legend-tooltip")).attr("id",a(u,"legend-tooltip")).style("position","absolute").style("left",d3.event.pageX+15+"px").style("top",d3.event.pageY+15+"px").style("background-color",y).style("border-color",v).style("min-width",s*(String(o).split(".")[0].length+3)+"px").style("min-height",s*(String(o).split(".")[0].length+3)+"px").style("border-radius","50%").style("border-radius","5000px").style("display","flex").style("justify-content","center").style("text-align","middle").style("padding","2px").style("border-style","solid").style("border-width",2),"div").text(m).style("color",f).style("align-self","center")}(0,0,m,d3.select(this))}).on("mouseout",function(t,e){d3.select("#"+a(u,"legend-tooltip")).remove()});c(g,"text","min").text(i(r,2)).attr("text-anchor","middle").attr("font-size",s+"px").attr("transform",function(t,r){return"translate("+e/2+","+(n-s/4)+")"}),c(g,"text","max").text(i(o,2)).attr("text-anchor","middle").attr("font-size",s+"px").attr("transform",function(t,n){return"translate("+e/2+","+s+")"})}return g.min=function(t){return arguments.length?(r=t,g):r},g.max=function(t){return arguments.length?(o=t,g):o},g.spaceX=function(t){return arguments.length?(e=t,g):e},g.spaceY=function(t){return arguments.length?(n=t,g):n},g.namespace=function(t){return arguments.length?(u=t,g):u},g.fontSize=function(t){return arguments.length?(s=t,g):s},g.backgroundFill=function(t){return arguments.length?(d=t,g):d},g.colorFunction=function(t){return arguments.length?(l=t,g):l},g.textColor=function(t){return arguments.length?(f=t,g):f},g.roundTo=function(t){return arguments.length?(h=t,g):h},g},O.categoricLegend=function(t){var e,n,r,o,a,i="horizontal",l=!1,u=function(t,e){return n[t]},s=function(t,e){return d3.ascending(t,e)},d=.05,h=10,g=100,p=2,m=j(),b="transparent",w="d3sm-legend",S="legend",z=1e3,A=d3.easeExp;function M(){var n="horizontal"==i,u=!n,j=v(t,w,{x:0,y:0,width:r,height:o},b);m.dataExtent([0,e.length-1]).colorBy("categories").categoryExtractor(function(t,e,n){return e});var M=Math.min(r,o),E=e.length,O=void 0==a?e.sort(s):a,L=f(O),C=n?r:o,F=y(C,E,h,g,d,l),Q=x(L,C,F,E,d,l);k().horizontalQ(n).scale(scale).moveby("category").numberOfObjects(E).objectClass(S).objectSize(F).spacerSize(Q).transitionDuration(z).easeFunc(A).namespace(w)(j,O,0),M=Math.min(F,r,o)/2-p,j.selectAll("g:not(.to-remove)."+S).each(function(t,e){var o=d3.select(this),a=c(o,"circle"),i=m(void 0,t,e,"fill"),l=m(void 0,t,e,"stroke"),s=n?M+p:(r-2*M)/2+M,d=u?M+p:(r-2*M)/2+M;a.attr("r",M).attr("cx",s).attr("cy",d).attr("fill",i).attr("stroke",l).attr("stroke-width",p);var f=c(o,"text");f.text(t).attr("text-anchor","middle").attr("transform",function(t,e){return"translate("+s+","+(d+f.node().getBoundingClientRect().height/4)+")"})})}return M.categories=function(t){return arguments.length?(e=t,M):e},M.selection=function(e){return arguments.length?(t=e,M):t},M.data=function(t){return arguments.length?(n=t,M):n},M.orient=function(t){return arguments.length?(i=t,M):i},M.spaceX=function(t){return arguments.length?(r=t,M):r},M.spaceY=function(t){return arguments.length?(o=t,M):o},M.overflowQ=function(t){return arguments.length?(l=t,M):l},M.grouping=function(t){return arguments.length?(a=t,M):a},M.valueExtractor=function(t){return arguments.length?(u=t,M):u},M.sortingFunction=function(t){return arguments.length?(s=t,M):s},M.objectSpacer=function(t){return arguments.length?(d=t,M):d},M.minObjectSize=function(t){return arguments.length?(h=t,M):h},M.maxObjectSize=function(t){return arguments.length?(g=t,M):g},M.bubbleStrokeWidth=function(t){return arguments.length?(p=t,M):p},M.colorFunction=function(t){return arguments.length?(m=t,M):m},M.backgroundFill=function(t){return arguments.length?(b=t,M):b},M.namespace=function(t){return arguments.length?(w=t,M):w},M.objectClass=function(t){return arguments.length?(S=t,M):S},M.transitionDuration=function(t){return arguments.length?(z=t,M):z},M.easeFunc=function(t){return arguments.length?(A=t,M):A},M},O.lasso=E,O.lassoWidget=function(t){var e,n,r,o,i,l,u,s,d="d3sm-lasso",f=(t=t,d3.line().x(function(t,e){return t[0]}).y(function(t,e){return t[1]}).curve(d3.curveLinearClosed),j());function h(t,e){console.log(t,e)}function g(){d3.select("html").select("style."+d+"lasso-widget").empty()&&d3.select("html").append("style").classed(d+"lasso-widget",!0).html("."+a(d,"data-table")+"{ height:100px; overflow:auto; }")}function p(t){console.log(t)}function m(){p((t.select("."+a(d,"tab-list")),t.select("."+a(d,"tab-content")).selectAll("."+a(d,"data-table")),{}))}function v(e,n){var r,o;t.select("#"+a(d,"tab",e)),t.select("#"+a(d,"tab","pane",e)),function(){var e=t.select("."+a(d,"tab-list")),n=(t.select("."+a(d,"tab-content")),e.selectAll("."+a(d,"tab")));if(0==n.size());else{var r=n.nodes()[n.size()-1];d3.select(r).select("a").attr("href")}}(),r=t.select("."+a(d,"tab-list")),o=t.select("."+a(d,"tab-content")),r=r.selectAll("."+a(d,"tab")),o=o.selectAll("."+a(d,"tab","pane")),r.each(function(t,e){d3.select(this).datum(e).attr("id",a(d,"tab",e)).select("a").attr("href","#"+a(d,"tab","pane",e)).text(function(t,n){var r=d3.select(this).text();return"Group"==r.split(" ")[0]?"Group "+e:r})}),o.each(function(t,e){d3.select(this).datum(e).attr("id",a(d,"tab","pane",e)),c(d3.select(this),"p","lead").text(function(t,n){var r=d3.select(this).text();return"Group"==r.split(" ")[0]?"Group "+e:r}),c(d3.select(this),"button","remove-btn").on("click",v)})}function y(t,i){var h=c(t,"p","lead").text("Group "+i),g=c(c(t,"div","table-responsive").attr("class",a(d,"data-table")),"table","table").classed("table-sm",!0).classed("table-hover",!0),p=(c(g,"caption","caption").html("List of selected"),c(t,"div","text-right")),m=i%f.colors().length;i%2!=0&&(m=f.colors().length-1-m);var y,k,w,S=function(t){var e=c(t,"button","lasso-btn").classed("btn btn-info",!0).classed(d,!0);return c(e,"i","fa").classed("fa-hand-pointer-o",!0),c(e,"span").text("Lasso select"),e}(p),j=(y=i,k=f.colors()[m],E().namespace(d).svg(e).objectClass(o).chartContainer(n).objectContainer(r).instance(y).color(k).yScale(s).xScale(u));!function(t,e,r,o){r.eventCatcher(t),t.node().addEventListener("click",x),t.datum([r]).on(a(d,"render"),function(){d3.select(this).datum()[0].draw()}).on(a(d,"drag"),function(t){var e=n.selectAll(".in-lasso-"+t[0].instance()).nodes(),a=e.map(function(t,e){var n=l(d3.select(t).datum());return n.__node=t,n});b(o,a,r)}),e.on("click",function(){r.allPoints([]),r.currentPoints([]),t.dispatch(a(d,"drag"))})}(S,function(t){var e=c(t,"button","clear-btn").classed("btn btn-light",!0).classed(d,!0);return c(e,"i","fa").classed("fa-eraser",!0),c(e,"span").text("Clear selection"),e}(p),j,g),c(w=c(p,"button","remove-btn").classed("btn btn-danger",!0).on("click",v),"i","fa").classed("fa-trash-o",!0),c(w,"span").text("Remove group"),h.on("mouseover",function(){j.draw()}),h.on("mouseout",function(){j.remove()})}function x(){var e=d3.select(this),n=e.datum()[0];n.toggle();var r=n.activeQ();function o(t){t.target!=e.node()&&t.target!=e.select("span").node()&&t.target!=e.select("i").node()&&(n.toggle(!1),e.classed("btn-info",!0),e.classed("btn-warning",!1),e.select("span").text("Lasso select"))}n.activeQ()?(e.classed("btn-info",!r),e.classed("btn-warning",r),e.select("span").text("Lasso select (active)"),t.selectAll("."+d+".lasso-btn").dispatch(a(d,"render")),d3.select("html").node().addEventListener("mousedown",o)):(e.classed("btn-info",!r),e.classed("btn-warning",r),e.select("span").text("Lasso select"),d3.select("html").node().removeEventListener("mousedown",o))}function b(t,e,n){var r=c(c(t,"thead"),"tr"),o=c(t,"tbody"),a=function(t,e){var n=d3.keys(e[0]).filter(function(t){return"__node"!=t});n.length>0&&n.push("remove");var r=t.selectAll("th");return(r=r.data(n)).exit().remove(),r=r.merge(r.enter().append("th").attr("scope","col")).text(function(t,e){return t}),n}(r,e);(function(t,e){var n=t.selectAll("tr");return(n=n.data(e)).exit().remove(),n=n.merge(n.enter().append("tr"))})(o,e).each(function(r,o){var i=d3.select(this);!function(t,e,n,r,o,a){(t=t.data(e)).exit().remove(),(t=t.merge(t.enter().append("td"))).html(function(t,e){return"remove"!=t?n[t]:""}).classed("text-left",function(t,e){return"remove"==t}),t.select("i.fa-close").on("click",function(t,e){var i=n.__node,l=d3.select(i);l.classed("in-lasso",!1),l.classed("in-lasso-"+o.instance(),!1),r.map(function(t,e){t.__node==i&&(r.splice(e,1),b(a,r,o))})})}(i.selectAll("td"),a,r,e,n,t),i.on("mouseover",function(t,e){n.applyObjectAttributes(d3.select(t.__node),!0)}).on("mouseout",function(t,e){n.applyObjectAttributes(d3.select(t.__node),!1)})})}function k(e,n){var r=t.select("."+a(d,"tab-list")),o=t.select("."+a(d,"tab-content")),l=function(){for(var e=t.select("."+a(d,"tab-list")).selectAll("li").size()-3,n="Group "+e,r=[];r.includes(n);)n="Group "+(e+=1);return e}();if(r.selectAll("."+a(d,"tab")).size()!=i){!function(t,e){var n=t.insert("li",".right-aligned-tabs").classed("nav-item",!0).classed("alert",!0).classed("alert-secondary",!0).classed("alert-dismissable",!0).classed("fade",!0).classed("show",!0).attr("role","alert").attr("id",a(d,"tab",e)).classed(a(d,"tab"),!0);c(n,"a").attr("data-toggle","tab").text("Group "+e).attr("href","#"+a(d,"tab","pane",e)).on("dblclick",function(t,e){var n=d3.select(this);n.attr("contenteditable",!0),d3.select(n.node().parentNode).classed("alert-secondary",!1).classed("alert-warning",!0)}).on("blur",function(t,e){var n=d3.select(this);n.attr("contenteditable",!1),d3.select(n.node().parentNode).classed("alert-secondary",!0).classed("alert-warning",!1)}).on("input",function(t,e){var n=d3.select(this),r=n.text();d3.select(n.attr("href")).select("p.lead").text(r)})}(r,l);var u=function(t,e){return t.append("div").datum(e).attr("role","tabpanel").classed("tab-pane",!0).classed("text-left",!0).classed(a(d,"tab","pane"),!0).attr("id",a(d,"tab","pane",e))}(o,l);y(u,l),u.attr("id"),t.select("."+a(d,"tab-content"))}else h("only "+i+" allowed.","warning")}return w=c(t,"div","card"),S=c(c(w,"div","card-header"),"ul","nav").classed("nav-tabs card-header-tabs",!0).classed(a(d,"tab-list"),!0).attr("role","tablist"),z=c(c(w,"div","card-body"),"div","tab-content").classed(a(d,"tab-content"),!0),A=c(S,"div","right-aligned-tabs").classed("nav ml-auto ",!0),function(t){c(c(c(t,"li",a(d,"plus-tab")).classed("ml-auto",!0).classed("nav-item",!0).on("click",k),"a","nav-link"),"i","fa").classed("fa-plus fa-2x text-success",!0)}(A),function(t){c(c(c(t,"li",a(d,"send-tab")).classed("ml-auto",!0).classed("nav-item",!0).on("click",m),"a","nav-link"),"i","fa").classed("fa-paper-plane-o fa-2x text-primary",!0)}(A),function(t){c(c(c(t,"li",a(d,"close-tab")).classed("ml-auto",!0).classed("nav-item",!0).on("click",function(){d3.mouse(d3.select("html").node())}),"a","nav-link"),"i","fa").classed("fa-window-close-o fa-2x text-danger",!0)}(A),c(c(z,"div","tab-pane").classed(a(d,"default-tab"),!0).classed("active",!0).classed("text-left",!0),"div").html("Click to add a new group.
Click to submit for re-analysis.
Click to close the dataselect widget."),g.objectClass=function(t){return arguments.length?(o="."+t.replace(".",""),g):o},g.svg=function(t){return arguments.length?(e=t,g):e},g.submit=function(t){return arguments.length?(p=t,g):p},g.maxNumberOfGroups=function(t){return arguments.length?(i=t,g):i},g.onError=function(t){return arguments.length?(h=t,g):h},g.objectContainer=function(t){return arguments.length?(r=t,g):r},g.chartContainer=function(t){return arguments.length?(n=t,g):n},g.dataExtractor=function(t){return arguments.length?(l=t,g):l},g.xScale=function(t){return arguments.length?(u=t,g):u},g.yScale=function(t){return arguments.length?(s=t,g):s},g;var w,S,z,A},O.selectFilter=A,O.upset=function(t){var e,n,r,o,i,l,u,s,f,h,g,p="horizontal",m=!1,b=20,w=50,S=2,j="transparent",z="d3sm-upset",A="upset",M=1e3,E=d3.easeExp,O=function(t,n){return e[t].set},L=function(t,n){return e[t].intersection},C=function(t,n){return e[t].elements},F=.05,Q=.05,B=function(t,e){return i.indexOf(O(t))-i.indexOf(O(e))},q=function(t,e){return l.indexOf(L(t))-l.indexOf(L(e))};function V(){var S="horizontal"==p,C=!S,V=v(t,z,{x:0,y:0,width:n,height:r},j);o=d3.keys(e),i=d(o.map(O)).sort(),l=d(o.map(L)).sort().sort(function(t,e){return t.split(";").length-e.split(";").length}),S?o.sort(function(t,e){return q(t,e)||B(t,e)}):o.sort(function(t,e){return B(t,e)||q(t,e)});var D=S?l:i,_=S?i:l,K=S?D.length:_.length,Y=S?_.length:D.length;h=y(n,K,b,w,F,m),s=y(r,Y,b,w,Q,m),g=x(D,n,h,K,F,m),f=x(_,r,s,Y,Q,m);var P=k().horizontalQ(!1).moveby("category").numberOfObjects(Y).objectSize(s).spacerSize(f).transitionDuration(M).easeFunc(E),X=k().horizontalQ(!0).moveby("category").numberOfObjects(K).objectClass(A).objectSize(h).spacerSize(g).transitionDuration(M).easeFunc(E);C?(X.objectClass(A),P.namespace("across").objectClass(a(A,"across")),P(V,_,0),V.selectAll("g."+a(A,"across")).each(function(t,e){X(d3.select(this),D,0)})):(X.namespace("across").objectClass(a(A,"across")),P.objectClass(A),X(V,D,0),V.selectAll("g."+a(A,"across")).each(function(t,e){P(d3.select(this),_,0)}));var R=V.selectAll("g:not(.to-remove)."+A),W={};o.map(function(t,e){W[O(t)+"::"+L(t)]=t}),R.data(o),R.each(function(t,n){var r=d3.select(this);if(void 0!=t){e[t];var o=O(t,n),i=L(t,n);r.classed(i,!0),r.classed(o,!0),c(r,"circle",a(A,"circle")).attr("cx",h/2).attr("cy",s/2).attr("r",void 0==u?Math.min(h,s)/2:u).attr("fill",i.includes(o)?"black":"rgb(233,233,233)").attr("stroke","black").attr("in-intersection",i.includes(o))}})}return V.selection=function(e){return arguments.length?(t=e,V):t},V.data=function(t){return arguments.length?(e=t,V):e},V.orient=function(t){return arguments.length?(p=t,V):p},V.spaceX=function(t){return arguments.length?(n=t,V):n},V.spaceY=function(t){return arguments.length?(r=t,V):r},V.overflowQ=function(t){return arguments.length?(m=t,V):m},V.minObjectSize=function(t){return arguments.length?(b=t,V):b},V.maxObjectSize=function(t){return arguments.length?(w=t,V):w},V.circleStrokeWidth=function(t){return arguments.length?(S=t,V):S},V.backgroundFill=function(t){return arguments.length?(j=t,V):j},V.namespace=function(t){return arguments.length?(z=t,V):z},V.objectClass=function(t){return arguments.length?(A=t,V):A},V.transitionDuration=function(t){return arguments.length?(M=t,V):M},V.easeFunc=function(t){return arguments.length?(E=t,V):E},V.cellKeys=function(t){return arguments.length?(o=t,V):o},V.setValues=function(t){return arguments.length?(i=t,V):i},V.intersectionValues=function(t){return arguments.length?(l=t,V):l},V.xObjectSpacer=function(t){return arguments.length?(F=t,V):F},V.yObjectSpacer=function(t){return arguments.length?(Q=t,V):Q},V.radius=function(t){return arguments.length?(u=t,V):u},V.setExtractor=function(t){return arguments.length?(O=t,V):O},V.intersectionExtractor=function(t){return arguments.length?(L=t,V):L},V.elementExtractor=function(t){return arguments.length?(C=t,V):C},V.setKeySortingFunction=function(t){return arguments.length?(B=t,V):B},V.intersectionKeySortingFunction=function(t){return arguments.length?(q=t,V):q},V.yObjectSize=function(t){return arguments.length?(s=t,V):s},V.ySpacerSize=function(t){return arguments.length?(f=t,V):f},V.xObjectSize=function(t){return arguments.length?(h=t,V):h},V.xSpacerSize=function(t){return arguments.length?(g=t,V):g},V.intersectionTotals=function(){var t={};return l.map(function(e,n){t[e]={total:0}}),o.map(function(e,n){var r=C(e,n);0==t[L(e,n)].total&&(Array.isArray(r)?(t[L(e,n)].total+=r.length,t[L(e,n)].values=r):t[L(e,n)].total+=r)}),t},V.setTotals=function(){var t={};return i.map(function(e,n){t[e]={total:0}}),o.map(function(e,n){var r=C(e,n);Array.isArray(r)?t[O(e,n)].total+=r.length:t[O(e,n)].total+=r}),t},V},O.filterTable=function(t){var e,n="d3sm-filter-table",r=function(t,e,n){return n};function o(){var o=c(t,"div","filter-table").classed(a(n,"container"),!0),u=c(o,"div","filter-input-group").classed("input-group",!0),s=(c(c(c(u,"div","input-group-prepend"),"span","input-group-text").classed("search-button",!0),"i","fa fa-search"),c(u,"input","form-control").attr("placeholder","filter").attr("type","text")),d=c(c(u,"div","input-group-append"),"a","close-button").classed("btn btn-outline-secondary",!0),f=(c(d,"i","fa fa-close"),d),h=c(c(o,"div","table-responsive"),"table","table").classed("table-hover",!0).classed("table-bordered",!0).classed("table-striped",!0),g=c(c(h,"thead").classed("thead-dark",!0),"tr"),p=c(h,"tbody"),m=d3.keys(e),v=d3.keys(e[m[0]]);(function(t,e){var n=t.selectAll("th");(n=n.data(e)).exit().remove(),(n=n.merge(n.enter().append("th"))).attr("scope","col").text(function(t,e){return t})})(g,v),l(i(p,m),v),s.on("input",function(t,n){var o,a=s.property("value"),c=new RegExp(a,"gi");""==a?o=m:(o=[],m.map(function(t,n){var a=e[t],i=v.map(function(t,e){return r(a,t,a[t])}).join("").match(c);null==i||""==i.join("")||o.push(t)})),l(i(p,o),v)}),f.on("click",function(t,e){s.property("value","").dispatch("input")})}function i(t,e){var n=t.selectAll("tr");return(n=n.data(e)).exit().remove(),n=n.merge(n.enter().append("tr"))}function l(t,n){return t.each(function(t,o){var a=e[t],i=d3.select(this).selectAll("td");(i=i.data(n)).exit().remove(),(i=i.merge(i.enter().append("td"))).attr("scope",function(t,e){return 0==e}).html(function(t,e){return r(a,t,a[t])})}),t}return o.data=function(t){return arguments.length?(e=t,o):e},o.namespace=function(t){return arguments.length?(n=t,o):n},o.fieldFunction=function(t){return arguments.length?(r=t,o):r},o},O.uniqueElements=e,O.getTranslation=n,O.modifyHexidecimalColorLuminance=r,O.tickRange=u,O.quartiles=o,O.extractViolinValues=function(t,e,n,r,a,i){var l={};return t.map(function(t,c){var u=n(t,c,e),s=d3.histogram()(u),d=s.map(function(t){return t.length}),f=r?{y:d3.min(u),x:0}:{x:d3.min(u),y:0},h=r?{y:d3.max(u),x:0}:{x:d3.max(u),y:0},g=s.map(function(t,e){return r?{y:t.length?d3.median(t):d3.median([t.x0,t.x1]),x:d[e]}:{x:t.length?d3.median(t):d3.median([t.x0,t.x1]),y:d[e]}}),p=o(u,i),m={values:u,binned:s,frequencies:d,points:[f].concat(g).concat([h])};m[a]=p,l[t]=m}),l},O.hypenate=a,O.round=i,O.getContainingSVG=l,O.interpolateColors=function(){return d3.interpolateRgbBasis(arguments)},O.truncateText=function(t,e,n,r,o,a){var i=t.node().getBoundingClientRect();for(t.text(e);Math.max(i.width,i.height)>o-r&&(e=(e=String(e)).slice(0,e.length-1),t.text(e+"..."),i=t.node().getBoundingClientRect(),0!=e.length););},O.safeSelect=c,O.whichBin=h,O.unique=d,O.flatten=f,O.setupStandardChartContainers=function(t,e,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{top:.01,bottom:.01,left:.01,right:.01},o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{w:.8,h:.6},a=arguments.length>5&&void 0!==arguments[5]?arguments[5]:{y:.1,x:.1},i=arguments.length>6&&void 0!==arguments[6]?arguments[6]:{x:0,margin:0,pos:"left"};void 0==n&&(n={w:window.innerWidth,h:window.Height});var l={w:n.w*o.w,h:n.h*o.h},c={top:r.top*l.h,bottom:r.bottom*l.h,left:r.left*l.w,right:r.right*l.w},u=l.w-c.left-c.right,s=l.h-c.top-c.bottom,d={x:s*a.x,y:u*a.y},f={x:u-d.y-i.x-2*i.margin,y:s-d.x},h={x:i.margin+c.left+("left"==i.pos?0:f.x+d.y),y:c.top,w:i.x,h:f.y},g={x:d.y+c.left+("left"==i.pos?i.x+2*i.margin:0),y:c.top,w:d.y,h:f.y},p={x:d.y+c.left+("left"==i.pos?i.x+2*i.margin:0),y:c.top,w:f.x,h:f.y},m={x:d.y+c.left+("left"==i.pos?i.x+2*i.margin:0),y:c.top+f.y,w:f.x,h:d.x};return n=d3sm.safeSelect(t,"svg",e).style("width",l.w+"px").style("height",l.h+"px"),a=d3sm.safeSelect(n,"g",d3sm.hypenate(e,"axes")),i=d3sm.safeSelect(n,"g",d3sm.hypenate(e,"legend")).attr("transform","translate("+h.x+","+h.y+")"),{svg:{selection:n,rect:l},plot:{selection:d3sm.safeSelect(n,"g",d3sm.hypenate(e,"plot")).attr("transform","translate("+p.x+","+p.y+")"),rect:p},xAxis:{selection:d3sm.safeSelect(a,"g",d3sm.hypenate(e,"x-axis")).attr("transform","translate("+m.x+","+m.y+")"),rect:m},yAxis:{selection:d3sm.safeSelect(a,"g",d3sm.hypenate(e,"y-axis")).attr("transform","translate("+g.x+","+g.y+")"),rect:g},legend:{selection:i,rect:h}}},O.log=m,O.warn=function(t,e,n){!0===window.d3sm.debugQ&&console.warn("%c[d3sm::"+t+"]:\t"+e,["background: #ffd53e","border-radius: 5000px","padding: 0px 2px","font-size: 14px"].join(";")),console.table(n)},O.info=function(t,e,n){window.d3sm.debugQ&&console.info("%c[d3sm::"+t+"]:\t"+e,["background: #009ccd","border-radius: 5000px","padding: 0px 2px","font-size: 14px"].join(";")),console.table(n)},O.error=function(t,e,n){window.d3sm.debugQ&&console.error("[d3sm::"+t+"]:\t"+e+"\t%o",n)},O.consoleGroup=g,O.consoleGroupEnd=p,O.resizeDebounce=function(t,e){var n=function(t,e,n){var r;return function(){var o=this,a=arguments,i=n&&!r;clearTimeout(r),r=setTimeout(function(){r=null,n||t.apply(o,a)},e),i&&t.apply(o,a)}}(function(){t()},e);window.addEventListener("resize",n)},O.debugQ=!1,window.d3sm=O,t.default=O,t}({}); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZDNzbS5taW4udjAuMC40LmpzIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL2hlbHBlcnMuanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL2FycmF5LWZ1bmN0aW9ucy5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvdXRpbHMuanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL2dyb3VwaW5nLXNwYWNlci5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvY29sb3ItZnVuY3Rpb24uanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL3Rvb2x0aXAuanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL3NlbGVjdC1maWx0ZXIuanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL2xhc3NvLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9kMy1wcm90b3R5cGVzLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbWFpbi5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvYXhpcy5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvYmFyLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9idWJibGUtaGVhdG1hcC5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvaGVhdG1hcC5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvYm94LXdoaXNrZXIuanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL2RhdGEtdG9nZ2xlLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9zY2F0dGVyLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9wbG90LXpvb20uanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL211bHRpLXBsb3Qtem9vbS5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvdmlvbGluLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9udW1lcmljLWxlZ2VuZC5qcyIsIi4uLy4uL3NyYy9zY3JpcHRzL21vZHVsZXMvY2F0ZWdvcmljYWwtbGVnZW5kLmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9sYXNzby13aWRnZXQuanMiLCIuLi8uLi9zcmMvc2NyaXB0cy9tb2R1bGVzL3Vwc2V0LmpzIiwiLi4vLi4vc3JjL3NjcmlwdHMvbW9kdWxlcy9maWx0ZXItdGFibGUuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gaW1wb3J0IHtoYXNRfSBmcm9tICcuL2FycmF5LWZ1bmN0aW9ucyc7XG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSEVMUEVSUyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuLyoqXG4qIEhlbHBlciBmdW5jdGlvbiBmb3IgQXJyYXkuZmlsdGVyIHRvIGdldCB1bmlxdWUgZWxlbWVudHMgb2YgdGhlIGFycmF5XG4qIEBwYXJhbSB7Kn0gdmFsdWUgY3VycmVudCB2YWx1ZSBhcyBtYXBwaW5nIG92ZXIgYXJyYXkgKHNlbGYpXG4qIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBjdXJyZW50IGluZGV4IGluIHRoZSBhcnJheVxuKiBAcGFyYW0ge0FycmF5fSBzZWxmIHBhc3NlZCBhcnJheSBmcm9tIEFycmF5LmZpbHRlciBtZXRob2RcbiogQHJldHVybnMge2Jvb2xlYW59IHdoZXRoZXIgb3Igbm90IHZhbHVlIGlzIHRoZSBmaXJzdCBvZiBpdHMga2luZCAoaS5lLiBpbmRleE9mKHZhbHVlKSA9PSBpbmRleClcbiovXG5leHBvcnQgZnVuY3Rpb24gdW5pcXVlRWxlbWVudHModmFsdWUsIGluZGV4LCBzZWxmKSB7IHJldHVybiBzZWxmLmluZGV4T2YodmFsdWUpID09PSBpbmRleDsgfVxuXG4vKipcbiogRXh0cmFjdHMgeCBhbmQgeSBvZiB0cmFuc2xhdGUgZnJvbSB0cmFuc2Zvcm0gcHJvcGVydHlcbiogQHBhcmFtIHtzdHJpbmd9IHRyYW5zZm9ybSB0cmFuc2Zvcm0gcHJvcGVydHkgb2Ygc3ZnIGVsZW1lbnRcbiogQHJldHVybnMge251bWJlcltdfSB4LCB5IG9mIHRyYW5zbGF0ZSh4LCB5KVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRUcmFuc2xhdGlvbih0cmFuc2Zvcm0pIHtcbiAgLy8gQ3JlYXRlIGEgZHVtbXkgZyBmb3IgY2FsY3VsYXRpb24gcHVycG9zZXMgb25seS4gVGhpcyB3aWxsIG5ldmVyXG4gIC8vIGJlIGFwcGVuZGVkIHRvIHRoZSBET00gYW5kIHdpbGwgYmUgZGlzY2FyZGVkIG9uY2UgdGhpcyBmdW5jdGlvblxuICAvLyByZXR1cm5zLlxuICB2YXIgZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUygnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnLCAnZycpO1xuICAvLyBTZXQgdGhlIHRyYW5zZm9ybSBhdHRyaWJ1dGUgdG8gdGhlIHByb3ZpZGVkIHN0cmluZyB2YWx1ZS5cbiAgdHJhbnNmb3JtID0gdHJhbnNmb3JtID09IHVuZGVmaW5lZCA/ICd0cmFuc2xhdGUoMCwwKScgOiB0cmFuc2Zvcm07XG4gIGcuc2V0QXR0cmlidXRlTlMobnVsbCwgJ3RyYW5zZm9ybScsIHRyYW5zZm9ybSk7XG4gIC8vIGNvbnNvbGlkYXRlIHRoZSBTVkdUcmFuc2Zvcm1MaXN0IGNvbnRhaW5pbmcgYWxsIHRyYW5zZm9ybWF0aW9uc1xuICAvLyB0byBhIHNpbmdsZSBTVkdUcmFuc2Zvcm0gb2YgdHlwZSBTVkdfVFJBTlNGT1JNX01BVFJJWCBhbmQgZ2V0XG4gIC8vIGl0cyBTVkdNYXRyaXguXG4gIHZhciBtYXRyaXggPSBnLnRyYW5zZm9ybS5iYXNlVmFsLmNvbnNvbGlkYXRlKCkubWF0cml4O1xuICAvLyBBcyBwZXIgZGVmaW5pdGlvbiB2YWx1ZXMgZSBhbmQgZiBhcmUgdGhlIG9uZXMgZm9yIHRoZSB0cmFuc2xhdGlvbi5cbiAgcmV0dXJuIFttYXRyaXguZSwgbWF0cml4LmZdO1xufVxuXG5cbi8qKlxuKiBNb2RpZmllcyBsdW1pbmFuY2Ugb2YgaGV4aWRlY2ltYWwgbnVtYmVyXG4qIEBwYXJhbSB7c3RyaW5nfSBoZXggc2hvdWxkIGJlIGhleGlkZWNpbWFsIHZhbHVlIHdpdGggb3Igd2l0aG91dCB0aGUgcHJvY2VlZGluZyBvY3RvdHJvcGVcbiogQHBhcmFtIHtudW1iZXJ9IGx1bSB2YWx1ZSB0byBpbmNyZWFzZSBvciBkZWNyZWFzZSBsdW1pbm9zaXR5IGJ5XG4qIEByZXR1cm5zIHtzdHJpbmd9IHVwZGF0ZWQgaGV4aWRlY2ltYWwgdmFsdWUgd2l0aG91dCB0aGUgcHJvY2VlZGluZyBvY3RvdHJvcGVcbiovXG5leHBvcnQgZnVuY3Rpb24gbW9kaWZ5SGV4aWRlY2ltYWxDb2xvckx1bWluYW5jZShoZXgsIGx1bSkge1xuICAvLyB2YWxpZGF0ZSBoZXggc3RyaW5nXG4gIHZhciBoZXggPSBTdHJpbmcoaGV4KS5yZXBsYWNlKC9bXjAtOWEtZl0vZ2ksICcnKTtcblxuICBpZiAoaGV4Lmxlbmd0aCA8IDYpIHtcbiAgICBoZXggPSBoZXhbMF0raGV4WzBdK2hleFsxXStoZXhbMV0raGV4WzJdK2hleFsyXTtcblx0fVxuXHRsdW0gPSBsdW0gfHwgMDtcblxuXHQvLyBjb252ZXJ0IHRvIGRlY2ltYWwgYW5kIGNoYW5nZSBsdW1pbm9zaXR5XG5cdHZhciByZ2IgPSAnIycsIGMsIGk7XG5cdGZvciAoaSA9IDA7IGkgPCAzOyBpKyspIHtcblx0XHRjID0gcGFyc2VJbnQoaGV4LnN1YnN0cihpKjIsMiksIDE2KTtcblx0XHRjID0gTWF0aC5yb3VuZChNYXRoLm1pbihNYXRoLm1heCgwLCBjICsgKGMgKiBsdW0pKSwgMjU1KSkudG9TdHJpbmcoMTYpO1xuXHRcdHJnYiArPSAoJzAwJytjKS5zdWJzdHIoYy5sZW5ndGgpO1xuXHR9XG5cblx0cmV0dXJuIHJnYjtcbn1cblxuXG4vKipcbiogQGRlcHJlY2F0ZWQgQHNlZXtAbGluayB0aWNrUmFuZ2V9XG4qIEBwYXJhbSB7bnVtYmVyfSBtaW5cbiogQHBhcmFtIHtudW1iZXJ9IG1heFxuKiBAcGFyYW0ge251bWJlcn0gcGFydHNcbiogQHJldHVybnMge251bWJlcltdfSBhcnJheSBvZiBsZW5ndGggcGFydHMgZXZlbmx5IHBhcnRpdGlvbmVkIGJldHdlZW4gbWluIGFuZCBtYXhcbiovXG5leHBvcnQgZnVuY3Rpb24gcGFydGl0aW9uUmFuZ2VJbnRvKG1pbiwgbWF4LCBwYXJ0cykge1xuICB2YXIgZGlmZiA9IG1heCAtIG1pblxuICByZXR1cm4gQXJyYXkocGFydHMpLm1hcChmdW5jdGlvbiAoZSwgaSkgeyByZXR1cm4gbWluICsgZGlmZiAvIHBhcnRzICogaSB9KVxufVxuXG5cbi8qKlxuKiBDYWxjdWxhdGVkIHRoZSBxdWFydGlsZXMgb2YgdGhlIHBhc3NlZCBkYXRhIGFuZCBzdG9yZXMgdGhlbSB3aXRoIHFLZXlzXG4qIEBwYXJhbSB7bnVtYmVyW119IGRhdGEgbGlzdCBvZiBudW1lcmljYWwgdmFsdWVzXG4qIEBwYXJhbSB7c3RyaW5nW119IFtxS2V5cz1bJ3EwJywgJ3ExJywgJ3EyJywgJ3EzJywgJ3E0J11dIGhvdyByZXR1cm5lZCBvYmplY3Qgd2l0aCBxdWFydGlsZXMgc2hvdWxkIGJlIHN0b3JlZFxuKiBAcmV0dXJucyB7T2JqZWN0fSB3aXRoIGtleXMgcUtleXMgZ2l2aW5nIG9ubHkgdGhlIG51bWVyaWNhbCB2YWx1ZXMgZm9yIHRoZSBxdWFydGlsZXNcbiovXG5leHBvcnQgZnVuY3Rpb24gcXVhcnRpbGVzKGRhdGEsIHFLZXlzKSB7XG4gIHZhclxuICBxMiA9IGQzLm1lZGlhbihkYXRhKSxcbiAgbG93ZXIgPSBkYXRhLmZpbHRlcih4ID0+IHggPCBxMiksXG4gIHVwcGVyID0gZGF0YS5maWx0ZXIoeCA9PiB4ID4gcTIpLFxuXG4gIHExID0gZDMubWVkaWFuKGxvd2VyKSxcbiAgcTEgPSBxMSA9PSB1bmRlZmluZWQgPyBxMiA6IHExLFxuXG4gIHEwID0gZDMubWluKGxvd2VyKSxcbiAgcTAgPSBxMCA9PSB1bmRlZmluZWQgPyBxMSA6IHEwLFxuXG4gIHEzID0gZDMubWVkaWFuKHVwcGVyKSxcbiAgcTMgPSBxMyA9PSB1bmRlZmluZWQgPyBxMiA6IHEzLFxuXG4gIHE0ID0gZDMubWF4KHVwcGVyKSxcbiAgcTQgPSBxNCA9PSB1bmRlZmluZWQgPyBxMyA6IHE0LFxuXG4gIGswID0gJ3EwJywgazEgPSAncTEnLCBrMiA9ICdxMicsIGszID0gJ3EzJywgazQgPSAncTQnLFxuICBvYmogPSB7fVxuICBpZiAocUtleXMhPXVuZGVmaW5lZCAmJiBxS2V5cy5sZW5ndGggPT0gNSkgeyBrMCA9IHFLZXlzWzBdOyBrMSA9IHFLZXlzWzFdOyBrMiA9IHFLZXlzWzJdOyBrMyA9IHFLZXlzWzNdOyBrNCA9IHFLZXlzWzRdOyB9XG4gIG9ialtrMF0gPSBxMDsgb2JqW2sxXSA9IHExOyBvYmpbazJdID0gcTI7IG9ialtrM10gPSBxMzsgb2JqW2s0XSA9IHE0O1xuXG4gIHJldHVybiBvYmpcbn1cblxuXG4vKipcbiogSGVscGVyIGZ1bmN0aW9uIHRvIGdldCBhbGwgdmFsdWVzIG5lZWRlZCBpbiBtYWtpbmcgdmlvbGluIHBsb3RzXG4qIEBwYXJhbSB7c3RyaW5nW119IHZpb2xpbktleXNcbiogQHBhcmFtIHtudW1iZXJbXX0gZGF0YVxuKiBAcGFyYW0ge0Z1bmN0aW9ufSB2YWx1ZUV4dHJhY3RvckZ1bmN0aW9uIGhvdyB0byBnZXQgdmFsdWVzIGZyb20gZGF0YVt2aW9saW5LZXlzW2ldXVxuKiBAcGFyYW0ge2Jvb2xlYW59IGhvcml6b250YWxRIHdoZXRoZXIgb3Igbm90IHZpb2xpbnMgd2lsbCBiZSByZW5kZXJlZCBob3Jpem9udGFsbHkgb3IgdmVydGljYWxseVxuKiBAcGFyYW0ge3N0cmluZ30gcUtleSBob3cgdGhlIG9iamVjdCBjb250YWluaW5nIHRoZSBxdWFydGlsZXMgc2hvdWxkIGJlIGxhYmVsZWQgYXNcbiogQHBhcmFtIHtzdHJpbmdbXX0gcUtleXMgaG93IGVhY2ggcXVhcnRpbGUgc2hvdWxkIGJlIGxhYmVsZWQgYXNcbiogQHJldHVybnMge09iamVjdH0gcmVxdWlyZWQgZm9yIEBzZWV7QGxpbmsgdmlvbGlufSBjb250YWluaW5nIGtleXMgdmFsdWVzLCBiaW5ubmVkLCBmcmVxdWVuY2llcywgcG9pbnRzLCBhbmQgcXVhcnRpbGVzXG4qIEBzZWV7QGxpbmsgcXVhcnRpbGVzfVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0VmlvbGluVmFsdWVzKFxuICB2aW9saW5LZXlzLFxuICBkYXRhLFxuICB2YWx1ZUV4dHJhY3RvckZ1bmN0aW9uLFxuICBob3Jpem9udGFsUSxcbiAgcUtleSxcbiAgcUtleXNcbil7XG4gIHZhciBvYmogPSB7fVxuICB2aW9saW5LZXlzLm1hcChmdW5jdGlvbihrLCBpKXtcbiAgICAgdmFyIGQgPSB2YWx1ZUV4dHJhY3RvckZ1bmN0aW9uKGssIGksIGRhdGEpLFxuICAgICBiaW5uZWQgPSBkMy5oaXN0b2dyYW0oKShkKSxcbiAgICAgZnJlcXVlbmNpZXMgPSBiaW5uZWQubWFwKHg9PngubGVuZ3RoKSxcbiAgICAgbWluUG9pbnQgPSBob3Jpem9udGFsUSA/IHt5OiBkMy5taW4oZCksIHg6IDB9IDoge3g6IGQzLm1pbihkKSwgeTogMH0sXG4gICAgIG1heFBvaW50ID0gaG9yaXpvbnRhbFEgPyB7eTogZDMubWF4KGQpLCB4OiAwfSA6IHt4OiBkMy5tYXgoZCksIHk6IDB9LFxuICAgICBwb2ludHMgPSBiaW5uZWQubWFwKGZ1bmN0aW9uKGJpbiwgaSkge1xuICAgICAgIHJldHVybiBob3Jpem9udGFsUVxuICAgICAgID8ge3k6IChiaW4ubGVuZ3RoKSA/IGQzLm1lZGlhbihiaW4pOiBkMy5tZWRpYW4oW2Jpbi54MCwgYmluLngxXSksIHg6IGZyZXF1ZW5jaWVzW2ldfVxuICAgICAgIDoge3g6IChiaW4ubGVuZ3RoKSA/IGQzLm1lZGlhbihiaW4pOiBkMy5tZWRpYW4oW2Jpbi54MCwgYmluLngxXSksIHk6IGZyZXF1ZW5jaWVzW2ldfVxuICAgICB9KSxcbiAgICAgcXVhcnRzID0gcXVhcnRpbGVzKGQsIHFLZXlzKSxcbiAgICAgbyA9IHtcbiAgICAgICB2YWx1ZXM6IGQsXG4gICAgICAgYmlubmVkOiBiaW5uZWQsXG4gICAgICAgZnJlcXVlbmNpZXM6IGZyZXF1ZW5jaWVzLFxuICAgICAgIHBvaW50czogW21pblBvaW50XS5jb25jYXQocG9pbnRzKS5jb25jYXQoW21heFBvaW50XSlcbiAgICAgfVxuICAgICBvW3FLZXldID0gcXVhcnRzO1xuICAgICBvYmpba10gPSBvO1xuICAgfSk7XG4gICByZXR1cm4gb2JqO1xufVxuXG4vKipcbiogSHlwZW5hdGVzIGFsbCBzdHJpbmdzIHRvZ2V0aGVyXG4qIEBwYXJhbSB7c3RyaW5nW119IGFyZ3VtZW50c1xuKiBAcmV0dXJucyB7c3RyaW5nfSBcImFyZzEtYXJnMi0uLi4tYXJnblwiXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIGh5cGVuYXRlKCl7IHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpLmpvaW4oJy0nKSB9XG5cblxuLyoqXG4qIFJvdW5kcyBkZWNpbWFscyBvZiBudW1iZXIgdG8gcHJlY2lzaW9uXG4qIEBwYXJhbSB7bnVtYmVyfSBudW1iZXJcbiogQHBhcmFtIHtudW1iZXJ9IHByZWNpc2lvblxuKiBAcmV0dXJucyB7bnVtYmVyfSByb3VuZGVkIHRvIHByZWNpc2lvblxuKi9cbmV4cG9ydCBmdW5jdGlvbiByb3VuZChudW1iZXIsIHByZWNpc2lvbikge1xuICB2YXIgc2hpZnQgPSBmdW5jdGlvbiAobnVtYmVyLCBwcmVjaXNpb24sIHJldmVyc2VTaGlmdCkge1xuICAgIGlmIChyZXZlcnNlU2hpZnQpIHtcbiAgICAgIHByZWNpc2lvbiA9IC1wcmVjaXNpb247XG4gICAgfVxuICAgIHZhciBudW1BcnJheSA9ICgnJyArIG51bWJlcikuc3BsaXQoJ2UnKTtcbiAgICByZXR1cm4gKyhudW1BcnJheVswXSArICdlJyArIChudW1BcnJheVsxXSA/ICgrbnVtQXJyYXlbMV0gKyBwcmVjaXNpb24pIDogcHJlY2lzaW9uKSk7XG4gIH07XG4gIHJldHVybiBzaGlmdChNYXRoLnJvdW5kKHNoaWZ0KG51bWJlciwgcHJlY2lzaW9uLCBmYWxzZSkpLCBwcmVjaXNpb24sIHRydWUpO1xufVxuXG4vKipcbiogcmVjdXJzaXZlbHkgYXNjZW5kcyBlbGVtZW50LnBhcmVudEVsZW1lbnQgdG8gZmluZCBhIHN2ZyB0YWdcbiogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4qIEByZXR1cm5zIHtFbGVtZW50IHwgdW5kZWZpbmVkfVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb250YWluaW5nU1ZHKGVsZW1lbnQpIHtcbiAgdmFyIHBhcmVudCA9IGVsZW1lbnQucGFyZW50RWxlbWVudFxuICB2YXIgdGFnID0gcGFyZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKVxuICBpZiAodGFnID09PSAnc3ZnJykgeyByZXR1cm4gcGFyZW50OyB9XG4gIGlmICh0YWcgPT09ICdodG1sJykgeyByZXR1cm4gdW5kZWZpbmVkOyB9XG4gIHJldHVybiBnZXRDb250YWluaW5nU1ZHKHBhcmVudCk7XG59XG5cbi8qKlxuKiBNYXBzIGFyZ3VtZW50cyBpbiB0byBkMy5pbnRlcnBvbGF0ZVJnYkJhc2lzXG4qIEBwYXJhbSBhcmd1bWVudHNcbiogQHJldHVybnMge0Z1bmN0aW9ufVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcnBvbGF0ZUNvbG9ycygpe3JldHVybiBkMy5pbnRlcnBvbGF0ZVJnYkJhc2lzKGFyZ3VtZW50cyl9XG5cblxuLyoqXG4qIFRyeXMgdG8gcmVkdWNlIHRleHQgdG8gZml0IGluIHNwZWNpZmllZCBhcmVhLCBtYWRlIGZvciB0aWNrIGxhYmVscyBhcyBjYWxsZWQgYnlcbiogQHNlZXtAbGluayBheGlzfVxuKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gdCBjb250YWluZXIgZm9yIHNwZWNpZmljIGF4aXMgdGlja1xuKiBAcGFyYW0ge3N0cmluZ30gdGV4dCB0byBiZSB0aGUgbGFiZWwgb2YgdGhlIHBhc3NlZCBheGlzIHRpY2tcbiogQHBhcmFtIHtib29sZWFufSBvcmllbnQgb2YgdGhlIGF4aXMsIHRydWUgaXMgaG9yaXpvbnRhbCwgZmFsc2UgaXMgdmVydGljYWxcbiogQHBhcmFtIHtudW1iZXJ9IHRpY2tMZW5ndGggaXMgdGhlIGxlbmd0aCBvZiB0aGUgdGV4dFxuKiBAcGFyYW0ge251bWJlcn0gc3BhY2UgaXMgdGhlIGFtb3VudCBvZiBhdmFpbGJsZSBzcGFjZSBmb3IgdGhlIHRleHQgYW5kIHRoZSB0aWNrIHRvIGZpdCBpblxuKiBAcGFyYW0ge2Jvb2xlYW59IG92ZXJmbG93USB3aGV0aGVyIG9yIG5vdCBhbGxvd2VkIHRvIGdvIG92ZXIgdGhlIGFsbG90ZWQgc3BhY2VcbiogQHJldHVybnMge25vbmV9XG4qL1xuZXhwb3J0IGZ1bmN0aW9uIHRydW5jYXRlVGV4dCh0LCB0ZXh0LCBvcmllbnQsIHRpY2tMZW5ndGgsIHNwYWNlLCBvdmVyZmxvd1EpIHtcbiAgdmFyIHJlY3QgPSB0Lm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVxuICB0LnRleHQodGV4dClcbiAgd2hpbGUgKE1hdGgubWF4KHJlY3Qud2lkdGgsIHJlY3QuaGVpZ2h0KSA+IHNwYWNlIC0gdGlja0xlbmd0aCkge1xuICAgIHRleHQgPSBTdHJpbmcodGV4dClcbiAgICB0ZXh0ID0gdGV4dC5zbGljZSgwLCB0ZXh0Lmxlbmd0aCAtIDEpXG4gICAgdC50ZXh0KHRleHQgKyAnLi4uJylcbiAgICByZWN0ID0gdC5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClcbiAgICBpZiAodGV4dC5sZW5ndGggPT0gMCkgYnJlYWtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJ1bmNhdGVTdHJpbmcoc3RyaW5nLCBzcGFjZSwgZm9udCkge1xuICB2YXIgY2hhcnMgPSBzcGFjZSAvIGZvbnQ7XG4gIGlmIChjaGFycyA8IHN0cmluZy5sZW5ndGgpIHtcbiAgICByZXR1cm4gc3RyaW5nLnNsaWNlKDAsIE1hdGgucm91bmQoY2hhcnMtNSkpICsgJy4uLidcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gc3RyaW5nXG4gIH1cbn1cblxuXG4vKipcbiogVHJ5cyB0byB1c2UgZDMuc2VsZWN0aW9uIHRvIGdldCBlbGVtZW50LCBpZiBpdCBkb2VzbnQgZXhpc3QsIG1ha2VzIG9uZVxuKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gc2VsIHNlbGVjdGlvbiBpbiB3aGljaCB0byB0cnkgYW5kIGZpbmQgb2JqZWN0XG4qIEBwYXJhbSB7c3RyaW5nfSB0YWcgdGFnIG9mIHdoaWNoIHRvIHRyeSBhbmQgc2VsZWN0XG4qIEBwYXJhbSB7c3RyaW5nfSBbY2xzPScnXSBjbGFzcyBvZiB0YWcgdG8gdHJ5IGFuZCBncmFiXG4qIEByZXR1cm5zIHtkMy5zZWxlY3Rpb259IG9mIGVpdGhlciBhcHBlbmQgb3Igc2VsZWN0ZWQgdGFnLmNscyB3aXRoaW4gc2VsXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIHNhZmVTZWxlY3Qoc2VsLCB0YWcsIGNscykge1xuICB2YXIgY2xzU3RyID0gY2xzID09IHVuZGVmaW5lZCA/ICcnIDogJy4nK2NscztcbiAgdmFyIHNTZWwgPSBzZWwuc2VsZWN0KHRhZytjbHNTdHIpLmVtcHR5KClcbiAgPyBzZWwuYXBwZW5kKHRhZylcbiAgOiBzZWwuc2VsZWN0KHRhZytjbHNTdHIpXG4gIHJldHVybiBzU2VsXG4gIC5jbGFzc2VkKGNsc1N0ci5yZXBsYWNlKCcuJywgJycpLCB0cnVlKVxuICAuYXR0cigndHJhbnNmb3JtJywgc1NlbC5hdHRyKCd0cmFuc2Zvcm0nKSA9PSB1bmRlZmluZWQgPyAndHJhbnNsYXRlKDAsMCknIDogc1NlbC5hdHRyKCd0cmFuc2Zvcm0nKSlcbn1cblxuLyoqXG4qIGV2ZW5seSBwYXJ0aXRpb25zIHRoZSByYW5nZSBbbWluLCBtYXhdIGludG8gbiBwYXJ0c1xuKiBAcGFyYW0ge251bWJlcn0gbWluXG4qIEBwYXJhbSB7bnVtYmVyfSBtYXhcbiogQHBhcmFtIHtudW1iZXJ9IG5cbiogQHJldHVybnMge251bWJlcltdfSBhcnJheSBvZiBsZW5ndGggbiBldmVubHkgcGFydGl0aW9uZWQgYmV0d2VlbiBtaW4gYW5kIG1heFxuKi9cbmV4cG9ydCBmdW5jdGlvbiB0aWNrUmFuZ2UobWluLCBtYXgsIG4pIHtcbiAgdmFyIGEgPSBbbWluXVxuICB2YXIgZCA9IG1heC1taW5cbiAgdmFyIHMgPSBkIC8gKG4tMSlcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuLTI7IGkrKykgeyBhLnB1c2gobWluICsgcyAqIChpKzEpKSB9XG4gIGEucHVzaChtYXgpXG4gIHJldHVybiBhXG59XG5cblxuZXhwb3J0IGZ1bmN0aW9uIGV1Y2xpZGVhbkRpc3RhbmNlKHAxLCBwMil7XG4gIHZhciBhID0gIHAxWzBdIC0gcDJbMF0sIGIgPSAgcDFbMV0gLSBwMlsxXVxuICByZXR1cm4gTWF0aC5zcXJ0KGEqYSArIGIqYilcbn1cbiIsImltcG9ydCB7dW5pcXVlRWxlbWVudHN9IGZyb20gJy4vaGVscGVycyc7XG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBST1RPVFlQRVMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuLyoqXG4qIFRoaXMgZnVuY3Rpb24gdGVzdHMgdG8gc2VlIGlmIGFsbCBlbGVtZW50cyBvZiB0aGUgcGFzc2VkIGFycmF5IGFyZSB0cnVlLlxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiB2YWx1ZXNcbiogQHBhcmFtIHtGdW5jdGlvbn0gW2Z1bmMgZnVuY3Rpb24odmFsdWUpe3JldHVybiB2YWx1ZSA9PSB0cnVlO31dIGlzIGFwcGxpZWQgdG8gZWFjaCB2YWx1ZSBvZiB0aGUgYXJyYXkgYW5kIHNob3VsZCByZXR1cm4gYSBib29sZWFuLlxuKiBAcmV0dXJucyB7Ym9vbGVhbn0gaWYgYWxsIHZhbHVlcyBhcmUgdHJ1ZSBieSBmdW5jdGlvblxuKi9cbmV4cG9ydCBmdW5jdGlvbiBhbGwoIGFycmF5LCBmdW5jICkge1xuICBpZiAoZnVuYyA9PSB1bmRlZmluZWQpIHsgcmV0dXJuIGFycmF5LmV2ZXJ5KCBmdW5jdGlvbih2YWx1ZSkgeyByZXR1cm4gdmFsdWUgPT09IHRydWU7IH0pOyB9XG4gIHJldHVybiBhcnJheS5ldmVyeSggZnVuY3Rpb24odmFsdWUpIHsgcmV0dXJuIGZ1bmModmFsdWUpOyB9ICk7XG59XG5cbi8qKlxuKiBDb3VudHMgdGhlIG51bWJlciBvZiBvY2N1cmFuY2VzIG9mIGVhY2ggZWxlbWVudCBpbiB0aGUgZ2l2ZW4gYXJyYXkuXG4qIEBwYXJhbSB7QXJyYXl9IGFycmF5IG9mIGVsZW1lbnRzXG4qIEByZXR1cm5zIHtPYmplY3R9IG9mIGtleTogdmFsdWUgcGFpcnMgd2hlcmUga2V5IGlzIGFuIGVsZW1lbnQgaW4gdGhlIGFycmF5IGFuZCB2YWx1ZSBpcyB0aGUgbnVtYmVyIG9mIHRpbWVzIGl0IG9jY3Vycy5cbiovXG5leHBvcnQgZnVuY3Rpb24gdGFsbHkoIGFycmF5ICkge1xuICB2YXIgdGFsbGllcyA9IHt9O1xuICBhcnJheS5tYXAoIGZ1bmN0aW9uICggZWxlbWVudCApIHtcbiAgICBpZiAoIGhhc1EoT2JqZWN0LmtleXModGFsbGllcyksIGVsZW1lbnQpICkgeyB0YWxsaWVzW2VsZW1lbnRdID0gMTsgfVxuICAgIGVsc2UgeyB0YWxsaWVzW2VsZW1lbnRdICs9IDE7IH1cbiAgfSk7XG4gIHJldHVybiB0YWxsaWVzO1xufVxuLyoqXG4qIFNob3J0LWhhbmQgZm9yIGFycmF5LmluY2x1ZGVzKGl0ZW0pO1xuKiBAcGFyYW0ge0FycmF5fSBhcnJheVxuKiBAcGFyYW0geyp9IGl0ZW0gdG8gdGVzdCBpZiBjb250YWluZWQgaW4gIHthcnJheX1cbiogQHJldHVybnMge2Jvb2xlYW59XG4qL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc1EoIGFycmF5LCBpdGVtICkgeyByZXR1cm4gYXJyYXkuaW5jbHVkZXMoaXRlbSk7IH1cblxuLyoqXG4qIFJldHVybnMgZmlyc3QgaXRlbSBpbiBhcnJheVxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtc1xuKiBAcmV0dXJucyB7Kn0gYXJyYXlbMF1cbiovXG5leHBvcnQgZnVuY3Rpb24gZmlyc3QoIGFycmF5ICkgeyByZXR1cm4gYXJyYXlbMF07IH1cblxuLyoqXG4qIFJldHVybnMgbGFzdCBpdGVtIGluIGFycmF5XG4qIEBwYXJhbSB7QXJyYXl9IGFycmF5IG9mIGl0ZW1zXG4qIEByZXR1cm5zIHsqfSBhcnJheVthcnJheS5sZW5ndGgtMV1cbiovXG5leHBvcnQgZnVuY3Rpb24gbGFzdCggYXJyYXkgKSB7IHJldHVybiBhcnJheVthcnJheS5sZW5ndGgtMV07IH1cblxuLyoqXG4qIENhbGN1bGF0ZXMgdGhlIHRvdGFsIHZhbHVlIG9mIG51bWJlcnMgaW4gcGFzc2VkIGFycmF5XG4qIEBwYXJhbSB7bnVtYmVyW119IGFycmF5IG9mIG51bWVyaWNhbCB2YWx1ZXNcbiogQHJldHVybnMge251bWJlcn0gc3VtIG92ZXIgZWxlbWVudHMgaW4gYXJyYXlcbiovXG5leHBvcnQgZnVuY3Rpb24gdG90YWwoIGFycmF5ICkgeyByZXR1cm4gYXJyYXkucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCkgfTtcblxuLyoqXG4qIFJlbW92ZXMgZHVwbGljYXRlcyBpbiBhcnJheVxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtc1xuKiBAcmV0dXJucyB7QXJyYXl9IG9mIGl0ZW1zIHN1Y2ggdGhhdCBpdGVtX2kgIT0gaXRlbV9qIGZvciBhbGwgaSA8IGpcbiogQHNlZXtAbGluayB1bmlxdWVFbGVtZW50c30gZm9yIHRoZSBmaWx0ZXJpbmcgZnVuY3Rpb25cbiovXG5leHBvcnQgZnVuY3Rpb24gdW5pcXVlKCBhcnJheSApIHsgcmV0dXJuIGFycmF5LmZpbHRlciggdW5pcXVlRWxlbWVudHMgKTsgfVxuXG4vKipcbiogRmlsdGVycyBwYXNzZWQgYXJyYXkgZm9yIHNwZWNpZmllZCBpbmRpY2llc1xuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtc1xuKiBAcGFyYW0ge251bWJlcltdfSBwb3NpdGlvbnMgb2YgaW50ZWdlcnMgc3VjaCB0aGF0IGkgPCBhcnJheS5sZW5ndGhcbiogQHJldHVybnMge0FycmF5fSBvZiBpdGVtcyBzdWNoIHRoYXQgZm9yIGFueSBpdGVtX2ksIHBvc2l0aW9ucy5pbmNsdWRlcyhpKSA9PT0gdHJ1ZVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXQoIGFycmF5LCBwb3NpdGlvbnMgKSB7XG4gIHJldHVybiBhcnJheS5maWx0ZXIoIGZ1bmN0aW9uKCB2YWx1ZSwgaW5kZXggKSB7IHJldHVybiBoYXNRKHBvc2l0aW9ucywgaW5kZXgpOyB9ICk7XG59XG5cbi8qKlxuKiBEZXRlcm1pbmVzIGlmIGFsbCBlbGVtZW50cyBpbiBwYXNzZWQgYXJyYXkgYXJlIGFycmF5cyB0aGVtc2VsdmVzLlxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtc1xuKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiBBcnJheS5pc0FycmF5KGUpIGlzIHRydWUgZm9yIGFsbCBlIGluIGFycmF5XG4qIEBzZWV7QGxpbmsgYWxsfVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXN0T2ZMaXN0c1EoIGFycmF5ICkge1xuICByZXR1cm4gYWxsKCBhcnJheS5tYXAoIGZ1bmN0aW9uKCBlbGVtZW50LCBpbmRleCApIHsgcmV0dXJuIEFycmF5LmlzQXJyYXkoZWxlbWVudCkgfSApIClcbn1cblxuLyoqXG4qIEJ1aWx0IG9uIHRvcCBvZiBAc2Vle0BsaW5rIGdldH0sIG1hcHBpbmcgaWYgcG9zaXRpb25zIGlzIGEgbGlzdCBvZiBsaXN0cyAoQHNlZXtAbGluayBsaXN0T2ZMaXN0c1F9KVxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtc1xuKiBAcGFyYW0ge251bWJlcltdIHwgW11udW1iZXJbXSB9IHBvc2l0aW9ucyBvZiBpbnRlZ2VycyBvciBsaXN0IG9mIHBvc2l0aW9ucyBvZiBpbnRlZ2Vyc1xuKiBAcmV0dXJucyB7Ym9vbGVhbn0gcmV0dXJucyBzcGVjaWZpZWQgcG9zaXRpb25zIGZyb20gYXJyYXkuIElmIG5lc3RlZCBwb3NpdGlvbnMgcGFzc2VkLCByZXR1cm5zIHJlcXVlc3RlZCBpdGVtcyBpbiBzYW1lIHN0cnVjdHVyZS5cbiovXG5leHBvcnQgZnVuY3Rpb24gY3V0KCBhcnJheSwgcG9zaXRpb25zICkge1xuICBpZiAoIGxpc3RPZkxpc3RzUShhcnJheSkgKSB7IHJldHVybiBwb3NpdGlvbnMubWFwKGZ1bmN0aW9uKHBvcywgaSkgeyByZXR1cm4gYXJyYXkuZ2V0KHBvcyk7IH0pOyB9XG4gIHJldHVybiBnZXQoIGFycmF5LCBwb3NpdGlvbnMgKTtcbn1cblxuLyoqXG4qIEdpdmVuIGFuIGFycmF5IG9mIG9iamVjdHMsIGNvbnN0cnVjdHMgbmV3IG9iamVjdHMgd2hlcmUgZWFjaCB2YWx1ZSBpcyBhIGxpc3RcbiogYmFzZWQgb24gdGhlIGNvcnJlc29uZGluZyBrZXksIHdoaWNoIGlzIGV4dHJhY3RlZCBieSB0aGUgcGFyYW1ldGVyIGJ5XG4qIEBwYXJhbSB7T2JqZWN0c1tdfSBhcnJheSBvZiBvYmplY3RzXG4qIEBwYXJhbSB7c3RyaW5nfSBieSBrZXkgd2l0aGluIGFsbCBvYmplY3RzIG9mIHBhc3NlZCBhcnJheVxuKiBAcGFyYW0ge3N0cmluZ1tdfSBbZ3JvdXBzXSBzYXZlcyBzb21lIGNvbXB1dGF0aW9uIGlmIGFsbCBrbm93biB2YWx1ZXMgZXh0cmFjdGVkIGJ5IG1hcHBpbmcgb3ZlciB0aGUgcGFyYW1ldGVyIGJ5IGFyZSBwYXNzZWRcbiogQHJldHVybnMge09iamVjdH0gb2Yga2V5IHZhbHVlIHBhaXJzLCB3aGVyZSBrZXlzIGFyZSBhbGwgdmFsdWVzIG9mIHRoZSBrZXkgYnkgZnJvbSBhbiBvYmplY3QgaW4gdGhlIHBhc3NlZCBhcnJheSBhbmQgdGhlIHZhbHVlIGFyZSB0aG9zZSBjb3JyZXNwb25kaW5nIG9iamVjdHMuXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIGdyb3VwQnkgKGFycmF5LCBieSwgZ3JvdXBzKSB7XG4gIGlmIChncm91cHMgPT0gdW5kZWZpbmVkKSB7XG4gICAgZ3JvdXBzID0gdW5pcXVlKGFycmF5Lm1hcChmdW5jdGlvbihlbGVtZW50cywgaW5kZXgpeyByZXR1cm4gZWxlbWVudFtieV07IH0pKTtcbiAgICBncm91cHMubWFwKGZ1bmN0aW9uKHZhbHVlLCBpbmRleCl7Z3JvdXBwZWRbdmFsdWVdID0gW119KVxuICB9XG5cbiAgdmFyIGdyb3VwcGVkID0ge307XG4gIGFycmF5Lm1hcChmdW5jdGlvbihlbGVtZW50LCBpbmRleCl7Z3JvdXBwZWRbZWxlbWVudFtieV1dLnB1c2goZWxlbWVudCl9KTtcbiAgcmV0dXJuIGdyb3VwcGVkXG59XG5cbi8qKlxuKiBUZXN0cyBpZiB0d28gYXJyYXlzIGFyZSBlcXVpdmFsZW50XG4qIEBwYXJhbSB7QXJyYXl9IGFycmF5XG4qIEBwYXJhbSB7QXJyYXl9IG90aGVyXG4qIEByZXR1cm5zIHtib29sZWFufSBpZiBldmVyeSBlbGVtZW50IG9mIGFycmF5IG1hdGNoZXMgdGhhdCBvZiBvdGhlclxuKi9cbmV4cG9ydCBmdW5jdGlvbiBhcnJheUVxdWFscyhhcnJheSwgb3RoZXIpIHtcbiAgaWYgKCFvdGhlcilcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgLy8gY29tcGFyZSBsZW5ndGhzIC0gY2FuIHNhdmUgYSBsb3Qgb2YgdGltZVxuICBpZiAoYXJyYXkubGVuZ3RoICE9IG90aGVyLmxlbmd0aClcbiAgICAgIHJldHVybiBmYWxzZTtcblxuICBmb3IgKHZhciBpID0gMCwgbD1hcnJheS5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgbmVzdGVkIGFycmF5c1xuICAgICAgaWYgKGFycmF5W2ldIGluc3RhbmNlb2YgQXJyYXkgJiYgb3RoZXJbaV0gaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgIC8vIHJlY3Vyc2UgaW50byB0aGUgbmVzdGVkIGFycmF5c1xuICAgICAgICAgIGlmICghYXJyYXlFcXVhbHMoYXJyYXlbaV0sb3RoZXJbaV0pKVxuICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChhcnJheVtpXSAhPSBvdGhlcltpXSkge1xuICAgICAgICAgIC8vIFdhcm5pbmcgLSB0d28gZGlmZmVyZW50IG9iamVjdCBpbnN0YW5jZXMgd2lsbCBuZXZlciBiZSBlcXVhbDoge3g6MjB9ICE9IHt4OjIwfVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuXG5cbi8qKlxuKiBSZWN1cnNpdmVseSB0YWxsaWVzIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgYXQgZWFjaCBsZXZlbCBvZiB0aGUgcGFzc2VkLCBwdXRhdGl2ZWx5IG5lc3RlZCBhcnJheVxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtcyB3aGljaCBtYXkgaW5jbHVkZSBuZXN0ZWQgYXJyYXlzXG4qIEBwYXJhbSB7bnVtYmVyfSBbbGV2ZWw9MF0gY3VycmVudCBkZXB0aCBpbiB0aGUgcmVjdXJzaW9uXG4qIEBwYXJhbSB7QXJyYXl9IFtsZXZlbERhdGE9W11dIGtlZXBzIHRyYWNrIG9mIGl0ZW1zIHNlZW4gc28gZmFyIGF0IGVhY2ggZGVwdGhcbiogQHJldHVybnMge0FycmF5fSBzdGF0aW5nIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgKGFycmF5IGluY2x1c2l2ZSkgZm91bmQgYXQgZWFjaCBsZXZlbCBvZiB0aGUgYXJyYXlcbiovXG5leHBvcnQgZnVuY3Rpb24gZWxlbWVudHNBdExldmVscyhhcnJheSwgbGV2ZWwsIGxldmVsRGF0YSkge1xuICBsZXZlbCA9IGxldmVsID09IHVuZGVmaW5lZCA/IDAgOiBsZXZlbCArIDE7XG4gIGxldmVsRGF0YSA9IGxldmVsRGF0YSA9PSB1bmRlZmluZWQgPyBbXSA6IGxldmVsRGF0YTtcbiAgaWYgKCBsZXZlbCA+PSBsZXZlbERhdGEubGVuZ3RoICkgeyBsZXZlbERhdGEucHVzaChhcnJheS5sZW5ndGgpfSBlbHNlIHtsZXZlbERhdGFbbGV2ZWxdICs9IGFycmF5Lmxlbmd0aCB9XG4gIGFycmF5Lm1hcChmdW5jdGlvbihlLCBpKSB7aWYgKEFycmF5LmlzQXJyYXkoZSkpeyBlbGVtZW50c0F0TGV2ZWxzKGUsIGxldmVsLCBsZXZlbERhdGEpIH19KVxuICByZXR1cm4gbGV2ZWxEYXRhXG59XG5cblxuLyoqXG4qIFJlY3Vyc2l2ZWx5IHRhbGxpZXMgdGhlIG51bWJlciBvZiBlbGVtZW50cyBvZiB0aGUgcGFzc2VkLCBwdXRhdGl2ZWx5IG5lc3RlZCBhcnJheVxuKiBAcGFyYW0ge0FycmF5fSBhcnJheSBvZiBpdGVtcyB3aGljaCBtYXkgaW5jbHVkZSBuZXN0ZWQgYXJyYXlzXG4qIEBwYXJhbSB7bnVtYmVyfSBbZWxlbWVudHM9MF0gY3VycmVudCBudW1iZXIgb2YgZWxlbWVudHMgc2VlbiBzbyBmYXJcbiogQHJldHVybnMge251bWJlcn0gbnVtYmVyIG9mIGVsZW1lbnRzIChhcnJheSBpbmNsdXNpdmUpIGZvdW5kIGluIHBhc3NlZCBhcnJheVxuKi9cbmV4cG9ydCBmdW5jdGlvbiBudW1iZXJPZkVsZW1lbnRzKCBhcnJheSwgZWxlbWVudHMgKSB7XG4gIGVsZW1lbnRzID0gZWxlbWVudHMgPT0gdW5kZWZpbmVkID8gMCA6IGVsZW1lbnRzO1xuICBhcnJheS5tYXAoZnVuY3Rpb24oZSwgaSkge1xuICAgIGlmICggQXJyYXkuaXNBcnJheShlKSApIHsgZWxlbWVudHMgPSBudW1iZXJPZkVsZW1lbnRzKGUsIGVsZW1lbnRzKSB9XG4gICAgZWxzZSB7IGVsZW1lbnRzICs9IDEgfVxuICB9KVxuICByZXR1cm4gZWxlbWVudHNcbn1cblxuLyoqXG4qIENvbmNhdHMgYWxsIG5lc3RlZCBhcnJheXMgaW4gcGFzc2VkIGFycmF5IHRvIGZvcm0gYSBzaW5nbGUgYXJyYXlcbiogQHBhcmFtIHtBcnJheX0gYXJyYXkgb2YgcHV0YXRpdmVseSBuZXN0ZWQgYXJyYXlzXG4qIEBwYXJhbSB7QXJyYXl9IFtmbGF0PVtdXSBjdXJyZW50IGZsYXR0ZW5lZCBhcnJheVxuKiBAcmV0dXJucyB7QXJyYXl9IHdpdGggZXZlcnkgZWxlbWVudCBpbiB0aGUgc2FtZSBsZXZlbFxuKi9cbmV4cG9ydCBmdW5jdGlvbiBmbGF0dGVuKCBhcnJheSwgZmxhdCApIHtcbiAgZmxhdCA9IGZsYXQgPT0gdW5kZWZpbmVkID8gW10gOiBmbGF0O1xuICBhcnJheS5tYXAoZnVuY3Rpb24oZSwgaSl7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZSkpIHtmbGF0ID0gZmxhdC5jb25jYXQoZmxhdHRlbihlKSl9XG4gICAgZWxzZSB7ZmxhdC5wdXNoKGUpfVxuICB9KVxuICByZXR1cm4gZmxhdDtcbn1cblxuLyoqXG4qIFNlYXJjaCBvZiBsaXN0IG9mIGxpc3RzIHRvIGZpbmQgd2hpY2ggLSBpZiBhbnkgLSBwYXNzZWQgdmFsdWUgaXMgaW5cbiogQHBhcmFtIHtBcnJheVtdfSBiaW5zIGxpc3Qgb2YgbGlzdHMgb2YgdmFsdWVzXG4qIEBwYXJhbSB7Kn0gdmFsdWUgaXRlbSB0byB0ZXN0IGlmIGluIGFueSBvZiB0aGUgYmluc1xuKiBAcmV0dXJucyB7bnVtYmVyfSBpbmRpY2F0aW5nIHRoZSBpbmRleCBvZiB0aGUgYmluIGluIHdoaWNoIHZhbHVlIHdhcyBmb3VuZFxuKi9cbmV4cG9ydCBmdW5jdGlvbiB3aGljaEJpbihiaW5zLCB2YWx1ZSkge1xuICB2YXIgaSA9IC0xXG4gIGZvciAodmFyIGogPSAwOyBqIDwgYmlucy5sZW5ndGg7IGorKykgeyBpZiAoaGFzUShiaW5zW2pdLHZhbHVlKSkge3JldHVybiBqfSB9XG4gIHJldHVybiBpXG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHt0b3RhbH0gZnJvbSAnLi9hcnJheS1mdW5jdGlvbnMnO1xuXG5cbi8qKlxuICogY2FsbHMgY29uc29sZS5ncm91cCBpZiBkM3NtLmRlYnVnUSA9PSB0cnVlXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBvZiB0aGUgZ3JvdXBcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25zb2xlR3JvdXAobmFtZSkge1xuICBpZiAod2luZG93LmQzc20uZGVidWdRID09PSB0cnVlKXtcbiAgICBjb25zb2xlLmdyb3VwKG5hbWUpXG4gIH1cbn1cblxuLyoqXG4gKiBjYWxscyBjb25zb2xlLmdyb3VwRW5kIGlmIGQzc20uZGVidWdRID09IHRydWVcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25zb2xlR3JvdXBFbmQoKSB7XG4gIGlmICh3aW5kb3cuZDNzbS5kZWJ1Z1EgPT09IHRydWUpe1xuICAgIGNvbnNvbGUuZ3JvdXBFbmQoKVxuICB9XG59XG5cbi8qKlxuICogQ2FsbHMgY29uc29sZS5sb2cgaWYgZDNzbS5kZWJ1Z1EgPT0gdHJ1ZVxuICogQHBhcmFtIHtzdHJpbmd9IGZ1bmMgbmFtZSBvZiB0aGUgZnVuY3Rpb24gbG9nZ2luZ1xuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0byBsb2dcbiAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhIHRvIGJlIGxvZ2dlZCBhbG9uZyBzaWRlIHRoZSBtZXNzYWdlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gbG9nKGZ1bmMsIG1zZywgZGF0YSkge1xuICBpZiAod2luZG93LmQzc20uZGVidWdRID09PSB0cnVlKXtcbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGAlY1tkM3NtOjoke2Z1bmN9XTpcXHQke21zZ31gLFxuICAgICAgW1xuICAgICAgICAnYmFja2dyb3VuZDogIzZjZDFlZicsXG4gICAgICAgICdib3JkZXItcmFkaXVzOiA1MDAwcHgnLFxuICAgICAgICAncGFkZGluZzogMHB4IDJweCcsXG4gICAgICAgICdmb250LXNpemU6IDE0cHgnXG4gICAgICBdLmpvaW4oJzsnKVxuICAgIClcbiAgICBjb25zb2xlLnRhYmxlKGRhdGEpXG4gICAgLy8gY29uc29sZS50cmFjZSgpXG4gIH1cbn1cblxuLyoqXG4gKiBDYWxscyBjb25zb2xlLndhcm4gaWYgZDNzbS5kZWJ1Z1EgPT0gdHJ1ZVxuICogQHBhcmFtIHtzdHJpbmd9IGZ1bmMgbmFtZSBvZiB0aGUgZnVuY3Rpb24gd2FybmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0byBkaXNwbGF5XG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YSB0byBiZSBkaXNwbGF5ZWQgYWxvbmcgc2lkZSB0aGUgbWVzc2FnZVxuICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdhcm4oZnVuYywgbXNnLCBkYXRhKSB7XG4gIGlmICh3aW5kb3cuZDNzbS5kZWJ1Z1EgPT09IHRydWUpXG4gICAgY29uc29sZS53YXJuKFxuICAgICAgYCVjW2Qzc206OiR7ZnVuY31dOlxcdCR7bXNnfWAsXG4gICAgICBbXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjZmZkNTNlJyxcbiAgICAgICAgJ2JvcmRlci1yYWRpdXM6IDUwMDBweCcsXG4gICAgICAgICdwYWRkaW5nOiAwcHggMnB4JyxcbiAgICAgICAgJ2ZvbnQtc2l6ZTogMTRweCdcbiAgICAgIF0uam9pbignOycpXG4gICAgKVxuICAgIGNvbnNvbGUudGFibGUoZGF0YSlcbn1cbi8qKlxuICogQ2FsbHMgdGhlIGNvbnNvbGUuaW5mbyBpZiBkM3NtLmRlYnVnUSA9PSB0cnVlXG4gKiBAcGFyYW0ge3N0cmluZ30gZnVuYyBuYW1lIG9mIHRoZSBmdW5jdGlvbiBwcm92aWRpbmcgaW5mb1xuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0byBkaXNwbGF5XG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YSB0byBiZSBkaXNwbGF5ZWQgYWxvbmcgc2lkZSB0aGUgbWVzc2FnZVxuICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluZm8oZnVuYywgbXNnLCBkYXRhKSB7XG4gIGlmICh3aW5kb3cuZDNzbS5kZWJ1Z1EpXG4gICAgY29uc29sZS5pbmZvKFxuICAgICAgYCVjW2Qzc206OiR7ZnVuY31dOlxcdCR7bXNnfWAsXG4gICAgICBbXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjMDA5Y2NkJyxcbiAgICAgICAgJ2JvcmRlci1yYWRpdXM6IDUwMDBweCcsXG4gICAgICAgICdwYWRkaW5nOiAwcHggMnB4JyxcbiAgICAgICAgJ2ZvbnQtc2l6ZTogMTRweCdcbiAgICAgIF0uam9pbignOycpXG4gICAgKVxuICAgIGNvbnNvbGUudGFibGUoZGF0YSlcbn1cblxuXG4vKipcbiAqIENhbGxzIGNvbnNvbGUuZXJyb3IgaWYgZDNzbS5kZWJ1Z1EgPT0gdHJ1ZVxuICogQHBhcmFtIHtzdHJpbmd9IGZ1bmMgbmFtZSBvZiB0aGUgZnVuY3Rpb24gd2hpY2ggc2VuZHMgdGhlIGVycm9yXG4gKiBAcGFyYW0ge3N0cmluZ30gbXNnIHRvIGRpc3BsYXlcbiAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhIHRvIGJlIGRpc3BsYXllZCBhbG9uZyBzaWRlIHRoZSBtZXNzYWdlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZXJyb3IoZnVuYywgbXNnLCBkYXRhKSB7XG4gIGlmICh3aW5kb3cuZDNzbS5kZWJ1Z1EpXG4gICAgY29uc29sZS5lcnJvcihgW2Qzc206OiR7ZnVuY31dOlxcdCR7bXNnfVxcdCVvYCxkYXRhKVxufVxuXG5cblxuXG5cbi8qKlxuKiBGdW5jdGlvbiBmb3Igc2V0dGluZyB1cCBjb250YWluZXJzIGZvciBtb3N0IHBsb3RzIHdpdGggdGhlIHkgYXhpcyBjb250YWluZXJcbiogcG9zaXRpb25lZCBvbiB0aGUgbGVmdCBhbmQgdGhlIHggYXhpcyBjb250YWluZXIgcG9zaXRpb25lZCBvbiB0aGUgYm90dG9tXG4qIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBzZWxlY3Rpb24gc2VsZWN0aW9uIG9mIGNvbnRhaW5lciBpbiB3aGljaCB0aGUgc3ZnIGlzIG9yIHNob3VsZCBiZSBtYWRlXG4qIEBwYXJhbSB7c3RyaW5nfSBuYW1lc3BhY2UgbmFtZXNwYWNlIG9mIHRoZSBjaGFydFxuKiBAcGFyYW0ge09iamVjdH0gW3NwYWNlPXt3OndpbmRvdy5pbm5lcldpZHRoLCBoOndpbmRvdy5pbm5lckhlaWdodH1dIHRoZSB3aWR0aCAodykgYW5kIGhlaWdodCAoaCkgYXZhaWxibGVcbiogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZS53PXdpbmRvdy5pbm5lcldpZHRoXSB0aGUgYXZhaWxhYmxlIHdpZHRoIGluIHdoaWNoIHRvIHJlbmRlciB0aGUgY2hhcnRcbiogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZS5oPXdpbmRvdy5pbm5lckhlaWdodF0gdGhlIGF2YWlsYWJsZSBoZWlnaHQgaW4gd2hpY2ggdG8gcmVuZGVyIHRoZSBjaGFydFxuXG4qIEBwYXJhbSB7T2JqZWN0fSBbbWFyZ2lucz17dG9wOiAwLjAxLCBib3R0b206IDAuMDEsIGxlZnQ6IDAuMDEsIHJpZ2h0OiAwLjAxfV0gdGhlIG1hcmdpbnMgZm9yIHRoZSBjaGFydFxuKiBAcGFyYW0ge251bWJlcn0gW21hcmdpbnMudG9wPTAuMDFdIHRoZSB0b3AgbWFyZ2luIG9mIHRoZSBjaGFydFxuKiBAcGFyYW0ge251bWJlcn0gW21hcmdpbnMuYm90dG9tPTAuMDFdIHRoZSBib3R0b20gbWFyZ2luIG9mIHRoZSBjaGFydFxuKiBAcGFyYW0ge251bWJlcn0gW21hcmdpbnMubGVmdD0wLjAxXSB0aGUgbGVmdCBtYXJnaW4gb2YgdGhlIGNoYXJ0XG4qIEBwYXJhbSB7bnVtYmVyfSBbbWFyZ2lucy5yaWdodD0wLjAxXSB0aGUgcmlnaHQgbWFyZ2luIG9mIHRoZSBjaGFydFxuXG5cbiogQHBhcmFtIHtPYmplY3R9IFtwZXJjZW50YWdlcyA9IHtheGVzOnt4OjAuMSx5OjAuMX0sc3BhY2U6e3c6MC44LGg6MC42fX1dIHBlcmNlbnRhZ2VzIG9mIHRoZSBwYXJhbWF0ZXIgc3BhY2Ugb2Ygd2hpY2ggdG8gbWFrZSB0aGUgeCBhbmQgeSBheGVzIGFzIHdlbGwgYXMgdGhlIHBlcmNlbnQgb2YgdGhlIGF2YWlsYmxlIHNwYWNlIGluIHdoaWNoIHRvIHJlbmRlciB0aGUgcGxvdFxuKiBAcGFyYW0ge09iamVjdH0gW3BlcmNlbnRhZ2VzLmF4ZXM9e3g6MC4xLHk6MC4xfV0gdGhlIHBlcmNlbnRhZ2VzIG9mIHRoZSBwYXJhbWF0ZXIgc3BhY2UsIG9mIHdoaWNoIHRoZSB4IGFuZCB5IGF4ZXMgd2lsbCB0YWtlIHVwXG4qIEBwYXJhbSB7bnVtYmVyfSBbcGVyY2VudGFnZXMuYXhlcy54QXhpc1BlcmNlbnQ9MC4xXSB0aGUgcGVyY2VudGFnZXMgb2YgdGhlIHBhcmFtYXRlciBzcGFjZSwgb2Ygd2hpY2ggdGhlIHggYXhpcyB3aWxsIHRha2UgdXBcbiogQHBhcmFtIHtudW1iZXJ9IFtwZXJjZW50YWdlcy5heGVzLnlBeGlzUGVyY2VudD0wLjFdIHRoZSBwZXJjZW50YWdlcyBvZiB0aGUgcGFyYW1hdGVyIHNwYWNlLCBvZiB3aGljaCB0aGUgeSBheGlzIHdpbGwgdGFrZSB1cFxuXG4qIEBwYXJhbSB7T2JqZWN0fSBbcGVyY2VudGFnZXMuc3BhY2U9e3c6MC44LGg6MC42fV0gdGhlIHBlcmNlbnRhZ2VzIG9mIHRoZSBwYXJhbWF0ZXIgc3BhY2UsIG9mIHdoaWNoIHRoZSBTVkcncyB3aWR0aCBhbmQgaGVpZ2h0IHdpbGwgYmUgc2V0XG4qIEBwYXJhbSB7bnVtYmVyfSBbcGVyY2VudGFnZXMuc3BhY2UucGVyY2VudE9mU3BhY2VGb3JXaWR0aD0wLjFdIHRoZSBwZXJjZW50YWdlcyBvZiB0aGUgcGFyYW1hdGVyIHNwYWNlLCBvZiB3aGljaCB0aGUgU1ZHJ3Mgd2lkdGggd2lsbCBiZSBzZXRcbiogQHBhcmFtIHtudW1iZXJ9IFtwZXJjZW50YWdlcy5zcGFjZS5wZXJjZW50T2ZTcGFjZUZvckhlaWdodD0wLjFdIHRoZSBwZXJjZW50YWdlcyBvZiB0aGUgcGFyYW1hdGVyIHNwYWNlLCBvZiB3aGljaCB0aGUgU1ZHJ3MgaGVpZ2h0IHdpbGwgYmUgc2V0XG5cbiogQHJldHVybnMge09iamVjdH0gcmV0dXJucyB0aGUgc2VsZWN0aW9uIGFuZCBcImJvdW5kaW5nUmVjdHNcIiBvZiB0aGUgcGxvdCBjb250YWluZXIsIHgtYXhpcyBjb250YWluZXIgYW5kIHktYXhpcyBjb250YWluZXJcbiogYXNcbipcbioge1xuKlxuKiAgIHBsb3Q6IHtzZWxlY3Rpb246IHBsb3RTZWxlY3Rpb24sIHJlY3Q6IHBsb3RSZWN0fSxcbipcbiogICB4QXhpczp7c2VsZWN0aW9uOnhBeGlzU2VsZWN0aW9uLCByZWN0OnhBeGlzUmVjdH0sXG4qXG4qICAgeUF4aXM6IHtzZWxlY3Rpb246eUF4aXNTZWxlY3Rpb24sIHJlY3Q6eUF4aXNSZWN0fVxuKlxuKiB9XG4qXG4qIHdoZXJlIGVhY2ggcmVjdCBoYXMgZm9ybTpcbipcbioge3g6ICMsIHk6ICMsIGg6ICMsIHc6ICN9XG4qXG4qIGRlcGljdGluZyB0aGUgc3RhcnRpbmcgeCBhbmQgeSBjb29yZGluYXRlIG9mIHRoZSBjb3Jlc3BvbmRpbmcgY29udGFpbmVyIChhbHNvIHRoZWlyIGRlZmF1bHQgdHJhbnNmb3JtIHZhbHVlcykgYXMgd2VsbCB0aGVpciBoZWlnaHQgKGgpIGFucyB3aWR0aCAodylcbiovXG4vLyBleHBvcnQgZnVuY3Rpb24gc2V0dXBTdGFuZGFyZENoYXJ0Q29udGFpbmVycyggc2VsZWN0aW9uLCBuYW1lc3BhY2UsIHNwYWNlLCBtYXJnaW5zLCBwZXJjZW50YWdlcykge1xuLy8gZXhwb3J0IGZ1bmN0aW9uIHNldHVwU3RhbmRhcmRDaGFydENvbnRhaW5lcnMoXG4vLyAgIHNlbGVjdGlvbixcbi8vICAgbmFtZXNwYWNlLFxuLy8gICBzcGFjZT17dzphdmFpbGFibGVXaWR0aD13aW5kb3cuaW5uZXJXaWR0aCwgaDphdmFpbGFibGVIZWlnaHQ9d2luZG93LmlubmVySGVpZ2h0fSxcbi8vICAgbWFyZ2lucz17dG9wOjAuMDEsIGJvdHRvbTowLjAxLCBsZWZ0OjAuMDEsIHJpZ2h0OjAuMDF9LFxuLy8gICBwZXJjZW50YWdlcz17YXhlczoge3g6IHhBeGlzUGVyY2VudD0wLjEsIHk6IHlBeGlzUGVyY2VudD0wLjF9LCBzcGFjZToge3c6IHBlcmNlbnRPZlNwYWNlRm9yV2lkdGgsIGg6IHBlcmNlbnRPZlNwYWNlRm9ySGVpZ2h0fX1cbi8vICkge1xuLy8gICBpZiAoc3BhY2UgPT0gdW5kZWZpbmVkKSB7IHNwYWNlID0ge3c6IHdpbmRvdy5pbm5lcldpZHRoLCBoOiB3aW5kb3cuaW5uZXJIZWlnaHR9IH1cbi8vICAgaWYgKG1hcmdpbnMgPT0gdW5kZWZpbmVkKSB7IG1hcmdpbnMgPSB7dG9wOiAwLjAxLCBib3R0b206IDAuMDEsIGxlZnQ6IDAuMDEsIHJpZ2h0OiAwLjAxfSB9XG4vLyAgIGlmIChwZXJjZW50YWdlcyA9PSB1bmRlZmluZWQpIHsgcGVyY2VudGFnZXMgPSB7fTsgfVxuLy8gICBpZiAocGVyY2VudGFnZXMuYXhlcyA9PSB1bmRlZmluZWQpIHsgcGVyY2VudGFnZXMuYXhlcyA9IHsgeDowLjEsIHk6MC4xIH0gfVxuLy8gICBpZiAocGVyY2VudGFnZXMuc3BhY2UgPT0gdW5kZWZpbmVkKSB7IHBlcmNlbnRhZ2VzLnNwYWNlID0geyB3OiAwLjgsIGg6IDAuNiB9IH1cbi8vXG4vLyAgIC8vIFNWRyB3aWR0aCBhbmQgaGVpZ2h0XG4vLyAgIHZhciBzdmdTcGFjZSA9ICB7XG4vLyAgICAgdzogc3BhY2UudyAqIHBlcmNlbnRhZ2VzLnNwYWNlLncsXG4vLyAgICAgaDogc3BhY2UuaCAqIHBlcmNlbnRhZ2VzLnNwYWNlLmhcbi8vICAgfSxcbi8vXG4vLyAgIC8vIFNwYWNlIGFmdGVyIHJlbW92aW5nIG1hcmdpbnNcbi8vICAgY2hhcnRTcGFjZSA9IHtcbi8vICAgICB3OiBzdmdTcGFjZS53IC0gKG1hcmdpbnMubGVmdCAqIHNwYWNlLncpIC0gKG1hcmdpbnMucmlnaHQgKiBzcGFjZS53KSxcbi8vICAgICBoOiBzdmdTcGFjZS5oIC0gKG1hcmdpbnMudG9wICogc3BhY2UuaCkgLSAobWFyZ2lucy5ib3R0b20gKiBzcGFjZS5oKVxuLy8gICB9LFxuLy9cbi8vICAgLy8gbWFpbiBkaW1lbnNpb24gb2YgeCBhbmQgeSBheGllc1xuLy8gICAvLyBlLmcuIGRlZmluZXMgaG93IHRhbGwgeCBheGlzIGlzIGFzIGxlbmd0aCBpcyBkZXRlcm1pbmVkIGJ5IHBsb3RSZWN0Lndcbi8vICAgYXhlc1NwYWNlID0ge1xuLy8gICAgIHg6IGNoYXJ0U3BhY2UuaCAqIHBlcmNlbnRhZ2VzLmF4ZXMueCxcbi8vICAgICB5OiBjaGFydFNwYWNlLncgKiBwZXJjZW50YWdlcy5heGVzLnlcbi8vICAgfSxcbi8vXG4vLyAgIC8vIHNwYWNlIGxlZnQgZm9yIGRyYXdpbmcgdGhlIGNoYXJ0IHByb3Blcmx5IChlLmcuIGJhcnMsIHZpb2xpbnMsIGV0Yylcbi8vICAgZHJhd2luZ1NwYWNlID0ge1xuLy8gICAgIHg6IGNoYXJ0U3BhY2UudyAtIGF4ZXNTcGFjZS55LFxuLy8gICAgIHk6IGNoYXJ0U3BhY2UuaCAtIGF4ZXNTcGFjZS54XG4vLyAgIH0sXG4vL1xuLy9cbi8vICAgeUF4aXNSZWN0ID0ge1xuLy8gICAgIHg6IGF4ZXNTcGFjZS55ICsgKG1hcmdpbnMubGVmdCAqIHNwYWNlLncpLFxuLy8gICAgIHk6IChtYXJnaW5zLnRvcCAqIHNwYWNlLmgpLFxuLy8gICAgIHc6IGF4ZXNTcGFjZS55LFxuLy8gICAgIGg6IGRyYXdpbmdTcGFjZS55XG4vLyAgIH0sXG4vL1xuLy8gICBwbG90UmVjdCA9IHtcbi8vICAgICB4OiBheGVzU3BhY2UueSArIChtYXJnaW5zLmxlZnQgKiBzcGFjZS53KSxcbi8vICAgICB5OiAobWFyZ2lucy50b3AgKiBzcGFjZS5oKSxcbi8vICAgICB3OiBkcmF3aW5nU3BhY2UueCxcbi8vICAgICBoOiBkcmF3aW5nU3BhY2UueVxuLy8gICB9LFxuLy9cbi8vICAgeEF4aXNSZWN0ID0ge1xuLy8gICAgIHg6IGF4ZXNTcGFjZS55ICsgKG1hcmdpbnMubGVmdCAqIHNwYWNlLncpLFxuLy8gICAgIHk6IChtYXJnaW5zLnRvcCAqIHNwYWNlLmggKyBwbG90UmVjdC5oKSxcbi8vICAgICB3OiBkcmF3aW5nU3BhY2UueCxcbi8vICAgICBoOiBheGVzU3BhY2UueFxuLy8gICB9XG4vL1xuLy9cbi8vICAgdmFyIGNvbnRhaW5lciA9IHNhZmVTZWxlY3Qoc2VsZWN0aW9uLCAnc3ZnJywgbmFtZXNwYWNlKVxuLy8gICAgIC5zdHlsZSgnd2lkdGgnLCBzdmdTcGFjZS53KydweCcpXG4vLyAgICAgLnN0eWxlKCdoZWlnaHQnLCBzdmdTcGFjZS5oKydweCcpXG4vL1xuLy8gICB2YXIgYXhlcyA9IHNhZmVTZWxlY3QoY29udGFpbmVyLCAnZycsIGh5cGVuYXRlKG5hbWVzcGFjZSwgJ2F4ZXMnKSlcbi8vXG4vLyAgIC8vIC5hdHRyKCd0cmFuc2Zvcm0nLCBcInRyYW5zbGF0ZShcIitwbG90UmVjdC54K1wiLFwiK3Bsb3RSZWN0LnkrXCIpXCIpLFxuLy9cbi8vICAgdmFyIHBsb3QgPSBzYWZlU2VsZWN0KGNvbnRhaW5lciwgJ2cnLCBoeXBlbmF0ZShuYW1lc3BhY2UsICdwbG90JykpXG4vLyAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIFwidHJhbnNsYXRlKFwiK3Bsb3RSZWN0LngrXCIsXCIrcGxvdFJlY3QueStcIilcIilcbi8vXG4vLyAgIHZhciB4QXhpcyA9IHNhZmVTZWxlY3QoYXhlcywgJ2cnLCBoeXBlbmF0ZShuYW1lc3BhY2UsICd4LWF4aXMnKSlcbi8vICAgICAuYXR0cigndHJhbnNmb3JtJywgXCJ0cmFuc2xhdGUoXCIreEF4aXNSZWN0LngrXCIsXCIreEF4aXNSZWN0LnkrXCIpXCIpXG4vL1xuLy8gICB2YXIgeUF4aXMgPSBzYWZlU2VsZWN0KGF4ZXMsICdnJywgaHlwZW5hdGUobmFtZXNwYWNlLCAneS1heGlzJykpXG4vLyAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIFwidHJhbnNsYXRlKFwiK3lBeGlzUmVjdC54K1wiLFwiK3lBeGlzUmVjdC55K1wiKVwiKVxuLy9cbi8vICAgcmV0dXJuIHtcbi8vICAgICBzdmc6IHtcbi8vICAgICAgIHNlbGVjdGlvbjogY29udGFpbmVyLFxuLy8gICAgICAgcmVjdDogc3ZnU3BhY2Vcbi8vICAgICB9LFxuLy8gICAgIHBsb3Q6IHtcbi8vICAgICAgIHNlbGVjdGlvbjogcGxvdCxcbi8vICAgICAgIHJlY3Q6IHBsb3RSZWN0XG4vLyAgICAgfSxcbi8vICAgICB4QXhpczoge1xuLy8gICAgICAgc2VsZWN0aW9uOiB4QXhpcyxcbi8vICAgICAgIHJlY3Q6IHhBeGlzUmVjdFxuLy8gICAgIH0sXG4vLyAgICAgeUF4aXM6IHtcbi8vICAgICAgIHNlbGVjdGlvbjogeUF4aXMsXG4vLyAgICAgICByZWN0OiB5QXhpc1JlY3Rcbi8vICAgICB9XG4vLyAgIH1cbi8vXG4vLyAgIC8vIHJldHVybiBbcGxvdCwgeEF4aXMsIHlBeGlzXVxuLy8gfVxuLy9cbi8vXG5cblxuXG5cblxuZXhwb3J0IGZ1bmN0aW9uIHNldHVwU3RhbmRhcmRDaGFydENvbnRhaW5lcnMoXG4gIHNlbGVjdGlvbixcbiAgbmFtZXNwYWNlLFxuICBjb250YWluZXIsXG4gIG1hcmdpbnM9e3RvcDowLjAxLCBib3R0b206MC4wMSwgbGVmdDowLjAxLCByaWdodDowLjAxfSxcbiAgc3ZnPXt3OjAuOCwgaDowLjZ9LCAvLyBwZXJjZW50IG9mIGNvbnRhaW5lciBzcGFjZSBmb3Igc3ZnXG4gIGF4ZXM9e3k6MC4xLCB4OjAuMX0sIC8vIHBlcmNlbnQgb2YgY29udGFpbmVyIHNwYWNlIGZvciBheGVzLFxuICBsZWc9e3g6MCwgbWFyZ2luOjAsIHBvczonbGVmdCd9IC8vIGFic29sdXRlIHdpZHRoIG9mIGxlZ2VuZCBhbmQgc3BhY2Ugb24gZWl0aGVyIHNpemVcbilcbntcbiAgaWYgKGNvbnRhaW5lciA9PSB1bmRlZmluZWQpIHtjb250YWluZXIgPSB7dzp3aW5kb3cuaW5uZXJXaWR0aCwgaDp3aW5kb3cuSGVpZ2h0fX1cbiAgLy8gU1ZHIHdpZHRoIGFuZCBoZWlnaHRcblxuICB2YXIgc3ZnU3BhY2UgPSAge1xuICAgIHc6IGNvbnRhaW5lci53ICogc3ZnLncsXG4gICAgaDogY29udGFpbmVyLmggKiBzdmcuaFxuICB9XG5cbiAgdmFyIG1hcmdQeCA9IHtcbiAgICB0b3A6IG1hcmdpbnMudG9wICogc3ZnU3BhY2UuaCxcbiAgICBib3R0b206IG1hcmdpbnMuYm90dG9tICogc3ZnU3BhY2UuaCxcbiAgICBsZWZ0OiBtYXJnaW5zLmxlZnQgKiBzdmdTcGFjZS53LFxuICAgIHJpZ2h0OiBtYXJnaW5zLnJpZ2h0ICogc3ZnU3BhY2Uud1xuICB9LFxuXG5cblxuICAvLyBTcGFjZSBhZnRlciByZW1vdmluZyBtYXJnaW5zXG4gIGNoYXJ0U3BhY2UgPSB7XG4gICAgdzogc3ZnU3BhY2UudyAtIG1hcmdQeC5sZWZ0IC0gbWFyZ1B4LnJpZ2h0LFxuICAgIGg6IHN2Z1NwYWNlLmggLSBtYXJnUHgudG9wIC0gbWFyZ1B4LmJvdHRvbVxuICB9LFxuXG4gIC8vIG1haW4gZGltZW5zaW9uIG9mIHggYW5kIHkgYXhpZXNcbiAgLy8gZS5nLiBkZWZpbmVzIGhvdyB0YWxsIHggYXhpcyBpcyBhcyBsZW5ndGggaXMgZGV0ZXJtaW5lZCBieSBwbG90UmVjdC53XG4gIGF4ZXNTcGFjZSA9IHtcbiAgICB4OiBjaGFydFNwYWNlLmggKiBheGVzLngsXG4gICAgeTogY2hhcnRTcGFjZS53ICogYXhlcy55XG4gIH0sXG5cbiAgLy8gc3BhY2UgbGVmdCBmb3IgZHJhd2luZyB0aGUgY2hhcnQgcHJvcGVybHkgKGUuZy4gYmFycywgdmlvbGlucywgZXRjKVxuICBkcmF3aW5nU3BhY2UgPSB7XG4gICAgeDogY2hhcnRTcGFjZS53IC0gYXhlc1NwYWNlLnkgLSBsZWcueCAtIDIqbGVnLm1hcmdpbixcbiAgICB5OiBjaGFydFNwYWNlLmggLSBheGVzU3BhY2UueFxuICB9LFxuXG5cbiAgbGVnUmVjdCA9IHtcbiAgICB4OiBsZWcubWFyZ2luICsgbWFyZ1B4LmxlZnQgKyAobGVnLnBvcyA9PSAnbGVmdCcgPyAwIDogZHJhd2luZ1NwYWNlLnggKyBheGVzU3BhY2UueSksXG4gICAgeTogbWFyZ1B4LnRvcCwgLy8gdGhpcyBpcyBzb29tZWhvdyBnZXR0aW5nIGNhbGN1bGF0ZWQgaW5jb3JlY3RseVxuICAgIHc6IGxlZy54LFxuICAgIGg6IGRyYXdpbmdTcGFjZS55XG4gIH0sXG5cbiAgeUF4aXNSZWN0ID0ge1xuICAgIHg6IGF4ZXNTcGFjZS55ICsgbWFyZ1B4LmxlZnQgKyAobGVnLnBvcyA9PSAnbGVmdCcgPyBsZWcueCArIDIqbGVnLm1hcmdpbiA6IDApLFxuICAgIHk6IG1hcmdQeC50b3AsXG4gICAgdzogYXhlc1NwYWNlLnksXG4gICAgaDogZHJhd2luZ1NwYWNlLnlcbiAgfSxcblxuICBwbG90UmVjdCA9IHtcbiAgICB4OiBheGVzU3BhY2UueSArIG1hcmdQeC5sZWZ0ICsgKGxlZy5wb3MgPT0gJ2xlZnQnID8gbGVnLnggKyAyKmxlZy5tYXJnaW4gOiAwKSxcbiAgICB5OiBtYXJnUHgudG9wLFxuICAgIHc6IGRyYXdpbmdTcGFjZS54LFxuICAgIGg6IGRyYXdpbmdTcGFjZS55XG4gIH0sXG5cbiAgeEF4aXNSZWN0ID0ge1xuICAgIHg6IGF4ZXNTcGFjZS55ICsgbWFyZ1B4LmxlZnQgKyAobGVnLnBvcyA9PSAnbGVmdCcgPyBsZWcueCArIDIqbGVnLm1hcmdpbiA6IDApLFxuICAgIHk6IG1hcmdQeC50b3AgKyBkcmF3aW5nU3BhY2UueSxcbiAgICB3OiBkcmF3aW5nU3BhY2UueCxcbiAgICBoOiBheGVzU3BhY2UueFxuICB9XG5cblxuXG4gIGNvbnRhaW5lciA9IGQzc20uc2FmZVNlbGVjdChzZWxlY3Rpb24sICdzdmcnLCBuYW1lc3BhY2UpXG4gICAgLnN0eWxlKCd3aWR0aCcsIHN2Z1NwYWNlLncrJ3B4JylcbiAgICAuc3R5bGUoJ2hlaWdodCcsIHN2Z1NwYWNlLmgrJ3B4JylcblxuICB2YXIgYXhlcyA9IGQzc20uc2FmZVNlbGVjdChjb250YWluZXIsICdnJywgZDNzbS5oeXBlbmF0ZShuYW1lc3BhY2UsICdheGVzJykpXG5cbiAgdmFyIGxlZyA9IGQzc20uc2FmZVNlbGVjdChjb250YWluZXIsICdnJywgZDNzbS5oeXBlbmF0ZShuYW1lc3BhY2UsICdsZWdlbmQnKSlcbiAgLmF0dHIoJ3RyYW5zZm9ybScsIFwidHJhbnNsYXRlKFwiK2xlZ1JlY3QueCtcIixcIitsZWdSZWN0LnkrXCIpXCIpXG5cbiAgdmFyIHBsb3QgPSBkM3NtLnNhZmVTZWxlY3QoY29udGFpbmVyLCAnZycsIGQzc20uaHlwZW5hdGUobmFtZXNwYWNlLCAncGxvdCcpKVxuICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBcInRyYW5zbGF0ZShcIitwbG90UmVjdC54K1wiLFwiK3Bsb3RSZWN0LnkrXCIpXCIpXG5cbiAgdmFyIHhBeGlzID0gZDNzbS5zYWZlU2VsZWN0KGF4ZXMsICdnJywgZDNzbS5oeXBlbmF0ZShuYW1lc3BhY2UsICd4LWF4aXMnKSlcbiAgICAuYXR0cigndHJhbnNmb3JtJywgXCJ0cmFuc2xhdGUoXCIreEF4aXNSZWN0LngrXCIsXCIreEF4aXNSZWN0LnkrXCIpXCIpXG5cbiAgdmFyIHlBeGlzID0gZDNzbS5zYWZlU2VsZWN0KGF4ZXMsICdnJywgZDNzbS5oeXBlbmF0ZShuYW1lc3BhY2UsICd5LWF4aXMnKSlcbiAgICAuYXR0cigndHJhbnNmb3JtJywgXCJ0cmFuc2xhdGUoXCIreUF4aXNSZWN0LngrXCIsXCIreUF4aXNSZWN0LnkrXCIpXCIpXG5cbiAgcmV0dXJuIHtcbiAgICBzdmc6IHtcbiAgICAgIHNlbGVjdGlvbjogY29udGFpbmVyLFxuICAgICAgcmVjdDogc3ZnU3BhY2VcbiAgICB9LFxuICAgIHBsb3Q6IHtcbiAgICAgIHNlbGVjdGlvbjogcGxvdCxcbiAgICAgIHJlY3Q6IHBsb3RSZWN0XG4gICAgfSxcbiAgICB4QXhpczoge1xuICAgICAgc2VsZWN0aW9uOiB4QXhpcyxcbiAgICAgIHJlY3Q6IHhBeGlzUmVjdFxuICAgIH0sXG4gICAgeUF4aXM6IHtcbiAgICAgIHNlbGVjdGlvbjogeUF4aXMsXG4gICAgICByZWN0OiB5QXhpc1JlY3RcbiAgICB9LFxuICAgIGxlZ2VuZDoge1xuICAgICAgc2VsZWN0aW9uOiBsZWcsXG4gICAgICByZWN0OiBsZWdSZWN0XG4gICAgfVxuICB9XG59XG5cblxuXG4vKipcbiogQWRkcyBhIGNsaXAtcGF0aCByZWN0IGFuZCBiaW5kcyBpdCB0byBjb250YWluZXJcbiogQHBhcmFtIHtkMy5zZWxlY3Rpb259IGNvbnRhaW5lciBpbiB3aGljaCB0byBhZGQgdGhlIGNsaXAtcGF0aCBhbmQgdG8gd2hpY2ggdG8gYmluZCB0aGUgY2xpcGluZyBwYXRoIHRvXG4qIEBwYXJhbSB7T2JqZWN0fSByZWN0IHRoZSBjb29yZGluYXRlcyAoeCwgeSwgd2lkdGgsIGhlaWdodCkgb2YgdGhlIGNsaXAtcGF0aFxuKiBAcGFyYW0ge3N0cmluZ30gbmFtZXNwYWNlXG4qIEByZXR1cm5zIHtkMy5zZWxlY3Rpb259IG9mIHRoZSBjbGlwLXBhdGggcmVjdFxuKi9cbmV4cG9ydCBmdW5jdGlvbiBjcFJlY3QoY29udGFpbmVyLCByZWN0LCBuYW1lc3BhY2UpIHtcbiAgdmFyIGRlZnMgPSBzYWZlU2VsZWN0KGNvbnRhaW5lciwgJ2RlZnMnLCBoeXBlbmF0ZShuYW1lc3BhY2UsICdkZWZpbml0aW9ucycpKVxuICB2YXIgY3AgPSBzYWZlU2VsZWN0KGRlZnMsICdjbGlwUGF0aCcsIGh5cGVuYXRlKG5hbWVzcGFjZSwgJ2NsaXAtcGF0aCcpKVxuICAuYXR0cignaWQnLCBoeXBlbmF0ZShuYW1lc3BhY2UsICdjbGlwLXBhdGgnKSlcblxuICB2YXIgY3BSZWN0ID0gc2FmZVNlbGVjdChjcCwgJ3JlY3QnKVxuICAuYXR0cigneCcsIHJlY3QueClcbiAgLmF0dHIoJ3knLCByZWN0LnkpXG4gIC5hdHRyKCd3aWR0aCcsIHJlY3Qud2lkdGgpXG4gIC5hdHRyKCdoZWlnaHQnLCByZWN0LmhlaWdodClcblxuICBkZWZzLnJhaXNlKClcbiAgLy8gc2V0IGNsaXBwaW5nIHBhdGggdG8gY29udGFpbmVyXG4gIGNvbnRhaW5lci5hdHRyKCdjbGlwLXBhdGgnLCAndXJsKCMnKyBoeXBlbmF0ZShuYW1lc3BhY2UsICdjbGlwLXBhdGgnKSsnKScpXG5cbiAgcmV0dXJuIGNwUmVjdFxufVxuXG5cbi8qKlxuKiBBZGRzIGEgYmFja2dyb3VuZCByZWN0IHQgdG8gY29udGFpbmVyXG4qIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBjb250YWluZXIgaW4gd2hpY2ggdG8gYWRkIHRoZSBiYWNrZ3JvdW5kIHJlY3RhbmdsZVxuKiBAcGFyYW0ge09iamVjdH0gcmVjdCB0aGUgY29vcmRpbmF0ZXMgKHgsIHksIHdpZHRoLCBoZWlnaHQpIG9mIHRoZSBiYWNrZ3JvdW5kXG4qIEBwYXJhbSB7c3RyaW5nfSBmaWxsIHRoZSBjb2xvciBvZiB0aGUgYmFja2dyb3VuZFxuKiBAcmV0dXJucyB7ZDMuc2VsZWN0aW9ufSBvZiB0aGUgYmFja2dyb3VuZCBmaWxsXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIGJnUmVjdChjb250YWluZXIsIHJlY3QsIGZpbGwpIHtcbiAgcmV0dXJuIHNhZmVTZWxlY3QoY29udGFpbmVyLCAncmVjdCcsICdiZycpXG4gIC5hdHRyKCd4JywgcmVjdC54KVxuICAuYXR0cigneScsIHJlY3QueSlcbiAgLmF0dHIoJ3dpZHRoJywgcmVjdC53aWR0aClcbiAgLmF0dHIoJ2hlaWdodCcsIHJlY3QuaGVpZ2h0KVxuICAuYXR0cignZmlsbCcsIGZpbGwpXG59XG5cblxuLyoqXG4qIFNldHMgdXAgdGhlIGNvbnRhaW5lciBmb3IgbWFraW5nIGNoYXJ0IGVsZW1lbnRzLiBUaGlzIGluY2x1ZGVzIG1ha2luZ1xuKiBhIGNsaXAtcGF0aCByZWN0IGJvdW5kIHRvIHRoZSBwYXNzZWQgY29udGFpbmVyLCBhIGJhY2tncm91bmQgcmVjdCwgYW5kXG4qIGEgZyBlbGVtZW50IHdpdGggY2xhc3MgPG5hbWVzcGFjZT4tb2JqZWN0LWNvbnRhaW5lci5cbiogQHBhcmFtIHtkMy5zZWxlY3Rpb259IGNvbnRhaW5lciBpbiB3aGljaCB0byBhZGQgdGhlIGNsaXAtcGF0aCBhbmQgYmFja2dyb3VuZFxuKiBAcGFyYW0ge3N0cmluZ30gbmFtZXNwYWNlXG4qIEBwYXJhbSB7T2JqZWN0fSByZWN0IHRoZSBjb29yZGluYXRlcyAoeCwgeSwgd2lkdGgsIGhlaWdodCkgb2YgdGhlIGJhY2tncm91bmQgYW5kIGNsaXAtcGF0aFxuKiBAcGFyYW0ge3N0cmluZ30gZmlsbCB0aGUgY29sb3Igb2YgdGhlIGJhY2tncm91bmRcbiogQHJldHVybnMge2QzLnNlbGVjdGlvbn0gb2YgZy48bmFtZXNwYWNlPi1vYmplY3QtY29udGFpbmVyXG4qXG4qIEBzZWV7QGxpbmsgYmdSZWN0fVxuKiBAc2Vle0BsaW5rIGNwUmVjdH1cbiovXG5leHBvcnQgZnVuY3Rpb24gc2V0dXBDb250YWluZXIoc2VsZWN0aW9uLCBuYW1lc3BhY2UsIHJlY3QsIGZpbGwpIHtcbiAgLy8gdGhlIGNvbnRhaW5lciBmb3IgdGhyZWUgbWFpbiBpdGVtcywgYmcsIGRlZnMsIGFuZCBvYmplY3QtY29udGFpbmVyXG4gIHZhclxuICBjb250YWluZXIgPSBzYWZlU2VsZWN0KHNlbGVjdGlvbiwgJ2cnLCBuYW1lc3BhY2UpLFxuICBiZyA9IGJnUmVjdChjb250YWluZXIsIHJlY3QsIGZpbGwpLFxuICBjcCA9IGNwUmVjdChjb250YWluZXIsIHJlY3QsIG5hbWVzcGFjZSksXG4gIG9iamVjdENvbnRhaW5lciA9IHNhZmVTZWxlY3QoY29udGFpbmVyLCAnZycsIGh5cGVuYXRlKG5hbWVzcGFjZSwgJ29iamVjdC1jb250YWluZXInKSlcbiAgcmV0dXJuIG9iamVjdENvbnRhaW5lclxufVxuXG5cbi8qKlxuKiBkZXRlcm1pbmVzIHRoZSB3aWR0aCBvZiBhbiBvYmplY3QgZm9yIHRoZSBjYWxsaW5nIHBsb3R0aW5nIGZ1bmN0aW9uXG4qIEBwYXJhbSB7bnVtYmVyfSBmcmVlU3BhY2UgaG93IG11Y2ggc3BhY2UgaXMgYXZhbGlibGVcbiogQHBhcmFtIHtudW1iZXJ9IG51bWJlck9mT2JqZWN0cyBob3cgbWFueSBvYmplY3QgZG8gd2UgbmVlZFxuKiBAcGFyYW0ge251bWJlcn0gbWluT2JqZWN0V2lkdGggaG93IHNtYWxsIGFyZSB0aGVzZSBvYmplY3RzIGFsbG93ZWQgdG8gYmVcbiogQHBhcmFtIHtudW1iZXJ9IG1heE9iamVjdFdpZHRoIGhvdyBsYXJnZSBhcmUgdGhlc2Ugb2JqZWN0IGFsbG93ZWQgdG8gYmVcbiogQHBhcmFtIHtudW1iZXJ9IHNpemVPZlNwYWNlciBwZXJjZW50IG9mIGZyZWVTcGFjZSB0aGF0IGEgc2luZ2xlIHNwYWNlciBzaG91bGQgdGFrZSB1cCAobmVlZCBudW1iZXJPZk9iamVjdHMgLSAxIHNwYWNlcnMpXG4qIEBwYXJhbSB7Ym9vbGVhbn0gb3ZlcmZsb3dRIGNhbiB3ZSBnbyBiZXlvbmQgYWxsb3RlZCBzcGFjZVxuKiBAcmV0dXJucyB7bnVtYmVyfSBob3cgbGFyZ2Ugb2JqZWN0IHNob3VsZCBiZVxuKiBmdW5jdGlvbiB0cmllcyB0byBrZWVwIG9iamVjdCB3aXRoaW4gbWluIC8gbWF4IHdpZHRoLCBidXQgd2lsIGRlZmF1bHQgdG9cbiogNWUtMTAgKHNtYWxsZXN0IGNvbnNpc3Rlbmx5IHZpc2libGUgYnkgc3ZnIHNpemUgb2YgZWxlbWVudCkgaWYgb3ZlcmZsb3dRIGlzIGZhbHNlXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3QoZnJlZVNwYWNlLCBudW1iZXJPZk9iamVjdHMsIG1pbk9iamVjdFdpZHRoLCBtYXhPYmplY3RXaWR0aCwgc2l6ZU9mU3BhY2VyLCBvdmVyZmxvd1EpIHtcbiAgdmFyIHNpemVPZlNwYWNlciA9XG4gIHNpemVPZlNwYWNlciA9PSAwIHx8IHNpemVPZlNwYWNlciA+IDFcbiAgPyBzaXplT2ZTcGFjZXJcbiAgOiBmcmVlU3BhY2UgKiBzaXplT2ZTcGFjZXJcblxuICB2YXIgbnVtYmVyT2ZTcGFjZXJzID0gbnVtYmVyT2ZPYmplY3RzIC0gMVxuICB2YXIgc3BhY2VUYWtlbkJ5U3BhY2VycyA9IG51bWJlck9mU3BhY2VycyAqIHNpemVPZlNwYWNlclxuICB2YXIgcmVtYWluaW5nU3BhY2UgPSBmcmVlU3BhY2UgLSBzcGFjZVRha2VuQnlTcGFjZXJzXG4gIHJlbWFpbmluZ1NwYWNlID0gcmVtYWluaW5nU3BhY2UgPCAwID8gMCA6IHJlbWFpbmluZ1NwYWNlXG4gIHZhciBvYmplY3RXaWR0aCA9IHJlbWFpbmluZ1NwYWNlIC8gbnVtYmVyT2ZPYmplY3RzXG5cbiAgaWYgKCBvdmVyZmxvd1EgJiYgbWluT2JqZWN0V2lkdGggIT0gdW5kZWZpbmVkICYmIG9iamVjdFdpZHRoIDwgbWluT2JqZWN0V2lkdGggKSB7IG9iamVjdFdpZHRoID0gbWluT2JqZWN0V2lkdGggfVxuICAvLyBpZiAoIG1heE9iamVjdFdpZHRoICE9IHVuZGVmaW5lZCAmJiBvYmplY3RXaWR0aCA+IG1heE9iamVjdFdpZHRoICkgeyBvYmplY3RXaWR0aCA9IG1heE9iamVjdFdpZHRoIH1cbiAgaWYgKCBvdmVyZmxvd1EgJiYgbWF4T2JqZWN0V2lkdGggIT0gdW5kZWZpbmVkICYmIG9iamVjdFdpZHRoIDwgbWF4T2JqZWN0V2lkdGggKSB7IG9iamVjdFdpZHRoID0gbWF4T2JqZWN0V2lkdGggfVxuICByZXR1cm4gTWF0aC5tYXgob2JqZWN0V2lkdGgsIDVlLTEwKVxufVxuXG4vKipcbiogQHBhcmFtIHtBcnJheVtdfSBkYXRhIGxpc3QgZGF0YSAoY2FuIGJlIG5lc3RlZCkuIElmIG5lc3RlZCB3aWxsIGNyZWF0ZSBtb3JlIGNvbXBsZXggc3BhY2VyIHNpemVcbiogQHBhcmFtIHtudW1iZXJ9IGZyZWVTcGFjZSBob3cgbXVjaCBzcGFjZSBpcyBhdmFsaWJsZVxuKiBAcGFyYW0ge251bWJlcn0gb2JqZWN0V2lkdGggQHNlZXtAbGluayBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0fVxuKiBAcGFyYW0ge251bWJlcn0gbnVtYmVyT2ZPYmplY3RzIGhvdyBtYW55IG9iamVjdCBkbyB3ZSBuZWVkXG4qIEBwYXJhbSB7bnVtYmVyfSBiYXNlU3BhY2VyU2l6ZSBwZXJjZW50IG9mIGZyZWVTcGFjZSB0aGF0IGEgc2luZ2xlIHNwYWNlciBzaG91bGQgdGFrZSB1cCAobmVlZCBudW1iZXJPZk9iamVjdHMgLSAxIHNwYWNlcnMpXG4qIEBwYXJhbSB7Ym9vbGVhbn0gb3ZlcmZsb3dRIGNhbiB3ZSBnbyBiZXlvbmQgYWxsb3RlZCBzcGFjZVxuKiBAcmV0dXJucyB7bnVtYmVyfSByZXR1cm5zIHNpemUgdGhhdCBzcGFjZXIgc2hvdWxkIGJlIGF0IGxldmVsPTBcbiovXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlV2lkdGhPZlNwYWNlcihkYXRhLCBmcmVlU3BhY2UsIG9iamVjdFdpZHRoLCBudW1iZXJPZk9iamVjdHMsIGJhc2VTcGFjZXJTaXplLCBvdmVyZmxvd1EpIHtcbiAgaWYgKG92ZXJmbG93USkge1xuICAgIC8vIHZhciBsaW1pdGVkTnVtYmVyT2ZPYmplY3RzID0gbnVtYmVyT2ZPYmplY3RzID4gNiA/IDYgOiBudW1iZXJPZk9iamVjdHNcbiAgICAvLyB2YXIgc3BhY2VMZWZ0ID0gZnJlZVNwYWNlIC0gbGltaXRlZE51bWJlck9mT2JqZWN0cyAqIG9iamVjdFdpZHRoXG4gICAgLy8gcmV0dXJuIHNwYWNlTGVmdCAvIChsaW1pdGVkTnVtYmVyT2ZPYmplY3RzIC0gMSlcbiAgICByZXR1cm4gZnJlZVNwYWNlICogYmFzZVNwYWNlclNpemVcbiAgfVxuICB2YXIgc3BhY2Vyc0F0RWFjaExldmVsID0gc3BhY2Vyc05lZWRlZEF0RWFjaExldmVsKGRhdGEpXG4gIHZhciB0b3RhbFNwYWNlclBlcmNlbnQgPSB0b3RhbChzcGFjZXJzQXRFYWNoTGV2ZWwubWFwKGZ1bmN0aW9uKGUsIGkpIHtyZXR1cm4gZSAqIDEgLyAoaSsxKX0pKVxuICB2YXIgYmFzZVNwYWNlclNpemUgPSAoZnJlZVNwYWNlIC0gKG9iamVjdFdpZHRoICogbnVtYmVyT2ZPYmplY3RzKSkgLyB0b3RhbFNwYWNlclBlcmNlbnRcbiAgLy8gY29uc29sZS5sb2coZnJlZVNwYWNlLCBvYmplY3RXaWR0aCwgbnVtYmVyT2ZPYmplY3RzLCB0b3RhbFNwYWNlclBlcmNlbnQpXG4gIC8vIGNvbnNvbGUubG9nKHRvdGFsU3BhY2VyUGVyY2VudCwgYmFzZVNwYWNlclNpemUsIHRvdGFsU3BhY2VyUGVyY2VudCAqIGJhc2VTcGFjZXJTaXplKVxuICByZXR1cm4gaXNOYU4oYmFzZVNwYWNlclNpemUpID8gMCA6IGJhc2VTcGFjZXJTaXplXG59XG5cblxuLyoqXG4qIENhbGN1bGF0ZXMgbnVtYmVyIG9mIHNwYWNlcnMgbmVlZGVkIHRvIHNlcGVyYXRlIGVsZW1lbnRzIGF0IGVhY2ggbGV2ZWwuXG4qIEBwYXJhbSB7QXJyYXlbXX0gYXJyYXkgbGlzdCBkYXRhIChjYW4gYmUgbmVzdGVkKS4gSWYgbmVzdGVkIHdpbGwgY3JlYXRlIG1vcmUgY29tcGxleCBzcGFjZXIgc2l6ZVxuKiBAcGFyYW0ge251bWJlcn0gW2xldmVsPTBdIGN1cnJlbnQgbGV2ZWwsIHVzZWQgaW4gcmVjdXNyaW9uXG4qIEBwYXJhbSB7QXJyYXl9IFtsZXZlbERhdGE9W11dIGhvdyBtYW55IHNwYWNlcnMgbmVlZGVkIGF0IGEgZ2l2ZW4gbGV2ZWxcbiogQHJldHVybnMge0FycmF5fSBsZXZlbERhdGFcbipcbiogQGV4YW1wbGVcbiogYXJyYXkgPSBbWzEsMl0sIFszLDRdXVxuKiAvLyByZXR1cm5zIFsxLCAyXVxuKiBhcyBhdCBsZXZlbD0wIHRoZSBvbmx5IHNwYWNlciBuZWVkZWQgaXMgYmV0d2VlbiBbMSwyXSBhbmQgWzMsNF1cbiogYW5kIGF0IGxldmVsPTEgdGhlIG9ubHkgdHdvIHNwYWNlcnMgbmVlZGVkIGlzIGJldHdlZW4gMSBhbmQgMiBhcyB3ZWxsIGFzXG4qIDMgYW5kIDQgc2luY2UgdGhlIHNwYWNlciBiZXR3ZWVuIDIgYW5kIDMgaXMgaGFuZGxlZCBhdCBsZXZlbD0wXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIHNwYWNlcnNOZWVkZWRBdEVhY2hMZXZlbCAoYXJyYXksIGxldmVsLCBsZXZlbERhdGEgKSB7XG4gIGlmICggbGV2ZWwgPT0gdW5kZWZpbmVkICkgeyBsZXZlbCA9IDA7ICB9IGVsc2UgeyBsZXZlbCArPSAxIH1cbiAgaWYgKCBsZXZlbERhdGEgPT0gdW5kZWZpbmVkICkgeyBsZXZlbERhdGEgPSBbXTsgfVxuICBpZiAoIGxldmVsID49IGxldmVsRGF0YS5sZW5ndGggKSB7IGxldmVsRGF0YS5wdXNoKGFycmF5Lmxlbmd0aCAtIDEpIH1cbiAgZWxzZSB7IGxldmVsRGF0YVtsZXZlbF0gKz0gYXJyYXkubGVuZ3RoIC0gMSB9XG4gIGFycmF5Lm1hcChmdW5jdGlvbihlLCBpKSB7IGlmIChBcnJheS5pc0FycmF5KGUpKSB7IHNwYWNlcnNOZWVkZWRBdEVhY2hMZXZlbChlLCBsZXZlbCwgbGV2ZWxEYXRhKSB9IH0gKVxuICByZXR1cm4gbGV2ZWxEYXRhXG59XG5cblxuXG5cbi8qKlxuKiBEcmF3cyBhIHdoaXNrZXIgZm9yIEBzZWV7QGxpbmsgYm94d2hpc2tlcn1cbiogQHBhcmFtIHtib29sZWFufSBkaXIgZGlyZWN0aW9uIHRvIGRyYXcgd2hpc2tlciwgc2hvdWxkIGJlIGVpdGhlciB0cnVlICh1cCwgdG9wKSBvciBmYWxzZSAoZG93biBvciBib3R0b20pXG4qIEBwYXJhbSB7bnVtYmVyfSB4IHN0YXJ0aW5nIHggY29vcmRpbmF0ZSBpbiB3aGljaCB0byBkcmF3IHdoaXNrZXJcbiogQHBhcmFtIHtudW1iZXJ9IHkgc3RhcnRpbmcgeSBjb29yZGluYXRlIGluIHdoaWNoIHRvIGRyYXcgd2hpc2tlclxuKiBAcGFyYW0ge251bWJlcn0gdyB3aWR0aCBvZiBzcGFjZSBpbiB3aGljaCB0byBkcmF3IHdoaXNrZXJcbiogQHBhcmFtIHtudW1iZXJ9IGggaGVpZ2h0IG9mIHNwYWNlIGluIHdoaWNoIHRvIGRyYXcgd2hpc2tlclxuKiBAcGFyYW0ge251bWJlcn0gcGVyIHBlcmNlbnRhZ2Ugb2YgdyBvciBoIChkZXBlbmRzIG9uIG8pIHRvIG1ha2Ugd2hpc2tlclxuKiBAcGFyYW0ge2Jvb2xlYW59IG8gb3JpZW50YXRpb24sIHRydWUgaXMgaG9yaXpvbnRhbCBhbmQgZmFsc2UgaXMgdmVydGljYWxcbiogQHJldHVybnMge3N0cmluZ30gcmVwcmVzZW50aW5nIHRoZSBzdmcgcGF0aCAoaS5lLiB0aGUgZCBhdHRyaWJ1dGUgZm9yIGEgcGF0aCB0YWcpXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIHdoaXNrZXJQYXRoKGRpciwgeCwgeSwgdywgaCwgcGVyLCBvKSB7XG4gIC8vIGQgPSBkaXJlY3Rpb24gKHRydWUgaXMgdXApLCBwID0gcGVyY2VudCB3aWR0aFxuICBpZiAoZGlyID09ICd1cCcgfHwgZGlyID09ICd0b3AnIHx8IGRpciA9PSB0cnVlKSB7ZGlyID0gdHJ1ZX1cbiAgaWYgKGRpciA9PSAnZG93bicgfHwgZGlyID09ICdib3R0b20nIHx8IGRpciA9PSBmYWxzZSkge2RpciA9IGZhbHNlfVxuICBvID0gbyA9PSB1bmRlZmluZWQgPyAnaG9yaXpvbnRhbCcgOiBvXG4gIHBlciA9IHBlciA9PSB1bmRlZmluZWQgPyAxIDogcGVyXG4gIGlmIChvICE9IFwiaG9yaXpvbnRhbFwiKSB7XG4gICAgdmFyIGhoID0gaCAqIHBlciAsXG4gICAgdyA9IGRpciA/IHcgOiAtdyAsXG4gICAgYSA9IGRpciA/IHggKyB3IDogeCAsXG4gICAgYiA9IGRpciA/IHggOiB4ICsgdyAsXG4gICAgYyA9IGRpciA/IGEgOiBiXG4gICAgcCA9IFwiTSBcIiArIGEgKyAnICcgKyAoICAgICBoIC8gMiAgICAgICkgKyAnICdcbiAgICAgICsgJ0wgJyArIGIgKyAnICcgKyAoICAgICBoIC8gMiAgICAgICkgKyAnICdcbiAgICAgICsgJ00gJyArIGMgKyAnICcgKyAoIGggLyAyIC0gaGggLyAyICkgKyAnICdcbiAgICAgICsgJ0wgJyArIGMgKyAnICcgKyAoIGggLyAyICsgaGggLyAyICkgKyAnICdcblxuICAgIHJldHVybiBwXG4gIH1cbiAgdmFyIHd3ID0gdyAqIHBlcixcbiAgYSA9IGRpciA/IHkgKyBoIDogeSAgLFxuICBiID0gZGlyID8geSA6IHkgKyBoICAsXG4gIHAgPSBcIk0gXCIgKyAoICB3IC8gMiAgKSArICcgJyArIGEgKyAnICcgLy8gc3RyYWlnaHQgbGluZSBwYXJ0XG4gICAgKyAnTCAnICsgKCAgdyAvIDIgICkgKyAnICcgKyBiICsgJyAnIC8vIHN0cmFpZ2h0IGxpbmUgcGFydFxuICAgICsgJ2ggJyArICggLXd3IC8gMiApICsgJyAnICsgMCArICcgJyAvLyBob3Jpem9udGFsIGxpbmUgcGFydFxuICAgICsgJ2ggJyArICggICAgd3cgICApICsgJyAnICsgMCArICcgJ1xuICByZXR1cm4gcFxufVxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5leHBvcnQgZnVuY3Rpb24gcmVzaXplRGVib3VuY2UoZiwgd2FpdCkge1xuICB2YXIgcmVzaXplID0gZGVib3VuY2UoZnVuY3Rpb24oKXtmKCl9LHdhaXQpXG4gIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCByZXNpemUpXG59XG5cblxuXG5mdW5jdGlvbiBkZWJvdW5jZShmdW5jLCB3YWl0LCBpbW1lZGlhdGUpIHtcbiAgdmFyIHRpbWVvdXQ7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgY29udGV4dCA9IHRoaXMsIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIHZhciBsYXRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGltZW91dCA9IG51bGw7XG4gICAgICAgICAgICBpZiAoIWltbWVkaWF0ZSkgZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNhbGxOb3cgPSBpbW1lZGlhdGUgJiYgIXRpbWVvdXQ7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQpO1xuICAgICAgICBpZiAoY2FsbE5vdykgZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICB9O1xufVxuIiwiaW1wb3J0IHtsb2csIHdhcm4sIGVycm9yLCBpbmZvfSBmcm9tICcuL3V0aWxzJztcbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU1BBQ0VHUk9VUElORyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4vKipcbiAqIFByb2R1Y2VzIGEgZnVuY3Rpb24gZm9yIHNwYWNpbmcgb2JqZWN0cyBieSBhbiBhcmJpdHJhcmx5IGNvbXBsZXggZ3JvdXBpbmdcbiAqIEByZXR1cm5zIHtyZWN1cnNpdmVseVBvc2l0aW9ufSB0aGUgZnVuY3Rpb24gZm9yIG1vdmluZyB0aGUgb2JqZWN0c1xuICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIjcmVjdXJzaXZlbHlQb3NpdGlvbn0pXG4gKiBAbmFtZXNwYWNlIGdyb3VwaW5nU3BhY2VyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBncm91cGluZ1NwYWNlcigpIHtcbiAgdmFyXG4gIC8qQHZhciB7Ym9vbGVhbn0gaG9yaXpvbnRhbFEgQGRlZmF1bHQqL1xuXG4gIC8qKlxuICAqIFdoZXRoZXIgb3Igbm90IHRvIHNwYWNlIG9iamVjdHMgaG9yaXpvbnRhbGx5IG9yIHZlcnRpY2FsbHkuXG4gICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIuaG9yaXpvbnRhbFF9KVxuICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2hvcml6b250YWxRPXRydWVdXG4gICogQG1lbWJlcm9mIGdyb3VwaW5nU3BhY2VyI1xuICAqIEBpbnN0YW5jZVxuICAqL1xuICBob3Jpem9udGFsUSA9IHRydWUsXG4gIC8qKlxuICAqIFRoZSBzY2FsZSB0byB1c2UgdG8gcG9zaXRpb24gZWxlbWVudHMgaWYge0BsaW5rIGdyb3VwaW5nU3BhY2VyI21vdmVieX09XCJzdHJpbmdcIlxuICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyLnNjYWxlfSlcbiAgKiBAcGFyYW0ge2QzLnNjYWxlfSBbc2NhbGU9ZDMuc2NhbGVMaW5lYXIoKV1cbiAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXIjXG4gICogQGluc3RhbmNlXG4gICovXG4gIHNjYWxlID0gZDMuc2NhbGVMaW5lYXIoKSxcbiAgLyoqXG4gICogSG93IGVsZW1lbnRzIGluIHRoZSBjb21wbGV4IGdyb3VwaW5nIHNob3VsZCBiZSBtb3ZlZCBvdmVyIGJ5LlxuICAqIEJ5IGRlZmF1bHQsIG1vdmVieT1cImNhdGVnb3J5XCIsIHdoaWNoIG1vdmVzIG9iamVjdHMgYnkgdGhlIGNvbXBsZXggZ3JvdXBpbmdcbiAgKiBCdXQgb2JqZWN0cyBjYW4gYWxzbyBiZSBtb3ZlZCBvdmVyIGJ5IHNjYWxlLlxuICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyLm1vdmVieX0pXG4gICogQHBhcmFtIHtzdHJpbmd9IFttb3ZlYnk9XCJjYXRlZ29yeVwiXVxuICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlciNcbiAgKiBAaW5zdGFuY2VcbiAgKi9cbiAgbW92ZWJ5ID0gJ2NhdGVnb3J5JyxcbiAgLyoqXG4gICogSG93IG1hbnkgb2JqZWN0cyBhcmUgdGhlcmUgaW4gdG90YWxcbiAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlci5udW1iZXJPZk9iamVjdHN9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbbnVtYmVyT2ZPYmplY3RzPW5vbmVdXG4gICogQG1lbWJlcm9mIGdyb3VwaW5nU3BhY2VyI1xuICAqIEBpbnN0YW5jZVxuICAqL1xuICBudW1iZXJPZk9iamVjdHMsXG4gIC8qKlxuICAqIFRoZSBjbGFzcyBnaXZlbiB0byBhbiBuZXN0ZWQgPGc+IHRhZyB3aG9zZSBwYXJlbnQocykgaGF2ZSB0aGUgY29ycmVjdCB0cmFuc2l0aW9uXG4gICogcHJvcGVydGllc1xuICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyLm51bWJlck9mT2JqZWN0c30pXG4gICogQHBhcmFtIHtzdHJpbmd9IFtudW1iZXJPZk9iamVjdHM9J2Qzc20tZ3JvdXBwZWQtaXRlbSddXG4gICogQG1lbWJlcm9mIGdyb3VwaW5nU3BhY2VyI1xuICAqIEBpbnN0YW5jZVxuICAqL1xuICBvYmplY3RDbGFzcyA9ICdkM3NtLWdyb3VwcGVkLWl0ZW0nLFxuICAvKipcbiAgKiBUaGUgc2l6ZSBvZiB0aGUgb2JqZWN0cyBiZWluZyBwb3NpdGlvbmVkXG4gICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIub2JqZWN0U2l6ZX0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtvYmplY3RTaXplPW5vbmVdXG4gICogQG1lbWJlcm9mIGdyb3VwaW5nU3BhY2VyI1xuICAqIEBpbnN0YW5jZVxuICAqL1xuICBvYmplY3RTaXplLFxuICAvKipcbiAgKiBUaGUgc2l6ZSBvZiB0aGUgdW4tbmVzdGVkIHNwYWNlciBiZXR3ZWVuIG9iamVjdHNcbiAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlci5zcGFjZXJTaXplfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlclNpemU9bm9uZV1cbiAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXIjXG4gICogQGluc3RhbmNlXG4gICovXG4gIHNwYWNlclNpemUsXG4gIC8qKlxuICAqIFRoZSBkdXJhdGlvbiBvZiB0cmFuc2l0aW9ucyBpbiBtc1xuICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyLnRyYW5zaXRpb25EdXJhdGlvbn0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFt0cmFuc2l0aW9uRHVyYXRpb249MTAwMF1cbiAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXIjXG4gICogQGluc3RhbmNlXG4gICovXG4gIHRyYW5zaXRpb25EdXJhdGlvbiA9IDEwMDAsXG4gIC8qKlxuICAqIFRoZSBlYXNlIGZ1bmN0aW9uIGZvciB0aGUgdHJhbnNpdGlvbnNcbiAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlci5lYXNlRnVuY30pXG4gICogQHBhcmFtIHtkMy5lYXNlfSBbZWFzZUZ1bmM9ZDMuZWFzZVNpbl1cbiAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXIjXG4gICogQGluc3RhbmNlXG4gICovXG4gIGVhc2VGdW5jID0gZDMuZWFzZVNpbixcbiAgLyoqXG4gICogVGhlIG5hbWVzcGFjZSBmb3IgdGhlIG9iamVjdHMgYmVpbmcgbW92ZWRcbiAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlci5uYW1lc3BhY2V9KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbbmFtZXNwYWNlPSdzcGFjZXInXVxuICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlciNcbiAgKiBAaW5zdGFuY2VcbiAgKi9cbiAgbmFtZXNwYWNlID0gJ3NwYWNlcicsXG4gIC8qKlxuICAqIFRoZSBhbmltYXRpb24gZm9yIG5ldyBvYmplY3RzIGJlaW5nIGFkZGVkXG4gICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIuZW50ZXJGdW5jdGlvbn0pXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gZW50ZXJGdW5jdGlvblxuICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlciNcbiAgKiBAaW5zdGFuY2VcbiAgKiBAZXhhbXBsZVxuICAqIC8vIGJ5IGRlZmF1bHRcbiAgKiBmdW5jdGlvbihuZXdPYmplY3RTZWxlY3Rpb24pIHtcbiAgKiAgbmV3T2JqZWN0U2VsZWN0aW9uLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQsIGkpe1xuICAqICAgIHZhclxuICAqICAgIHggPSBob3Jpem9udGFsUSA/IG9iamVjdFNpemUgKiBudW1iZXJPZk9iamVjdHMgKyBzcGFjZXJTaXplICogKG51bWJlck9mT2JqZWN0cyAtIDEpIDogMCxcbiAgKiAgICB5ID0gIWhvcml6b250YWxRID8gb2JqZWN0U2l6ZSAqIG51bWJlck9mT2JqZWN0cyArIHNwYWNlclNpemUgKiAobnVtYmVyT2ZPYmplY3RzIC0gMSkgOiAwLFxuICAqICAgIHQgPSAndHJhbnNsYXRlKCcreCsnLCcreSsnKSdcbiAgKiAgICByZXR1cm4gdFxuICAqICB9KVxuICAqIH1cbiAgKi9cbiAgZW50ZXJGdW5jdGlvbiA9IGZ1bmN0aW9uKGN1cikge1xuICAgIGN1ci5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhclxuICAgICAgLy8geCA9IGhvcml6b250YWxRID8gb2JqZWN0U2l6ZSAqIG51bWJlck9mT2JqZWN0cyArIHNwYWNlclNpemUgKiAobnVtYmVyT2ZPYmplY3RzIC0gMSkgOiAwLFxuICAgICAgLy8geSA9ICFob3Jpem9udGFsUSA/IG9iamVjdFNpemUgKiBudW1iZXJPZk9iamVjdHMgKyBzcGFjZXJTaXplICogKG51bWJlck9mT2JqZWN0cyAtIDEpIDogMCxcbiAgICAgIHggPSBob3Jpem9udGFsUSA/IHdpbmRvdy5vdXRlcldpZHRoIDogMCxcbiAgICAgIHkgPSAhaG9yaXpvbnRhbFEgPyB3aW5kb3cub3V0ZXJXaWR0aCA6IDAsXG4gICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICAgICAvLyBpZih5ID09IHVuZGVmaW5lZCkge2NvbnNvbGUubG9nKGN1ci5ub2RlKCksIHksIGQpfVxuICAgICAgcmV0dXJuIHRcbiAgICB9KVxuICB9LFxuICAvKipcbiAgKiBUaGUgYW5pbWF0aW9uIGZvciBvbGQgb2JqZWN0cyBiZWluZyByZW1vdmVkXG4gICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIuZXhpdEZ1bmN0aW9ufSlcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBleGl0RnVuY3Rpb25cbiAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXIjXG4gICogQGluc3RhbmNlXG4gICogQGV4YW1wbGVcbiAgKiAvLyBieSBkZWZhdWx0XG4gICogb2xkT2JqZWN0U2VsZWN0aW9uLnRyYW5zaXRpb24oKS5kdXJhdGlvbih0cmFuc2l0aW9uRHVyYXRpb24pLmVhc2UoZWFzZUZ1bmMpXG4gICogLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQsIGkpe1xuICAqICAgICB2YXJcbiAgKiAgIHggPSBob3Jpem9udGFsUSA/IG9iamVjdFNpemUgKiBudW1iZXJPZk9iamVjdHMgKyBzcGFjZXJTaXplICogKG51bWJlck9mT2JqZWN0cyAtIDEpIDogMCxcbiAgKiAgIHkgPSAhaG9yaXpvbnRhbFEgPyBvYmplY3RTaXplICogbnVtYmVyT2ZPYmplY3RzICsgc3BhY2VyU2l6ZSAqIChudW1iZXJPZk9iamVjdHMgLSAxKSA6IDAsXG4gICogICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICogICByZXR1cm4gdFxuICAqIH0pLnJlbW92ZSgpXG4gICovXG4gIGV4aXRGdW5jdGlvbiA9IGZ1bmN0aW9uKGN1cil7XG4gICAgbG9nKFwiZ3JvdXBpbmdTcGFjZXJcIiwgXCJleGl0aW5nIHdpdGhcIiwge2N1cnJlbnQ6IGN1ciwgY3VycmVudE5vZGU6IGN1ci5ub2RlKCl9KVxuICAgIGN1ci5zZWxlY3RBbGwoJ2cnKS5jbGFzc2VkKCd0by1yZW1vdmUnLCB0cnVlKVxuXG4gICAgY3VyLnRyYW5zaXRpb24oKS5kdXJhdGlvbih0cmFuc2l0aW9uRHVyYXRpb24qMC45KS5lYXNlKGVhc2VGdW5jKVxuICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhclxuICAgICAgLy8geCA9IGhvcml6b250YWxRID8gb2JqZWN0U2l6ZSAqIG51bWJlck9mT2JqZWN0cyArIHNwYWNlclNpemUgKiAobnVtYmVyT2ZPYmplY3RzIC0gMSkgOiAwLFxuICAgICAgLy8geSA9ICFob3Jpem9udGFsUSA/IG9iamVjdFNpemUgKiBudW1iZXJPZk9iamVjdHMgKyBzcGFjZXJTaXplICogKG51bWJlck9mT2JqZWN0cyAtIDEpIDogMCxcbiAgICAgIHggPSBob3Jpem9udGFsUSA/IHdpbmRvdy5vdXRlcldpZHRoIDogMCxcbiAgICAgIHkgPSAhaG9yaXpvbnRhbFEgPyB3aW5kb3cub3V0ZXJXaWR0aCA6IDAsXG4gICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICAgICAvLyBpZih5ID09IHVuZGVmaW5lZCkge2NvbnNvbGUubG9nKGN1ci5ub2RlKCksIHksIGQpfVxuICAgICAgcmV0dXJuIHRcbiAgICB9KS5yZW1vdmUoKVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIGhvcml6b250YWxRICh3aGV0aGVyIG9yIG5vdCB0byBzcGFjZSBvYmplY3RzIGhvcml6b250YWxseSBvciB2ZXJ0aWNhbGx5KS5cbiAgICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIjaG9yaXpvbnRhbFF9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXJcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcmVjdXJzaXZlbHlQb3NpdGlvbi5ob3Jpem9udGFsUSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaG9yaXpvbnRhbFEgPSBfLCByZWN1cnNpdmVseVBvc2l0aW9uKSA6IGhvcml6b250YWxRIH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzY2FsZSB0byB1c2UgdG8gcG9zaXRpb24gZWxlbWVudHMgaWYge0BsaW5rIGdyb3VwaW5nU3BhY2VyI21vdmVieX09XCJzdHJpbmdcIlxuICAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlciNzY2FsZX0pXG4gICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtncm91cGluZ1NwYWNlciB8IGQzLnNjYWxlfVxuICAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXJcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcmVjdXJzaXZlbHlQb3NpdGlvbi5zY2FsZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGUgPSBfLCByZWN1cnNpdmVseVBvc2l0aW9uKSA6IHNjYWxlIH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIG1vdmVieSAod2hldGhlciBvciBub3QgdG8gbW92ZSBieSBzY2FsZSBvciBieSBncm91cGluZykuXG4gICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyI21vdmVieX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Z3JvdXBpbmdTcGFjZXIgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlclxuICAgKiBAc3RhdGljXG4gICAqL1xuICByZWN1cnNpdmVseVBvc2l0aW9uLm1vdmVieSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobW92ZWJ5ID0gXywgcmVjdXJzaXZlbHlQb3NpdGlvbikgOiBtb3ZlYnkgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgbnVtYmVyT2ZPYmplY3RzLlxuICAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlciNudW1iZXJPZk9iamVjdHN9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXJcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcmVjdXJzaXZlbHlQb3NpdGlvbi5udW1iZXJPZk9iamVjdHMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG51bWJlck9mT2JqZWN0cyA9IF8sIHJlY3Vyc2l2ZWx5UG9zaXRpb24pIDogbnVtYmVyT2ZPYmplY3RzIH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RDbGFzcyAod2lsbCBiZSBhcHBsaWVkIHRvIDxnPiBlbGVtZW50cykuXG4gICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyI29iamVjdENsYXNzfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtncm91cGluZ1NwYWNlciB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGdyb3VwaW5nU3BhY2VyXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIHJlY3Vyc2l2ZWx5UG9zaXRpb24ub2JqZWN0Q2xhc3MgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdENsYXNzID0gXywgcmVjdXJzaXZlbHlQb3NpdGlvbikgOiBvYmplY3RDbGFzcyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgb2JqZWN0U2l6ZS5cbiAgICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIjb2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Z3JvdXBpbmdTcGFjZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlclxuICAgKiBAc3RhdGljXG4gICAqL1xuICByZWN1cnNpdmVseVBvc2l0aW9uLm9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNpemUgPSBfLCByZWN1cnNpdmVseVBvc2l0aW9uKSA6IG9iamVjdFNpemUgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHNwYWNlclNpemUuXG4gICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyI3NwYWNlclNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXJcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcmVjdXJzaXZlbHlQb3NpdGlvbi5zcGFjZXJTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZXJTaXplID0gXywgcmVjdXJzaXZlbHlQb3NpdGlvbikgOiBzcGFjZXJTaXplIH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB0cmFuc2l0aW9uRHVyYXRpb24uXG4gICAqIChzZWUge0BsaW5rIGdyb3VwaW5nU3BhY2VyI3RyYW5zaXRpb25EdXJhdGlvbn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Z3JvdXBpbmdTcGFjZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlclxuICAgKiBAc3RhdGljXG4gICAqL1xuICByZWN1cnNpdmVseVBvc2l0aW9uLnRyYW5zaXRpb25EdXJhdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodHJhbnNpdGlvbkR1cmF0aW9uID0gXywgcmVjdXJzaXZlbHlQb3NpdGlvbikgOiB0cmFuc2l0aW9uRHVyYXRpb24gfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGVhc2VGdW5jLlxuICAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlciNlYXNlRnVuY30pXG4gICAqIEBwYXJhbSB7ZDMuZWFzZX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgZDMuZWFzZX1cbiAgICogQG1lbWJlcm9mIGdyb3VwaW5nU3BhY2VyXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIHJlY3Vyc2l2ZWx5UG9zaXRpb24uZWFzZUZ1bmMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGVhc2VGdW5jID0gXywgcmVjdXJzaXZlbHlQb3NpdGlvbikgOiBlYXNlRnVuYyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbmFtZXNwYWNlLlxuICAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlciNuYW1lc3BhY2V9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXJcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcmVjdXJzaXZlbHlQb3NpdGlvbi5uYW1lc3BhY2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG5hbWVzcGFjZSA9IF8sIHJlY3Vyc2l2ZWx5UG9zaXRpb24pIDogbmFtZXNwYWNlIH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBlbnRlckZ1bmN0aW9uLlxuICAgKiAoc2VlIHtAbGluayBncm91cGluZ1NwYWNlciNlbnRlckZ1bmN0aW9ufSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlclxuICAgKiBAc3RhdGljXG4gICAqL1xuICByZWN1cnNpdmVseVBvc2l0aW9uLmVudGVyRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGVudGVyRnVuY3Rpb24gPSBfLCByZWN1cnNpdmVseVBvc2l0aW9uKSA6IGVudGVyRnVuY3Rpb24gfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGV4aXRGdW5jdGlvbi5cbiAgICogKHNlZSB7QGxpbmsgZ3JvdXBpbmdTcGFjZXIjZXhpdEZ1bmN0aW9ufSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2dyb3VwaW5nU3BhY2VyIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBncm91cGluZ1NwYWNlclxuICAgKiBAc3RhdGljXG4gICAqL1xuICByZWN1cnNpdmVseVBvc2l0aW9uLmV4aXRGdW5jdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZXhpdEZ1bmN0aW9uID0gXywgcmVjdXJzaXZlbHlQb3NpdGlvbikgOiBleGl0RnVuY3Rpb24gfVxuXG5cbiAgLyoqXG4gICAqIHJlY3Vyc2l2ZWx5IHBvc2l0aW9uIHRoZSBvYmplY3RzIGluc2lkZSBvZiB0aGUgc2VsZWN0aW9uLlxuICAgKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gc2VsZWN0aW9uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhXG4gICAqIEBwYXJhbSB7bGV2ZWx9IFtsZXZlbD0wXSByZWN1cnNpb24gZGVwdGhcbiAgICogQHJldHVybnMge251bWJlcn0gKGhvdyBtdWNoIHRvIG1vdmUgbmV4dCBlbGVtZW50KVxuICAgKiBAbWVtYmVyb2YgZ3JvdXBpbmdTcGFjZXIjXG4gICAqL1xuICBmdW5jdGlvbiByZWN1cnNpdmVseVBvc2l0aW9uKHNlbGVjdGlvbiwgZGF0YSwgbGV2ZWwpIHtcbiAgICBpZiAoIGxldmVsID09IHVuZGVmaW5lZCApIHsgbGV2ZWwgPSAwOyAgfVxuXG4gICAgdmFyIGN1cnJlbnRTZWxlY3Rpb24gPSBzZWxlY3Rpb24uc2VsZWN0QWxsKCdnLicrbmFtZXNwYWNlKydbbGV2ZWw9XCInK2xldmVsKydcIl0nKS5kYXRhKGRhdGEpXG4gICAgdmFyIGVudGVyID0gY3VycmVudFNlbGVjdGlvbi5lbnRlcigpLmFwcGVuZCgnZycpLmF0dHIoJ2xldmVsJywgbGV2ZWwpLmF0dHIoJ2NsYXNzJywgbmFtZXNwYWNlKVxuICAgIHZhciBleGl0ID0gY3VycmVudFNlbGVjdGlvbi5leGl0KClcbiAgICBjdXJyZW50U2VsZWN0aW9uID0gY3VycmVudFNlbGVjdGlvbi5tZXJnZShlbnRlcilcblxuXG4gICAgaWYgKHR5cGVvZiBleGl0RnVuY3Rpb24gPT0gJ2Z1bmN0aW9uJyApeyBleGl0LmVhY2goZnVuY3Rpb24oZCwgaSl7IGV4aXRGdW5jdGlvbihkMy5zZWxlY3QodGhpcykpfSkgfVxuICAgIGVsc2V7ZXhpdC5yZW1vdmUoKX1cbiAgICAvLyBzcGFjZXIgZm9yIGN1cnJlbnQgbGV2ZWxcbiAgICB2YXIgbGV2ZWxTcGFjZXIgPSBzcGFjZXJTaXplIC8gKGxldmVsKzEpXG4gICAgLy8gbW92ZW1lbnQgZm9yIGN1cnJlbnQgbGV2ZWxcbiAgICB2YXIgbW92ZSA9IDBcbiAgICBjdXJyZW50U2VsZWN0aW9uLmVhY2goZnVuY3Rpb24oY3VycmVudEVsZW1lbnQsIGluZGV4KSB7XG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgICAgaWYgKHQuYXR0cigndHJhbnNmb3JtJykgPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBlbnRlckZ1bmN0aW9uID09ICdmdW5jdGlvbicpIHsgZW50ZXJGdW5jdGlvbih0KSB9XG5cbiAgICAgIHQudHJhbnNpdGlvbigpLmR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbikuZWFzZShlYXNlRnVuYylcbiAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgIHZhclxuICAgICAgICB4ID0gaG9yaXpvbnRhbFEgPyAobW92ZWJ5ID09XCJzY2FsZVwiID8gc2NhbGUoZCkgOiBtb3ZlKSA6IDAsXG4gICAgICAgIHkgPSAhaG9yaXpvbnRhbFEgPyAobW92ZWJ5ID09XCJzY2FsZVwiID8gc2NhbGUoZCkgOiBtb3ZlKTogMCxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcblxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY3VycmVudEVsZW1lbnQpKSB7XG4gICAgICAgIG1vdmUgKz0gcmVjdXJzaXZlbHlQb3NpdGlvbih0LCBjdXJyZW50RWxlbWVudCwgbGV2ZWwrMSlcbiAgICAgICAgdmFyIHRvUmVtb3ZlID0gdC5zZWxlY3RBbGwoJ2cuJytuYW1lc3BhY2UrJ1tsZXZlbD1cIicrKGxldmVsKSsnXCJdID4gZy4nK29iamVjdENsYXNzKycuJytuYW1lc3BhY2UpXG4gICAgICAgIGlmICh0eXBlb2YgZXhpdEZ1bmN0aW9uID09ICdmdW5jdGlvbicgKXsgdG9SZW1vdmUuZWFjaChmdW5jdGlvbihkLCBpKXsgZXhpdEZ1bmN0aW9uKGQzLnNlbGVjdCh0aGlzKSl9KSB9XG4gICAgICAgIGVsc2V7dG9SZW1vdmUucmVtb3ZlKCl9XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgbW92ZSArPSBvYmplY3RTaXplXG4gICAgICAgIHZhciBvYmogPSB0LnNlbGVjdCgnZy4nK25hbWVzcGFjZSsnW2xldmVsPVwiJytsZXZlbCsnXCJdID4gZy4nK29iamVjdENsYXNzKycuJytuYW1lc3BhY2UpXG4gICAgICAgIGlmIChvYmouZW1wdHkoKSkgeyBvYmogPSB0LmFwcGVuZCgnZycpLmF0dHIoJ2NsYXNzJywgb2JqZWN0Q2xhc3MpLmNsYXNzZWQobmFtZXNwYWNlLCB0cnVlKSB9XG4gICAgICAgIG9iai5hdHRyKCdwYXJlbnQtaW5kZXgnLCBpbmRleClcbiAgICAgICAgdmFyIHRvUmVtb3ZlID0gdC5zZWxlY3RBbGwoJ2cuJytuYW1lc3BhY2UrJ1tsZXZlbD1cIicrKGxldmVsKzEpKydcIl0nKVxuXG4gICAgICAgIGlmICh0eXBlb2YgZXhpdEZ1bmN0aW9uID09ICdmdW5jdGlvbicgKXsgdG9SZW1vdmUuZWFjaChmdW5jdGlvbihkLCBpKXsgZXhpdEZ1bmN0aW9uKGQzLnNlbGVjdCh0aGlzKSl9KSB9XG4gICAgICAgIGVsc2V7dG9SZW1vdmUucmVtb3ZlKCl9XG4gICAgICB9XG4gICAgICBtb3ZlICs9IChpbmRleCA9PSBjdXJyZW50U2VsZWN0aW9uLnNpemUoKS0xKSA/IDAgOiBsZXZlbFNwYWNlclxuICAgIH0pXG4gICAgcmV0dXJuIG1vdmVcbiAgfVxuICByZXR1cm4gcmVjdXJzaXZlbHlQb3NpdGlvblxufVxuIiwiaW1wb3J0IHttb2RpZnlIZXhpZGVjaW1hbENvbG9yTHVtaW5hbmNlfSBmcm9tICcuL2hlbHBlcnMnO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBjb2xvckZ1bmN0aW9uXG4gKiBAY29uc3RydWN0b3IgY29sb3JGdW5jdGlvblxuICogQG5hbWVzcGFjZSBjb2xvckZ1bmN0aW9uXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IGNvbG9yRnVuY3Rpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbG9yRnVuY3Rpb24oKSB7XG4gIHZhclxuICBkYXRhLFxuXG4gIC8qKlxuICAqIERlZmF1bHQgY29sb3JzIHRvIHVzZVxuICAqIEBwYXJhbSB7bnVtYmVyW119IFtjb2xvcnM9W1wiIzJjN2JiNlwiLCBcIiMwMGE2Y2FcIiwgXCIjMDBjY2JjXCIsIFwiIzkwZWI5ZFwiLCBcIiNmZmZmOGNcIiwgXCIjZjlkMDU3XCIsIFwiI2YyOWUyZVwiLCBcIiNlNzY4MThcIiwgXCIjZDcxOTFjXCJdXVxuICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjb2xvcnMgPSBbXCIjMmM3YmI2XCIsIFwiIzAwYTZjYVwiLCBcIiMwMGNjYmNcIiwgXCIjOTBlYjlkXCIsIFwiI2ZmZmY4Y1wiLCBcIiNmOWQwNTdcIiwgXCIjZjI5ZTJlXCIsIFwiI2U3NjgxOFwiLCBcIiNkNzE5MWNcIl0sXG4gIC8qKlxuICAqIEludGVycG9sYXRvciBmb3IgY29sb3JzXG4gICogQHBhcmFtIHtkMy5pbnRlcnBvbGF0aW9ufSBbaW50ZXJwb2xhdGlvbj1kMy5pbnRlcnBvbGF0ZVJnYl1cbiAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgaW50ZXJwb2xhdGlvbiA9IGQzLmludGVycG9sYXRlUmdiLFxuICAvKipcbiAgKiBGdW5jdGlvbiBmb3IgbW9kaWZ5aW5nIGNvbG9yIGx1bWluYW5jZVxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFttb2RpZnlPcGFjaXR5PW1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2VdXG4gICogQG1lbWJlcm9mIGNvbG9yRnVuY3Rpb24jXG4gICogQHByb3BlcnR5XG4gICovXG4gIG1vZGlmeU9wYWNpdHkgPSBtb2RpZnlIZXhpZGVjaW1hbENvbG9yTHVtaW5hbmNlLFxuICAvKipcbiAgKiBIb3cgdG8gbW9kaWZ5IGNvbG9yIGZvciBzdHJva2VcbiAgKiBAcGFyYW0ge251bWJlcn0gW3N0cm9rZU9wYWNpdHk9MF1cbiAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3Ryb2tlT3BhY2l0eSA9IDAsXG4gIC8qKlxuICAqIEhvdyB0byBtb2RpZnkgY29sb3IgZm9yIGZpbGxcbiAgKiBAcGFyYW0ge251bWJlcn0gW2ZpbGxPcGFjaXR5PTAuNF1cbiAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZmlsbE9wYWNpdHkgPSAwLjQsXG4gIC8qKlxuICAqIEhvdyB0byBkZXRlcm1pbmUgdGhlIGNvbG9yIHRvIHVzZVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbY29sb3JCeT0naW5kZXgnXVxuICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjb2xvckJ5ID0gJ2luZGV4JyxcbiAgLyoqXG4gICogU2V0cyB0aGUgc2NhbGUgZm9yIGludGVycG9sYXRpbmcgdGhlIGNvbG9yc1xuICAqIEBwYXJhbSB7bnVtYmVyW119IFtkYXRhRXh0ZW50PVswLCBjb2xvcnMubGVuZ3RoIC0gMV1dXG4gICogQG1lbWJlcm9mIGNvbG9yRnVuY3Rpb24jXG4gICogQHByb3BlcnR5XG4gICovXG4gIGRhdGFFeHRlbnQgPSBbMCwgY29sb3JzLmxlbmd0aCAtIDFdLFxuICAvKipcbiAgKiBFeHRyYWN0cyB0aGUgdmFsdWUgdG8gY29sb3IgYnlcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbdmFsdWVFeHRyYWN0b3I9ZnVuY3Rpb24oaywgdiwgaSkge3JldHVybiB2fV1cbiAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihrLCB2LCBpKSB7cmV0dXJuIHZ9LFxuXG4gIC8qKlxuICAqIEV4dHJhY3RzIHRoZSBjYXRlZ29yeSB0byBjb2xvciBieVxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtjYXRlZ29yeUV4dHJhY3Rvcj1mdW5jdGlvbihrLCB2LCBpKSB7cmV0dXJuIHYuY2F0ZWdvcnl9XVxuICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjYXRlZ29yeUV4dHJhY3RvciA9IGZ1bmN0aW9uKGssIHYsIGkpIHtyZXR1cm4gdi5jYXRlZ29yeX0sXG5cbiAgLyoqXG4gICogVGhlIGRpZmZlcmVudCB0eXBlIG9mIGNhdGVnb3JpZXMgb2Ygd2hpY2ggdG8gY29sb3IgYnlcbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbY2F0ZWdvcmllcz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGNvbG9yRnVuY3Rpb24jXG4gICogQHByb3BlcnR5XG4gICovXG4gIGNhdGVnb3JpZXMsXG5cbiAgLyoqXG4gICogU2NhbGUgZm9yIGludGVycG9sYXRpbmcgdGhlIGNvbG9yc1xuICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtzY2FsZT1kMy5zY2FsZUxpbmVhcigpXVxuICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKClcbiAgLmludGVycG9sYXRlKGludGVycG9sYXRpb24pLmRvbWFpbihkYXRhRXh0ZW50KS5yYW5nZShjb2xvcnMpLFxuICBoZWxwZXJTY2FsZSA9IGQzLnNjYWxlTGluZWFyKClcblxuXG5cbiAgLy8gdmFyIGggPSB4ID0+ICcjJyArIHgubWF0Y2goL1xcZCsvZykubWFwKHkgPSB6ID0+ICgoK3ogPCAxNik/JzAnOicnKSArICgreikudG9TdHJpbmcoMTYpKS5qb2luKCcnKTtcbiAgdmFyIGggPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIFwiI1wiICsgeC5tYXRjaCgvXFxkKy9nKS5tYXAoXG4gICAgICBmdW5jdGlvbih5LCBpKSB7XG4gICAgICAgIHJldHVybiAgKCgreSA8IDE2KT8nMCc6JycpICsgKCt5KS50b1N0cmluZygxNilcbiAgICAgIH0pLmpvaW4oJycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZGVmYXVsdCBjb2xvcnNcbiAgICogKHNlZSB7QGxpbmsgY29sb3JGdW5jdGlvbiNjb2xvcnN9KVxuICAgKiBAcGFyYW0ge251bWJlcltdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Y29sb3JGdW5jdGlvbiB8IG51bWJlcltdfVxuICAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvblxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGNvbG9yRnVuY3Rpb24uY29sb3JzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoXG4gICAgP1xuICAgICAgKFxuICAgICAgICBjb2xvcnMgPSBfLFxuICAgICAgICBzY2FsZS5yYW5nZShjb2xvcnMpLFxuICAgICAgICBjb2xvckZ1bmN0aW9uXG4gICAgICApXG4gICAgOiBjb2xvcnM7XG4gIH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGZ1bmN0aW9uIGZvciBpbnRlcnBvbGF0aW5nIHRoZSBjb2xvcnNcbiAgICogKHNlZSB7QGxpbmsgY29sb3JGdW5jdGlvbiNpbnRlcnBvbGF0aW9ufSlcbiAgICogQHBhcmFtIHtkMy5pbnRlcnBvbGF0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Y29sb3JGdW5jdGlvbiB8IGQzLmludGVycG9sYXRpb259XG4gICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgY29sb3JGdW5jdGlvbi5pbnRlcnBvbGF0aW9uID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoXG4gICAgP1xuICAgIChcbiAgICAgIGludGVycG9sYXRpb24gPSBfLFxuICAgICAgc2NhbGUuaW50ZXJwb2xhdGUoaW50ZXJwb2xhdGlvbikucmFuZ2UoY29sb3JzKSxcbiAgICAgIGNvbG9yRnVuY3Rpb25cbiAgICApXG4gICAgOiBpbnRlcnBvbGF0aW9uO1xuICB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB2YWx1ZXMgZm9yIHRoZSBzY2FsZSB3aGljaCB0cmFuc2Zvcm1zIHRoZSB2YWx1ZSB0byBhIGNvbG9yXG4gICAqIChzZWUge0BsaW5rIGNvbG9yRnVuY3Rpb24jZGF0YUV4dGVudH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtjb2xvckZ1bmN0aW9uIHwgbnVtYmVyW119XG4gICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoXG4gICAgPyAoXG4gICAgICAgIGRhdGFFeHRlbnQgPSBfLFxuICAgICAgICBzY2FsZS5kb21haW4oZGF0YUV4dGVudCkuaW50ZXJwb2xhdGUoc2NhbGUuaW50ZXJwb2xhdGUoKSksXG4gICAgICAgIGNvbG9yRnVuY3Rpb25cbiAgICAgIClcbiAgICA6IGRhdGFFeHRlbnQ7XG4gIH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHZ0aGUgc2NhbGUgd2hpY2ggdHJhbnNmb3JtcyB0aGUgdmFsdWUgdG8gYSBjb2xvclxuICAgKiAoc2VlIHtAbGluayBjb2xvckZ1bmN0aW9uI3NjYWxlfSlcbiAgICogQHBhcmFtIHtkMy5zY2FsZX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2NvbG9yRnVuY3Rpb24gfCBkMy5zY2FsZX1cbiAgICogQG1lbWJlcm9mIGNvbG9yRnVuY3Rpb25cbiAgICogQHByb3BlcnR5XG4gICAqL1xuICBjb2xvckZ1bmN0aW9uLnNjYWxlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoXG4gICAgPyAoXG4gICAgICAgIF8gPSBfLmRvbWFpbihzY2FsZS5kb21haW4oKSkuaW50ZXJwb2xhdGUoc2NhbGUuaW50ZXJwb2xhdGUoKSkucmFuZ2Uoc2NhbGUucmFuZ2UoKSksXG4gICAgICAgIHNjYWxlID0gXyxcbiAgICAgICAgY29sb3JGdW5jdGlvblxuICAgICAgKVxuICAgIDogc2NhbGU7XG4gIH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGZ1bmN0aW9uIGZvciBtb2RpZnkgb3BhY2l0eVxuICAgKiAoc2VlIHtAbGluayBjb2xvckZ1bmN0aW9uI21vZGlmeU9wYWNpdHl9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Y29sb3JGdW5jdGlvbiB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvblxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGNvbG9yRnVuY3Rpb24ubW9kaWZ5T3BhY2l0eSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobW9kaWZ5T3BhY2l0eSA9IF8sIGNvbG9yRnVuY3Rpb24pIDogbW9kaWZ5T3BhY2l0eTsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgdmFsdWUgdG8gbW9kaWZ5IHRoZSBjb2xvciBmb3IgdGhlIHN0cm9rZSB2aWEge0BsaW5rIGNvbG9yRnVuY3Rpb24jbW9kaWZ5T3BhY2l0eX1cbiAgICogKHNlZSB7QGxpbmsgY29sb3JGdW5jdGlvbiNzdHJva2VPcGFjaXR5fSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtjb2xvckZ1bmN0aW9uIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvblxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGNvbG9yRnVuY3Rpb24uc3Ryb2tlT3BhY2l0eSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3Ryb2tlT3BhY2l0eSA9IF8sIGNvbG9yRnVuY3Rpb24pIDogc3Ryb2tlT3BhY2l0eTsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgdmFsdWUgdG8gbW9kaWZ5IHRoZSBjb2xvciBmb3IgdGhlIHN0cm9rZSB2aWEge0BsaW5rIGNvbG9yRnVuY3Rpb24jZmlsbE9wYWNpdHl9XG4gICAqIChzZWUge0BsaW5rIGNvbG9yRnVuY3Rpb24jZmlsbE9wYWNpdHl9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2NvbG9yRnVuY3Rpb24gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgY29sb3JGdW5jdGlvbi5maWxsT3BhY2l0eSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZmlsbE9wYWNpdHkgPSBfLCBjb2xvckZ1bmN0aW9uKSA6IGZpbGxPcGFjaXR5OyB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB2YWx1ZSB0byBjb2xvckJ5XG4gICAqIChzZWUge0BsaW5rIGNvbG9yRnVuY3Rpb24jY29sb3JCeX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Y29sb3JGdW5jdGlvbiB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGNvbG9yRnVuY3Rpb25cbiAgICogQHByb3BlcnR5XG4gICAqL1xuICBjb2xvckZ1bmN0aW9uLmNvbG9yQnkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvbG9yQnkgPSBfLCBjb2xvckZ1bmN0aW9uKSA6IGNvbG9yQnk7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHZhbHVlIG9mIHZhbHVlRXh0cmFjdG9yXG4gICAqIChzZWUge0BsaW5rIGNvbG9yRnVuY3Rpb24jdmFsdWVFeHRyYWN0b3J9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Y29sb3JGdW5jdGlvbiB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgY29sb3JGdW5jdGlvblxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGNvbG9yRnVuY3Rpb24udmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZhbHVlRXh0cmFjdG9yID0gXywgY29sb3JGdW5jdGlvbikgOiB2YWx1ZUV4dHJhY3RvcjsgfTtcblxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB2YWx1ZSBvZiBjYXRlZ29yeUV4dHJhY3RvclxuICAgKiAoc2VlIHtAbGluayBjb2xvckZ1bmN0aW9uI2NhdGVnb3J5RXh0cmFjdG9yfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2NvbG9yRnVuY3Rpb24gfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGNvbG9yRnVuY3Rpb25cbiAgICogQHByb3BlcnR5XG4gICAqL1xuICBjb2xvckZ1bmN0aW9uLmNhdGVnb3J5RXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjYXRlZ29yeUV4dHJhY3RvciA9IF8sIGNvbG9yRnVuY3Rpb24pIDogY2F0ZWdvcnlFeHRyYWN0b3I7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHZhbHVlIG9mIGNhdGVnb3J5RXh0cmFjdG9yXG4gICAqIChzZWUge0BsaW5rIGNvbG9yRnVuY3Rpb24jY2F0ZWdvcmllc30pXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtjb2xvckZ1bmN0aW9uIHwgc3RyaW5nW119XG4gICAqIEBtZW1iZXJvZiBjb2xvckZ1bmN0aW9uXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgY29sb3JGdW5jdGlvbi5jYXRlZ29yaWVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjYXRlZ29yaWVzID0gXywgY29sb3JGdW5jdGlvbikgOiBjYXRlZ29yaWVzOyB9O1xuXG5cbiAgZnVuY3Rpb24gY29sb3JGdW5jdGlvbihrZXksIHZhbHVlLCBpbmRleCwgdHlwZSwgaG92ZXJRKSB7XG4gICAgdmFyIGMsXG4gICAgb3BhYyA9IHR5cGUgPT0gXCJmaWxsXCIgPyBmaWxsT3BhY2l0eSA6IHN0cm9rZU9wYWNpdHk7XG5cblxuICAgIHVwZGF0ZVNjYWxlKClcblxuICAgIGlmIChjb2xvckJ5ID09IFwiaW5kZXhcIikge1xuICAgICAgYyA9ICh0eXBlICE9IHVuZGVmaW5lZCkgPyBtb2RpZnlPcGFjaXR5KGgoc2NhbGUoaW5kZXgpKSwgb3BhYykgOiBoKHNjYWxlKGluZGV4KSlcbiAgICB9XG5cbiAgICBlbHNlIGlmIChjb2xvckJ5ID09ICd2YWx1ZScpIHtcbiAgICAgIHZhciB2ID0gdmFsdWVFeHRyYWN0b3Ioa2V5LCB2YWx1ZSwgaW5kZXgpO1xuICAgICAgLy8gaWYgKHYgPCBkYXRhRXh0ZW50WzBdKSB7ZGF0YUV4dGVudFswXSA9IHY7IHVwZGF0ZVNjYWxlKCl9XG4gICAgICAvLyBpZiAodiA+IGRhdGFFeHRlbnRbMV0pIHtkYXRhRXh0ZW50WzFdID0gdjsgdXBkYXRlU2NhbGUoKX1cblxuICAgICAgYyA9ICh0eXBlICE9IHVuZGVmaW5lZCkgPyBtb2RpZnlPcGFjaXR5KGgoc2NhbGUodikpLCBvcGFjKSA6IGgoc2NhbGUodikpXG4gICAgfVxuXG4gICAgZWxzZSBpZiAoY29sb3JCeSA9PSAnY2F0ZWdvcnknICl7XG4gICAgICB2YXIgY2F0ID0gY2F0ZWdvcnlFeHRyYWN0b3Ioa2V5LCB2YWx1ZSwgaW5kZXgpO1xuICAgICAgdmFyIHYgPSBjYXRlZ29yaWVzLmluZGV4T2YoY2F0KVxuICAgICAgYyA9ICh0eXBlICE9IHVuZGVmaW5lZCkgPyBtb2RpZnlPcGFjaXR5KGgoc2NhbGUodikpLCBvcGFjKSA6IGgoc2NhbGUodikpXG5cbiAgICB9XG5cbiAgICBlbHNlIHtcbiAgICAgIGMgPSAodHlwZSAhPSB1bmRlZmluZWQpID8gbW9kaWZ5T3BhY2l0eShoKHNjYWxlKGluZGV4KSksIG9wYWMpIDogaChzY2FsZShpbmRleCkpXG4gICAgfVxuXG4gICAgcmV0dXJuIGNcbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZVNjYWxlKCl7XG5cblxuICAgIGhlbHBlclNjYWxlLmRvbWFpbihbMCwgY29sb3JzLmxlbmd0aF0pXG4gICAgaWYgKGNvbG9yQnkgPT0gJ2NhdGVnb3J5JyAmJiBjYXRlZ29yaWVzICE9IHVuZGVmaW5lZCkgeyBoZWxwZXJTY2FsZS5yYW5nZShbMCwgY2F0ZWdvcmllcy5sZW5ndGhdKSB9XG4gICAgZWxzZSB7IGhlbHBlclNjYWxlLnJhbmdlKGRhdGFFeHRlbnQpIH1cblxuXG4gICAgdmFyIGEgPSBBcnJheShjb2xvcnMubGVuZ3RoKS5maWxsKDApLm1hcChmdW5jdGlvbihkLCBpKXsgcmV0dXJuIGhlbHBlclNjYWxlKGkpIH0pXG4gICAgc2NhbGUuZG9tYWluKGEpXG4gIH1cblxuICByZXR1cm4gY29sb3JGdW5jdGlvblxufVxuIiwiaW1wb3J0IHtzYWZlU2VsZWN0LCByb3VuZH0gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7bG9nLCB3YXJuLCBpbmZvLCBlcnJvciwgY29uc29sZUdyb3VwLCBjb25zb2xlR3JvdXBFbmR9IGZyb20gJy4vdXRpbHMnO1xuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUT09MVElQICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbi8qKlxuICogUHJvZHVjZXMgYSBmdW5jdGlvbiBmb3IgaGFuZGxpbmcgdGhlIHRvb2x0aXBcbiAqXG4gKiB7QGxpbmsgaHR0cHM6Ly9zdW1uZXVyb24uZ2l0bGFiLmlvL2Qzc20vZGVtb3MvdG9vbHRpcC1kZXNpZ24vaW5kZXguaHRtbCBEZW1vfVxuICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IHNlbGVjdGlvblxuICogQHJldHVybnMge3Rvb2x0aXB9XG4gKiBAbmFtZXNwYWNlIHRvb2x0aXBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvb2x0aXAoIHNlbGVjdGlvbiApIHtcblxuICB2YXJcbiAga2V5cyxcbiAgdmFsdWVzLFxuICBoZWFkZXIsXG4gIGRhdGEsXG4gIHNlbGVjdGlvblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUga2V5cyB0byBiZSBkaXNwbGF5ZWQgaW4gdGhlIHRvb2x0aXAuXG4gICAqIElmIG5vdCBzZXQsIHVzZXMgZDMua2V5cyhkYXRhW2tleV0pXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt0b29sdGlwIHwgc3RyaW5nW119XG4gICAqIEBtZW1iZXJvZiB0b29sdGlwXG4gICAqL1xuICB0b29sdGlwLmtleXMgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChrZXlzID0gXywgdG9vbHRpcCkgOiBrZXlzfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB2YWx1ZXMgdG8gYmUgZGlzcGxheWVkIG5leHQgdG8gdGhlIGtleXMuXG4gICAqIElmIG5vdCBzZXQsIHVzZXMgZGF0YVtrZXldW2tleXNbaV1dLlxuICAgKiBJZiBhIGZ1bmN0aW9uLCBnZXRzIHBhc3NlZCBjdXJyZW50RGF0YSAoZGF0YVtrZXldKSBhbmQga2V5c1tpXS5cbiAgICogQHBhcmFtIHsqW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt0b29sdGlwIHwgKltdfVxuICAgKiBAbWVtYmVyb2YgdG9vbHRpcFxuICAgKi9cbiAgdG9vbHRpcC52YWx1ZXMgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZXMgPSBfLCB0b29sdGlwKSA6IHZhbHVlc307XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgaGVhZGVyIHRvIGJlIGRpc3BsYXllZCBpbiB0aGUgdG9vbHRpcC5cbiAgICogSWYgbm90IHNldCwgdXNlcyBrZXlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt0b29sdGlwIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgdG9vbHRpcFxuICAgKi9cbiAgdG9vbHRpcC5oZWFkZXIgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChoZWFkZXIgPSBfLCB0b29sdGlwKSA6IGhlYWRlcn07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgZGF0YSAob3ZlciB0aGUgc2VsZWN0aW9uKSB0byBiZSB1c2VkIGZvciB0aGUgdG9vbHRpcFxuICAgKiBAcGFyYW0ge09iamVjdH0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Rvb2x0aXAgfCBPYmplY3R9XG4gICAqIEBtZW1iZXJvZiB0b29sdGlwXG4gICAqL1xuICB0b29sdGlwLmRhdGEgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkYXRhID0gXywgdG9vbHRpcCkgOiBkYXRhfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzZWxlY3Rpb24gZm9yIHRoZSB0b29sdGlwIHRvIGJlIGFwcGxpZWQgb25cbiAgICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt0b29sdGlwIHwgZDMuc2VsZWN0aW9ufVxuICAgKiBAbWVtYmVyb2YgdG9vbHRpcFxuICAgKi9cbiAgdG9vbHRpcC5zZWxlY3Rpb24gPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZWxlY3Rpb24gPSBfLCB0b29sdGlwKSA6IHNlbGVjdGlvbn07XG5cbiAgLyoqXG4gICAqIEJpbmQsIHZpYSBzZWxlY3Rpb24ub24oKSwgdGhlIG1vdXNlbW92ZSBhbmQgbW91c2VvdXQgZXZlbnRzXG4gICAqIEByZXR1cm5zIHVuZGVmaW5lZFxuICAgKi9cbiAgZnVuY3Rpb24gdG9vbHRpcCggKSB7XG4gICAgc2VsZWN0aW9uLm9uKCdtb3VzZW92ZXInLCBtb3VzZW1vdmUpXG4gICAgc2VsZWN0aW9uLm9uKCdtb3VzZW1vdmUnLCBtb3VzZW1vdmUpXG4gICAgc2VsZWN0aW9uLm9uKCdtb3VzZW91dCcsIGZ1bmN0aW9uKCl7IGQzLnNlbGVjdEFsbChcIi5kM3NtLXRvb2x0aXBcIikucmVtb3ZlKCl9KVxuICB9XG5cblxuICAvKipcbiAgICogUHJvZHVjZXMgdGhlIHRvb2x0aXAgb24gbW91c2Vtb3ZlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgb2YgdGhlIG9iamVjdCB0YXJnZXRlZCBieSB0aGUgbW91c2Vtb3ZlXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpIChpbmRleCkgb2YgdGhlIG9iamVjdCB0YXJnZXRlZCBieSBtb3VzZW1vdmVcbiAgICogQG1lbWJlcm9mIHRvb2x0aXBcbiAgICogQHByaXZhdGVcbiAgICovXG4gIGZ1bmN0aW9uIG1vdXNlbW92ZShrZXksIGkpIHtcbiAgICBjb25zb2xlR3JvdXAoJ2Qzc20tdG9vbHRpcCcpXG4gICAgdmFyIGN1cnJlbnREYXRhID0gZGF0YVtrZXldXG5cbiAgICB2YXIgW3gsIHldID0gZDMubW91c2UoZDMuc2VsZWN0KFwiaHRtbFwiKS5ub2RlKCkpXG4gICAgbG9nKCd0b29sdGlwJywgJ21vdXNlbW92ZSBkZXRlY3RlZCcse2tleToga2V5LCBpbmRleDogaSwgeDp4LCB5Onl9KVxuICAgIGxvZygndG9vbHRpcCcsICdjdXJyZW50IGRhdGEnLCBjdXJyZW50RGF0YSlcblxuXG5cbiAgICB2YXIgZGl2ID0gc2FmZVNlbGVjdChkMy5zZWxlY3QoJ2h0bWwnKSwgJ3Rvb2x0aXAnLCAnZDNzbS10b29sdGlwJylcbiAgICAuY2xhc3NlZCgnY2FyZCcsIHRydWUpXG4gICAgLnN0eWxlKCdtYXgtd2lkdGgnLCAnMzAwcHgnKVxuICAgIC5zdHlsZSgnYmFja2dyb3VuZC1jb2xvcicsIFwiIzIxMjUyOVwiKVxuICAgIC5zdHlsZSgnY29sb3InLCAnd2hpdGUnKVxuXG5cblxuICAgIHZhciBjYXJkQm9keSA9IHNhZmVTZWxlY3QoZGl2LCAnZGl2JywgJ2NhcmQtYm9keScpXG4gICAgdmFyIGNhcmRUaXRsZSA9IHNhZmVTZWxlY3QoY2FyZEJvZHksICdoNScsICdjYXJkLXRpdGxlJylcbiAgICAudGV4dChoZWFkZXIgPT0gdW5kZWZpbmVkID8ga2V5IDogdHlwZW9mIGhlYWRlciA9PSAnZnVuY3Rpb24nID8gaGVhZGVyKGtleSwgY3VycmVudERhdGEsIGkpIDogaGVhZGVyKVxuICAgIC5zdHlsZSgnY29sb3InLCAnY3lhbicpXG5cblxuICAgIHZhciB0YWJsZSA9IHNhZmVTZWxlY3QoY2FyZEJvZHksICd0YWJsZScsICd0YWJsZScpLmNsYXNzZWQoJ3RhYmxlLWRhcmsnLCB0cnVlKVxuICAgIHZhciB0Qm9keSA9IHNhZmVTZWxlY3QodGFibGUsICd0Ym9keScpXG5cbiAgICB0Qm9keSA9IHRCb2R5LnNlbGVjdEFsbCgndHInKVxuICAgIHRCb2R5PSB0Qm9keS5kYXRhKGtleXMgPT0gdW5kZWZpbmVkID8gZDMua2V5cyhjdXJyZW50RGF0YSk6IGtleXMpXG4gICAgdEJvZHkuZXhpdCgpLnJlbW92ZSgpXG5cblxuICAgIHZhciB0ciA9IHRCb2R5LmVudGVyKCkuYXBwZW5kKCd0cicpLnN0eWxlKCdtYXgtd2lkdGgnLCAnMzAwcHgnKVxuICAgIHRyLmFwcGVuZCgndGQnKS5hdHRyKCdjbGFzcycsIGZ1bmN0aW9uKGQsIGkpe3JldHVybiAndG9vbHRpcC1rZXknfSlcbiAgICB0ci5hcHBlbmQoJ3RkJykuYXR0cignY2xhc3MnLCAgZnVuY3Rpb24oZCwgaSwgail7cmV0dXJuICd0b29sdGlwLXZhbHVlJ30pXG4gICAgLmF0dHIoJ3Rvb2x0aXAtcm93LWluZGV4JywgZnVuY3Rpb24oZCwgaSl7cmV0dXJuIGl9KVxuXG4gICAgLy8gdEJvZHkgPSB0Qm9keS5tZXJnZSh0cilcbiAgICBjb25zb2xlR3JvdXAoJ3Rvb2x0aXAtcm93cycpXG4gICAgdEJvZHkuc2VsZWN0QWxsKCcudG9vbHRpcC1rZXknKS50ZXh0KGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkfSlcbiAgICB0Qm9keS5zZWxlY3RBbGwoJ3RyIC50b29sdGlwLXZhbHVlJylcbiAgICAudGV4dChmdW5jdGlvbihkLCBpKXtcbiAgICAgIGxvZygndG9vbHRpcCcsICd0cnlpbmcgdG8gc2V0IHZhbHVlJywge3Jvd0tleTogZCwgcm93SW5kZXg6IGl9KVxuICAgICAgdmFyIGkgPSBkMy5zZWxlY3QodGhpcykuYXR0cigndG9vbHRpcC1yb3ctaW5kZXgnKVxuICAgICAgdmFyIHYgPSBjdXJyZW50RGF0YVtkXTtcblxuXG4gICAgICBpZiAodmFsdWVzICE9IHVuZGVmaW5lZCkge3YgPSB2YWx1ZXNbaV07IGlmKHR5cGVvZiB2ID09IFwiZnVuY3Rpb25cIikge3YgPSB2KGN1cnJlbnREYXRhLCBkKX19XG4gICAgICByZXR1cm4gIHR5cGVvZiB2ID09ICdudW1iZXInID8gcm91bmQodiwgNSkgOiB2XG4gICAgfSlcbiAgICBjb25zb2xlR3JvdXBFbmQoKVxuICAgIGNvbnNvbGVHcm91cEVuZCgpXG5cbiAgICB4ICs9IDE1XG4gICAgLy8geCArPSAxNVxuICAgIHZhciBiYm94ID0gZGl2Lm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVxuICAgIGlmICh4ICsgYmJveC53aWR0aCA+IHdpbmRvdy5pbm5lcldpZHRoIC0gd2luZG93LnNjcm9sbFgpIHsgeCA9IGQzLmV2ZW50LnBhZ2VYIC0gYmJveC53aWR0aCAtIDE1IH1cbiAgICBpZiAoeSArIGJib3guaGVpZ2h0ID4gd2luZG93LmlubmVySGVpZ2h0ICAtIHdpbmRvdy5zY3JvbGxZKSB7IHkgPSBkMy5ldmVudC5wYWdlWSAtIGJib3guaGVpZ2h0IC0gMTUgfVxuICAgIGRpdi5zdHlsZSgncG9zaXRpb24nKSA9PSBcInJlbGF0aXZlXCJcbiAgICA/IGRpdi5zdHlsZSgncG9zaXRpb24nLCAnYWJzb2x1dGUnKS5zdHlsZSgnbGVmdCcsIHgrJ3B4Jykuc3R5bGUoJ3RvcCcsIHkrJ3B4JylcbiAgICA6IGRpdi5zdHlsZSgnbGVmdCcsIHgrJ3B4Jykuc3R5bGUoJ3RvcCcsIHkrJ3B4JylcbiAgICAvLyAudHJhbnNpdGlvbigpLmR1cmF0aW9uKDIwMCkuZWFzZShkMy5lYXNlU2luKVxuXG4gICAgLy8gaWYgKGJib3gueCArIGJib3gud2lkdGggPiB3aW5kb3cuaW5uZXJXaWR0aCkge1xuICAgIC8vICAgZGl2LnN0eWxlKCdsZWZ0JywgKGQzLmV2ZW50LnBhZ2VYLTE1LWJib3gud2lkdGgpKydweCcpXG4gICAgLy8gfVxuICAgIC8vIGlmIChiYm94LnkgKyBiYm94LmhlaWdodCA+IHdpbmRvdy5pbm5lckhlaWdodCkge1xuICAgIC8vICAgZGl2LnN0eWxlKCd0b3AnLCAoZDMuZXZlbnQucGFnZVktMTUtYmJveC5oZWlnaHQpKydweCcpXG4gICAgLy8gfVxuXG4gICAgZGl2LmF0dHIoJ3otaW5kZXgnLCAxMDAwMClcbiAgfVxuXG4gIHJldHVybiB0b29sdGlwXG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuXG5leHBvcnQgZnVuY3Rpb24gc2VsZWN0RmlsdGVyKHNlbGVjdGlvbikge1xuXG4gIHZhclxuICBkYXRhLFxuICBuYW1lc3BhY2UgPSAnZDNzbS1zZWxlY3QtZmlsdGVyJyxcbiAgc2VsZWN0aW9uTmFtZSA9ICdTZWxlY3Qgb3B0aW9uczonLFxuICBkZWZhdWx0VmFsdWUgPSB1bmRlZmluZWRcblxuXG5cblxuICB2YXIgbGFzdFZhbHVlID0gdW5kZWZpbmVkXG5cbiAgc2VsZWN0RmlsdGVyLmRhdGEgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRhdGEgPSBfLCBzZWxlY3RGaWx0ZXIpIDogZGF0YX1cbiAgc2VsZWN0RmlsdGVyLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgc2VsZWN0RmlsdGVyKSA6IG5hbWVzcGFjZX1cbiAgc2VsZWN0RmlsdGVyLnNlbGVjdGlvbk5hbWUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNlbGVjdGlvbk5hbWUgPSBfLCBzZWxlY3RGaWx0ZXIpIDogc2VsZWN0aW9uTmFtZX1cbiAgc2VsZWN0RmlsdGVyLmRlZmF1bHRWYWx1ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGVmYXVsdFZhbHVlID0gXywgc2VsZWN0RmlsdGVyKSA6IGRlZmF1bHRWYWx1ZX1cbiAgc2VsZWN0RmlsdGVyLmN1cnJlbnRPcHRpb24gPSBjdXJyZW50T3B0aW9uXG5cbiAgZnVuY3Rpb24gc2VsZWN0RmlsdGVyKCkge1xuICAgIHZhclxuICAgIGNvbnRhaW5lciA9IHNhZmVTZWxlY3Qoc2VsZWN0aW9uLCAnZGl2JywgJ2lucHV0LWdyb3VwJykuY2xhc3NlZChoeXBlbmF0ZShuYW1lc3BhY2UsJ2NvbnRhaW5lcicpLHRydWUpLFxuXG4gICAgICBzZWxlY3RQcmVwZW5kID0gc2FmZVNlbGVjdChjb250YWluZXIsICdkaXYnLCAnc2VsZWN0LXByZXBlbmQnKS5jbGFzc2VkKCdpbnB1dC1ncm91cC1wcmVwZW5kJywgdHJ1ZSksXG4gICAgICAgIHNlbGVjdFByZXBlbmRTcGFuID0gc2FmZVNlbGVjdChzZWxlY3RQcmVwZW5kLCAnc3BhbicsICdpbnB1dC1ncm91cC10ZXh0JykudGV4dChzZWxlY3Rpb25OYW1lKSxcblxuICAgICAgc2VsZWN0ID0gc2FmZVNlbGVjdChjb250YWluZXIsICdzZWxlY3QnLCAnY3VzdG9tLXNlbGVjdCcpLmNsYXNzZWQoaHlwZW5hdGUobmFtZXNwYWNlLCdzZWxlY3QnKSx0cnVlKSxcblxuICAgICAgc2VsZWN0QXBwZW5kID0gc2FmZVNlbGVjdChjb250YWluZXIsICdkaXYnLCAnc2VsZWN0LWFwcGVuZCcpLmNsYXNzZWQoJ2lucHV0LWdyb3VwLXByZXBlbmQnLCB0cnVlKSxcbiAgICAgICAgc2VsZWN0QXBwZW5kQnV0dG9uID0gc2FmZVNlbGVjdChzZWxlY3RBcHBlbmQsICdhJywgJ2ZpbHRlci1idXR0b24nKS5jbGFzc2VkKCdidG4gYnRuLW91dGxpbmUtc2Vjb25kYXJ5JywgdHJ1ZSksXG4gICAgICAgICAgZmlsdGVyQnV0dG9uSWNvbiA9IHNhZmVTZWxlY3Qoc2VsZWN0QXBwZW5kQnV0dG9uLCAnaScsICdmYSBmYS1maWx0ZXInKSxcblxuICAgICAgaW5wdXRHcm91cCA9IHNhZmVTZWxlY3QoY29udGFpbmVyLCAnZGl2JywgJ2ZpbHRlci1pbnB1dC1ncm91cCcpLmNsYXNzZWQoJ2lucHV0LWdyb3VwJyx0cnVlKS5jbGFzc2VkKCdkLW5vbmUnLCB0cnVlKSxcbiAgICAgICAgaW5wdXRQcmVwZW5kID0gc2FmZVNlbGVjdChpbnB1dEdyb3VwLCAnZGl2JywgJ2lucHV0LWdyb3VwLXByZXBlbmQnKSxcbiAgICAgICAgICBpbnB1dFByZXBlbmRTcGFuID0gc2FmZVNlbGVjdChpbnB1dFByZXBlbmQsICdzcGFuJywgJ2lucHV0LWdyb3VwLXRleHQnKS5jbGFzc2VkKCdzZWFyY2gtYnV0dG9uJywgdHJ1ZSksXG4gICAgICAgICAgICBpbnB1dFByZXBlbmRTcGFuSWNvbiA9IHNhZmVTZWxlY3QoaW5wdXRQcmVwZW5kU3BhbiwnaScsJ2ZhIGZhLXNlYXJjaCcpLFxuXG4gICAgICAgIGlucHV0ID0gc2FmZVNlbGVjdChpbnB1dEdyb3VwLCAnaW5wdXQnLCAnZm9ybS1jb250cm9sJykuYXR0cigncGxhY2Vob2xkZXInLCAnYWxsJykuYXR0cigndHlwZScsICd0ZXh0JyksXG4gICAgICAgIGlucHV0QXBwZW5kID0gc2FmZVNlbGVjdChpbnB1dEdyb3VwLCAnZGl2JywgJ2lucHV0LWdyb3VwLWFwcGVuZCcpLFxuICAgICAgICAgIGlucHV0QXBwZW5kQnV0dG9uID0gc2FmZVNlbGVjdChpbnB1dEFwcGVuZCwgJ2EnLCAnY2xvc2UtYnV0dG9uJykuY2xhc3NlZCgnYnRuIGJ0bi1vdXRsaW5lLXNlY29uZGFyeScsIHRydWUpLFxuICAgICAgICAgICAgaW5wdXRBcHBlbmRCdXR0b25JY29uID0gc2FmZVNlbGVjdChpbnB1dEFwcGVuZEJ1dHRvbiwgJ2knLCAnZmEgZmEtY2xvc2UnKVxuXG5cbiAgICB2YXIga2V5cyA9IGQzLmtleXMoZGF0YSksXG4gICAgb3B0aW9ucyA9IHNlbGVjdC5zZWxlY3RBbGwoJ29wdGlvbicpXG5cbiAgICBvcHRpb25zID0gb3B0aW9ucy5kYXRhKGQzLmtleXMoZGF0YSkpXG4gICAgb3B0aW9ucyA9IG9wdGlvbnMubWVyZ2Uob3B0aW9ucy5lbnRlcigpLmFwcGVuZCgnb3B0aW9uJykpXG4gICAgLmF0dHIoJ3ZhbHVlJywgZnVuY3Rpb24oZCwgaSl7cmV0dXJuIGR9KVxuICAgIC50ZXh0KGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkfSlcblxuICAgIHZhclxuICAgIGZpbHRlckJ1dHRvbiA9IHNlbGVjdEFwcGVuZEJ1dHRvbixcbiAgICBjbG9zZUJ1dHRvbiA9IGlucHV0QXBwZW5kQnV0dG9uXG5cbiAgICBmaWx0ZXJCdXR0b24ub24oJ2NsaWNrJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICB2YXIgY3VycmVudFN0eWxlID0gaW5wdXRHcm91cC5jbGFzc2VkKCdkLW5vbmUnKVxuICAgICAgaW5wdXRHcm91cC5jbGFzc2VkKCdkLW5vbmUnLCAhY3VycmVudFN0eWxlKVxuICAgIH0pXG5cbiAgICBjbG9zZUJ1dHRvbi5vbignY2xpY2snLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgIGlucHV0LnByb3BlcnR5KCd2YWx1ZScsICcnKS5kaXNwYXRjaCgnaW5wdXQnKVxuICAgIH0pXG5cbiAgICBpbnB1dC5vbignaW5wdXQnLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhclxuICAgICAgdmFsID0gaW5wdXQucHJvcGVydHkoJ3ZhbHVlJyksXG4gICAgICByZWcgPSBuZXcgUmVnRXhwKHZhbCwgJ2dpJyksXG4gICAgICB1c2VcblxuICAgICAgaWYgKHZhbCA9PSAnJykge3VzZSA9IGtleXN9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdXNlID0gW11cbiAgICAgICAgZDMua2V5cyhkYXRhKS5tYXAoZnVuY3Rpb24ob3B0aW9uLCBqKXtcbiAgICAgICAgICB2YXIgbWF0Y2ggPSBvcHRpb24ubWF0Y2gocmVnKVxuICAgICAgICAgIGlmIChtYXRjaCA9PSBudWxsIHx8IG1hdGNoLmpvaW4oJycpID09ICcnKSB7fVxuICAgICAgICAgIGVsc2UgeyB1c2UucHVzaChvcHRpb24pIH1cbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgb3B0aW9ucyA9IHNlbGVjdC5zZWxlY3RBbGwoJ29wdGlvbicpXG4gICAgICBvcHRpb25zID0gb3B0aW9ucy5kYXRhKHVzZSlcbiAgICAgIG9wdGlvbnMuZXhpdCgpLnJlbW92ZSgpXG4gICAgICBvcHRpb25zID0gb3B0aW9ucy5tZXJnZShvcHRpb25zLmVudGVyKCkuYXBwZW5kKCdvcHRpb24nKSlcbiAgICAgIC5hdHRyKCd2YWx1ZScsIGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkfSlcbiAgICAgIC50ZXh0KGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkfSlcblxuICAgICAgdmFyIGN1cnJlbnQgPSBjdXJyZW50T3B0aW9uKClcbiAgICAgIGlmIChsYXN0VmFsdWUgIT0gY3VycmVudCkge1xuICAgICAgICBsYXN0VmFsdWUgPSBjdXJyZW50XG4gICAgICAgIHNlbGVjdC5kaXNwYXRjaCgnY2hhbmdlJylcbiAgICAgIH1cbiAgICB9KVxuXG5cbiAgfVxuXG4gIGZ1bmN0aW9uIGN1cnJlbnRPcHRpb24oKSB7XG4gICAgdmFyIHZhbCA9IHNlbGVjdGlvbi5zZWxlY3QoXCJzZWxlY3RcIikucHJvcGVydHkoJ3ZhbHVlJylcbiAgICByZXR1cm4gdmFsID09IHVuZGVmaW5lZCB8fCB2YWwgPT0gJydcbiAgICA/IGRlZmF1bHRWYWx1ZSA9PSB1bmRlZmluZWRcbiAgICAgID8gZDMua2V5cyhkYXRhKVswXVxuICAgICAgOiBkZWZhdWx0VmFsdWVcbiAgICA6IHZhbFxuICB9XG5cbiAgcmV0dXJuIHNlbGVjdEZpbHRlclxufVxuIiwiaW1wb3J0IHtoeXBlbmF0ZSwgc2FmZVNlbGVjdCwgZXVjbGlkZWFuRGlzdGFuY2V9IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQge3NldHVwQ29udGFpbmVyLCBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0LCBjYWxjdWxhdGVXaWR0aE9mU3BhY2VyfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7dW5pcXVlLCBoYXNRLCBmbGF0dGVuLCB3aGljaEJpbn0gZnJvbSAnLi9hcnJheS1mdW5jdGlvbnMnO1xuaW1wb3J0IHtncm91cGluZ1NwYWNlcn0gZnJvbSAnLi9ncm91cGluZy1zcGFjZXInO1xuaW1wb3J0IHtjb2xvckZ1bmN0aW9uIGFzIENGfSBmcm9tICcuL2NvbG9yLWZ1bmN0aW9uJztcbmltcG9ydCB7dG9vbHRpcCBhcyBUVGlwfSBmcm9tICcuL3Rvb2x0aXAnO1xuaW1wb3J0ICcuL2QzLXByb3RvdHlwZXMnO1xuXG5mdW5jdGlvbiBnZXRUcmFuc2xhdGlvbihzZWxlY3Rpb24pe1xuICB2YXIgdHJhbnNmb3JtID0gc2VsZWN0aW9uLmF0dHIoJ3RyYW5zZm9ybScpXG4gIHZhciBbanVuaywgeHldID10cmFuc2Zvcm0uc3BsaXQoJ3RyYW5zbGF0ZSgnKVxuICB2YXIgW3gsIHldID0geHkuc3BsaXQoJywnKVxuICB5LCBqdW5rID0geS5zcGxpdCgnKScpXG4gIHJldHVybiBbcGFyc2VGbG9hdCh4KSwgcGFyc2VGbG9hdCh5KV1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxhc3NvKCBzZWxlY3Rpb24gKSB7XG4gIHZhclxuICBzdmcsIC8vIHN2ZyB0aGF0IGlzIHRhcmdldCBvZiBldmVudHNcbiAgb2JqZWN0Q29udGFpbmVyLCAvLyBjb250YWluZXIgd2hpY2ggaG91c2VzIG9iamVjdHMgd2UgYXJlIHNlbGVjdGluZyAoYWxsb3dzIGZvciB0cmFuc2Zvcm0gdG8gYmUgYXBwbGllZCB0byBsYXNzbylcbiAgb2JqZWN0Q2xhc3MsIC8vIGNsYXNzIG9mIG9iamVjdCB3ZSBhcmUgc2VsZWN0aW5nXG4gIG5hbWVzcGFjZT1cImQzc20tbGFzc29cIixcbiAgY2hhcnRDb250YWluZXIsXG4gIGNoYXJ0T2Zmc2V0LFxuICBvYmplY3RzT2Zmc2V0LFxuICBldmVudENhdGNoZXIsXG5cbiAgeFNjYWxlLCAvLyBvcHRpb25hbCBzY2FsZSBmb3IgdGhlIGxhc3NvIGN1cnJlbnRQb2ludHNcbiAgeVNjYWxlLCAvLyBvcHRpb25hbCBzY2FsZSBmb3IgdGhlIGxhc3NvIGN1cnJlbnRQb2ludHNcblxuICBhY3RpdmVRID0gZmFsc2UsIC8vIHdoZXRoZXIgb3Igbm90IGxhc3NvIGlzIGFjdGl2ZVxuXG4gIGN1cnJlbnRQb2ludHM9W10sIC8vIG1vdXNlIHBvaW50cyBmb3IgY3VycmVudCBsYXNzb1xuICBhbGxQb2ludHM9W10sIC8vIGxpc3Qgb2YgbGlzdHMgZm9yIGFsbCBwb2ludHMgb2YgbGFzc29zXG5cbiAgbGluZSA9IGQzLmxpbmUoKVxuICAueChmdW5jdGlvbihkLCBpKXtcbiAgICB2YXIgeFxuICAgIGlmICh4U2NhbGUgIT0gdW5kZWZpbmVkKSB7IHggPSB4U2NhbGUoZFswXSkgfVxuICAgIGVsc2Uge3ggPSBkWzBdfVxuICAgIHJldHVybiB4IC8vLSBjaGFydE9mZnNldFswXS8vIC0gb2JqZWN0c09mZnNldFswXVxuICB9KVxuICAueShmdW5jdGlvbihkLCBpKXtcbiAgICB2YXIgeVxuICAgIGlmICh5U2NhbGUgIT0gdW5kZWZpbmVkKSB7IHk9IHlTY2FsZShkWzFdKSB9XG4gICAgZWxzZSB7eSA9ICBkWzFdfVxuICAgIHJldHVybiB5Ly8gLSBjaGFydE9mZnNldFsxXS8vIC0gb2JqZWN0c09mZnNldFsxXVxuICB9KVxuICAuY3VydmUoZDMuY3VydmVMaW5lYXJDbG9zZWQpLFxuXG4gIGluc3RhbmNlPTAsICAgIC8vIGFuIGluZGVudGlmaWVyIGZvciB3aGljaCBpbnN0YW5jZSB0aGlzIGxhc3NvIGlzIHVuZGVyIHRoZSBjdXJyZW50IHN2Z1xuXG4gIHRpY2tEaXN0YW5jZSA9IDEwLFxuXG4gIC8vIHN0eWxlcyBmb3IgbGFzc28gcGF0aFxuICBjb2xvciA9ICcjMTdhMmI4JyxcbiAgYW5pbWF0aW9uUmF0ZSA9ICcxMHMnLFxuICBvcGFjaXR5PTAuMyxcbiAgZGFzaEFycmF5ID0gJzUsIDEwJyxcbiAgc3Ryb2tlID0gJ2JsYWNrJyxcbiAgc3Ryb2tlV2lkdGg9MixcblxuICAvLyBzdHlsZXMgZm9yIGxhc3NvZWQgb2JqZWN0c1xuICBsYXNzb2VkRmlsbCA9IFwid2hpdGVcIixcbiAgbGFzc29lZFN0cm9rZSA9ICdibGFjaycsXG4gIGxhc3NvZWRTdHJva2VXaWR0aCA9IDMsXG5cbiAgdHJhbnNpdGlvbkR1cmF0aW9uID0gMTAwMCxcbiAgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwXG5cbiAgdmFyIHBhdGhcblxuICBsYXNzby5zdmcgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN2ZyA9IF8sIGxhc3NvKSA6IHN2ZzsgfVxuICBsYXNzby5jaGFydENvbnRhaW5lciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY2hhcnRDb250YWluZXIgPSBfLCBsYXNzbykgOiBjaGFydENvbnRhaW5lcjsgfVxuICBsYXNzby5vYmplY3RDb250YWluZXIgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdENvbnRhaW5lciA9IF8sIGxhc3NvKSA6IG9iamVjdENvbnRhaW5lcjsgfVxuICBsYXNzby5vYmplY3RDbGFzcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q2xhc3MgPSBfLCBsYXNzbykgOiBvYmplY3RDbGFzczsgfVxuICBsYXNzby5uYW1lc3BhY2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG5hbWVzcGFjZSA9IF8sIGxhc3NvKSA6IG5hbWVzcGFjZTsgfVxuICBsYXNzby54U2NhbGUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhTY2FsZSA9IF8sIGxhc3NvKSA6IHhTY2FsZTsgfVxuICBsYXNzby55U2NhbGUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlTY2FsZSA9IF8sIGxhc3NvKSA6IHlTY2FsZTsgfVxuICBsYXNzby5hY3RpdmVRID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChhY3RpdmVRID0gXywgbGFzc28pIDogYWN0aXZlUTsgfVxuICBsYXNzby5jdXJyZW50UG9pbnRzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjdXJyZW50UG9pbnRzID0gXywgbGFzc28pIDogY3VycmVudFBvaW50czsgfVxuICBsYXNzby5hbGxQb2ludHMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGFsbFBvaW50cyA9IF8sIGxhc3NvKSA6IGFsbFBvaW50czsgfVxuICBsYXNzby5pbnN0YW5jZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaW5zdGFuY2UgPSBfLCBsYXNzbykgOiBpbnN0YW5jZTsgfVxuICBsYXNzby50aWNrRGlzdGFuY2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tEaXN0YW5jZSA9IF8sIGxhc3NvKSA6IHRpY2tEaXN0YW5jZTsgfVxuICBsYXNzby5jb2xvciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY29sb3IgPSBfLCBsYXNzbykgOiBjb2xvcjsgfVxuICBsYXNzby5hbmltYXRpb25SYXRlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChhbmltYXRpb25SYXRlID0gXywgbGFzc28pIDogYW5pbWF0aW9uUmF0ZTsgfVxuICBsYXNzby5vcGFjaXR5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvcGFjaXR5ID0gXywgbGFzc28pIDogb3BhY2l0eTsgfVxuICBsYXNzby5kYXNoQXJyYXkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRhc2hBcnJheSA9IF8sIGxhc3NvKSA6IGRhc2hBcnJheTsgfVxuICBsYXNzby5zdHJva2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN0cm9rZSA9IF8sIGxhc3NvKSA6IHN0cm9rZTsgfVxuICBsYXNzby5sYXNzb2VkRmlsbCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobGFzc29lZEZpbGwgPSBfLCBsYXNzbykgOiBsYXNzb2VkRmlsbDsgfVxuICBsYXNzby5sYXNzb2VkU3Ryb2tlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChsYXNzb2VkU3Ryb2tlID0gXywgbGFzc28pIDogbGFzc29lZFN0cm9rZTsgfVxuICBsYXNzby5sYXNzb2VkU3Ryb2tlV2lkdGggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGxhc3NvZWRTdHJva2VXaWR0aCA9IF8sIGxhc3NvKSA6IGxhc3NvZWRTdHJva2VXaWR0aDsgfVxuICBsYXNzby5ldmVudENhdGNoZXIgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGV2ZW50Q2F0Y2hlciA9IF8sIGxhc3NvKSA6IGV2ZW50Q2F0Y2hlcjsgfVxuXG4gIGxhc3NvLmRyYWcgPSBkcmFnXG4gIGxhc3NvLmRyYXcgPSBkcmF3XG4gIGxhc3NvLnRpY2sgPSB0aWNrXG4gIGxhc3NvLmRldGVjdCA9IGRldGVjdFxuICBsYXNzby50b2dnbGUgPSB0b2dnbGVcbiAgbGFzc28ucmVtb3ZlID0gcmVtb3ZlXG4gIGxhc3NvLnJlbmRlciA9IHJlbmRlclxuICBsYXNzby5rZXlGcmFtZXMgPSBrZXlGcmFtZXNcbiAgbGFzc28udXBkYXRlT2JqZWN0cyA9IHVwZGF0ZU9iamVjdHNcbiAgbGFzc28uYXBwbHlQYXRoQXR0cmlidXRlcyA9IGFwcGx5UGF0aEF0dHJpYnV0ZXNcbiAgbGFzc28uYXBwbHlPYmplY3RBdHRyaWJ1dGVzID0gYXBwbHlPYmplY3RBdHRyaWJ1dGVzXG5cbiAga2V5RnJhbWVzKClcblxuICBmdW5jdGlvbiBsYXNzbygpIHtcbiAgICAvLyBhZGQgYSBkYXNoIGFuaW1hdGlvbiBpZiBuZWVkZWRcbiAgICBpZiAoYWN0aXZlUSkgeyB0cmFuc2l0aW9uRHJhdygpIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHRvZ2dsZShzdGF0ZSkge1xuICAgIC8vIHVzZSBvcHRpb25hbCBwYXJhbSB0byBzZXQgc3RhdGUsIG90aGVyd2lzZSB0b2dnbGUgc3RhdGVcbiAgICBhY3RpdmVRID0gKHN0YXRlIT11bmRlZmluZWQpID8gc3RhdGUgOiAhYWN0aXZlUVxuICAgIGNoYXJ0T2Zmc2V0ID0gZ2V0VHJhbnNsYXRpb24oY2hhcnRDb250YWluZXIpXG4gICAgb2JqZWN0c09mZnNldCA9IGdldFRyYW5zbGF0aW9uKG9iamVjdENvbnRhaW5lcilcblxuICAgIGlmIChhY3RpdmVRKSB7XG4gICAgICBzdmcubm9kZSgpLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHJlbmRlciwgdHJ1ZSlcbiAgICB9IGVsc2Uge1xuICAgICAgc3ZnLm5vZGUoKS5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCByZW5kZXIsIHRydWUpXG4gICAgICByZW1vdmUoKVxuICAgIH1cblxuICB9XG5cbiAgZnVuY3Rpb24gZHJhdygpIHtcbiAgICBjaGFydE9mZnNldCA9IGdldFRyYW5zbGF0aW9uKGNoYXJ0Q29udGFpbmVyKVxuICAgIG9iamVjdHNPZmZzZXQgPSBnZXRUcmFuc2xhdGlvbihvYmplY3RDb250YWluZXIpXG5cbiAgICB2YXIgY29udGFpbmVyID0gc2FmZVNlbGVjdChvYmplY3RDb250YWluZXIsICdnJywgJ2xhc3NvLWNvbnRhaW5lcicpXG4gICAgdmFyIHBhdGhzID0gY29udGFpbmVyLnNlbGVjdEFsbCgncGF0aFtpbnN0YW5jZT1cIicraW5zdGFuY2UrJ1wiXScpXG5cbiAgICAvLyB1cGRhdGVcbiAgICBwYXRocyA9IHBhdGhzLmRhdGEoYWxsUG9pbnRzKVxuXG4gICAgLy8gcmVtb3ZlIGV4Y2Vzc1xuICAgIHZhciBwRXhpdCA9IHBhdGhzLmV4aXQoKS5yZW1vdmUoKVxuICAgIC8vIGFkZCBuZWVkZWQgcGF0aHNcbiAgICB2YXIgcEVudGVyID0gcGF0aHMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKVxuXG4gICAgLy8gbWVyZ2VcbiAgICBwYXRocyA9IHBhdGhzLm1lcmdlKHBFbnRlcilcblxuICAgIC8vIGFwcGx5XG4gICAgYXBwbHlQYXRoQXR0cmlidXRlcyhwYXRocylcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbW92ZSgpIHtcbiAgICB2YXIgY29udGFpbmVyID0gc2FmZVNlbGVjdChvYmplY3RDb250YWluZXIsICdnJywgJ2xhc3NvLWNvbnRhaW5lcicpXG4gICAgdmFyIHBhdGhzID0gY29udGFpbmVyLnNlbGVjdEFsbCgncGF0aFtpbnN0YW5jZT1cIicraW5zdGFuY2UrJ1wiXScpLnJlbW92ZSgpXG4gICAgY29udGFpbmVyLnJlbW92ZSgpXG4gICAgb2JqZWN0Q29udGFpbmVyLnNlbGVjdEFsbChvYmplY3RDbGFzcykuY2xhc3NlZChcImluLWxhc3NvXCIsIGZhbHNlKVxuICAgIHVwZGF0ZU9iamVjdHMoKVxuICB9XG5cbiAgZnVuY3Rpb24gcmVuZGVyKCBldmVudCApIHtcbiAgICAvLyBub3RoaW5nIGNhbiBpbnRlcmVmZXIgd2l0aCBkcmF3aW5nIHRoZSBsYXNzb1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgdmFyIGNvbnRhaW5lciA9IHNhZmVTZWxlY3Qob2JqZWN0Q29udGFpbmVyLCAnZycsICdsYXNzby1jb250YWluZXInKVxuXG4gICAgLypcbiAgICBlYWNoIHRpbWUgdGhlIHVzZXIgcHJlc3NlcyBkb3duLCB3aGlsZSB0aGUgc3RhdGUgaXMgYWN0aXZlLCB0aGUgbGFzc29cbiAgICB0aGUgbGFzc28gc2hvdWxkIG1ha2UgYSBzZXBlcmF0ZSBzZWdtZW50LlxuICAgICovXG4gICAgY3VycmVudFBvaW50cyA9IFtdO1xuXG4gICAgc3ZnLm5vZGUoKS5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBkcmFnKVxuICAgIHN2Zy5ub2RlKCkuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICBzdmcubm9kZSgpLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIGRyYWcpXG4gICAgICBhbGxQb2ludHMucHVzaChjdXJyZW50UG9pbnRzKVxuICAgICAgLy8gQlVHOiAgc29tZWhvdyB0aGlzIGlzIHB1c2hpbmcgY3VycmVudFBvaW50cyBuIHRpbWVzIHdoZXJlIG4gaXMgdGhlIG50aCBsYXNzbyBwYXRoIGZvciB0aGUgY3VycmVudCBpbnN0YW5jZVxuICAgICAgLy8gTk9URTogYWxsUG9pbnRzID0gdW5pcXVlKGFsbFBvaW50cykgaXMgYSB0ZW1wb3JhcnkgYW5kIGluZWZmaWNpZW50IGZpeFxuICAgICAgYWxsUG9pbnRzID0gdW5pcXVlKGFsbFBvaW50cylcbiAgICB9KVxuXG4gICAgcGF0aCA9IGNvbnRhaW5lci5hcHBlbmQoJ3BhdGgnKS5kYXRhKFtjdXJyZW50UG9pbnRzXSlcbiAgICBhcHBseVBhdGhBdHRyaWJ1dGVzKHBhdGgpXG4gIH1cblxuICBmdW5jdGlvbiB0cmFuc2l0aW9uRHJhdygpIHtcbiAgICB2YXIgY29udGFpbmVyID0gc2FmZVNlbGVjdChvYmplY3RDb250YWluZXIsICdnJywgJ2xhc3NvLWNvbnRhaW5lcicpXG4gICAgdmFyIHBhdGhzID0gY29udGFpbmVyLnNlbGVjdEFsbCgncGF0aFtpbnN0YW5jZT1cIicraW5zdGFuY2UrJ1wiXScpXG5cbiAgICAvLyB1cGRhdGVcbiAgICBwYXRocyA9IHBhdGhzLmRhdGEoYWxsUG9pbnRzKVxuXG4gICAgLy8gcmVtb3ZlIGV4Y2Vzc1xuICAgIHZhciBwRXhpdCA9IHBhdGhzLmV4aXQoKS5yZW1vdmUoKVxuICAgIC8vIGFkZCBuZWVkZWQgcGF0aHNcbiAgICB2YXIgcEVudGVyID0gcGF0aHMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKVxuXG4gICAgLy8gbWVyZ2VcbiAgICBwYXRocyA9IHBhdGhzLm1lcmdlKHBFbnRlcilcbiAgICAudHJhbnNpdGlvbigpLmR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbilcbiAgICAuZWFzZShlYXNlRnVuYylcbiAgICBhcHBseVBhdGhBdHRyaWJ1dGVzKHBhdGhzKVxuXG4gIH1cblxuICBmdW5jdGlvbiBhcHBseVBhdGhBdHRyaWJ1dGVzKHBhdGgpIHtcbiAgICBwYXRoXG4gICAgLmF0dHIoXCJjbGFzc1wiLCBoeXBlbmF0ZShuYW1lc3BhY2UsIFwibGFzc28tcGF0aFwiKSlcbiAgICAuc3R5bGUoJ29wYWNpdHknLCBvcGFjaXR5KVxuICAgIC5hdHRyKCdmaWxsJywgY29sb3IpXG4gICAgLmF0dHIoXCJkXCIsIGxpbmUpXG4gICAgLmF0dHIoJ2luc3RhbmNlJywgaW5zdGFuY2UpXG4gICAgLnN0eWxlKFwic3Ryb2tlLWRhc2hhcnJheVwiLCBkYXNoQXJyYXkpXG4gICAgLmF0dHIoXCJzdHJva2VcIiwgc3Ryb2tlKVxuICAgIC5hdHRyKFwic3Ryb2tlLXdpZHRoXCIsIHN0cm9rZVdpZHRoKVxuICAgIC5zdHlsZSgnYW5pbWF0aW9uJywgJ2xhc3NvRGFzaCAnK2FuaW1hdGlvblJhdGUrJyBsaW5lYXInKVxuICAgIC5zdHlsZShcImFuaW1hdGlvbi1pdGVyYXRpb24tY291bnRcIiwgXCJpbmZpbml0ZVwiKVxuICB9XG5cbiAgZnVuY3Rpb24gZHJhZyhldmVudCkge1xuICAgIC8qXG4gICAgZWZmZWN0aXZlbHkgY3JlYXRlIGEgbW91c2UgZG93biBhbmQgbW92ZSBldmVudCAod2hpY2ggbm9ybWFsbHkgaXMgaW50ZXBlcmF0ZWRcbiAgICBhcyAnZHJhZycgYnkgdGhlIGJyb3dzZXIpIGJ5IGR5bmFtaWNhbGx5IGFkZGluZyAvIHJlbW92aW5nIHRoaXMgZXZlbnQgb25cbiAgICBtb3VzZSBkb3duIC8gbW91c2UgdXAuXG4gICAgKi9cblxuICAgIGlmIChldmVudENhdGNoZXIgIT0gdW5kZWZpbmVkKSB7ZXZlbnRDYXRjaGVyLmRpc3BhdGNoKGh5cGVuYXRlKG5hbWVzcGFjZSxcImRyYWdcIikpfVxuICAgIC8vIGQzLmRpc3BhdGNoKGh5cGVuYXRlKG5hbWVzcGFjZSxcImRyYWdcIikpXG5cbiAgICBpZiAoZXZlbnQud2hpY2ggIT0gMSkge3JldHVybn0gLy8gZW5zdXJlcyBsZWZ0IG1vdXNlIGJ1dHRvbiBzZXRcbiAgICBkMy5ldmVudCA9IGV2ZW50XG4gICAgdmFyIHB0ID0gZDMubW91c2Uob2JqZWN0Q29udGFpbmVyLm5vZGUoKSk7XG4gICAgdmFyIHB0ID0gZDMubW91c2Uoc3ZnLm5vZGUoKSk7XG5cbiAgICBpZiAoeFNjYWxlICE9IHVuZGVmaW5lZCkge3B0WzBdID0geFNjYWxlLmludmVydChwdFswXSl9XG4gICAgaWYgKHlTY2FsZSAhPSB1bmRlZmluZWQpIHtwdFsxXSA9IHlTY2FsZS5pbnZlcnQocHRbMV0pfVxuICAgIHB0WzBdID0gcHRbMF0gLSBjaGFydE9mZnNldFswXSAtIG9iamVjdHNPZmZzZXRbMF1cbiAgICBwdFsxXSA9IHB0WzFdIC0gY2hhcnRPZmZzZXRbMV0gLSBvYmplY3RzT2Zmc2V0WzFdXG5cbiAgICAvKiBpZiB3ZSBoYXZlIGEgcG9pbnQgYWxyZWFkeSwgdGVzdCBpZiBpdCBwYXNzZXMgYSBtaW5pbXVtIGRpc3RhbmNlIHRvIHByZXZlbnQgb3ZlcndoZWxtaW5nIHdpdGggdG9vIG1hbnkgdGljayBmdW5jdGlvbnMgKi9cbiAgICBpZiAoY3VycmVudFBvaW50cy5sZW5ndGgpIHtcbiAgICAgIHZhciBsYXN0UHQgPSBjdXJyZW50UG9pbnRzW2N1cnJlbnRQb2ludHMubGVuZ3RoIC0gMV1cbiAgICAgIHZhciBhID0gW3B0WzBdLCBwdFsxXV0sIGIgPSBbbGFzdFB0WzBdLCBsYXN0UHRbMV1dXG5cbiAgICAgIGlmICh4U2NhbGUpIHtiWzBdID0geFNjYWxlKGJbMF0pOyBhWzBdID0geFNjYWxlKGFbMF0pfVxuICAgICAgaWYgKHlTY2FsZSkge2JbMV0gPSB5U2NhbGUoYlsxXSk7IGFbMV0gPSB5U2NhbGUoYVsxXSl9XG5cbiAgICAgIHZhciBkaXN0ID0gZXVjbGlkZWFuRGlzdGFuY2UoYiwgYSlcbiAgICAgIGlmIChkaXN0ID4gdGlja0Rpc3RhbmNlKSB7IHRpY2socHQpIH1cbiAgICB9XG4gICAgZWxzZSB7IHRpY2socHQpIH1cbiAgfVxuXG5cbiAgZnVuY3Rpb24gdGljayAocHQpIHtcbiAgICAvKlxuICAgIElmIGEgcG9pbnQgaXMgcHJvdmlkZWQgdXBkYXRlIGRhdGEgYW5kIG9iamVjdHMuXG4gICAgT3RoZXJ3aXNlIGp1c3QgY2FsbCBvbiBkYXRhIHdlIGFscmVhZHkgaGF2ZS5cblxuICAgIFdoeSBsaWtlIHRoaXM/OlxuICAgIDEuIGN1cnJlbnRQb2ludHMgaXMgY3VycmVudCBwb2ludHMgdG8gYWxsb3cgZGlzanVuY3QgbGFzc29zLCBjdXJyZW50UG9pbnRzIGlzIG9ubHkgcHVzaGVkIHRvXG4gICAgYWxsUG9pbnRzIGFmdGVyIG1vdXNldXAuXG4gICAgMi4gdG8gYWxsb3cgcmVuZGVyIG9mIG9iamVjdHMgaW4gdGhlIGxhc3NvIGNsYXNzIC8gdXBkYXRpbmcgdGhlIGRhdGEgbGlzdFxuICAgIGp1c3QgYnkgdG9nZ2xpbmcgdGhlIGJ1dHRvblxuICAgICovXG5cbiAgICBpZiAocHQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICBjdXJyZW50UG9pbnRzLnB1c2gocHQpO1xuICAgICAgcGF0aC5hdHRyKFwiZFwiLCBsaW5lKTtcbiAgICAgIGlmIChjdXJyZW50UG9pbnRzLmxlbmd0aCA8IDMpIHtyZXR1cm59IC8vIG5lZWQgYXQgbGVhc3QgMyBwb2ludHMgdG8gZGV0ZWN0IGFueXRoaW5nLlxuICAgICAgZGV0ZWN0KGFsbFBvaW50cy5jb25jYXQoW2N1cnJlbnRQb2ludHNdKSlcbiAgICB9IGVsc2Uge1xuICAgICAgZGV0ZWN0KGFsbFBvaW50cylcbiAgICB9XG4gIH1cblxuXG4gIGZ1bmN0aW9uIGRldGVjdChsYXNzb3MpIHtcbiAgICBpZiAobGFzc29zID09IHVuZGVmaW5lZCkge2xhc3NvcyA9IGFsbFBvaW50c31cbiAgICBvYmplY3RDb250YWluZXIuc2VsZWN0QWxsKG9iamVjdENsYXNzKS5lYWNoKGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgdmFyIGN1cnJlbnQgPSBkMy5zZWxlY3QodGhpcyksXG5cbiAgICAgIGJveCA9IGN1cnJlbnQuYWJzb2x1dGVQb3NpdGlvbigpLFxuICAgICAgLy8gYm94ID0gY3VycmVudC5yZWxhdGl2ZVBvc2l0aW9uVG8ob2JqZWN0Q29udGFpbmVyLm5vZGUoKSksXG5cbiAgICAgIGJveFB0cyA9IFtcbiAgICAgICAgW1xuICAgICAgICAgIGJveC5sZWZ0IC0gY2hhcnRPZmZzZXRbMF0gLSBvYmplY3RzT2Zmc2V0WzBdLFxuICAgICAgICAgIGJveC50b3AgLSBjaGFydE9mZnNldFsxXSAtIG9iamVjdHNPZmZzZXRbMV1cbiAgICAgICAgXSxcbiAgICAgICAgW1xuICAgICAgICAgIGJveC5yaWdodCAtIGNoYXJ0T2Zmc2V0WzBdIC0gb2JqZWN0c09mZnNldFswXSxcbiAgICAgICAgICBib3gudG9wIC0gY2hhcnRPZmZzZXRbMV0gLSBvYmplY3RzT2Zmc2V0WzFdXG4gICAgICAgIF0sXG4gICAgICAgIFtcbiAgICAgICAgICBib3gubGVmdCAtIGNoYXJ0T2Zmc2V0WzBdIC0gb2JqZWN0c09mZnNldFswXSxcbiAgICAgICAgICBib3guYm90dG9tIC0gY2hhcnRPZmZzZXRbMV0gLSBvYmplY3RzT2Zmc2V0WzFdXG4gICAgICAgIF0sXG4gICAgICAgIFtcbiAgICAgICAgICBib3gucmlnaHQgLSBjaGFydE9mZnNldFswXSAtIG9iamVjdHNPZmZzZXRbMF0sXG4gICAgICAgICAgYm94LmJvdHRvbSAtIGNoYXJ0T2Zmc2V0WzFdIC0gb2JqZWN0c09mZnNldFsxXVxuICAgICAgICBdXG4gICAgICBdXG5cbiAgICAgIGlmICh4U2NhbGUgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGJveFB0c1swXVswXSA9IHhTY2FsZS5pbnZlcnQoYm94UHRzWzBdWzBdKVxuICAgICAgICBib3hQdHNbMV1bMF0gPSB4U2NhbGUuaW52ZXJ0KGJveFB0c1sxXVswXSlcbiAgICAgICAgYm94UHRzWzJdWzBdID0geFNjYWxlLmludmVydChib3hQdHNbMl1bMF0pXG4gICAgICAgIGJveFB0c1szXVswXSA9IHhTY2FsZS5pbnZlcnQoYm94UHRzWzNdWzBdKVxuICAgICAgfVxuICAgICAgaWYgKHlTY2FsZSAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgYm94UHRzWzBdWzFdID0geVNjYWxlLmludmVydChib3hQdHNbMF1bMV0pXG4gICAgICAgIGJveFB0c1sxXVsxXSA9IHlTY2FsZS5pbnZlcnQoYm94UHRzWzFdWzFdKVxuICAgICAgICBib3hQdHNbMl1bMV0gPSB5U2NhbGUuaW52ZXJ0KGJveFB0c1syXVsxXSlcbiAgICAgICAgYm94UHRzWzNdWzFdID0geVNjYWxlLmludmVydChib3hQdHNbM11bMV0pXG4gICAgICB9XG5cblxuICAgICAgLypcbiAgICAgIGZsYWcgbmVlZGVkIGFzIHdlIGhhdmUgdG8gdGVzdCBtdWx0aXBsZSBsYXNzbyBzZWdtZW50cywgYW5kIGlmIHRoZSBwb2ludFxuICAgICAgaXMgbm90IGluIG9uZSBzZWdtZW50LCBpdCBkb2VzIG5vdCBtZWFuIGl0IGlzIG5vdCBpbiBhbnlcbiAgICAgICovXG4gICAgICB2YXIgaW5BbnlMYXNzb1EgPSBmYWxzZTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGFzc29zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBsYXNzb1BvaW50cyA9IGxhc3Nvc1tpXVxuICAgICAgICAvLyAubWFwKGZ1bmN0aW9uKHB0KXtcbiAgICAgICAgLy8gICB2YXIgeCwgeSA9IHB0XG4gICAgICAgIC8vICAgaWYgKHhTY2FsZSE9dW5kZWZpbmVkKSB7eCA9IHhTY2FsZSh4KX1cbiAgICAgICAgLy8gICBpZiAoeVNjYWxlIT11bmRlZmluZWQpIHt5ID0geVNjYWxlKHkpfVxuICAgICAgICAvLyAgIHJldHVybiBbeCwgeV1cbiAgICAgICAgLy8gfSlcbiAgICAgICAgdmFyIGJveEluTGFzc29RID0gYm94UHRzLmV2ZXJ5KGNvb3JkID0+IGQzLnBvbHlnb25Db250YWlucyhsYXNzb1BvaW50cywgY29vcmQpKVxuXG4gICAgICAgIGlmIChib3hJbkxhc3NvUSkgeyBpbkFueUxhc3NvUSA9IHRydWU7IH0gLy8gb25seSB1cGRhdGUgZmxhZyBpbiB0aGUgcG9zaXRpdmUgY2FzZS5cbiAgICAgIH1cblxuICAgICAgY3VycmVudC5jbGFzc2VkKCdpbi1sYXNzbycsIGluQW55TGFzc29RKVxuICAgICAgY3VycmVudC5jbGFzc2VkKCdpbi1sYXNzby0nK2luc3RhbmNlLCBpbkFueUxhc3NvUSlcbiAgICB9KVxuXG4gICAgdXBkYXRlT2JqZWN0cygpXG4gICAgcmV0dXJuIG9iamVjdENvbnRhaW5lci5zZWxlY3RBbGwoJy5pbi1sYXNzby0nK2luc3RhbmNlKVxuICB9XG5cblxuXG4gIGZ1bmN0aW9uIHVwZGF0ZU9iamVjdHMoKSB7XG4gICAgb2JqZWN0Q29udGFpbmVyLnNlbGVjdEFsbChvYmplY3RDbGFzcykuZWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgICAgYXBwbHlPYmplY3RBdHRyaWJ1dGVzKHQsIHQuY2xhc3NlZCgnaW4tbGFzc28nKSlcbiAgICB9KVxuICB9XG5cbiAgZnVuY3Rpb24gYXBwbHlPYmplY3RBdHRyaWJ1dGVzKG9iaiwgc2V0USkge1xuICAgIHZhclxuICAgIHByZUxhc3NvRmlsbCA9IG9iai5hdHRyKCdfcHJlX2xhc3NvX2ZpbGwnKSxcbiAgICBwcmVMYXNzb1N0cm9rZSA9IG9iai5hdHRyKCdfcHJlX2xhc3NvX3N0cm9rZScpLFxuICAgIHByZUxhc3NvU3Ryb2tlV2lkdGggPSBvYmouYXR0cignX3ByZV9sYXNzb19zdHJva2Utd2lkdGgnKVxuXG4gICAgaWYgKHNldFEpIHtcbiAgICAgIG9iai5jbGFzc2VkKFwiaW4tbGFzc29cIiwgdHJ1ZSlcbiAgICAgIG9iai5jbGFzc2VkKCdpbi1sYXNzby0nK2luc3RhbmNlLCB0cnVlKVxuICAgICAgaWYgKHByZUxhc3NvRmlsbCA9PSB1bmRlZmluZWQpIHsgb2JqLmF0dHIoJ19wcmVfbGFzc29fZmlsbCcsIG9iai5hdHRyKCdmaWxsJykpIH1cbiAgICAgIGlmIChwcmVMYXNzb1N0cm9rZSA9PSB1bmRlZmluZWQpIHsgb2JqLmF0dHIoJ19wcmVfbGFzc29fc3Ryb2tlJywgb2JqLmF0dHIoJ3N0cm9rZScpKSB9XG4gICAgICBpZiAocHJlTGFzc29TdHJva2VXaWR0aCA9PSB1bmRlZmluZWQpIHsgb2JqLmF0dHIoJ19wcmVfbGFzc29fc3Ryb2tlLXdpZHRoJywgb2JqLmF0dHIoJ3N0cm9rZS13aWR0aCcpKSB9XG5cbiAgICAgIG9ialxuICAgICAgLy9CVUc6IHdoZW4gLnJhaXNlKClcbiAgICAgIC5hdHRyKCdmaWxsJywgbGFzc29lZEZpbGwpXG4gICAgICAuYXR0cignc3Ryb2tlJywgbGFzc29lZFN0cm9rZSlcbiAgICAgIC5hdHRyKCdzdG9rZS13aWR0aCcsIGxhc3NvZWRTdHJva2VXaWR0aClcblxuICAgIH0gZWxzZSB7XG4gICAgICBvYmouY2xhc3NlZChcImluLWxhc3NvXCIsIGZhbHNlKVxuICAgICAgb2JqLmNsYXNzZWQoJ2luLWxhc3NvLScraW5zdGFuY2UsIGZhbHNlKVxuICAgICAgaWYgKHByZUxhc3NvRmlsbCAhPSB1bmRlZmluZWQpIHsgb2JqLmF0dHIoJ2ZpbGwnLCBwcmVMYXNzb0ZpbGwpIH1cbiAgICAgIGlmIChwcmVMYXNzb1N0cm9rZSAhPSB1bmRlZmluZWQpIHsgb2JqLmF0dHIoJ3N0cm9rZScsIHByZUxhc3NvU3Ryb2tlKSB9XG4gICAgICBpZiAocHJlTGFzc29TdHJva2VXaWR0aCAhPSB1bmRlZmluZWQpIHsgb2JqLmF0dHIoJ3N0cm9rZS13aWR0aCcsIHByZUxhc3NvU3Ryb2tlV2lkdGgpIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBrZXlGcmFtZXMoKSB7XG4gICAgdmFyIHN0eWxlID1cbiAgICBkMy5zZWxlY3QoXCJodG1sXCIpLnNlbGVjdCgnc3R5bGUuJytoeXBlbmF0ZShuYW1lc3BhY2UsXCJsYXNzby1kYXNoXCIpKVxuICAgIGlmIChzdHlsZS5lbXB0eSgpKSB7XG4gICAgICBkMy5zZWxlY3QoXCJodG1sXCIpLmFwcGVuZCgnc3R5bGUnKVxuICAgICAgLmNsYXNzZWQoaHlwZW5hdGUobmFtZXNwYWNlLFwibGFzc28tZGFzaFwiKSwgdHJ1ZSlcbiAgICAgIC5odG1sKFwiQGtleWZyYW1lcyBsYXNzb0Rhc2gge3RvIHsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDEwMDA7fX1cIilcbiAgICB9XG5cbiAgfVxuICByZXR1cm4gbGFzc29cbn1cbiIsImltcG9ydCB7Z2V0Q29udGFpbmluZ1NWR30gZnJvbSBcIi4vaGVscGVyc1wiO1xuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEQzIEVYVEVOU0lPTlMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbi8qKlxuKiBSZWN1cnNpdmVseSBhc2NlbmRzIHBhcmVudHMgb2Ygc2VsZWN0aW9uIHVudGlsIGl0IGZpbmRzIGFuIHN2ZyB0YWdcbiogQGZ1bmN0aW9uIGQzLnNlbGVjdGlvbi50aGlzU1ZHXG4qIEBhdWdtZW50cyBkMy5zZWxlY3Rpb25cbiogQHJldHVybnMge0VsZW1lbnR9IHdoaWNoIGlzIHRoZSBzdmcgdGFnLCBub3QgdGhlIGQzIHNlbGVjdGlvbiBvZiB0aGF0IHRhZ1xuKi9cbmQzLnNlbGVjdGlvbi5wcm90b3R5cGUudGhpc1NWRyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gZ2V0Q29udGFpbmluZ1NWRyh0aGlzLm5vZGUoKSk7IH1cblxuXG4vKipcbiogSGVscGVyIGZvciBnZXR0aW5nIGFic29sdXRlIHBvc2l0aW9uIG9mIHRoZSBtb3VzZVxuKiBAZnVuY3Rpb24gZDMubW91c2UuYWJzb2x1dGVcbiogQGF1Z21lbnRzIGQzLm1vdXNlXG4qIEByZXR1cm5zIHtudW1iZXJbXX0gW3gsIHldIGFzIHRoZXkgcmVsYXRlIHRvIGBodG1sYCBub3QgdG8gbG9jYWwgc2NvcGUuXG4qL1xuZDMubW91c2UuYWJzb2x1dGUgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGh0bWwgPSBkMy5zZWxlY3QoJ2h0bWwnKS5ub2RlKClcbiAgdmFyIFt4LCB5XSA9IHRoaXMoaHRtbClcbiAgcmV0dXJuIFt4LCB5XVxufVxuXG5cbi8qKlxuKiBHZXRzIHBvc2l0aW9uIG9mIHRoZSBzZWxlY3Rpb24gaW4gcmVsYXRpb24gdG8gdGhlIGNvbnRhaW5pbmcgc3ZnXG4qIEBzZWV7QGxpbmsgZ2V0Q29udGFpbmluZ1NWR31cbiogQGZ1bmN0aW9uIGQzLnNlbGVjdGlvbi5hYnNvbHV0ZVBvc2l0aW9uXG4qIEBhdWdtZW50cyBkMy5zZWxlY3Rpb25cbiogQHJldHVybnMge09iamVjdH0gd2l0aCBzdHJ1Y3R1cmUgc2ltaWxhciB0byBnZXRCb3VuZGluZ0NsaWVudFJlY3QsIGUuZy5cbiogdG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0LCBoZWlnaHQsIHdpZHRoXG4qL1xuZDMuc2VsZWN0aW9uLnByb3RvdHlwZS5hYnNvbHV0ZVBvc2l0aW9uID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGVsZW1lbnQgPSB0aGlzLm5vZGUoKTtcbiAgICB2YXIgZWxlbWVudFBvc2l0aW9uID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB2YXIgY29udGFpbmVyU1ZHID0gZ2V0Q29udGFpbmluZ1NWRyhlbGVtZW50KVxuICAgIHZhciBzdmdQb3NpdGlvbiA9IGNvbnRhaW5lclNWRy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHRvcDogICAgZWxlbWVudFBvc2l0aW9uLnRvcCAgICAtIHN2Z1Bvc2l0aW9uLnRvcCxcbiAgICAgICAgbGVmdDogICBlbGVtZW50UG9zaXRpb24ubGVmdCAgIC0gc3ZnUG9zaXRpb24ubGVmdCxcbiAgICAgICAgYm90dG9tOiBlbGVtZW50UG9zaXRpb24uYm90dG9tIC0gc3ZnUG9zaXRpb24udG9wLFxuICAgICAgICByaWdodDogIGVsZW1lbnRQb3NpdGlvbi5yaWdodCAgLSBzdmdQb3NpdGlvbi5sZWZ0LFxuICAgICAgICBoZWlnaHQ6IGVsZW1lbnRQb3NpdGlvbi5oZWlnaHQsXG4gICAgICAgIHdpZHRoOiAgZWxlbWVudFBvc2l0aW9uLndpZHRoXG4gICAgfTtcblxufVxuXG5cbmQzLnNlbGVjdGlvbi5wcm90b3R5cGUucmVsYXRpdmVQb3NpdGlvblRvID0gZnVuY3Rpb24oY29udGFpbmVyKSB7XG4gICAgdmFyIGVsZW1lbnQgPSB0aGlzLm5vZGUoKTtcbiAgICB2YXIgZWxlbWVudFBvc2l0aW9uID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB2YXIgY29udGFpbmVyU1ZHID0gY29udGFpbmVyXG4gICAgdmFyIHN2Z1Bvc2l0aW9uID0gY29udGFpbmVyU1ZHLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdG9wOiAgICBlbGVtZW50UG9zaXRpb24udG9wICAgIC0gc3ZnUG9zaXRpb24udG9wLFxuICAgICAgICBsZWZ0OiAgIGVsZW1lbnRQb3NpdGlvbi5sZWZ0ICAgLSBzdmdQb3NpdGlvbi5sZWZ0LFxuICAgICAgICBib3R0b206IGVsZW1lbnRQb3NpdGlvbi5ib3R0b20gLSBzdmdQb3NpdGlvbi50b3AsXG4gICAgICAgIHJpZ2h0OiAgZWxlbWVudFBvc2l0aW9uLnJpZ2h0ICAtIHN2Z1Bvc2l0aW9uLmxlZnQsXG4gICAgICAgIGhlaWdodDogZWxlbWVudFBvc2l0aW9uLmhlaWdodCxcbiAgICAgICAgd2lkdGg6ICBlbGVtZW50UG9zaXRpb24ud2lkdGhcbiAgICB9O1xuXG59XG4iLCIvLyBJbXBvcnQgc3R5bGVzIChhdXRvbWF0aWNhbGx5IGluamVjdCBpbnRvIDxoZWFkPikuXG4vLyBpbXBvcnQgJy4uL3N0eWxlcy9tYWluLmNzcyc7XG5pbXBvcnQge2F4aXN9IGZyb20gJy4vbW9kdWxlcy9heGlzJztcbmltcG9ydCB7YmFyfSBmcm9tICcuL21vZHVsZXMvYmFyJztcbmltcG9ydCB7YnViYmxlSGVhdG1hcH0gZnJvbSAnLi9tb2R1bGVzL2J1YmJsZS1oZWF0bWFwJztcbmltcG9ydCB7aGVhdG1hcH0gZnJvbSAnLi9tb2R1bGVzL2hlYXRtYXAnO1xuaW1wb3J0IHtib3h3aGlza2VyfSBmcm9tICcuL21vZHVsZXMvYm94LXdoaXNrZXInO1xuaW1wb3J0IHtjb2xvckZ1bmN0aW9ufSBmcm9tICcuL21vZHVsZXMvY29sb3ItZnVuY3Rpb24nO1xuaW1wb3J0IHtkYXRhdG9nZ2xlfSBmcm9tICcuL21vZHVsZXMvZGF0YS10b2dnbGUnO1xuaW1wb3J0IHtncm91cGluZ1NwYWNlcn0gZnJvbSAnLi9tb2R1bGVzL2dyb3VwaW5nLXNwYWNlcic7XG5pbXBvcnQge3Rvb2x0aXB9IGZyb20gJy4vbW9kdWxlcy90b29sdGlwJztcbmltcG9ydCB7c2NhdHRlcn0gZnJvbSAnLi9tb2R1bGVzL3NjYXR0ZXInO1xuaW1wb3J0IHtwbG90Wm9vbX0gZnJvbSAnLi9tb2R1bGVzL3Bsb3Qtem9vbSc7XG5pbXBvcnQge211bHRpUGxvdFpvb219IGZyb20gJy4vbW9kdWxlcy9tdWx0aS1wbG90LXpvb20nO1xuaW1wb3J0IHt2aW9saW59IGZyb20gJy4vbW9kdWxlcy92aW9saW4nO1xuaW1wb3J0IHtudW1lcmljTGVnZW5kfSBmcm9tICcuL21vZHVsZXMvbnVtZXJpYy1sZWdlbmQnO1xuaW1wb3J0IHtjYXRlZ29yaWNMZWdlbmR9IGZyb20gJy4vbW9kdWxlcy9jYXRlZ29yaWNhbC1sZWdlbmQnO1xuaW1wb3J0IHtsYXNzb30gZnJvbSAnLi9tb2R1bGVzL2xhc3NvJztcbmltcG9ydCB7bGFzc29XaWRnZXR9IGZyb20gJy4vbW9kdWxlcy9sYXNzby13aWRnZXQnO1xuaW1wb3J0IHtzZWxlY3RGaWx0ZXJ9IGZyb20gJy4vbW9kdWxlcy9zZWxlY3QtZmlsdGVyJztcbmltcG9ydCB7dXBzZXR9IGZyb20gJy4vbW9kdWxlcy91cHNldCc7XG5pbXBvcnQge2ZpbHRlclRhYmxlfSBmcm9tICcuL21vZHVsZXMvZmlsdGVyLXRhYmxlJztcblxuaW1wb3J0IHt1bmlxdWVFbGVtZW50cywgZ2V0VHJhbnNsYXRpb24sIG1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2UsIHRpY2tSYW5nZSxcbnF1YXJ0aWxlcywgZXh0cmFjdFZpb2xpblZhbHVlcywgaHlwZW5hdGUsIHJvdW5kLCBnZXRDb250YWluaW5nU1ZHLFxuaW50ZXJwb2xhdGVDb2xvcnMsIHRydW5jYXRlVGV4dCwgc2FmZVNlbGVjdH0gZnJvbSAnLi9tb2R1bGVzL2hlbHBlcnMnO1xuXG5pbXBvcnQge1xuICBhbGwsIHRhbGx5LCBoYXNRLCBmaXJzdCwgbGFzdCwgdG90YWwsIHVuaXF1ZSwgZ2V0LCBsaXN0T2ZMaXN0c1EsXG4gIGN1dCwgZ3JvdXBCeSwgYXJyYXlFcXVhbHMsIGVsZW1lbnRzQXRMZXZlbHMsIG51bWJlck9mRWxlbWVudHMsXG4gIGZsYXR0ZW4sIHdoaWNoQmluXG59IGZyb20gJy4vbW9kdWxlcy9hcnJheS1mdW5jdGlvbnMnO1xuXG5cbmltcG9ydCB7XG4gIHNldHVwU3RhbmRhcmRDaGFydENvbnRhaW5lcnMsIGxvZyBhcyBteUxvZywgd2FybiwgaW5mbywgZXJyb3IsXG4gIGNvbnNvbGVHcm91cCwgY29uc29sZUdyb3VwRW5kLCByZXNpemVEZWJvdW5jZVxufSBmcm9tICcuL21vZHVsZXMvdXRpbHMnO1xuXG4vLyAvKiogQG1vZHVsZSBkM3NtICovXG52YXIgZDNzbSA9IHt9O1xuZDNzbS5heGlzID0gYXhpcztcbmQzc20uYmFyID0gYmFyO1xuZDNzbS5idWJibGVIZWF0bWFwID0gYnViYmxlSGVhdG1hcDtcbmQzc20uaGVhdG1hcCA9IGhlYXRtYXA7XG5kM3NtLmJveHdoaXNrZXIgPSBib3h3aGlza2VyO1xuZDNzbS5jb2xvckZ1bmN0aW9uID0gY29sb3JGdW5jdGlvbjtcbmQzc20uZGF0YXRvZ2dsZSA9IGRhdGF0b2dnbGU7XG5kM3NtLmdyb3VwaW5nU3BhY2VyID0gZ3JvdXBpbmdTcGFjZXI7XG5kM3NtLnRvb2x0aXAgPSB0b29sdGlwO1xuZDNzbS5zY2F0dGVyID0gc2NhdHRlcjtcbmQzc20ucGxvdFpvb20gPSBwbG90Wm9vbTtcbmQzc20ubXVsdGlQbG90Wm9vbSA9IG11bHRpUGxvdFpvb207XG5kM3NtLnZpb2xpbiA9IHZpb2xpbjtcbmQzc20ubnVtZXJpY0xlZ2VuZCA9IG51bWVyaWNMZWdlbmQ7XG5kM3NtLmNhdGVnb3JpY0xlZ2VuZCA9IGNhdGVnb3JpY0xlZ2VuZDtcbmQzc20ubGFzc28gPSBsYXNzbztcbmQzc20ubGFzc29XaWRnZXQgPSBsYXNzb1dpZGdldDtcbmQzc20uc2VsZWN0RmlsdGVyID0gc2VsZWN0RmlsdGVyO1xuZDNzbS51cHNldCA9IHVwc2V0O1xuZDNzbS5maWx0ZXJUYWJsZSA9IGZpbHRlclRhYmxlO1xuXG5kM3NtLnVuaXF1ZUVsZW1lbnRzID0gdW5pcXVlRWxlbWVudHM7XG5kM3NtLmdldFRyYW5zbGF0aW9uID0gZ2V0VHJhbnNsYXRpb247XG5kM3NtLm1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2UgPSBtb2RpZnlIZXhpZGVjaW1hbENvbG9yTHVtaW5hbmNlO1xuZDNzbS50aWNrUmFuZ2UgPSB0aWNrUmFuZ2U7XG5kM3NtLnF1YXJ0aWxlcyA9IHF1YXJ0aWxlcztcbmQzc20uZXh0cmFjdFZpb2xpblZhbHVlcyA9IGV4dHJhY3RWaW9saW5WYWx1ZXM7XG5kM3NtLmh5cGVuYXRlID0gaHlwZW5hdGU7XG5kM3NtLnJvdW5kID0gcm91bmQ7XG5kM3NtLmdldENvbnRhaW5pbmdTVkcgPSBnZXRDb250YWluaW5nU1ZHO1xuZDNzbS5pbnRlcnBvbGF0ZUNvbG9ycyA9IGludGVycG9sYXRlQ29sb3JzO1xuZDNzbS50cnVuY2F0ZVRleHQgPSB0cnVuY2F0ZVRleHQ7XG5kM3NtLnNhZmVTZWxlY3QgPSBzYWZlU2VsZWN0O1xuXG5kM3NtLndoaWNoQmluID0gd2hpY2hCaW47XG5kM3NtLnVuaXF1ZSA9IHVuaXF1ZTtcbmQzc20uZmxhdHRlbiA9IGZsYXR0ZW47XG5cbmQzc20uc2V0dXBTdGFuZGFyZENoYXJ0Q29udGFpbmVycyA9IHNldHVwU3RhbmRhcmRDaGFydENvbnRhaW5lcnM7XG5kM3NtLmxvZyA9IG15TG9nO1xuZDNzbS53YXJuID0gd2FybjtcbmQzc20uaW5mbyA9IGluZm87XG5kM3NtLmVycm9yID0gZXJyb3I7XG5kM3NtLmNvbnNvbGVHcm91cCA9IGNvbnNvbGVHcm91cDtcbmQzc20uY29uc29sZUdyb3VwRW5kID0gY29uc29sZUdyb3VwRW5kO1xuZDNzbS5yZXNpemVEZWJvdW5jZSA9IHJlc2l6ZURlYm91bmNlO1xuXG5kM3NtLmRlYnVnUSA9IGZhbHNlXG5cblxuXG4vLyBJbXBvcnQgYSBsb2dnZXIgZm9yIGVhc2llciBkZWJ1Z2dpbmdcbi8vIGltcG9ydCBkZWJ1ZyBmcm9tICdkZWJ1Zyc7XG4vLyBjb25zdCBsb2cgPSBkZWJ1ZygnYXBwOmxvZycpO1xuXG4vLyBUaGUgbG9nZ2VyIHNob3VsZCBvbmx5IGJlIGRpc2FibGVkIGlmIHdlJ3JlIG5vdCBpbiBwcm9kdWN0aW9uLlxuLy8gaWYgKEVOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4vLyAgIC8vIEVuYWJsZSB0aGUgbG9nZ2VyLlxuLy8gICBkZWJ1Zy5lbmFibGUoJyonKTtcbi8vICAgbG9nKCdMb2dnaW5nIGlzIGVuYWJsZWQhJyk7XG4vL1xuLy8gICAvLyBFbmFibGUgTGl2ZVJlbG9hZFxuLy8gICBkb2N1bWVudC53cml0ZShcbi8vICAgICAnPHNjcmlwdCBzcmM9XCJodHRwOi8vJ1xuLy8gICAgICsgKGxvY2F0aW9uLmhvc3QgfHwgJ2xvY2FsaG9zdCcpLnNwbGl0KCc6JylbMF1cbi8vICAgICArICc6MzU3MjkvbGl2ZXJlbG9hZC5qcz9zbmlwdmVyPTFcIj48Lydcbi8vICAgICArICdzY3JpcHQ+J1xuLy8gICApO1xuLy8gfSBlbHNlIHtcbi8vICAgZGVidWcuZGlzYWJsZSgpO1xuLy8gfVxuXG53aW5kb3cuZDNzbSA9IGQzc207XG5cbmV4cG9ydCBkZWZhdWx0IGQzc21cbiIsImltcG9ydCB7XG4gIGh5cGVuYXRlLCBzYWZlU2VsZWN0LCBleHRyYWN0VmlvbGluVmFsdWVzLFxuICB0aWNrUmFuZ2UsIG1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2UsIHRydW5jYXRlVGV4dCxcbiAgdHJ1bmNhdGVTdHJpbmcsXG4gIHJvdW5kXG59IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQge3NldHVwQ29udGFpbmVyLCBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0LCBjYWxjdWxhdGVXaWR0aE9mU3BhY2VyfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7dW5pcXVlLCBoYXNRLCBmbGF0dGVufSBmcm9tICcuL2FycmF5LWZ1bmN0aW9ucyc7XG5pbXBvcnQge2dyb3VwaW5nU3BhY2VyfSBmcm9tICcuL2dyb3VwaW5nLXNwYWNlcic7XG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBWElTICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXhpc1xuICpcbiAqIHtAbGluayBodHRwczovL3N1bW5ldXJvbi5naXRsYWIuaW8vZDNzbS9kZW1vcy9heGVzL2luZGV4Lmh0bWwgRGVtb31cbiAqIEBjb25zdHJ1Y3RvciBheGlzXG4gKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gc2VsZWN0aW9uXG4gKiBAbmFtZXNwYWNlIGF4aXNcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gYXhpc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYXhpcyAoIHNlbGVjdGlvbiApIHtcbiAgdmFyXG4gIC8qKlxuICAqIFRoZSBvcmllbnRhdGlvbiBvZiB0aGUgYXhpc1xuICAqIChzZWUge0BsaW5rIGF4aXMjb3JpZW50fSlcbiAgKiBAcGFyYW0ge3N0cmluZ30gW29yaWVudD0nYm90dG9tJ11cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb3JpZW50ID0gJ2JvdHRvbScsICAgICAgIC8vIGRpcmVjdGlvbiBvZiB0aGUgYXhpc1xuXG4gIC8qKlxuICAqIEFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSBheGlzIGluXG4gICogKHNlZSB7QGxpbmsgYXhpcyNzcGFjZVh9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbc3BhY2VYPTBdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNwYWNlWD0wLFxuICAvKipcbiAgKiBBbW91bnQgb2YgdmVydGljYWwgc3BhY2UgKGluIHBpeGVscykgYXZhaWJsZSB0byByZW5kZXIgdGhlIGF4aXMgaW5cbiAgKiAoc2VlIHtAbGluayBheGlzLnNwYWNlWX0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZVk9MF1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VZPTAsXG5cblxuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0byBhbGxvdyBheGlzIHRvIHJlbmRlciBlbGVtZW50cyBwYXNzIHRoZSBtYWluIHNwYXRpYWwgZGltZW5zaW9uXG4gICogZ2l2ZW4gdGhlIG9yaWVudGF0aW9uIChzZWUge0BsaW5rIGF4aXMjb3JpZW50fSksIHdoZXJlIHtAbGluayBheGlzI29yaWVudH09XCJib3R0b21cIiBvciB7QGxpbmsgYXhpcyNvcmllbnR9PVwidG9wXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGF4aXMjc3BhY2VYfSBhbmQgd2hlcmUge0BsaW5rIGF4aXMjb3JpZW50fT1cImxlZnRcIiBvciB7QGxpbmsgYXhpcyNvcmllbnR9PVwicmlnaHRcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgYXhpcyNzcGFjZVl9XG4gICogQHBhcmFtIHtib29sZWFufSBbb3ZlcmZsb3dRPWZhbHNlXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvdmVyZmxvd1EgPSBmYWxzZSwgICAgLy8gd2hldGhlciBvciBub3QgdG8gYWxsb3cgb3ZlcmZsb3dcbiAgLyoqXG4gICogV2hldGhlciBvciBub3QgdGhlIGF4aXMgbGFiZWxzIGFyZSBmb3IgY2F0ZWdvcmljYWwgZGF0YS4gSWYgZmFsc2UsXG4gICogd2lsbCB1c2Uge0BsaW5rIGF4aXMjc2NhbGV9IHRvIHBvc2l0aW9uIHRpY2tzLlxuICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2NhdGVnb3JpY2FsUT1mYWxzZV1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgY2F0ZWdvcmljYWxRID0gZmFsc2UsIC8vIHdoZXRoZXIgb3Igbm90IHRoZSBheGlzIGlzIHNob3dpbmcgdmFsdWVzIG9yIGdyb3Vwc1xuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0aGUgYXhpcyB0aWNrcyBzaG91bGQgaGF2ZSBndWlkZWxpbmVzXG4gICogQHBhcmFtIHtib29sZWFufSBbY2F0ZWdvcmljYWxRPWZhbHNlXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBndWlkZUxpbmVzUSA9IGZhbHNlLCAgICAvLyB3aGV0aGVyIG9yIG5vdCB0byBhbGxvdyBvdmVyZmxvd1xuXG5cbiAgLyoqXG4gICogSG93IHRvIGdyb3VwIHRoZSB0aWNrIGxhYmVsc1xuICAqIEBwYXJhbSB7QXJyYXlbXX0gW2dyb3VwaW5nPXVuZGVmaW5lZF0gbGlzdCBvZiBwdXRhdGl2ZWx5IG90aGVyIGxpc3RzLCB3aGljaCBzaG91bGQgY29ycmVzcG9uZCB0byB0aWNrTGFiZWxzXG4gICogd2lsbCBzcGFjZSB0aWNrIGxhYmVscyBpbiBuZXN0ZWQgbGlzdHMgY2xvc2VyIHRvZ2V0aGVyIHRoYW4gb3V0ZXIgbGlzdHNcbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZ3JvdXBpbmcsXG5cbiAgLyoqXG4gICogVGhlIHNjYWxlIGZvciB3aGljaCBub24tY2F0ZWdvcmlhbCAoc2VlIHtAbGluayBheGlzI2NhdGVnb3JpY2FsUX0pIHRpY2tzIHNob3VsZCBiZSBzcGFjZWRcbiAgKiBAcGFyYW0ge2QzLnNjYWxlfSBbc2NhbGU9ZDMuc2NhbGVMaW5lYXJdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG5cbiAgc2NhbGUgPSBkMy5zY2FsZUxpbmVhcigpLFxuICAvKipcbiAgKiBUaGUgcGFkZGluZyBmb3IgdGhlIGRvbWFpbiBvZiB0aGUgc2NhbGUgKHNlZSB7QGxpbmsgYXhpcyNzY2FsZX0pXG4gICogQHBhcmFtIHtkMy5zY2FsZX0gW3NjYWxlPWQzLnNjYWxlTGluZWFyXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBkb21haW5QYWRkaW5nID0gMC41LFxuXG5cbiAgLyoqXG4gICogRGVmYXVsdCBzcGFjZSBmb3IgdGhlIHNwYWNlciAocGVyY2VudGFnZSkgb2YgbWFpbiBkaW1lbnNpb24gZ2l2ZW4gdGhlIG9yaWVudGF0aW9uXG4gICogKHNlZSB7QGxpbmsgYXhpcyNvcmllbnR9KSwgd2hlcmUge0BsaW5rIGF4aXMjb3JpZW50fT1cImJvdHRvbVwiIG9yIHtAbGluayBheGlzI29yaWVudH09XCJ0b3BcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgYXhpcyNzcGFjZVh9IGFuZCB3aGVyZSB7QGxpbmsgYXhpcyNvcmllbnR9PVwibGVmdFwiIG9yIHtAbGluayBheGlzI29yaWVudH09XCJyaWdodFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayBheGlzI3NwYWNlWX1iZXR3ZWVuIHRpY2tzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtvYmplY3RTcGFjZXI9MC4wNV1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0U3BhY2VyID0gMC4wNSxcbiAgLyoqXG4gICogVGhlIG1pbmltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmUgaWYge0BsaW5rIGF4aXMjY2F0ZWdvcmljYWxRfSBpcyBzZXQgdG8gdHJ1ZVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbbWluT2JqZWN0U2l6ZT0xNV1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbWluT2JqZWN0U2l6ZSA9IDE1LFxuICAvKipcbiAgKiBUaGUgbWF4aW11bSBzaXplIHRoYXQgYW4gb2JqZWN0IGNhbiBiZSBpZiB7QGxpbmsgYXhpcyNjYXRlZ29yaWNhbFF9IGlzIHNldCB0byB0cnVlXG4gICogQHBhcmFtIHtudW1iZXJ9IFttYXhPYmplY3RTaXplPTE1XVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBtYXhPYmplY3RTaXplID0gNTAsXG5cbiAgLyoqXG4gICogQ29sb3Igb2YgdGhlIGJhY2tncm91bmRcbiAgKiBAcGFyYW0ge3N0cmluZ30gW2JhY2tncm91bmRGaWxsPVwidHJhbnNwYXJlbnRcIl1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgYmFja2dyb3VuZEZpbGwgPSAndHJhbnNwYXJlbnQnLFxuICAvKipcbiAgKiBOYW1lc3BhY2UgZm9yIGFsbCBpdGVtcyBtYWRlIGJ5IHRoaXMgaW5zdGFuY2Ugb2YgYXhpc1xuICAqIEBwYXJhbSB7c3RyaW5nfSBbbmFtZXNwYWNlPVwiZDNzbS1heGlzXCJdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG5hbWVzcGFjZSA9ICdkM3NtLWF4aXMnLFxuICAvKipcbiAgKiBDbGFzcyBuYW1lIGZvciB0aWNrIGNvbnRhaW5lciAoPGc+IGVsZW1lbnQpXG4gICogQHBhcmFtIHtzdHJpbmd9IFtvYmplY3RDbGFzcz1cInRpY2stZ3JvdXBcIl1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0Q2xhc3MgPSAndGljay1ncm91cCcsXG5cbiAgLyoqXG4gICogVmFsdWVzIHRvIHNob3cgYXQgZWFjaCB0aWNrLiBPbmx5IHVzZWQgaWYgY2F0ZWdvcmljYWxRIGlzIHNldCB0cnVlLiBTZWUge0BsaW5rIGF4aXMjY2F0ZWdvcmljYWxRfVxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt0aWNrTGFiZWxzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdGlja0xhYmVscywgICAvLyB3aGF0IHRvIHBsYWNlIGF0IHRpY2tzXG4gIC8qKlxuICAqIFZhbHVlcyB0byBzaG93IGF0IGVhY2ggdGljay4gT25seSB1c2VkIGlmIGNhdGVnb3JpY2FsUSBpcyBzZXQgZmFsc2UuIFNlZSB7QGxpbmsgYXhpcyNjYXRlZ29yaWNhbFF9XG4gICogQHBhcmFtIHtzdHJpbmdbXSB8IG51bWJlcltdfSBbb2JqZWN0Q2xhc3M9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0aWNrVmFsdWVzLCAgIC8vIHdoZXJlIHRvIHBsYWNlIHRpY2tzIGlmIG5vdFxuICAvKipcbiAgKiBOdW1iZXIgb2YgdGlja3MgdG8gZGlzcGxheSBpZiBjYXRlZ29yaWNhbFEgaXMgZmFsc2UuIFNlZSB7QGxpbmsgYXhpcyNjYXRlZ29yaWNhbFF9XG4gICogQHBhcmFtIHtudW1iZXJ9IFtudW1iZXJPZlRpY2tzPTVdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG51bWJlck9mVGlja3MgPSA1LFxuXG5cbiAgLyoqXG4gICogU3Ryb2tlIGNvbG9yIG9mIHRoZSBtYWluIGF4aXMgbGluZVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbbGluZVN0cm9rZT0nYmxhY2snXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBsaW5lU3Ryb2tlID0gJ2JsYWNrJyxcbiAgLyoqXG4gICogU3Ryb2tlIHdpZHRoIG9mIHRoZSBtYWluIGF4aXMgbGluZVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbbGluZVN0cm9rZVdpZHRoPTNdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGxpbmVTdHJva2VXaWR0aCA9IDMsXG5cblxuICAvKipcbiAgKiBTdHJva2UgY29sb3Igb2YgdGlja3NcbiAgKiBAcGFyYW0ge3N0cmluZ30gW3RpY2tTdHJva2U9J2JsYWNrJ11cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdGlja1N0cm9rZSA9ICdibGFjaycsXG4gIC8qKlxuICAqIFN0cm9rZSBudW1iZXIgb2YgdGlja3NcbiAgKiBAcGFyYW0ge3N0cmluZ30gW3RpY2tTdHJva2VXaWR0aD0yXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0aWNrU3Ryb2tlV2lkdGggPSAyLFxuICAvKipcbiAgKiBMZW5ndGggLSBpbiBwaXhlbHMgLSBvZiB0aWNrc1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbdGlja0xlbmd0aD0xMF1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdGlja0xlbmd0aCA9IDEwLFxuXG4gIHRpY2tUaWNrTGFiZWxTcGFjZXIgPSAxMCxcbiAgdGlja0xhYmVsTWFyZ2luID0gMTAsXG5cblxuICAvKipcbiAgKiBGb250IHNpemUgb2YgdGljayBsYWJlbHNcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RpY2tMYWJlbEZvbnRTaXplPTE0XVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0aWNrTGFiZWxGb250U2l6ZSA9IDE0LFxuICAvKipcbiAgKiBNaW4gZm9udCBzaXplIG9mIHRpY2sgbGFiZWxzXG4gICogQHBhcmFtIHtudW1iZXJ9IFt0aWNrTGFiZWxNaW5Gb250U2l6ZT04XVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0aWNrTGFiZWxNaW5Gb250U2l6ZSA9IDgsXG4gIC8qKlxuICAqIE1heCBmb250IHNpemUgb2YgdGljayBsYWJlbHNcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RpY2tMYWJlbE1heEZvbnRTaXplPTIwXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0aWNrTGFiZWxNYXhGb250U2l6ZSA9IDIwLFxuXG5cbiAgLyoqXG4gICogVGV4dCBhbmNob3Igb2YgdGljayBsYWJlbHNcbiAgKiBAcGFyYW0ge3N0cmluZ30gW3RpY2tMYWJlbFRleHRBbmNob3I9XCJtaWRkbGVcIl1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdGlja0xhYmVsVGV4dEFuY2hvcixcbiAgLyoqXG4gICogUm90YXRpb24gb2YgdGljayBsYWJlbHNcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RpY2tMYWJlbFJvdGF0aW9uPTBdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRpY2tMYWJlbFJvdGF0aW9uLFxuICAvKipcbiAgKiBPcHRpb25hbCBmdW5jdGlvbiBmb3IgZXh0cmFjdGluZyB0aGUgdGljayBsYWJlbCBmcm9tIGRhdGFcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbdGlja0xhYmVsRnVuYz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRpY2tMYWJlbEZ1bmMgPSB1bmRlZmluZWQsXG5cbiAgLyoqXG4gICogT3B0aW9uYWwgZnVuY3Rpb24gZm9yIHdoYXQgdG8gZG8gd2hlbiBsYWJlbCBpcyBjbGlja2VkXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3RpY2tMYWJlbE9uQ2xpY2s9ZnVuY3Rpb24oZCwgaSl7fV1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdGlja0xhYmVsT25DbGljayA9IGZ1bmN0aW9uKGQsIGkpe30sXG5cbiAgLyoqXG4gICogT3B0aW9uYWwgZnVuY3Rpb24gZm9yIHdoYXQgdG8gZG8gd2hlbiBsYWJlbCBpcyBob3ZlcmVkXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3RpY2tMYWJlbE9uSG92ZXJGdW5jPWZ1bmN0aW9uKGQsIGkpe31dXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRpY2tMYWJlbE9uSG92ZXJGdW5jID0gZnVuY3Rpb24oZCwgaSl7XG4gICAgcmV0dXJuIFN0cmluZyhkKS5yZXBsYWNlKCctJywgJyAnKS5yZXBsYWNlKCdfJywgJyAnKVxuICB9LFxuXG5cbiAgLyoqXG4gICogTGVuZ3RoIG9mIGd1aWRlbGluZXNcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbZ3VpZGVsaW5lU3BhY2U9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBndWlkZWxpbmVTcGFjZSxcbiAgLyoqXG4gICogU3Ryb2tlIGNvbG9yIG9mIGd1aWRsaW5lc1xuICAqIEBwYXJhbSB7c3RyaW5nfSBbZ3VpZGVsaW5lU3BhY2U9XCIjMzMzMzMzXCJdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGd1aWRlTGluZVN0cm9rZSA9ICcjMzMzMzMzJyxcbiAgLyoqXG4gICogU3Ryb2tlIHdpZHRoIG9mIGd1aWRsaW5lc1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbZ3VpZGVsaW5lU3BhY2U9Ml1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZ3VpZGVMaW5lU3Ryb2tlV2lkdGggPSAyLFxuXG4gIC8qKlxuICAqIER1cmF0aW9uIG9mIGFsbCB0cmFuc2l0aW9ucyBvZiB0aGlzIGVsZW1lbnRcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RyYW5zaXRpb25EdXJhdGlvbj0xMDAwXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwLFxuICAvKipcbiAgKiBFYXNpbmcgZnVuY3Rpb24gZm9yIHRyYW5zaXRpb25zXG4gICogQHBhcmFtIHtkMy5lYXNlfSBbZWFzZUZ1bmM9ZDMuZWFzZUV4cF1cbiAgKiBAbWVtYmVyb2YgYXhpcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwLFxuXG5cbiAgLyoqXG4gICogQ2xvc3VyZSB2YXJpYWJsZSBmb3IgZ2V0dGluZyBvYmplY3Qgc2l6ZSBhZnRlciBjYWxjdWxhdGlvblxuICAqIEBwYXJhbSB7bnVtYmVyfSBbb2JqZWN0U2l6ZT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGF4aXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdFNpemUsXG4gIC8qKlxuICAqIENsb3N1cmUgdmFyaWFibGUgZm9yIGdldHRpbmcgc3BhY2VyIHNpemUgYWZ0ZXIgY2FsY3VsYXRpb25cbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlclNpemU9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzcGFjZXJTaXplLFxuXG4gIC8qKlxuICAqIERlY2ltYWwgcGVyY2lzaW9uIHRvIHJvdW5kIG51bWVyaWNhbCB0aWNrIGxhYmVscyB0b1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbcm91bmRUbz0yXVxuICAqIEBtZW1iZXJvZiBheGlzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICByb3VuZFRvID0gMixcblxuICBsYWJlbCxcblxuXG4gIHJldmVyc2VTY2FsZVEgPSBmYWxzZVxuXG4gIGF4aXMubGFiZWwgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGxhYmVsID0gXywgYXhpcykgOiBsYWJlbDsgfTtcbiAgYXhpcy50aWNrVGlja0xhYmVsU3BhY2VyID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0aWNrVGlja0xhYmVsU3BhY2VyID0gXywgYXhpcykgOiB0aWNrVGlja0xhYmVsU3BhY2VyOyB9O1xuICBheGlzLnRpY2tMYWJlbE1hcmdpbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja0xhYmVsTWFyZ2luID0gXywgYXhpcykgOiB0aWNrTGFiZWxNYXJnaW47IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHNlbGVjdGlvbiBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgZDMuc2VsZWN0aW9ufVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzZWxlY3Rpb24gPSBzZWxlY3Rpb25cbiAgICovXG5cbiAgYXhpcy5zZWxlY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNlbGVjdGlvbiA9IF8sIGF4aXMpIDogc2VsZWN0aW9uOyB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIG9yaWVudGF0aW9uIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBheGlzI29yaWVudH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXSBzaG91bGQgYmUgaG9yaXpvbnRhbCBvciB2ZXJ0aWNhbFxuICAgKiBAcmV0dXJucyB7YXhpcyB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3JpZW50PVwiYm90dG9tXCJcbiAgICovXG4gIGF4aXMub3JpZW50ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvcmllbnQgPSBfLCBheGlzKSA6IG9yaWVudDsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgYW1vdW50IG9mIGhvcml6b250YWwgc3BhY2UgaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIGF4aXMjc3BhY2VYfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge2F4aXMgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlWCA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYXhpcy5zcGFjZVggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWCA9IF8sIGF4aXMpIDogc3BhY2VYOyB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBhbW91bnQgb2YgdmVydGljYWwgc3BhY2UgaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIGF4aXMjc3BhY2VZfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge2F4aXMgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlWSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYXhpcy5zcGFjZVkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWSA9IF8sIGF4aXMpIDogc3BhY2VZOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IGF4aXMgaXMgYWxsb3dlZCB0byBnbyBiZXlvbmQgc3BlY2lmaWVkIGRpbWVuc2lvbnNcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNzcGFjZVh9KVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgYm9vbGVhbn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3ZlcmZsb3dRID0gZmFsc2VcbiAgICovXG4gIGF4aXMub3ZlcmZsb3dRID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvdmVyZmxvd1EgPSBfLCBheGlzKSA6IG92ZXJmbG93UTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IGF4aXMgd2lsbCBkaXNwbGF5IGNhdGVnb3JpYWwgdGlja3Mgb3IgYnkgbnVtZXJpY2FsIHZhbHVlXG4gICAqIChzZWUge0BsaW5rIGF4aXMjY2F0ZWdvcmljYWxRfSlcbiAgICogQHBhcmFtIHtib29sZWFufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IGJvb2xlYW59XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGNhdGVnb3JpY2FsUSA9IGZhbHNlXG4gICAqL1xuICBheGlzLmNhdGVnb3JpY2FsUSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY2F0ZWdvcmljYWxRID0gXywgYXhpcykgOiBjYXRlZ29yaWNhbFE7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB3aGV0aGVyIG9yIG5vdCBheGlzIHRpY2tzIHNob3VsZCBoYXZlIGd1aWRlbGluZXNcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNndWlkZUxpbmVzUX0pXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2F4aXMgfCBib29sZWFufVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBndWlkZUxpbmVzUSA9IGZhbHNlXG4gICAqL1xuICBheGlzLmd1aWRlTGluZXNRID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChndWlkZUxpbmVzUSA9IF8sIGF4aXMpIDogZ3VpZGVMaW5lc1E7IH07XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgaG93IHRpY2tzIHNob3VsZCBiZSBncm91cHBlZFxuICAgKiAoc2VlIHtAbGluayBheGlzI2dyb3VwaW5nfSlcbiAgICogQHBhcmFtIHtBcnJheVtdfSBbXz1ub25lXSBsaXN0IG9mIHB1dGF0aXZlbHkgb3RoZXIgbGlzdHMsIHdoaWNoIHNob3VsZCBjb3JyZXNwb25kIHRvIHRpY2tMYWJlbHNcbiAgICogd2lsbCBzcGFjZSB0aWNrIGxhYmVscyBpbiBuZXN0ZWQgbGlzdHMgY2xvc2VyIHRvZ2V0aGVyIHRoYW4gb3V0ZXIgbGlzdHNcbiAgICogQHJldHVybnMge2F4aXMgfCBBcnJheVtdfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBncm91cGluZyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYXhpcy5ncm91cGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZ3JvdXBpbmcgPSBfLCBheGlzKSA6IGdyb3VwaW5nOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzY2FsZSBmb3Igd2hpY2ggbm9uLWNhdGVnb3JpYWwgIHRpY2tzIHNob3VsZFxuICAgKiBiZSBzcGFjZWRcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNzY2FsZX0pXG4gICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgZDMuc2NhbGV9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNjYWxlID0gZDMuc2NhbGVMaW5lYXIoKVxuICAgKi9cbiAgYXhpcy5zY2FsZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGUgPSBfLCBheGlzKSA6IHNjYWxlOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHBhZGRpbmcgZm9yIHRoZSBkb21haW4gb2YgdGhlIHNjYWxlXG4gICAqIChzZWUge0BsaW5rIGF4aXMjZG9tYWluUGFkZGluZ30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZG9tYWluUGFkZGluZyA9IDAuNVxuICAgKi9cbiAgYXhpcy5kb21haW5QYWRkaW5nID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkb21haW5QYWRkaW5nID0gXywgYXhpcykgOiBkb21haW5QYWRkaW5nOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIG9iamVjdFNwYWNlclxuICAgKiAoc2VlIHtAbGluayBheGlzI29iamVjdFNwYWNlcn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0U3BhY2VyID0gMC4wNVxuICAgKi9cbiAgYXhpcy5vYmplY3RTcGFjZXIgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNwYWNlciA9IF8sIGF4aXMpIDogb2JqZWN0U3BhY2VyOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1pbk9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNtaW5PYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBtaW5PYmplY3RTaXplID0gMTVcbiAgICovXG4gIGF4aXMubWluT2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobWluT2JqZWN0U2l6ZSA9IF8sIGF4aXMpIDogbWluT2JqZWN0U2l6ZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBtYXhPYmplY3RTaXplXG4gICAqIChzZWUge0BsaW5rIGF4aXMjbWF4T2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbWF4T2JqZWN0U2l6ZSA9IDUwXG4gICAqL1xuICBheGlzLm1heE9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1heE9iamVjdFNpemUgPSBfLCBheGlzKSA6IG1heE9iamVjdFNpemU7IH07XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG5hbWVzcGFjZVxuICAgKiAoc2VlIHtAbGluayBheGlzI25hbWVzcGFjZX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbmFtZXNwYWNlID0gJ2Qzc20tYXhpcydcbiAgICovXG4gIGF4aXMubmFtZXNwYWNlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChuYW1lc3BhY2UgPSBfLCBheGlzKSA6IG5hbWVzcGFjZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBiYWNrZ3JvdW5kRmlsbFxuICAgKiAoc2VlIHtAbGluayBheGlzI2JhY2tncm91bmRGaWxsfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCdcbiAgICovXG4gIGF4aXMuYmFja2dyb3VuZEZpbGwgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJhY2tncm91bmRGaWxsID0gXywgYXhpcykgOiBiYWNrZ3JvdW5kRmlsbDsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RDbGFzc1xuICAgKiAoc2VlIHtAbGluayBheGlzI29iamVjdENsYXNzfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RDbGFzcyA9ICd0aWNrLWdyb3VwJ1xuICAgKi9cbiAgYXhpcy5vYmplY3RDbGFzcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q2xhc3MgPSBfLCBheGlzKSA6IG9iamVjdENsYXNzOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB0aWNrTGFiZWxzXG4gICAqIChzZWUge0BsaW5rIGF4aXMjdGlja0xhYmVsc30pXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgc3RyaW5nW119XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRpY2tMYWJlbHMgPSB1bmRlZmluZWRcbiAgICovXG4gIGF4aXMudGlja0xhYmVscyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja0xhYmVscyA9IF8sIGF4aXMpIDogdGlja0xhYmVsczsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB0aWNrVmFsdWVzXG4gICAqIChzZWUge0BsaW5rIGF4aXMjdGlja1ZhbHVlc30pXG4gICAqIEBwYXJhbSB7bnVtYmVyW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgbnVtYmVyW119XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRpY2tWYWx1ZXMgPSB1bmRlZmluZWRcbiAgICovXG4gIGF4aXMudGlja1ZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja1ZhbHVlcyA9IF8sIGF4aXMpIDogdGlja1ZhbHVlczsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB0aWNrVmFsdWVzXG4gICAqIChzZWUge0BsaW5rIGF4aXMjbnVtYmVyT2ZUaWNrc30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbnVtYmVyT2ZUaWNrcyA9IDVcbiAgICovXG4gIGF4aXMubnVtYmVyT2ZUaWNrcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobnVtYmVyT2ZUaWNrcyA9IF8sIGF4aXMpIDogbnVtYmVyT2ZUaWNrczsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbGluZVN0cm9rZVxuICAgKiAoc2VlIHtAbGluayBheGlzI2xpbmVTdHJva2V9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2F4aXMgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGxpbmVTdHJva2UgPSAnYmxhY2snXG4gICAqL1xuICBheGlzLmxpbmVTdHJva2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGxpbmVTdHJva2UgPSBfLCBheGlzKSA6IGxpbmVTdHJva2U7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbGluZVN0cm9rZVdpZHRoXG4gICAqIChzZWUge0BsaW5rIGF4aXMjbGluZVN0cm9rZVdpZHRofSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBsaW5lU3Ryb2tlV2lkdGggPSAzXG4gICAqL1xuICBheGlzLmxpbmVTdHJva2VXaWR0aCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobGluZVN0cm9rZVdpZHRoID0gXywgYXhpcykgOiBsaW5lU3Ryb2tlV2lkdGg7IH07XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRpY2tTdHJva2VcbiAgICogKHNlZSB7QGxpbmsgYXhpcyN0aWNrU3Ryb2tlfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0aWNrU3Ryb2tlID0gJ2JsYWNrJ1xuICAgKi9cbiAgYXhpcy50aWNrU3Ryb2tlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0aWNrU3Ryb2tlID0gXywgYXhpcykgOiB0aWNrU3Ryb2tlOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRpY2tTdHJva2VXaWR0aFxuICAgKiAoc2VlIHtAbGluayBheGlzI3RpY2tTdHJva2VXaWR0aH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdGlja1N0cm9rZVdpZHRoID0gMlxuICAgKi9cbiAgYXhpcy50aWNrU3Ryb2tlV2lkdGggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tTdHJva2VXaWR0aCA9IF8sIGF4aXMpIDogdGlja1N0cm9rZVdpZHRoOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRpY2tMZW5ndGhcbiAgICogKHNlZSB7QGxpbmsgYXhpcyN0aWNrTGVuZ3RofSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0aWNrTGVuZ3RoID0gMTBcbiAgICovXG4gIGF4aXMudGlja0xlbmd0aCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja0xlbmd0aCA9IF8sIGF4aXMpIDogdGlja0xlbmd0aDsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdGlja0xhYmVsRm9udFNpemVcbiAgICogKHNlZSB7QGxpbmsgYXhpcyN0aWNrTGFiZWxGb250U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdGlja0xhYmVsRm9udFNpemUgPSAxNFxuICAgKi9cbiAgYXhpcy50aWNrTGFiZWxGb250U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja0xhYmVsRm9udFNpemUgPSBfLCBheGlzKSA6IHRpY2tMYWJlbEZvbnRTaXplOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRpY2tMYWJlbE1pbkZvbnRTaXplXG4gICAqIChzZWUge0BsaW5rIGF4aXMjdGlja0xhYmVsTWluRm9udFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2F4aXMgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRpY2tMYWJlbE1pbkZvbnRTaXplID0gOFxuICAgKi9cbiAgYXhpcy50aWNrTGFiZWxNaW5Gb250U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja0xhYmVsTWluRm9udFNpemUgPSBfLCBheGlzKSA6IHRpY2tMYWJlbE1pbkZvbnRTaXplOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRpY2tMYWJlbE1heEZvbnRTaXplXG4gICAqIChzZWUge0BsaW5rIGF4aXMjdGlja0xhYmVsTWF4Rm9udFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2F4aXMgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRpY2tMYWJlbE1heEZvbnRTaXplID0gMjBcbiAgICovXG4gIGF4aXMudGlja0xhYmVsTWF4Rm9udFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tMYWJlbE1heEZvbnRTaXplID0gXywgYXhpcykgOiB0aWNrTGFiZWxNYXhGb250U2l6ZTt9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB0aWNrTGFiZWxUZXh0QW5jaG9yXG4gICAqIChzZWUge0BsaW5rIGF4aXMjdGlja0xhYmVsVGV4dEFuY2hvcn0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdGlja0xhYmVsVGV4dEFuY2hvciA9ICdjZW50ZXInXG4gICAqL1xuICBheGlzLnRpY2tMYWJlbFRleHRBbmNob3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tMYWJlbFRleHRBbmNob3IgPSBfLCBheGlzKSA6IHRpY2tMYWJlbFRleHRBbmNob3I7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdGlja0xhYmVsUm90YXRpb25cbiAgICogKHNlZSB7QGxpbmsgYXhpcyN0aWNrTGFiZWxSb3RhdGlvbn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdGlja0xhYmVsUm90YXRpb24gPSAwXG4gICAqL1xuICBheGlzLnRpY2tMYWJlbFJvdGF0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0aWNrTGFiZWxSb3RhdGlvbiA9IF8sIGF4aXMpIDogdGlja0xhYmVsUm90YXRpb247IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdGlja0xhYmVsRnVuY1xuICAgKiAoc2VlIHtAbGluayBheGlzI3RpY2tMYWJlbEZ1bmN9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0aWNrTGFiZWxGdW5jID0gdW5kZWZpbmVkXG4gICAqL1xuICBheGlzLnRpY2tMYWJlbEZ1bmMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tMYWJlbEZ1bmMgPSBfLCBheGlzKSA6IHRpY2tMYWJlbEZ1bmM7IH07XG5cblxuICAvKipcbiAgKiBHZXRzIC8gc2V0cyB0aGUgdGlja0xhYmVsT25DbGlja1xuICAqIChzZWUge0BsaW5rIGF4aXMjdGlja0xhYmVsT25DbGlja30pXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgKiBAcmV0dXJucyB7YXhpcyB8IGZ1bmN0aW9ufVxuICAqIEBtZW1iZXJvZiBheGlzXG4gICogQHByb3BlcnR5XG4gICovXG4gIGF4aXMudGlja0xhYmVsT25DbGljayA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlja0xhYmVsT25DbGljayA9IF8sIGF4aXMpIDogdGlja0xhYmVsT25DbGljazsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgZ3VpZGVsaW5lU3BhY2VcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNndWlkZWxpbmVTcGFjZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZ3VpZGVsaW5lU3BhY2UgPSB1bmRlZmluZWRcbiAgICovXG4gIGF4aXMuZ3VpZGVsaW5lU3BhY2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGd1aWRlbGluZVNwYWNlID0gXywgYXhpcykgOiBndWlkZWxpbmVTcGFjZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBndWlkZUxpbmVTdHJva2VcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNndWlkZUxpbmVTdHJva2V9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2F4aXMgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGd1aWRlTGluZVN0cm9rZSA9IFwiIzMzMzMzM1wiXG4gICAqL1xuICBheGlzLmd1aWRlTGluZVN0cm9rZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZ3VpZGVMaW5lU3Ryb2tlID0gXywgYXhpcykgOiBndWlkZUxpbmVTdHJva2U7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgZ3VpZGVMaW5lU3Ryb2tlV2lkdGhcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNndWlkZUxpbmVTdHJva2VXaWR0aH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZ3VpZGVMaW5lU3Ryb2tlV2lkdGggPSAyXG4gICAqL1xuICBheGlzLmd1aWRlTGluZVN0cm9rZVdpZHRoID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChndWlkZUxpbmVTdHJva2VXaWR0aCA9IF8sIGF4aXMpIDogZ3VpZGVMaW5lU3Ryb2tlV2lkdGg7IH07XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRyYW5zaXRpb25EdXJhdGlvblxuICAgKiAoc2VlIHtAbGluayBheGlzI3RyYW5zaXRpb25EdXJhdGlvbn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YXhpcyB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdHJhbnNpdGlvbkR1cmF0aW9uID0gMTAwMFxuICAgKi9cbiAgYXhpcy50cmFuc2l0aW9uRHVyYXRpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRyYW5zaXRpb25EdXJhdGlvbiA9IF8sIGF4aXMpIDogdHJhbnNpdGlvbkR1cmF0aW9uOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGVhc2VGdW5jXG4gICAqIChzZWUge0BsaW5rIGF4aXMjZWFzZUZ1bmN9KVxuICAgKiBAcGFyYW0ge2QzLmVhc2V9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgZDMuZWFzZX1cbiAgICogQG1lbWJlcm9mIGF4aXNcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwXG4gICAqL1xuICBheGlzLmVhc2VGdW5jID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChlYXNlRnVuYyA9IF8sIGF4aXMpIDogZWFzZUZ1bmM7IH07XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgYXhpcyNvYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RTaXplID0gdW5kZWZpbmVkXG4gICAqL1xuICBheGlzLm9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNpemUgPSBfLCBheGlzKSA6IG9iamVjdFNpemU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgc3BhY2VyU2l6ZVxuICAgKiAoc2VlIHtAbGluayBheGlzI3NwYWNlclNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2F4aXMgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBheGlzXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlclNpemUgPSB1bmRlZmluZWRcbiAgICovXG4gIGF4aXMuc3BhY2VyU2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3BhY2VyU2l6ZSA9IF8sIGF4aXMpIDogc3BhY2VyU2l6ZTsgfTtcblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHJvdW5kVG9cbiAgICogKHNlZSB7QGxpbmsgYXhpcyNyb3VuZFRvfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtheGlzIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYXhpc1xuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCByb3VuZFRvID0gMlxuICAgKi9cbiAgIGF4aXMucm91bmRUbyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocm91bmRUbyA9IF8sIGF4aXMpIDogcm91bmRUbzsgfTtcbiAgIGF4aXMucmV2ZXJzZVNjYWxlUSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocmV2ZXJzZVNjYWxlUSA9IF8sIGF4aXMpIDogcmV2ZXJzZVNjYWxlUTsgfTtcblxuXG4gICBheGlzLnRpY2tMYWJlbE9uSG92ZXJGdW5jID0gZnVuY3Rpb24oXykge3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tMYWJlbE9uSG92ZXJGdW5jID0gXywgYXhpcykgOiB0aWNrTGFiZWxPbkhvdmVyRnVuYzsgfTtcblxuXG4gIGZ1bmN0aW9uIGF4aXMgKCkge1xuICAgIC8vIGZvciBjb252ZW5pZW5jZSBpbiBoYW5kbGluZyBvcmllbnRhdGlvbiBzcGVjaWZpYyB2YWx1ZXNcbiAgICB2YXIgaG9yaXpvbnRhbFEgPSBoYXNRKFsndG9wJywgJ2JvdHRvbScsICdob3Jpem9udGFsJ10sIG9yaWVudCkgPyB0cnVlIDogZmFsc2VcbiAgICB2YXIgdmVydGljYWxRID0gIWhvcml6b250YWxRXG5cbiAgICAvLyBiYWNrZ3JvdW5kIGNsaXBpbmcgcmVjdGFuZ2xlXG4gICAgdmFyIGJnY3BSZWN0ID0ge3g6MCwgeTowLCB3aWR0aDogc3BhY2VYLCBoZWlnaHQ6c3BhY2VZfVxuICAgIC8vIG1vZGlmeSB0aGUgcmVjdCBiYXNlZCBvbiBheGlzIG9yaWVudGF0aW9uXG4gICAgaWYgKG9yaWVudCA9PSBcImxlZnRcIikge1xuICAgICAgYmdjcFJlY3QueCAtPSBzcGFjZVg7XG4gICAgICBpZihndWlkZUxpbmVzUSkgeyBiZ2NwUmVjdC53aWR0aCArPSBndWlkZWxpbmVTcGFjZSB9O1xuICAgICAgLyogdGhlc2UgdHdvIGxpbmVzIGluY3JlYXNlIHRoZSBjbGlwcGluZyByZWN0IHRvIGFsbG93IGZvciB0ZXh0IGF0IHRoZSBlZGdlIG9mIHRoZSBheGlzICovXG4gICAgICBiZ2NwUmVjdC55IC09IHRpY2tMYWJlbE1heEZvbnRTaXplO1xuICAgICAgYmdjcFJlY3QuaGVpZ2h0ICs9IDIqdGlja0xhYmVsTWF4Rm9udFNpemVcbiAgICB9XG4gICAgaWYgKG9yaWVudCA9PSBcImJvdHRvbVwiKXtcbiAgICAgIGJnY3BSZWN0LnkgPSBiZ2NwUmVjdC55O1xuICAgICAgaWYoZ3VpZGVMaW5lc1EpIHsgYmdjcFJlY3QueSAtPSBndWlkZWxpbmVTcGFjZTsgYmdjcFJlY3QuaGVpZ2h0ICs9IGd1aWRlbGluZVNwYWNlOyB9O1xuICAgICAgLyogdGhlc2UgdHdvIGxpbmVzIGluY3JlYXNlIHRoZSBjbGlwcGluZyByZWN0IHRvIGFsbG93IGZvciB0ZXh0IGF0IHRoZSBlZGdlIG9mIHRoZSBheGlzICovXG4gICAgICBiZ2NwUmVjdC54IC09IHRpY2tMYWJlbE1heEZvbnRTaXplO1xuICAgICAgYmdjcFJlY3Qud2lkdGggKz0gMip0aWNrTGFiZWxNYXhGb250U2l6ZVxuICAgIH1cbiAgICBpZiAob3JpZW50ID09IFwidG9wXCIpIHtcbiAgICAgIGJnY3BSZWN0LnkgLT0gc3BhY2VZO1xuICAgICAgaWYoZ3VpZGVMaW5lc1EpIHsgYmdjcFJlY3QuaGVpZ2h0ICs9IGd1aWRlbGluZVNwYWNlIH07XG4gICAgICAvKiB0aGVzZSB0d28gbGluZXMgaW5jcmVhc2UgdGhlIGNsaXBwaW5nIHJlY3QgdG8gYWxsb3cgZm9yIHRleHQgYXQgdGhlIGVkZ2Ugb2YgdGhlIGF4aXMgKi9cbiAgICAgIGJnY3BSZWN0LnkgLT0gdGlja0xhYmVsTWF4Rm9udFNpemU7XG4gICAgICBiZ2NwUmVjdC5oZWlnaHQgKz0gMip0aWNrTGFiZWxNYXhGb250U2l6ZVxuICAgIH1cbiAgICBpZiAob3JpZW50ID09IFwicmlnaHRcIikgeyBiZ2NwUmVjdC54ID0gMDtcbiAgICAgIGlmKGd1aWRlTGluZXNRKSB7IGJnY3BSZWN0LndpZHRoICs9IGd1aWRlbGluZVNwYWNlOyBiZ2NwUmVjdC54IC09IGd1aWRlbGluZVNwYWNlIH07XG4gICAgICAvKiB0aGVzZSB0d28gbGluZXMgaW5jcmVhc2UgdGhlIGNsaXBwaW5nIHJlY3QgdG8gYWxsb3cgZm9yIHRleHQgYXQgdGhlIGVkZ2Ugb2YgdGhlIGF4aXMgKi9cbiAgICAgIGJnY3BSZWN0LnkgLT0gdGlja0xhYmVsTWF4Rm9udFNpemU7XG4gICAgICBiZ2NwUmVjdC5oZWlnaHQgKz0gMip0aWNrTGFiZWxNYXhGb250U2l6ZVxuICAgIH1cblxuXG4gICAgdmFyIGNvbnRhaW5lciA9IHNldHVwQ29udGFpbmVyKCBzZWxlY3Rpb24sIG5hbWVzcGFjZSwgYmdjcFJlY3QsIGJhY2tncm91bmRGaWxsICk7XG5cbiAgICAvLyBkZWZhdWx0cyBmb3IgdGV4dC1hbmNob3IgYW5kIHRleHQgcm90YXRpb25cbiAgICBpZiAob3JpZW50ID09ICd0b3AnKSB7XG4gICAgICB0aWNrTGFiZWxUZXh0QW5jaG9yID0gdGlja0xhYmVsVGV4dEFuY2hvciA9PSB1bmRlZmluZWQgPyAnc3RhcnQnIDogdGlja0xhYmVsVGV4dEFuY2hvclxuICAgICAgdGlja0xhYmVsUm90YXRpb24gPSB0aWNrTGFiZWxSb3RhdGlvbiA9PSB1bmRlZmluZWQgPyAtOTAgOiB0aWNrTGFiZWxSb3RhdGlvblxuICAgIH1cbiAgICBpZiAob3JpZW50ID09ICdib3R0b20nKSB7XG4gICAgICB0aWNrTGFiZWxUZXh0QW5jaG9yID0gdGlja0xhYmVsVGV4dEFuY2hvciA9PSB1bmRlZmluZWQgPyAnZW5kJyA6IHRpY2tMYWJlbFRleHRBbmNob3JcbiAgICAgIHRpY2tMYWJlbFJvdGF0aW9uID0gdGlja0xhYmVsUm90YXRpb24gPT0gdW5kZWZpbmVkID8gLTkwIDogdGlja0xhYmVsUm90YXRpb25cbiAgICB9XG4gICAgaWYgKG9yaWVudCA9PSAnbGVmdCcpIHtcbiAgICAgIHRpY2tMYWJlbFRleHRBbmNob3IgPSB0aWNrTGFiZWxUZXh0QW5jaG9yID09IHVuZGVmaW5lZCA/ICdlbmQnIDogdGlja0xhYmVsVGV4dEFuY2hvclxuICAgICAgdGlja0xhYmVsUm90YXRpb24gPSB0aWNrTGFiZWxSb3RhdGlvbiA9PSB1bmRlZmluZWQgPyAwIDogdGlja0xhYmVsUm90YXRpb25cbiAgICB9XG4gICAgaWYgKG9yaWVudCA9PSAncmlnaHQnKSB7XG4gICAgICB0aWNrTGFiZWxUZXh0QW5jaG9yID0gdGlja0xhYmVsVGV4dEFuY2hvciA9PSB1bmRlZmluZWQgPyAnc3RhcnQnIDogdGlja0xhYmVsVGV4dEFuY2hvclxuICAgICAgdGlja0xhYmVsUm90YXRpb24gPSB0aWNrTGFiZWxSb3RhdGlvbiA9PSB1bmRlZmluZWQgPyAwIDogdGlja0xhYmVsUm90YXRpb25cbiAgICB9XG5cbiAgICAvKlxuICAgIElmIGNhdGVnb3JpY2FsOlxuICAgICAgLT4gdXNlIGdyb3VwaW5nIGlmIGRlZmluZWQsXG4gICAgICAtPiBlbHNlIHVzZSB0aGUgbGFiZWxzIHByb3ZpZGVkXG4gICAgZWxzZTpcbiAgICAgIGlmIGdyb3VwaW5nIHVuZGVmaW5lZFxuICAgICAgICBhbmQgbm8gc3BlY2lmaWVkIG51bWJlciBvZiB0aWNrZXNcbiAgICAgICAgICAtPiBtYWtlIG51bWJlck9mVGljayB0aWNrc1xuICAgICAgICAgIC0+IGVsc2UgdXNlIHByb3ZpZGVkIHRpY2sgdmFsdWVzXG4gICAgICAgIC0+IHVzZSBncm91cGluZ1xuICAgICovXG4gICAgdmFyIHRpY2tEYXRhID0gY2F0ZWdvcmljYWxRXG4gICAgPyAoZ3JvdXBpbmcgPT0gdW5kZWZpbmVkKVxuICAgICAgPyB0aWNrTGFiZWxzXG4gICAgICA6IGdyb3VwaW5nXG4gICAgOiAoZ3JvdXBpbmcgPT0gdW5kZWZpbmVkKVxuICAgICAgPyAobnVtYmVyT2ZUaWNrcyAhPSB1bmRlZmluZWQpXG4gICAgICAvLyA/ICh0aWNrVmFsdWVzLmxlbmd0aCA8IG51bWJlck9mVGlja3MpXG4gICAgICAgID8gKHRpY2tSYW5nZSguLi5kMy5leHRlbnQodGlja1ZhbHVlcyksIG51bWJlck9mVGlja3MpKVxuICAgICAgICA6IHRpY2tWYWx1ZXNcbiAgICAgIDogZ3JvdXBpbmdcblxuXG4gICAgdmFyIGZsYXRUaWNrRGF0YSA9IGZsYXR0ZW4odGlja0RhdGEpXG4gICAgdmFyIG51bWJlck9mT2JqZWN0cyA9IGZsYXRUaWNrRGF0YS5sZW5ndGhcbiAgICB2YXIgc3BhY2UgPSBob3Jpem9udGFsUSA/IHNwYWNlWCA6IHNwYWNlWVxuICAgIHZhciBleHRlbnQgPSBkMy5leHRlbnQoZmxhdFRpY2tEYXRhKVxuXG5cbiAgICBpZiAocmV2ZXJzZVNjYWxlUSkge2V4dGVudC5yZXZlcnNlKCl9XG4gICAgdmFyIGRvbWFpbiA9IHJldmVyc2VTY2FsZVFcbiAgICA/IFtleHRlbnRbMF0gKyBkb21haW5QYWRkaW5nLCBleHRlbnRbMV0gLSBkb21haW5QYWRkaW5nXVxuICAgIDogW2V4dGVudFswXSAtIGRvbWFpblBhZGRpbmcsIGV4dGVudFsxXSArIGRvbWFpblBhZGRpbmddXG5cbiAgICBzY2FsZVxuICAgIC5kb21haW4oZG9tYWluKVxuICAgIC5yYW5nZShbaG9yaXpvbnRhbFEgPyAwIDogc3BhY2VZLCBob3Jpem9udGFsUSA/IHNwYWNlWCA6IDBdKVxuXG5cbiAgICAvKlxuICAgIFNjYWxlcyBhcmUgYmFzZWQgb24gdGhlIHZhbHVlcyBvZiB0aGUgY2hhcnQgYW5kIGNvcnJlc3BvbmQgdG8gdGhlIHNwYWNpbmdzIG9mIHRoZVxuICAgIGNoYXJ0LiBJZiB0aGUgY2hhcnQgaGFzIGFscmVhZHkgYmVlbiByZW5kZXJlZCwgdGhlc2UgdmFsdWVzIChleHBlbnNpdmUgdG8gY2FsdWNsYXRlKSBjYW5cbiAgICBiZSBwYXNzZWQgdG8gYXhpcyB0byBwcmV2ZW50IHJlY2FsY3VsYXRpb24uXG4gICAgKi9cblxuICAgIC8vIGNhbGN1bGF0ZSBvYmplY3Qgc2l6ZSBpZiBuZWVkZWRcbiAgICBvYmplY3RTaXplID0gKG9iamVjdFNpemUgPT0gdW5kZWZpbmVkKVxuICAgID8gY2FsY3VsYXRlV2lkdGhPZk9iamVjdChzcGFjZSwgbnVtYmVyT2ZPYmplY3RzLCBtaW5PYmplY3RTaXplLCBtYXhPYmplY3RTaXplLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICA6IG9iamVjdFNpemVcblxuICAgIC8vIGNhbGN1bGF0ZSBzcGFjZXIgc2l6ZSBpZiBuZWVkZWRcbiAgICBzcGFjZXJTaXplID0gKHNwYWNlclNpemUgPT0gdW5kZWZpbmVkKVxuICAgID8gY2FsY3VsYXRlV2lkdGhPZlNwYWNlcihmbGF0VGlja0RhdGEsIHNwYWNlLCBvYmplY3RTaXplLCBudW1iZXJPZk9iamVjdHMsIG9iamVjdFNwYWNlciwgb3ZlcmZsb3dRKVxuICAgIDogc3BhY2VyU2l6ZVxuXG5cbiAgICB2YXIgb2JqQ2xhc3MgPSBoeXBlbmF0ZShuYW1lc3BhY2UsIGNhdGVnb3JpY2FsUSA/IG9iamVjdENsYXNzKyctY2F0ZWdvcmljYWwnIDogb2JqZWN0Q2xhc3MpXG5cbiAgICB2YXIgc3BhY2VyRnVuY3Rpb24gPSBncm91cGluZ1NwYWNlcigpXG4gICAgLmhvcml6b250YWxRKGhvcml6b250YWxRKS5zY2FsZShzY2FsZSkubW92ZWJ5KChjYXRlZ29yaWNhbFE/J2NhdGVnb3J5Jzonc2NhbGUnKSkubnVtYmVyT2ZPYmplY3RzKG51bWJlck9mT2JqZWN0cylcbiAgICAub2JqZWN0Q2xhc3Mob2JqQ2xhc3MpLm9iamVjdFNpemUob2JqZWN0U2l6ZSkuc3BhY2VyU2l6ZShzcGFjZXJTaXplKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlRnVuYyhlYXNlRnVuYylcbiAgICAubmFtZXNwYWNlKG5hbWVzcGFjZSlcblxuICAgIHZhciB0aWNrRW50ZXJBbmltYXRpb24gPSBmdW5jdGlvbihzZWwpe1xuICAgICAgdmFyIG10ID0gc2NhbGUoc2VsLmRhdHVtKCkpLFxuICAgICAgZGlzdCA9IHNjYWxlKGV4dGVudFsxXSkgKiAyLFxuICAgICAgayA9IChtdCA8IGV4dGVudFsxXSAvIDIpID8gMSA6IC0xXG4gICAgICBrID0gaG9yaXpvbnRhbFEgPyBrICogLTEgOiBrXG4gICAgICBzZWwuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24gKGQsIGkpIHtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBob3Jpem9udGFsUSA/ICBkaXN0ICogayA6IDAsXG4gICAgICAgIHkgPSAhaG9yaXpvbnRhbFEgPyBkaXN0ICogayA6IDAsXG4gICAgICAgIHQgPSAndHJhbnNsYXRlKCcreCsnLCcreSsnKSdcbiAgICAgICAgcmV0dXJuIHRcbiAgICAgIH0pXG4gICAgfVxuICAgIHZhciB0aWNrRXhpdEFuaW1hdGlvbiA9IGZ1bmN0aW9uKHNlbCkge1xuICAgICAgdmFyIG10ID0gc2NhbGUoc2VsLmRhdHVtKCkpLFxuICAgICAgZGlzdCA9IHNjYWxlKGV4dGVudFsxXSkgKiAyLFxuICAgICAgayA9IChtdCA8IGV4dGVudFsxXSAvIDIpID8gMSA6IC0xXG4gICAgICBrID0gaG9yaXpvbnRhbFEgPyBrICogLTEgOiBrXG4gICAgICBzZWwudHJhbnNpdGlvbigpLmR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbikuZWFzZShlYXNlRnVuYylcbiAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDApXG4gICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24gKGQsIGkpIHtcbiAgICAgICAgdmFyXG5cbiAgICAgICAgeCA9IGhvcml6b250YWxRID8gIGRpc3QgKiBrICA6IDAsXG4gICAgICAgIHkgPSAhaG9yaXpvbnRhbFEgPyBkaXN0ICogayA6IDAsXG4gICAgICAgIHQgPSAndHJhbnNsYXRlKCcreCsnLCcreSsnKSdcbiAgICAgICAgcmV0dXJuIHRcbiAgICAgIH0pLnJlbW92ZSgpXG4gICAgfVxuXG4gICAgaWYgKCFjYXRlZ29yaWNhbFEpe1xuICAgICAgc3BhY2VyRnVuY3Rpb24uZW50ZXJGdW5jdGlvbih0aWNrRW50ZXJBbmltYXRpb24pXG4gICAgICBzcGFjZXJGdW5jdGlvbi5leGl0RnVuY3Rpb24odGlja0V4aXRBbmltYXRpb24pXG4gICAgfVxuXG4gICAgLy8gbW92ZSB0aWNrIGNvbnRhaW5lcnNcbiAgICBzcGFjZXJGdW5jdGlvbihjb250YWluZXIsIHRpY2tEYXRhLCAwKVxuXG4gICAgLy8gbW92ZSBieSBmb3IgeCBhbmQgeSBuZWVkZWQgdG8gY2VudGVyIGNhdGVnb3JpY2FsIHRpY2tzLCBsYWJlbHMsIGFuZCBndWlkZWxpbmVzXG4gICAgZnVuY3Rpb24gbW92ZVhCeShkLCBpLCBob3Jpem9udGFsUSwgY2F0ZWdvcmljYWxRLCBvYmplY3RTaXplKXtcbiAgICAgIHJldHVybiAoaG9yaXpvbnRhbFEpXG4gICAgICA/IChjYXRlZ29yaWNhbFEpXG4gICAgICAgID8gb2JqZWN0U2l6ZSAvIDJcbiAgICAgICAgOiAwXG4gICAgICA6IDBcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb3ZlWUJ5KGQsIGksIHZlcnRpY2FsUSwgY2F0ZWdvcmljYWxRLCBvYmplY3RTaXplKXtcbiAgICAgIHJldHVybiAodmVydGljYWxRKVxuICAgICAgPyAoY2F0ZWdvcmljYWxRKVxuICAgICAgICA/IG9iamVjdFNpemUgLyAyXG4gICAgICAgIDogMFxuICAgICAgOiAwXG4gICAgfVxuXG5cblxuICAgIHZhciBsYWJlbE5hbWVHcm91cCA9IHNhZmVTZWxlY3Qoc2VsZWN0aW9uLCAnZycsIGh5cGVuYXRlKG5hbWVzcGFjZSwnYXhpcy1uYW1lJykpXG5cblxuXG4gICAgdmFyIGxhYmVsRWxlbWVudCA9IHNhZmVTZWxlY3QobGFiZWxOYW1lR3JvdXAsICd0ZXh0JywgaHlwZW5hdGUobmFtZXNwYWNlLCAnbmFtZScpKVxuICAgIGlmIChsYWJlbEVsZW1lbnQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICBsYWJlbEVsZW1lbnQudGV4dChsYWJlbClcblxuICAgICAgaWYgKG9yaWVudCA9PSAnbGVmdCcgfHwgb3JpZW50ID09ICdyaWdodCcpIHtcbiAgICAgICAgbGFiZWxFbGVtZW50LmF0dHIoJ3RyYW5zZm9ybScsICdyb3RhdGUoLTkwKScpXG4gICAgICB9XG5cbiAgICAgIHZhciBiYm94ID0gbGFiZWxFbGVtZW50Lm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVxuICAgICAgbGFiZWxOYW1lR3JvdXAuYXR0cigndHJhbnNmb3JtJyxmdW5jdGlvbihkLCBpKXtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSAwLFxuICAgICAgICB5ID0gMCxcbiAgICAgICAgdFxuXG4gICAgICAgIGlmIChvcmllbnQgPT0gJ2JvdHRvbScpIHtcbiAgICAgICAgICB4ID0gc3BhY2VYIC0gYmJveC53aWR0aCAtIHRpY2tMYWJlbE1hcmdpblxuICAgICAgICAgIHkgPSAtIHRpY2tUaWNrTGFiZWxTcGFjZXJcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChvcmllbnQgPT0gJ3RvcCcpIHtcbiAgICAgICAgICB4ID0gc3BhY2VYIC0gYmJveC53aWR0aCAtIHRpY2tMYWJlbE1hcmdpblxuICAgICAgICAgIHggPSB0aWNrTGFiZWxNYXJnaW5cbiAgICAgICAgICB5ID0gYmJveC5oZWlnaHQgKyB0aWNrVGlja0xhYmVsU3BhY2VyXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob3JpZW50ID09ICdsZWZ0Jykge1xuICAgICAgICAgIHggPSBiYm94LndpZHRoICsgdGlja1RpY2tMYWJlbFNwYWNlclxuICAgICAgICAgIHkgPSBiYm94LmhlaWdodCArIHRpY2tMYWJlbE1hcmdpblxuICAgICAgICB9IGVsc2UgaWYgKG9yaWVudCA9PSAncmlnaHQnKSB7XG4gICAgICAgICAgeCA9IC0oYmJveC53aWR0aCArIHRpY2tUaWNrTGFiZWxTcGFjZXIpXG4gICAgICAgICAgeSA9IGJib3guaGVpZ2h0ICsgdGlja0xhYmVsTWFyZ2luXG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgfVxuICAgICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICAgICAgIHJldHVybiB0XG4gICAgICB9KVxuXG5cblxuICAgIH0gZWxzZSB7XG4gICAgICBsYWJlbEVsZW1lbnQucmVtb3ZlKClcbiAgICB9XG4gICAgLypcbiAgICBJZGVhIGZyb20gU3RhY2sgT3ZlcmZsb3dcbiAgICBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy81MDU3OTUzNS9kMy1qcy12NC10cnVuY2F0ZS10ZXh0LXRvLWZpdC1pbi1maXhlZC1zcGFjZS81MDU4NTAyMj9ub3JlZGlyZWN0PTEjY29tbWVudDg4MjM1NTYyXzUwNTg1MDIyXG4gICAgdG8gdXNlIGNsaXAgcGF0aCB0byBtYWtlIHRoaW5ncyBmaXQgaW4gZml4ZWQgc2l6ZS4gSGF2ZSB5ZXQgZ290IHRoaXMgdG8gd29yayBuaWNlbHkuXG4gICAgKi9cbiAgICAvLyB2YXIgZGVmcyA9IGQzLnNlbGVjdChjb250YWluZXIubm9kZSgpLnBhcmVudE5vZGUpLnNlbGVjdCgnZGVmcycpXG4gICAgLy8gdmFyIHRpY2tMYWJlbENsaXBQYXRoID0gc2FmZVNlbGVjdChkZWZzLCAnY2xpcFBhdGgnLCBoeXBlbmF0ZShuYW1lc3BhY2UsJ3RpY2stbGFiZWwtY2xpcC1wYXRoJykpLmF0dHIoJ2lkJywgIGh5cGVuYXRlKG5hbWVzcGFjZSwndGljay1sYWJlbC1jbGlwLXBhdGgnKSlcbiAgICAvLyB2YXIgdGlja0xhYmVsQ2xpcFBhdGhSZWN0ID0gc2FmZVNlbGVjdCh0aWNrTGFiZWxDbGlwUGF0aCwgJ3JlY3QnLCAgaHlwZW5hdGUobmFtZXNwYWNlLCd0aWNrLWxhYmVsLWNsaXAtcGF0aC1yZWN0JykpXG4gICAgLy8gLmF0dHIoJ3gnLCAwKVxuICAgIC8vIC5hdHRyKCd5JywgMClcbiAgICAvLyAuYXR0cignd2lkdGgnLCBmdW5jdGlvbihkLCBpKXtcbiAgICAvLyAgIGlmIChob3Jpem9udGFsUSkgeyByZXR1cm4gdGlja0xhYmVsRm9udFNpemUgfVxuICAgIC8vICAgaWYgKHZlcnRpY2FsUSkgeyByZXR1cm4gc3BhY2VYIC0gdGlja0xlbmd0aCB9XG4gICAgLy8gfSlcbiAgICAvLyAuYXR0cignaGVpZ2h0JywgZnVuY3Rpb24oZCwgaSl7XG4gICAgLy8gICBpZiAodmVydGljYWxRKSB7IHJldHVybiB0aWNrTGFiZWxGb250U2l6ZSB9XG4gICAgLy8gICBpZiAoaG9yaXpvbnRhbFEpIHsgcmV0dXJuIHNwYWNlWSAtIHRpY2tMZW5ndGggfVxuICAgIC8vIH0pXG5cblxuICAgIC8vIGZvciBlYWNoIHRpY2sgY29udGFpbmVyXG4gICAgdmFyIHRpY2tzID0gY29udGFpbmVyLnNlbGVjdEFsbCgnZzpub3QoLnRvLXJlbW92ZSkuJytvYmpDbGFzcykuZWFjaChmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhciB0aGF0ID0gZDMuc2VsZWN0KHRoaXMpLnN0eWxlKCdvcGFjaXR5JywgMSlcblxuICAgICAgLy8gbWFrZSBhbmQgbW92ZSB0aWNrXG4gICAgICB2YXIgdGljayA9IHNhZmVTZWxlY3QodGhhdCwgJ2xpbmUnLCBoeXBlbmF0ZShuYW1lc3BhY2UsJ3RpY2snKSlcbiAgICAgIC5hdHRyKFwieDFcIiwgMClcbiAgICAgIC5hdHRyKFwieDJcIiwgaG9yaXpvbnRhbFEgPyAwIDogb3JpZW50ID09IFwibGVmdFwiID8gLXRpY2tMZW5ndGggOiB0aWNrTGVuZ3RoKVxuICAgICAgLmF0dHIoXCJ5MVwiLCAwKVxuICAgICAgLmF0dHIoJ3kyJywgIHZlcnRpY2FsUSA/IDAgOiBvcmllbnQgPT0gXCJ0b3BcIiA/IC10aWNrTGVuZ3RoIDogdGlja0xlbmd0aClcbiAgICAgIC5hdHRyKCdzdHJva2UnLCB0aWNrU3Ryb2tlKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIHRpY2tTdHJva2VXaWR0aClcbiAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgIHZhclxuICAgICAgICB4ID0gbW92ZVhCeShkLCBpLCBob3Jpem9udGFsUSwgY2F0ZWdvcmljYWxRLCBvYmplY3RTaXplKSxcbiAgICAgICAgeSA9IG1vdmVZQnkoZCwgaSwgdmVydGljYWxRLCBjYXRlZ29yaWNhbFEsIG9iamVjdFNpemUpLFxuICAgICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICAgICAgIHJldHVybiB0XG4gICAgICB9KVxuXG4gICAgICAvLyBtYWtlIGFuZCBtb3ZlIGxhYmVsXG4gICAgICB2YXIgbGFiZWwgPSBzYWZlU2VsZWN0KHRoYXQsICd0ZXh0JywgaHlwZW5hdGUobmFtZXNwYWNlLCdsYWJlbCcpKVxuICAgICAgLnRleHQoZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIHZhciBzID0gdHlwZW9mIGQgPT0gJ251bWJlcicgPyByb3VuZChkLCByb3VuZFRvKSA6IGRcbiAgICAgICAgcyA9IHRydW5jYXRlU3RyaW5nKFN0cmluZyhzKSwgKGhvcml6b250YWxRID8gc3BhY2VZIDogc3BhY2VYKSAtIHRpY2tMZW5ndGgtdGlja0xhYmVsTWFyZ2luLXRpY2tUaWNrTGFiZWxTcGFjZXIsIHRpY2tMYWJlbEZvbnRTaXplICogMC40NSlcbiAgICAgICAgcmV0dXJuIHNcbiAgICAgIH0pXG4gICAgICAuYXR0cignZm9udC1zaXplJywgdGlja0xhYmVsRm9udFNpemUpXG4gICAgICAuYXR0cigndGV4dC1hbmNob3InLCB0aWNrTGFiZWxUZXh0QW5jaG9yKVxuICAgICAgLy8gdHJ1bmNhdGVUZXh0KGxhYmVsLCBsYWJlbC50ZXh0KCksIG9yaWVudCwgdGlja0xlbmd0aCwgaG9yaXpvbnRhbFEgPyBzcGFjZVkgOiBzcGFjZVgsIG92ZXJmbG93USlcblxuICAgICAgbGFiZWwuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICB2YXJcbiAgICAgICAgcmVjdCA9IGQzLnNlbGVjdCh0aGlzKS5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksXG4gICAgICAgIGxlbmcgPSBkMy5zZWxlY3QodGhpcykubm9kZSgpLmdldENvbXB1dGVkVGV4dExlbmd0aCgpLFxuICAgICAgICB4ID0gbW92ZVhCeShkLCBpLCBob3Jpem9udGFsUSwgY2F0ZWdvcmljYWxRLCBvYmplY3RTaXplKSxcbiAgICAgICAgeSA9IG1vdmVZQnkoZCwgaSwgdmVydGljYWxRLCBjYXRlZ29yaWNhbFEsIG9iamVjdFNpemUpXG4gICAgICAgIC8vIG9uIHJlY2FsbCwgcmVjdCBjaGFuZ2VzIGJlY2F1c2Ugb2Ygcm90YXRpb24gc28gbmVlZCBNYXRoLm1pbihyZWN0LmhlaWdodCwgcmVjdC53aWR0aClcblxuICAgICAgICB2YXIgcyA9IE1hdGguc2luKHRpY2tMYWJlbFJvdGF0aW9uKSAqIGxlbmcgKiAwXG5cbiAgICAgICAgaWYgKG9yaWVudCA9PSAndG9wJykge1xuICAgICAgICAgIHkgPSAtKHRpY2tMZW5ndGgrdGlja1RpY2tMYWJlbFNwYWNlcik7XG4gICAgICAgICAgLy8geSA9IHRpY2tMZW5ndGgrdGlja1RpY2tMYWJlbFNwYWNlcjtcblxuICAgICAgICAgIC8vIHkgLT0gTWF0aC5tYXgocmVjdC5oZWlnaHQsIHJlY3Qud2lkdGgpO1xuICAgICAgICAgIHggKz0gTWF0aC5taW4ocmVjdC5oZWlnaHQsIHJlY3Qud2lkdGgpICogMC4yNVxuICAgICAgICAgIC8vIHggLT0gbGVuZyAqIDAuMjUgKyBzXG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9yaWVudCA9PSAnYm90dG9tJykge1xuICAgICAgICAgIHkgPSB0aWNrTGVuZ3RoK3RpY2tUaWNrTGFiZWxTcGFjZXI7XG4gICAgICAgICAgeCArPSBNYXRoLm1pbihyZWN0LmhlaWdodCwgcmVjdC53aWR0aCkgKiAwLjI1XG4gICAgICAgICAgLy8geCArPSBsZW5nICogMC4yNSAtIHNcbiAgICAgICAgfVxuICAgICAgICBpZiAob3JpZW50ID09ICdsZWZ0Jykge1xuICAgICAgICAgIHggLT0gKHRpY2tMZW5ndGgrdGlja1RpY2tMYWJlbFNwYWNlcik7XG4gICAgICAgICAgLy8geSArPSByZWN0LmhlaWdodCAqIDAuNTsgeS09IHJlY3QuaGVpZ2h0LzRcbiAgICAgICAgICB5ICs9IE1hdGgubWluKHJlY3QuaGVpZ2h0LCByZWN0LndpZHRoKSAqIDAuMjVcbiAgICAgICAgICAvLyB5ICs9IGxlbmcgKiAwLjI1XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9yaWVudCA9PSAncmlnaHQnKSB7XG4gICAgICAgICAgeCArPSAodGlja0xlbmd0aCt0aWNrVGlja0xhYmVsU3BhY2VyKTtcbiAgICAgICAgICAvLyB5ICs9IE1hdGgubWluKHJlY3QuaGVpZ2h0LCByZWN0LndpZHRoKSAqIDAuMjVcbiAgICAgICAgICAvLyB5ICs9IGxlbmcgKiAwLjI1XG4gICAgICAgICAgeSArPSByZWN0LmhlaWdodCAqIDAuNTsgeS09IHJlY3QuaGVpZ2h0LzRcbiAgICAgICAgfVxuXG4gICAgICAgIHZhclxuICAgICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknLFxuICAgICAgICByID0gJ3JvdGF0ZSgnK3RpY2tMYWJlbFJvdGF0aW9uKycpJ1xuICAgICAgICByZXR1cm4gdCArIHJcbiAgICAgIH0pXG4gICAgICAub24oJ21vdXNlbW92ZScsIGxhYmVsSG92ZXIpXG4gICAgICAub24oJ21vdXNlb3V0JywgbGFiZWxIb3Zlck9mZilcbiAgICAgIC5vbignY2xpY2snLCB0aWNrTGFiZWxPbkNsaWNrKVxuICAgICAgLy8gLmF0dHIoJ2NsaXAtcGF0aCcsICd1cmwoIycraHlwZW5hdGUobmFtZXNwYWNlLCd0aWNrLWxhYmVsLWNsaXAtcGF0aCcpKycpJylcblxuICAgICAgLy8gYWRkIGd1aWRsaW5lcyBhcyBuZWVkZWRcbiAgICAgICBpZiAoZ3VpZGVMaW5lc1EpIHtcbiAgICAgICAgIHZhciBnbGluZSA9IHNhZmVTZWxlY3QodGhhdCwgJ2xpbmUnLCBoeXBlbmF0ZShuYW1lc3BhY2UsICdndWlkZWxpbmUnKSlcbiAgICAgICAgIC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgICAgLmF0dHIoXCJ4MVwiLCAwKVxuICAgICAgICAgLmF0dHIoXCJ4MlwiLCBob3Jpem9udGFsUSA/IDAgOiBvcmllbnQgPT0gXCJsZWZ0XCIgPyBndWlkZWxpbmVTcGFjZSA6IC1ndWlkZWxpbmVTcGFjZSlcbiAgICAgICAgIC5hdHRyKFwieTFcIiwgMClcbiAgICAgICAgIC5hdHRyKCd5MicsICB2ZXJ0aWNhbFEgPyAwIDogb3JpZW50ID09IFwidG9wXCIgPyBndWlkZWxpbmVTcGFjZSA6IC1ndWlkZWxpbmVTcGFjZSlcbiAgICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgIHZhclxuICAgICAgICAgICB4ID0gbW92ZVhCeShkLCBpLCBob3Jpem9udGFsUSwgY2F0ZWdvcmljYWxRLCBvYmplY3RTaXplKSxcbiAgICAgICAgICAgeSA9IG1vdmVZQnkoZCwgaSwgdmVydGljYWxRLCBjYXRlZ29yaWNhbFEsIG9iamVjdFNpemUpLFxuICAgICAgICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICAgICAgICAgIHJldHVybiB0XG4gICAgICAgICB9KVxuICAgICAgIH0gZWxzZSB7IHRoYXQuc2VsZWN0KCdsaW5lLicraHlwZW5hdGUobmFtZXNwYWNlLCAnZ3VpZGVsaW5lJykpLnJlbW92ZSgpIH1cblxuICAgIH0pXG5cbiAgICAvLyBhcHBseSBhbHRlcm5hdGluZyBndWlkbGluZSB0aGlja25lc3NcbiAgICBpZiAoZ3VpZGVMaW5lc1EpIHtcbiAgICAgIGNvbnRhaW5lci5zZWxlY3RBbGwoJy4nK2h5cGVuYXRlKG5hbWVzcGFjZSwnZ3VpZGVsaW5lJykpXG4gICAgICAuYXR0cignc3Ryb2tlJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIGlmIChpICUgMiA9PSAwKSB7IHJldHVybiBtb2RpZnlIZXhpZGVjaW1hbENvbG9yTHVtaW5hbmNlKGd1aWRlTGluZVN0cm9rZSwgMC44KSB9XG4gICAgICAgIHJldHVybiBndWlkZUxpbmVTdHJva2VcbiAgICAgIH0pXG4gICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIGlmIChpICUgMiA9PSAwKSB7IHJldHVybiBndWlkZUxpbmVTdHJva2VXaWR0aCAqMC44fVxuICAgICAgICByZXR1cm4gZ3VpZGVMaW5lU3Ryb2tlV2lkdGhcbiAgICAgIH0pXG4gICAgICAuYXR0cignbWlub3InLCBmdW5jdGlvbihkLCBpKXtyZXR1cm4gaSUyID09IDB9KVxuICAgIH1cblxuXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICoqIE1ha2UgdGhlIGxpbmUgb2YgdGhlIGF4aXNcbiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4gICAgdmFyIGxpbmUgPSBzYWZlU2VsZWN0KHNlbGVjdGlvbiwgJ3BhdGgnLCBoeXBlbmF0ZShuYW1lc3BhY2UsJ2xpbmUnKSlcbiAgICAvLyAuYXR0cigneDEnLCAwKVxuICAgIC8vIC5hdHRyKCd4MicsIGhvcml6b250YWxRID8gc3BhY2VYIDogMClcbiAgICAvLyAuYXR0cigneTEnLCAwKVxuICAgIC8vIC5hdHRyKCd5MicsIGhvcml6b250YWxRID8gMCA6IHNwYWNlWSlcbiAgICAuYXR0cignZCcsXG4gICAgICBob3Jpem9udGFsUVxuICAgICAgPyAnTSAwLDAgSCcgKyBzcGFjZVggKyAnLDAnXG4gICAgICA6ICdNIDAsMCBWIDAsJyArIHNwYWNlWVxuICAgIClcbiAgICAuYXR0cignc3Ryb2tlJywgbGluZVN0cm9rZSlcbiAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgbGluZVN0cm9rZVdpZHRoKVxuICAgIC5jbGFzc2VkKCdheGlzLWxpbmUnLCB0cnVlKVxuXG5cbiAgfVxuXG4gIC8vIGhvdmVyIG9mIGxhYmVsIHNob3cgZnVsbCB0ZXh0IGxhYmVsIGluIGNhc2UgaXQgaXMgdHJ1bmNhdGVkXG4gIGZ1bmN0aW9uIGxhYmVsSG92ZXIoZCwgaSl7XG4gICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcykuc3R5bGUoJ2ZpbGwnLCAncmVkJylcbiAgICBkMy5zZWxlY3QodC5ub2RlKCkucGFyZW50Tm9kZSkuc2VsZWN0KFwibGluZS5cIitoeXBlbmF0ZShuYW1lc3BhY2UsJ3RpY2snKSlcbiAgICAuYXR0cihcInN0cm9rZVwiLCAncmVkJylcbiAgICAuYXR0cihcInN0cm9rZS13aWR0aFwiLCB0aWNrU3Ryb2tlV2lkdGgqMilcblxuICAgIGlmIChndWlkZUxpbmVzUSkge1xuICAgICAgZDMuc2VsZWN0KHQubm9kZSgpLnBhcmVudE5vZGUpLnNlbGVjdCgnbGluZS4nK2h5cGVuYXRlKG5hbWVzcGFjZSwgJ2d1aWRlbGluZScpKVxuICAgICAgLmF0dHIoJ3N0cm9rZScsICdyZWQnKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGd1aWRlTGluZVN0cm9rZVdpZHRoKjIpXG4gICAgfVxuXG4gICAgdmFyIHMgPSB0eXBlb2YgZCA9PSAnbnVtYmVyJyA/IHJvdW5kKGQsIHJvdW5kVG8pIDogZFxuXG4gICAgdmFyIG0gPSBkMy5tb3VzZShkMy5zZWxlY3QoJ2h0bWwnKS5ub2RlKCkpXG4gICAgdmFyIGRpdiA9IHNhZmVTZWxlY3QoZDMuc2VsZWN0KCdib2R5JyksICdkaXYnLCBoeXBlbmF0ZShuYW1lc3BhY2UsJ2d1aWRlbGluZS10b29sdGlwJykpXG4gICAgLmF0dHIoJ2lkJywgaHlwZW5hdGUobmFtZXNwYWNlLCdndWlkZWxpbmUtdG9vbHRpcCcpKVxuICAgIC5zdHlsZSgncG9zaXRpb24nLCAnYWJzb2x1dGUnKVxuICAgIC5zdHlsZSgnbGVmdCcsIChkMy5ldmVudC5wYWdlWCsxNSkrJ3B4JylcbiAgICAuc3R5bGUoJ3RvcCcsIChkMy5ldmVudC5wYWdlWSsxNSkrJ3B4JylcbiAgICAuc3R5bGUoJ2JhY2tncm91bmQtY29sb3InLCAnd2hpdGUnKVxuICAgIC5zdHlsZSgnYm9yZGVyLWNvbG9yJywgJ2JsYWNrJylcbiAgICAvLyAuc3R5bGUoJ21pbi13aWR0aCcsICh0aWNrTGFiZWxGb250U2l6ZSAqIChTdHJpbmcocykuc3BsaXQoJy4nKVswXS5sZW5ndGgrMykpKydweCcpXG4gICAgLy8gLnN0eWxlKCdtaW4taGVpZ2h0JywgKHRpY2tMYWJlbEZvbnRTaXplICogKFN0cmluZyhzKS5zcGxpdCgnLicpWzBdLmxlbmd0aCszKSkrJ3B4JylcbiAgICAuc3R5bGUoJ2JvcmRlci1yYWRpdXMnLCAnMTBweCcpXG4gICAgLnN0eWxlKCdkaXNwbGF5JywgJ2ZsZXgnKVxuICAgIC5zdHlsZSgnanVzdGlmeS1jb250ZW50JywgJ2NlbnRlcicpXG4gICAgLnN0eWxlKCd0ZXh0LWFsaWduJywgJ21pZGRsZScpXG4gICAgLnN0eWxlKCdwYWRkaW5nJywgNCtcInB4XCIpXG5cbiAgICAuc3R5bGUoJ2JvcmRlci1zdHlsZScsICdzb2xpZCcpXG4gICAgLnN0eWxlKCdib3JkZXItd2lkdGgnLCAyKVxuXG4gICAgdmFyIHRleHQgPSBzYWZlU2VsZWN0KGRpdiwgJ2RpdicpXG4gICAgLnRleHQodGlja0xhYmVsT25Ib3ZlckZ1bmMocywgaSkpXG4gICAgLnN0eWxlKCdjb2xvcicsICdibGFjaycpXG4gICAgLnN0eWxlKCdhbGlnbi1zZWxmJywgJ2NlbnRlcicpXG5cbiAgICB2YXIgYmJveCA9IGRpdi5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClcbiAgICBpZiAoYmJveC54ICsgYmJveC53aWR0aCA+IHdpbmRvdy5pbm5lcldpZHRoKSB7XG4gICAgICBkaXYuc3R5bGUoJ2xlZnQnLCAoZDMuZXZlbnQucGFnZVgtMTUtMzAwKSsncHgnKVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGxhYmVsSG92ZXJPZmYoZCwgaSl7XG4gICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcykuc3R5bGUoJ2ZpbGwnLCAnYmxhY2snKVxuICAgIGQzLnNlbGVjdCh0Lm5vZGUoKS5wYXJlbnROb2RlKS5zZWxlY3QoXCJsaW5lLlwiK2h5cGVuYXRlKG5hbWVzcGFjZSwndGljaycpKVxuICAgIC5hdHRyKFwic3Ryb2tlXCIsIHRpY2tTdHJva2UpXG4gICAgLmF0dHIoXCJzdHJva2Utd2lkdGhcIiwgdGlja1N0cm9rZVdpZHRoKVxuXG4gICAgaWYgKGd1aWRlTGluZXNRKSB7XG4gICAgICB2YXIgZ2xpbmUgPSBkMy5zZWxlY3QodC5ub2RlKCkucGFyZW50Tm9kZSkuc2VsZWN0KCdsaW5lLicraHlwZW5hdGUobmFtZXNwYWNlLCAnZ3VpZGVsaW5lJykpXG4gICAgICB2YXIgbWlub3JRID0gZ2xpbmUuYXR0cignbWlub3InKVxuICAgICAgZ2xpbmUuYXR0cignc3Ryb2tlJywgZnVuY3Rpb24oZCwgaWkpe1xuICAgICAgICBpZiAobWlub3JRID09ICd0cnVlJykgeyByZXR1cm4gbW9kaWZ5SGV4aWRlY2ltYWxDb2xvckx1bWluYW5jZShndWlkZUxpbmVTdHJva2UsIDAuOCkgfVxuICAgICAgICByZXR1cm4gZ3VpZGVMaW5lU3Ryb2tlXG4gICAgICB9KVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGZ1bmN0aW9uKGQsIGlpKXtcbiAgICAgICAgaWYgKG1pbm9yUSA9PSAndHJ1ZScpIHsgcmV0dXJuIGd1aWRlTGluZVN0cm9rZVdpZHRoICowLjh9XG4gICAgICAgIHJldHVybiBndWlkZUxpbmVTdHJva2VXaWR0aFxuICAgICAgfSlcbiAgICB9XG4gICAgZDMuc2VsZWN0KFwiI1wiK2h5cGVuYXRlKG5hbWVzcGFjZSwnZ3VpZGVsaW5lLXRvb2x0aXAnKSkucmVtb3ZlKClcbiAgfVxuXG5cblxuICByZXR1cm4gYXhpc1xufVxuIiwiaW1wb3J0IHtoeXBlbmF0ZSwgc2FmZVNlbGVjdH0gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7c2V0dXBDb250YWluZXIsIGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3QsIGNhbGN1bGF0ZVdpZHRoT2ZTcGFjZXJ9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHt1bmlxdWUsIGZsYXR0ZW59IGZyb20gJy4vYXJyYXktZnVuY3Rpb25zJztcbmltcG9ydCB7Z3JvdXBpbmdTcGFjZXJ9IGZyb20gJy4vZ3JvdXBpbmctc3BhY2VyJztcbmltcG9ydCB7Y29sb3JGdW5jdGlvbiBhcyBDRn0gZnJvbSAnLi9jb2xvci1mdW5jdGlvbic7XG5pbXBvcnQge3Rvb2x0aXAgYXMgVFRpcH0gZnJvbSAnLi90b29sdGlwJztcbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCQVIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbi8qKlxuICogQ3JlYXRlcyBhIGJhclxuICpcbiAqIHtAbGluayBodHRwczovL3N1bW5ldXJvbi5naXRsYWIuaW8vZDNzbS9kZW1vcy9iYXItY2hhcnQtc2FtZS1kYXRhLWNvbXBsZXgtZ3JvdXBpbmcvaW5kZXguaHRtbCBEZW1vfVxuICogQGNvbnN0cnVjdG9yIGJhclxuICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IHNlbGVjdGlvblxuICogQG5hbWVzcGFjZSBiYXJcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gYmFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBiYXIgKCBzZWxlY3Rpb24gKSB7XG4gIC8qXG4gIEFzc3VtZXMgdGhhdCBkYXRhIGlzIGxpc3QgYW4gb2JqZWN0LlxuXG4gIFRoZSBrZXlzIG9mIGRhdGEgd2lsbCBiZSBib3VuZCB0byB0aGUgYmFycy5cbiAgVGhlIHZhbHVlRXh0cmFjdG9yIGZ1bmN0aW9uIHdpbGwgZXh0cmFjdCB0aGUgdmFsdWUgZnJvbSBkYXRhW2tleV0uXG5cbiAgR3JvdXBpbmcgY2FuIGJlIHVzZWQgaWYgZGVzaXJlZC4gSXQgc2hvdWxkIGJlIGFuIGFyYml0cmFyeSBjb21wbGV4IGxpc3Qgd2hlcmVcbiAgdGhlIHZhbHVlcyBhcmUgc3RyaW5ncyBtYXRjaGluZyBrZXlzIGluIGRhdGEuXG4gICovXG4gIHZhclxuICAvKipcbiAgKiBEYXRhIHRvIHBsb3QuIEFzc3VtZWQgdG8gYmUgYSBvYmplY3QsIHdoZXJlIGVhY2gga2V5IGNvcnJlc3BvbmRzIHRvIGEgYmFyXG4gICogKHNlZSB7QGxpbmsgYmFyI2RhdGF9KVxuICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZGF0YSxcbiAgLyoqXG4gICogV2hpY2ggZGlyZWN0aW9uIHRvIHJlbmRlciB0aGUgYmFycyBpblxuICAqIChzZWUge0BsaW5rIGJhciNvcmllbnR9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbb3JpZW50PSdob3Jpem9udGFsJ11cbiAgKiBAbWVtYmVyb2YgYmFyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvcmllbnQ9J2hvcml6b250YWwnLFxuICAvKipcbiAgKiBBbW91bnQgb2YgaG9yaXpvbnRhbCBzcGFjZSAoaW4gcGl4ZWxzKSBhdmFpYmxlIHRvIHJlbmRlciB0aGUgYmFyIGluXG4gICogKHNlZSB7QGxpbmsgYmFyI3NwYWNlWH0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZVg9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNwYWNlWCxcbiAgLyoqXG4gICogQW1vdW50IG9mIHZlcnRpY2FsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSBiYXIgaW5cbiAgKiAoc2VlIHtAbGluayBiYXIuc3BhY2VZfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlWT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VZLFxuXG4gIC8qKlxuICAqIFdoZXRoZXIgb3Igbm90IHRvIGFsbG93IGJhciB0byByZW5kZXIgZWxlbWVudHMgcGFzcyB0aGUgbWFpbiBzcGF0aWFsIGRpbWVuc2lvblxuICAqIGdpdmVuIHRoZSBvcmllbnRhdGlvbiAoc2VlIHtAbGluayBiYXIjb3JpZW50fSksIHdoZXJlIHtAbGluayBiYXIjb3JpZW50fT1cImhvcml6b250YWxcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgYmFyI3NwYWNlWH0gYW5kIHdoZXJlIHtAbGluayBiYXIjb3JpZW50fT1cInZlcnRpY2FsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJhciNzcGFjZVl9XG4gICogQHBhcmFtIHtib29sZWFufSBbb3ZlcmZsb3dRPWZhbHNlXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG92ZXJmbG93USA9IGZhbHNlLFxuXG4gIC8qKlxuICAqIEFuIGFycmF5IC0gcHV0YXRpdmVseSBvZiBvdGhlciBhcnJheXMgLSBkZXBpY3RpbmcgaG93IGJhcnMgc2hvdWxkIGJlIGFycmFuZ2VkXG4gICogQHBhcmFtIHtBcnJheVtdfSBbZ3JvdXBpbmc9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGdyb3VwaW5nLFxuXG4gIC8qKlxuICAqIEhvdyB0byBnZXQgdGhlIHZhbHVlIG9mIHRoZSBiYXJcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbdmFsdWVFeHRyYWN0b3I9ZnVuY3Rpb24oa2V5LCBpbmRleCkgeyByZXR1cm4gZGF0YVtrZXldIH1dXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGluZGV4KSB7IHJldHVybiBkYXRhW2tleV0gfSxcbiAgLyoqXG4gICogSG93IHRvIHNvcnQgdGhlIGJhcnMgLSBpZiB7QGxpbmsgYmFyI2dyb3VwaW5nfSBpcyBub3QgcHJvdmlkZWQuXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3NvcnRpbmdGdW5jdGlvbj1mdW5jdGlvbihrZXlBLCBrZXlCKSB7cmV0dXJuIGQzLmRlc2NlbmRpbmcoZGF0YVtrZXlBXSwgZGF0YVtrZXlCXSl9XVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKGtleUEsIGtleUIpIHtyZXR1cm4gZDMuZGVzY2VuZGluZyhkYXRhW2tleUFdLCBkYXRhW2tleUJdKX0sXG5cbiAgLyoqXG4gICogVGhlIHNjYWxlIGZvciB3aGljaCBiYXIgdmFsdWVzIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBieVxuICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtzY2FsZT1kMy5zY2FsZUxpbmVhcl1cbiAgKiBAbWVtYmVyb2YgYmFyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKCksXG4gIC8qKlxuICAqIFRoZSBwYWRkaW5nIGZvciB0aGUgZG9tYWluIG9mIHRoZSBzY2FsZSAoc2VlIHtAbGluayBiYXIjc2NhbGV9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbZG9tYWluUGFkZGluZz0wLjVdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZG9tYWluUGFkZGluZyA9IDAuNSxcblxuICAvKipcbiAgKiBEZWZhdWx0IHNwYWNlIGZvciB0aGUgc3BhY2VyIChwZXJjZW50YWdlKSBvZiBtYWluIGRpbWVuc2lvbiBnaXZlbiB0aGUgb3JpZW50YXRpb25cbiAgKiAoc2VlIHtAbGluayBiYXIjb3JpZW50fSksIHdoZXJlIHtAbGluayBiYXIjb3JpZW50fT1cImhvcml6b250YWxcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgYmFyI3NwYWNlWH0gYW5kIHdoZXJlIHtAbGluayBiYXIjb3JpZW50fT1cInZlcnRpY2FsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJhciNzcGFjZVl9IGJldHdlZW4gYmFyc1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbb2JqZWN0U3BhY2VyPTAuMDVdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0U3BhY2VyID0gMC4wNSxcbiAgLyoqXG4gICogVGhlIG1pbmltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmVcbiAgKiBAcGFyYW0ge251bWJlcn0gW21pbk9iamVjdFNpemU9NTBdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbWluT2JqZWN0U2l6ZSA9IDUwLFxuICAvKipcbiAgKiBUaGUgbWF4aW11bSBzaXplIHRoYXQgYW4gb2JqZWN0IGNhbiBiZVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbbWF4T2JqZWN0U2l6ZT0xMDBdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbWF4T2JqZWN0U2l6ZSA9IDEwMCxcblxuICAvKipcbiAgKiBUaGUgc3Ryb2tlIHdpZHRoIG9mIHRoZSBiYXJzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtiYXJTdHJva2VXaWR0aD0yXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJhclN0cm9rZVdpZHRoID0gMixcbiAgLyoqXG4gICogSW5zdGFuY2Ugb2YgQ29sb3JGdW5jdGlvblxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtjb2xvckZ1bmN0aW9uID0gY29sb3JGdW5jdGlvbigpXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGNvbG9yRnVuY3Rpb24gPSBDRigpLFxuXG5cbiAgLyoqXG4gICogQ29sb3Igb2YgdGhlIGJhY2tncm91bmRcbiAgKiBAcGFyYW0ge3N0cmluZ30gW2JhY2tncm91bmRGaWxsPVwidHJhbnNwYXJlbnRcIl1cbiAgKiBAbWVtYmVyb2YgYmFyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCcsXG4gIC8qKlxuICAqIE5hbWVzcGFjZSBmb3IgYWxsIGl0ZW1zIG1hZGUgYnkgdGhpcyBpbnN0YW5jZSBvZiBiYXJcbiAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWVzcGFjZT1cImQzc20tYmFyXCJdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbmFtZXNwYWNlID0gJ2Qzc20tYmFyJyxcbiAgLyoqXG4gICogQ2xhc3MgbmFtZSBmb3IgYmFyIGNvbnRhaW5lciAoPGc+IGVsZW1lbnQpXG4gICogQHBhcmFtIHtzdHJpbmd9IFtvYmplY3RDbGFzcz1cImJhclwiXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdENsYXNzID0gJ2JhcicsXG5cbiAgLyoqXG4gICogRHVyYXRpb24gb2YgYWxsIHRyYW5zaXRpb25zIG9mIHRoaXMgZWxlbWVudFxuICAqIEBwYXJhbSB7bnVtYmVyfSBbdHJhbnNpdGlvbkR1cmF0aW9uPTEwMDBdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdHJhbnNpdGlvbkR1cmF0aW9uID0gMTAwMCxcbiAgLyoqXG4gICogRWFzaW5nIGZ1bmN0aW9uIGZvciB0cmFuc2l0aW9uc1xuICAqIEBwYXJhbSB7ZDMuZWFzZX0gW2Vhc2VGdW5jPWQzLmVhc2VFeHBdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwLFxuXG4gIC8vIHVzZWZ1bCB2YWx1ZXMgdG8gZXh0cmFjdCB0byBwcmV2ZW50IHJlLWNhbGN1bGF0aW9uXG4gIC8qKlxuICAqIFRoZSBrZXlzIG9mIHRoZSBiYXJzXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW2JhcktleXM9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJhcktleXMsXG4gIC8qKlxuICAqIFRoZSB2YWx1ZXMgb2YgdGhlIGJhcnNcbiAgKiBAcGFyYW0ge251bWJlcltdfSBbYmFyVmFsdWVzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYmFyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBiYXJWYWx1ZXMsXG4gIC8qKlxuICAqIFRoZSBvYmplY3RTaXplIChhY3R1YWwgd2lkdGgpIHVzZWQgYnkgdGhlIGJhcnNcbiAgKiBAcGFyYW0ge251bWJlcn0gW29iamVjdFNpemU9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBiYXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdFNpemUsXG4gIC8qKlxuICAqIFRoZSBzcGFjZXJTaXplIChhY3R1YWwgd2lkdGgpIHVzZWQgYnkgdGhlIHNwYWNlcnMgYmV0d2VlbiB0aGUgYmFyc1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbc3BhY2VyU2l6ZT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VyU2l6ZSxcbiAgLyoqXG4gICogSW5zdGFuY2Ugb2YgVG9vbHRpcFxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFt0b29sdGlwPXRvb2x0aXAoKV1cbiAgKiBAbWVtYmVyb2YgYmFyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0b29sdGlwID0gVFRpcCgpLFxuICBiYXJQZXJjZW50ID0gMVxuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHNlbGVjdGlvbiBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBkMy5zZWxlY3Rpb259XG4gICAqIEBtZW1iZXJvZiBiYXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc2VsZWN0aW9uID0gc2VsZWN0aW9uXG4gICAqL1xuICBiYXIuc2VsZWN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZWxlY3Rpb24gPSBfLCBiYXIpIDogc2VsZWN0aW9uOyB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBkYXRhXG4gICAqIChzZWUge0BsaW5rIGJhciNkYXRhfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBvYmplY3R9XG4gICAqIEBtZW1iZXJvZiBiYXJcbiAgICogQHByb3BlcnR5XG4gICAqL1xuICBiYXIuZGF0YSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGF0YSA9IF8sIGJhcikgOiBkYXRhOyB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBvcmllbnQgb2YgdGhlIGJhcnNcbiAgICogKHNlZSB7QGxpbmsgYmFyI29yaWVudH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YmFyIHwgb2JqZWN0fVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgYmFyLm9yaWVudCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3JpZW50ID0gXywgYmFyKSA6IG9yaWVudDsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgYW1vdW50IG9mIGhvcml6b250YWwgc3BhY2UgaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIGJhciNzcGFjZVh9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV0gc2hvdWxkIGJlIGEgbnVtYmVyID4gMFxuICAgKiBAcmV0dXJucyB7YmFyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlWCA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmFyLnNwYWNlWCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3BhY2VYID0gXywgYmFyKSA6IHNwYWNlWDsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgYW1vdW50IG9mIHZlcnRpY2FsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBiYXIjc3BhY2VZfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge2JhciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVkgPSB1bmRlZmluZWRcbiAgICovXG4gIGJhci5zcGFjZVkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWSA9IF8sIGJhcikgOiBzcGFjZVk7IH07XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IGJhciBpcyBhbGxvd2VkIHRvIGdvIGJleW9uZCBzcGVjaWZpZWQgZGltZW5zaW9uc1xuICAgKiAoc2VlIHtAbGluayBiYXIjc3BhY2VYfSlcbiAgICogQHBhcmFtIHtib29sZWFufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YmFyIHwgYm9vbGVhbn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvdmVyZmxvd1EgPSBmYWxzZVxuICAgKi9cbiAgYmFyLm92ZXJmbG93USA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3ZlcmZsb3dRID0gXywgYmFyKSA6IG92ZXJmbG93UTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBncm91cGluZyBvZiB0aGUgYmFyc1xuICAgKiAoc2VlIHtAbGluayBiYXIjZ3JvdXBpbmd9KVxuICAgKiBAcGFyYW0ge0FycmF5W119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBBcnJheVtdfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGdyb3VwaW5nID0gdW5kZWZpbmVkXG4gICAqL1xuICBiYXIuZ3JvdXBpbmcgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGdyb3VwaW5nID0gXywgYmFyKSA6IGdyb3VwaW5nOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHZhbHVlRXh0cmFjdG9yXG4gICAqIChzZWUge0BsaW5rIGJhciN2YWx1ZUV4dHJhY3Rvcn0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB2YWx1ZUV4dHJhY3RvciA9IGZ1bmN0aW9uKGtleSwgaW5kZXgpIHsgcmV0dXJuIGRhdGFba2V5XSB9LFxuICAgKi9cbiAgYmFyLnZhbHVlRXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZUV4dHJhY3RvciA9IF8sIGJhcikgOiB2YWx1ZUV4dHJhY3RvcjsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzb3J0aW5nRnVuY3Rpb25cbiAgICogKHNlZSB7QGxpbmsgYmFyI3NvcnRpbmdGdW5jdGlvbn0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihrZXlBLCBrZXlCKSB7cmV0dXJuIGQzLmRlc2NlbmRpbmcoZGF0YVtrZXlBXSwgZGF0YVtrZXlCXSl9LFxuICAgKi9cbiAgYmFyLnNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc29ydGluZ0Z1bmN0aW9uID0gXywgYmFyKSA6IHNvcnRpbmdGdW5jdGlvbjsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzY2FsZSBmb3Igd2hpY2ggdGhlIGJhciB2YWx1ZXMgc2hvdWxkIGJlIHRyYW5zZm9ybWVkIGJ5XG4gICAqIChzZWUge0BsaW5rIGJhciNzY2FsZX0pXG4gICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBkMy5zY2FsZX1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKClcbiAgICovXG4gIGJhci5zY2FsZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGUgPSBfLCBiYXIpIDogc2NhbGU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcGFkZGluZyBmb3IgdGhlIGRvbWFpbiBvZiB0aGUgc2NhbGVcbiAgICogKHNlZSB7QGxpbmsgYmFyI2RvbWFpblBhZGRpbmd9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBkb21haW5QYWRkaW5nID0gMC41XG4gICAqL1xuICBiYXIuZG9tYWluUGFkZGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluUGFkZGluZyA9IF8sIGJhcikgOiBkb21haW5QYWRkaW5nOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgb2JqZWN0U3BhY2VyXG4gICAqIChzZWUge0BsaW5rIGJhciNvYmplY3RTcGFjZXJ9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RTcGFjZXIgPSAwLjA1XG4gICAqL1xuICBiYXIub2JqZWN0U3BhY2VyID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvYmplY3RTcGFjZXIgPSBfLCBiYXIpIDogb2JqZWN0U3BhY2VyOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1pbk9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgYmFyI21pbk9iamVjdFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBtaW5PYmplY3RTaXplID0gNTBcbiAgICovXG4gIGJhci5taW5PYmplY3RTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChtaW5PYmplY3RTaXplID0gXywgYmFyKSA6IG1pbk9iamVjdFNpemU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbWF4T2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayBiYXIjbWF4T2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YmFyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1heE9iamVjdFNpemUgPSAxMDBcbiAgICovXG4gIGJhci5tYXhPYmplY3RTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChtYXhPYmplY3RTaXplID0gXywgYmFyKSA6IG1heE9iamVjdFNpemU7IH07XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBiYXJTdHJva2VXaWR0aFxuICAgKiAoc2VlIHtAbGluayBiYXIjYmFyU3Ryb2tlV2lkdGh9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBiYXJTdHJva2VXaWR0aCA9IDJcbiAgICovXG4gIGJhci5iYXJTdHJva2VXaWR0aCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFyU3Ryb2tlV2lkdGggPSBfLCBiYXIpIDogYmFyU3Ryb2tlV2lkdGg7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgY29sb3JGdW5jdGlvblxuICAgKiAoc2VlIHtAbGluayBiYXIjY29sb3JGdW5jdGlvbn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YmFyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGNvbG9yRnVuY3Rpb24gPSBjb2xvckZ1bmN0aW9uKClcbiAgICovXG4gIGJhci5jb2xvckZ1bmN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjb2xvckZ1bmN0aW9uID0gXywgYmFyKSA6IGNvbG9yRnVuY3Rpb247IH07XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBiYWNrZ3JvdW5kRmlsbFxuICAgKiAoc2VlIHtAbGluayBiYXIjYmFja2dyb3VuZEZpbGx9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCdcbiAgICovXG4gIGJhci5iYWNrZ3JvdW5kRmlsbCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFja2dyb3VuZEZpbGwgPSBfLCBiYXIpIDogYmFja2dyb3VuZEZpbGw7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbmFtZXNwYWNlXG4gICAqIChzZWUge0BsaW5rIGJhciNuYW1lc3BhY2V9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBuYW1lc3BhY2UgPSAnZDNzbS1iYXInXG4gICAqL1xuICBiYXIubmFtZXNwYWNlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChuYW1lc3BhY2UgPSBfLCBiYXIpIDogbmFtZXNwYWNlOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG9iamVjdENsYXNzXG4gICAqIChzZWUge0BsaW5rIGJhciNvYmplY3RDbGFzc30pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YmFyIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG9iamVjdENsYXNzID0gJ3RpY2stZ3JvdXAnXG4gICAqL1xuICBiYXIub2JqZWN0Q2xhc3MgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdENsYXNzID0gXywgYmFyKSA6IG9iamVjdENsYXNzOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRyYW5zaXRpb25EdXJhdGlvblxuICAgKiAoc2VlIHtAbGluayBiYXIjdHJhbnNpdGlvbkR1cmF0aW9ufSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBiYXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdHJhbnNpdGlvbkR1cmF0aW9uID0gMTAwMFxuICAgKi9cbiAgYmFyLnRyYW5zaXRpb25EdXJhdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodHJhbnNpdGlvbkR1cmF0aW9uID0gXywgYmFyKSA6IHRyYW5zaXRpb25EdXJhdGlvbjsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBlYXNlRnVuY1xuICAgKiAoc2VlIHtAbGluayBiYXIjZWFzZUZ1bmN9KVxuICAgKiBAcGFyYW0ge2QzLmVhc2V9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBkMy5lYXNlfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGVhc2VGdW5jID0gZDMuZWFzZUV4cFxuICAgKi9cbiAgYmFyLmVhc2VGdW5jID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChlYXNlRnVuYyA9IF8sIGJhcikgOiBlYXNlRnVuYzsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYmFyS2V5c1xuICAgKiAoc2VlIHtAbGluayBiYXIjYmFyS2V5c30pXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBzdHJpbmdbXX1cbiAgICogQG1lbWJlcm9mIGJhclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBiYXJLZXlzID0gdW5kZWZpbmVkXG4gICAqL1xuICBiYXIuYmFyS2V5cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFyS2V5cyA9IF8sIGJhcikgOiBiYXJLZXlzOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGJhclZhbHVlc1xuICAgKiAoc2VlIHtAbGluayBiYXIjYmFyVmFsdWVzfSlcbiAgICogQHBhcmFtIHtudW1iZXJbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JhciB8IG51bWJlcltdfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGJhclZhbHVlcyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmFyLmJhclZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFyVmFsdWVzID0gXywgYmFyKSA6IGJhclZhbHVlczsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RTaXplXG4gICAqIChzZWUge0BsaW5rIGJhciNvYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBiYXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0U2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmFyLm9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNpemUgPSBfLCBiYXIpIDogb2JqZWN0U2l6ZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzcGFjZXJTaXplXG4gICAqIChzZWUge0BsaW5rIGJhciNzcGFjZXJTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBiYXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc3BhY2VyU2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmFyLnNwYWNlclNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlclNpemUgPSBfLCBiYXIpIDogc3BhY2VyU2l6ZTsgfTtcblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRvb2x0aXBcbiAgICogKHNlZSB7QGxpbmsgYmFyI3Rvb2x0aXB9KVxuICAgKiBAcGFyYW0ge3Rvb2x0aXB9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtiYXIgfCB0b29sdGlwfVxuICAgKiBAbWVtYmVyb2YgYmFyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRvb2x0aXAgPSB0b29sdGlwKClcbiAgICovXG4gIGJhci50b29sdGlwID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0b29sdGlwID0gXywgYmFyKSA6IHRvb2x0aXA7IH07XG5cbiAgYmFyLmJhclBlcmNlbnQgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJhclBlcmNlbnQgPSBfLCBiYXIpIDogYmFyUGVyY2VudDsgfTtcblxuICBmdW5jdGlvbiBiYXIoKSB7XG4gICAgLy8gZm9yIGNvbnZlbmllbmNlIGluIGhhbmRsaW5nIG9yaWVudGF0aW9uIHNwZWNpZmljIHZhbHVlc1xuICAgIHZhciBob3Jpem9udGFsUSA9IChvcmllbnQgPT0gJ2hvcml6b250YWwnIHx8IG9yaWVudCA9PSAnYm90dG9tJyB8fCBvcmllbnQgPT0gJ3RvcCcpID8gdHJ1ZSA6IGZhbHNlXG4gICAgdmFyIHZlcnRpY2FsUSA9ICFob3Jpem9udGFsUVxuXG4gICAgLy8gYmFja2dyb3VuZCBjbGlwaW5nIHJlY3RhbmdsZVxuICAgIHZhciBiZ2NwUmVjdCA9IHt4OjAsIHk6MCwgd2lkdGg6IHNwYWNlWCwgaGVpZ2h0OnNwYWNlWX1cbiAgICB2YXIgY29udGFpbmVyID0gc2V0dXBDb250YWluZXIoIHNlbGVjdGlvbiwgbmFtZXNwYWNlLCBiZ2NwUmVjdCwgYmFja2dyb3VuZEZpbGwgKTtcblxuICAgIC8vIHRvIHByZXZlbnQgcmUtY2FsY3VsYXRpb24gYW5kIGdldHRlcnMgdG8gYmUgcGFzc2VkIHRvIGF4ZXNcbiAgICBiYXJLZXlzID0gZDMua2V5cyhkYXRhKVxuICAgIGJhclZhbHVlcyA9IGJhcktleXMubWFwKHZhbHVlRXh0cmFjdG9yKVxuXG4gICAgLy8gaWYgZ3JvdXBpbmcgaXMgdW5kZWZpbmVkIHNvcnQgYmFyS2V5cyBieSBzb3J0aW5nRnVuY3Rpb25cbiAgICB2YXIgb3JkZXJlZCA9IChncm91cGluZyA9PSB1bmRlZmluZWQpID8gYmFyS2V5cy5zb3J0KHNvcnRpbmdGdW5jdGlvbikgOiBncm91cGluZ1xuICAgIC8vIG9yZGVyZWQgbWlnaHQgYmUgbmVzdGVkIGRlcGVuZGluZyBvbiBncm91cGluZ1xuICAgIGJhcktleXMgPSBmbGF0dGVuKG9yZGVyZWQpXG5cbiAgICB2YXIgbnVtYmVyT2ZPYmplY3RzID0gYmFyS2V5cy5sZW5ndGhcbiAgICB2YXIgZXh0ZW50ID0gW01hdGgubWluKC4uLmJhclZhbHVlcykgLSBkb21haW5QYWRkaW5nLE1hdGgubWF4KC4uLmJhclZhbHVlcykgKyBkb21haW5QYWRkaW5nXTtcblxuXG5cbiAgICAvLyBzZXQgdGhlIHNjYWxlXG5cbiAgICBzY2FsZS5kb21haW4oZXh0ZW50KS5yYW5nZShob3Jpem9udGFsUVxuICAgICAgPyBbMCxzcGFjZVldXG4gICAgICA6IG9yaWVudCA9PSAncmlnaHQnXG4gICAgICAgID8gWzAsIHNwYWNlWF1cbiAgICAgICAgOiBbc3BhY2VYLCAwXVxuICAgIClcbiAgICB2YXIgc3BhY2UgPSBob3Jpem9udGFsUSA/IHNwYWNlWCA6IHNwYWNlWVxuICAgIC8vIGNhbGN1bGF0ZSBvYmplY3Qgc2l6ZVxuICAgIG9iamVjdFNpemUgPSAgKG9iamVjdFNpemUgPT0gdW5kZWZpbmVkKVxuICAgID8gY2FsY3VsYXRlV2lkdGhPZk9iamVjdChzcGFjZSwgbnVtYmVyT2ZPYmplY3RzLCBtaW5PYmplY3RTaXplLCBtYXhPYmplY3RTaXplLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICA6IG9iamVjdFNpemVcblxuICAgIC8vIGNhbGN1bGF0ZSBzcGFjZXIgc2l6ZSBpZiBuZWVkZWRcbiAgICBzcGFjZXJTaXplID0gKHNwYWNlclNpemUgPT0gdW5kZWZpbmVkKVxuICAgID8gY2FsY3VsYXRlV2lkdGhPZlNwYWNlcihiYXJLZXlzLCBzcGFjZSwgb2JqZWN0U2l6ZSwgbnVtYmVyT2ZPYmplY3RzLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICA6IHNwYWNlclNpemVcbiAgICAvLyBtYWtlIHRoZSBuZXN0ZWQgZ3JvdXBzXG4gICAgdmFyIHNwYWNlckZ1bmN0aW9uID0gZ3JvdXBpbmdTcGFjZXIoKVxuICAgIC5ob3Jpem9udGFsUShob3Jpem9udGFsUSkuc2NhbGUoc2NhbGUpLm1vdmVieSgnY2F0ZWdvcnknKS5udW1iZXJPZk9iamVjdHMobnVtYmVyT2ZPYmplY3RzKVxuICAgIC5vYmplY3RDbGFzcyhvYmplY3RDbGFzcykub2JqZWN0U2l6ZShvYmplY3RTaXplKS5zcGFjZXJTaXplKHNwYWNlclNpemUpXG4gICAgLnRyYW5zaXRpb25EdXJhdGlvbih0cmFuc2l0aW9uRHVyYXRpb24pLmVhc2VGdW5jKGVhc2VGdW5jKVxuICAgIC5uYW1lc3BhY2UobmFtZXNwYWNlKVxuICAgIC8vIHNhZmUgZGVmYXVsdCBmdW5jdGlvblxuICAgIHZhciBkZWZhdWx0RXhpdCA9IHNwYWNlckZ1bmN0aW9uLmV4aXRGdW5jdGlvbigpXG5cbiAgICBzcGFjZXJGdW5jdGlvbi5leGl0RnVuY3Rpb24oZnVuY3Rpb24oc2VsKXtcbiAgICAgIC8vIHVzZSBkZWZhdWx0IHRvIG1vdmUgb2JqZWN0cyBvZmYgc2NyZWVuXG4gICAgICAvLyBjb25zb2xlLmxvZyhcIkVYSVRcIiwgc2VsLm5vZGVzKCksIG9iamVjdFNpemUsIHNjYWxlKGV4dGVudFsxXSkpXG4gICAgICBpZiAob2JqZWN0U2l6ZSA9PSB1bmRlZmluZWQpIHtjb25zb2xlLmxvZyhzZWwubm9kZXMoKSwgb2JqZWN0U2l6ZSl9XG4gICAgICBkZWZhdWx0RXhpdChzZWwpXG4gICAgICBzZWwuc2VsZWN0QWxsKCdnJykuY2xhc3NlZChcInRvLXJlbW92ZVwiLCB0cnVlKVxuICAgICAgLy8gc2hyaW5rIHJlY3RhbmdsZXMgaW4gYWRkaXRpb25cbiAgICAgIHNlbC5zZWxlY3RBbGwoJyogPiByZWN0JylcbiAgICAgIC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKVxuICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBob3Jpem9udGFsUVxuICAgICAgICAgID8gMFxuICAgICAgICAgIDogMFxuICAgICAgICAsXG4gICAgICAgIHkgPSB2ZXJ0aWNhbFFcbiAgICAgICAgICA/IDBcbiAgICAgICAgICA6IHNjYWxlKGV4dGVudFsxXSlcbiAgICAgICAgLFxuICAgICAgICB0ID0gJ3RyYW5zbGF0ZSgnK3grJywnK3krJyknXG4gICAgICAgIHJldHVybiB0XG4gICAgICB9KVxuICAgICAgLmF0dHIoJ3dpZHRoJywgaG9yaXpvbnRhbFEgPyBvYmplY3RTaXplIDogMClcbiAgICAgIC5hdHRyKCdoZWlnaHQnLCB2ZXJ0aWNhbFEgPyBvYmplY3RTaXplIDogMClcbiAgICAgIC5yZW1vdmUoKVxuICAgIH0pXG5cblxuICAgIC8vIG1vdmUgc3R1ZmZcbiAgICBzcGFjZXJGdW5jdGlvbihjb250YWluZXIsIG9yZGVyZWQsIDApXG5cblxuXG5cblxuICAgIHZhciBwYXJlbnRJbmRleEFycmF5ID0gW11cbiAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnOm5vdCgudG8tcmVtb3ZlKS4nK29iamVjdENsYXNzKVxuICAgIC5lYWNoKGZ1bmN0aW9uKGQsIGkpe3BhcmVudEluZGV4QXJyYXkucHVzaChOdW1iZXIoZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ3BhcmVudC1pbmRleCcpKSl9KVxuXG5cbiAgICBjb2xvckZ1bmN0aW9uID0gY29sb3JGdW5jdGlvbi5jb2xvckJ5KCkgPT0gJ2luZGV4J1xuICAgID8gY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50KFswLCBNYXRoLm1heCguLi5wYXJlbnRJbmRleEFycmF5KV0pXG4gICAgOiBjb2xvckZ1bmN0aW9uLmRhdGFFeHRlbnQoZXh0ZW50KVxuXG5cblxuICAgIGNvbnRhaW5lci5zZWxlY3RBbGwoJ2cuJytvYmplY3RDbGFzcysnOm5vdCgudG8tcmVtb3ZlKScpLmVhY2goZnVuY3Rpb24oa2V5LCBpKSB7XG4gICAgICAvLyBjb25zb2xlLmxvZyhrZXksIHNjYWxlKGV4dGVudFsxXSkgLSBzY2FsZSh2YWx1ZUV4dHJhY3RvcihrZXksIGkpKSlcbiAgICAgIHZhciB0ID0gZDMuc2VsZWN0KHRoaXMpLFxuICAgICAgY3VycmVudERhdGEgPSBkYXRhW2tleV0sXG4gICAgICB2YWx1ZSA9IHZhbHVlRXh0cmFjdG9yKGtleSwgaSksXG4gICAgICBpID0gdC5hdHRyKCdwYXJlbnQtaW5kZXgnKSA9PSB1bmRlZmluZWQgPyBpIDogdC5hdHRyKCdwYXJlbnQtaW5kZXgnKSxcbiAgICAgIGZpbGxDb2xvciA9IGNvbG9yRnVuY3Rpb24oa2V5LCB2YWx1ZSwgaSwgJ2ZpbGwnKSwgLy8gcHJldmVudCBkdXBsaWNhdGUgY29tcHV0YXRpb25cbiAgICAgIHN0cm9rZUNvbG9yID0gY29sb3JGdW5jdGlvbihrZXksIHZhbHVlLCBpLCAgJ3N0cm9rZScpXG5cblxuICAgICAgdmFyIGJhciA9IHNhZmVTZWxlY3QodCwgJ3JlY3QnLCAnYmFyLXJlY3QnKVxuXG4gICAgICBpZiAoYmFyLmF0dHIoJ3RyYW5zZm9ybScpID09IHVuZGVmaW5lZCkge1xuICAgICAgICBiYXIuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgIHZhclxuICAgICAgICAgIHggPSBob3Jpem9udGFsUVxuICAgICAgICAgICAgPyAwXG4gICAgICAgICAgICA6IDBcbiAgICAgICAgICAsXG4gICAgICAgICAgeSA9IHZlcnRpY2FsUVxuICAgICAgICAgICAgPyAwXG4gICAgICAgICAgICA6IHNjYWxlKGV4dGVudFsxXSlcbiAgICAgICAgICAsXG4gICAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICAgIHJldHVybiB0XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIGhvcml6b250YWxRID8gb2JqZWN0U2l6ZSA6IDApXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCB2ZXJ0aWNhbFEgPyBvYmplY3RTaXplIDogMClcblxuICAgICAgfVxuXG5cbiAgICAgIGJhci50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBob3Jpem9udGFsUVxuICAgICAgICAgID8gb2JqZWN0U2l6ZSAtIG9iamVjdFNpemUgKiBiYXJQZXJjZW50XG4gICAgICAgICAgOiBvcmllbnQgPT0gJ3JpZ2h0J1xuICAgICAgICAgICAgPyBzY2FsZShleHRlbnRbMV0pIC0gc2NhbGUodmFsdWUpXG4gICAgICAgICAgICA6IG9iamVjdFNpemUgLSBvYmplY3RTaXplICogYmFyUGVyY2VudFxuICAgICAgICAgICxcbiAgICAgICAgeSA9IHZlcnRpY2FsUVxuICAgICAgICAgID8gb2JqZWN0U2l6ZSAtIG9iamVjdFNpemUgKiBiYXJQZXJjZW50XG4gICAgICAgICAgOiBzY2FsZShleHRlbnRbMV0pIC0gc2NhbGUodmFsdWUpXG4gICAgICAgICxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcbiAgICAgIC5hdHRyKCd3aWR0aCcsIGhvcml6b250YWxRID8gb2JqZWN0U2l6ZSAqIGJhclBlcmNlbnQgOiBzY2FsZSh2YWx1ZSkpXG4gICAgICAuYXR0cignaGVpZ2h0JywgdmVydGljYWxRID8gb2JqZWN0U2l6ZSAqIGJhclBlcmNlbnQ6IHNjYWxlKHZhbHVlKSlcbiAgICAgIC5hdHRyKCdmaWxsJywgZmlsbENvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZScsIHN0cm9rZUNvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGJhclN0cm9rZVdpZHRoKVxuXG5cblxuICAgICAgdC5vbignbW91c2VvdmVyJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIGNvbnRhaW5lci5zZWxlY3RBbGwoJ2cuJytvYmplY3RDbGFzcykuc3R5bGUoJ29wYWNpdHknLCAwLjIpXG4gICAgICAgIHQuc3R5bGUoJ29wYWNpdHknLCAxKVxuICAgICAgICBiYXIuYXR0cignc3Ryb2tlLXdpZHRoJyxiYXJTdHJva2VXaWR0aCoyKVxuXG4gICAgICB9KVxuICAgICAgdC5vbignbW91c2VvdXQnLCBmdW5jdGlvbigpe1xuICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnLicrb2JqZWN0Q2xhc3MpLnN0eWxlKCdvcGFjaXR5JywgMSlcbiAgICAgICAgYmFyLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGJhclN0cm9rZVdpZHRoKVxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgdG9vbHRpcC5zZWxlY3Rpb24oY29udGFpbmVyLnNlbGVjdEFsbCgnLmJhci1yZWN0JykpXG4gICAgLmRhdGEoZGF0YSlcblxuICAgIHRvb2x0aXAoKVxuXG4gIH1cbiAgcmV0dXJuIGJhclxufVxuIiwiaW1wb3J0IHtoeXBlbmF0ZSwgc2FmZVNlbGVjdH0gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7c2V0dXBDb250YWluZXIsIGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3QsIGNhbGN1bGF0ZVdpZHRoT2ZTcGFjZXIsIGxvZ30gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQge3VuaXF1ZX0gZnJvbSAnLi9hcnJheS1mdW5jdGlvbnMnO1xuaW1wb3J0IHtncm91cGluZ1NwYWNlcn0gZnJvbSAnLi9ncm91cGluZy1zcGFjZXInO1xuaW1wb3J0IHtjb2xvckZ1bmN0aW9uIGFzIENGfSBmcm9tICcuL2NvbG9yLWZ1bmN0aW9uJztcbmltcG9ydCB7dG9vbHRpcCBhcyBUVGlwfSBmcm9tICcuL3Rvb2x0aXAnO1xuXG5cbi8qKlxuICogQ3JlYXRlcyBhIGJ1YmJsZUhlYXRtYXBcbiAqXG4gKiB7QGxpbmsgaHR0cHM6Ly9zdW1uZXVyb24uZ2l0bGFiLmlvL2Qzc20vZGVtb3MvYnViYmxlLWhlYXRtYXAvaW5kZXguaHRtbCBEZW1vfVxuICogQGNvbnN0cnVjdG9yIGJ1YmJsZUhlYXRtYXBcbiAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBzZWxlY3Rpb25cbiAqIEBuYW1lc3BhY2UgYnViYmxlSGVhdG1hcFxuICogQHJldHVybnMge2Z1bmN0aW9ufSBidWJibGVIZWF0bWFwXG4gKi9cbmZ1bmN0aW9uIGJ1YmJsZUhlYXRtYXAoIHNlbGVjdGlvbiApIHtcbiAgdmFyXG4gIC8qKlxuICAqIERhdGEgdG8gcGxvdC4gQXNzdW1lZCB0byBiZSBhIG9iamVjdCwgd2hlcmUgZWFjaCBrZXkgY29ycmVzcG9uZHMgdG8gYSBjZWxsXG4gICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNkYXRhfSlcbiAgKiBAcGFyYW0ge09iamVjdH0gW2RhdGE9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBkYXRhLFxuXG4gIC8qKlxuICAqIEFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSBidWJibGVIZWF0bWFwIGluXG4gICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNzcGFjZVh9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbc3BhY2VYPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VYLFxuICAvKipcbiAgKiBBbW91bnQgb2YgdmVydGljYWwgc3BhY2UgKGluIHBpeGVscykgYXZhaWJsZSB0byByZW5kZXIgdGhlIGJ1YmJsZUhlYXRtYXAgaW5cbiAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwLnNwYWNlWX0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZVk9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzcGFjZVksXG5cbiAgLyoqXG4gICogVGhlIGludGVybmFsIGtleSBvZiB0aGUgY2VsbCBzcGVjaWZpeWluZyB0byB3aGljaCB4IGF4aXMga2V5IGl0IGJlbG9uZ3NcbiAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwLnhLZXl9KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbeEtleT0neCddXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhLZXkgPSAneCcsXG4gIC8qKlxuICAqIFRoZSBpbnRlcm5hbCBrZXkgb2YgdGhlIGNlbGwgc3BlY2lmaXlpbmcgdG8gd2hpY2ggeSBheGlzIGtleSBpdCBiZWxvbmdzXG4gICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcC55S2V5fSlcbiAgKiBAcGFyYW0ge3N0cmluZ30gW3lLZXk9J3knXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB5S2V5ID0gJ3knLFxuICAvKipcbiAgKiBUaGUgaW50ZXJuYWwga2V5IG9mIHRoZSBjZWxsIHNwZWNpZml5aW5nIHdoYXQgdmFsdWUgdG8gdXNlIHRvIGRldGVybWluZSB0aGUgcmFkaXVzXG4gICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcC5yS2V5fSlcbiAgKiBAcGFyYW0ge3N0cmluZ30gW3JLZXk9J3InXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICByS2V5ID0gJ3InLFxuICAvKipcbiAgKiBUaGUgaW50ZXJuYWwga2V5IG9mIHRoZSBjZWxsIHNwZWNpZml5aW5nIHdoYXQgdmFsdWUgdG8gdXNlIHRvIGRldGVybWluZSB0aGUgY29sb3JcbiAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwLnZLZXl9KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbdktleT0ndiddXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHZLZXkgPSAndicsXG5cbiAgLyoqXG4gICogRnVuY3Rpb24gZm9yIGV4dHJhY3RpbmcgdGhlIHRoZSB2YWx1ZSBmcm9tIHhLZXkuXG4gICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcC54RXh0cmFjdG9yfSlcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbeEV4dHJhY3Rvcj1mdW5jdGlvbihrZXksIGkpIHsgcmV0dXJuIGRhdGFba2V5XVt4S2V5XSB9XVxuICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGkpIHtyZXR1cm4gZGF0YVtrZXldW3hLZXldIH0sXG4gIC8qKlxuICAqIEZ1bmN0aW9uIGZvciBleHRyYWN0aW5nIHRoZSB0aGUgdmFsdWUgZnJvbSB5S2V5LlxuICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAueUV4dHJhY3Rvcn0pXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3lFeHRyYWN0b3I9ZnVuY3Rpb24oa2V5LCBpKSB7IHJldHVybiBkYXRhW2tleV1beUtleV0gfV1cbiAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB5RXh0cmFjdG9yID0gZnVuY3Rpb24oa2V5LCBpKSB7IHJldHVybiBkYXRhW2tleV1beUtleV0gfSxcbiAgLyoqXG4gICogRnVuY3Rpb24gZm9yIGV4dHJhY3RpbmcgdGhlIHRoZSB2YWx1ZSBmcm9tIHJLZXkuXG4gICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcC5yRXh0cmFjdG9yfSlcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbckV4dHJhY3Rvcj1mdW5jdGlvbihrZXksIGkpIHsgcmV0dXJuIGRhdGFba2V5XVtyS2V5XSB9XVxuICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHJFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGkpIHsgcmV0dXJuIGRhdGFba2V5XVtyS2V5XSB9LFxuICAvKipcbiAgKiBGdW5jdGlvbiBmb3IgZXh0cmFjdGluZyB0aGUgdGhlIHZhbHVlIGZyb20gdktleS5cbiAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwLnZFeHRyYWN0b3J9KVxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFt2RXh0cmFjdG9yPWZ1bmN0aW9uKGtleSwgaSkgeyByZXR1cm4gZGF0YVtrZXldW3ZLZXldIH1dXG4gICogQHJldHVybnMge251bWJlcn1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdkV4dHJhY3RvciA9IGZ1bmN0aW9uKGtleSwgaSkgeyByZXR1cm4gZGF0YVtrZXldW3ZLZXldIH0sXG5cblxuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0byBhbGxvdyBidWJibGVIZWF0bWFwIHRvIHJlbmRlciBlbGVtZW50cyBwYXNzIHRoZSBtYWluIHNwYXRpYWwgZGltZW5zaW9uXG4gICogZ2l2ZW4gdGhlIG9yaWVudGF0aW9uIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjb3JpZW50fSksIHdoZXJlIHtAbGluayBidWJibGVIZWF0bWFwI29yaWVudH09XCJib3R0b21cIiBvciB7QGxpbmsgYnViYmxlSGVhdG1hcCNvcmllbnR9PVwidG9wXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJ1YmJsZUhlYXRtYXAjc3BhY2VYfSBhbmQgd2hlcmUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjb3JpZW50fT1cImxlZnRcIiBvciB7QGxpbmsgYnViYmxlSGVhdG1hcCNvcmllbnR9PVwicmlnaHRcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgYnViYmxlSGVhdG1hcCNzcGFjZVl9XG4gICogQHBhcmFtIHtib29sZWFufSBbb3ZlcmZsb3dRPWZhbHNlXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvdmVyZmxvd1EgPSBmYWxzZSxcblxuICAvKipcbiAgKiBUaGUgc2NhbGUgZm9yIHdoaWNoIHRoZSByYWRpdXMgdmFsdWVzIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBieVxuICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtzY2FsZT1kMy5zY2FsZUxpbmVhcl1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc2NhbGUgPSBkMy5zY2FsZUxpbmVhcigpLFxuICAvKipcbiAgKiBUaGUgcGFkZGluZyBmb3IgdGhlIGRvbWFpbiBvZiB0aGUgc2NhbGUgKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNzY2FsZX0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtkb21haW5QYWRkaW5nPTAuNV1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZG9tYWluUGFkZGluZyA9IDAuNSxcblxuICAvKipcbiAgKiBEZWZhdWx0IHNwYWNlIGZvciB0aGUgc3BhY2VyIChwZXJjZW50YWdlKSBvZiBtYWluIGRpbWVuc2lvbiBnaXZlbiB0aGUgb3JpZW50YXRpb25cbiAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI29yaWVudH0pLCB3aGVyZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNvcmllbnR9PVwiaG9yaXpvbnRhbFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayBidWJibGVIZWF0bWFwI3NwYWNlWH0gYW5kIHdoZXJlIHtAbGluayBidWJibGVIZWF0bWFwI29yaWVudH09XCJ2ZXJ0aWNhbFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayBidWJibGVIZWF0bWFwI3NwYWNlWX0gYmV0d2VlbiBidWJibGVzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtvYmplY3RTcGFjZXI9MC4wXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvYmplY3RTcGFjZXIgPSAwLjAsXG4gIC8qKlxuICAqIFRoZSBtaW5pbXVtIHNpemUgdGhhdCBhbiBvYmplY3QgY2FuIGJlXG4gICogQHBhcmFtIHtudW1iZXJ9IFttaW5PYmplY3RTaXplPTUwXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBtaW5PYmplY3RTaXplID0gNTAsXG4gIC8qKlxuICAqIFRoZSBtYXhpbXVtIHNpemUgdGhhdCBhbiBvYmplY3QgY2FuIGJlXG4gICogQHBhcmFtIHtudW1iZXJ9IFttYXhPYmplY3RTaXplPTEwMF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbWF4T2JqZWN0U2l6ZSA9IDEwMCxcblxuXG4gIC8qKlxuICAqIFRoZSBzdHJva2Ugd2lkdGggb2YgdGhlIGJ1YmJsZXNcbiAgKiBAcGFyYW0ge251bWJlcn0gW2J1YmJsZVN0cm9rZVdpZHRoPTJdXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJ1YmJsZVN0cm9rZVdpZHRoID0gMixcbiAgLy8gY29sb3JGdW5jID0gY29sb3JGdW5jdGlvbigpLFxuXG4gIC8qKlxuICAqIENvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kXG4gICogQHBhcmFtIHtzdHJpbmd9IFtiYWNrZ3JvdW5kRmlsbD1cInRyYW5zcGFyZW50XCJdXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJhY2tncm91bmRGaWxsID0gJ3RyYW5zcGFyZW50JyxcbiAgLyoqXG4gICogTmFtZXNwYWNlIGZvciBhbGwgaXRlbXMgbWFkZSBieSB0aGlzIGluc3RhbmNlIG9mIGJ1YmJsZUhlYXRtYXBcbiAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWVzcGFjZT1cImQzc20tYnViYmxlXCJdXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG5hbWVzcGFjZSA9ICdkM3NtLWJ1YmJsZScsXG4gIC8qKlxuICAqIENsYXNzIG5hbWUgZm9yIGJ1YmJsZSBjb250YWluZXIgKDxnPiBlbGVtZW50KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbb2JqZWN0Q2xhc3M9XCJidWJibGVcIl1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0Q2xhc3MgPSAnYnViYmxlJyxcbiAgLyoqXG4gICogRHVyYXRpb24gb2YgYWxsIHRyYW5zaXRpb25zIG9mIHRoaXMgZWxlbWVudFxuICAqIEBwYXJhbSB7bnVtYmVyfSBbdHJhbnNpdGlvbkR1cmF0aW9uPTEwMDBdXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRyYW5zaXRpb25EdXJhdGlvbiA9IDEwMDAsXG4gIC8qKlxuICAqIEVhc2luZyBmdW5jdGlvbiBmb3IgdHJhbnNpdGlvbnNcbiAgKiBAcGFyYW0ge2QzLmVhc2V9IFtlYXNlRnVuYz1kMy5lYXNlRXhwXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBlYXNlRnVuYyA9IGQzLmVhc2VFeHAsXG5cbiAgLyoqXG4gICogU3RvcmVzIHRoZSBrZXlzIG9mIGFsbCB0aGUgY2VsbHNcbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGJ1YmJsZUhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFtjZWxsS2V5cz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGNlbGxLZXlzLFxuICAvKipcbiAgKiBTdG9yZXMgdGhlIGxpc3Qgb2YgdW5pcXVlIHhWYWx1ZXNcbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGJ1YmJsZUhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt4VmFsdWVzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeFZhbHVlcyxcbiAgLyoqXG4gICogU3RvcmVzIHRoZSBsaXN0IG9mIHVuaXF1ZSB5VmFsdWVzXG4gICogQ2FsY3VsYXRlZCBhZnRlciBidWJibGVIZWF0bWFwIGNhbGxlZC5cbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbeVZhbHVlcz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHlWYWx1ZXMsXG4gIC8qKlxuICAqIFN0b3JlcyB0aGUgbGlzdCBvZiB1bmlxdWUgclZhbHVlc1xuICAqIENhbGN1bGF0ZWQgYWZ0ZXIgYnViYmxlSGVhdG1hcCBjYWxsZWQuXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW3JWYWx1ZXM9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICByVmFsdWVzLFxuICAvKipcbiAgKiBTdG9yZXMgdGhlIGxpc3Qgb2YgdW5pcXVlIHZWYWx1ZXNcbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGJ1YmJsZUhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt2VmFsdWVzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdlZhbHVlcyxcblxuICB4S2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4geEV4dHJhY3RvcihhKSAtIHhFeHRyYWN0b3IoYikgfSxcbiAgeUtleVNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIHlFeHRyYWN0b3IoYSkgLSB5RXh0cmFjdG9yKGIpIH0sXG4gIHJLZXlTb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihhLCBiKSB7IHJldHVybiByRXh0cmFjdG9yKGEpIC0gckV4dHJhY3RvcihiKSB9LFxuICB2S2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gdkV4dHJhY3RvcihhKSAtIHZFeHRyYWN0b3IoYikgfSxcblxuICAvKipcbiAgKiBJbnN0YW5jZSBvZiBDb2xvckZ1bmN0aW9uIHdpdGggLmNvbG9yQnkgc2V0IHRvICdjYXRlZ29yeSdcbiAgKiBAZnVuY3Rpb24gY29sb3JGdW5jdGlvblxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjb2xvckZ1bmN0aW9uID0gQ0YoKS5jb2xvckJ5KCd2YWx1ZScpLFxuICAvKipcbiAgKiBJbnN0YW5jZSBvZiBUb29sdGlwXG4gICogQGZ1bmN0aW9uIHRvb2x0aXBcbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdG9vbHRpcCA9IFRUaXAoKSxcblxuICAvKipcbiAgKiBzdG9yZSB0aGUgc2l6ZSB0aGUgYnViYmxlIGNvdWxkIGJlIGluIHRoZSB4IGRpbWVuc2lvblxuICAqIHRoZSBhY3R1YWxsIHNpemUgb2YgdGhlIGJ1YmJsZSB3aWxsIGJlIHRoZSBtaW4gb2YgeFNpemUgYW5kIHtAbGluayBidWJibGVIZWF0bWFwI3lTaXplfVxuICAqIENhbGN1bGF0ZWQgYWZ0ZXIgYnViYmxlSGVhdG1hcCBjYWxsZWQuXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW3hTaXplPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeFNpemUsXG4gIC8qKlxuICAqIHN0b3JlIHRoZSBzaXplIG9mIHRoZSBzcGFjZXIgaW4gdGhlIHggZGltZW5zaW9uXG4gICogQ2FsY3VsYXRlZCBhZnRlciBidWJibGVIZWF0bWFwIGNhbGxlZC5cbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbeFNwYWNlclNpemU9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB4U3BhY2VyU2l6ZSxcblxuICAvKipcbiAgKiBzdG9yZSB0aGUgc2l6ZSB0aGUgYnViYmxlIGNvdWxkIGJlIGluIHRoZSB5IGRpbWVuc2lvblxuICAqIHRoZSBhY3R1YWxsIHNpemUgb2YgdGhlIGJ1YmJsZSB3aWxsIGJlIHRoZSBtaW4gb2YgeFNpemUgYW5kIHtAbGluayBidWJibGVIZWF0bWFwI3hTaXplfVxuICAqIENhbGN1bGF0ZWQgYWZ0ZXIgYnViYmxlSGVhdG1hcCBjYWxsZWQuXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW3lTaXplPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeVNpemUsXG4gIC8qKlxuICAqIHN0b3JlIHRoZSBzaXplIG9mIHRoZSBzcGFjZXIgaW4gdGhlIHkgZGltZW5zaW9uLlxuICAqIENhbGN1bGF0ZWQgYWZ0ZXIgYnViYmxlSGVhdG1hcCBjYWxsZWQuXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW3hTcGFjZXJTaXplPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeVNwYWNlclNpemVcblxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBzZWxlY3Rpb24gaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IGQzLnNlbGVjdGlvbn1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc2VsZWN0aW9uID0gc2VsZWN0aW9uXG4gICAqL1xuICBiaG0uc2VsZWN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZWxlY3Rpb24gPSBfLCBiaG0pIDogc2VsZWN0aW9uOyB9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGRhdGFcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNkYXRhfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgb2JqZWN0fVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGJobS5kYXRhID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkYXRhID0gXywgYmhtKSA6IGRhdGE7IH1cbiAgLy8gYmhtLm9yaWVudCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3JpZW50ID0gXywgYmhtKSA6IG9yaWVudDsgfVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBhbW91bnQgb2YgaG9yaXpvbnRhbCBzcGFjZSBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNzcGFjZVh9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV0gc2hvdWxkIGJlIGEgbnVtYmVyID4gMFxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc3BhY2VYID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0uc3BhY2VYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVggPSBfLCBiaG0pIDogc3BhY2VYOyB9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiB2ZXJ0aWNhbCBzcGFjZSBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNzcGFjZVl9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV0gc2hvdWxkIGJlIGEgbnVtYmVyID4gMFxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc3BhY2VZID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0uc3BhY2VZID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVkgPSBfLCBiaG0pIDogc3BhY2VZOyB9XG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeEtleVxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3hLZXl9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHhLZXkgPSAneCdcbiAgICovXG4gIGJobS54S2V5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4S2V5ID0gXywgYmhtKSA6IHhLZXk7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeUtleVxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3lLZXl9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHlLZXkgPSAneSdcbiAgICovXG4gIGJobS55S2V5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5S2V5ID0gXywgYmhtKSA6IHlLZXk7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgcktleVxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3JLZXl9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHJLZXkgPSAncidcbiAgICovXG4gIGJobS5yS2V5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChyS2V5ID0gXywgYmhtKSA6IHJLZXk7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgdktleVxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3ZLZXl9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZLZXkgPSAneSdcbiAgICovXG4gIGJobS52S2V5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2S2V5ID0gXywgYmhtKSA6IHZLZXk7IH1cblxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBjZWxsS2V5c1xuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI2NlbGxLZXlzfSlcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmdbXX1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgY2VsbEtleXMgPSB1bmRlZmluZWRcbiAgICovXG4gIGJobS5jZWxsS2V5cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY2VsbEtleXMgPSBfLCBiaG0pIDogY2VsbEtleXM7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeFZhbHVlc1xuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3hWYWx1ZXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB4VmFsdWVzID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0ueFZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeFZhbHVlcyA9IF8sIGJobSkgOiB4VmFsdWVzOyB9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHlWYWx1ZXNcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCN5VmFsdWVzfSlcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmdbXX1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgeVZhbHVlcyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmhtLnlWYWx1ZXMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlWYWx1ZXMgPSBfLCBiaG0pIDogeVZhbHVlczsgfVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSByVmFsdWVzXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjclZhbHVlc30pXG4gICAqIEBwYXJhbSB7bnVtYmVyW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgbnVtYmVyW119XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHJWYWx1ZXMgPSB1bmRlZmluZWRcbiAgICovXG4gIGJobS5yVmFsdWVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChyVmFsdWVzID0gXywgYmhtKSA6IHJWYWx1ZXM7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgdlZhbHVlc1xuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3ZWYWx1ZXN9KVxuICAgKiBAcGFyYW0ge251bWJlcltdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IG51bWJlcltdfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB2VmFsdWVzID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0udlZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodlZhbHVlcyA9IF8sIGJobSkgOiB2VmFsdWVzOyB9XG5cblxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB4RXh0cmFjdG9yXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjeEV4dHJhY3Rvcn0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHhFeHRyYWN0b3IgPSB1bmRlZmluZWRcbiAgICovXG4gIGJobS54RXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4RXh0cmFjdG9yID0gXywgYmhtKSA6IHhFeHRyYWN0b3I7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeUV4dHJhY3RvclxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3lFeHRyYWN0b3J9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5RXh0cmFjdG9yID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0ueUV4dHJhY3RvciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeUV4dHJhY3RvciA9IF8sIGJobSkgOiB5RXh0cmFjdG9yOyB9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHJFeHRyYWN0b3JcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNyRXh0cmFjdG9yfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgckV4dHJhY3RvciA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmhtLnJFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHJFeHRyYWN0b3IgPSBfLCBiaG0pIDogckV4dHJhY3RvcjsgfVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB2RXh0cmFjdG9yXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjdkV4dHJhY3Rvcn0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZFeHRyYWN0b3IgPSB1bmRlZmluZWRcbiAgICovXG4gIGJobS52RXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2RXh0cmFjdG9yID0gXywgYmhtKSA6IHZFeHRyYWN0b3I7IH1cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgd2hldGhlciBvciBub3QgYnViYmxlSGVhdG1hcCBpcyBhbGxvd2VkIHRvIGdvIGJleW9uZCBzcGVjaWZpZWQgZGltZW5zaW9uc1xuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3NwYWNlWH0pXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBib29sZWFufVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvdmVyZmxvd1EgPSBmYWxzZVxuICAgKi9cbiAgYmhtLm92ZXJmbG93USA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3ZlcmZsb3dRID0gXywgYmhtKSA6IG92ZXJmbG93UTsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHNjYWxlIGZvciB3aGljaCB0aGUgcmFkaXVzIG9mIGJ1YmJsZXMgc2hvdWxkIGJlIHRyYW5zZm9ybWVkIGJ5XG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjc2NhbGV9KVxuICAgKiBAcGFyYW0ge2QzLnNjYWxlfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IGQzLnNjYWxlfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKClcbiAgICovXG4gIGJobS5zY2FsZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGUgPSBfLCBiaG0pIDogc2NhbGU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcGFkZGluZyBmb3IgdGhlIGRvbWFpbiBvZiB0aGUgc2NhbGVcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNkb21haW5QYWRkaW5nfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBkb21haW5QYWRkaW5nID0gMC41XG4gICAqL1xuICBiaG0uZG9tYWluUGFkZGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluUGFkZGluZyA9IF8sIGJobSkgOiBkb21haW5QYWRkaW5nOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgb2JqZWN0U3BhY2VyXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjb2JqZWN0U3BhY2VyfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RTcGFjZXIgPSAwLjBcbiAgICovXG4gIGJobS5vYmplY3RTcGFjZXIgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNwYWNlciA9IF8sIG9iamVjdFNwYWNlcikgOiBkYXRhOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbWluT2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI21pbk9iamVjdFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1pbk9iamVjdFNpemUgPSA1MFxuICAgKi9cbiAgYmhtLm1pbk9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1pbk9iamVjdFNpemUgPSBfLCBiaG0pIDogbWluT2JqZWN0U2l6ZTsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1heE9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNtYXhPYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBtYXhPYmplY3RTaXplID0gMTAwXG4gICAqL1xuICBiaG0ubWF4T2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobWF4T2JqZWN0U2l6ZSA9IF8sIGJobSkgOiBtYXhPYmplY3RTaXplOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYnViYmxlU3Ryb2tlV2lkdGhcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNidWJibGVTdHJva2VXaWR0aH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYnViYmxlU3Ryb2tlV2lkdGggPSAyXG4gICAqL1xuICBiaG0uYnViYmxlU3Ryb2tlV2lkdGggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJ1YmJsZVN0cm9rZVdpZHRoID0gXywgYmhtKSA6IGJ1YmJsZVN0cm9rZVdpZHRoOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYmFja2dyb3VuZEZpbGxcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNiYWNrZ3JvdW5kRmlsbH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYmFja2dyb3VuZEZpbGwgPSAndHJhbnNwYXJlbnQnXG4gICAqL1xuICBiaG0uYmFja2dyb3VuZEZpbGwgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJhY2tncm91bmRGaWxsID0gXywgYmhtKSA6IGJhY2tncm91bmRGaWxsOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbmFtZXNwYWNlXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjbmFtZXNwYWNlfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBuYW1lc3BhY2UgPSAnZDNzbS1idWJibGVIZWF0bWFwJ1xuICAgKi9cbiAgYmhtLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgYmhtKSA6IG5hbWVzcGFjZTsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG9iamVjdENsYXNzXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjb2JqZWN0Q2xhc3N9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG9iamVjdENsYXNzID0gJ3RpY2stZ3JvdXAnXG4gICAqL1xuICBiaG0ub2JqZWN0Q2xhc3MgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdENsYXNzID0gXywgYmhtKSA6IG9iamVjdENsYXNzOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdHJhbnNpdGlvbkR1cmF0aW9uXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjdHJhbnNpdGlvbkR1cmF0aW9ufSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwXG4gICAqL1xuICBiaG0udHJhbnNpdGlvbkR1cmF0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0cmFuc2l0aW9uRHVyYXRpb24gPSBfLCBiaG0pIDogdHJhbnNpdGlvbkR1cmF0aW9uOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgZWFzZUZ1bmNcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNlYXNlRnVuY30pXG4gICAqIEBwYXJhbSB7ZDMuZWFzZX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBkMy5lYXNlfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBlYXNlRnVuYyA9IGQzLmVhc2VFeHBcbiAgICovXG4gIGJobS5lYXNlRnVuYyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZWFzZUZ1bmMgPSBfLCBiaG0pIDogZWFzZUZ1bmM7IH1cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRvb2x0aXBcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCN0b29sdGlwfSlcbiAgICogQHBhcmFtIHt0b29sdGlwfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IHRvb2x0aXB9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRvb2x0aXAgPSB0b29sdGlwKClcbiAgICovXG4gIGJobS50b29sdGlwID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0b29sdGlwID0gXywgYmhtKSA6IHRvb2x0aXA7IH1cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGNvbG9yRnVuY3Rpb25cbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCNjb2xvckZ1bmN0aW9ufSlcbiAgICogQHBhcmFtIHtjb2xvckZ1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IGNvbG9yRnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGNvbG9yRnVuY3Rpb24gPSBjb2xvckZ1bmN0aW9uKClcbiAgICovXG4gIGJobS5jb2xvckZ1bmN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjb2xvckZ1bmN0aW9uID0gXywgYmhtKSA6IGNvbG9yRnVuY3Rpb247IH1cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHhTaXplXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjeFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHhTaXplID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0ueFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhTaXplID0gXywgYmhtKSA6IHhTaXplOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgeFNwYWNlclNpemVcbiAgICogKHNlZSB7QGxpbmsgYnViYmxlSGVhdG1hcCN4U3BhY2VyU2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YnViYmxlSGVhdG1hcCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJ1YmJsZUhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgeFNwYWNlclNpemUgPSB1bmRlZmluZWRcbiAgICovXG4gIGJobS54U3BhY2VyU2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeFNwYWNlclNpemUgPSBfLCBiaG0pIDogeFNwYWNlclNpemU7IH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB5U2l6ZVxuICAgKiAoc2VlIHtAbGluayBidWJibGVIZWF0bWFwI3lTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtidWJibGVIZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYnViYmxlSGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5U2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYmhtLnlTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5U2l6ZSA9IF8sIGJobSkgOiB5U2l6ZTsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHlTcGFjZXJTaXplXG4gICAqIChzZWUge0BsaW5rIGJ1YmJsZUhlYXRtYXAjeVNwYWNlclNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2J1YmJsZUhlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBidWJibGVIZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHlTcGFjZXJTaXplID0gdW5kZWZpbmVkXG4gICAqL1xuICBiaG0ueVNwYWNlclNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlTcGFjZXJTaXplID0gXywgYmhtKSA6IHlTcGFjZXJTaXplOyB9XG4gIC8vIGJobS55S2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5S2V5U29ydGluZ0Z1bmN0aW9uID0gXywgYmhtKSA6IHlLZXlTb3J0aW5nRnVuY3Rpb247IH1cbiAgLy8gYmhtLnhLZXlTb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhLZXlTb3J0aW5nRnVuY3Rpb24gPSBfLCBiaG0pIDogeEtleVNvcnRpbmdGdW5jdGlvbjsgfVxuXG5cblxuICBmdW5jdGlvbiBiaG0oKSB7XG4gICAgdmFyIGhvcml6b250YWxRID0gdHJ1ZTsgLy8gbm8gb3JpZW50YXRpb24gaW4gaGVhdG1hcHMuIEFpZHMgYXMgcGxhY2Vob2xkZXIgaW4gZnVuY3Rpb25zIHRoYXQgdGFrZSBvcmllbnQgYXMgYSBwYXJhbWV0ZXJcbiAgICB2YXIgYmdjcFJlY3QgPSB7eDowLCB5OjAsIHdpZHRoOiBzcGFjZVgsIGhlaWdodDpzcGFjZVl9XG4gICAgdmFyIGNvbnRhaW5lciA9IHNldHVwQ29udGFpbmVyKCBzZWxlY3Rpb24sIG5hbWVzcGFjZSwgYmdjcFJlY3QsIGJhY2tncm91bmRGaWxsICk7XG5cbiAgICBjZWxsS2V5cyA9IGQzLmtleXMoZGF0YSk7XG4gICAgY2VsbEtleXMuc29ydChmdW5jdGlvbihhLCBiKXsgcmV0dXJuIHhLZXlTb3J0aW5nRnVuY3Rpb24oYSwgYikgfHwgeUtleVNvcnRpbmdGdW5jdGlvbihhLCBiKSB9KVxuICAgIGxvZygnYnViYmxlSGVhdG1hcCcsICdjZWxscyBhcmUgc29ydGVkIGJ5JywgY2VsbEtleXMpXG5cblxuXG4gICAgeFZhbHVlcyA9IHVuaXF1ZShjZWxsS2V5cy5tYXAoeEV4dHJhY3RvcikpO1xuICAgIHlWYWx1ZXMgPSB1bmlxdWUoY2VsbEtleXMubWFwKHlFeHRyYWN0b3IpKTtcbiAgICByVmFsdWVzID0gdW5pcXVlKGNlbGxLZXlzLm1hcChyRXh0cmFjdG9yKSk7XG4gICAgdlZhbHVlcyA9IHVuaXF1ZShjZWxsS2V5cy5tYXAodkV4dHJhY3RvcikpO1xuICAgIGxvZygnYnViYmxlSGVhdG1hcCcsICd4IGFuZCB5IGtleXMgYXJlJywge3g6IHhWYWx1ZXMsIHk6eVZhbHVlc30pXG5cblxuICAgIHZhciB4RGltID0geFZhbHVlcy5sZW5ndGgsIHlEaW0gPSB5VmFsdWVzLmxlbmd0aDtcblxuXG4gICAgdmFyIGV4dGVudCA9IFtNYXRoLm1pbiguLi5yVmFsdWVzKSAtIGRvbWFpblBhZGRpbmcsTWF0aC5tYXgoLi4uclZhbHVlcykgKyBkb21haW5QYWRkaW5nXTtcblxuXG4gICAgeVNpemUgPSBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0KHNwYWNlWSwgeURpbSwgbWluT2JqZWN0U2l6ZSwgbWF4T2JqZWN0U2l6ZSwgb2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgeFNpemUgPSBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0KHNwYWNlWCwgeERpbSwgbWluT2JqZWN0U2l6ZSwgbWF4T2JqZWN0U2l6ZSwgb2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgeVNwYWNlclNpemUgPSBjYWxjdWxhdGVXaWR0aE9mU3BhY2VyKHlWYWx1ZXMsIHNwYWNlWSwgeVNpemUsIHlEaW0sIG9iamVjdFNwYWNlciwgb3ZlcmZsb3dRKVxuICAgIHhTcGFjZXJTaXplID0gY2FsY3VsYXRlV2lkdGhPZlNwYWNlcih4VmFsdWVzLCBzcGFjZVgsIHhTaXplLCB4RGltLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICBsb2coJ2J1YmJsZUhlYXRtYXAnLCAnc2l6ZSBvZicsIHt4OiB4U2l6ZSwgeTogeVNpemV9KVxuXG5cbiAgICBzY2FsZS5kb21haW4oZXh0ZW50KS5yYW5nZShbTWF0aC5taW4obWluT2JqZWN0U2l6ZS8yLCAgIE1hdGgubWluKHlTaXplLCB4U2l6ZSkvMiksIE1hdGgubWluKHlTaXplLCB4U2l6ZSkvMl0pXG5cbiAgICB2YXIgeVNwYWNlciA9IGdyb3VwaW5nU3BhY2VyKClcbiAgICAuaG9yaXpvbnRhbFEoZmFsc2UpXG4gICAgLm1vdmVieSgnY2F0ZWdvcnknKS5udW1iZXJPZk9iamVjdHMoeURpbSlcbiAgICAub2JqZWN0Q2xhc3MoaHlwZW5hdGUob2JqZWN0Q2xhc3MsICdyb3cnKSlcbiAgICAub2JqZWN0U2l6ZSh5U2l6ZSkuc3BhY2VyU2l6ZSh5U3BhY2VyU2l6ZSlcbiAgICAudHJhbnNpdGlvbkR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbikuZWFzZUZ1bmMoZWFzZUZ1bmMpXG4gICAgLm5hbWVzcGFjZSgncm93JylcblxuICAgIHZhciB4U3BhY2VyID0gZ3JvdXBpbmdTcGFjZXIoKVxuICAgIC5ob3Jpem9udGFsUSh0cnVlKVxuICAgIC5tb3ZlYnkoJ2NhdGVnb3J5JykubnVtYmVyT2ZPYmplY3RzKHhEaW0pXG4gICAgLm9iamVjdENsYXNzKG9iamVjdENsYXNzKVxuICAgIC5vYmplY3RTaXplKHhTaXplKS5zcGFjZXJTaXplKHhTcGFjZXJTaXplKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlRnVuYyhlYXNlRnVuYylcblxuXG4gICAgeVNwYWNlcihjb250YWluZXIsIHlWYWx1ZXMsIDApXG4gICAgY29udGFpbmVyLnNlbGVjdEFsbCgnZy4nK2h5cGVuYXRlKG9iamVjdENsYXNzLCAncm93JykpXG4gICAgLmVhY2goZnVuY3Rpb24oZCwgaSl7XG4gICAgICB4U3BhY2VyKGQzLnNlbGVjdCh0aGlzKSwgeFZhbHVlcywgMClcbiAgICB9KVxuICAgIHZhciBjZWxscyA9IGNvbnRhaW5lci5zZWxlY3RBbGwoJ2c6bm90KC50by1yZW1vdmUpLicrb2JqZWN0Q2xhc3MpLmRhdGEoY2VsbEtleXMpO1xuXG4gICAgdmFyIHBhcmVudEluZGV4QXJyYXkgPSBbXVxuICAgIGNlbGxzLmVhY2goZnVuY3Rpb24oZCwgaSl7IHBhcmVudEluZGV4QXJyYXkucHVzaChOdW1iZXIoZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ3BhcmVudC1pbmRleCcpKSkgfSlcblxuXG4gICAgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24uY29sb3JCeSgpID09ICdpbmRleCdcbiAgICA/IGNvbG9yRnVuY3Rpb24uZGF0YUV4dGVudChbMCwgTWF0aC5tYXgoLi4ucGFyZW50SW5kZXhBcnJheSldKVxuICAgIDogY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50KFswLCBNYXRoLm1heCguLi52VmFsdWVzKV0pXG5cbiAgICBjZWxscy5lYWNoKGZ1bmN0aW9uKGtleSwgaSkge1xuICAgICAgbG9nKCdidWJibGVIZWF0bWFwJywgJ2VhY2ggY2VsbCcsIHtrZXk6IGtleSwgaW5kZXg6IGksIG5vZGU6IGQzLnNlbGVjdCh0aGlzKS5ub2RlKCl9KVxuXG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKSxcbiAgICAgIGN1cnJlbnREYXRhID0gZGF0YVtrZXldLFxuICAgICAgdmFsdWUgPSB2RXh0cmFjdG9yKGtleSwgaSksXG4gICAgICByYWRpdXM9IHJFeHRyYWN0b3Ioa2V5LCBpKSxcbiAgICAgIGkgPSB0LmF0dHIoJ3BhcmVudC1pbmRleCcpID09IHVuZGVmaW5lZCA/IGkgOiB0LmF0dHIoJ3BhcmVudC1pbmRleCcpLFxuICAgICAgZmlsbENvbG9yID0gY29sb3JGdW5jdGlvbihrZXksIHZhbHVlLCBpLCAnZmlsbCcpLCAvLyBwcmV2ZW50IGR1cGxpY2F0ZSBjb21wdXRhdGlvblxuICAgICAgc3Ryb2tlQ29sb3IgPSBjb2xvckZ1bmN0aW9uKGtleSwgdmFsdWUsIGksICAnc3Ryb2tlJylcblxuICAgICAgbG9nKCdidWJibGVIZWF0bWFwJywgJ3JhZGl1cycse3JhZGl1czogcmFkaXVzLCBzY2FsZWQ6IHNjYWxlKHJhZGl1cyksIGV4dGVudDogZXh0ZW50LCByYW5nZTpzY2FsZS5yYW5nZSgpfSlcblxuICAgICAgdmFyIGMgPSBzYWZlU2VsZWN0KHQsICdjaXJjbGUnLCBoeXBlbmF0ZShvYmplY3RDbGFzcywnY2lyY2xlJykpXG4gICAgICBjLmF0dHIoJ2N4JywgeFNpemUgLyAyKVxuICAgICAgLmF0dHIoJ2N5JywgeVNpemUgLyAyIClcbiAgICAgIC5hdHRyKCdyJywgc2NhbGUocmFkaXVzKSlcbiAgICAgIC5hdHRyKCdmaWxsJywgZmlsbENvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZScsIHN0cm9rZUNvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGJ1YmJsZVN0cm9rZVdpZHRoKVxuXG4gICAgfSlcblxuICAgIHRvb2x0aXAuc2VsZWN0aW9uKGNlbGxzLnNlbGVjdEFsbCgnY2lyY2xlLicraHlwZW5hdGUob2JqZWN0Q2xhc3MsICdjaXJjbGUnKSkpXG4gICAgLmRhdGEoZGF0YSlcbiAgICAvLyAua2V5cyhbJ3InLCAndiddKVxuICAgIC8vIC5oZWFkZXIoZnVuY3Rpb24oZCwgaSl7cmV0dXJuIGh5cGVuYXRlKGRhdGFbZF1beEtleV0sIGRhdGFbZF1beUtleV0pIH0pXG5cbiAgICB0b29sdGlwKClcblxuXG4gIH1cblxuICByZXR1cm4gYmhtO1xufVxuXG5leHBvcnQge2J1YmJsZUhlYXRtYXB9XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtzZXR1cENvbnRhaW5lciwgY2FsY3VsYXRlV2lkdGhPZk9iamVjdCwgY2FsY3VsYXRlV2lkdGhPZlNwYWNlciwgbG9nfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7dW5pcXVlfSBmcm9tICcuL2FycmF5LWZ1bmN0aW9ucyc7XG5pbXBvcnQge2dyb3VwaW5nU3BhY2VyfSBmcm9tICcuL2dyb3VwaW5nLXNwYWNlcic7XG5pbXBvcnQge2NvbG9yRnVuY3Rpb24gYXMgQ0Z9IGZyb20gJy4vY29sb3ItZnVuY3Rpb24nO1xuaW1wb3J0IHt0b29sdGlwIGFzIFRUaXB9IGZyb20gJy4vdG9vbHRpcCc7XG5cblxuLyoqXG4gKiBDcmVhdGVzIGEgaGVhdG1hcFxuICpcbiAqIHtAbGluayBodHRwczovL3N1bW5ldXJvbi5naXRsYWIuaW8vZDNzbS9kZW1vcy9oZWF0bWFwLWhlYXRtYXAvaW5kZXguaHRtbCBEZW1vfVxuICogQGNvbnN0cnVjdG9yIGhlYXRtYXBcbiAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBzZWxlY3Rpb25cbiAqIEBuYW1lc3BhY2UgaGVhdG1hcFxuICogQHJldHVybnMge2Z1bmN0aW9ufSBoZWF0bWFwXG4gKi9cbmZ1bmN0aW9uIGhlYXRtYXAoIHNlbGVjdGlvbiApIHtcbiAgdmFyXG4gIC8qKlxuICAqIERhdGEgdG8gcGxvdC4gQXNzdW1lZCB0byBiZSBhIG9iamVjdCwgd2hlcmUgZWFjaCBrZXkgY29ycmVzcG9uZHMgdG8gYSBjZWxsXG4gICogKHNlZSB7QGxpbmsgaGVhdG1hcCNkYXRhfSlcbiAgKiBAcGFyYW0ge09iamVjdH0gW2RhdGE9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBkYXRhLFxuXG4gIC8qKlxuICAqIEFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSBoZWF0bWFwIGluXG4gICogKHNlZSB7QGxpbmsgaGVhdG1hcCNzcGFjZVh9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbc3BhY2VYPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VYLFxuICAvKipcbiAgKiBBbW91bnQgb2YgdmVydGljYWwgc3BhY2UgKGluIHBpeGVscykgYXZhaWJsZSB0byByZW5kZXIgdGhlIGhlYXRtYXAgaW5cbiAgKiAoc2VlIHtAbGluayBoZWF0bWFwLnNwYWNlWX0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZVk9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzcGFjZVksXG5cbiAgLyoqXG4gICogVGhlIGludGVybmFsIGtleSBvZiB0aGUgY2VsbCBzcGVjaWZpeWluZyB0byB3aGljaCB4IGF4aXMga2V5IGl0IGJlbG9uZ3NcbiAgKiAoc2VlIHtAbGluayBoZWF0bWFwLnhLZXl9KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbeEtleT0neCddXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhLZXkgPSAneCcsXG4gIC8qKlxuICAqIFRoZSBpbnRlcm5hbCBrZXkgb2YgdGhlIGNlbGwgc3BlY2lmaXlpbmcgdG8gd2hpY2ggeSBheGlzIGtleSBpdCBiZWxvbmdzXG4gICogKHNlZSB7QGxpbmsgaGVhdG1hcC55S2V5fSlcbiAgKiBAcGFyYW0ge3N0cmluZ30gW3lLZXk9J3knXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB5S2V5ID0gJ3knLFxuXG4gIC8qKlxuICAqIFRoZSBpbnRlcm5hbCBrZXkgb2YgdGhlIGNlbGwgc3BlY2lmaXlpbmcgd2hhdCB2YWx1ZSB0byB1c2UgdG8gZGV0ZXJtaW5lIHRoZSBjb2xvclxuICAqIChzZWUge0BsaW5rIGhlYXRtYXAudktleX0pXG4gICogQHBhcmFtIHtzdHJpbmd9IFt2S2V5PSd2J11cbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdktleSA9ICd2JyxcblxuICAvKipcbiAgKiBGdW5jdGlvbiBmb3IgZXh0cmFjdGluZyB0aGUgdGhlIHZhbHVlIGZyb20geEtleS5cbiAgKiAoc2VlIHtAbGluayBoZWF0bWFwLnhFeHRyYWN0b3J9KVxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFt4RXh0cmFjdG9yPWZ1bmN0aW9uKGtleSwgaSkgeyByZXR1cm4gZGF0YVtrZXldW3hLZXldIH1dXG4gICogQHJldHVybnMge3N0cmluZ31cbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeEV4dHJhY3RvciA9IGZ1bmN0aW9uKGtleSwgaSkge3JldHVybiBkYXRhW2tleV1beEtleV0gfSxcbiAgLyoqXG4gICogRnVuY3Rpb24gZm9yIGV4dHJhY3RpbmcgdGhlIHRoZSB2YWx1ZSBmcm9tIHlLZXkuXG4gICogKHNlZSB7QGxpbmsgaGVhdG1hcC55RXh0cmFjdG9yfSlcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbeUV4dHJhY3Rvcj1mdW5jdGlvbihrZXksIGkpIHsgcmV0dXJuIGRhdGFba2V5XVt5S2V5XSB9XVxuICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHlFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGkpIHsgcmV0dXJuIGRhdGFba2V5XVt5S2V5XSB9LFxuXG4gIC8qKlxuICAqIEZ1bmN0aW9uIGZvciBleHRyYWN0aW5nIHRoZSB0aGUgdmFsdWUgZnJvbSB2S2V5LlxuICAqIChzZWUge0BsaW5rIGhlYXRtYXAudkV4dHJhY3Rvcn0pXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3ZFeHRyYWN0b3I9ZnVuY3Rpb24oa2V5LCBpKSB7IHJldHVybiBkYXRhW2tleV1bdktleV0gfV1cbiAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2RXh0cmFjdG9yID0gZnVuY3Rpb24oa2V5LCBpKSB7IHJldHVybiBkYXRhW2tleV1bdktleV0gfSxcblxuXG4gIC8qKlxuICAqIFdoZXRoZXIgb3Igbm90IHRvIGFsbG93IGhlYXRtYXAgdG8gcmVuZGVyIGVsZW1lbnRzIHBhc3MgdGhlIG1haW4gc3BhdGlhbCBkaW1lbnNpb25cbiAgKiBnaXZlbiB0aGUgb3JpZW50YXRpb24gKHNlZSB7QGxpbmsgaGVhdG1hcCNvcmllbnR9KSwgd2hlcmUge0BsaW5rIGhlYXRtYXAjb3JpZW50fT1cImJvdHRvbVwiIG9yIHtAbGluayBoZWF0bWFwI29yaWVudH09XCJ0b3BcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgaGVhdG1hcCNzcGFjZVh9IGFuZCB3aGVyZSB7QGxpbmsgaGVhdG1hcCNvcmllbnR9PVwibGVmdFwiIG9yIHtAbGluayBoZWF0bWFwI29yaWVudH09XCJyaWdodFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayBoZWF0bWFwI3NwYWNlWX1cbiAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvdmVyZmxvd1E9ZmFsc2VdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG92ZXJmbG93USA9IGZhbHNlLFxuXG4gIC8qKlxuICAqIERlZmF1bHQgc3BhY2UgZm9yIHRoZSBzcGFjZXIgKHBlcmNlbnRhZ2UpIG9mIG1haW4gZGltZW5zaW9uIGdpdmVuIHRoZSBvcmllbnRhdGlvblxuICAqIChzZWUge0BsaW5rIGhlYXRtYXAjb3JpZW50fSksIHdoZXJlIHtAbGluayBoZWF0bWFwI29yaWVudH09XCJob3Jpem9udGFsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGhlYXRtYXAjc3BhY2VYfSBhbmQgd2hlcmUge0BsaW5rIGhlYXRtYXAjb3JpZW50fT1cInZlcnRpY2FsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGhlYXRtYXAjc3BhY2VZfSBiZXR3ZWVuIGJ1YmJsZXNcbiAgKiBAcGFyYW0ge251bWJlcn0gW29iamVjdFNwYWNlcj0wLjBdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdFNwYWNlciA9IDAuMCxcbiAgLyoqXG4gICogVGhlIG1pbmltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmUgaW4gdGhlIHkgZGltZW5zaW9uXG4gICogQHBhcmFtIHtudW1iZXJ9IFttaW5PYmplY3RTaXplPTUwXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB5TWluT2JqZWN0U2l6ZSA9IDUwLFxuICAvKipcbiAgKiBUaGUgbWluaW11bSBzaXplIHRoYXQgYW4gb2JqZWN0IGNhbiBiZSBpbiB0aGUgeCBkaW1lbnNpb25cbiAgKiBAcGFyYW0ge251bWJlcn0gW21pbk9iamVjdFNpemU9NTBdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhNaW5PYmplY3RTaXplID0gNTAsXG4gIC8qKlxuICAqIFRoZSBtYXhpbXVtIHNpemUgdGhhdCBhbiBvYmplY3QgY2FuIGJlIGluIHRoZSB4IGRpbWVuc2lvblxuICAqIEBwYXJhbSB7bnVtYmVyfSBbbWF4T2JqZWN0U2l6ZT0xMDBdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhNYXhPYmplY3RTaXplID0gMTAwLFxuICAvKipcbiAgKiBUaGUgbWF4aW11bSBzaXplIHRoYXQgYW4gb2JqZWN0IGNhbiBiZSBpbiB0aGUgeSBkaW1lbnNpb25cbiAgKiBAcGFyYW0ge251bWJlcn0gW21heE9iamVjdFNpemU9MTAwXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB5TWF4T2JqZWN0U2l6ZSA9IDEwMCxcblxuXG4gIC8qKlxuICAqIFRoZSBzdHJva2Ugd2lkdGggb2YgdGhlIGJ1YmJsZXNcbiAgKiBAcGFyYW0ge251bWJlcn0gW29iamVjdFN0cm9rZVdpZHRoPTJdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdFN0cm9rZVdpZHRoID0gMixcbiAgLy8gY29sb3JGdW5jID0gY29sb3JGdW5jdGlvbigpLFxuXG4gIC8qKlxuICAqIENvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kXG4gICogQHBhcmFtIHtzdHJpbmd9IFtiYWNrZ3JvdW5kRmlsbD1cInRyYW5zcGFyZW50XCJdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJhY2tncm91bmRGaWxsID0gJ3RyYW5zcGFyZW50JyxcbiAgLyoqXG4gICogTmFtZXNwYWNlIGZvciBhbGwgaXRlbXMgbWFkZSBieSB0aGlzIGluc3RhbmNlIG9mIGhlYXRtYXBcbiAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWVzcGFjZT1cImQzc20taGVhdG1hcFwiXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBuYW1lc3BhY2UgPSAnZDNzbS1oZWF0bWFwJyxcbiAgLyoqXG4gICogQ2xhc3MgbmFtZSBmb3IgaGVhdG1hcCBjb250YWluZXIgKDxnPiBlbGVtZW50KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbb2JqZWN0Q2xhc3M9XCJoZWF0bWFwXCJdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdENsYXNzID0gJ2hlYXRtYXAnLFxuICAvKipcbiAgKiBEdXJhdGlvbiBvZiBhbGwgdHJhbnNpdGlvbnMgb2YgdGhpcyBlbGVtZW50XG4gICogQHBhcmFtIHtudW1iZXJ9IFt0cmFuc2l0aW9uRHVyYXRpb249MTAwMF1cbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdHJhbnNpdGlvbkR1cmF0aW9uID0gMTAwMCxcbiAgLyoqXG4gICogRWFzaW5nIGZ1bmN0aW9uIGZvciB0cmFuc2l0aW9uc1xuICAqIEBwYXJhbSB7ZDMuZWFzZX0gW2Vhc2VGdW5jPWQzLmVhc2VFeHBdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGVhc2VGdW5jID0gZDMuZWFzZUV4cCxcblxuICAvKipcbiAgKiBTdG9yZXMgdGhlIGtleXMgb2YgYWxsIHRoZSBjZWxsc1xuICAqIENhbGN1bGF0ZWQgYWZ0ZXIgaGVhdG1hcCBjYWxsZWQuXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW2NlbGxLZXlzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgY2VsbEtleXMsXG4gIC8qKlxuICAqIFN0b3JlcyB0aGUgbGlzdCBvZiB1bmlxdWUgeFZhbHVlc1xuICAqIENhbGN1bGF0ZWQgYWZ0ZXIgaGVhdG1hcCBjYWxsZWQuXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW3hWYWx1ZXM9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB4VmFsdWVzLFxuICAvKipcbiAgKiBTdG9yZXMgdGhlIGxpc3Qgb2YgdW5pcXVlIHlWYWx1ZXNcbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt5VmFsdWVzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeVZhbHVlcyxcbiAgLyoqXG4gICogU3RvcmVzIHRoZSBsaXN0IG9mIHVuaXF1ZSB2VmFsdWVzXG4gICogQ2FsY3VsYXRlZCBhZnRlciBoZWF0bWFwIGNhbGxlZC5cbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbdlZhbHVlcz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHZWYWx1ZXMsXG5cbiAgeEtleVNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIHhWYWx1ZXMuaW5kZXhPZih4RXh0cmFjdG9yKGEpKSAtIHhWYWx1ZXMuaW5kZXhPZih4RXh0cmFjdG9yKGIpKSB9LFxuICB5S2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4geVZhbHVlcy5pbmRleE9mKHlFeHRyYWN0b3IoYSkpIC0geVZhbHVlcy5pbmRleE9mKHlFeHRyYWN0b3IoYikpIH0sXG4gIHZLZXlTb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihhLCBiKSB7IHJldHVybiB2VmFsdWVzLmluZGV4T2YodkV4dHJhY3RvcihhKSkgLSB5VmFsdWVzLmluZGV4T2YodkV4dHJhY3RvcihiKSkgfSxcblxuICAvKipcbiAgKiBJbnN0YW5jZSBvZiBDb2xvckZ1bmN0aW9uIHdpdGggLmNvbG9yQnkgc2V0IHRvICdjYXRlZ29yeSdcbiAgKiBAZnVuY3Rpb24gY29sb3JGdW5jdGlvblxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjb2xvckZ1bmN0aW9uID0gQ0YoKS5jb2xvckJ5KCdjYXRlZ29yeScpLFxuICAvKipcbiAgKiBJbnN0YW5jZSBvZiBUb29sdGlwXG4gICogQGZ1bmN0aW9uIHRvb2x0aXBcbiAgKiBAbWVtYmVyb2YgaGVhdG1hcCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdG9vbHRpcCA9IFRUaXAoKSxcblxuICAvKipcbiAgKiBzdG9yZSB0aGUgc2l6ZSB0aGUgaGVhdG1hcCBjb3VsZCBiZSBpbiB0aGUgeCBkaW1lbnNpb25cbiAgKiB0aGUgYWN0dWFsbCBzaXplIG9mIHRoZSBoZWF0bWFwIHdpbGwgYmUgdGhlIG1pbiBvZiB4U2l6ZSBhbmQge0BsaW5rIGhlYXRtYXAjeVNpemV9XG4gICogQ2FsY3VsYXRlZCBhZnRlciBoZWF0bWFwIGNhbGxlZC5cbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbeFNpemU9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBoZWF0bWFwI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB4U2l6ZSxcbiAgLyoqXG4gICogc3RvcmUgdGhlIHNpemUgb2YgdGhlIHNwYWNlciBpbiB0aGUgeCBkaW1lbnNpb25cbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt4U3BhY2VyU2l6ZT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhTcGFjZXJTaXplLFxuXG4gIC8qKlxuICAqIHN0b3JlIHRoZSBzaXplIHRoZSBoZWF0bWFwIGNvdWxkIGJlIGluIHRoZSB5IGRpbWVuc2lvblxuICAqIHRoZSBhY3R1YWxsIHNpemUgb2YgdGhlIGhlYXRtYXAgd2lsbCBiZSB0aGUgbWluIG9mIHhTaXplIGFuZCB7QGxpbmsgaGVhdG1hcCN4U2l6ZX1cbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt5U2l6ZT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHlTaXplLFxuICAvKipcbiAgKiBzdG9yZSB0aGUgc2l6ZSBvZiB0aGUgc3BhY2VyIGluIHRoZSB5IGRpbWVuc2lvbi5cbiAgKiBDYWxjdWxhdGVkIGFmdGVyIGhlYXRtYXAgY2FsbGVkLlxuICAqIEBwYXJhbSB7c3RyaW5nW119IFt4U3BhY2VyU2l6ZT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGhlYXRtYXAjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHlTcGFjZXJTaXplXG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgc2VsZWN0aW9uIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBkMy5zZWxlY3Rpb259XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNlbGVjdGlvbiA9IHNlbGVjdGlvblxuICAgKi9cbiAgaG0uc2VsZWN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZWxlY3Rpb24gPSBfLCBobSkgOiBzZWxlY3Rpb247IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZGF0YVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI2RhdGF9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBvYmplY3R9XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgaG0uZGF0YSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGF0YSA9IF8sIGhtKSA6IGRhdGE7IH1cbiAgLy8gaG0ub3JpZW50ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvcmllbnQgPSBfLCBobSkgOiBvcmllbnQ7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgYW1vdW50IG9mIGhvcml6b250YWwgc3BhY2UgaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjc3BhY2VYfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlWCA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0uc3BhY2VYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVggPSBfLCBobSkgOiBzcGFjZVg7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgYW1vdW50IG9mIHZlcnRpY2FsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3NwYWNlWX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBudW1iZXIgPiAwXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVkgPSB1bmRlZmluZWRcbiAgICovXG4gIGhtLnNwYWNlWSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3BhY2VZID0gXywgaG0pIDogc3BhY2VZOyB9XG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeEtleVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3hLZXl9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHhLZXkgPSAneCdcbiAgICovXG4gIGhtLnhLZXkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhLZXkgPSBfLCBobSkgOiB4S2V5OyB9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHlLZXlcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCN5S2V5fSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5S2V5ID0gJ3knXG4gICAqL1xuICBobS55S2V5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5S2V5ID0gXywgaG0pIDogeUtleTsgfVxuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHZLZXlcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCN2S2V5fSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB2S2V5ID0gJ3knXG4gICAqL1xuICBobS52S2V5ID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2S2V5ID0gXywgaG0pIDogdktleTsgfVxuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGNlbGxLZXlzXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjY2VsbEtleXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBjZWxsS2V5cyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0uY2VsbEtleXMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNlbGxLZXlzID0gXywgaG0pIDogY2VsbEtleXM7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeFZhbHVlc1xuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3hWYWx1ZXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB4VmFsdWVzID0gdW5kZWZpbmVkXG4gICAqL1xuICBobS54VmFsdWVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4VmFsdWVzID0gXywgaG0pIDogeFZhbHVlczsgfVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB5VmFsdWVzXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjeVZhbHVlc30pXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgc3RyaW5nW119XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHlWYWx1ZXMgPSB1bmRlZmluZWRcbiAgICovXG4gIGhtLnlWYWx1ZXMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlWYWx1ZXMgPSBfLCBobSkgOiB5VmFsdWVzOyB9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHZWYWx1ZXNcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCN2VmFsdWVzfSlcbiAgICogQHBhcmFtIHtudW1iZXJbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBudW1iZXJbXX1cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdlZhbHVlcyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0udlZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodlZhbHVlcyA9IF8sIGhtKSA6IHZWYWx1ZXM7IH1cblxuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHhFeHRyYWN0b3JcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCN4RXh0cmFjdG9yfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgeEV4dHJhY3RvciA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0ueEV4dHJhY3RvciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeEV4dHJhY3RvciA9IF8sIGhtKSA6IHhFeHRyYWN0b3I7IH1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgeUV4dHJhY3RvclxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3lFeHRyYWN0b3J9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5RXh0cmFjdG9yID0gdW5kZWZpbmVkXG4gICAqL1xuICBobS55RXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5RXh0cmFjdG9yID0gXywgaG0pIDogeUV4dHJhY3RvcjsgfVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSB2RXh0cmFjdG9yXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjdkV4dHJhY3Rvcn0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZFeHRyYWN0b3IgPSB1bmRlZmluZWRcbiAgICovXG4gIGhtLnZFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZFeHRyYWN0b3IgPSBfLCBobSkgOiB2RXh0cmFjdG9yOyB9XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IGhlYXRtYXAgaXMgYWxsb3dlZCB0byBnbyBiZXlvbmQgc3BlY2lmaWVkIGRpbWVuc2lvbnNcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCNzcGFjZVh9KVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgYm9vbGVhbn1cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3ZlcmZsb3dRID0gZmFsc2VcbiAgICovXG4gIGhtLm92ZXJmbG93USA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3ZlcmZsb3dRID0gXywgaG0pIDogb3ZlcmZsb3dROyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyBvYmplY3RTcGFjZXJcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCNvYmplY3RTcGFjZXJ9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG9iamVjdFNwYWNlciA9IDAuMFxuICAgKi9cbiAgaG0ub2JqZWN0U3BhY2VyID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvYmplY3RTcGFjZXIgPSBfLCBvYmplY3RTcGFjZXIpIDogZGF0YTsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1pbk9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCNtaW5PYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBtaW5PYmplY3RTaXplID0gNTBcbiAgICovXG4gIGhtLnlNaW5PYmplY3RTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5TWluT2JqZWN0U2l6ZSA9IF8sIGhtKSA6IHlNaW5PYmplY3RTaXplOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbWF4T2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI21heE9iamVjdFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1heE9iamVjdFNpemUgPSAxMDBcbiAgICovXG4gIGhtLnlNYXhPYmplY3RTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5TWF4T2JqZWN0U2l6ZSA9IF8sIGhtKSA6IHlNYXhPYmplY3RTaXplOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbWluT2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI21pbk9iamVjdFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2hlYXRtYXAgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1pbk9iamVjdFNpemUgPSA1MFxuICAgKi9cbiAgaG0ueE1pbk9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhNaW5PYmplY3RTaXplID0gXywgaG0pIDogeE1pbk9iamVjdFNpemU7IH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBtYXhPYmplY3RTaXplXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjbWF4T2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbWF4T2JqZWN0U2l6ZSA9IDEwMFxuICAgKi9cbiAgaG0ueE1heE9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhNYXhPYmplY3RTaXplID0gXywgaG0pIDogeE1heE9iamVjdFNpemU7IH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RTdHJva2VXaWR0aFxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI29iamVjdFN0cm9rZVdpZHRofSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RTdHJva2VXaWR0aCA9IDJcbiAgICovXG4gIGhtLm9iamVjdFN0cm9rZVdpZHRoID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvYmplY3RTdHJva2VXaWR0aCA9IF8sIGhtKSA6IG9iamVjdFN0cm9rZVdpZHRoOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYmFja2dyb3VuZEZpbGxcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCNiYWNrZ3JvdW5kRmlsbH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYmFja2dyb3VuZEZpbGwgPSAndHJhbnNwYXJlbnQnXG4gICAqL1xuICBobS5iYWNrZ3JvdW5kRmlsbCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFja2dyb3VuZEZpbGwgPSBfLCBobSkgOiBiYWNrZ3JvdW5kRmlsbDsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG5hbWVzcGFjZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI25hbWVzcGFjZX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbmFtZXNwYWNlID0gJ2Qzc20taGVhdG1hcCdcbiAgICovXG4gIGhtLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgaG0pIDogbmFtZXNwYWNlOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgb2JqZWN0Q2xhc3NcbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCNvYmplY3RDbGFzc30pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0Q2xhc3MgPSAndGljay1ncm91cCdcbiAgICovXG4gIGhtLm9iamVjdENsYXNzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvYmplY3RDbGFzcyA9IF8sIGhtKSA6IG9iamVjdENsYXNzOyB9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdHJhbnNpdGlvbkR1cmF0aW9uXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjdHJhbnNpdGlvbkR1cmF0aW9ufSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwXG4gICAqL1xuICBobS50cmFuc2l0aW9uRHVyYXRpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRyYW5zaXRpb25EdXJhdGlvbiA9IF8sIGhtKSA6IHRyYW5zaXRpb25EdXJhdGlvbjsgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGVhc2VGdW5jXG4gICAqIChzZWUge0BsaW5rIGhlYXRtYXAjZWFzZUZ1bmN9KVxuICAgKiBAcGFyYW0ge2QzLmVhc2V9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgZDMuZWFzZX1cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwXG4gICAqL1xuICBobS5lYXNlRnVuYyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZWFzZUZ1bmMgPSBfLCBobSkgOiBlYXNlRnVuYzsgfVxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdG9vbHRpcFxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3Rvb2x0aXB9KVxuICAgKiBAcGFyYW0ge3Rvb2x0aXB9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgdG9vbHRpcH1cbiAgICogQG1lbWJlcm9mIGhlYXRtYXBcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdG9vbHRpcCA9IHRvb2x0aXAoKVxuICAgKi9cbiAgaG0udG9vbHRpcCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodG9vbHRpcCA9IF8sIGhtKSA6IHRvb2x0aXA7IH1cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGNvbG9yRnVuY3Rpb25cbiAgICogKHNlZSB7QGxpbmsgaGVhdG1hcCNjb2xvckZ1bmN0aW9ufSlcbiAgICogQHBhcmFtIHtjb2xvckZ1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7aGVhdG1hcCB8IGNvbG9yRnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBoZWF0bWFwXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGNvbG9yRnVuY3Rpb24gPSBjb2xvckZ1bmN0aW9uKClcbiAgICovXG4gIGhtLmNvbG9yRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvbG9yRnVuY3Rpb24gPSBfLCBobSkgOiBjb2xvckZ1bmN0aW9uOyB9XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB4U2l6ZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3hTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB4U2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0ueFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhTaXplID0gXywgaG0pIDogeFNpemU7IH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB4U3BhY2VyU2l6ZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3hTcGFjZXJTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB4U3BhY2VyU2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0ueFNwYWNlclNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhTcGFjZXJTaXplID0gXywgaG0pIDogeFNwYWNlclNpemU7IH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB5U2l6ZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3lTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5U2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0ueVNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlTaXplID0gXywgaG0pIDogeVNpemU7IH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB5U3BhY2VyU2l6ZVxuICAgKiAoc2VlIHtAbGluayBoZWF0bWFwI3lTcGFjZXJTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtoZWF0bWFwIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgaGVhdG1hcFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5U3BhY2VyU2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgaG0ueVNwYWNlclNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlTcGFjZXJTaXplID0gXywgaG0pIDogeVNwYWNlclNpemU7IH1cbiAgLy8gaG0ueUtleVNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeUtleVNvcnRpbmdGdW5jdGlvbiA9IF8sIGhtKSA6IHlLZXlTb3J0aW5nRnVuY3Rpb247IH1cbiAgLy8gaG0ueEtleVNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeEtleVNvcnRpbmdGdW5jdGlvbiA9IF8sIGhtKSA6IHhLZXlTb3J0aW5nRnVuY3Rpb247IH1cblxuXG5cbiAgZnVuY3Rpb24gaG0oKSB7XG4gICAgdmFyIGhvcml6b250YWxRID0gdHJ1ZTsgLy8gbm8gb3JpZW50YXRpb24gaW4gaGVhdG1hcHMuIEFpZHMgYXMgcGxhY2Vob2xkZXIgaW4gZnVuY3Rpb25zIHRoYXQgdGFrZSBvcmllbnQgYXMgYSBwYXJhbWV0ZXJcbiAgICB2YXIgYmdjcFJlY3QgPSB7eDowLCB5OjAsIHdpZHRoOiBzcGFjZVgsIGhlaWdodDpzcGFjZVl9XG4gICAgdmFyIGNvbnRhaW5lciA9IHNldHVwQ29udGFpbmVyKCBzZWxlY3Rpb24sIG5hbWVzcGFjZSwgYmdjcFJlY3QsIGJhY2tncm91bmRGaWxsICk7XG5cbiAgICBjZWxsS2V5cyA9IGQzLmtleXMoZGF0YSk7XG5cbiAgICB4VmFsdWVzID0gdW5pcXVlKGNlbGxLZXlzLm1hcCh4RXh0cmFjdG9yKSk7XG4gICAgeVZhbHVlcyA9IHVuaXF1ZShjZWxsS2V5cy5tYXAoeUV4dHJhY3RvcikpO1xuICAgIHZWYWx1ZXMgPSB1bmlxdWUoY2VsbEtleXMubWFwKHZFeHRyYWN0b3IpKTtcblxuICAgIGNlbGxLZXlzLnNvcnQoZnVuY3Rpb24oYSwgYil7IHJldHVybiB4S2V5U29ydGluZ0Z1bmN0aW9uKGEsIGIpIHx8IHlLZXlTb3J0aW5nRnVuY3Rpb24oYSwgYikgfSlcbiAgICBsb2coJ2hlYXRtYXAnLCAnY2VsbHMgYXJlIHNvcnRlZCBieScsIGNlbGxLZXlzKVxuXG5cblxuICAgIGxvZygnaGVhdG1hcCcsICd4IGFuZCB5IGtleXMgYXJlJywge3g6IHhWYWx1ZXMsIHk6eVZhbHVlc30pXG5cblxuICAgIHZhciB4RGltID0geFZhbHVlcy5sZW5ndGgsIHlEaW0gPSB5VmFsdWVzLmxlbmd0aDtcblxuXG4gICAgeVNpemUgPSBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0KHNwYWNlWSwgeURpbSwgeU1pbk9iamVjdFNpemUsIHlNYXhPYmplY3RTaXplLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICB4U2l6ZSA9IGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3Qoc3BhY2VYLCB4RGltLCB4TWluT2JqZWN0U2l6ZSwgeE1heE9iamVjdFNpemUsIG9iamVjdFNwYWNlciwgb3ZlcmZsb3dRKVxuICAgIHlTcGFjZXJTaXplID0gY2FsY3VsYXRlV2lkdGhPZlNwYWNlcih5VmFsdWVzLCBzcGFjZVksIHlTaXplLCB5RGltLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICB4U3BhY2VyU2l6ZSA9IGNhbGN1bGF0ZVdpZHRoT2ZTcGFjZXIoeFZhbHVlcywgc3BhY2VYLCB4U2l6ZSwgeERpbSwgb2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgLy8gY29uc29sZS50YWJsZSh7XG4gICAgLy8gICAgIHg6e1xuICAgIC8vICAgICAgIG9iamVjdDogeFNpemUsXG4gICAgLy8gICAgICAgc3BhY2VyOiB4U3BhY2VyU2l6ZSxcbiAgICAvLyAgICAgICBkaW06IHhEaW1cbiAgICAvLyAgICAgfSxcbiAgICAvLyAgICAgeTp7XG4gICAgLy8gICAgICAgb2JqZWN0OiB5U2l6ZSxcbiAgICAvLyAgICAgICBzcGFjZXI6IHlTcGFjZXJTaXplLFxuICAgIC8vICAgICAgIGRpbTogeURpbVxuICAgIC8vICAgICB9XG4gICAgLy9cbiAgICAvLyB9KVxuICAgIGxvZygnaGVhdG1hcCcsICdzaXplIG9mJywge3g6IHhTaXplLCB5OiB5U2l6ZX0pXG5cblxuXG4gICAgdmFyIHlTcGFjZXIgPSBncm91cGluZ1NwYWNlcigpXG4gICAgLmhvcml6b250YWxRKGZhbHNlKVxuICAgIC5tb3ZlYnkoJ2NhdGVnb3J5JylcbiAgICAubnVtYmVyT2ZPYmplY3RzKHlEaW0pXG4gICAgLm9iamVjdENsYXNzKGh5cGVuYXRlKG9iamVjdENsYXNzLCAncm93JykpXG4gICAgLm9iamVjdFNpemUoeVNpemUgKyB5U3BhY2VyU2l6ZSlcbiAgICAuc3BhY2VyU2l6ZSgwKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKVxuICAgIC5lYXNlRnVuYyhlYXNlRnVuYylcbiAgICAubmFtZXNwYWNlKCdyb3cnKVxuXG4gICAgdmFyIHhTcGFjZXIgPSBncm91cGluZ1NwYWNlcigpXG4gICAgLmhvcml6b250YWxRKHRydWUpXG4gICAgLm1vdmVieSgnY2F0ZWdvcnknKVxuICAgIC5udW1iZXJPZk9iamVjdHMoeERpbSlcbiAgICAub2JqZWN0Q2xhc3Mob2JqZWN0Q2xhc3MpXG4gICAgLm9iamVjdFNpemUoeFNpemUgKyB4U3BhY2VyU2l6ZSlcbiAgICAuc3BhY2VyU2l6ZSgwKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKVxuICAgIC5lYXNlRnVuYyhlYXNlRnVuYylcblxuXG4gICAgeVNwYWNlcihjb250YWluZXIsIHlWYWx1ZXMsIDApXG4gICAgY29udGFpbmVyLnNlbGVjdEFsbCgnZy4nK2h5cGVuYXRlKG9iamVjdENsYXNzLCAncm93JykpXG4gICAgLmVhY2goZnVuY3Rpb24oZCwgaSl7IHhTcGFjZXIoZDMuc2VsZWN0KHRoaXMpLCB4VmFsdWVzLCAwKSB9KVxuXG4gICAgdmFyIGNlbGxzID0gY29udGFpbmVyLnNlbGVjdEFsbCgnZzpub3QoLnRvLXJlbW92ZSkuJytvYmplY3RDbGFzcylcblxuXG4gICAgaWYgKGNlbGxLZXlzLmxlbmd0aCAhPSB5VmFsdWVzLmxlbmd0aCAqIHhWYWx1ZXMubGVuZ3RoKSB7XG4gICAgICB2YXIgbG9va3VwID0ge31cbiAgICAgIGNlbGxLZXlzLm1hcChmdW5jdGlvbihrLCBpKXtcbiAgICAgICAgbG9va3VwW3hFeHRyYWN0b3IoaykrJzo6Jyt5RXh0cmFjdG9yKGspXSA9IGtcbiAgICAgIH0pXG5cbiAgICAgIHZhciBwb3NpdGlvbmVkQ2VsbEtleXMgPSBbXVxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB5VmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgeFZhbHVlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgIHZhciBsb29rdXBWYWx1ZSA9IGxvb2t1cFt4VmFsdWVzW2pdK1wiOjpcIit5VmFsdWVzW2ldXVxuICAgICAgICAgIGlmIChsb29rdXBWYWx1ZSA9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHBvc2l0aW9uZWRDZWxsS2V5cy5wdXNoKHVuZGVmaW5lZClcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcG9zaXRpb25lZENlbGxLZXlzLnB1c2gobG9va3VwVmFsdWUpXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNlbGxzLmRhdGEocG9zaXRpb25lZENlbGxLZXlzKTtcblxuICAgICAgLy8gbWF5YmUgYnJlYWtzIHRoaXNcbiAgICAgIC8vICEhISEhISBJTVBPUlRBTlQgTk9URSBUT0RPIExPT0sgSEVSRSBCVUdcbiAgICAgIGNlbGxLZXlzID0gcG9zaXRpb25lZENlbGxLZXlzXG4gICAgfSBlbHNlIHtcbiAgICAgIGNlbGxzLmRhdGEoY2VsbEtleXMpO1xuICAgIH1cblxuXG5cbiAgICB2YXIgcGFyZW50SW5kZXhBcnJheSA9IFtdXG4gICAgY2VsbHMuZWFjaChmdW5jdGlvbihkLCBpKXsgcGFyZW50SW5kZXhBcnJheS5wdXNoKE51bWJlcihkMy5zZWxlY3QodGhpcykuYXR0cigncGFyZW50LWluZGV4JykpKSB9KVxuXG4gICAgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24uY29sb3JCeSgpID09ICdpbmRleCdcbiAgICA/IGNvbG9yRnVuY3Rpb24uZGF0YUV4dGVudChbMCwgTWF0aC5tYXgoLi4ucGFyZW50SW5kZXhBcnJheSldKVxuICAgIDogY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50KFswLCBNYXRoLm1heCguLi52VmFsdWVzKV0pXG5cbiAgICBjZWxscy5lYWNoKGZ1bmN0aW9uKGtleSwgaSkge1xuICAgICAgbG9nKCdoZWF0bWFwJywgJ2VhY2ggY2VsbCcsIHtrZXk6IGtleSwgaW5kZXg6IGksIG5vZGU6IGQzLnNlbGVjdCh0aGlzKS5ub2RlKCl9KVxuXG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgICAgaWYgKGtleSA9PSB1bmRlZmluZWQpIHtyZXR1cm59XG4gICAgICB2YXIgY3VycmVudERhdGEgPSBkYXRhW2tleV0sXG4gICAgICB2YWx1ZSA9IHZFeHRyYWN0b3Ioa2V5LCBpKSxcbiAgICAgIGkgPSB0LmF0dHIoJ3BhcmVudC1pbmRleCcpID09IHVuZGVmaW5lZCA/IGkgOiB0LmF0dHIoJ3BhcmVudC1pbmRleCcpLFxuICAgICAgZmlsbENvbG9yID0gY29sb3JGdW5jdGlvbihrZXksIHZhbHVlLCBpLCAnZmlsbCcpLCAvLyBwcmV2ZW50IGR1cGxpY2F0ZSBjb21wdXRhdGlvblxuICAgICAgc3Ryb2tlQ29sb3IgPSBjb2xvckZ1bmN0aW9uKGtleSwgdmFsdWUsIGksICAnc3Ryb2tlJylcblxuICAgICAgdmFyIGMgPSBzYWZlU2VsZWN0KHQsICdyZWN0JywgaHlwZW5hdGUob2JqZWN0Q2xhc3MsJ3JlY3QnKSlcbiAgICAgIGMuYXR0cignd2lkdGgnLCB4U2l6ZSArIHhTcGFjZXJTaXplIC0gb2JqZWN0U3Ryb2tlV2lkdGgpXG4gICAgICAuYXR0cignaGVpZ2h0JywgeVNpemUgKyB5U3BhY2VyU2l6ZSAtIG9iamVjdFN0cm9rZVdpZHRoKVxuICAgICAgLmF0dHIoJ2ZpbGwnLCBmaWxsQ29sb3IpXG4gICAgICAuYXR0cigneCcsIG9iamVjdFN0cm9rZVdpZHRoLzIpXG4gICAgICAuYXR0cigneScsIG9iamVjdFN0cm9rZVdpZHRoLzIpXG4gICAgICAuYXR0cignc3Ryb2tlJywgXCIjMDAwXCIpXG4gICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgb2JqZWN0U3Ryb2tlV2lkdGgpXG5cbiAgICB9KVxuXG4gICAgdG9vbHRpcC5zZWxlY3Rpb24oY2VsbHMuc2VsZWN0QWxsKCdyZWN0LicraHlwZW5hdGUob2JqZWN0Q2xhc3MsICdyZWN0JykpKVxuICAgIC5kYXRhKGRhdGEpXG4gICAgLy8gLmtleXMoWydyJywgJ3YnXSlcbiAgICAvLyAuaGVhZGVyKGZ1bmN0aW9uKGQsIGkpe3JldHVybiBoeXBlbmF0ZShkYXRhW2RdW3hLZXldLCBkYXRhW2RdW3lLZXldKSB9KVxuXG4gICAgdG9vbHRpcCgpXG5cblxuICB9XG5cbiAgcmV0dXJuIGhtO1xufVxuXG5leHBvcnQge2hlYXRtYXB9XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtzZXR1cENvbnRhaW5lciwgY2FsY3VsYXRlV2lkdGhPZk9iamVjdCwgY2FsY3VsYXRlV2lkdGhPZlNwYWNlciwgd2hpc2tlclBhdGh9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHt1bmlxdWUsIGhhc1EsIGZsYXR0ZW59IGZyb20gJy4vYXJyYXktZnVuY3Rpb25zJztcbmltcG9ydCB7Z3JvdXBpbmdTcGFjZXJ9IGZyb20gJy4vZ3JvdXBpbmctc3BhY2VyJztcbmltcG9ydCB7Y29sb3JGdW5jdGlvbiBhcyBDRn0gZnJvbSAnLi9jb2xvci1mdW5jdGlvbic7XG5pbXBvcnQge3Rvb2x0aXAgYXMgVFRpcH0gZnJvbSAnLi90b29sdGlwJztcbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCT1ggQU5EIFdISVNLRVIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4vKipcbiAqIENyZWF0ZXMgYSBib3h3aGlza2VyXG4gKlxuICoge0BsaW5rIGh0dHBzOi8vc3VtbmV1cm9uLmdpdGxhYi5pby9kM3NtL2RlbW9zL2JveC13aGlza2Vycy9pbmRleC5odG1sIERlbW99XG4gKiBAY29uc3RydWN0b3IgYm94d2hpc2tlclxuICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IHNlbGVjdGlvblxuICogQG5hbWVzcGFjZSBib3h3aGlza2VyXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IGJveHdoaXNrZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJveHdoaXNrZXIoIHNlbGVjdGlvbiApIHtcbiAgdmFyXG4gIC8qKlxuICAqIERhdGEgdG8gcGxvdC4gQXNzdW1lZCB0byBiZSBhIG9iamVjdCwgd2hlcmUgZWFjaCBrZXkgY29ycmVzcG9uZHMgdG8gYSBib3hcbiAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI2RhdGF9KVxuICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGRhdGEsXG4gIC8qKlxuICAqIFdoaWNoIGRpcmVjdGlvbiB0byByZW5kZXIgdGhlIGJveGVzIGluXG4gICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNvcmllbnR9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbb3JpZW50PSdob3Jpem9udGFsJ11cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb3JpZW50ID0gJ2hvcml6b250YWwnLFxuICAvKipcbiAgKiBBbW91bnQgb2YgaG9yaXpvbnRhbCBzcGFjZSAoaW4gcGl4ZWxzKSBhdmFpYmxlIHRvIHJlbmRlciB0aGUgYm94d2hpc2tlciBpblxuICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjc3BhY2VYfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlWD11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNwYWNlWCxcbiAgLyoqXG4gICogQW1vdW50IG9mIHZlcnRpY2FsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSBib3h3aGlza2VyIGluXG4gICogKHNlZSB7QGxpbmsgYm94d2hpc2tlci5zcGFjZVl9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbc3BhY2VZPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VZLFxuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0byBhbGxvdyBib3h3aGlza2VyIHRvIHJlbmRlciBlbGVtZW50cyBwYXNzIHRoZSBtYWluIHNwYXRpYWwgZGltZW5zaW9uXG4gICogZ2l2ZW4gdGhlIG9yaWVudGF0aW9uIChzZWUge0BsaW5rIGJveHdoaXNrZXIjb3JpZW50fSksIHdoZXJlIHtAbGluayBib3h3aGlza2VyI29yaWVudH09XCJob3Jpem9udGFsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJveHdoaXNrZXIjc3BhY2VYfSBhbmQgd2hlcmUge0BsaW5rIGJveHdoaXNrZXIjb3JpZW50fT1cInZlcnRpY2FsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJveHdoaXNrZXIjc3BhY2VZfVxuICAqIEBwYXJhbSB7Ym9vbGVhbn0gW292ZXJmbG93UT1mYWxzZV1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb3ZlcmZsb3dRID0gdHJ1ZSxcblxuICAvKipcbiAgKiBBbiBhcnJheSAtIHB1dGF0aXZlbHkgb2Ygb3RoZXIgYXJyYXlzIC0gZGVwaWN0aW5nIGhvdyBib3hlcyBzaG91bGQgYmUgYXJyYW5nZWRcbiAgKiBAcGFyYW0ge0FycmF5W119IFtncm91cGluZz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGdyb3VwaW5nLFxuICBxdWFydGlsZXNLZXkgPSAncXVhcnRpbGVzJywgLy8ga2V5IGluIG9iamVjdCB3aGVyZSBxdWFydGlsZXMgYXJlIHN0b3JlZFxuICBxdWFydGlsZXNLZXlzID0gW1wiMC4wMFwiLCBcIjAuMjVcIiwgXCIwLjUwXCIsIFwiMC43NVwiLCBcIjEuMDBcIl0sIC8vIGtleXMgaW4gcXVhcnRpbGVzIG9iamVjdCBtYXBwaW5nIHZhbHVlcyB0byBtaW4sIHExLCBxMiwgcTMgYW5kIG1heFxuXG5cbiAgLyoqXG4gICogSG93IHRvIGdldCB0aGUgdmFsdWUgb2YgdGhlIGJveHdoaXNrZXJcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbdmFsdWVFeHRyYWN0b3I9ZnVuY3Rpb24oa2V5LCBpbmRleCkgeyByZXR1cm4gZGF0YVtrZXldW3F1YXJ0aWxlc0tleV0gfV1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGluZGV4KSB7IHJldHVybiBkYXRhW2tleV1bcXVhcnRpbGVzS2V5XSB9LFxuICAvKipcbiAgKiBIb3cgdG8gc29ydCB0aGUgYm94ZXMgLSBpZiB7QGxpbmsgYm94d2hpc2tlciNncm91cGluZ30gaXMgbm90IHByb3ZpZGVkLlxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtzb3J0aW5nRnVuY3Rpb249ZGVzY2VuZGluZ11cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKiBkZWZhdWx0XG4gICogZnVuY3Rpb24oa2V5QSwga2V5Qikge3JldHVybiBkMy5kZXNjZW5kaW5nKFxuICAqICAgdmFsdWVFeHRyYWN0b3Ioa2V5QSlbcXVhcnRpbGVzS2V5c1s0XV0sXG4gICogICB2YWx1ZUV4dHJhY3RvcihrZXlCKVtxdWFydGlsZXNLZXlzWzRdXVxuICAqICl9XG4gICovXG4gIHNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKGtleUEsIGtleUIpIHtyZXR1cm4gZDMuZGVzY2VuZGluZyhcbiAgICB2YWx1ZUV4dHJhY3RvcihrZXlBKVtxdWFydGlsZXNLZXlzWzRdXSxcbiAgICB2YWx1ZUV4dHJhY3RvcihrZXlCKVtxdWFydGlsZXNLZXlzWzRdXVxuICApfSxcbiAgLyoqXG4gICogVGhlIHNjYWxlIGZvciB3aGljaCBib3h3aGlza2VyIHZhbHVlcyBzaG91bGQgYmUgdHJhbnNmb3JtZWQgYnlcbiAgKiBAcGFyYW0ge2QzLnNjYWxlfSBbc2NhbGU9ZDMuc2NhbGVMaW5lYXJdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNjYWxlID0gZDMuc2NhbGVMaW5lYXIoKSxcbiAgLyoqXG4gICogVGhlIHBhZGRpbmcgZm9yIHRoZSBkb21haW4gb2YgdGhlIHNjYWxlIChzZWUge0BsaW5rIGJveHdoaXNrZXIjc2NhbGV9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbZG9tYWluUGFkZGluZz0wLjVdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGRvbWFpblBhZGRpbmcgPSAwLjUsXG4gIC8qKlxuICAqIERlZmF1bHQgc3BhY2UgZm9yIHRoZSBzcGFjZXIgKHBlcmNlbnRhZ2UpIG9mIG1haW4gZGltZW5zaW9uIGdpdmVuIHRoZSBvcmllbnRhdGlvblxuICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjb3JpZW50fSksIHdoZXJlIHtAbGluayBib3h3aGlza2VyI29yaWVudH09XCJob3Jpem9udGFsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJveHdoaXNrZXIjc3BhY2VYfSBhbmQgd2hlcmUge0BsaW5rIGJveHdoaXNrZXIjb3JpZW50fT1cInZlcnRpY2FsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGJveHdoaXNrZXIjc3BhY2VZfSBiZXR3ZWVuIGJveGVzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtvYmplY3RTcGFjZXI9MC4wNV1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0U3BhY2VyID0gMC4wNSxcbiAgLyoqXG4gICogVGhlIG1pbmltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmVcbiAgKiBAcGFyYW0ge251bWJlcn0gW21pbk9iamVjdFNpemU9MTVdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG1pbk9iamVjdFNpemUgPSAxNSxcbiAgLyoqXG4gICogVGhlIG1heGltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmVcbiAgKiBAcGFyYW0ge251bWJlcn0gW21heE9iamVjdFNpemU9NTBdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG1heE9iamVjdFNpemUgPSA1MCxcbiAgLyoqXG4gICogUGVyY2VudCBvZiBib3ggYW5kIHdoaXNrZXIgc2l6ZSB0aGF0IHdoaXNrZXJzIHdpbGwgYmUgcmVuZGVyZWRcbiAgKiBzZWUge0BsaW5rIGJveHdoaXNrZXIjb2JqZWN0U2l6ZX1cbiAgKiBAcGFyYW0ge251bWJlcn0gW3doaXNrZXJXaWR0aFBlcmNlbnQ9MC42XVxuICAqIEBtZW1iZXJvZiBib3h3aGlza2VyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB3aGlza2VyV2lkdGhQZXJjZW50ID0gLjYsXG4gIC8qKlxuICAqIEluc3RhbmNlIG9mIENvbG9yRnVuY3Rpb25cbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24oKV1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgY29sb3JGdW5jdGlvbiA9IENGKCksXG4gIC8qKlxuICAqIFRoZSBzdHJva2Ugd2lkdGggb2YgdGhlIGJveGVzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtib3hTdHJva2VXaWR0aD0yXVxuICAqIEBtZW1iZXJvZiBib3h3aGlza2VyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBib3hTdHJva2VXaWR0aCA9IDIsXG4gIC8qKlxuICAqIFRoZSBzdHJva2Ugd2lkdGggb2YgdGhlIHdoaXNrZXJzXG4gICogQHBhcmFtIHtudW1iZXJ9IFt3aGlza2VyU3Ryb2tlV2lkdGg9Ml1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgd2hpc2tlclN0cm9rZVdpZHRoID0gMixcblxuICAvKipcbiAgKiBDb2xvciBvZiB0aGUgYmFja2dyb3VuZFxuICAqIEBwYXJhbSB7c3RyaW5nfSBbYmFja2dyb3VuZEZpbGw9XCJ0cmFuc3BhcmVudFwiXVxuICAqIEBtZW1iZXJvZiBib3h3aGlza2VyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCcsXG4gIC8qKlxuICAqIE5hbWVzcGFjZSBmb3IgYWxsIGl0ZW1zIG1hZGUgYnkgdGhpcyBpbnN0YW5jZSBvZiBib3h3aGlza2VyXG4gICogQHBhcmFtIHtzdHJpbmd9IFtuYW1lc3BhY2U9XCJkM3NtLWJveC13aGlza2VyXCJdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG5hbWVzcGFjZSA9ICdkM3NtLWJveC13aGlza2VyJyxcbiAgLyoqXG4gICogQ2xhc3MgbmFtZSBmb3IgYm94d2hpc2tlciBjb250YWluZXIgKDxnPiBlbGVtZW50KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbb2JqZWN0Q2xhc3M9XCJib3gtd2hpc2tcIl1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0Q2xhc3MgPSAnYm94LXdoaXNrJyxcblxuICAvKipcbiAgKiBEdXJhdGlvbiBvZiBhbGwgdHJhbnNpdGlvbnMgb2YgdGhpcyBlbGVtZW50XG4gICogQHBhcmFtIHtudW1iZXJ9IFt0cmFuc2l0aW9uRHVyYXRpb249MTAwMF1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdHJhbnNpdGlvbkR1cmF0aW9uID0gMTAwMCxcbiAgLyoqXG4gICogRWFzaW5nIGZ1bmN0aW9uIGZvciB0cmFuc2l0aW9uc1xuICAqIEBwYXJhbSB7ZDMuZWFzZX0gW2Vhc2VGdW5jPWQzLmVhc2VFeHBdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGVhc2VGdW5jID0gZDMuZWFzZUV4cCxcblxuICAvKipcbiAgKiBUaGUga2V5cyBvZiB0aGUgYm94ZXNcbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbYm94S2V5cz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJveEtleXMsXG4gIC8qKlxuICAqIFRoZSB2YWx1ZXMgb2YgdGhlIGJveGVzXG4gICogQHBhcmFtIHtzdHJpbmdbXX0gW2JveFZhbHVlcz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGJveHdoaXNrZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJveFZhbHVlcyxcbiAgLyoqXG4gICogVGhlIG9iamVjdFNpemUgKGFjdHVhbCB3aWR0aCkgdXNlZCBieSB0aGUgYm94ZXNcbiAgKiBAcGFyYW0ge251bWJlcn0gW29iamVjdFNpemU9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBib3h3aGlza2VyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvYmplY3RTaXplLFxuICAvKipcbiAgKiBUaGUgc3BhY2VyU2l6ZSAoYWN0dWFsIHdpZHRoKSB1c2VkIGJ5IHRoZSBzcGFjZXJzIGJldHdlZW4gdGhlIGJveGVzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZXJTaXplPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VyU2l6ZSxcbiAgLyoqXG4gICogSW5zdGFuY2Ugb2YgVG9vbHRpcFxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFt0b29sdGlwPXRvb2x0aXAoKV1cbiAgKiBAbWVtYmVyb2YgYm94d2hpc2tlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdG9vbHRpcCA9IFRUaXAoKVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBzZWxlY3Rpb24gaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IGQzLnNlbGVjdGlvbn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc2VsZWN0aW9uID0gc2VsZWN0aW9uXG4gICAqL1xuICBib3h3aGlza2VyLnNlbGVjdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2VsZWN0aW9uID0gXywgYm94d2hpc2tlcikgOiBzZWxlY3Rpb247IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGRhdGFcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNkYXRhfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgb2JqZWN0fVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGJveHdoaXNrZXIuZGF0YSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGF0YSA9IF8sIGJveHdoaXNrZXIpIDogZGF0YTsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgb3JpZW50IG9mIHRoZSBib3hlc1xuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI29yaWVudH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IG9iamVjdH1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqL1xuICBib3h3aGlza2VyLm9yaWVudCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3JpZW50ID0gXywgYm94d2hpc2tlcikgOiBvcmllbnQ7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI3NwYWNlWH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBudW1iZXIgPiAwXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVggPSB1bmRlZmluZWRcbiAgICovXG4gIGJveHdoaXNrZXIuc3BhY2VYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVggPSBfLCBib3h3aGlza2VyKSA6IHNwYWNlWDsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgYW1vdW50IG9mIHZlcnRpY2FsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI3NwYWNlWX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBudW1iZXIgPiAwXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVkgPSB1bmRlZmluZWRcbiAgICovXG4gIGJveHdoaXNrZXIuc3BhY2VZID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVkgPSBfLCBib3h3aGlza2VyKSA6IHNwYWNlWTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IGJveHdoaXNrZXIgaXMgYWxsb3dlZCB0byBnbyBiZXlvbmQgc3BlY2lmaWVkIGRpbWVuc2lvbnNcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNvdmVyZmxvd1F9KVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgYm9vbGVhbn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3ZlcmZsb3dRID0gZmFsc2VcbiAgICovXG4gIGJveHdoaXNrZXIub3ZlcmZsb3dRID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvdmVyZmxvd1EgPSBfLCBib3h3aGlza2VyKSA6IG92ZXJmbG93UTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBncm91cGluZyBvZiB0aGUgYm94ZXNcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNncm91cGluZ30pXG4gICAqIEBwYXJhbSB7QXJyYXlbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBBcnJheVtdfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBncm91cGluZyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYm94d2hpc2tlci5ncm91cGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZ3JvdXBpbmcgPSBfLCBib3h3aGlza2VyKSA6IGdyb3VwaW5nOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHF1YXJ0aWxlc0tleVxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI3F1YXJ0aWxlc0tleX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgcXVhcnRpbGVzS2V5ID0gcXVhcnRpbGVzXG4gICAqL1xuICBib3h3aGlza2VyLnF1YXJ0aWxlc0tleSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocXVhcnRpbGVzS2V5ID0gXywgYm94d2hpc2tlcikgOiBxdWFydGlsZXNLZXk7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcXVhcnRpbGVzS2V5c1xuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI3F1YXJ0aWxlc0tleXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBxdWFydGlsZXNLZXlzID0gW1EwLCBRMSwgUTIsIFEzLCBRNF1cbiAgICovXG4gIGJveHdoaXNrZXIucXVhcnRpbGVzS2V5cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocXVhcnRpbGVzS2V5cyA9IF8sIGJveHdoaXNrZXIpIDogcXVhcnRpbGVzS2V5czsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB2YWx1ZUV4dHJhY3RvclxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI3ZhbHVlRXh0cmFjdG9yfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGluZGV4KSB7IHJldHVybiBkYXRhW2tleV1bcXVhcnRpbGVzS2V5XSB9LFxuICAgKi9cblxuICBib3h3aGlza2VyLnZhbHVlRXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZUV4dHJhY3RvciA9IF8sIGJveHdoaXNrZXIpIDogdmFsdWVFeHRyYWN0b3I7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgc29ydGluZ0Z1bmN0aW9uXG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjc29ydGluZ0Z1bmN0aW9ufSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oa2V5QSwga2V5Qikge3JldHVybiBkMy5kZXNjZW5kaW5nKFxuICAgKiAgIHZhbHVlRXh0cmFjdG9yKGtleUEpW3F1YXJ0aWxlc0tleXNbNF1dLFxuICAgKiAgIHZhbHVlRXh0cmFjdG9yKGtleUIpW3F1YXJ0aWxlc0tleXNbNF1dXG4gICAqICl9LFxuICAgKi9cbiAgYm94d2hpc2tlci5zb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNvcnRpbmdGdW5jdGlvbiA9IF8sIGJveHdoaXNrZXIpIDogc29ydGluZ0Z1bmN0aW9uOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHNjYWxlIGZvciB3aGljaCB0aGUgYm94d2hpc2tlciB2YWx1ZXMgc2hvdWxkIGJlIHRyYW5zZm9ybWVkIGJ5XG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjc2NhbGV9KVxuICAgKiBAcGFyYW0ge2QzLnNjYWxlfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IGQzLnNjYWxlfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKClcbiAgICovXG4gIGJveHdoaXNrZXIuc2NhbGUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNjYWxlID0gXywgYm94d2hpc2tlcikgOiBzY2FsZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBwYWRkaW5nIGZvciB0aGUgZG9tYWluIG9mIHRoZSBzY2FsZVxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI2RvbWFpblBhZGRpbmd9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGRvbWFpblBhZGRpbmcgPSAwLjVcbiAgICovXG4gIGJveHdoaXNrZXIuZG9tYWluUGFkZGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluUGFkZGluZyA9IF8sIGJveHdoaXNrZXIpIDogZG9tYWluUGFkZGluZzsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIG9iamVjdFNwYWNlclxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI29iamVjdFNwYWNlcn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0U3BhY2VyID0gMC4wNVxuICAgKi9cbiAgYm94d2hpc2tlci5vYmplY3RTcGFjZXIgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNwYWNlciA9IF8sIGJveHdoaXNrZXIpIDogb2JqZWN0U3BhY2VyOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1pbk9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNtaW5PYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBtaW5PYmplY3RTaXplID0gMTVcbiAgICovXG4gIGJveHdoaXNrZXIubWluT2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobWluT2JqZWN0U2l6ZSA9IF8sIGJveHdoaXNrZXIpIDogbWluT2JqZWN0U2l6ZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBtYXhPYmplY3RTaXplXG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjbWF4T2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbWF4T2JqZWN0U2l6ZSA9IDUwXG4gICAqL1xuICBib3h3aGlza2VyLm1heE9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1heE9iamVjdFNpemUgPSBfLCBib3h3aGlza2VyKSA6IG1heE9iamVjdFNpemU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgd2hpc2tlcldpZHRoUGVyY2VudFxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI3doaXNrZXJXaWR0aFBlcmNlbnR9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1heE9iamVjdFNpemUgPSAwLjZcbiAgICovXG4gIGJveHdoaXNrZXIud2hpc2tlcldpZHRoUGVyY2VudCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAod2hpc2tlcldpZHRoUGVyY2VudCA9IF8sIGJveHdoaXNrZXIpIDogd2hpc2tlcldpZHRoUGVyY2VudDsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBjb2xvckZ1bmN0aW9uXG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjY29sb3JGdW5jdGlvbn0pXG4gICAqIEBwYXJhbSB7Y29sb3JGdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBjb2xvckZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBjb2xvckZ1bmN0aW9uID0gY29sb3JGdW5jdGlvbigpXG4gICAqL1xuICBib3h3aGlza2VyLmNvbG9yRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvbG9yRnVuY3Rpb24gPSBfLCBib3h3aGlza2VyKSA6IGNvbG9yRnVuY3Rpb247IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYm94U3Ryb2tlV2lkdGhcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNib3hTdHJva2VXaWR0aH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYm94U3Ryb2tlV2lkdGggPSAyXG4gICAqL1xuICBib3h3aGlza2VyLmJveFN0cm9rZVdpZHRoID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChib3hTdHJva2VXaWR0aCA9IF8sIGJveHdoaXNrZXIpIDogYm94U3Ryb2tlV2lkdGg7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgd2hpc2tlclN0cm9rZVdpZHRoXG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjd2hpc2tlclN0cm9rZVdpZHRofSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB3aGlza2VyU3Ryb2tlV2lkdGggPSAyXG4gICAqL1xuICBib3h3aGlza2VyLndoaXNrZXJTdHJva2VXaWR0aCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAod2hpc2tlclN0cm9rZVdpZHRoID0gXywgYm94d2hpc2tlcikgOiB3aGlza2VyU3Ryb2tlV2lkdGg7IH07XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBiYWNrZ3JvdW5kRmlsbFxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI2JhY2tncm91bmRGaWxsfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtib3h3aGlza2VyIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCdcbiAgICovXG4gIGJveHdoaXNrZXIuYmFja2dyb3VuZEZpbGwgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJhY2tncm91bmRGaWxsID0gXywgYm94d2hpc2tlcikgOiBiYWNrZ3JvdW5kRmlsbDsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBuYW1lc3BhY2VcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNuYW1lc3BhY2V9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG5hbWVzcGFjZSA9ICdkM3NtLWJveHdoaXNrZXInXG4gICAqL1xuICBib3h3aGlza2VyLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgYm94d2hpc2tlcikgOiBuYW1lc3BhY2U7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgb2JqZWN0Q2xhc3NcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciNvYmplY3RDbGFzc30pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0Q2xhc3MgPSAndGljay1ncm91cCdcbiAgICovXG4gIGJveHdoaXNrZXIub2JqZWN0Q2xhc3MgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdENsYXNzID0gXywgYm94d2hpc2tlcikgOiBvYmplY3RDbGFzczsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB0cmFuc2l0aW9uRHVyYXRpb25cbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciN0cmFuc2l0aW9uRHVyYXRpb259KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRyYW5zaXRpb25EdXJhdGlvbiA9IDEwMDBcbiAgICovXG4gIGJveHdoaXNrZXIudHJhbnNpdGlvbkR1cmF0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0cmFuc2l0aW9uRHVyYXRpb24gPSBfLCBib3h3aGlza2VyKSA6IHRyYW5zaXRpb25EdXJhdGlvbjsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBlYXNlRnVuY1xuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI2Vhc2VGdW5jfSlcbiAgICogQHBhcmFtIHtkMy5lYXNlfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IGQzLmVhc2V9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGVhc2VGdW5jID0gZDMuZWFzZUV4cFxuICAgKi9cbiAgYm94d2hpc2tlci5lYXNlRnVuYyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZWFzZUZ1bmMgPSBfLCBib3h3aGlza2VyKSA6IGVhc2VGdW5jOyB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYmFyS2V5c1xuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI2JveEtleXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgYm94d2hpc2tlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBib3hLZXlzID0gdW5kZWZpbmVkXG4gICAqL1xuICBib3h3aGlza2VyLmJveEtleXMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJveEtleXMgPSBfLCBib3h3aGlza2VyKSA6IGJveEtleXM7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYm94VmFsdWVzXG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjYm94VmFsdWVzfSlcbiAgICogQHBhcmFtIHtudW1iZXJbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBudW1iZXJbXX1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYm94VmFsdWVzID0gdW5kZWZpbmVkXG4gICAqL1xuICBib3h3aGlza2VyLmJveFZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYm94VmFsdWVzID0gXywgYm94d2hpc2tlcikgOiBib3hWYWx1ZXM7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgb2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayBib3h3aGlza2VyI29iamVjdFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2JveHdoaXNrZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG9iamVjdFNpemUgPSB1bmRlZmluZWRcbiAgICovXG4gIGJveHdoaXNrZXIub2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0U2l6ZSA9IF8sIGJveHdoaXNrZXIpIDogb2JqZWN0U2l6ZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzcGFjZXJTaXplXG4gICAqIChzZWUge0BsaW5rIGJveHdoaXNrZXIjc3BhY2VyU2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGJveHdoaXNrZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc3BhY2VyU2l6ZSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgYm94d2hpc2tlci5zcGFjZXJTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZXJTaXplID0gXywgYm94d2hpc2tlcikgOiBzcGFjZXJTaXplOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRvb2x0aXBcbiAgICogKHNlZSB7QGxpbmsgYm94d2hpc2tlciN0b29sdGlwfSlcbiAgICogQHBhcmFtIHt0b29sdGlwfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Ym94d2hpc2tlciB8IHRvb2x0aXB9XG4gICAqIEBtZW1iZXJvZiBib3h3aGlza2VyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRvb2x0aXAgPSB0b29sdGlwKClcbiAgICovXG4gIGJveHdoaXNrZXIudG9vbHRpcCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodG9vbHRpcCA9IF8sIGJveHdoaXNrZXIpIDogdG9vbHRpcDsgfTtcblxuXG4gIGZ1bmN0aW9uIGJveHdoaXNrZXIoKSB7XG4gICAgLy8gZm9yIGNvbnZlbmllbmNlIGluIGhhbmRsaW5nIG9yaWVudGF0aW9uIHNwZWNpZmljIHZhbHVlc1xuICAgIHZhciBob3Jpem9udGFsUSA9IChvcmllbnQgPT0gJ2hvcml6b250YWwnKSA/IHRydWUgOiBmYWxzZVxuICAgIHZhciB2ZXJ0aWNhbFEgPSAhaG9yaXpvbnRhbFFcblxuICAgIC8vIGJhY2tncm91bmQgY2xpcGluZyByZWN0YW5nbGVcbiAgICB2YXIgYmdjcFJlY3QgPSB7eDowLCB5OjAsIHdpZHRoOiBzcGFjZVgsIGhlaWdodDpzcGFjZVl9XG4gICAgdmFyIGNvbnRhaW5lciA9IHNldHVwQ29udGFpbmVyKCBzZWxlY3Rpb24sIG5hbWVzcGFjZSwgYmdjcFJlY3QsIGJhY2tncm91bmRGaWxsICk7XG5cbiAgICAvLyBpZiBncm91cGluZyBpcyB1bmRlZmluZWQgc29ydCBrZXlzIGJ5IHNvcnRpbmcgZnVuY3RcbiAgICB2YXIgb3JkZXJlZCA9IChncm91cGluZyA9PSB1bmRlZmluZWQpID8gZDMua2V5cyhkYXRhKS5zb3J0KHNvcnRpbmdGdW5jdGlvbikgOiBncm91cGluZ1xuICAgIC8vIHRvIHByZXZlbnQgcmUtY2FsY3VsYXRpb24gYW5kIGdldHRlcnMgdG8gYmUgcGFzc2VkIHRvIGF4ZXNcbiAgICBib3hLZXlzID0gZmxhdHRlbihvcmRlcmVkKVxuICAgIGJveFZhbHVlcyA9IGJveEtleXMubWFwKHZhbHVlRXh0cmFjdG9yKVxuXG5cbiAgICB2YXIgbnVtYmVyT2ZPYmplY3RzID0gYm94S2V5cy5sZW5ndGhcbiAgICB2YXIgZXh0ZW50ID0gW1xuICAgICAgTWF0aC5taW4oLi4uYm94VmFsdWVzLm1hcChmdW5jdGlvbihkLGkpe3JldHVybiBkW3F1YXJ0aWxlc0tleXNbMF1dfSkpIC0gZG9tYWluUGFkZGluZyxcbiAgICAgIE1hdGgubWF4KC4uLmJveFZhbHVlcy5tYXAoZnVuY3Rpb24oZCxpKXtyZXR1cm4gZFtxdWFydGlsZXNLZXlzWzRdXX0pKSArIGRvbWFpblBhZGRpbmdcbiAgICBdO1xuXG4gICAgLy8gc2V0IHRoZSBzY2FsZVxuICAgIHNjYWxlLmRvbWFpbihleHRlbnQpLnJhbmdlKGhvcml6b250YWxRID8gWzAsc3BhY2VZXSA6IFtzcGFjZVgsIDBdKVxuICAgIHZhciBzcGFjZSA9IGhvcml6b250YWxRID8gc3BhY2VYIDogc3BhY2VZXG4gICAgLy8gY2FsY3VsYXRlIG9iamVjdCBzaXplXG4gICAgb2JqZWN0U2l6ZSA9IGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3Qoc3BhY2UsIG51bWJlck9mT2JqZWN0cywgbWluT2JqZWN0U2l6ZSwgbWF4T2JqZWN0U2l6ZSwgb2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgLy8gY2FsY3VsYXRlIHNwYWNlciBzaXplIGlmIG5lZWRlZFxuICAgIHNwYWNlclNpemUgPSBjYWxjdWxhdGVXaWR0aE9mU3BhY2VyKGJveEtleXMsIHNwYWNlLCBvYmplY3RTaXplLCBudW1iZXJPZk9iamVjdHMsIG9iamVjdFNwYWNlciwgb3ZlcmZsb3dRKVxuICAgIC8vIG1ha2UgdGhlIG5lc3RlZCBncm91cHNcbiAgICB2YXIgc3BhY2VyRnVuY3Rpb24gPSBncm91cGluZ1NwYWNlcigpXG4gICAgLmhvcml6b250YWxRKGhvcml6b250YWxRKS5zY2FsZShzY2FsZSkubW92ZWJ5KCdjYXRlZ29yeScpLm51bWJlck9mT2JqZWN0cyhudW1iZXJPZk9iamVjdHMpXG4gICAgLm9iamVjdENsYXNzKG9iamVjdENsYXNzKS5vYmplY3RTaXplKG9iamVjdFNpemUpLnNwYWNlclNpemUoc3BhY2VyU2l6ZSlcbiAgICAudHJhbnNpdGlvbkR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbikuZWFzZUZ1bmMoZWFzZUZ1bmMpXG4gICAgLm5hbWVzcGFjZShuYW1lc3BhY2UpXG5cbiAgICAvLyBtb3ZlIHN0dWZmXG4gICAgc3BhY2VyRnVuY3Rpb24oY29udGFpbmVyLCBvcmRlcmVkLCAwKVxuXG4gICAgdmFyIHBhcmVudEluZGV4QXJyYXkgPSBbXVxuICAgIGNvbnRhaW5lci5zZWxlY3RBbGwoJ2c6bm90KC50by1yZW1vdmUpLicrb2JqZWN0Q2xhc3MpXG4gICAgLmVhY2goZnVuY3Rpb24oZCwgaSl7aWYgKGhhc1EoYm94S2V5cywgZCkpeyBwYXJlbnRJbmRleEFycmF5LnB1c2goTnVtYmVyKGQzLnNlbGVjdCh0aGlzKS5hdHRyKCdwYXJlbnQtaW5kZXgnKSkpfX0pXG5cblxuXG4gICAgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24uY29sb3JCeSgpID09ICdpbmRleCdcbiAgICA/IGNvbG9yRnVuY3Rpb24uZGF0YUV4dGVudChbMCwgTWF0aC5tYXgoLi4ucGFyZW50SW5kZXhBcnJheSldKVxuICAgIDogY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50KGV4dGVudClcblxuXG4gICAgLy8gc2V0IGF0dHJpYnV0ZXMgZm9yIGJveCBhbmQgd2hpc2tlcnNcbiAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnOm5vdCgudG8tcmVtb3ZlKS4nK29iamVjdENsYXNzKS5lYWNoKGZ1bmN0aW9uKGtleSwgaSkge1xuICAgICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcyksXG4gICAgICBjdXJyZW50RGF0YSA9IGRhdGFba2V5XSxcblxuICAgICAgcXVhcnRpbGVzID0gdmFsdWVFeHRyYWN0b3Ioa2V5LCBpKSxcbiAgICAgIHEwID0gcXVhcnRpbGVzW3F1YXJ0aWxlc0tleXNbMF1dLFxuICAgICAgcTEgPSBxdWFydGlsZXNbcXVhcnRpbGVzS2V5c1sxXV0sXG4gICAgICBxMiA9IHF1YXJ0aWxlc1txdWFydGlsZXNLZXlzWzJdXSxcbiAgICAgIHEzID0gcXVhcnRpbGVzW3F1YXJ0aWxlc0tleXNbM11dLFxuICAgICAgcTQgPSBxdWFydGlsZXNbcXVhcnRpbGVzS2V5c1s0XV1cblxuICAgICAgdmFyIGkgPSB0LmF0dHIoJ3BhcmVudC1pbmRleCcpID09IHVuZGVmaW5lZCA/IGkgOiB0LmF0dHIoJ3BhcmVudC1pbmRleCcpLFxuICAgICAgZmlsbENvbG9yID0gY29sb3JGdW5jdGlvbihrZXksIHEyLCBpLCAnZmlsbCcpLCAvLyBwcmV2ZW50IGR1cGxpY2F0ZSBjb21wdXRhdGlvblxuICAgICAgc3Ryb2tlQ29sb3IgPSBjb2xvckZ1bmN0aW9uKGtleSwgcTIsIGksICAnc3Ryb2tlJylcblxuXG4gICAgICB2YXJcbiAgICAgIHdoaXNrID0gc2FmZVNlbGVjdCh0LCAnZycsICd3aGlza2VyJyksXG4gICAgICB1V2hpc2sgPSBzYWZlU2VsZWN0KHdoaXNrLCAncGF0aCcsICd1cHBlcicpLFxuICAgICAgbFdoaXNrID0gc2FmZVNlbGVjdCh3aGlzaywgJ3BhdGgnLCAnbG93ZXInKSxcbiAgICAgIHF1YXJ0ID0gc2FmZVNlbGVjdCh0LCAnZycsICdxdWFydGlsZScpLFxuICAgICAgdVF1YXJ0ID0gc2FmZVNlbGVjdChxdWFydCwgJ3JlY3QnLCAndXBwZXInKSxcbiAgICAgIGxRdWFydCA9IHNhZmVTZWxlY3QocXVhcnQsICdyZWN0JywgJ2xvd2VyJyksXG4gICAgICBtUXVhcnQgPSBzYWZlU2VsZWN0KHF1YXJ0LCAnY2lyY2xlJywgJ21lZGlhbicpXG5cblxuICAgICAgLy8gc2V0IHVwcGVyIHF1YXJ0aWxlIChxMylcbiAgICAgIHVRdWFydC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ3dpZHRoJywgaG9yaXpvbnRhbFEgPyBvYmplY3RTaXplIDogc2NhbGUocTMpIC0gc2NhbGUocTIpKVxuICAgICAgLmF0dHIoJ2hlaWdodCcsIHZlcnRpY2FsUSA/IG9iamVjdFNpemUgOiBzY2FsZShxMykgLSBzY2FsZShxMikpXG4gICAgICAuYXR0cignZmlsbCcsIGZpbGxDb2xvcilcbiAgICAgIC5hdHRyKCdzdHJva2UnLCBzdHJva2VDb2xvcilcbiAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCBib3hTdHJva2VXaWR0aClcbiAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBob3Jpem9udGFsUSA/IDAgOiBzY2FsZShxMiksXG4gICAgICAgIHkgPSB2ZXJ0aWNhbFEgPyAwIDogc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKHEzKSxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcblxuICAgICAgLy8gc2V0IGxvd2VyIHF1YXJ0aWxlIChxMSlcbiAgICAgIGxRdWFydC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ3dpZHRoJywgaG9yaXpvbnRhbFEgPyBvYmplY3RTaXplIDogc2NhbGUocTIpIC0gc2NhbGUocTEpKVxuICAgICAgLmF0dHIoJ2hlaWdodCcsIHZlcnRpY2FsUSA/IG9iamVjdFNpemUgOiBzY2FsZShxMikgLSBzY2FsZShxMSkpXG4gICAgICAuYXR0cignZmlsbCcsIGZpbGxDb2xvcilcbiAgICAgIC5hdHRyKCdzdHJva2UnLCBzdHJva2VDb2xvcilcbiAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCBib3hTdHJva2VXaWR0aClcbiAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBob3Jpem9udGFsUSA/IDAgOiBzY2FsZShxMSksXG4gICAgICAgIHkgPSB2ZXJ0aWNhbFEgPyAwIDogc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKHEyKSxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcblxuXG4gICAgICAvLyBzZXQgbWVkaWFuIChxMilcbiAgICAgIG1RdWFydC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ3InLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgICAgdmFyIHIgPSBvYmplY3RTaXplIC8gMlxuICAgICAgICB2YXIgZGlmID0gKHNjYWxlKHEzKSAtIHNjYWxlKHExKSkgLyAyXG4gICAgICAgIHJldHVybiAociA+IGRpZikgPyBkaWYgOiByXG4gICAgICB9KVxuICAgICAgLmF0dHIoJ2ZpbGwnLCBmaWxsQ29sb3IpXG4gICAgICAuYXR0cignc3Ryb2tlJywgc3Ryb2tlQ29sb3IpXG4gICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgYm94U3Ryb2tlV2lkdGgpXG4gICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIHZhclxuICAgICAgICB4ID0gaG9yaXpvbnRhbFEgPyBvYmplY3RTaXplIC8gMiA6IHNjYWxlKHEyKSxcbiAgICAgICAgeSA9IHZlcnRpY2FsUSA/IG9iamVjdFNpemUgLyAyIDogc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKHEyKSxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcblxuICAgICAgLy8gc2V0IGxvd2VyIHdoaXNrZXIgKG1pbilcbiAgICAgIGxXaGlzay50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ2QnLCBmdW5jdGlvbihkZCwgaWkpe1xuICAgICAgICB2YXJcbiAgICAgICAgZGlyID0gZmFsc2UsXG4gICAgICAgIHggPSAwLFxuICAgICAgICB5ID0gMCxcbiAgICAgICAgaCA9IGhvcml6b250YWxRID8gc2NhbGUocTEpIC0gc2NhbGUocTApIDogb2JqZWN0U2l6ZSxcbiAgICAgICAgdyA9IHZlcnRpY2FsUSA/IHNjYWxlKHExKSAtIHNjYWxlKHEwKSA6IG9iamVjdFNpemVcbiAgICAgICAgcmV0dXJuIHdoaXNrZXJQYXRoKGRpciwgeCwgeSwgdywgaCwgd2hpc2tlcldpZHRoUGVyY2VudCwgb3JpZW50KVxuICAgICAgfSlcbiAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBob3Jpem9udGFsUSA/IDAgOiBzY2FsZShxMSksXG4gICAgICAgIHkgPSB2ZXJ0aWNhbFEgPyAwIDogc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKHExKSxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcbiAgICAgIC5hdHRyKCdzdHJva2UnLCAnYmxhY2snKS5hdHRyKCdzdHJva2Utd2lkdGgnLCB3aGlza2VyU3Ryb2tlV2lkdGgpXG4gICAgICAuYXR0cignZmlsbCcsICdub25lJylcblxuICAgICAgLy8gc2V0IHVwcGVyIHdoaXNrZXIgKG1heClcbiAgICAgIHVXaGlzay50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ2QnLCBmdW5jdGlvbihkZCwgaWkpe1xuICAgICAgICB2YXJcbiAgICAgICAgZGlyID0gdHJ1ZSxcbiAgICAgICAgeCA9IDAsXG4gICAgICAgIHkgPSAwLFxuICAgICAgICBoID0gaG9yaXpvbnRhbFEgPyBzY2FsZShxNCkgLSBzY2FsZShxMykgOiBvYmplY3RTaXplLFxuICAgICAgICB3ID0gdmVydGljYWxRID8gc2NhbGUocTQpIC0gc2NhbGUocTMpIDogb2JqZWN0U2l6ZVxuICAgICAgICByZXR1cm4gd2hpc2tlclBhdGgoZGlyLCB4LCB5LCB3LCBoLCB3aGlza2VyV2lkdGhQZXJjZW50LCBvcmllbnQpXG4gICAgICB9KVxuICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgICB2YXJcbiAgICAgICAgeCA9IGhvcml6b250YWxRID8gMCA6IHNjYWxlKHEzKSxcbiAgICAgICAgeSA9IHZlcnRpY2FsUSA/IDAgOiAgc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKHE0KSxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcbiAgICAgIC5hdHRyKCdzdHJva2UnLCAnYmxhY2snKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIHdoaXNrZXJTdHJva2VXaWR0aClcbiAgICAgIC5hdHRyKCdmaWxsJywgJ25vbmUnKVxuXG4gICAgfSlcblxuICAgIHRvb2x0aXAuc2VsZWN0aW9uKGNvbnRhaW5lci5zZWxlY3RBbGwoJ2c6bm90KC50by1yZW1vdmUpLicrb2JqZWN0Q2xhc3MpKVxuICAgIC5kYXRhKGRhdGEpXG4gICAgdG9vbHRpcCgpXG5cblxuICB9XG5cbiAgcmV0dXJuIGJveHdoaXNrZXJcbn1cbiIsImltcG9ydCB7aHlwZW5hdGUsIHNhZmVTZWxlY3R9IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQge3NlbGVjdEZpbHRlcn0gZnJvbSAnLi9zZWxlY3QtZmlsdGVyJztcblxuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERBVEFUT0dHTEUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbi8qKlxuICogQ3JlYXRlcyBhIGRhdGF0b2dnbGVcbiAqIEBjb25zdHJ1Y3RvciBkYXRhdG9nZ2xlXG4gKiBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gc2VsZWN0aW9uXG4gKiBAbmFtZXNwYWNlIGRhdGF0b2dnbGVcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gZGF0YXRvZ2dsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGF0YXRvZ2dsZSggc2VsZWN0aW9uICkge1xuICB2YXJcbiAgLyoqXG4gICogS2V5cyB0byBtYWtlIHRvZ2dsZS1hYmxlIG9wdGlvbnNcbiAgKiAoc2VlIHtAbGluayBkYXRhdG9nZ2xlI2tleXN9KVxuICAqIEBwYXJhbSB7c3RyaW5nW119IFtrZXlzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgZGF0YXRvZ2dsZSNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAga2V5cyxcbiAgLyoqXG4gICogV2hhdCB0byBkbyB3aGVuIGEgZGlmZmVyZW50IGtleSBpcyBjbGlja2VkXG4gICogKHNlZSB7QGxpbmsgZGF0YXRvZ2dsZSN1cGRhdGVGdW5jdGlvbn0pXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3VwZGF0ZUZ1bmN0aW9uPWZ1bmN0aW9uKCl7fV1cbiAgKiBAbWVtYmVyb2YgZGF0YXRvZ2dsZSNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdXBkYXRlRnVuY3Rpb24gPSBmdW5jdGlvbigpe30sXG4gIC8qKlxuICAqIE5hbWVzcGFjZSBmb3IgYWxsIGl0ZW1zIG1hZGUgYnkgdGhpcyBpbnN0YW5jZSBvZiBkYXRhdG9nZ2xlXG4gICogQHBhcmFtIHtzdHJpbmd9IFtuYW1lc3BhY2U9XCJkM3NtLWRhdGFiYXJcIl1cbiAgKiBAbWVtYmVyb2YgZGF0YXRvZ2dsZSNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbmFtZXNwYWNlPSdkM3NtLWRhdGFiYXInLFxuICAvKipcbiAgKiBDdXJyZW50bHkgdG9nZ2xlZCBrZXlcbiAgKiBAcGFyYW0ge3N0cmluZ30gW2N1cnJlbnRLZXk9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBkYXRhdG9nZ2xlI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjdXJyZW50S2V5LFxuXG4gIHhBeGlzU2VsZWN0USA9IGZhbHNlLFxuICB4QXhpc09wdGlvbnMsXG4gIHlBeGlzU2VsZWN0USA9IGZhbHNlLFxuICB5QXhpc09wdGlvbnMsXG4gIGRhdGFcbiAgdG9nZ2xlLnhBeGlzU2VsZWN0USA9IGZ1bmN0aW9uKF8pe3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhBeGlzU2VsZWN0USA9IF8sIHRvZ2dsZSkgOiB4QXhpc1NlbGVjdFF9XG4gIHRvZ2dsZS55QXhpc1NlbGVjdFEgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5QXhpc1NlbGVjdFEgPSBfLCB0b2dnbGUpIDogeUF4aXNTZWxlY3RRfVxuICB0b2dnbGUueEF4aXNPcHRpb25zID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeEF4aXNPcHRpb25zID0gXywgdG9nZ2xlKSA6IHhBeGlzT3B0aW9uc31cbiAgdG9nZ2xlLnlBeGlzT3B0aW9ucyA9IGZ1bmN0aW9uKF8pe3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlBeGlzT3B0aW9ucyA9IF8sIHRvZ2dsZSkgOiB5QXhpc09wdGlvbnN9XG4gIHRvZ2dsZS5kYXRhID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGF0YSA9IF8sIHRvZ2dsZSkgOiBkYXRhfVxuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB1cGRhdGVGdW5jdGlvblxuICAgKiAoc2VlIHtAbGluayBkYXRhdG9nZ2xlI3VwZGF0ZUZ1bmN0aW9ufSlcbiAgICogQGZ1bmN0aW9uIGRhdGF0b2dnbGUudXBkYXRlRnVuY3Rpb25cbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2RhdGF0b2dnbGUgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIGRhdGF0b2dnbGVcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdXBkYXRlRnVuY3Rpb24gPSBmdW5jdGlvbigpe31cbiAgICovXG4gIHRvZ2dsZS51cGRhdGVGdW5jdGlvbiA9IGZ1bmN0aW9uKF8pe3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHVwZGF0ZUZ1bmN0aW9uID0gXywgdG9nZ2xlKSA6IHVwZGF0ZUZ1bmN0aW9ufVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG5hbWVzcGFjZVxuICAgKiAoc2VlIHtAbGluayBkYXRhdG9nZ2xlI25hbWVzcGFjZX0pXG4gICAqIEBmdW5jdGlvbiBkYXRhdG9nZ2xlLm5hbWVzcGFjZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge2RhdGF0b2dnbGUgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBkYXRhdG9nZ2xlXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG5hbWVzcGFjZSA9ICdkM3NtLWRhdGFiYXInXG4gICAqL1xuICB0b2dnbGUubmFtZXNwYWNlID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgdG9nZ2xlKSA6IG5hbWVzcGFjZX1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBjdXJyZW50S2V5XG4gICAqIChzZWUge0BsaW5rIGRhdGF0b2dnbGUjY3VycmVudEtleX0pXG4gICAqIEBmdW5jdGlvbiBkYXRhdG9nZ2xlLmN1cnJlbnRLZXlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtkYXRhdG9nZ2xlIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgZGF0YXRvZ2dsZVxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBjdXJyZW50S2V5ID0gdW5kZWZpbmVkXG4gICAqL1xuICB0b2dnbGUuY3VycmVudEtleXMgPVxuICBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHZhbHMgPSB7fVxuICAgIGQzLmtleXMoZmlsdGVyU2VsZWN0cykubWFwKGZ1bmN0aW9uKGssIGkpe1xuICAgICAgdmFsc1trXT0gZmlsdGVyU2VsZWN0c1trXS5jdXJyZW50T3B0aW9uKClcbiAgICB9KVxuICAgIHJldHVybiB2YWxzXG4gIH1cblxuICB2YXIgZmlsdGVyU2VsZWN0cyA9IHt9XG4gIGZ1bmN0aW9uIHRvZ2dsZSgpIHtcbiAgICAvLyBzZWxlY3Rpb24gb3B0aW9uc1xuXG4gICAgLy8gc2VsZWN0aW9uLmNsYXNzZWQoJ2QtZmxleCBmbGV4LXJvdycsIHRydWUpXG4gICAgLy8gdmFyIGZpbHRlckJ1dHRvbiA9IHNhZmVTZWxlY3Qoc2VsZWN0aW9uLCAnYScsICdzbGlkZXItYnV0dG9ucycpXG4gICAgLy8gdmFyIGZpbHRlckkgPSBzYWZlU2VsZWN0KGZpbHRlckJ1dHRvbiwgJ2knLCAnZmEgZmEtc2xpZGVycycpXG5cbiAgICAvKkJVRzogdW5leHBlY3RlZCBiZWhhdmlvci5cbiAgICAgIC0gd2hlbiB1c2luZyBib290c3RyYXAtZXF1ZSB3YXkgZm9yIGNvbGxhcHNlLCBjbGlja2luZyBidXR0b24gc3VibWl0cyB0b1xuICAgICAgdGhlIHNhbWUgcGFnZSBpbiBhcHBsaWNhdGlvbnMgKGJ1dCBub3QgaW4gZGVtbyksIHNvIHVzaW5nIGFuY2hvciAoPGE+KVxuICAgICAgLSB3aGVuIHVzaW5nIGFuY2hvciwgY2F1c2UgcGFnZSB0byBqdW1wIHRvIHRoYXQgbG9jYXRpb25cbiAgICAgIC0gd2hlbiB1c2luZyBzaG93LCB0aGUgZmlyc3Qgb3BlbiB3b3JrcywgYnV0IHRoZSBjbG9zZSBkb2VzIG5vdC5cbiAgICAqL1xuICAgIC8vIGZpbHRlckJ1dHRvbi5hdHRyKCdjbGFzcycsICdidG4gYnRuLXNlY29uZGFyeScpXG4gICAgLy8gLmF0dHIoJ2RhdGEtdG9nZ2xlJywgJ2NvbGxhcHNlJylcbiAgICAvLyAuYXR0cignaHJlZicsICcjJytoeXBlbmF0ZShuYW1lc3BhY2UsICdkYXRhLXRvZ2dsZScpKVxuICAgIC8vIC5hdHRyKCd0YXJnZXQnLCAnX2JsYW5rJylcbiAgICAvLyAuaHRtbChmaWx0ZXJCdXR0b24uaHRtbCgpKycgRmlsdGVycycpXG4gICAgLy8gLm9uKCdjbGljaycsIGZ1bmN0aW9uKGQsIGkpe1xuICAgIC8vICAgZDMuZXZlbnQucHJldmVudERlZmF1bHQoKVxuICAgIC8vICAgZDMuZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcbiAgICAvLyAgIHZhciBkdCA9IGQzLnNlbGVjdChcIiNcIitoeXBlbmF0ZShuYW1lc3BhY2UsICdkYXRhLXRvZ2dsZScpKVxuICAgIC8vICAgZHQuY2xhc3NlZCgnc2hvdycsICFkdC5jbGFzc2VkKCdzaG93JykpXG4gICAgLy8gICBkdC5jbGFzc2VkKCdkLWlubGluZS1mbGV4JywgZHQuY2xhc3NlZCgnc2hvdycpKVxuICAgIC8vXG4gICAgLy8gICBmaWx0ZXJCdXR0b24uY2xhc3NlZCgnYnRuLXByaW1hcnknLCBkdC5jbGFzc2VkKCdzaG93JykpXG4gICAgLy8gICBmaWx0ZXJCdXR0b24uY2xhc3NlZCgnYnRuLXNlY29uZGFyeScsICFkdC5jbGFzc2VkKCdzaG93JykpXG4gICAgLy8gfSlcbiAgICAvLyAuY2xhc3NlZCgnZC1pbmxpbmUtZmxleCcsIHRydWUpXG4gICAgLy8gLnN0eWxlKFwibWFyZ2luLXJpZ2h0XCIsICcxMHB4JylcblxuXG5cbiAgICAvLyB2YXIgZGF0YXRvZ2dsZUNvbGxhcHNlID0gc2FmZVNlbGVjdChzZWxlY3Rpb24sICdkaXYnLCBoeXBlbmF0ZShuYW1lc3BhY2UsJ2NvbGxhcHNlJykpXG4gICAgLy8gLmF0dHIoJ2lkJywgaHlwZW5hdGUobmFtZXNwYWNlLCAnZGF0YS10b2dnbGUnKSlcbiAgICAvLyAuY2xhc3NlZCgnY29sbGFwc2UnLCB0cnVlKVxuXG4gICAgLy8gdmFyIGZsZXhSb3cgPSBzYWZlU2VsZWN0KGRhdGF0b2dnbGVDb2xsYXBzZSwgJ2RpdicsICdkLWlubGluZS1mbGV4IGZsZXgtcm93IGZsZXgtd3JhcCcpXG4gICAgdmFyIGZsZXhSb3cgPSBzYWZlU2VsZWN0KHNlbGVjdGlvbiwgJ2RpdicsICdkLWlubGluZS1mbGV4IGZsZXgtcm93IGZsZXgtd3JhcCcpXG5cbiAgICB2YXIgZGF0YW9wdHMgPSBmbGV4Um93LnNlbGVjdEFsbCgnZGl2LicraHlwZW5hdGUobmFtZXNwYWNlLCdzZWxlY3QtZmlsdGVyJykpXG4gICAgLy8gcmVtb3ZlIGV4Y2Vzc1xuICAgIGRhdGFvcHRzLmV4aXQoKS5yZW1vdmUoKVxuICAgIC8vIGJpbmQgZGF0YVxuICAgIGRhdGFvcHRzID0gZGF0YW9wdHMuZGF0YShkMy5rZXlzKGRhdGEpKVxuICAgIC8vZW50ZXJcbiAgICB2YXIgZG9FbnRlciA9IGRhdGFvcHRzLmVudGVyKCkuYXBwZW5kKCdkaXYnKVxuICAgIC5hdHRyKCdjbGFzcycsICdzZWxlY3QtZmlsdGVyJylcblxuICAgIGRhdGFvcHRzID0gZGF0YW9wdHMubWVyZ2UoZG9FbnRlcikuc3R5bGUoJ21hcmdpbi1yaWdodCcsIFwiMTBweFwiKVxuXG4gICAgZGF0YW9wdHMuZWFjaChmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhciB0ID0gZDMuc2VsZWN0KHRoaXMpXG4gICAgICB2YXIgc2YgPSBzZWxlY3RGaWx0ZXIodClcbiAgICAgIC5kYXRhKGRhdGFbZF0pXG4gICAgICAubmFtZXNwYWNlKGh5cGVuYXRlKG5hbWVzcGFjZSwgZCkpXG4gICAgICAuc2VsZWN0aW9uTmFtZShkKVxuICAgICAgc2YoKVxuICAgICAgZmlsdGVyU2VsZWN0c1tkXSA9IHNmXG4gICAgfSlcblxuXG4gICAgc2VsZWN0aW9uLnNlbGVjdEFsbCgnc2VsZWN0JylcbiAgICAub24oJ2NoYW5nZScsIGZ1bmN0aW9uKCl7dXBkYXRlRnVuY3Rpb24oKX0pXG4gICAgLy8gYmluZCB1cGRhdGUgZnVuY3Rpb25cbiAgICAvLyBkMy5zZWxlY3RBbGxcbiAgICByZXR1cm4gdG9nZ2xlXG4gIH1cblxuXG4gIGZ1bmN0aW9uIG9ubHlPbmUoKSB7XG4gICAgLy8gZDMuZXZlbnQucHJldmVudERlZmF1bHQoKVxuICAgIC8vIGQzLmV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXG4gICAgdmFyIGRhdGFvcHRzID0gc2VsZWN0aW9uLnNlbGVjdEFsbCgnZGl2LmRhdGEtb3B0aW9uJylcbiAgICBjdXJyZW50S2V5ID0gZGF0YW9wdHMuc2VsZWN0KCc6Y2hlY2tlZCcpLmRhdHVtKClcbiAgICB1cGRhdGVGdW5jdGlvbigpXG5cbiAgfVxuXG4gIGZ1bmN0aW9uIGF4aXNTZWxlY3RGaWx0ZXIoc2VsZWN0aW9uLCBheGlzPVwieC1heGlzXCIsIGF4aXNEYXRhKSB7XG4gICAgaWYgKGF4aXNEYXRhID09IHVuZGVmaW5lZCkge1xuICAgICAgYXhpc0RhdGEgPSB7XG4gICAgICAgICdsaW5lYXInOiBkMy5zY2FsZUxpbmVhcigpLFxuICAgICAgICAnbG9nJzogZDMuc2NhbGVMb2coKSxcbiAgICAgICAgJ3Bvdyc6IGQzLnNjYWxlUG93KCksXG4gICAgICAgICdzcXJ0JzogZDMuc2NhbGVTcXJ0KClcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc2YgPSBzZWxlY3RGaWx0ZXIoc2VsZWN0aW9uKVxuICAgIC5kYXRhKGF4aXNEYXRhKVxuICAgIC5uYW1lc3BhY2UoYXhpcylcbiAgICAuc2VsZWN0aW9uTmFtZShheGlzKycgc2NhbGUnKVxuICAgIC5kZWZhdWx0VmFsdWUoZDMuc2NhbGVMaW5lYXIoKSlcblxuXG4gICAgc2YoKVxuXG4gIH1cblxuICByZXR1cm4gdG9nZ2xlXG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtzZXR1cENvbnRhaW5lciwgY2FsY3VsYXRlV2lkdGhPZk9iamVjdCwgY2FsY3VsYXRlV2lkdGhPZlNwYWNlcn0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQge3VuaXF1ZSwgZmxhdHRlbn0gZnJvbSAnLi9hcnJheS1mdW5jdGlvbnMnO1xuaW1wb3J0IHtncm91cGluZ1NwYWNlcn0gZnJvbSAnLi9ncm91cGluZy1zcGFjZXInO1xuaW1wb3J0IHtjb2xvckZ1bmN0aW9uIGFzIENGfSBmcm9tICcuL2NvbG9yLWZ1bmN0aW9uJztcbmltcG9ydCB7dG9vbHRpcCBhcyBUVGlwfSBmcm9tICcuL3Rvb2x0aXAnO1xuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTQ0FUVEVSICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbi8qKlxuICogQ3JlYXRlcyBhIHNjYXR0ZXJcbiAqXG4gKiB7QGxpbmsgaHR0cHM6Ly9zdW1uZXVyb24uZ2l0bGFiLmlvL2Qzc20vZGVtb3Mvc2NhdHRlci9pbmRleC5odG1sIERlbW99XG4gKiBAY29uc3RydWN0b3Igc2NhdHRlclxuICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IHNlbGVjdGlvblxuICogQG5hbWVzcGFjZSBzY2F0dGVyXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IHNjYXR0ZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjYXR0ZXIgKCBzZWxlY3Rpb24gKSB7XG5cbiAgdmFyXG4gIC8qKlxuICAqIERhdGEgdG8gcGxvdC4gQXNzdW1lZCB0byBiZSBhIG9iamVjdCwgd2hlcmUgZWFjaCBrZXkgY29ycmVzcG9uZHMgdG8gYSBwb2ludFxuICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjZGF0YX0pXG4gICogQHBhcmFtIHtPYmplY3R9IFtkYXRhPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZGF0YSxcbiAgLyoqXG4gICogQW1vdW50IG9mIGhvcml6b250YWwgc3BhY2UgKGluIHBpeGVscykgYXZhaWJsZSB0byByZW5kZXIgdGhlIHNjYXR0ZXIgaW5cbiAgKiAoc2VlIHtAbGluayBzY2F0dGVyI3NwYWNlWH0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZVg9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzcGFjZVgsXG4gIC8qKlxuICAqIEFtb3VudCBvZiB2ZXJ0aWNhbCBzcGFjZSAoaW4gcGl4ZWxzKSBhdmFpYmxlIHRvIHJlbmRlciB0aGUgc2NhdHRlciBpblxuICAqIChzZWUge0BsaW5rIHNjYXR0ZXIuc3BhY2VZfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlWT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNwYWNlWSxcblxuICAvKipcbiAgKiBUaGUgc2NhbGUgZm9yIHdoaWNoIHNjYXR0ZXIgeCB2YWx1ZXMgc2hvdWxkIGJlIHRyYW5zZm9ybWVkIGJ5XG4gICogQHBhcmFtIHtkMy5zY2FsZX0gW3NjYWxlWD1kMy5zY2FsZUxpbmVhcl1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc2NhbGVYID0gZDMuc2NhbGVMaW5lYXIoKSxcbiAgLyoqXG4gICogVGhlIHBhZGRpbmcgZm9yIHRoZSBkb21haW4gb2YgdGhlIHNjYWxlWCAoc2VlIHtAbGluayBzY2F0dGVyI3NjYWxlWH0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtkb21haW5QYWRkaW5nWD0wLjVdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGRvbWFpblBhZGRpbmdYID0gMC41LFxuICAvKipcbiAgKiBUaGUgZnVuY3Rpb24gZm9yIGdldHRpbmcgdGhlIHggdmFsdWUgb2YgdGhlIGN1cnJlbnQgcG9pbnRcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbdmFsdWVFeHRyYWN0b3JYPWZ1bmN0aW9uKGQsIGkpe3JldHVybiBkYXRhW2RdWyd4J119XVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2YWx1ZUV4dHJhY3RvclggPSBmdW5jdGlvbihkLCBpKSB7cmV0dXJuIGRhdGFbZF1bJ3gnXX0sXG5cbiAgLyoqXG4gICogVGhlIHNjYWxlIGZvciB3aGljaCBzY2F0dGVyIHkgdmFsdWVzIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBieVxuICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtzY2FsZVk9ZDMuc2NhbGVMaW5lYXJdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNjYWxlWSA9IGQzLnNjYWxlTGluZWFyKCksXG4gIC8qKlxuICAqIFRoZSBwYWRkaW5nIGZvciB0aGUgZG9tYWluIG9mIHRoZSBzY2FsZVkgKHNlZSB7QGxpbmsgc2NhdHRlciNzY2FsZVl9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbZG9tYWluUGFkZGluZ1k9MC41XVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBkb21haW5QYWRkaW5nWSA9IDAuNSxcbiAgLyoqXG4gICogVGhlIGZ1bmN0aW9uIGZvciBnZXR0aW5nIHRoZSB5IHZhbHVlIG9mIHRoZSBjdXJyZW50IHBvaW50XG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3ZhbHVlRXh0cmFjdG9yWT1mdW5jdGlvbihkLCBpKXtyZXR1cm4gZGF0YVtkXVsneSddfV1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmFsdWVFeHRyYWN0b3JZID0gZnVuY3Rpb24oZCwgaSkge3JldHVybiBkYXRhW2RdWyd5J119LFxuXG5cbiAgLyoqXG4gICogVGhlIHNjYWxlIGZvciB3aGljaCBzY2F0dGVyIHIgdmFsdWVzIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBieVxuICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtzY2FsZVI9ZDMuc2NhbGVMaW5lYXJdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNjYWxlUiA9IGQzLnNjYWxlTGluZWFyKCksXG4gIC8qKlxuICAqIFRoZSBwYWRkaW5nIGZvciB0aGUgZG9tYWluIG9mIHRoZSBzY2FsZVIgKHNlZSB7QGxpbmsgc2NhdHRlciNzY2FsZVJ9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbZG9tYWluUGFkZGluZ1I9MC41XVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBkb21haW5QYWRkaW5nUiA9IDAuNSxcbiAgLyoqXG4gICogVGhlIGZ1bmN0aW9uIGZvciBnZXR0aW5nIHRoZSByIHZhbHVlIG9mIHRoZSBjdXJyZW50IHBvaW50XG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3ZhbHVlRXh0cmFjdG9yUj1mdW5jdGlvbihkLCBpKXtyZXR1cm4gMn1dXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHZhbHVlRXh0cmFjdG9yUiA9IGZ1bmN0aW9uKGQsIGkpIHtyZXR1cm4gMn0sXG4gIC8qKlxuICAqIFRoZSBtaW4gcmFkaXVzIGEgcG9pbnQgY2FuIGhhdmVcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbbWluUmFkaXVzPTJdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG1pblJhZGl1cyA9IDIsXG4gIC8qKlxuICAqIFRoZSBtaW4gcmFkaXVzIGEgcG9pbnQgY2FuIGhhdmVcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbbWF4UmFkaXVzPTEwXVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBtYXhSYWRpdXMgPSAxMCxcblxuICAvKipcbiAgKiBUaGUgc3Ryb2tlIHdpZHRoIG9mIHRoZSBwb2ludHNcbiAgKiBAcGFyYW0ge251bWJlcn0gW3BvaW50U3Ryb2tlV2lkdGg9Ml1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgcG9pbnRTdHJva2VXaWR0aCA9IDIsXG4gIC8qKlxuICAqIEluc3RhbmNlIG9mIENvbG9yRnVuY3Rpb25cbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24oKV1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgY29sb3JGdW5jdGlvbiA9IENGKCksXG4gIC8qKlxuICAqIENvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kXG4gICogQHBhcmFtIHtzdHJpbmd9IFtiYWNrZ3JvdW5kRmlsbD1cInRyYW5zcGFyZW50XCJdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJhY2tncm91bmRGaWxsID0gJ3RyYW5zcGFyZW50JyxcbiAgLyoqXG4gICogTmFtZXNwYWNlIGZvciBhbGwgaXRlbXMgbWFkZSBieSB0aGlzIGluc3RhbmNlIG9mIHNjYXR0ZXJcbiAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWVzcGFjZT1cImQzc20tc2NhdHRlclwiXVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBuYW1lc3BhY2UgPSAnZDNzbS1zY2F0dGVyJyxcbiAgLyoqXG4gICogQ2xhc3MgbmFtZSBmb3Igc2NhdHRlciBjb250YWluZXIgKDxjaXJjbGU+IGVsZW1lbnQpXG4gICogQHBhcmFtIHtzdHJpbmd9IFtvYmplY3RDbGFzcz1cInNjYXR0ZXItcG9pbnRcIl1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0Q2xhc3MgPSAnc2NhdHRlci1wb2ludCcsXG4gIC8qKlxuICAqIER1cmF0aW9uIG9mIGFsbCB0cmFuc2l0aW9ucyBvZiB0aGlzIGVsZW1lbnRcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RyYW5zaXRpb25EdXJhdGlvbj0xMDAwXVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwLFxuICAvKipcbiAgKiBFYXNpbmcgZnVuY3Rpb24gZm9yIHRyYW5zaXRpb25zXG4gICogQHBhcmFtIHtkMy5lYXNlfSBbZWFzZUZ1bmM9ZDMuZWFzZUV4cF1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwLFxuXG4gIC8vIHVzZWZ1bCB2YWx1ZXMgdG8gZXh0cmFjdCB0byBwcmV2ZW50IHJlLWNhbGN1bGF0aW9uXG4gIC8qKlxuICAqIFRoZSBrZXlzIG9mIHRoZSBwb2ludHNcbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbcG9pbnRLZXlzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgcG9pbnRLZXlzLFxuICAvKipcbiAgKiBUaGUgeCB2YWx1ZXMgb2YgdGhlIHBvaW50c1xuICAqIEBwYXJhbSB7bnVtYmVyW119IFt2YWx1ZXNYPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2Ygc2NhdHRlciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmFsdWVzWCxcbiAgLyoqXG4gICogVGhlIHkgdmFsdWVzIG9mIHRoZSBwb2ludHNcbiAgKiBAcGFyYW0ge251bWJlcltdfSBbdmFsdWVzWT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHZhbHVlc1ksXG4gIC8qKlxuICAqIFRoZSByIHZhbHVlcyBvZiB0aGUgcG9pbnRzXG4gICogQHBhcmFtIHtudW1iZXJbXX0gW3ZhbHVlc1I9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiBzY2F0dGVyI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2YWx1ZXNSLFxuXG4gIC8qKlxuICAqIEluc3RhbmNlIG9mIFRvb2x0aXBcbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbdG9vbHRpcD10b29sdGlwKCldXG4gICogQG1lbWJlcm9mIHNjYXR0ZXIjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRvb2x0aXAgPSBUVGlwKClcblxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBzZWxlY3Rpb24gaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IGQzLnNlbGVjdGlvbn1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc2VsZWN0aW9uID0gc2VsZWN0aW9uXG4gICAqL1xuICBzY2F0dGVyLnNlbGVjdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2VsZWN0aW9uID1fLCBzY2F0dGVyKSA6IHNlbGVjdGlvbn1cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZGF0YVxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI2RhdGF9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBvYmplY3R9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgc2NhdHRlci5kYXRhID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkYXRhID1fLCBzY2F0dGVyKSA6IGRhdGF9XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI3NwYWNlWH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBudW1iZXIgPiAwXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVggPSB1bmRlZmluZWRcbiAgICovXG4gIHNjYXR0ZXIuc3BhY2VYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVggPV8sIHNjYXR0ZXIpIDogc3BhY2VYfVxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBhbW91bnQgb2YgdmVydGljYWwgc3BhY2UgaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjc3BhY2VZfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlWSA9IHVuZGVmaW5lZFxuICAgKi9cbiAgc2NhdHRlci5zcGFjZVkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWSA9Xywgc2NhdHRlcikgOiBzcGFjZVl9XG5cblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgeCBzY2FsZSBmb3Igd2hpY2ggdGhlIHNjYXR0ZXIgeCB2YWx1ZXMgc2hvdWxkIGJlIHRyYW5zZm9ybWVkIGJ5XG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjc2NhbGVYfSlcbiAgICogQHBhcmFtIHtkMy5zY2FsZX0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBkMy5zY2FsZX1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc2NhbGVYID0gZDMuc2NhbGVMaW5lYXIoKVxuICAgKi9cbiAgc2NhdHRlci5zY2FsZVggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNjYWxlWCA9Xywgc2NhdHRlcikgOiBzY2FsZVh9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcGFkZGluZyBmb3IgdGhlIGRvbWFpbiBvZiB0aGUgeCBzY2FsZVxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI2RvbWFpblBhZGRpbmdYfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBkb21haW5QYWRkaW5nWCA9IDAuNVxuICAgKi9cbiAgc2NhdHRlci5kb21haW5QYWRkaW5nWCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluUGFkZGluZ1ggPV8sIHNjYXR0ZXIpIDogZG9tYWluUGFkZGluZ1h9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdmFsdWVFeHRyYWN0b3JYXG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjdmFsdWVFeHRyYWN0b3JYfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdmFsdWVFeHRyYWN0b3JYID0gZnVuY3Rpb24oa2V5LCBpbmRleCkgeyByZXR1cm4gZGF0YVtrZXldWyd4J10gfVxuICAgKi9cbiAgc2NhdHRlci52YWx1ZUV4dHJhY3RvclggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZhbHVlRXh0cmFjdG9yWCA9Xywgc2NhdHRlcikgOiB2YWx1ZUV4dHJhY3Rvclh9XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHkgc2NhbGUgZm9yIHdoaWNoIHRoZSBzY2F0dGVyIHkgdmFsdWVzIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBieVxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI3NjYWxlWX0pXG4gICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgZDMuc2NhbGV9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNjYWxlWSA9IGQzLnNjYWxlTGluZWFyKClcbiAgICovXG4gIHNjYXR0ZXIuc2NhbGVZID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzY2FsZVkgPV8sIHNjYXR0ZXIpIDogc2NhbGVZfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHBhZGRpbmcgZm9yIHRoZSBkb21haW4gb2YgdGhlIHkgc2NhbGVcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciNkb21haW5QYWRkaW5nWX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZG9tYWluUGFkZGluZ1kgPSAwLjVcbiAgICovXG4gIHNjYXR0ZXIuZG9tYWluUGFkZGluZ1kgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRvbWFpblBhZGRpbmdZID1fLCBzY2F0dGVyKSA6IGRvbWFpblBhZGRpbmdZfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHZhbHVlRXh0cmFjdG9yWVxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI3ZhbHVlRXh0cmFjdG9yWX0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZhbHVlRXh0cmFjdG9yWSA9IGZ1bmN0aW9uKGtleSwgaW5kZXgpIHsgcmV0dXJuIGRhdGFba2V5XVsneSddIH1cbiAgICovXG4gIHNjYXR0ZXIudmFsdWVFeHRyYWN0b3JZID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZUV4dHJhY3RvclkgPV8sIHNjYXR0ZXIpIDogdmFsdWVFeHRyYWN0b3JZfVxuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSByIHNjYWxlIGZvciB3aGljaCB0aGUgc2NhdHRlciByIHZhbHVlcyBzaG91bGQgYmUgdHJhbnNmb3JtZWQgYnlcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciNzY2FsZVJ9KVxuICAgKiBAcGFyYW0ge2QzLnNjYWxlfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IGQzLnNjYWxlfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzY2FsZVIgPSBkMy5zY2FsZUxpbmVhcigpXG4gICAqL1xuICBzY2F0dGVyLnNjYWxlUiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGVSID1fLCBzY2F0dGVyKSA6IHNjYWxlUn1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBwYWRkaW5nIGZvciB0aGUgZG9tYWluIG9mIHRoZSByIHNjYWxlXG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjZG9tYWluUGFkZGluZ1J9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGRvbWFpblBhZGRpbmdSID0gMC41XG4gICAqL1xuICBzY2F0dGVyLmRvbWFpblBhZGRpbmdSID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkb21haW5QYWRkaW5nUiA9Xywgc2NhdHRlcikgOiBkb21haW5QYWRkaW5nUn1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB2YWx1ZUV4dHJhY3RvclJcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciN2YWx1ZUV4dHJhY3RvclJ9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB2YWx1ZUV4dHJhY3RvclIgPSBmdW5jdGlvbihrZXksIGluZGV4KSB7IHJldHVybiBkYXRhW2tleV1bJ3InXSB9XG4gICAqL1xuICBzY2F0dGVyLnZhbHVlRXh0cmFjdG9yUiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodmFsdWVFeHRyYWN0b3JSID1fLCBzY2F0dGVyKSA6IHZhbHVlRXh0cmFjdG9yUn1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBtaW5SYWRpdXNcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciNtaW5SYWRpdXN9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1pblJhZGl1cyA9IDJcbiAgICovXG4gIHNjYXR0ZXIubWluUmFkaXVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChtaW5SYWRpdXMgPV8sIHNjYXR0ZXIpIDogbWluUmFkaXVzfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1heFJhZGl1c1xuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI21heFJhZGl1c30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbWF4UmFkaXVzID0gMTBcbiAgICovXG4gIHNjYXR0ZXIubWF4UmFkaXVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChtYXhSYWRpdXMgPV8sIHNjYXR0ZXIpIDogbWF4UmFkaXVzfVxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcG9pbnRTdHJva2VXaWR0aFxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI3BvaW50U3Ryb2tlV2lkdGh9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHBvaW50U3Ryb2tlV2lkdGggPSAyXG4gICAqL1xuICBzY2F0dGVyLnBvaW50U3Ryb2tlV2lkdGggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBvaW50U3Ryb2tlV2lkdGggPV8sIHNjYXR0ZXIpIDogcG9pbnRTdHJva2VXaWR0aH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBjb2xvckZ1bmN0aW9uXG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjY29sb3JGdW5jdGlvbn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24oKVxuICAgKi9cbiAgc2NhdHRlci5jb2xvckZ1bmN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjb2xvckZ1bmN0aW9uID1fLCBzY2F0dGVyKSA6IGNvbG9yRnVuY3Rpb259XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYmFja2dyb3VuZEZpbGxcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciNiYWNrZ3JvdW5kRmlsbH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYmFja2dyb3VuZEZpbGwgPSAndHJhbnNwYXJlbnQnXG4gICAqL1xuICBzY2F0dGVyLmJhY2tncm91bmRGaWxsID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChiYWNrZ3JvdW5kRmlsbCA9Xywgc2NhdHRlcikgOiBiYWNrZ3JvdW5kRmlsbH1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBuYW1lc3BhY2VcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciNuYW1lc3BhY2V9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG5hbWVzcGFjZSA9ICdkM3NtLXNjYXR0ZXInXG4gICAqL1xuICBzY2F0dGVyLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID1fLCBzY2F0dGVyKSA6IG5hbWVzcGFjZX1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RDbGFzc1xuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI29iamVjdENsYXNzfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RDbGFzcyA9ICd0aWNrLWdyb3VwJ1xuICAgKi9cbiAgc2NhdHRlci5vYmplY3RDbGFzcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q2xhc3MgPV8sIHNjYXR0ZXIpIDogb2JqZWN0Q2xhc3N9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdHJhbnNpdGlvbkR1cmF0aW9uXG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjdHJhbnNpdGlvbkR1cmF0aW9ufSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwXG4gICAqL1xuICBzY2F0dGVyLnRyYW5zaXRpb25EdXJhdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodHJhbnNpdGlvbkR1cmF0aW9uID1fLCBzY2F0dGVyKSA6IHRyYW5zaXRpb25EdXJhdGlvbn1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBlYXNlRnVuY1xuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI2Vhc2VGdW5jfSlcbiAgICogQHBhcmFtIHtkMy5lYXNlfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IGQzLmVhc2V9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGVhc2VGdW5jID0gZDMuZWFzZUV4cFxuICAgKi9cbiAgc2NhdHRlci5lYXNlRnVuYyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZWFzZUZ1bmMgPV8sIHNjYXR0ZXIpIDogZWFzZUZ1bmN9XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBwb2ludEtleXNcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciNwb2ludEtleXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBwb2ludEtleXMgPSB1bmRlZmluZWRcbiAgICovXG4gIHNjYXR0ZXIucG9pbnRLZXlzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwb2ludEtleXMgPV8sIHNjYXR0ZXIpIDogcG9pbnRLZXlzfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHZhbHVlc1hcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciN2YWx1ZXNYfSlcbiAgICogQHBhcmFtIHtudW1iZXJbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge3NjYXR0ZXIgfCBudW1iZXJbXX1cbiAgICogQG1lbWJlcm9mIHNjYXR0ZXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdmFsdWVzWCA9IHVuZGVmaW5lZFxuICAgKi9cbiAgc2NhdHRlci52YWx1ZXNYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZXNYID1fLCBzY2F0dGVyKSA6IHZhbHVlc1h9XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdmFsdWVzWVxuICAgKiAoc2VlIHtAbGluayBzY2F0dGVyI3ZhbHVlc1l9KVxuICAgKiBAcGFyYW0ge251bWJlcltdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IG51bWJlcltdfVxuICAgKiBAbWVtYmVyb2Ygc2NhdHRlclxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB2YWx1ZXNZID0gdW5kZWZpbmVkXG4gICAqL1xuICBzY2F0dGVyLnZhbHVlc1kgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZhbHVlc1kgPV8sIHNjYXR0ZXIpIDogdmFsdWVzWX1cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB2YWx1ZXNSXG4gICAqIChzZWUge0BsaW5rIHNjYXR0ZXIjdmFsdWVzUn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyW119IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtzY2F0dGVyIHwgbnVtYmVyW119XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZhbHVlc1IgPSB1bmRlZmluZWRcbiAgICovXG4gIHNjYXR0ZXIudmFsdWVzUiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodmFsdWVzUiA9Xywgc2NhdHRlcikgOiB2YWx1ZXNSfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHRvb2x0aXBcbiAgICogKHNlZSB7QGxpbmsgc2NhdHRlciN0b29sdGlwfSlcbiAgICogQHBhcmFtIHt0b29sdGlwfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7c2NhdHRlciB8IHRvb2x0aXB9XG4gICAqIEBtZW1iZXJvZiBzY2F0dGVyXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHRvb2x0aXAgPSB0b29sdGlwKClcbiAgICovXG5cbiAgc2NhdHRlci50b29sdGlwID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0b29sdGlwID1fLCBzY2F0dGVyKSA6IHRvb2x0aXB9XG5cblxuICBmdW5jdGlvbiBzY2F0dGVyKCkge1xuICAgIC8vIGJhY2tncm91bmQgY2xpcGluZyByZWN0YW5nbGVcbiAgICB2YXIgYmdjcFJlY3QgPSB7eDowLCB5OjAsIHdpZHRoOiBzcGFjZVgsIGhlaWdodDpzcGFjZVl9XG4gICAgdmFyIGNvbnRhaW5lciA9IHNldHVwQ29udGFpbmVyKCBzZWxlY3Rpb24sIG5hbWVzcGFjZSwgYmdjcFJlY3QsIGJhY2tncm91bmRGaWxsICk7XG5cblxuICAgIHBvaW50S2V5cyA9IGQzLmtleXMoZGF0YSlcbiAgICB2YWx1ZXNYID0gcG9pbnRLZXlzLm1hcCh2YWx1ZUV4dHJhY3RvclgpXG4gICAgdmFsdWVzWSA9IHBvaW50S2V5cy5tYXAodmFsdWVFeHRyYWN0b3JZKVxuICAgIHZhbHVlc1IgPSBwb2ludEtleXMubWFwKHZhbHVlRXh0cmFjdG9yUilcblxuICAgIHZhciBudW1iZXJPZk9iamVjdHMgPSBwb2ludEtleXMubGVuZ3RoXG4gICAgdmFyIGV4dGVudFggPSBbTWF0aC5taW4oLi4udmFsdWVzWCkgLSBkb21haW5QYWRkaW5nWCwgTWF0aC5tYXgoLi4udmFsdWVzWCkgKyBkb21haW5QYWRkaW5nWF1cbiAgICB2YXIgZXh0ZW50WSA9IFtNYXRoLm1pbiguLi52YWx1ZXNZKSAtIGRvbWFpblBhZGRpbmdZLCBNYXRoLm1heCguLi52YWx1ZXNZKSArIGRvbWFpblBhZGRpbmdZXVxuICAgIHZhciBleHRlbnRSID0gW01hdGgubWluKC4uLnZhbHVlc1IpIC0gZG9tYWluUGFkZGluZ1IsIE1hdGgubWF4KC4uLnZhbHVlc1IpICsgZG9tYWluUGFkZGluZ1JdXG5cbiAgICBzY2FsZVguZG9tYWluKGV4dGVudFgpLnJhbmdlKFswLCBzcGFjZVhdKVxuICAgIHNjYWxlWS5kb21haW4oZXh0ZW50WSkucmFuZ2UoW3NwYWNlWSwgMF0pXG4gICAgc2NhbGVSLmRvbWFpbihleHRlbnRSKS5yYW5nZShbbWluUmFkaXVzLCBtYXhSYWRpdXNdKVxuXG4gICAgdmFyIHBvaW50cyA9IGNvbnRhaW5lci5zZWxlY3RBbGwoJy4nK29iamVjdENsYXNzKVxuICAgIHBvaW50cyA9IHBvaW50cy5kYXRhKHBvaW50S2V5cylcbiAgICB2YXIgcEVudGVyID0gcG9pbnRzLmVudGVyKCkuYXBwZW5kKCdjaXJjbGUnKVxuICAgIC5hdHRyKCdjbGFzcycsIG9iamVjdENsYXNzKVxuICAgIC5hdHRyKCdjeCcsIDApLmF0dHIoJ2N5Jywgc3BhY2VZKS5hdHRyKCdyJywgMClcblxuICAgIHZhciBwRXhpdCA9IHBvaW50cy5leGl0KClcblxuICAgIHBvaW50cyA9IHBvaW50cy5tZXJnZShwRW50ZXIpXG5cbiAgICBwb2ludHMuZWFjaChmdW5jdGlvbihrZXksIGkpe1xuICAgICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcyksXG4gICAgICBjdXJyZW50RGF0YSA9IGRhdGFba2V5XSxcbiAgICAgIHggPSB2YWx1ZXNYW2ldLFxuICAgICAgeSA9IHZhbHVlc1lbaV0sXG4gICAgICByID0gdmFsdWVzUltpXSxcbiAgICAgIGZpbGxDb2xvciA9IGNvbG9yRnVuY3Rpb24oa2V5LCBjdXJyZW50RGF0YSwgaSwgJ2ZpbGwnKSxcbiAgICAgIHN0cm9rZUNvbG9yID0gY29sb3JGdW5jdGlvbihrZXksIGN1cnJlbnREYXRhLCBpLCAnc3Ryb2tlJylcblxuICAgICAgdC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgLmF0dHIoJ2N4Jywgc2NhbGVYKHgpKVxuICAgICAgLmF0dHIoJ2N5Jywgc2NhbGVZKHkpKVxuICAgICAgLmF0dHIoJ3InLCBzY2FsZVIocikpXG4gICAgICAuYXR0cignZmlsbCcsIGZpbGxDb2xvcilcbiAgICAgIC5hdHRyKCdzdHJva2UnLCBzdHJva2VDb2xvcilcbiAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCBwb2ludFN0cm9rZVdpZHRoKVxuXG5cblxuICAgICAgdC5vbignbW91c2VvdmVyJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIHBvaW50cy5zdHlsZSgnb3BhY2l0eScsIDAuMilcbiAgICAgICAgdC5zdHlsZSgnb3BhY2l0eScsIDEpXG4gICAgICAgIHQudHJhbnNpdGlvbigpLmR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbi8yKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgcG9pbnRTdHJva2VXaWR0aCoyKVxuICAgICAgICAuYXR0cigncicsIHNjYWxlUihyKSAqIDEuNSlcblxuICAgICAgfSlcbiAgICAgIHQubm9kZSgpLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3V0JywgZnVuY3Rpb24oKXtcbiAgICAgICAgY29udGFpbmVyLnNlbGVjdEFsbCgnLicrb2JqZWN0Q2xhc3MpLnN0eWxlKCdvcGFjaXR5JywgMSlcbiAgICAgICAgdC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uLzIpLmVhc2UoZWFzZUZ1bmMpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCBwb2ludFN0cm9rZVdpZHRoKVxuICAgICAgICAuYXR0cigncicsIHNjYWxlUihyKSlcblxuICAgICAgfSlcblxuICAgIH0pXG5cblxuXG4gICAgcEV4aXQudHJhbnNpdGlvbigpLmR1cmF0aW9uKHRyYW5zaXRpb25EdXJhdGlvbikuZWFzZShlYXNlRnVuYylcbiAgICAuYXR0cignY3gnLCAwKS5hdHRyKCdjeScsIHNwYWNlWSkuYXR0cigncicsIDApXG4gICAgLnJlbW92ZSgpXG5cbiAgICB0b29sdGlwLnNlbGVjdGlvbihwb2ludHMpXG4gICAgLmRhdGEoZGF0YSlcblxuICAgIHRvb2x0aXAoKVxuICB9XG5cblxuICByZXR1cm4gc2NhdHRlclxufVxuIiwiaW1wb3J0IHtoeXBlbmF0ZSwgc2FmZVNlbGVjdCwgZ2V0VHJhbnNsYXRpb259IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQge2xvZywgd2FybiwgZXJyb3IsIGluZm99IGZyb20gJy4vdXRpbHMnO1xuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcblxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUExPVFpPT00gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuLyoqXG4gKiBDcmVhdGVzIGFuIHBsb3Rab29tIGluc3RhbmNlLCB3aGljaCBjYW4gaGFuZGxlIGRyYWcgYW5kIHNjcm9sbCBldmVudHNcbiAqIEBjb25zdHJ1Y3RvciBwbG90Wm9vbVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2hhcnQgYSBmdW5jdGlvbiBpbnN0YW5jZSBvZiBvbmUgb2YgdGhlIGQzc20gcGxvdHMgKGUuZy4gYmFyLCBib3h3aGlza2VyLCBidWJibGVIZWF0bWFwLCB2aW9saW4sIGV0YylcbiAqIEBwYXJhbSB7YXhpc30gIHhBeGlzIHRoZSBheGlzIGluc3RhbmNlIHJlc3BvbnNpYmxlIGZvciB0aGUgeCBheGlzXG4gKiBAcGFyYW0ge2F4aXN9IHlBeGlzIHRoZSBheGlzIGluc3RhbmNlIHJlc3BvbnNpYmxlIGZvciB0aGUgeSBheGlzXG4gKiBAbmFtZXNwYWNlIHBsb3Rab29tXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IHpvb21cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBsb3Rab29tKCBjaGFydCwgeEF4aXMsIHlBeGlzICkge1xuICB2YXJcbiAgLyoqXG4gICogVGhlIGV2ZW50IG9uIHdoaWNoIHRvIGZpcmVcbiAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSNldmVudFR5cGV9KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFR5cGUgd2hpY2ggZXZlbnQgaXQgc2hvdWxkIGhhbmRsZS4gQ3VycmVudGx5IHN1cHBvcnRzIHNjcm9sbCBhbmQgd2hlZWxcbiAgKiBAbWVtYmVyb2YgcGxvdFpvb20jXG4gICogQHByb3BlcnR5XG4gICovXG4gIGV2ZW50VHlwZSxcbiAgLyoqXG4gICogQSBzY2FsaW5nIGZhY3RvciBmb3IgdGhlIHdoZWVsIFwic3BlZWRcIlxuICAqIChzZWUge0BsaW5rIHBsb3Rab29tI3doZWVsU3BlZWR9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbd2hlZWxTcGVlZD0yMF0gc2NhbGVzIHRoZSB3aGVlbCB0cmFuc2xhdGlvbiBieSB3aGVlbFNwZWVkXG4gICogQG1lbWJlcm9mIHBsb3Rab29tI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB3aGVlbFNwZWVkID0gMjAsXG4gIC8qKlxuICAqIFRoZSBvcmllbnRhdGlvbiBpbiB3aGljaCB0byBhbGxvdyBzY3JvbGxpbmc6ICdob3Jpem9udGFsJywgJ3ZlcnRpY2FsJywgb3IgJzJEJ1xuICAqIChzZWUge0BsaW5rIHBsb3Rab29tI29yaWVudH0pXG4gICogQHBhcmFtIHtzdHJpbmd9IFtvcmllbnQ9Y2hhcnQub3JpZW50KCkgfHwgJ2hvcml6b250YWwnXVxuICAqIEBtZW1iZXJvZiBwbG90Wm9vbSNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb3JpZW50ID0gKGNoYXJ0Lm9yaWVudCA9PSB1bmRlZmluZWQpID8gJ2hvcml6b250YWwnIDogY2hhcnQub3JpZW50KCksXG4gIC8qKlxuICAqIFRoZSBtYXggZGlzdGFuY2UgYWxsb3dlZCB0byBzY3JvbGwgaW4gdGhlIHggZGlyZWN0aW9uXG4gICogKHNlZSB7QGxpbmsgcGxvdFpvb20jeExvY2t9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbeExvY2s9Y2hhcnQuc3BhY2VYKCldIGlkZWFsbHkgY2hhcnQub3ZlcmZsb3dRKCkgPT0gdHJ1ZSBhbmQgdGhpcyB2YWx1ZSBpcyB0aGVcbiAgKiBib3VuZGluZyByZWN0IGFjcm9zcyBhbGwgZWxlbWVudHMgaW4gdGhlIGNoYXJ0ICBtaW51cyB0aGUgc3BhY2UgaW4gd2hpY2ggdG8gc2hvdy5cbiAgKiBAbWVtYmVyb2YgcGxvdFpvb20jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHhMb2NrPWNoYXJ0LnNwYWNlWCgpLFxuICAvKipcbiAgKiBUaGUgbWF4IGRpc3RhbmNlIGFsbG93ZWQgdG8gc2Nyb2xsIGluIHRoZSB5IGRpcmVjdGlvblxuICAqIChzZWUge0BsaW5rIHBsb3Rab29tI3lMb2NrfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3lMb2NrPWNoYXJ0LnNwYWNlWSgpXSBpZGVhbGx5IGNoYXJ0Lm92ZXJmbG93USgpID09IHRydWUgYW5kIHRoaXMgdmFsdWUgaXMgdGhlXG4gICogYm91bmRpbmcgcmVjdCBhY3Jvc3MgYWxsIGVsZW1lbnRzIGluIHRoZSBjaGFydCAgbWludXMgdGhlIHNwYWNlIGluIHdoaWNoIHRvIHNob3cuXG4gICogQG1lbWJlcm9mIHBsb3Rab29tI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB5TG9jaz1jaGFydC5zcGFjZVkoKSxcblxuICBjaGFydFNlbCA9IGNoYXJ0LnNlbGVjdGlvbigpLFxuICB4QXhpc1NlbCA9IHhBeGlzLnNlbGVjdGlvbigpLFxuICB5QXhpc1NlbCA9IHlBeGlzLnNlbGVjdGlvbigpLFxuICBzdmcgPSBkMy5zZWxlY3QoY2hhcnRTZWwudGhpc1NWRygpKVxuXG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZXZlbnQgdHlwZSBpbiB3aGljaCB0byByZXNwb25kXG4gICAqIChzZWUge0BsaW5rIHBsb3Rab29tI2V2ZW50VHlwZX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXSBzaG91bGQgYmUgJ2RyYWcnIG9yICd3aGVlbCdcbiAgICogQHJldHVybnMge3pvb20gfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBwbG90Wm9vbVxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBwbG90Wm9vbT11bmRlZmluZWRcbiAgICovXG4gIHpvb20uZXZlbnRUeXBlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChldmVudFR5cGUgPSBfLCB6b29tKSA6IGV2ZW50VHlwZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgd2hlZWwgc3BlZWQgaW4gd2hpY2ggdG8gc2NhbGUgdGhlIHdoZWVsIHNjcm9sbCB0cmFuc2Zvcm1cbiAgICogKHNlZSB7QGxpbmsgcGxvdFpvb20jd2hlZWxTcGVlZH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7em9vbSB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHBsb3Rab29tXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHdoZWVsU3BlZWQ9MjBcbiAgICovXG4gIHpvb20ud2hlZWxTcGVlZCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAod2hlZWxTcGVlZCA9IF8sIHpvb20pIDogd2hlZWxTcGVlZDsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgb3JpZW50YXRpb24gaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIHBsb3Rab29tI29yaWVudH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXSBzaG91bGQgYmUgaG9yaXpvbnRhbCwgdmVydGljYWwsIG9yIDJEXG4gICAqIEByZXR1cm5zIHt6b29tIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgcGxvdFpvb21cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3JpZW50PWNoYXJ0Lm9yaWVudCgpIHx8ICdob3Jpem9udGFsJ1xuICAgKi9cbiAgem9vbS5vcmllbnQgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9yaWVudCA9IF8sIHpvb20pIDogb3JpZW50OyB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIG1heCBkaXN0YW5jZSBpbiB3aGljaCB0byBzY3JvbGwgWFxuICAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN4TG9ja30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBwb3NpdGl2ZSB2YWx1ZVxuICAgKiBAcmV0dXJucyB7em9vbSB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHBsb3Rab29tXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHhMb2NrPWNoYXJ0LnNwYWNlWCgpXG4gICAqL1xuICB6b29tLnhMb2NrID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4TG9jayA9IF8sIHpvb20pIDogeExvY2s7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIG1heCBkaXN0YW5jZSBpbiB3aGljaCB0byBzY3JvbGwgWVxuICAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN5TG9ja30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSAgc2hvdWxkIGJlIGEgcG9zaXRpdmUgdmFsdWVcbiAgICogQHJldHVybnMge3pvb20gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBwbG90Wm9vbVxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5TG9jaz1jaGFydC5zcGFjZVkoKVxuICAgKi9cbiAgem9vbS55TG9jayA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeUxvY2sgPSBfLCB6b29tKSA6IHlMb2NrOyB9O1xuXG5cbiAgZnVuY3Rpb24gc2V0TG9ja3MoKSB7XG4gICAgdmFyIGNoYXJ0T2JqU2VsID0gY2hhcnRTZWwuc2VsZWN0KCcuJytoeXBlbmF0ZShjaGFydC5uYW1lc3BhY2UoKSwnb2JqZWN0LWNvbnRhaW5lcicpKVxuICAgIHZhciBjaGFydE9ialRyYW5zID0gZ2V0VHJhbnNsYXRpb24oY2hhcnRPYmpTZWwuYXR0cigndHJhbnNmb3JtJykpXG4gICAgdmFyIGNvcyA9IGNoYXJ0T2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoMCwwKScpXG4gICAgeExvY2sgPSBjaGFydFNlbC5ub2RlKCkuZ2V0QkJveCgpLndpZHRoIC0gY2hhcnQuc3BhY2VYKCkgKiAuOVxuICAgIHlMb2NrID0gY2hhcnRTZWwubm9kZSgpLmdldEJCb3goKS5oZWlnaHQgLSBjaGFydC5zcGFjZVkoKSAqIC45XG4gICAgY29zLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJytjaGFydE9ialRyYW5zWzBdKycsJytjaGFydE9ialRyYW5zWzFdKycpJylcbiAgICBsb2coJ3Bsb3Rab29tJywgJ3NldExvY2tzJywge3hMb2NrOnhMb2NrLCB5TG9jazp5TG9ja30pXG4gIH1cblxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSB4IGFuZCB5IGxvY2tzIChob3cgZmFyIG9uZSBjYW4gc2Nyb2xsKVxuICAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN4TG9ja30gYW5kIHtAbGluayBwbG90Wm9vbSN5TG9ja30pXG4gICAqIEBmdW5jdGlvbiBwbG90Wm9vbS5zZXRMb2Nrc1xuICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICAgKiBAbWVtYmVyb2YgcGxvdFpvb21cbiAgICogQHByb3BlcnR5XG4gICAqL1xuICB6b29tLnNldExvY2tzID0gc2V0TG9ja3NcblxuICBmdW5jdGlvbiB6b29tKCkge1xuICAgIHNldExvY2tzKClcblxuICAgIHZhciBob3Jpem9udGFsUSwgdmVydGljYWxRXG4gICAgaWYgKG9yaWVudCA9PSAnMkQnKSB7aG9yaXpvbnRhbFEgPSB0cnVlOyB2ZXJ0aWNhbFEgPSB0cnVlO31cbiAgICBpZiAob3JpZW50ID09ICdob3Jpem9udGFsJykge2hvcml6b250YWxRID0gdHJ1ZTsgdmVydGljYWxRID0gZmFsc2U7fVxuICAgIGlmIChvcmllbnQgPT0gJ3ZlcnRpY2FsJykge3ZlcnRpY2FsUSA9IHRydWU7IGhvcml6b250YWxRID0gZmFsc2U7fVxuXG4gICAgLy8gY2FwdHVyZSB0cmFuc2Zvcm0gZXZlbnRcbiAgICB2YXIgdHJhbnNmb3JtID0gZDMuZXZlbnQudHJhbnNmb3JtXG5cbiAgICB2YXIgY2hhcnRCb3ggPSBjaGFydFNlbC5ub2RlKCkuZ2V0QkJveCgpXG4gICAgdmFyIHhBeGlzQm94ID0geEF4aXNTZWwubm9kZSgpLmdldEJCb3goKVxuICAgIHZhciB5QXhpc0JveCA9IHhBeGlzU2VsLm5vZGUoKS5nZXRCQm94KClcblxuICAgIHZhciBjaGFydFdpZHRoID0gY2hhcnRCb3gud2lkdGggLSBjaGFydEJveC54XG4gICAgdmFyIGNoYXJ0SGVpZ2h0ID0gY2hhcnRCb3guaGVpZ2h0IC0gY2hhcnRCb3gueVxuICAgIHZhciB4QXhpc1dpZHRoID0geEF4aXNCb3gud2lkdGgvLyAtIHhBeGlzQm94LnhcbiAgICB2YXIgeEF4aXNIZWlnaHQgPSB4QXhpc0JveC5oZWlnaHQvLyAtIHhBeGlzQm94LnlcbiAgICB2YXIgeUF4aXNXaWR0aCA9IHlBeGlzQm94LndpZHRoLy8gLSB5QXhpc0JveC54XG4gICAgdmFyIHlBeGlzSGVpZ2h0ID0geUF4aXNCb3guaGVpZ2h0Ly8gLXlBeGlzQm94LnlcblxuICAgIC8vIGVuYWJsZSB3aGVlbCBldmVudFxuICAgIGlmIChldmVudFR5cGUgPT0gXCJ3aGVlbFwiKSB7XG4gICAgICB2YXIgZSA9IGQzLmV2ZW50XG4gICAgICAvLyBwcmV2ZW50IHBhZ2Ugc2Nyb2xsaW5nXG4gICAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICAgIC8vIGV2ZW50IGRlbHRhIGlzIHZlcnkgdmVyeSBzbG93LCBzbyBzcGVlZCBpdCB1cCB3aXRoIHdoZWVsIHNwZWVkXG4gICAgICB2YXIgdyA9IGQzLmV2ZW50LmRlbHRhWSAqIHdoZWVsU3BlZWRcbiAgICAgIHZhciBzaGlmdFEgPSBkMy5ldmVudC5zaGlmdEtleVxuXG4gICAgICAvLyBkMyBoYXMgbm8gd2F5IHRvIG1ha2UgY3VzdG9tIHRyYW5zZm9ybSwgc28gbWFrZSBhbiBvYmplY3QgYW5kIGFkZFxuICAgICAgLy8gdGhlIG5lY2Vzc2FyeSBmdW5jdGlvbnMgdG8gbWFrZSB3aGVlbCBldmVudCBjb21wYXRpYmxlIHdpdGggZHJhZyBldmVudHNcbiAgICAgIGlmIChvcmllbnQgPT0gJzJEJykge1xuICAgICAgICB0cmFuc2Zvcm0gPSBzaGlmdFEgPyB7azogMSwgeDogdywgeTogMH0gOiB7azogMSwgeDogMCwgeTogd31cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyYW5zZm9ybSA9IGhvcml6b250YWxRID8ge2s6IDEsIHg6IHcsIHk6IDB9IDoge2s6IDEsIHg6IDAsIHk6IHd9XG4gICAgICB9XG4gICAgICAvLyB0aGUgKiAtMSBpbnZlcnRzIHRoZSBkaXJlY3Rpb25cbiAgICAgIHRyYW5zZm9ybS5hcHBseVggPSBmdW5jdGlvbih4KSB7IHJldHVybiB4ICogdGhpcy5rICsgdGhpcy54ICogLTE7IH1cbiAgICAgIHRyYW5zZm9ybS5hcHBseVkgPSAgZnVuY3Rpb24oeSkgeyByZXR1cm4geSAqIHRoaXMuayArIHRoaXMueSAqIC0xOyB9XG4gICAgfVxuXG5cblxuICAgIHZhciBjaGFydE9ialNlbCA9IGNoYXJ0U2VsLnNlbGVjdCgnLicraHlwZW5hdGUoY2hhcnQubmFtZXNwYWNlKCksJ29iamVjdC1jb250YWluZXInKSlcbiAgICB2YXIgeEF4aXNPYmpTZWwgPSB4QXhpc1NlbC5zZWxlY3QoJy4nK2h5cGVuYXRlKHhBeGlzLm5hbWVzcGFjZSgpLCdvYmplY3QtY29udGFpbmVyJykpXG4gICAgdmFyIHlBeGlzT2JqU2VsID0geUF4aXNTZWwuc2VsZWN0KCcuJytoeXBlbmF0ZSh5QXhpcy5uYW1lc3BhY2UoKSwnb2JqZWN0LWNvbnRhaW5lcicpKVxuXG4gICAgLy8geExvY2sgPSBjaGFydFNlbC5ub2RlKCkuZ2V0QkJveCgpLndpZHRoIC0gY2hhcnQuc3BhY2VYKCkgLSBjaGFydFNlbC5ub2RlKCkuZ2V0QkJveCgpLnhcbiAgICAvLyB5TG9jayA9IGNoYXJ0U2VsLm5vZGUoKS5nZXRCQm94KCkuaGVpZ2h0IC0gY2hhcnQuc3BhY2VZKClcbiAgICAvLyBjb25zb2xlLnRhYmxlKHsneExvY2snOnhMb2NrLCBcInlMb2NrXCI6eUxvY2t9KVxuICAgIC8vIGJobS5zZWxlY3Rpb24oKS5ub2RlKCkuZ2V0QkJveCgpLndpZHRoIC0gYmhtLnNwYWNlWCgpXG5cblxuICAgIHZhciBjaGFydE9ialRyYW5zID0gZ2V0VHJhbnNsYXRpb24oY2hhcnRPYmpTZWwuYXR0cigndHJhbnNmb3JtJykpXG4gICAgdmFyIHhBeGlzT2JqVHJhbnMgPSBnZXRUcmFuc2xhdGlvbih4QXhpc09ialNlbC5hdHRyKCd0cmFuc2Zvcm0nKSlcbiAgICB2YXIgeUF4aXNPYmpUcmFucyA9IGdldFRyYW5zbGF0aW9uKHlBeGlzT2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScpKVxuXG5cbiAgICB2YXIgeCA9IGhvcml6b250YWxRID8gdHJhbnNmb3JtLmFwcGx5WChjaGFydE9ialRyYW5zWzBdKSA6IDBcbiAgICBpZiAoaG9yaXpvbnRhbFEpIHt4ID0geCA8IC14TG9jayA/ICh0cmFuc2Zvcm0ueCA9IDAsIC14TG9jaykgOiAodHJhbnNmb3JtLnggPSAwLCBNYXRoLm1pbih4LCAwKSkgfVxuXG4gICAgdmFyIHkgPSB2ZXJ0aWNhbFEgPyB0cmFuc2Zvcm0uYXBwbHlZKGNoYXJ0T2JqVHJhbnNbMV0pIDogMFxuICAgIGlmICh2ZXJ0aWNhbFEpIHt5ID0geSA8IC15TG9jayA/ICh0cmFuc2Zvcm0ueSA9IDAsIC15TG9jayk6ICh0cmFuc2Zvcm0ueSA9IDAsIE1hdGgubWluKHksIDApKX1cblxuICAgIGNoYXJ0T2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJylcbiAgICBpZiAoaG9yaXpvbnRhbFEpIHsgeEF4aXNPYmpTZWwuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnK3grJywnKzArJyknKSB9XG4gICAgaWYgKHZlcnRpY2FsUSkgeyB5QXhpc09ialNlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcrMCsnLCcreSsnKScpIH1cblxuICAgIC8vIHZhciBsYXNzbyA9IHN2Zy5zZWxlY3QoXCIubGFzc28tY29udGFpbmVyXCIpXG4gICAgLy8gaWYgKCFsYXNzby5lbXB0eSgpKSB7XG4gICAgLy8gICBsYXNzby5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcreCsnLCcreSsnKScpXG4gICAgLy8gfVxuXG4gIH1cblxuICB6b29tLnJlc2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGhvcml6b250YWxRLCB2ZXJ0aWNhbFFcbiAgICBpZiAob3JpZW50ID09ICcyRCcpIHtob3Jpem9udGFsUSA9IHRydWU7IHZlcnRpY2FsUSA9IHRydWU7fVxuICAgIGlmIChvcmllbnQgPT0gJ2hvcml6b250YWwnKSB7aG9yaXpvbnRhbFEgPSB0cnVlOyB2ZXJ0aWNhbFEgPSBmYWxzZTt9XG4gICAgaWYgKG9yaWVudCA9PSAndmVydGljYWwnKSB7dmVydGljYWxRID0gdHJ1ZTsgaG9yaXpvbnRhbFEgPSBmYWxzZTt9XG5cbiAgICB2YXIgY2hhcnRPYmpTZWwgPSBjaGFydFNlbC5zZWxlY3QoJy4nK2h5cGVuYXRlKGNoYXJ0Lm5hbWVzcGFjZSgpLCdvYmplY3QtY29udGFpbmVyJykpXG4gICAgdmFyIHhBeGlzT2JqU2VsID0geEF4aXNTZWwuc2VsZWN0KCcuJytoeXBlbmF0ZSh4QXhpcy5uYW1lc3BhY2UoKSwnb2JqZWN0LWNvbnRhaW5lcicpKVxuICAgIHZhciB5QXhpc09ialNlbCA9IHlBeGlzU2VsLnNlbGVjdCgnLicraHlwZW5hdGUoeUF4aXMubmFtZXNwYWNlKCksJ29iamVjdC1jb250YWluZXInKSlcbiAgICBjaGFydE9ialNlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcrMCsnLCcrMCsnKScpXG4gICAgeEF4aXNPYmpTZWwuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnKzArJywnKzArJyknKVxuICAgIHlBeGlzT2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyswKycsJyswKycpJylcbiAgfVxuXG4gIHJldHVybiB6b29tXG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0LCBnZXRUcmFuc2xhdGlvbn0gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7bG9nLCB3YXJuLCBlcnJvciwgaW5mb30gZnJvbSAnLi91dGlscyc7XG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQTE9UWk9PTSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4vKipcbiAqIENyZWF0ZXMgYW4gcGxvdFpvb20gaW5zdGFuY2UsIHdoaWNoIGNhbiBoYW5kbGUgZHJhZyBhbmQgc2Nyb2xsIGV2ZW50c1xuICogQGNvbnN0cnVjdG9yIHBsb3Rab29tXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjaGFydCBhIGZ1bmN0aW9uIGluc3RhbmNlIG9mIG9uZSBvZiB0aGUgZDNzbSBwbG90cyAoZS5nLiBiYXIsIGJveHdoaXNrZXIsIGJ1YmJsZUhlYXRtYXAsIHZpb2xpbiwgZXRjKVxuICogQHBhcmFtIHtheGlzfSAgeEF4aXMgdGhlIGF4aXMgaW5zdGFuY2UgcmVzcG9uc2libGUgZm9yIHRoZSB4IGF4aXNcbiAqIEBwYXJhbSB7YXhpc30geUF4aXMgdGhlIGF4aXMgaW5zdGFuY2UgcmVzcG9uc2libGUgZm9yIHRoZSB5IGF4aXNcbiAqIEBuYW1lc3BhY2UgcGxvdFpvb21cbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gem9vbVxuICovXG5leHBvcnQgZnVuY3Rpb24gbXVsdGlQbG90Wm9vbSggY2hhcnQgKSB7XG4gIHZhclxuICAvKipcbiAgKiBUaGUgZXZlbnQgb24gd2hpY2ggdG8gZmlyZVxuICAqIChzZWUge0BsaW5rIHBsb3Rab29tI2V2ZW50VHlwZX0pXG4gICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50VHlwZSB3aGljaCBldmVudCBpdCBzaG91bGQgaGFuZGxlLiBDdXJyZW50bHkgc3VwcG9ydHMgc2Nyb2xsIGFuZCB3aGVlbFxuICAqIEBtZW1iZXJvZiBwbG90Wm9vbSNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZXZlbnRUeXBlLFxuICAvKipcbiAgKiBBIHNjYWxpbmcgZmFjdG9yIGZvciB0aGUgd2hlZWwgXCJzcGVlZFwiXG4gICogKHNlZSB7QGxpbmsgcGxvdFpvb20jd2hlZWxTcGVlZH0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFt3aGVlbFNwZWVkPTIwXSBzY2FsZXMgdGhlIHdoZWVsIHRyYW5zbGF0aW9uIGJ5IHdoZWVsU3BlZWRcbiAgKiBAbWVtYmVyb2YgcGxvdFpvb20jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHdoZWVsU3BlZWQgPSAyMCxcbiAgLyoqXG4gICogVGhlIG9yaWVudGF0aW9uIGluIHdoaWNoIHRvIGFsbG93IHNjcm9sbGluZzogJ2hvcml6b250YWwnLCAndmVydGljYWwnLCBvciAnMkQnXG4gICogKHNlZSB7QGxpbmsgcGxvdFpvb20jb3JpZW50fSlcbiAgKiBAcGFyYW0ge3N0cmluZ30gW29yaWVudD1jaGFydC5vcmllbnQoKSB8fCAnaG9yaXpvbnRhbCddXG4gICogQG1lbWJlcm9mIHBsb3Rab29tI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvcmllbnQgPSAoY2hhcnQub3JpZW50ID09IHVuZGVmaW5lZCkgPyAnaG9yaXpvbnRhbCcgOiBjaGFydC5vcmllbnQoKSxcbiAgLyoqXG4gICogVGhlIG1heCBkaXN0YW5jZSBhbGxvd2VkIHRvIHNjcm9sbCBpbiB0aGUgeCBkaXJlY3Rpb25cbiAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN4TG9ja30pXG4gICogQHBhcmFtIHtudW1iZXJ9IFt4TG9jaz1jaGFydC5zcGFjZVgoKV0gaWRlYWxseSBjaGFydC5vdmVyZmxvd1EoKSA9PSB0cnVlIGFuZCB0aGlzIHZhbHVlIGlzIHRoZVxuICAqIGJvdW5kaW5nIHJlY3QgYWNyb3NzIGFsbCBlbGVtZW50cyBpbiB0aGUgY2hhcnQgIG1pbnVzIHRoZSBzcGFjZSBpbiB3aGljaCB0byBzaG93LlxuICAqIEBtZW1iZXJvZiBwbG90Wm9vbSNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgeExvY2s9Y2hhcnQuc3BhY2VYKCksXG4gIC8qKlxuICAqIFRoZSBtYXggZGlzdGFuY2UgYWxsb3dlZCB0byBzY3JvbGwgaW4gdGhlIHkgZGlyZWN0aW9uXG4gICogKHNlZSB7QGxpbmsgcGxvdFpvb20jeUxvY2t9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbeUxvY2s9Y2hhcnQuc3BhY2VZKCldIGlkZWFsbHkgY2hhcnQub3ZlcmZsb3dRKCkgPT0gdHJ1ZSBhbmQgdGhpcyB2YWx1ZSBpcyB0aGVcbiAgKiBib3VuZGluZyByZWN0IGFjcm9zcyBhbGwgZWxlbWVudHMgaW4gdGhlIGNoYXJ0ICBtaW51cyB0aGUgc3BhY2UgaW4gd2hpY2ggdG8gc2hvdy5cbiAgKiBAbWVtYmVyb2YgcGxvdFpvb20jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHlMb2NrPWNoYXJ0LnNwYWNlWSgpLFxuXG4gIGNoYXJ0U2VsID0gY2hhcnQuc2VsZWN0aW9uKCksXG5cbiAgc3ZnID0gZDMuc2VsZWN0KGNoYXJ0U2VsLnRoaXNTVkcoKSksXG5cbiAgeENvbXBvbmVudHMgPSBbXSxcbiAgeUNvbXBvbmVudHMgPSBbXVxuXG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZXZlbnQgdHlwZSBpbiB3aGljaCB0byByZXNwb25kXG4gICAqIChzZWUge0BsaW5rIHBsb3Rab29tI2V2ZW50VHlwZX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXSBzaG91bGQgYmUgJ2RyYWcnIG9yICd3aGVlbCdcbiAgICogQHJldHVybnMge3pvb20gfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBwbG90Wm9vbVxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBwbG90Wm9vbT11bmRlZmluZWRcbiAgICovXG4gIHpvb20uZXZlbnRUeXBlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChldmVudFR5cGUgPSBfLCB6b29tKSA6IGV2ZW50VHlwZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgd2hlZWwgc3BlZWQgaW4gd2hpY2ggdG8gc2NhbGUgdGhlIHdoZWVsIHNjcm9sbCB0cmFuc2Zvcm1cbiAgICogKHNlZSB7QGxpbmsgcGxvdFpvb20jd2hlZWxTcGVlZH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7em9vbSB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHBsb3Rab29tXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHdoZWVsU3BlZWQ9MjBcbiAgICovXG4gIHpvb20ud2hlZWxTcGVlZCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAod2hlZWxTcGVlZCA9IF8sIHpvb20pIDogd2hlZWxTcGVlZDsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgb3JpZW50YXRpb24gaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIChzZWUge0BsaW5rIHBsb3Rab29tI29yaWVudH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXSBzaG91bGQgYmUgaG9yaXpvbnRhbCwgdmVydGljYWwsIG9yIDJEXG4gICAqIEByZXR1cm5zIHt6b29tIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgcGxvdFpvb21cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3JpZW50PWNoYXJ0Lm9yaWVudCgpIHx8ICdob3Jpem9udGFsJ1xuICAgKi9cbiAgem9vbS5vcmllbnQgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9yaWVudCA9IF8sIHpvb20pIDogb3JpZW50OyB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIG1heCBkaXN0YW5jZSBpbiB3aGljaCB0byBzY3JvbGwgWFxuICAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN4TG9ja30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBwb3NpdGl2ZSB2YWx1ZVxuICAgKiBAcmV0dXJucyB7em9vbSB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHBsb3Rab29tXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHhMb2NrPWNoYXJ0LnNwYWNlWCgpXG4gICAqL1xuICB6b29tLnhMb2NrID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4TG9jayA9IF8sIHpvb20pIDogeExvY2s7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIG1heCBkaXN0YW5jZSBpbiB3aGljaCB0byBzY3JvbGwgWVxuICAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN5TG9ja30pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSAgc2hvdWxkIGJlIGEgcG9zaXRpdmUgdmFsdWVcbiAgICogQHJldHVybnMge3pvb20gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBwbG90Wm9vbVxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB5TG9jaz1jaGFydC5zcGFjZVkoKVxuICAgKi9cbiAgem9vbS55TG9jayA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeUxvY2sgPSBfLCB6b29tKSA6IHlMb2NrOyB9O1xuXG4gIHpvb20ueENvbXBvbmVudHMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhDb21wb25lbnRzID0gXywgem9vbSkgOiB4Q29tcG9uZW50czsgfTtcbiAgem9vbS55Q29tcG9uZW50cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeUNvbXBvbmVudHMgPSBfLCB6b29tKSA6IHlDb21wb25lbnRzOyB9O1xuXG5cbiAgZnVuY3Rpb24gc2V0TG9ja3MoKSB7XG4gICAgdmFyIGNoYXJ0T2JqU2VsID0gY2hhcnRTZWwuc2VsZWN0KCcuJytoeXBlbmF0ZShjaGFydC5uYW1lc3BhY2UoKSwnb2JqZWN0LWNvbnRhaW5lcicpKVxuICAgIHZhciBjaGFydE9ialRyYW5zID0gZ2V0VHJhbnNsYXRpb24oY2hhcnRPYmpTZWwuYXR0cigndHJhbnNmb3JtJykpXG4gICAgdmFyIGNvcyA9IGNoYXJ0T2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoMCwwKScpXG5cbiAgICB4TG9jayA9IGNoYXJ0U2VsLm5vZGUoKS5nZXRCQm94KCkud2lkdGggLSBjaGFydC5zcGFjZVgoKS8vICogLjlcbiAgICB5TG9jayA9IGNoYXJ0U2VsLm5vZGUoKS5nZXRCQm94KCkuaGVpZ2h0IC0gY2hhcnQuc3BhY2VZKCkvLyAqIC45XG4gICAgY29zLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJytjaGFydE9ialRyYW5zWzBdKycsJytjaGFydE9ialRyYW5zWzFdKycpJylcbiAgICBsb2coJ3Bsb3Rab29tJywgJ3NldExvY2tzJywge3hMb2NrOnhMb2NrLCB5TG9jazp5TG9ja30pXG4gIH1cblxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSB4IGFuZCB5IGxvY2tzIChob3cgZmFyIG9uZSBjYW4gc2Nyb2xsKVxuICAgKiAoc2VlIHtAbGluayBwbG90Wm9vbSN4TG9ja30gYW5kIHtAbGluayBwbG90Wm9vbSN5TG9ja30pXG4gICAqIEBmdW5jdGlvbiBwbG90Wm9vbS5zZXRMb2Nrc1xuICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICAgKiBAbWVtYmVyb2YgcGxvdFpvb21cbiAgICogQHByb3BlcnR5XG4gICAqL1xuICB6b29tLnNldExvY2tzID0gc2V0TG9ja3NcblxuICBmdW5jdGlvbiB6b29tKCkge1xuICAgIHNldExvY2tzKClcblxuICAgIHZhclxuICAgIHhDb21wb25lbnRzU2VsID0geENvbXBvbmVudHMubWFwKGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkLnNlbGVjdGlvbigpfSksXG4gICAgeUNvbXBvbmVudHNTZWwgPSB5Q29tcG9uZW50cy5tYXAoZnVuY3Rpb24oZCwgaSl7cmV0dXJuIGQuc2VsZWN0aW9uKCl9KVxuXG4gICAgdmFyIGhvcml6b250YWxRLCB2ZXJ0aWNhbFFcbiAgICBpZiAob3JpZW50ID09ICcyRCcpIHtob3Jpem9udGFsUSA9IHRydWU7IHZlcnRpY2FsUSA9IHRydWU7fVxuICAgIGlmIChvcmllbnQgPT0gJ2hvcml6b250YWwnKSB7aG9yaXpvbnRhbFEgPSB0cnVlOyB2ZXJ0aWNhbFEgPSBmYWxzZTt9XG4gICAgaWYgKG9yaWVudCA9PSAndmVydGljYWwnKSB7dmVydGljYWxRID0gdHJ1ZTsgaG9yaXpvbnRhbFEgPSBmYWxzZTt9XG5cbiAgICAvLyBjYXB0dXJlIHRyYW5zZm9ybSBldmVudFxuICAgIHZhciB0cmFuc2Zvcm0gPSBkMy5ldmVudC50cmFuc2Zvcm1cblxuICAgIHZhciBjaGFydEJveCA9IGNoYXJ0U2VsLm5vZGUoKS5nZXRCQm94KClcbiAgICB2YXIgeENvbXBvbmVudHNCb3ggPSB4Q29tcG9uZW50c1NlbC5tYXAoZnVuY3Rpb24oZCwgaSl7cmV0dXJuIGQubm9kZSgpLmdldEJCb3goKX0pXG4gICAgdmFyIHlDb21wb25lbnRzQm94ID0geENvbXBvbmVudHNTZWwubWFwKGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkLm5vZGUoKS5nZXRCQm94KCl9KVxuXG5cbiAgICB2YXIgY2hhcnRXaWR0aCA9IGNoYXJ0Qm94LndpZHRoIC0gY2hhcnRCb3gueFxuICAgIHZhciBjaGFydEhlaWdodCA9IGNoYXJ0Qm94LmhlaWdodCAtIGNoYXJ0Qm94LnlcblxuICAgIC8vIGVuYWJsZSB3aGVlbCBldmVudFxuICAgIGlmIChldmVudFR5cGUgPT0gXCJ3aGVlbFwiKSB7XG4gICAgICB2YXIgZSA9IGQzLmV2ZW50XG4gICAgICAvLyBwcmV2ZW50IHBhZ2Ugc2Nyb2xsaW5nXG4gICAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICAgIC8vIGV2ZW50IGRlbHRhIGlzIHZlcnkgdmVyeSBzbG93LCBzbyBzcGVlZCBpdCB1cCB3aXRoIHdoZWVsIHNwZWVkXG4gICAgICB2YXIgdyA9IGQzLmV2ZW50LmRlbHRhWSAqIHdoZWVsU3BlZWRcbiAgICAgIHZhciBzaGlmdFEgPSBkMy5ldmVudC5zaGlmdEtleVxuXG4gICAgICAvLyBkMyBoYXMgbm8gd2F5IHRvIG1ha2UgY3VzdG9tIHRyYW5zZm9ybSwgc28gbWFrZSBhbiBvYmplY3QgYW5kIGFkZFxuICAgICAgLy8gdGhlIG5lY2Vzc2FyeSBmdW5jdGlvbnMgdG8gbWFrZSB3aGVlbCBldmVudCBjb21wYXRpYmxlIHdpdGggZHJhZyBldmVudHNcbiAgICAgIGlmIChvcmllbnQgPT0gJzJEJykge1xuICAgICAgICB0cmFuc2Zvcm0gPSBzaGlmdFEgPyB7azogMSwgeDogdywgeTogMH0gOiB7azogMSwgeDogMCwgeTogd31cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyYW5zZm9ybSA9IGhvcml6b250YWxRID8ge2s6IDEsIHg6IHcsIHk6IDB9IDoge2s6IDEsIHg6IDAsIHk6IHd9XG4gICAgICB9XG4gICAgICAvLyAqIC0xIGlzIGludmVydFxuICAgICAgdHJhbnNmb3JtLmFwcGx5WCA9IGZ1bmN0aW9uKHgpIHsgcmV0dXJuIHggKiB0aGlzLmsgKyB0aGlzLnggKi0xOyB9XG4gICAgICB0cmFuc2Zvcm0uYXBwbHlZID0gIGZ1bmN0aW9uKHkpIHsgcmV0dXJuIHkgKiB0aGlzLmsgKyB0aGlzLnkgKi0xOyB9XG4gICAgfVxuXG5cblxuICAgIHZhciBjaGFydE9ialNlbCA9IGNoYXJ0U2VsLnNlbGVjdCgnLicraHlwZW5hdGUoY2hhcnQubmFtZXNwYWNlKCksJ29iamVjdC1jb250YWluZXInKSlcbiAgICB2YXIgeENvbXBvbmVudE9ialNlbCA9IHhDb21wb25lbnRzU2VsLm1hcChmdW5jdGlvbihkLCBpKXtcbiAgICAgIHJldHVybiBkLnNlbGVjdCgnLicraHlwZW5hdGUoeENvbXBvbmVudHNbaV0ubmFtZXNwYWNlKCksJ29iamVjdC1jb250YWluZXInKSlcbiAgICB9KVxuICAgIHZhciB5Q29tcG9uZW50T2JqU2VsID0geUNvbXBvbmVudHNTZWwubWFwKGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgcmV0dXJuIGQuc2VsZWN0KCcuJytoeXBlbmF0ZSh5Q29tcG9uZW50c1tpXS5uYW1lc3BhY2UoKSwnb2JqZWN0LWNvbnRhaW5lcicpKVxuICAgIH0pXG5cbiAgICB2YXIgY2hhcnRPYmpUcmFucyA9IGdldFRyYW5zbGF0aW9uKGNoYXJ0T2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScpKVxuICAgIHZhciB4Q29tcG9uZW50c09ialRyYW5zID0geENvbXBvbmVudE9ialNlbC5tYXAoZnVuY3Rpb24oZCwgaSl7XG4gICAgICByZXR1cm4gZ2V0VHJhbnNsYXRpb24oZC5hdHRyKCd0cmFuc2Zvcm0nKSlcbiAgICB9KVxuICAgIHZhciB5Q29tcG9uZW50c09ialRyYW5zID0geUNvbXBvbmVudE9ialNlbC5tYXAoZnVuY3Rpb24oZCwgaSl7XG4gICAgICByZXR1cm4gZ2V0VHJhbnNsYXRpb24oZC5hdHRyKCd0cmFuc2Zvcm0nKSlcbiAgICB9KVxuXG4gICAgdmFyIHggPSBob3Jpem9udGFsUSA/IHRyYW5zZm9ybS5hcHBseVgoY2hhcnRPYmpUcmFuc1swXSkgOiAwXG4gICAgaWYgKGhvcml6b250YWxRKSB7eCA9IHggPCAteExvY2sgPyAodHJhbnNmb3JtLnggPSAwLCAteExvY2spIDogKHRyYW5zZm9ybS54ID0gMCwgTWF0aC5taW4oeCwgMCkpIH1cblxuICAgIHZhciB5ID0gdmVydGljYWxRID8gdHJhbnNmb3JtLmFwcGx5WShjaGFydE9ialRyYW5zWzFdKSA6IDBcbiAgICBpZiAodmVydGljYWxRKSB7eSA9IHkgPCAteUxvY2sgPyAodHJhbnNmb3JtLnkgPSAwLCAteUxvY2spOiAodHJhbnNmb3JtLnkgPSAwLCBNYXRoLm1pbih5LCAwKSl9XG5cbiAgICBjaGFydE9ialNlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcreCsnLCcreSsnKScpXG4gICAgaWYgKGhvcml6b250YWxRKSB7XG4gICAgICAvLyB4QXhpc09ialNlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcreCsnLCcrMCsnKScpXG4gICAgICB4Q29tcG9uZW50T2JqU2VsLm1hcChmdW5jdGlvbihkLCBpKXsgZC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcreCsnLCcrMCsnKScpICB9KVxuICAgIH1cbiAgICBpZiAodmVydGljYWxRKSB7XG4gICAgICAvLyB5QXhpc09ialNlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcrMCsnLCcreSsnKScpXG4gICAgICB5Q29tcG9uZW50T2JqU2VsLm1hcChmdW5jdGlvbihkLCBpKXsgZC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcrMCsnLCcreSsnKScpICB9KVxuXG4gICAgfVxuXG5cbiAgfVxuXG4gIHpvb20ucmVzZXQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgaG9yaXpvbnRhbFEsIHZlcnRpY2FsUVxuICAgIGlmIChvcmllbnQgPT0gJzJEJykge2hvcml6b250YWxRID0gdHJ1ZTsgdmVydGljYWxRID0gdHJ1ZTt9XG4gICAgaWYgKG9yaWVudCA9PSAnaG9yaXpvbnRhbCcpIHtob3Jpem9udGFsUSA9IHRydWU7IHZlcnRpY2FsUSA9IGZhbHNlO31cbiAgICBpZiAob3JpZW50ID09ICd2ZXJ0aWNhbCcpIHt2ZXJ0aWNhbFEgPSB0cnVlOyBob3Jpem9udGFsUSA9IGZhbHNlO31cblxuICAgIHZhciBjaGFydE9ialNlbCA9IGNoYXJ0U2VsLnNlbGVjdCgnLicraHlwZW5hdGUoY2hhcnQubmFtZXNwYWNlKCksJ29iamVjdC1jb250YWluZXInKSlcbiAgICB2YXIgeEF4aXNPYmpTZWwgPSB4QXhpc1NlbC5zZWxlY3QoJy4nK2h5cGVuYXRlKHhBeGlzLm5hbWVzcGFjZSgpLCdvYmplY3QtY29udGFpbmVyJykpXG4gICAgdmFyIHlBeGlzT2JqU2VsID0geUF4aXNTZWwuc2VsZWN0KCcuJytoeXBlbmF0ZSh5QXhpcy5uYW1lc3BhY2UoKSwnb2JqZWN0LWNvbnRhaW5lcicpKVxuICAgIGNoYXJ0T2JqU2VsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyswKycsJyswKycpJylcbiAgICB4QXhpc09ialNlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcrMCsnLCcrMCsnKScpXG4gICAgeUF4aXNPYmpTZWwuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnKzArJywnKzArJyknKVxuICB9XG5cbiAgcmV0dXJuIHpvb21cbn1cbiIsImltcG9ydCB7aHlwZW5hdGUsIHNhZmVTZWxlY3QsIG1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2UsIGV4dHJhY3RWaW9saW5WYWx1ZXMsIHF1YXJ0aWxlc30gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7c2V0dXBDb250YWluZXIsIGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3QsIGNhbGN1bGF0ZVdpZHRoT2ZTcGFjZXJ9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHt1bmlxdWUsIGhhc1EsIGZsYXR0ZW4sIHdoaWNoQmlufSBmcm9tICcuL2FycmF5LWZ1bmN0aW9ucyc7XG5pbXBvcnQge2dyb3VwaW5nU3BhY2VyfSBmcm9tICcuL2dyb3VwaW5nLXNwYWNlcic7XG5pbXBvcnQge2NvbG9yRnVuY3Rpb24gYXMgQ0Z9IGZyb20gJy4vY29sb3ItZnVuY3Rpb24nO1xuaW1wb3J0IHt0b29sdGlwIGFzIFRUaXB9IGZyb20gJy4vdG9vbHRpcCc7XG5cbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVklPTElOICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqXG4qKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKlxuKiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbi8qKlxuICogQ3JlYXRlcyBhIHZpb2xpblxuICpcbiAqIHtAbGluayBodHRwczovL3N1bW5ldXJvbi5naXRsYWIuaW8vZDNzbS9kZW1vcy9iYXNpYy12aW9saW5zL2luZGV4Lmh0bWwgRGVtb31cbiAqIEBjb25zdHJ1Y3RvciB2aW9saW5cbiAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBzZWxlY3Rpb25cbiAqIEBuYW1lc3BhY2UgdmlvbGluXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IHZpb2xpblxuICovXG5leHBvcnQgZnVuY3Rpb24gdmlvbGluKCBzZWxlY3Rpb24gKSB7XG4gIHZhclxuICAvKipcbiAgKiBEYXRhIHRvIHBsb3QuIEFzc3VtZWQgdG8gYmUgYSBvYmplY3QsIHdoZXJlIGVhY2gga2V5IGNvcnJlc3BvbmRzIHRvIGEgdmlvbGluXG4gICogKHNlZSB7QGxpbmsgdmlvbGluI2RhdGF9KVxuICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZGF0YSxcbiAgLyoqXG4gICogV2hpY2ggZGlyZWN0aW9uIHRvIHJlbmRlciB0aGUgYmFycyBpblxuICAqIChzZWUge0BsaW5rIHZpb2xpbiNvcmllbnR9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbb3JpZW50PSdob3Jpem9udGFsJ11cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvcmllbnQ9J2hvcml6b250YWwnLFxuICAvKipcbiAgKiBBbW91bnQgb2YgaG9yaXpvbnRhbCBzcGFjZSAoaW4gcGl4ZWxzKSBhdmFpYmxlIHRvIHJlbmRlciB0aGUgdmlvbGluIGluXG4gICogKHNlZSB7QGxpbmsgdmlvbGluI3NwYWNlWH0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtzcGFjZVg9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNwYWNlWCxcbiAgLyoqXG4gICogQW1vdW50IG9mIHZlcnRpY2FsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSB2aW9saW4gaW5cbiAgKiAoc2VlIHtAbGluayB2aW9saW4uc3BhY2VZfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlWT11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VZLFxuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0byBhbGxvdyB2aW9saW4gdG8gcmVuZGVyIGVsZW1lbnRzIHBhc3MgdGhlIG1haW4gc3BhdGlhbCBkaW1lbnNpb25cbiAgKiBnaXZlbiB0aGUgb3JpZW50YXRpb24gKHNlZSB7QGxpbmsgdmlvbGluI29yaWVudH0pLCB3aGVyZSB7QGxpbmsgdmlvbGluI29yaWVudH09XCJob3Jpem9udGFsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIHZpb2xpbiNzcGFjZVh9IGFuZCB3aGVyZSB7QGxpbmsgdmlvbGluI29yaWVudH09XCJ2ZXJ0aWNhbFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayB2aW9saW4jc3BhY2VZfVxuICAqIEBwYXJhbSB7Ym9vbGVhbn0gW292ZXJmbG93UT1mYWxzZV1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvdmVyZmxvd1EgPSB0cnVlLFxuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0byBkaXNwbGF5IHBvaW50cyBpbnNpZGUgdGhlIHBvaW50c1xuICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3BvaW50c1E9ZmFsc2VdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgcG9pbnRzUSA9IHRydWUsXG4gIC8qKlxuICAqIEFuIGFycmF5IC0gcHV0YXRpdmVseSBvZiBvdGhlciBhcnJheXMgLSBkZXBpY3RpbmcgaG93IGJhcnMgc2hvdWxkIGJlIGFycmFuZ2VkXG4gICogQHBhcmFtIHtBcnJheVtdfSBbZ3JvdXBpbmc9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIGdyb3VwaW5nLFxuICAvKipcbiAgKiBIb3cgdG8gZ2V0IHRoZSB2YWx1ZSBvZiB0aGUgdmlvbGluXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3ZhbHVlRXh0cmFjdG9yPWZ1bmN0aW9uKGtleSwgaW5kZXgpIHsgcmV0dXJuIGRhdGFba2V5XSB9XVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHZhbHVlRXh0cmFjdG9yID0gZnVuY3Rpb24oa2V5LCBpbmRleCkge3JldHVybiBkYXRhW2tleV0gfSxcbiAgLyoqXG4gICogSG93IHRvIHNvcnQgdGhlIGJhcnMgLSBpZiB7QGxpbmsgdmlvbGluI2dyb3VwaW5nfSBpcyBub3QgcHJvdmlkZWQuXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3NvcnRpbmdGdW5jdGlvbj1mdW5jdGlvbihrZXlBLCBrZXlCKSB7cmV0dXJuIGQzLmRlc2NlbmRpbmcoZGF0YVtrZXlBXSwgZGF0YVtrZXlCXSl9XVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNvcnRpbmdGdW5jdGlvbiA9IGZ1bmN0aW9uKGtleUEsIGtleUIpIHtyZXR1cm4gZDMuZGVzY2VuZGluZyhkYXRhW2tleUFdLCBkYXRhW2tleUJdKX0sXG5cbiAgLyoqXG4gICogVGhlIHNjYWxlIGZvciB3aGljaCB2aW9saW4gdmFsdWVzIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBieVxuICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtzY2FsZT1kMy5zY2FsZUxpbmVhcl1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKCksXG4gIC8qKlxuICAqIFRoZSBwYWRkaW5nIGZvciB0aGUgZG9tYWluIG9mIHRoZSBzY2FsZSAoc2VlIHtAbGluayB2aW9saW4jc2NhbGV9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbZG9tYWluUGFkZGluZz0wLjVdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZG9tYWluUGFkZGluZyA9IDAuNSxcbiAgLyoqXG4gICogRGVmYXVsdCBzcGFjZSBmb3IgdGhlIHNwYWNlciAocGVyY2VudGFnZSkgb2YgbWFpbiBkaW1lbnNpb24gZ2l2ZW4gdGhlIG9yaWVudGF0aW9uXG4gICogKHNlZSB7QGxpbmsgdmlvbGluI29yaWVudH0pLCB3aGVyZSB7QGxpbmsgdmlvbGluI29yaWVudH09XCJob3Jpem9udGFsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIHZpb2xpbiNzcGFjZVh9IGFuZCB3aGVyZSB7QGxpbmsgdmlvbGluI29yaWVudH09XCJ2ZXJ0aWNhbFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayB2aW9saW4jc3BhY2VZfSBiZXR3ZWVuIGJhcnNcbiAgKiBAcGFyYW0ge251bWJlcn0gW29iamVjdFNwYWNlcj0wLjA1XVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdFNwYWNlciA9IDAuMDUsXG4gIC8qKlxuICAqIFRoZSBtaW5pbXVtIHNpemUgdGhhdCBhbiBvYmplY3QgY2FuIGJlXG4gICogQHBhcmFtIHtudW1iZXJ9IFttaW5PYmplY3RTaXplPTUwXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIG1pbk9iamVjdFNpemUgPSA1MCxcbiAgLyoqXG4gICogVGhlIG1heGltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmVcbiAgKiBAcGFyYW0ge251bWJlcn0gW21heE9iamVjdFNpemU9MTAwXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIG1heE9iamVjdFNpemUgPSAxMDAsXG5cbiAgLyoqXG4gICogVGhlIHN0cm9rZSB3aWR0aCBvZiB0aGUgYmFyc1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbYmFyU3Ryb2tlV2lkdGg9Ml1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvYmplY3RTdHJva2VXaWR0aCA9IDIsXG4gIC8qKlxuICAqIEluc3RhbmNlIG9mIENvbG9yRnVuY3Rpb25cbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24oKV1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBjb2xvckZ1bmN0aW9uID0gQ0YoKSxcbiAgLyoqXG4gICogSW5zdGFuY2Ugb2YgQ29sb3JGdW5jdGlvbiBtb2RpZmllZCBieSBhIHNjYWxlIGZvciB0aGUgcG9pbnRzXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gW3BvaW50Q29sb3JGdW5jID0gY29sb3JGdW5jdGlvbigpXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHBvaW50Q29sb3JGdW5jID0gZnVuY3Rpb24gKGQsIHR5cGUsIGJhc2UsIG1pbiwgbWF4KSB7XG4gICAgdmFyIG1pbk1heEhleFNjYWxlID0gZDMuc2NhbGVMaW5lYXIoKS5kb21haW4oW21pbiwgbWF4XSkucmFuZ2UoWy0wLjI1LCAwLjA1XSlcbiAgICB2YXIgc2NhbGVkQ29sb3IgPSBtb2RpZnlIZXhpZGVjaW1hbENvbG9yTHVtaW5hbmNlKGJhc2UucmVwbGFjZSgnIycsICcnKSwgbWluTWF4SGV4U2NhbGUoZCkpXG4gICAgdmFyIG1vZCA9IHR5cGUgPT0gXCJzdHJva2VcIiA/IDAgOiAwLjI1XG4gICAgcmV0dXJuIG1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2Uoc2NhbGVkQ29sb3IucmVwbGFjZSgnIycsICcnKSwgbW9kKVxuICB9LFxuXG4gIC8qKlxuICAqIFRoZSByYWRpdXMgb2YgYSBwb2ludFxuICAqIEBwYXJhbSB7bnVtYmVyfSBbcG9pbnRSYWRpdXM9M11cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBwb2ludFJhZGl1cyA9IDMsXG4gIC8qKlxuICAqIFRoZSBzdHJva2Ugd2lkdGggb2YgdGhlIG9pbnRzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtwb2ludFN0cm9rZVdpZHRoPTJdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgcG9pbnRTdHJva2VXaWR0aCA9IDIsXG5cbiAgLyoqXG4gICogQ29sb3Igb2YgdGhlIGJhY2tncm91bmRcbiAgKiBAcGFyYW0ge3N0cmluZ30gW2JhY2tncm91bmRGaWxsPVwidHJhbnNwYXJlbnRcIl1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCcsXG4gIC8qKlxuICAqIE5hbWVzcGFjZSBmb3IgYWxsIGl0ZW1zIG1hZGUgYnkgdGhpcyBpbnN0YW5jZSBvZiB2aW9saW5cbiAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWVzcGFjZT1cImQzc20tdmlvbGluXCJdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbmFtZXNwYWNlID0gJ2Qzc20tdmlvbGluJyxcbiAgLyoqXG4gICogQ2xhc3MgbmFtZSBmb3IgdmlvbGluIGNvbnRhaW5lciAoPGc+IGVsZW1lbnQpXG4gICogQHBhcmFtIHtzdHJpbmd9IFtvYmplY3RDbGFzcz1cInZpb2xpblwiXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9iamVjdENsYXNzID0gJ3Zpb2xpbicsXG4gIC8qKlxuICAqIER1cmF0aW9uIG9mIGFsbCB0cmFuc2l0aW9ucyBvZiB0aGlzIGVsZW1lbnRcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RyYW5zaXRpb25EdXJhdGlvbj0xMDAwXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRyYW5zaXRpb25EdXJhdGlvbiA9IDEwMDAsXG4gIC8qKlxuICAqIEVhc2luZyBmdW5jdGlvbiBmb3IgdHJhbnNpdGlvbnNcbiAgKiBAcGFyYW0ge2QzLmVhc2V9IFtlYXNlRnVuYz1kMy5lYXNlRXhwXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIGVhc2VGdW5jID0gZDMuZWFzZUV4cCxcblxuICAvKipcbiAgKiBUaGUga2V5IGNvbnRhaW5pbmcgdGhlIHF1YXJ0aWxlc1xuICAqIEBwYXJhbSB7c3RyaW5nfSBbcXVhcnRpbGVzS2V5PXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBxdWFydGlsZXNLZXkgPSBcInF1YXJ0aWxlc1wiLFxuICAvKipcbiAgKiBUaGUga2V5cyBjb3JyZXNwb25kaW5nIHRvIGVhY2ggcXVhcnRpbGVcbiAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbcXVhcnRpbGVLZXlzPVtcIlEwXCIsIFwiUTFcIiwgXCJRMlwiLCBcIlEzXCIsIFwiUTRcIl1dXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgcXVhcnRpbGVLZXlzID0gW1wiUTBcIiwgXCJRMVwiLCBcIlEyXCIsIFwiUTNcIiwgXCJRNFwiXSxcblxuICAvKipcbiAgKiBUaGUga2V5cyBvZiB0aGUgYmFyc1xuICAqIEBwYXJhbSB7c3RyaW5nW119IFt2aW9saW5LZXlzPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2aW9saW5LZXlzLFxuICAvKipcbiAgKiBUaGUgdmFsdWVzIG9mIHRoZSBiYXJzXG4gICogQHBhcmFtIHtudW1iZXJbXX0gW3Zpb2xpblZhbHVlcz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmlvbGluVmFsdWVzLFxuICAvKipcbiAgKiBUaGUgb2JqZWN0U2l6ZSAoYWN0dWFsIHdpZHRoKSB1c2VkIGJ5IHRoZSBiYXJzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtvYmplY3RTaXplPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvYmplY3RTaXplLFxuICAvKipcbiAgKiBUaGUgc3BhY2VyU2l6ZSAoYWN0dWFsIHdpZHRoKSB1c2VkIGJ5IHRoZSBzcGFjZXJzIGJldHdlZW4gdGhlIGJhcnNcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlclNpemU9dW5kZWZpbmVkXVxuICAqIEBtZW1iZXJvZiB2aW9saW4jXG4gICogQHByb3BlcnR5XG4gICovXG4gIHNwYWNlclNpemUsXG5cbiAgLyoqXG4gICogSW5zdGFuY2Ugb2YgVG9vbHRpcFxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFt0b29sdGlwPXRvb2x0aXAoKV1cbiAgKiBAbWVtYmVyb2YgdmlvbGluI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB0b29sdGlwID0gVFRpcCgpLmtleXMoW3F1YXJ0aWxlS2V5c1s0XSwgcXVhcnRpbGVLZXlzWzNdLCBxdWFydGlsZUtleXNbMl0sIHF1YXJ0aWxlS2V5c1sxXSwgcXVhcnRpbGVLZXlzWzBdXSksXG4gIHBvaW50c1Rvb2x0aXAgPSBUVGlwKCksXG4gIC8vIHBvaW50S2V5RXh0cmFjdG9yID0gZnVuY3Rpb24odmlvbGluS2V5LCB2aW9saW5EYXRhLCB2aW9saW5WYWx1ZXMpIHtyZXR1cm4gZDMua2V5cyh2aW9saW5WYWx1ZXNbdmlvbGluS2V5XS52YWx1ZXMpfSxcbiAgLy8gcG9pbnRWYWx1ZUV4dHJhY3RvciA9IGZ1bmN0aW9uKHBvaW50S2V5LCB2aW9saW5LZXksIHZpb2xpbkRhdGEsIHZpb2xpblZhbHVlcykge3JldHVybiB2aW9saW5WYWx1ZXNbdmlvbGluS2V5XS52YWx1ZXNbcG9pbnRLZXldfSxcblxuXG4gIC8qKlxuICAqIEZ1bmN0aW9uIHdoaWNoIGdpdmVuIHRoZSBrZXkgb2YgdGhlIHZpb2xpbiBhbmQgdGhhdCBrZXkncyBhc3NvY2lhdGVkIHZhbHVlXG4gICogcmV0dXJucyB0aGUgb2JqZWN0IGNvbnNpdGluZyBvZiB0aGUgcG9pbnRzIG9mIHRoZSB2aW9saW5cbiAgKiAoc2VlIHtAbGluayB2aW9saW4jdmlvbGluUG9pbnRzRXh0cmFjdG9yfSlcbiAgKiBAcGFyYW0ge09iamVjdH0gW3Zpb2xpblBvaW50c0V4dHJhY3Rvcj1mdW5jdGlvbih2aW9saW5LZXksIHZpb2xpbkRhdGEpIHsgcmV0dXJuIHZpb2xpbkRhdGEucG9pbnRzIH1dXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmlvbGluUG9pbnRzRXh0cmFjdG9yID0gZnVuY3Rpb24gKHZpb2xpbktleSwgdmlvbGluRGF0YSkge3JldHVybiB2aW9saW5EYXRhLnBvaW50cyB9LFxuICAvKipcbiAgKiBGdW5jdGlvbiB3aGljaCBnaXZlbiB0aGUga2V5IG9mIHRoZSBjdXJyZW50IHBvaW50IGFuZCB0aGUgb2JqZWN0IG9mIHBvaW50cyBmb3IgdGhlXG4gICogdmlvbGluLCByZXR1cm5zIHRoZSBudW1lcmljYWwgdmFsdWUgb2YgdGhlIHBvaW50XG4gICogKHNlZSB7QGxpbmsgdmlvbGluI3Zpb2xpblBvaW50VmFsdWVFeHRyYWN0b3J9KVxuICAqIEBwYXJhbSB7T2JqZWN0fSBbdmlvbGluUG9pbnRWYWx1ZUV4dHJhY3Rvcj1mdW5jdGlvbih2aW9saW5Qb2ludEtleSwgdmlvbGluUG9pbnREYXRhKSB7IHJldHVybiB2aW9saW5Qb2ludERhdGFbdmlvbGluUG9pbnRLZXldLnZhbHVlIH1dXG4gICogQG1lbWJlcm9mIHZpb2xpbiNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgdmlvbGluUG9pbnRWYWx1ZUV4dHJhY3RvciA9IGZ1bmN0aW9uKHZpb2xpblBvaW50S2V5LCB2aW9saW5Qb2ludERhdGEpIHsgcmV0dXJuIHZpb2xpblBvaW50RGF0YVt2aW9saW5Qb2ludEtleV0udmFsdWUgfVxuXG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgdmlvbGluUG9pbnRzRXh0cmFjdG9yXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB2aW9saW5Qb2ludHNFeHRyYWN0b3IgPSBmdW5jdGlvbih2aW9saW5LZXksIHZpb2xpbkRhdGEpIHsgcmV0dXJuIHZpb2xpbkRhdGEucG9pbnRzIH1cbiAgICovXG4gIHZpb2xpbi52aW9saW5Qb2ludHNFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZpb2xpblBvaW50c0V4dHJhY3RvciA9IF8sIHZpb2xpbikgOiB2aW9saW5Qb2ludHNFeHRyYWN0b3I7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3JcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZpb2xpblBvaW50c0V4dHJhY3RvciA9IGZ1bmN0aW9uKHBvaW50S2V5LCB2aW9saW5LZXksIHZpb2xpbkRhdGEsIHZpb2xpblZhbHVlcykge3JldHVybiB2aW9saW5WYWx1ZXNbdmlvbGluS2V5XS52YWx1ZXNbcG9pbnRLZXldfVxuICAgKi9cbiAgdmlvbGluLnZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3IgPSBfLCB2aW9saW4pIDogdmlvbGluUG9pbnRWYWx1ZUV4dHJhY3RvcjsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIHNlbGVjdGlvbiBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBkMy5zZWxlY3Rpb259XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc2VsZWN0aW9uID0gc2VsZWN0aW9uXG4gICAqL1xuICB2aW9saW4uc2VsZWN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZWxlY3Rpb24gPSBfLCB2aW9saW4pIDogc2VsZWN0aW9uOyB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBkYXRhXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNkYXRhfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBvYmplY3R9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqL1xuICB2aW9saW4uZGF0YSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGF0YSA9IF8sIHZpb2xpbikgOiBkYXRhOyB9O1xuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBvcmllbnQgb2YgdGhlIGJveGVzXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNvcmllbnR9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG9iamVjdH1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIHZpb2xpbi5vcmllbnQgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9yaWVudCA9IF8sIHZpb2xpbikgOiBvcmllbnQ7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jc3BhY2VYfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVggPSB1bmRlZmluZWRcbiAgICovXG4gIHZpb2xpbi5zcGFjZVggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWCA9IF8sIHZpb2xpbikgOiBzcGFjZVg7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiB2ZXJ0aWNhbCBzcGFjZSBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3NwYWNlWX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBudW1iZXIgPiAwXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc3BhY2VZID0gdW5kZWZpbmVkXG4gICAqL1xuICB2aW9saW4uc3BhY2VZID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVkgPSBfLCB2aW9saW4pIDogc3BhY2VZOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IHZpb2xpbiBpcyBhbGxvd2VkIHRvIGdvIGJleW9uZCBzcGVjaWZpZWQgZGltZW5zaW9uc1xuICAgKiAoc2VlIHtAbGluayB2aW9saW4jb3ZlcmZsb3dRfSlcbiAgICogQHBhcmFtIHtib29sZWFufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7dmlvbGluIHwgYm9vbGVhbn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvdmVyZmxvd1EgPSBmYWxzZVxuICAgKi9cbiAgdmlvbGluLm92ZXJmbG93USA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob3ZlcmZsb3dRID0gXywgdmlvbGluKSA6IG92ZXJmbG93UTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHdoZXRoZXIgb3Igbm90IHRvIHBsb3QgcG9pbnRzIHdpdGggdGhlIHZpb2xpbnNcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3BvaW50c1F9KVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBib29sZWFufVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHBvaW50c1EgPSBmYWxzZVxuICAgKi9cbiAgdmlvbGluLnBvaW50c1EgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBvaW50c1EgPSBfLCB2aW9saW4pIDogcG9pbnRzUTsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgZ3JvdXBpbmcgb2YgdGhlIGJveGVzXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNncm91cGluZ30pXG4gICAqIEBwYXJhbSB7QXJyYXlbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IEFycmF5W119XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZ3JvdXBpbmcgPSB1bmRlZmluZWRcbiAgICovXG4gIHZpb2xpbi5ncm91cGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZ3JvdXBpbmcgPSBfLCB2aW9saW4pIDogZ3JvdXBpbmc7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdmFsdWVFeHRyYWN0b3JcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3ZhbHVlRXh0cmFjdG9yfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgdmlvbGluLnZhbHVlRXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZUV4dHJhY3RvciA9IF8sIHZpb2xpbikgOiB2YWx1ZUV4dHJhY3RvcjsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzb3J0aW5nRnVuY3Rpb25cbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3NvcnRpbmdGdW5jdGlvbn0pXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBmdW5jdGlvbn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIHZpb2xpbi5zb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNvcnRpbmdGdW5jdGlvbiA9IF8sIHZpb2xpbikgOiBzb3J0aW5nRnVuY3Rpb247IH07XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBzY2FsZSBmb3Igd2hpY2ggdGhlIHZpb2xpbiB2YWx1ZXMgc2hvdWxkIGJlIHRyYW5zZm9ybWVkIGJ5XG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNzY2FsZX0pXG4gICAqIEBwYXJhbSB7ZDMuc2NhbGV9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBkMy5zY2FsZX1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzY2FsZSA9IGQzLnNjYWxlTGluZWFyKClcbiAgICovXG4gIHZpb2xpbi5zY2FsZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGUgPSBfLCB2aW9saW4pIDogc2NhbGU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcGFkZGluZyBmb3IgdGhlIGRvbWFpbiBvZiB0aGUgc2NhbGVcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI2RvbWFpblBhZGRpbmd9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBkb21haW5QYWRkaW5nID0gMC41XG4gICAqL1xuICB2aW9saW4uZG9tYWluUGFkZGluZyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluUGFkZGluZyA9IF8sIHZpb2xpbikgOiBkb21haW5QYWRkaW5nOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIG9iamVjdFNwYWNlclxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jb2JqZWN0U3BhY2VyfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0U3BhY2VyID0gMC4wNVxuICAgKi9cbiAgdmlvbGluLm9iamVjdFNwYWNlciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0U3BhY2VyID0gXywgdmlvbGluKSA6IG9iamVjdFNwYWNlcjsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBtaW5PYmplY3RTaXplXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNtaW5PYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbWluT2JqZWN0U2l6ZSA9IDE1XG4gICAqL1xuICB2aW9saW4ubWluT2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobWluT2JqZWN0U2l6ZSA9IF8sIHZpb2xpbikgOiBtaW5PYmplY3RTaXplOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG1heE9iamVjdFNpemVcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI21heE9iamVjdFNpemV9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBtYXhPYmplY3RTaXplID0gNTBcbiAgICovXG4gIHZpb2xpbi5tYXhPYmplY3RTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChtYXhPYmplY3RTaXplID0gXywgdmlvbGluKSA6IG1heE9iamVjdFNpemU7IH07XG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RTdHJva2VXaWR0aFxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jb2JqZWN0U3Ryb2tlV2lkdGh9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RTdHJva2VXaWR0aCA9IDJcbiAgICovXG4gIHZpb2xpbi5vYmplY3RTdHJva2VXaWR0aCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0U3Ryb2tlV2lkdGggPSBfLCB2aW9saW4pIDogb2JqZWN0U3Ryb2tlV2lkdGg7IH07XG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGNvbG9yRnVuY3Rpb25cbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI2NvbG9yRnVuY3Rpb259KVxuICAgKiBAcGFyYW0ge2NvbG9yRnVuY3Rpb259IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBjb2xvckZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGNvbG9yRnVuY3Rpb24gPSBjb2xvckZ1bmN0aW9uKClcbiAgICovXG4gIHZpb2xpbi5jb2xvckZ1bmN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjb2xvckZ1bmN0aW9uID0gXywgdmlvbGluKSA6IGNvbG9yRnVuY3Rpb247IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgY29sb3JGdW5jdGlvblxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jY29sb3JGdW5jdGlvbn0pXG4gICAqIEBwYXJhbSB7Y29sb3JGdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IGNvbG9yRnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24oKVxuICAgKi9cbiAgdmlvbGluLnBvaW50Q29sb3JGdW5jID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwb2ludENvbG9yRnVuYyA9IF8sIHZpb2xpbikgOiBwb2ludENvbG9yRnVuYzsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcG9pbnRSYWRpdXNcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3BvaW50UmFkaXVzfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgcG9pbnRSYWRpdXMgPSAyXG4gICAqL1xuICB2aW9saW4ucG9pbnRSYWRpdXMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBvaW50UmFkaXVzID0gXywgdmlvbGluKSA6IHBvaW50UmFkaXVzOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHBvaW50U3Ryb2tlV2lkdGhcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3BvaW50U3Ryb2tlV2lkdGh9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBwb2ludFN0cm9rZVdpZHRoID0gMlxuICAgKi9cbiAgdmlvbGluLnBvaW50U3Ryb2tlV2lkdGggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBvaW50U3Ryb2tlV2lkdGggPSBfLCB2aW9saW4pIDogcG9pbnRTdHJva2VXaWR0aDsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgYmFja2dyb3VuZEZpbGxcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI2JhY2tncm91bmRGaWxsfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgYmFja2dyb3VuZEZpbGwgPSAndHJhbnNwYXJlbnQnXG4gICAqL1xuICB2aW9saW4uYmFja2dyb3VuZEZpbGwgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJhY2tncm91bmRGaWxsID0gXywgdmlvbGluKSA6IGJhY2tncm91bmRGaWxsOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIG5hbWVzcGFjZVxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jbmFtZXNwYWNlfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHt2aW9saW4gfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbmFtZXNwYWNlID0gJ2Qzc20tdmlvbGluJ1xuICAgKi9cbiAgdmlvbGluLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgdmlvbGluKSA6IG5hbWVzcGFjZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBvYmplY3RDbGFzc1xuICAgKiAoc2VlIHtAbGluayB2aW9saW4jb2JqZWN0Q2xhc3N9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBvYmplY3RDbGFzcyA9ICd0aWNrLWdyb3VwJ1xuICAgKi9cbiAgdmlvbGluLm9iamVjdENsYXNzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvYmplY3RDbGFzcyA9IF8sIHZpb2xpbikgOiBvYmplY3RDbGFzczsgfTtcblxuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdHJhbnNpdGlvbkR1cmF0aW9uXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiN0cmFuc2l0aW9uRHVyYXRpb259KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwXG4gICAqL1xuICB2aW9saW4udHJhbnNpdGlvbkR1cmF0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0cmFuc2l0aW9uRHVyYXRpb24gPSBfLCB2aW9saW4pIDogdHJhbnNpdGlvbkR1cmF0aW9uOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGVhc2VGdW5jXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNlYXNlRnVuY30pXG4gICAqIEBwYXJhbSB7ZDMuZWFzZX0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IGQzLmVhc2V9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwXG4gICAqL1xuICB2aW9saW4uZWFzZUZ1bmMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGVhc2VGdW5jID0gXywgdmlvbGluKSA6IGVhc2VGdW5jOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBxdWFydGlsZUtleVxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jcXVhcnRpbGVLZXl9KVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IHN0cmluZ31cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBxdWFydGlsZUtleSA9IFwicXVhcnRpbGVzXCJcbiAgICovXG4gIHZpb2xpbi5xdWFydGlsZUtleSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocXVhcnRpbGVLZXkgPSBfLCB2aW9saW4pIDogcXVhcnRpbGVLZXk7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgcXVhcnRpbGVLZXlzXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNxdWFydGlsZUtleXN9KVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7dmlvbGluIHwgc3RyaW5nW119XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgcXVhcnRpbGVLZXlzID0gW1wiUTBcIixcIlExXCIsXCJRMlwiLFwiUTNcIixcIlE0XCJdXG4gICAqL1xuICB2aW9saW4ucXVhcnRpbGVLZXlzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChxdWFydGlsZUtleXMgPSBfLCB2aW9saW4pIDogcXVhcnRpbGVLZXlzOyB9O1xuXG5cbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB2aW9saW5LZXlzXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiN2aW9saW5LZXlzfSlcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHZpb2xpbktleXMgPSB1bmRlZmluZWRcbiAgICovXG4gIHZpb2xpbi52aW9saW5LZXlzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2aW9saW5LZXlzID0gXywgdmlvbGluKSA6IHZpb2xpbktleXM7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdmlvbGluVmFsdWVzXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiN2aW9saW5WYWx1ZXN9KVxuICAgKiBAcGFyYW0ge09iamVjdFtdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7dmlvbGluIHwgT2JqZWN0W119XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdmlvbGluVmFsdWVzID0gdW5kZWZpbmVkXG4gICAqL1xuICB2aW9saW4udmlvbGluVmFsdWVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2aW9saW5WYWx1ZXMgPSBfLCB2aW9saW4pIDogdmlvbGluVmFsdWVzOyB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgb2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jb2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7dmlvbGluIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG9iamVjdFNpemUgPSB1bmRlZmluZWRcbiAgICovXG4gIHZpb2xpbi5vYmplY3RTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvYmplY3RTaXplID0gXywgdmlvbGluKSA6IG9iamVjdFNpemU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgc3BhY2VyU2l6ZVxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jc3BhY2VyU2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7dmlvbGluIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgdmlvbGluXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNwYWNlclNpemUgPSB1bmRlZmluZWRcbiAgICovXG4gIHZpb2xpbi5zcGFjZXJTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZXJTaXplID0gXywgdmlvbGluKSA6IHNwYWNlclNpemU7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdG9vbHRpcFxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jdG9vbHRpcH0pXG4gICAqIEBwYXJhbSB7dG9vbHRpcH0gW189bm9uZV1cbiAgICogQHJldHVybnMge3Zpb2xpbiB8IHRvb2x0aXB9XG4gICAqIEBtZW1iZXJvZiB2aW9saW5cbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdG9vbHRpcCA9IHRvb2x0aXAoKVxuICAgKi9cbiAgdmlvbGluLnRvb2x0aXAgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRvb2x0aXAgPSBfLCB2aW9saW4pIDogdG9vbHRpcDsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBwb2ludHNUb29sdGlwXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNwb2ludHNUb29sdGlwfSlcbiAgICogQHBhcmFtIHt0b29sdGlwfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7dmlvbGluIHwgdG9vbHRpcH1cbiAgICogQG1lbWJlcm9mIHZpb2xpblxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBwb2ludHNUb29sdGlwID0gdG9vbHRpcCgpXG4gICAqL1xuICB2aW9saW4ucG9pbnRzVG9vbHRpcCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocG9pbnRzVG9vbHRpcCA9IF8sIHZpb2xpbikgOiBwb2ludHNUb29sdGlwOyB9O1xuXG5cblxuXG5cbiAgZnVuY3Rpb24gdmlvbGluICgpIHtcbiAgICAvLyBmb3IgY29udmVuaWVuY2UgaW4gaGFuZGxpbmcgb3JpZW50YXRpb24gc3BlY2lmaWMgdmFsdWVzXG4gICAgdmFyIGhvcml6b250YWxRID0gKG9yaWVudCA9PSAnaG9yaXpvbnRhbCcpID8gdHJ1ZSA6IGZhbHNlXG4gICAgdmFyIHZlcnRpY2FsUSA9ICFob3Jpem9udGFsUVxuXG4gICAgLy8gYmFja2dyb3VuZCBjbGlwaW5nIHJlY3RhbmdsZVxuICAgIHZhciBiZ2NwUmVjdCA9IHt4OjAsIHk6MCwgd2lkdGg6IHNwYWNlWCwgaGVpZ2h0OnNwYWNlWX1cbiAgICB2YXIgY29udGFpbmVyID0gc2V0dXBDb250YWluZXIoIHNlbGVjdGlvbiwgbmFtZXNwYWNlLCBiZ2NwUmVjdCwgYmFja2dyb3VuZEZpbGwgKTtcblxuICAgIC8vIGlmIGdyb3VwaW5nIGlzIHVuZGVmaW5lZCBzb3J0IHZpb2xpbktleXMgYnkgc29ydGluZ0Z1bmN0aW9uXG4gICAgdmFyIG9yZGVyZWQgPSAoZ3JvdXBpbmcgPT0gdW5kZWZpbmVkKSA/IGQzLmtleXMoZGF0YSkuc29ydChzb3J0aW5nRnVuY3Rpb24pIDogZ3JvdXBpbmdcblxuICAgIC8vIGNvbnNvbGUubG9nKG9yZGVyZWQpXG5cbiAgICB2aW9saW5LZXlzID0gZmxhdHRlbihvcmRlcmVkKVxuXG5cbiAgICB2YXIgY2FsY1ZhbHVlcyA9IG5lZWRlZFZpb2xpblZhbHVlcygpXG4gICAgLmhvcml6b250YWxRKGhvcml6b250YWxRKVxuICAgIC5xdWFydGlsZUtleXMocXVhcnRpbGVLZXlzKVxuICAgIC52aW9saW5Qb2ludHNFeHRyYWN0b3IodmlvbGluUG9pbnRzRXh0cmFjdG9yKVxuICAgIC52aW9saW5Qb2ludFZhbHVlRXh0cmFjdG9yKHZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3IpXG5cblxuXG4gICAgLy8gYXVnbWVudCB2YWx1c1xuICAgIHZpb2xpbktleXMubWFwKGZ1bmN0aW9uKHZrLCBpKXsgY2FsY1ZhbHVlcyh2aywgZGF0YSkgfSlcblxuICAgIHZhciBudW1iZXJPZk9iamVjdHMgPSB2aW9saW5LZXlzLmxlbmd0aFxuXG4gICAgdmFyIG1pbiA9IFtdLmNvbmNhdCguLi52aW9saW5LZXlzLm1hcChmdW5jdGlvbihrLCBpKXtyZXR1cm4gZGF0YVtrXS5xdWFydGlsZXNbcXVhcnRpbGVLZXlzWzBdXX0pKVxuICAgIHZhciBtYXggPSBbXS5jb25jYXQoLi4udmlvbGluS2V5cy5tYXAoZnVuY3Rpb24oaywgaSl7cmV0dXJuIGRhdGFba10ucXVhcnRpbGVzW3F1YXJ0aWxlS2V5c1txdWFydGlsZUtleXMubGVuZ3RoIC0gMV1dfSkpXG4gICAgdmFyIGV4dGVudCA9IFtNYXRoLm1pbiguLi5taW4pIC0gZG9tYWluUGFkZGluZywgTWF0aC5tYXgoLi4ubWF4KSArIGRvbWFpblBhZGRpbmddXG4gICAgLy8gY29uc29sZS5sb2coZXh0ZW50LCB2aW9saW5WYWx1ZXMsIG9yZGVyZWQpXG5cbiAgICAvLyBzZXQgdGhlIHNjYWxlXG4gICAgc2NhbGUuZG9tYWluKGV4dGVudCkucmFuZ2UoaG9yaXpvbnRhbFEgPyBbMCxzcGFjZVldIDogWzAsIHNwYWNlWF0pXG4gICAgdmFyIHNwYWNlID0gaG9yaXpvbnRhbFEgPyBzcGFjZVggOiBzcGFjZVlcbiAgICAvLyBjYWxjdWxhdGUgb2JqZWN0IHNpemVcbiAgICBvYmplY3RTaXplID0gY2FsY3VsYXRlV2lkdGhPZk9iamVjdChzcGFjZSwgbnVtYmVyT2ZPYmplY3RzLCBtaW5PYmplY3RTaXplLCBtYXhPYmplY3RTaXplLCBvYmplY3RTcGFjZXIsIG92ZXJmbG93USlcbiAgICAvLyBjYWxjdWxhdGUgc3BhY2VyIHNpemUgaWYgbmVlZGVkXG4gICAgc3BhY2VyU2l6ZSA9IGNhbGN1bGF0ZVdpZHRoT2ZTcGFjZXIob3JkZXJlZCwgc3BhY2UsIG9iamVjdFNpemUsIG51bWJlck9mT2JqZWN0cywgb2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgLy8gbWFrZSB0aGUgbmVzdGVkIGdyb3Vwc1xuICAgIHZhciBzcGFjZXJGdW5jdGlvbiA9IGdyb3VwaW5nU3BhY2VyKClcbiAgICAuaG9yaXpvbnRhbFEoaG9yaXpvbnRhbFEpLnNjYWxlKHNjYWxlKS5tb3ZlYnkoJ2NhdGVnb3J5JykubnVtYmVyT2ZPYmplY3RzKG51bWJlck9mT2JqZWN0cylcbiAgICAub2JqZWN0Q2xhc3Mob2JqZWN0Q2xhc3MpLm9iamVjdFNpemUob2JqZWN0U2l6ZSkuc3BhY2VyU2l6ZShzcGFjZXJTaXplKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlRnVuYyhlYXNlRnVuYylcbiAgICAubmFtZXNwYWNlKG5hbWVzcGFjZSlcblxuICAgIC8vIG1vdmUgc3R1ZmZcbiAgICBzcGFjZXJGdW5jdGlvbihjb250YWluZXIsIG9yZGVyZWQsIDApXG4gICAgLy8gY29uc29sZS5sb2codmlvbGluS2V5cywgb3JkZXJlZCwgY29udGFpbmVyLnNlbGVjdEFsbCgnZzpub3QoLnRvLXJlbW92ZSkuJytvYmplY3RDbGFzcykubm9kZXMoKSlcblxuICAgIC8vIGZvciBjb2xvciBmdW5jdGlvblxuICAgIHZhciBwYXJlbnRJbmRleEFycmF5ID0gW11cbiAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnOm5vdCgudG8tcmVtb3ZlKS4nK29iamVjdENsYXNzKVxuICAgIC5lYWNoKGZ1bmN0aW9uKGQsIGkpe2lmIChoYXNRKHZpb2xpbktleXMsIGQpKXsgcGFyZW50SW5kZXhBcnJheS5wdXNoKE51bWJlcihkMy5zZWxlY3QodGhpcykuYXR0cigncGFyZW50LWluZGV4JykpKX19KVxuXG4gICAgLy8gdXBkYXRlIGNvbG9yIGZ1bmN0aW9uXG4gICAgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24uY29sb3JCeSgpID09ICdpbmRleCdcbiAgICA/IGNvbG9yRnVuY3Rpb24uZGF0YUV4dGVudChbMCwgTWF0aC5tYXgoLi4ucGFyZW50SW5kZXhBcnJheSldKVxuICAgIDogY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50KGV4dGVudClcblxuICAgIC8qIHZpb2xpaW4gc3BlY2lmaWMgbmVlZHMgKi9cblxuXG4gICAgdmFyIGZyZXF1ZW5jeU1heCA9IE1hdGgubWF4KC4uLltdLmNvbmNhdCguLi52aW9saW5LZXlzLm1hcChmdW5jdGlvbihrLCBpKXtyZXR1cm4gZDMubWF4KGRhdGFba10uZnJlcXVlbmNpZXMpfSkpKVxuICAgIHZhciB2U2NhbGUgPSBkMy5zY2FsZUxpbmVhcigpLmRvbWFpbihbMCwgZnJlcXVlbmN5TWF4XSkucmFuZ2UoWzAsIG9iamVjdFNpemUgLyAyXSlcblxuICAgIHZhciBsQXJlYSA9IGQzLmxpbmUoKVxuICAgIC54KGZ1bmN0aW9uKGQsIGkpeyByZXR1cm4gaG9yaXpvbnRhbFEgPyAtdlNjYWxlKGQueCkgOiBzY2FsZShkLngpfSlcbiAgICAueShmdW5jdGlvbihkLCBpKXsgcmV0dXJuIGhvcml6b250YWxRID8gc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKGQueSkgOiAtdlNjYWxlKGQueSl9KVxuICAgIC5jdXJ2ZShkMy5jdXJ2ZUJhc2lzKVxuICAgIHZhciByQXJlYSA9IGQzLmxpbmUoKVxuICAgIC54KGZ1bmN0aW9uKGQsIGkpeyByZXR1cm4gaG9yaXpvbnRhbFEgPyB2U2NhbGUoZC54KSA6IHNjYWxlKGQueCl9KVxuICAgIC55KGZ1bmN0aW9uKGQsIGkpeyByZXR1cm4gaG9yaXpvbnRhbFEgPyBzY2FsZShleHRlbnRbMV0pIC0gc2NhbGUoZC55KSA6IHZTY2FsZShkLnkpfSlcbiAgICAuY3VydmUoZDMuY3VydmVCYXNpcylcblxuXG5cblxuXG5cbiAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnOm5vdCgudG8tcmVtb3ZlKS4nK29iamVjdENsYXNzKS5lYWNoKGZ1bmN0aW9uKGtleSwgaSl7XG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKSxcbiAgICAgIGN1cnJlbnREYXRhID0gZGF0YVtrZXldXG4gICAgICAvLyBuZWVkZWQgYmVjYXVzZSBidWcgaW4gc2VsZWN0aW5nIC50by1yZW1vdmVcbiAgICAgIGlmICghaGFzUSh2aW9saW5LZXlzLCBrZXkpKSB7cmV0dXJufVxuICAgICAgdmFyXG4gICAgICBpID0gdC5hdHRyKCdwYXJlbnQtaW5kZXgnKSA9PSB1bmRlZmluZWQgPyBpIDogdC5hdHRyKCdwYXJlbnQtaW5kZXgnKSxcbiAgICAgIGZpbGxDb2xvciA9IGNvbG9yRnVuY3Rpb24oa2V5LCBjdXJyZW50RGF0YSwgaSwgJ2ZpbGwnKSwgLy8gcHJldmVudCBkdXBsaWNhdGUgY29tcHV0YXRpb25cbiAgICAgIHN0cm9rZUNvbG9yID0gY29sb3JGdW5jdGlvbihrZXksIGN1cnJlbnREYXRhLCBpLCAnc3Ryb2tlJyksXG4gICAgICBhcmVhID0gc2FmZVNlbGVjdCh0LCAnZycsICdhcmVhJyksXG4gICAgICBsYSA9IHNhZmVTZWxlY3QoYXJlYSwgJ3BhdGgnLCAnbGVmdCcpLFxuICAgICAgcmEgPSBzYWZlU2VsZWN0KGFyZWEsICdwYXRoJywgJ3JpZ2h0JyksXG4gICAgICBxdWFydHMgPSBzYWZlU2VsZWN0KHQsICdnJywgJ3F1YXJ0cycpLFxuICAgICAgbHEzID0gc2FmZVNlbGVjdChxdWFydHMsICdsaW5lJywgJ3EzJyksXG4gICAgICBscTEgPSBzYWZlU2VsZWN0KHF1YXJ0cywgJ2xpbmUnLCAncTEnKSxcbiAgICAgIHEzID0gY3VycmVudERhdGEucXVhcnRpbGVzW3F1YXJ0aWxlS2V5c1szXV0sXG4gICAgICBxMiA9IGN1cnJlbnREYXRhLnF1YXJ0aWxlc1txdWFydGlsZUtleXNbMl1dLFxuICAgICAgcTEgPSBjdXJyZW50RGF0YS5xdWFydGlsZXNbcXVhcnRpbGVLZXlzWzFdXVxuXG4gICAgICB0LmF0dHIoJ3RyYW5zZm9ybScsIGhvcml6b250YWxRID8gJ3RyYW5zbGF0ZSgnK29iamVjdFNpemUgLyAyKycsMCknIDogJ3RyYW5zbGF0ZSgwLCcrb2JqZWN0U2l6ZSAvIDIrJyknICApXG4gICAgICAvLyBkcmF3IGN1cnZlXG4gICAgICBsYS50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5hdHRyKCdkJywgZnVuY3Rpb24oZGQsIGlpKXsgcmV0dXJuIGxBcmVhKGN1cnJlbnREYXRhLmNvbnRvdXIpfSlcbiAgICAgIC5hdHRyKCdmaWxsJywgZmlsbENvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZScsIHN0cm9rZUNvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIG9iamVjdFN0cm9rZVdpZHRoKVxuXG4gICAgICByYS50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5hdHRyKCdkJywgZnVuY3Rpb24oZGQsIGlpKXsgcmV0dXJuIHJBcmVhKGN1cnJlbnREYXRhLmNvbnRvdXIpfSlcbiAgICAgIC5hdHRyKCdmaWxsJywgZmlsbENvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZScsIHN0cm9rZUNvbG9yKVxuICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIG9iamVjdFN0cm9rZVdpZHRoKVxuXG4gICAgICBhcmVhLm5vZGUoKS5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW92ZXInLCBmdW5jdGlvbihkZCwgaWkpe1xuICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnLicrb2JqZWN0Q2xhc3MpLnN0eWxlKCdvcGFjaXR5JywgMC4yKVxuICAgICAgICB0LnN0eWxlKCdvcGFjaXR5JywgMSlcbiAgICAgICAgbGEuYXR0cignc3Ryb2tlLXdpZHRoJyxvYmplY3RTdHJva2VXaWR0aCoyKVxuICAgICAgICByYS5hdHRyKCdzdHJva2Utd2lkdGgnLG9iamVjdFN0cm9rZVdpZHRoKjIpXG4gICAgICB9KVxuICAgICAgYXJlYS5ub2RlKCkuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VvdXQnLCBmdW5jdGlvbihkZCwgaWkpe1xuICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnLicrb2JqZWN0Q2xhc3MpLnN0eWxlKCdvcGFjaXR5JywgMSlcbiAgICAgICAgbGEuYXR0cignc3Ryb2tlLXdpZHRoJyxvYmplY3RTdHJva2VXaWR0aClcbiAgICAgICAgcmEuYXR0cignc3Ryb2tlLXdpZHRoJyxvYmplY3RTdHJva2VXaWR0aClcbiAgICAgIH0pXG5cbiAgICAgIGlmIChwb2ludHNRKSB7XG4gICAgICAgIHZhciBwdHNDb250YWluZXIgPSBzYWZlU2VsZWN0KHQsICdnJywgJ3BvaW50cycpXG4gICAgICAgIHZhciBwdHMgPSBwdHNDb250YWluZXIuc2VsZWN0QWxsKCcucG9pbnQnKS5kYXRhKGN1cnJlbnREYXRhLnBvaW50S2V5cylcbiAgICAgICAgcHRzLm9uKCdtb3VzZW92ZXInLCBudWxsKVxuXG5cbiAgICAgICAgdmFyIHB0c0V4aXQgPSBwdHMuZXhpdCgpLnRyYW5zaXRpb24oKS5lYXNlKGVhc2VGdW5jKS5kdXJhdGlvbih0cmFuc2l0aW9uRHVyYXRpb24pXG4gICAgICAgIC5hdHRyKCdyJywgMClcbiAgICAgICAgLmF0dHIoJ2N5JywgaG9yaXpvbnRhbFEgPyBzY2FsZShleHRlbnRbMV0pIC0gc2NhbGUocTIpIDogdlNjYWxlKDApKVxuICAgICAgICAuYXR0cignY3gnLCBob3Jpem9udGFsUSA/IHZTY2FsZSgwKSA6IHNjYWxlKHEyKSkucmVtb3ZlKClcblxuICAgICAgICB2YXIgcHRzRW50ZXIgPSBwdHMuZW50ZXIoKS5hcHBlbmQoJ2NpcmNsZScpLmF0dHIoJ2NsYXNzJywgJ3BvaW50JykuYXR0cigncicsIDApXG4gICAgICAgIC5hdHRyKCdjeCcsIGhvcml6b250YWxRID8gMCA6IHNjYWxlKHEyKSlcbiAgICAgICAgLmF0dHIoJ2N5JywgaG9yaXpvbnRhbFEgPyBzY2FsZShxMikgOiAwKVxuXG4gICAgICAgIHB0cyA9IHB0cy5tZXJnZShwdHNFbnRlcilcblxuICAgICAgICAvLyBjb25zb2xlLmxvZyhwb2ludHNUb29sdGlwLmhlYWRlcigpKVxuXG4gICAgICAgIHZhciBwVFRpcHMgPSBUVGlwKCkuc2VsZWN0aW9uKHB0cykuZGF0YSh2aW9saW5Qb2ludHNFeHRyYWN0b3Ioa2V5LCBjdXJyZW50RGF0YSkpXG4gICAgICAgIC5oZWFkZXIocG9pbnRzVG9vbHRpcC5oZWFkZXIoKSlcbiAgICAgICAgLmtleXMocG9pbnRzVG9vbHRpcC5rZXlzKCkpXG4gICAgICAgIC52YWx1ZXMocG9pbnRzVG9vbHRpcC52YWx1ZXMoKSlcblxuICAgICAgICBwVFRpcHMoKVxuXG4gICAgICAgIHZhciBwTWluID0gZDMubWluKGN1cnJlbnREYXRhLnBvaW50VmFsdWVzKSwgcE1heCA9IGQzLm1heChjdXJyZW50RGF0YS5wb2ludFZhbHVlcylcblxuXG5cbiAgICAgICAgcHRzLnRyYW5zaXRpb24oKS5kdXJhdGlvbih0cmFuc2l0aW9uRHVyYXRpb24pLmVhc2UoZWFzZUZ1bmMpLmF0dHIoJ3InLCBwb2ludFJhZGl1cylcbiAgICAgICAgLmF0dHIoJ2N5JywgZnVuY3Rpb24ocG9pbnRLZXksIGlpKXtcbiAgICAgICAgICB2YXIgZGQgPSBjdXJyZW50RGF0YS5wb2ludFZhbHVlc1tpaV1cbiAgICAgICAgICBpZiAoaG9yaXpvbnRhbFEpIHsgcmV0dXJuIHNjYWxlKGV4dGVudFsxXSkgLSBzY2FsZShkZCkgfVxuICAgICAgICAgIHZhciBqID0gd2hpY2hCaW4oY3VycmVudERhdGEuYmlubmVkLCBkZClcbiAgICAgICAgICB2YXIgciA9IE1hdGgucmFuZG9tKClcbiAgICAgICAgICB2YXIgbiA9IHZTY2FsZShyICogY3VycmVudERhdGEuZnJlcXVlbmNpZXNbal0gKiAwLjUpXG4gICAgICAgICAgdmFyIGsgPSBNYXRoLnJhbmRvbSgpID4gMC41ID8gbiA6IC1uXG4gICAgICAgICAgcmV0dXJuIGtcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ2N4JywgZnVuY3Rpb24ocG9pbnRLZXksIGlpKXtcbiAgICAgICAgICB2YXIgZGQgPSBjdXJyZW50RGF0YS5wb2ludFZhbHVlc1tpaV1cbiAgICAgICAgICBpZiAoaG9yaXpvbnRhbFEpIHtcbiAgICAgICAgICAgIHZhciBqID0gd2hpY2hCaW4oY3VycmVudERhdGEuYmlubmVkLCBkZClcbiAgICAgICAgICAgIHZhciByID0gTWF0aC5yYW5kb20oKVxuICAgICAgICAgICAgdmFyIG4gPSB2U2NhbGUociAqIGN1cnJlbnREYXRhLmZyZXF1ZW5jaWVzW2pdICogMC41KVxuICAgICAgICAgICAgdmFyIGsgPSBNYXRoLnJhbmRvbSgpID4gMC41ID8gbiA6IC1uXG4gICAgICAgICAgICByZXR1cm4ga1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gc2NhbGUoZGQpXG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCdzdHJva2UnLCBmdW5jdGlvbihkZCwgaWkpIHsgdmFyIGRkID0gY3VycmVudERhdGEucG9pbnRWYWx1ZXNbaWldOyByZXR1cm4gcG9pbnRDb2xvckZ1bmMoZGQsICdzdHJva2UnLCBzdHJva2VDb2xvciwgcE1pbiwgcE1heCkgfSlcbiAgICAgICAgLmF0dHIoJ2ZpbGwnICAsIGZ1bmN0aW9uKGRkLCBpaSkgeyB2YXIgZGQgPSBjdXJyZW50RGF0YS5wb2ludFZhbHVlc1tpaV07IHJldHVybiBwb2ludENvbG9yRnVuYyhkZCwgJ2ZpbGwnICAsIHN0cm9rZUNvbG9yLCBwTWluLCBwTWF4KSB9KVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgcG9pbnRTdHJva2VXaWR0aClcblxuICAgICAgICBwdHNDb250YWluZXIuc2VsZWN0QWxsKCdjaXJjbGUucG9pbnQnKS5vbignbW91c2VvdmVyJywgZnVuY3Rpb24oZGQsIGlpKXtcbiAgICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnLicrb2JqZWN0Q2xhc3MpLnN0eWxlKCdvcGFjaXR5JywgMC4yKVxuICAgICAgICAgIHQuc3R5bGUoJ29wYWNpdHknLCAxKVxuICAgICAgICAgIGxhLmF0dHIoJ3N0cm9rZS13aWR0aCcsb2JqZWN0U3Ryb2tlV2lkdGgqMilcbiAgICAgICAgICByYS5hdHRyKCdzdHJva2Utd2lkdGgnLG9iamVjdFN0cm9rZVdpZHRoKjIpXG5cbiAgICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCcucG9pbnQnKS5zdHlsZSgnb3BhY2l0eScsIDAuMilcbiAgICAgICAgICBkMy5zZWxlY3QodGhpcykuc3R5bGUoJ29wYWNpdHknLCAxKS5hdHRyKCdyJywgcG9pbnRSYWRpdXMgKiAyKS5hdHRyKCdzdHJva2Utd2lkdGgnLHBvaW50U3Ryb2tlV2lkdGgqMilcbiAgICAgICAgfSlcbiAgICAgICAgcHRzQ29udGFpbmVyLnNlbGVjdEFsbCgnY2lyY2xlLnBvaW50Jykub24oJ21vdXNlb3V0JywgZnVuY3Rpb24oZGQsIGlpKXtcbiAgICAgICAgICB2YXIgZSA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdTVkdFdmVudHMnKVxuICAgICAgICAgIGUuaW5pdEV2ZW50KCdtb3VzZW91dCcsdHJ1ZSx0cnVlKTtcbiAgICAgICAgICBhcmVhLm5vZGUoKS5kaXNwYXRjaEV2ZW50KGUpXG5cbiAgICAgICAgICBjb250YWluZXIuc2VsZWN0QWxsKCcucG9pbnQnKS5zdHlsZSgnb3BhY2l0eScsIDEpXG4gICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ3N0cm9rZS13aWR0aCcsIHBvaW50U3Ryb2tlV2lkdGgpLmF0dHIoJ3InLCBwb2ludFJhZGl1cylcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBjVi5zZWxlY3RBbGwoJy5wb2ludCcpXG4gICAgICAgIC50cmFuc2l0aW9uKCkuZHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlKGVhc2VGdW5jKVxuICAgICAgICAuYXR0cigncicsIDApXG4gICAgICAgIC5hdHRyKCdjeScsIGhvcml6b250YWxRID8gc2NhbGUoZXh0ZW50WzFdKSAtIHNjYWxlKHEyKSA6IHZTY2FsZSgwKSlcbiAgICAgICAgLmF0dHIoJ2N4JywgaG9yaXpvbnRhbFEgPyB2U2NhbGUoMCkgOiBzY2FsZShxMikpXG4gICAgICAgIC5yZW1vdmUoKVxuICAgICAgfVxuXG5cbiAgICB9KVxuXG5cbiAgICB0b29sdGlwLnNlbGVjdGlvbihjb250YWluZXIuc2VsZWN0QWxsKCdnOm5vdCgudG8tcmVtb3ZlKS4nK29iamVjdENsYXNzICsgJyAuYXJlYScpKVxuICAgIGlmICh0b29sdGlwLmRhdGEoKSA9PSB1bmRlZmluZWQpIHt0b29sdGlwLmRhdGEoZGF0YSl9XG4gICAgdG9vbHRpcCgpXG4gICAgaWYgKHRvb2x0aXAudmFsdWVzKCkgPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0b29sdGlwLnZhbHVlcyhbXG4gICAgICAgIGZ1bmN0aW9uKGN1cnJlbnREYXRhLCB0b29sdGlwS2V5KXsgcmV0dXJuIGN1cnJlbnREYXRhWydxdWFydGlsZXMnXVt0b29sdGlwS2V5XSB9LFxuICAgICAgICBmdW5jdGlvbihjdXJyZW50RGF0YSwgdG9vbHRpcEtleSl7IHJldHVybiBjdXJyZW50RGF0YVsncXVhcnRpbGVzJ11bdG9vbHRpcEtleV0gfSxcbiAgICAgICAgZnVuY3Rpb24oY3VycmVudERhdGEsIHRvb2x0aXBLZXkpeyByZXR1cm4gY3VycmVudERhdGFbJ3F1YXJ0aWxlcyddW3Rvb2x0aXBLZXldIH0sXG4gICAgICAgIGZ1bmN0aW9uKGN1cnJlbnREYXRhLCB0b29sdGlwS2V5KXsgcmV0dXJuIGN1cnJlbnREYXRhWydxdWFydGlsZXMnXVt0b29sdGlwS2V5XSB9LFxuICAgICAgICBmdW5jdGlvbihjdXJyZW50RGF0YSwgdG9vbHRpcEtleSl7IHJldHVybiBjdXJyZW50RGF0YVsncXVhcnRpbGVzJ11bdG9vbHRpcEtleV0gfVxuICAgICAgXSlcblxuICAgIH1cblxuICB9XG5cbiAgcmV0dXJuIHZpb2xpblxufVxuXG5cblxuXG5cbi8qKlxuKiBQcm9kdWNlcyB0aGUgZnVuY3Rpb24gd2hpY2ggbWFuaXB1bGF0ZXMgdGhlIHZpb2xpbiBkYXRhIHRvIGhhdmUgdmFsdWVzIG5lZWRlZFxuKiBmb3IgcmVuZGVyaW5nIHRoZSB2aW9saW5zIGFzIHN2Zy5cbiogQHJldHVybnMge2Z1bmN0aW9ufSBjYWxjdWxhdGVWaW9saW5WYWx1ZXNcbiogQG5hbWVzcGFjZSBuZWVkZWRWaW9saW5WYWx1ZXNcbiovXG5mdW5jdGlvbiBuZWVkZWRWaW9saW5WYWx1ZXMoKSB7XG4gIHZhclxuICAvKipcbiAgKiBXaGV0aGVyIG9yIG5vdCB0aGUgb3JpZW50YXRpb24gb2YgdGhlIHZpb2xpbnMgYXJlIGhvcml6b250YWxcbiAgKiAoc2VlIHtAbGluayB2aW9saW4jb3JpZW50fSlcbiAgKiBAcGFyYW0ge09iamVjdH0gW2hvcml6b250YWxRPXRydWVdXG4gICogQG1lbWJlcm9mIG5lZWRlZFZpb2xpblZhbHVlcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgaG9yaXpvbnRhbFEgPSB0cnVlLFxuICAvKipcbiAgKiBLZXlzIHRvIGJlIHB1dCBpbnRvIHRoZSBxdWFydGlsZXMgaWYgdGhleSBuZWVkIHRvIGJlIGNhbGN1bGF0ZWQuXG4gICogKHNlZSB7QGxpbmsgdmlvbGluI3F1YXJ0aWxlS2V5c30pXG4gICogQHBhcmFtIHtPYmplY3R9IFtxdWFydGlsZUtleXM9WydRMCcsICdRMScsICdRMicsICdRMycsICdRNCddXVxuICAqIEBtZW1iZXJvZiBuZWVkZWRWaW9saW5WYWx1ZXMjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHF1YXJ0aWxlS2V5cyA9IFsnUTAnLCAnUTEnLCAnUTInLCAnUTMnLCAnUTQnXSxcbiAgLyoqXG4gICogRnVuY3Rpb24gd2hpY2ggZ2l2ZW4gdGhlIGtleSBvZiB0aGUgdmlvbGluIGFuZCB0aGF0IGtleSdzIGFzc29jaWF0ZWQgdmFsdWVcbiAgKiByZXR1cm5zIHRoZSBvYmplY3QgY29uc2l0aW5nIG9mIHRoZSBwb2ludHMgb2YgdGhlIHZpb2xpblxuICAqIChzZWUge0BsaW5rIHZpb2xpbiN2aW9saW5Qb2ludHNFeHRyYWN0b3J9KVxuICAqIEBwYXJhbSB7T2JqZWN0fSBbdmlvbGluUG9pbnRzRXh0cmFjdG9yPWZ1bmN0aW9uKHZpb2xpbktleSwgdmlvbGluRGF0YSkgeyByZXR1cm4gdmlvbGluRGF0YS5wb2ludHMgfV1cbiAgKiBAbWVtYmVyb2YgbmVlZGVkVmlvbGluVmFsdWVzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2aW9saW5Qb2ludHNFeHRyYWN0b3IsXG4gIC8qKlxuICAqIEZ1bmN0aW9uIHdoaWNoIGdpdmVuIHRoZSBrZXkgb2YgdGhlIGN1cnJlbnQgcG9pbnQgYW5kIHRoZSBvYmplY3Qgb2YgcG9pbnRzIGZvciB0aGVcbiAgKiB2aW9saW4sIHJldHVybnMgdGhlIG51bWVyaWNhbCB2YWx1ZSBvZiB0aGUgcG9pbnRcbiAgKiAoc2VlIHtAbGluayB2aW9saW4jdmlvbGluUG9pbnRWYWx1ZUV4dHJhY3Rvcn0pXG4gICogQHBhcmFtIHtPYmplY3R9IFt2aW9saW5Qb2ludFZhbHVlRXh0cmFjdG9yPWZ1bmN0aW9uKHZpb2xpblBvaW50S2V5LCB2aW9saW5Qb2ludERhdGEpIHsgcmV0dXJuIHZpb2xpblBvaW50RGF0YVt2aW9saW5Qb2ludEtleV0udmFsdWUgfV1cbiAgKiBAbWVtYmVyb2YgbmVlZGVkVmlvbGluVmFsdWVzI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2aW9saW5Qb2ludFZhbHVlRXh0cmFjdG9yXG5cblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGhvcml6b250YWxRXG4gICAqIChzZWUge0BsaW5rIHZpb2xpbiNvcmllbnR9KVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtjYWxjdWxhdGVWaW9saW5WYWx1ZXMgfCBib29sZWFufVxuICAgKiBAbWVtYmVyb2YgY2FsY3VsYXRlVmlvbGluVmFsdWVzXG4gICAqIEBwcm9wZXJ0eVxuICAgKlxuICAgKiBieSBkZWZhdWx0IGhvcml6b250YWxRID0gdHJ1ZVxuICAgKi9cbiAgY2FsY3VsYXRlVmlvbGluVmFsdWVzLmhvcml6b250YWxRID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChob3Jpem9udGFsUT1fLCBjYWxjdWxhdGVWaW9saW5WYWx1ZXMpIDogaG9yaXpvbnRhbFEgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHF1YXJ0aWxlS2V5c1xuICAgKiAoc2VlIHtAbGluayB2aW9saW4jcXVhcnRpbGVLZXlzfSlcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2NhbGN1bGF0ZVZpb2xpblZhbHVlcyB8IHN0cmluZ1tdfVxuICAgKiBAbWVtYmVyb2YgY2FsY3VsYXRlVmlvbGluVmFsdWVzXG4gICAqIEBwcm9wZXJ0eVxuICAgKlxuICAgKiBieSBkZWZhdWx0IHF1YXJ0aWxlS2V5cyA9IFtcIlEwXCIsXCJRMVwiLFwiUTJcIixcIlEzXCIsXCJRNFwiXVxuICAgKi9cbiAgY2FsY3VsYXRlVmlvbGluVmFsdWVzLnF1YXJ0aWxlS2V5cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocXVhcnRpbGVLZXlzPV8sIGNhbGN1bGF0ZVZpb2xpblZhbHVlcykgOiBxdWFydGlsZUtleXMgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHZpb2xpblBvaW50c0V4dHJhY3RvclxuICAgKiAoc2VlIHtAbGluayB2aW9saW4jdmlvbGluUG9pbnRzRXh0cmFjdG9yfSlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2NhbGN1bGF0ZVZpb2xpblZhbHVlcyB8IGZ1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgY2FsY3VsYXRlVmlvbGluVmFsdWVzXG4gICAqIEBwcm9wZXJ0eVxuICAgKlxuICAgKiBieSBkZWZhdWx0IHZpb2xpblBvaW50c0V4dHJhY3RvciA9IGZ1bmN0aW9uKHZpb2xpbktleSwgdmlvbGluRGF0YSkgeyByZXR1cm4gdmlvbGluRGF0YS5wb2ludHMgfVxuICAgKi9cbiAgY2FsY3VsYXRlVmlvbGluVmFsdWVzLnZpb2xpblBvaW50c0V4dHJhY3RvciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodmlvbGluUG9pbnRzRXh0cmFjdG9yPV8sIGNhbGN1bGF0ZVZpb2xpblZhbHVlcykgOiB2aW9saW5Qb2ludHNFeHRyYWN0b3IgfVxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIHZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3JcbiAgICogKHNlZSB7QGxpbmsgdmlvbGluI3Zpb2xpblBvaW50VmFsdWVFeHRyYWN0b3J9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7Y2FsY3VsYXRlVmlvbGluVmFsdWVzIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBjYWxjdWxhdGVWaW9saW5WYWx1ZXNcbiAgICogQHByb3BlcnR5XG4gICAqXG4gICAqIGJ5IGRlZmF1bHQgdmlvbGluUG9pbnRWYWx1ZUV4dHJhY3RvciA9IGZ1bmN0aW9uKHZpb2xpblBvaW50S2V5LCB2aW9saW5Qb2ludERhdGEpIHsgcmV0dXJuIHZpb2xpblBvaW50RGF0YVt2aW9saW5Qb2ludEtleV0udmFsdWUgfVxuICAgKi9cbiAgY2FsY3VsYXRlVmlvbGluVmFsdWVzLnZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3I9XywgY2FsY3VsYXRlVmlvbGluVmFsdWVzKSA6IHZpb2xpblBvaW50VmFsdWVFeHRyYWN0b3IgfVxuXG5cbiAgLyoqXG4gICogVGhlIGZ1bmN0aW9uIHByb2R1Y2VkIGJ5IG5lZWRlZFZpb2xpblZhbHVlcy5cbiAgKlxuICAqIEFkZHMgdGhlIGRhdGEgbmVlZCB0byByZW5kZXIgdGhlIHZpb2xpbiBhcyBhbiBzdmdcbiAgKiBAcGFyYW0ge3N0cmluZ30gdmlvbGluS2V5IHRoZSBrZXkgb2YgdGhlIGN1cnJlbnQgdmlvbGluXG4gICogQHBhcmFtIHtvYmplY3R9IGRhdGEgdGhlIG9iamVjdCBjb25zaXN0aW5nIG9mIHZpb2xpbktleSAtIHZhbHVlcyAodmlvbGluIGRhdGEpIHBhaXJzXG4gICogQHJldHVybnMge25vbmV9IHRoaXMgZnVuY3Rpb24gbWFuaXB1bGF0ZXMgdGhlIHBhc3NlZCBkYXRhIG9iamVjdCBhZGRpbmcgdGhlIGZvbGxvd2luZyBrZXlzXG4gICpcbiAgKiBkYXRhW3Zpb2xpbktleV0uYmlubmVkIC8vIHRoZSBiaW5uZWQgdmFsdWVzIG9mIHRoZSBwb2ludHNcbiAgKlxuICAqIGRhdGFbdmlvbGluS2V5XS5mcmVxdWVuY2llcyAvLyB0aGUgbGlzdCBjb25zaXN0aW5nIG9mIHRoZSBsZW5ndGggb2YgZWFjaCBiaW5cbiAgKlxuICAqIGRhdGFbdmlvbGluS2V5XS5jb250b3VyIC8vIHRoZSBwb2ludHMgZGVwaWN0aW5nIHRoZSBjb250b3VyIG9mIDEvMiBvZiB0aGUgdmlvbGluXG4gICpcbiAgKiBkYXRhW3Zpb2xpbktleV0ucXVhcnRpbGVzIC8vIHRoZSBxdWFydGlsZXMgb2YgdGhlIHBvaW50cycgdmFsdWVzXG4gICpcbiAgKiBkYXRhW3Zpb2xpbktleV0ucG9pbnRLZXlzIC8vIHRoZSBrZXlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgcG9pbnRzXG4gICpcbiAgKiBkYXRhW3Zpb2xpbktleV0ucG9pbnRWYWx1ZXMgLy8gdGhlIG51bWVyaWNhbCB2YWx1ZXMgb2YgdGhlIHBvaW50c1xuICAqXG4gICogQG1lbWJlcm9mIG5lZWRlZFZpb2xpblZhbHVlcyNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZnVuY3Rpb24gY2FsY3VsYXRlVmlvbGluVmFsdWVzKHZpb2xpbktleSwgZGF0YSkge1xuICAgIC8vIGRhdGEgZm9yIHRoZSBjdXJyZW50IHZpb2xpblxuICAgIHZhciB2aW9saW5EYXRhID0gZGF0YVt2aW9saW5LZXldO1xuICAgIC8vIHRoZSBvYmplY3Qgb2YgcG9pbnRzXG4gICAgdmFyIHZpb2xpblBvaW50cyA9IHZpb2xpblBvaW50c0V4dHJhY3Rvcih2aW9saW5LZXksIHZpb2xpbkRhdGEpO1xuICAgIC8vXG4gICAgdmFyIHZpb2xpblBvaW50c0tleXMgPSBkMy5rZXlzKHZpb2xpblBvaW50cyk7XG4gICAgLy8gdGhlIG51bWVyaWNhbCB2YWx1ZXMgb2YgdGhvc2UgcG9pbnRzXG4gICAgdmFyIHZpb2xpblBvaW50c1ZhbHVlcyA9IHZpb2xpblBvaW50c0tleXMubWFwKGZ1bmN0aW9uKHBrLCBpKXtyZXR1cm4gdmlvbGluUG9pbnRWYWx1ZUV4dHJhY3RvcihwaywgdmlvbGluUG9pbnRzKX0pXG5cbiAgICAvLyBxdWFydGlsZXMgb2YgdGhvc2UgcG9pbnRzXG4gICAgdmFyIHBvaW50UXVhcnRpbGVzID0gcXVhcnRpbGVzKHZpb2xpblBvaW50c1ZhbHVlcywgcXVhcnRpbGVLZXlzKVxuXG4gICAgLy8gYmlubmVkIHBvaW50c1xuICAgIHZhciBiaW5uZWQgPSBkMy5oaXN0b2dyYW0oKSh2aW9saW5Qb2ludHNWYWx1ZXMpXG4gICAgLy8gbGVuZ3RoIG9mIGJpbnNcbiAgICB2YXIgZnJlcXVlbmNpZXMgPSBiaW5uZWQubWFwKGJpbj0+YmluLmxlbmd0aClcbiAgICAvLyBtaW4gYW5kIG1heCBjb3VudG91ciBwb2ludHMgZm9yIG5pY2UgZHJhd2luZ3NcbiAgICB2YXIgbWluQ29udG91clBvaW50ID0gaG9yaXpvbnRhbFEgPyB7eDogMCwgeTogZDMubWluKHZpb2xpblBvaW50c1ZhbHVlcyl9IDogIHt4OiBkMy5taW4odmlvbGluUG9pbnRzVmFsdWVzKSwgeTogMH1cbiAgICB2YXIgbWF4Q29udG91clBvaW50ID0gaG9yaXpvbnRhbFEgPyB7eDogMCwgeTogZDMubWF4KHZpb2xpblBvaW50c1ZhbHVlcyl9IDogIHt4OiBkMy5tYXgodmlvbGluUG9pbnRzVmFsdWVzKSwgeTogMH1cbiAgICB2YXIgdmlvbGluQ29udG91clBvaW50cyA9IGJpbm5lZC5tYXAoZnVuY3Rpb24oYmluLCBpKSB7XG4gICAgICAgIHJldHVybiBob3Jpem9udGFsUVxuICAgICAgICA/IHt5OiAoYmluLmxlbmd0aCkgPyBkMy5tZWRpYW4oYmluKTogZDMubWVkaWFuKFtiaW4ueDAsIGJpbi54MV0pLCB4OiBmcmVxdWVuY2llc1tpXX1cbiAgICAgICAgOiB7eDogKGJpbi5sZW5ndGgpID8gZDMubWVkaWFuKGJpbik6IGQzLm1lZGlhbihbYmluLngwLCBiaW4ueDFdKSwgeTogZnJlcXVlbmNpZXNbaV19XG4gICAgICB9KVxuICAgIC8vIHBvaW50cyBhbG9uZyB3aGljaCB0byBkcmF3IHRoZSB2aW9saW4gc2hwZVxuICAgIHZpb2xpbkNvbnRvdXJQb2ludHMgPSBbbWluQ29udG91clBvaW50XS5jb25jYXQodmlvbGluQ29udG91clBvaW50cykuY29uY2F0KFttYXhDb250b3VyUG9pbnRdKVxuXG4gICAgLy8gc2V0IGRhdGFcbiAgICB2aW9saW5EYXRhLmJpbm5lZCA9IGJpbm5lZDtcbiAgICB2aW9saW5EYXRhLmZyZXF1ZW5jaWVzID0gZnJlcXVlbmNpZXNcbiAgICB2aW9saW5EYXRhLmNvbnRvdXIgPSB2aW9saW5Db250b3VyUG9pbnRzXG4gICAgdmlvbGluRGF0YS5xdWFydGlsZXMgPSBwb2ludFF1YXJ0aWxlc1xuICAgIHZpb2xpbkRhdGEucG9pbnRLZXlzID0gdmlvbGluUG9pbnRzS2V5c1xuICAgIHZpb2xpbkRhdGEucG9pbnRWYWx1ZXMgPSB2aW9saW5Qb2ludHNWYWx1ZXNcbiAgfVxuXG4gIHJldHVybiBjYWxjdWxhdGVWaW9saW5WYWx1ZXNcbn1cbiIsImltcG9ydCB7aHlwZW5hdGUsIHNhZmVTZWxlY3QsIHJvdW5kLCBpbnRlcnBvbGF0ZUNvbG9yc30gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7c2V0dXBDb250YWluZXJ9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHtjb2xvckZ1bmN0aW9uIGFzIENGfSBmcm9tICcuL2NvbG9yLWZ1bmN0aW9uJztcblxuXG5leHBvcnQgZnVuY3Rpb24gbnVtZXJpY0xlZ2VuZCggc2VsZWN0aW9uICkge1xuXG4gIHZhclxuICBtaW49MCxcbiAgbWF4PTEsXG4gIHNwYWNlWCxcbiAgc3BhY2VZLFxuICBjb2xvckZ1bmN0aW9uID0gQ0YoKSxcbiAgbmFtZXNwYWNlPSdkM3NtLWxpbmVhci12ZXJ0aWNhbC1ncmFkaWVudCcsXG4gIGZvbnRTaXplID0gMTIsXG4gIGJhY2tncm91bmRGaWxsID0gJ3RyYW5zcGFyZW50JyxcbiAgdGV4dENvbG9yID0gJ2JsYWNrJyxcbiAgcm91bmRUbyA9IDJcblxuXG4gIGxlZ2VuZC5taW4gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1pbj1fLCBsZWdlbmQpIDogbWluIH1cbiAgbGVnZW5kLm1heCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobWF4PV8sIGxlZ2VuZCkgOiBtYXggfVxuICBsZWdlbmQuc3BhY2VYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVg9XywgbGVnZW5kKSA6IHNwYWNlWCB9XG4gIGxlZ2VuZC5zcGFjZVkgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWT1fLCBsZWdlbmQpIDogc3BhY2VZIH1cbiAgbGVnZW5kLm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlPV8sIGxlZ2VuZCkgOiBuYW1lc3BhY2UgfVxuICBsZWdlbmQuZm9udFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGZvbnRTaXplPV8sIGxlZ2VuZCkgOiBmb250U2l6ZSB9XG4gIGxlZ2VuZC5iYWNrZ3JvdW5kRmlsbCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFja2dyb3VuZEZpbGw9XywgbGVnZW5kKSA6IGJhY2tncm91bmRGaWxsIH1cbiAgbGVnZW5kLmNvbG9yRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvbG9yRnVuY3Rpb249XywgbGVnZW5kKSA6IGNvbG9yRnVuY3Rpb24gfVxuICBsZWdlbmQudGV4dENvbG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0ZXh0Q29sb3I9XywgbGVnZW5kKSA6IHRleHRDb2xvciB9XG4gIGxlZ2VuZC5yb3VuZFRvID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChyb3VuZFRvPV8sIGxlZ2VuZCkgOiByb3VuZFRvIH1cblxuICBmdW5jdGlvbiBsZWdlbmQoKSB7XG4gICAgLy8gYmFja2dyb3VuZCBjbGlwaW5nIHJlY3RhbmdsZVxuICAgIHZhciBiZ2NwUmVjdCA9IHt4OjAsIHk6MCwgd2lkdGg6IHNwYWNlWCwgaGVpZ2h0OnNwYWNlWX1cbiAgICB2YXIgY29udGFpbmVyID0gc2V0dXBDb250YWluZXIoIHNlbGVjdGlvbiwgbmFtZXNwYWNlLCBiZ2NwUmVjdCwgYmFja2dyb3VuZEZpbGwgKTtcblxuICAgIHZhciBkZWZzID0gc2FmZVNlbGVjdChzZWxlY3Rpb24sICdkZWZzJylcbiAgICB2YXIgbGluZWFyR3JhZGllbnQgPSBzYWZlU2VsZWN0KGRlZnMsICdsaW5lYXJHcmFkaWVudCcpXG4gICAgLmF0dHIoXCJ4MVwiLCBcIjAlXCIpXG4gICAgLmF0dHIoXCJ5MVwiLCBcIjEwMCVcIilcbiAgICAuYXR0cihcIngyXCIsIFwiMCVcIilcbiAgICAuYXR0cihcInkyXCIsIFwiMCVcIilcbiAgICAuYXR0cignaWQnLCBoeXBlbmF0ZShuYW1lc3BhY2UsJ251bWVyaWNhbC1sZWdlbmQtZ3JhZGllbnQnKSlcblxuXG4gICAgY29sb3JGdW5jdGlvbi5kYXRhRXh0ZW50KFttaW4sIG1heF0pXG4gICAgLmNvbG9yQnkoJ3ZhbHVlJylcbiAgICAudmFsdWVFeHRyYWN0b3IoZnVuY3Rpb24oaywgdiwgaSl7cmV0dXJuIHZ9KVxuXG5cbiAgICBsaW5lYXJHcmFkaWVudC5zZWxlY3RBbGwoJ3N0b3AnKVxuICAgIC5kYXRhKCBjb2xvckZ1bmN0aW9uLmNvbG9ycygpIClcbiAgICAuZW50ZXIoKVxuICAgIC5hcHBlbmQoJ3N0b3AnKVxuICAgIC5hdHRyKFwib2Zmc2V0XCIsIGZ1bmN0aW9uKGQsIGkpeyByZXR1cm4gaSAvIChjb2xvckZ1bmN0aW9uLmNvbG9ycygpLmxlbmd0aCAtIDEpIH0pXG4gICAgLmF0dHIoJ3N0b3AtY29sb3InLCBmdW5jdGlvbihkKSB7cmV0dXJuIGR9KVxuXG5cblxuXG4gICAgdmFyIHJlY3QgPSBzYWZlU2VsZWN0KGNvbnRhaW5lciwgJ3JlY3QnLCAnbGVnZW5kJylcbiAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgwLCcrZm9udFNpemUrJyknKVxuICAgIC5zdHlsZShcImZpbGxcIiwgXCJ1cmwoI1wiK2h5cGVuYXRlKG5hbWVzcGFjZSwnbnVtZXJpY2FsLWxlZ2VuZC1ncmFkaWVudCcpK1wiKVwiKVxuICAgIC5hdHRyKCd4JywgMClcbiAgICAuYXR0cigneScsIDApXG4gICAgLmF0dHIoJ3dpZHRoJywgc3BhY2VYKVxuICAgIC5hdHRyKCdoZWlnaHQnLCBzcGFjZVkgLSBmb250U2l6ZSoyKVxuICAgIC5vbignbW91c2Vtb3ZlJywgZnVuY3Rpb24oZCwgaSl7bGVnZW5kTW91c2Vtb3ZlKGQsIGksIHJlY3QsIGQzLnNlbGVjdCh0aGlzKSl9KVxuICAgIC5vbignbW91c2VvdXQnLCBmdW5jdGlvbihkLCBpKXsgZDMuc2VsZWN0KFwiI1wiK2h5cGVuYXRlKG5hbWVzcGFjZSwnbGVnZW5kLXRvb2x0aXAnKSkucmVtb3ZlKCkgfSlcblxuICAgIHZhciBtaW5UZXh0ID0gc2FmZVNlbGVjdChjb250YWluZXIsICd0ZXh0JywgJ21pbicpXG4gICAgLnRleHQocm91bmQobWluLCAyKSlcbiAgICAuYXR0cigndGV4dC1hbmNob3InLCAnbWlkZGxlJylcbiAgICAuYXR0cihcImZvbnQtc2l6ZVwiLCBmb250U2l6ZSsncHgnKVxuICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhclxuICAgICAgeCA9IHNwYWNlWCAvIDIsXG4gICAgICB5ID0gc3BhY2VZIC0gZm9udFNpemUgLyA0LFxuICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgcmV0dXJuIHRcbiAgICB9KVxuXG4gICAgdmFyIG1heFRleHQgPSBzYWZlU2VsZWN0KGNvbnRhaW5lciwgJ3RleHQnLCAnbWF4JylcbiAgICAudGV4dChyb3VuZChtYXgsIDIpKVxuICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsICdtaWRkbGUnKVxuICAgIC5hdHRyKFwiZm9udC1zaXplXCIsIGZvbnRTaXplKydweCcpXG4gICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgdmFyXG4gICAgICB4ID0gc3BhY2VYIC8gMixcbiAgICAgIHkgPSBmb250U2l6ZSxcbiAgICAgIHQgPSAndHJhbnNsYXRlKCcreCsnLCcreSsnKSdcbiAgICAgIHJldHVybiB0XG4gICAgfSlcblxuXG5cblxuICB9XG5cbiAgZnVuY3Rpb24gbGVnZW5kTW91c2Vtb3ZlKGQsIGksIHJlY3QsIHQpIHtcbiAgICB2YXIgcyA9IGQzLnNjYWxlTGluZWFyKClcbiAgICAuZG9tYWluKFswLCByZWN0LmF0dHIoJ2hlaWdodCcpXSlcbiAgICAucmFuZ2UoW21heCwgbWluXSlcbiAgICB2YXIgbSA9IGQzLm1vdXNlKHJlY3Qubm9kZSgpKVxuICAgIHZhciB2ID0gcm91bmQocyhtWzFdKSxyb3VuZFRvKVxuXG4gICAgdmFyIHN0cm9rZUNvbG9yID0gY29sb3JGdW5jdGlvbih1bmRlZmluZWQsIHYsIHVuZGVmaW5lZCwgJ3N0cm9rZScpXG4gICAgdmFyIGZpbGxDb2xvciA9IGNvbG9yRnVuY3Rpb24odW5kZWZpbmVkLCB2LCB1bmRlZmluZWQsICdmaWxsJylcblxuICAgIHZhciBkaXYgPSBzYWZlU2VsZWN0KGQzLnNlbGVjdCgnYm9keScpLCAnZGl2JywgaHlwZW5hdGUobmFtZXNwYWNlLCdsZWdlbmQtdG9vbHRpcCcpKVxuICAgIC5hdHRyKCdpZCcsIGh5cGVuYXRlKG5hbWVzcGFjZSwnbGVnZW5kLXRvb2x0aXAnKSlcbiAgICAuc3R5bGUoJ3Bvc2l0aW9uJywgJ2Fic29sdXRlJylcbiAgICAuc3R5bGUoJ2xlZnQnLCAoZDMuZXZlbnQucGFnZVgrMTUpKydweCcpXG4gICAgLnN0eWxlKCd0b3AnLCAoZDMuZXZlbnQucGFnZVkrMTUpKydweCcpXG4gICAgLnN0eWxlKCdiYWNrZ3JvdW5kLWNvbG9yJywgZmlsbENvbG9yKVxuICAgIC5zdHlsZSgnYm9yZGVyLWNvbG9yJywgc3Ryb2tlQ29sb3IpXG5cbiAgICAuc3R5bGUoJ21pbi13aWR0aCcsIChmb250U2l6ZSAqIChTdHJpbmcobWF4KS5zcGxpdCgnLicpWzBdLmxlbmd0aCszKSkrJ3B4JylcbiAgICAuc3R5bGUoJ21pbi1oZWlnaHQnLCAoZm9udFNpemUgKiAoU3RyaW5nKG1heCkuc3BsaXQoJy4nKVswXS5sZW5ndGgrMykpKydweCcpXG4gICAgLnN0eWxlKCdib3JkZXItcmFkaXVzJywgJzUwJScpXG4gICAgLnN0eWxlKCdib3JkZXItcmFkaXVzJywgJzUwMDBweCcpXG5cbiAgICAuc3R5bGUoJ2Rpc3BsYXknLCAnZmxleCcpXG4gICAgLnN0eWxlKCdqdXN0aWZ5LWNvbnRlbnQnLCAnY2VudGVyJylcbiAgICAuc3R5bGUoJ3RleHQtYWxpZ24nLCAnbWlkZGxlJylcbiAgICAuc3R5bGUoJ3BhZGRpbmcnLCAyK1wicHhcIilcblxuICAgIC5zdHlsZSgnYm9yZGVyLXN0eWxlJywgJ3NvbGlkJylcbiAgICAuc3R5bGUoJ2JvcmRlci13aWR0aCcsIDIpXG5cbiAgICB2YXIgdGV4dCA9IHNhZmVTZWxlY3QoZGl2LCAnZGl2JylcbiAgICAudGV4dCh2KVxuICAgIC5zdHlsZSgnY29sb3InLCB0ZXh0Q29sb3IpXG4gICAgLnN0eWxlKCdhbGlnbi1zZWxmJywgJ2NlbnRlcicpXG4gIH1cblxuICByZXR1cm4gbGVnZW5kXG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0LCByb3VuZCwgaW50ZXJwb2xhdGVDb2xvcnN9IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQge3NldHVwQ29udGFpbmVyLCBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0LCBjYWxjdWxhdGVXaWR0aE9mU3BhY2VyfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7Y29sb3JGdW5jdGlvbiBhcyBDRn0gZnJvbSAnLi9jb2xvci1mdW5jdGlvbic7XG5pbXBvcnQge2dyb3VwaW5nU3BhY2VyfSBmcm9tICcuL2dyb3VwaW5nLXNwYWNlcic7XG5pbXBvcnQge3VuaXF1ZSwgZmxhdHRlbn0gZnJvbSAnLi9hcnJheS1mdW5jdGlvbnMnO1xuXG5leHBvcnQgZnVuY3Rpb24gY2F0ZWdvcmljTGVnZW5kKCBzZWxlY3Rpb24gKSB7XG4gIHZhclxuICBjYXRlZ29yaWVzLFxuXG4gIC8qKlxuICAqIERhdGEgdG8gcGxvdC4gQXNzdW1lZCB0byBiZSBhIG9iamVjdCwgd2hlcmUgZWFjaCBrZXkgY29ycmVzcG9uZHMgdG8gYSBsZWdlbmRcbiAgKiAoc2VlIHtAbGluayBsZWdlbmQjZGF0YX0pXG4gICogQHBhcmFtIHtPYmplY3R9IFtkYXRhPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgbGVnZW5kI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBkYXRhLFxuICAvKipcbiAgKiBXaGljaCBkaXJlY3Rpb24gdG8gcmVuZGVyIHRoZSBiYXJzIGluXG4gICogKHNlZSB7QGxpbmsgbGVnZW5kI29yaWVudH0pXG4gICogQHBhcmFtIHtudW1iZXJ9IFtvcmllbnQ9J2hvcml6b250YWwnXVxuICAqIEBtZW1iZXJvZiBsZWdlbmQjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG9yaWVudD0naG9yaXpvbnRhbCcsXG4gIC8qKlxuICAqIEFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIChpbiBwaXhlbHMpIGF2YWlibGUgdG8gcmVuZGVyIHRoZSBsZWdlbmQgaW5cbiAgKiAoc2VlIHtAbGluayBsZWdlbmQjc3BhY2VYfSlcbiAgKiBAcGFyYW0ge251bWJlcn0gW3NwYWNlWD11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc3BhY2VYLFxuICAvKipcbiAgKiBBbW91bnQgb2YgdmVydGljYWwgc3BhY2UgKGluIHBpeGVscykgYXZhaWJsZSB0byByZW5kZXIgdGhlIGxlZ2VuZCBpblxuICAqIChzZWUge0BsaW5rIGxlZ2VuZC5zcGFjZVl9KVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbc3BhY2VZPXVuZGVmaW5lZF1cbiAgKiBAbWVtYmVyb2YgbGVnZW5kI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBzcGFjZVksXG5cbiAgLyoqXG4gICogV2hldGhlciBvciBub3QgdG8gYWxsb3cgbGVnZW5kIHRvIHJlbmRlciBlbGVtZW50cyBwYXNzIHRoZSBtYWluIHNwYXRpYWwgZGltZW5zaW9uXG4gICogZ2l2ZW4gdGhlIG9yaWVudGF0aW9uIChzZWUge0BsaW5rIGxlZ2VuZCNvcmllbnR9KSwgd2hlcmUge0BsaW5rIGxlZ2VuZCNvcmllbnR9PVwiaG9yaXpvbnRhbFwiXG4gICogdGhlIG1haW4gZGltZW5zaW9uIGlzIHtAbGluayBsZWdlbmQjc3BhY2VYfSBhbmQgd2hlcmUge0BsaW5rIGxlZ2VuZCNvcmllbnR9PVwidmVydGljYWxcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgbGVnZW5kI3NwYWNlWX1cbiAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvdmVyZmxvd1E9ZmFsc2VdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb3ZlcmZsb3dRID0gZmFsc2UsXG5cbiAgLyoqXG4gICogQW4gYXJyYXkgLSBwdXRhdGl2ZWx5IG9mIG90aGVyIGFycmF5cyAtIGRlcGljdGluZyBob3cgYmFycyBzaG91bGQgYmUgYXJyYW5nZWRcbiAgKiBAcGFyYW0ge0FycmF5W119IFtncm91cGluZz11bmRlZmluZWRdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgZ3JvdXBpbmcsXG5cbiAgLyoqXG4gICogSG93IHRvIGdldCB0aGUgdmFsdWUgb2YgdGhlIGxlZ2VuZFxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFt2YWx1ZUV4dHJhY3Rvcj1mdW5jdGlvbihrZXksIGluZGV4KSB7IHJldHVybiBkYXRhW2tleV0gfV1cbiAgKiBAbWVtYmVyb2YgbGVnZW5kI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICB2YWx1ZUV4dHJhY3RvciA9IGZ1bmN0aW9uKGtleSwgaW5kZXgpIHsgcmV0dXJuIGRhdGFba2V5XSB9LFxuICAvKipcbiAgKiBIb3cgdG8gc29ydCB0aGUgYmFycyAtIGlmIHtAbGluayBiYXIjZ3JvdXBpbmd9IGlzIG5vdCBwcm92aWRlZC5cbiAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbc29ydGluZ0Z1bmN0aW9uPWZ1bmN0aW9uKGtleUEsIGtleUIpIHtyZXR1cm4gZDMuZGVzY2VuZGluZyhkYXRhW2tleUFdLCBkYXRhW2tleUJdKX1dXG4gICogQG1lbWJlcm9mIGJhciNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgc29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oa2V5QSwga2V5Qikge3JldHVybiBkMy5hc2NlbmRpbmcoa2V5QSwga2V5Qil9LFxuICAvKipcbiAgKiBEZWZhdWx0IHNwYWNlIGZvciB0aGUgc3BhY2VyIChwZXJjZW50YWdlKSBvZiBtYWluIGRpbWVuc2lvbiBnaXZlbiB0aGUgb3JpZW50YXRpb25cbiAgKiAoc2VlIHtAbGluayBsZWdlbmQjb3JpZW50fSksIHdoZXJlIHtAbGluayBsZWdlbmQjb3JpZW50fT1cImhvcml6b250YWxcIlxuICAqIHRoZSBtYWluIGRpbWVuc2lvbiBpcyB7QGxpbmsgbGVnZW5kI3NwYWNlWH0gYW5kIHdoZXJlIHtAbGluayBsZWdlbmQjb3JpZW50fT1cInZlcnRpY2FsXCJcbiAgKiB0aGUgbWFpbiBkaW1lbnNpb24gaXMge0BsaW5rIGxlZ2VuZCNzcGFjZVl9IGJldHdlZW4gYmFyc1xuICAqIEBwYXJhbSB7bnVtYmVyfSBbb2JqZWN0U3BhY2VyPTAuMDVdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgb2JqZWN0U3BhY2VyID0gMC4wNSxcbiAgLyoqXG4gICogVGhlIG1pbmltdW0gc2l6ZSB0aGF0IGFuIG9iamVjdCBjYW4gYmVcbiAgKiBAcGFyYW0ge251bWJlcn0gW21pbk9iamVjdFNpemU9NTBdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbWluT2JqZWN0U2l6ZSA9IDEwLFxuICAvKipcbiAgKiBUaGUgbWF4aW11bSBzaXplIHRoYXQgYW4gb2JqZWN0IGNhbiBiZVxuICAqIEBwYXJhbSB7bnVtYmVyfSBbbWF4T2JqZWN0U2l6ZT0xMDBdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgbWF4T2JqZWN0U2l6ZSA9IDEwMCxcblxuICAvKipcbiAgKiBUaGUgc3Ryb2tlIHdpZHRoIG9mIHRoZSBiYXJzXG4gICogQHBhcmFtIHtudW1iZXJ9IFtiYXJTdHJva2VXaWR0aD0yXVxuICAqIEBtZW1iZXJvZiBsZWdlbmQjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGJ1YmJsZVN0cm9rZVdpZHRoID0gMixcbiAgLyoqXG4gICogSW5zdGFuY2Ugb2YgQ29sb3JGdW5jdGlvblxuICAqIEBwYXJhbSB7ZnVuY3Rpb259IFtjb2xvckZ1bmN0aW9uID0gY29sb3JGdW5jdGlvbigpXVxuICAqIEBtZW1iZXJvZiBsZWdlbmQjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGNvbG9yRnVuY3Rpb24gPSBDRigpLFxuXG4gIC8qKlxuICAqIENvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kXG4gICogQHBhcmFtIHtzdHJpbmd9IFtiYWNrZ3JvdW5kRmlsbD1cInRyYW5zcGFyZW50XCJdXG4gICogQG1lbWJlcm9mIGxlZ2VuZCNcbiAgKiBAcHJvcGVydHlcbiAgKi9cbiAgYmFja2dyb3VuZEZpbGwgPSAndHJhbnNwYXJlbnQnLFxuICAvKipcbiAgKiBOYW1lc3BhY2UgZm9yIGFsbCBpdGVtcyBtYWRlIGJ5IHRoaXMgaW5zdGFuY2Ugb2YgbGVnZW5kXG4gICogQHBhcmFtIHtzdHJpbmd9IFtuYW1lc3BhY2U9XCJkM3NtLWxlZ2VuZFwiXVxuICAqIEBtZW1iZXJvZiBsZWdlbmQjXG4gICogQHByb3BlcnR5XG4gICovXG4gIG5hbWVzcGFjZSA9ICdkM3NtLWxlZ2VuZCcsXG4gIC8qKlxuICAqIENsYXNzIG5hbWUgZm9yIGxlZ2VuZCBjb250YWluZXIgKDxnPiBlbGVtZW50KVxuICAqIEBwYXJhbSB7c3RyaW5nfSBbb2JqZWN0Q2xhc3M9XCJsZWdlbmRcIl1cbiAgKiBAbWVtYmVyb2YgbGVnZW5kI1xuICAqIEBwcm9wZXJ0eVxuICAqL1xuICBvYmplY3RDbGFzcyA9ICdsZWdlbmQnLFxuXG4gIC8qKlxuICAqIER1cmF0aW9uIG9mIGFsbCB0cmFuc2l0aW9ucyBvZiB0aGlzIGVsZW1lbnRcbiAgKiBAcGFyYW0ge251bWJlcn0gW3RyYW5zaXRpb25EdXJhdGlvbj0xMDAwXVxuICAqIEBtZW1iZXJvZiBsZWdlbmQjXG4gICogQHByb3BlcnR5XG4gICovXG4gIHRyYW5zaXRpb25EdXJhdGlvbiA9IDEwMDAsXG4gIC8qKlxuICAqIEVhc2luZyBmdW5jdGlvbiBmb3IgdHJhbnNpdGlvbnNcbiAgKiBAcGFyYW0ge2QzLmVhc2V9IFtlYXNlRnVuYz1kMy5lYXNlRXhwXVxuICAqIEBtZW1iZXJvZiBsZWdlbmQjXG4gICogQHByb3BlcnR5XG4gICovXG4gIGVhc2VGdW5jID0gZDMuZWFzZUV4cFxuXG5cbiAgbGVnZW5kLmNhdGVnb3JpZXMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNhdGVnb3JpZXM9XywgbGVnZW5kKSA6IGNhdGVnb3JpZXMgfTtcblxuICAvKipcbiAgICogR2V0cyBvciBzZXRzIHRoZSBzZWxlY3Rpb24gaW4gd2hpY2ggaXRlbXMgYXJlIG1hbmlwdWxhdGVkXG4gICAqIEBwYXJhbSB7ZDMuc2VsZWN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgZDMuc2VsZWN0aW9ufVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IHNlbGVjdGlvbiA9IHNlbGVjdGlvblxuICAgKi9cbiAgbGVnZW5kLnNlbGVjdGlvbiA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2VsZWN0aW9uID0gXywgbGVnZW5kKSA6IHNlbGVjdGlvbjsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZGF0YVxuICAgKiAoc2VlIHtAbGluayBsZWdlbmQjZGF0YX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgb2JqZWN0fVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKi9cbiAgbGVnZW5kLmRhdGEgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRhdGEgPSBfLCBsZWdlbmQpIDogZGF0YTsgfTtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgb3JpZW50IG9mIHRoZSBiYXJzXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCNvcmllbnR9KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2xlZ2VuZCB8IG9iamVjdH1cbiAgICogQG1lbWJlcm9mIGxlZ2VuZFxuICAgKiBAcHJvcGVydHlcbiAgICovXG4gIGxlZ2VuZC5vcmllbnQgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9yaWVudCA9IF8sIGxlZ2VuZCkgOiBvcmllbnQ7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiBob3Jpem9udGFsIHNwYWNlIGluIHdoaWNoIGl0ZW1zIGFyZSBtYW5pcHVsYXRlZFxuICAgKiAoc2VlIHtAbGluayBsZWdlbmQjc3BhY2VYfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdIHNob3VsZCBiZSBhIG51bWJlciA+IDBcbiAgICogQHJldHVybnMge2xlZ2VuZCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGxlZ2VuZFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBzcGFjZVggPSB1bmRlZmluZWRcbiAgICovXG4gIGxlZ2VuZC5zcGFjZVggPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNwYWNlWCA9IF8sIGxlZ2VuZCkgOiBzcGFjZVg7IH07XG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIGFtb3VudCBvZiB2ZXJ0aWNhbCBzcGFjZSBpbiB3aGljaCBpdGVtcyBhcmUgbWFuaXB1bGF0ZWRcbiAgICogKHNlZSB7QGxpbmsgbGVnZW5kI3NwYWNlWX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXSBzaG91bGQgYmUgYSBudW1iZXIgPiAwXG4gICAqIEByZXR1cm5zIHtsZWdlbmQgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc3BhY2VZID0gdW5kZWZpbmVkXG4gICAqL1xuICBsZWdlbmQuc3BhY2VZID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVkgPSBfLCBsZWdlbmQpIDogc3BhY2VZOyB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB3aGV0aGVyIG9yIG5vdCBsZWdlbmQgaXMgYWxsb3dlZCB0byBnbyBiZXlvbmQgc3BlY2lmaWVkIGRpbWVuc2lvbnNcbiAgICogKHNlZSB7QGxpbmsgbGVnZW5kI3NwYWNlWH0pXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2xlZ2VuZCB8IGJvb2xlYW59XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb3ZlcmZsb3dRID0gZmFsc2VcbiAgICovXG4gIGxlZ2VuZC5vdmVyZmxvd1EgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG92ZXJmbG93USA9IF8sIGxlZ2VuZCkgOiBvdmVyZmxvd1E7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgZ3JvdXBpbmcgb2YgdGhlIGJhcnNcbiAgICogKHNlZSB7QGxpbmsgbGVnZW5kI2dyb3VwaW5nfSlcbiAgICogQHBhcmFtIHtBcnJheVtdfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgQXJyYXlbXX1cbiAgICogQG1lbWJlcm9mIGxlZ2VuZFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCBncm91cGluZyA9IHVuZGVmaW5lZFxuICAgKi9cbiAgbGVnZW5kLmdyb3VwaW5nID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChncm91cGluZyA9IF8sIGxlZ2VuZCkgOiBncm91cGluZzsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSB2YWx1ZUV4dHJhY3RvclxuICAgKiAoc2VlIHtAbGluayBsZWdlbmQjdmFsdWVFeHRyYWN0b3J9KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgdmFsdWVFeHRyYWN0b3IgPSBmdW5jdGlvbihrZXksIGluZGV4KSB7IHJldHVybiBkYXRhW2tleV0gfSxcbiAgICovXG4gIGxlZ2VuZC52YWx1ZUV4dHJhY3RvciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodmFsdWVFeHRyYWN0b3IgPSBfLCBsZWdlbmQpIDogdmFsdWVFeHRyYWN0b3I7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgc29ydGluZ0Z1bmN0aW9uXG4gICAqIChzZWUge0BsaW5rIGJhciNzb3J0aW5nRnVuY3Rpb259KVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7YmFyIHwgZnVuY3Rpb259XG4gICAqIEBtZW1iZXJvZiBiYXJcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgc29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oa2V5QSwga2V5Qikge3JldHVybiBkMy5kZXNjZW5kaW5nKGRhdGFba2V5QV0sIGRhdGFba2V5Ql0pfSxcbiAgICovXG4gIGxlZ2VuZC5zb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNvcnRpbmdGdW5jdGlvbiA9IF8sIGxlZ2VuZCkgOiBzb3J0aW5nRnVuY3Rpb247IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyBvYmplY3RTcGFjZXJcbiAgICogKHNlZSB7QGxpbmsgbGVnZW5kI29iamVjdFNwYWNlcn0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG9iamVjdFNwYWNlciA9IDAuMDVcbiAgICovXG4gIGxlZ2VuZC5vYmplY3RTcGFjZXIgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9iamVjdFNwYWNlciA9IF8sIGxlZ2VuZCkgOiBvYmplY3RTcGFjZXI7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgbWluT2JqZWN0U2l6ZVxuICAgKiAoc2VlIHtAbGluayBsZWdlbmQjbWluT2JqZWN0U2l6ZX0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG1pbk9iamVjdFNpemUgPSA1MFxuICAgKi9cbiAgbGVnZW5kLm1pbk9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1pbk9iamVjdFNpemUgPSBfLCBsZWdlbmQpIDogbWluT2JqZWN0U2l6ZTsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBtYXhPYmplY3RTaXplXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCNtYXhPYmplY3RTaXplfSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtsZWdlbmQgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgbWF4T2JqZWN0U2l6ZSA9IDEwMFxuICAgKi9cbiAgbGVnZW5kLm1heE9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1heE9iamVjdFNpemUgPSBfLCBsZWdlbmQpIDogbWF4T2JqZWN0U2l6ZTsgfTtcblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGJhclN0cm9rZVdpZHRoXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCNiYXJTdHJva2VXaWR0aH0pXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgbnVtYmVyfVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGJhclN0cm9rZVdpZHRoID0gMlxuICAgKi9cbiAgbGVnZW5kLmJ1YmJsZVN0cm9rZVdpZHRoID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChidWJibGVTdHJva2VXaWR0aCA9IF8sIGxlZ2VuZCkgOiBidWJibGVTdHJva2VXaWR0aDsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBjb2xvckZ1bmN0aW9uXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCNjb2xvckZ1bmN0aW9ufSlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtsZWdlbmQgfCBudW1iZXJ9XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgY29sb3JGdW5jdGlvbiA9IGNvbG9yRnVuY3Rpb24oKVxuICAgKi9cbiAgbGVnZW5kLmNvbG9yRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvbG9yRnVuY3Rpb24gPSBfLCBsZWdlbmQpIDogY29sb3JGdW5jdGlvbjsgfTtcblxuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGJhY2tncm91bmRGaWxsXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCNiYWNrZ3JvdW5kRmlsbH0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IGJhY2tncm91bmRGaWxsID0gJ3RyYW5zcGFyZW50J1xuICAgKi9cbiAgbGVnZW5kLmJhY2tncm91bmRGaWxsID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChiYWNrZ3JvdW5kRmlsbCA9IF8sIGxlZ2VuZCkgOiBiYWNrZ3JvdW5kRmlsbDsgfTtcbiAgLyoqXG4gICAqIEdldHMgLyBzZXRzIHRoZSBuYW1lc3BhY2VcbiAgICogKHNlZSB7QGxpbmsgbGVnZW5kI25hbWVzcGFjZX0pXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbXz1ub25lXVxuICAgKiBAcmV0dXJucyB7bGVnZW5kIHwgc3RyaW5nfVxuICAgKiBAbWVtYmVyb2YgbGVnZW5kXG4gICAqIEBwcm9wZXJ0eVxuICAgKiBieSBkZWZhdWx0IG5hbWVzcGFjZSA9ICdkM3NtLWxlZ2VuZCdcbiAgICovXG4gIGxlZ2VuZC5uYW1lc3BhY2UgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG5hbWVzcGFjZSA9IF8sIGxlZ2VuZCkgOiBuYW1lc3BhY2U7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgb2JqZWN0Q2xhc3NcbiAgICogKHNlZSB7QGxpbmsgbGVnZW5kI29iamVjdENsYXNzfSlcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtfPW5vbmVdXG4gICAqIEByZXR1cm5zIHtsZWdlbmQgfCBzdHJpbmd9XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgb2JqZWN0Q2xhc3MgPSAndGljay1ncm91cCdcbiAgICovXG4gIGxlZ2VuZC5vYmplY3RDbGFzcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q2xhc3MgPSBfLCBsZWdlbmQpIDogb2JqZWN0Q2xhc3M7IH07XG4gIC8qKlxuICAgKiBHZXRzIC8gc2V0cyB0aGUgdHJhbnNpdGlvbkR1cmF0aW9uXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCN0cmFuc2l0aW9uRHVyYXRpb259KVxuICAgKiBAcGFyYW0ge251bWJlcn0gW189bm9uZV1cbiAgICogQHJldHVybnMge2xlZ2VuZCB8IG51bWJlcn1cbiAgICogQG1lbWJlcm9mIGxlZ2VuZFxuICAgKiBAcHJvcGVydHlcbiAgICogYnkgZGVmYXVsdCB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwXG4gICAqL1xuICBsZWdlbmQudHJhbnNpdGlvbkR1cmF0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0cmFuc2l0aW9uRHVyYXRpb24gPSBfLCBsZWdlbmQpIDogdHJhbnNpdGlvbkR1cmF0aW9uOyB9O1xuICAvKipcbiAgICogR2V0cyAvIHNldHMgdGhlIGVhc2VGdW5jXG4gICAqIChzZWUge0BsaW5rIGxlZ2VuZCNlYXNlRnVuY30pXG4gICAqIEBwYXJhbSB7ZDMuZWFzZX0gW189bm9uZV1cbiAgICogQHJldHVybnMge2xlZ2VuZCB8IGQzLmVhc2V9XG4gICAqIEBtZW1iZXJvZiBsZWdlbmRcbiAgICogQHByb3BlcnR5XG4gICAqIGJ5IGRlZmF1bHQgZWFzZUZ1bmMgPSBkMy5lYXNlRXhwXG4gICAqL1xuICBsZWdlbmQuZWFzZUZ1bmMgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGVhc2VGdW5jID0gXywgbGVnZW5kKSA6IGVhc2VGdW5jOyB9O1xuXG5cbiAgZnVuY3Rpb24gbGVnZW5kKCkge1xuICAgIHZhciBob3Jpem9udGFsUSA9IChvcmllbnQgPT0gJ2hvcml6b250YWwnKSA/IHRydWUgOiBmYWxzZVxuICAgIHZhciB2ZXJ0aWNhbFEgPSAhaG9yaXpvbnRhbFFcbiAgICAvLyBiYWNrZ3JvdW5kIGNsaXBpbmcgcmVjdGFuZ2xlXG4gICAgdmFyIGJnY3BSZWN0ID0ge3g6MCwgeTowLCB3aWR0aDogc3BhY2VYLCBoZWlnaHQ6c3BhY2VZfVxuICAgIHZhciBjb250YWluZXIgPSBzZXR1cENvbnRhaW5lciggc2VsZWN0aW9uLCBuYW1lc3BhY2UsIGJnY3BSZWN0LCBiYWNrZ3JvdW5kRmlsbCApO1xuXG5cbiAgICBjb2xvckZ1bmN0aW9uLmRhdGFFeHRlbnQoWzAsIGNhdGVnb3JpZXMubGVuZ3RoIC0gMV0pXG4gICAgLmNvbG9yQnkoJ2NhdGVnb3JpZXMnKVxuICAgIC5jYXRlZ29yeUV4dHJhY3RvcihmdW5jdGlvbihrLCB2LCBpKXtyZXR1cm4gdn0pXG5cbiAgICB2YXIgciA9IE1hdGgubWluKHNwYWNlWCwgc3BhY2VZKSAvIDJcbiAgICB2YXIgbnVtYmVyT2ZPYmplY3RzID0gY2F0ZWdvcmllcy5sZW5ndGhcblxuICAgIC8vIGlmIGdyb3VwaW5nIGlzIHVuZGVmaW5lZCBzb3J0IGJhcktleXMgYnkgc29ydGluZ0Z1bmN0aW9uXG4gICAgdmFyIG9yZGVyZWQgPSAoZ3JvdXBpbmcgPT0gdW5kZWZpbmVkKSA/IGNhdGVnb3JpZXMuc29ydChzb3J0aW5nRnVuY3Rpb24pIDogZ3JvdXBpbmdcbiAgICAvLyBvcmRlcmVkIG1pZ2h0IGJlIG5lc3RlZCBkZXBlbmRpbmcgb24gZ3JvdXBpbmdcbiAgICB2YXIgY2F0S2V5cyA9IGZsYXR0ZW4ob3JkZXJlZClcblxuICAgIHZhciBzcGFjZSA9IGhvcml6b250YWxRID8gc3BhY2VYIDogc3BhY2VZXG4gICAgLy8gY2FsY3VsYXRlIG9iamVjdCBzaXplXG4gICAgdmFyIG9iamVjdFNpemUgPSBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0KHNwYWNlLCBudW1iZXJPZk9iamVjdHMsIG1pbk9iamVjdFNpemUsIG1heE9iamVjdFNpemUsIG9iamVjdFNwYWNlciwgb3ZlcmZsb3dRKVxuICAgIC8vIGNhbGN1bGF0ZSBzcGFjZXIgc2l6ZSBpZiBuZWVkZWRcbiAgICB2YXIgc3BhY2VyU2l6ZSA9IGNhbGN1bGF0ZVdpZHRoT2ZTcGFjZXIoY2F0S2V5cywgc3BhY2UsIG9iamVjdFNpemUsIG51bWJlck9mT2JqZWN0cywgb2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgLy8gbWFrZSB0aGUgbmVzdGVkIGdyb3Vwc1xuICAgIHZhciBzcGFjZXJGdW5jdGlvbiA9IGdyb3VwaW5nU3BhY2VyKClcbiAgICAuaG9yaXpvbnRhbFEoaG9yaXpvbnRhbFEpLnNjYWxlKHNjYWxlKS5tb3ZlYnkoJ2NhdGVnb3J5JykubnVtYmVyT2ZPYmplY3RzKG51bWJlck9mT2JqZWN0cylcbiAgICAub2JqZWN0Q2xhc3Mob2JqZWN0Q2xhc3MpLm9iamVjdFNpemUob2JqZWN0U2l6ZSkuc3BhY2VyU2l6ZShzcGFjZXJTaXplKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlRnVuYyhlYXNlRnVuYylcbiAgICAubmFtZXNwYWNlKG5hbWVzcGFjZSlcblxuICAgIHNwYWNlckZ1bmN0aW9uKGNvbnRhaW5lciwgb3JkZXJlZCwgMClcbiAgICB2YXIgciA9IE1hdGgubWluKG9iamVjdFNpemUsIHNwYWNlWCwgc3BhY2VZKSAvIDIgLSBidWJibGVTdHJva2VXaWR0aFxuXG4gICAgY29udGFpbmVyLnNlbGVjdEFsbCgnZzpub3QoLnRvLXJlbW92ZSkuJytvYmplY3RDbGFzcykuZWFjaChmdW5jdGlvbihjYXQsIGkpIHtcbiAgICAgIHZhciB0ID0gZDMuc2VsZWN0KHRoaXMpXG4gICAgICB2YXIgYyA9IHNhZmVTZWxlY3QodCwgJ2NpcmNsZScpXG4gICAgICB2YXIgZmlsbENvbG9yID0gY29sb3JGdW5jdGlvbih1bmRlZmluZWQsIGNhdCwgaSwgJ2ZpbGwnKSwgLy8gcHJldmVudCBkdXBsaWNhdGUgY29tcHV0YXRpb25cbiAgICAgIHN0cm9rZUNvbG9yID0gY29sb3JGdW5jdGlvbih1bmRlZmluZWQsIGNhdCwgaSwgICdzdHJva2UnKVxuXG4gICAgICB2YXIgY3ggPSBob3Jpem9udGFsUVxuICAgICAgICA/IHIrYnViYmxlU3Ryb2tlV2lkdGhcbiAgICAgICAgOiAoc3BhY2VYIC0gcioyKSAvIDIgKyByXG4gICAgICB2YXIgY3kgPSB2ZXJ0aWNhbFFcbiAgICAgICAgPyByK2J1YmJsZVN0cm9rZVdpZHRoXG4gICAgICAgIDogKHNwYWNlWCAtIHIqMikgLyAyICsgclxuXG4gICAgICBjLmF0dHIoXCJyXCIsIHIpXG4gICAgICAuYXR0cignY3gnLCBjeClcbiAgICAgIC5hdHRyKCdjeScsIGN5KVxuICAgICAgLmF0dHIoJ2ZpbGwnLCBmaWxsQ29sb3IpXG4gICAgICAuYXR0cignc3Ryb2tlJywgc3Ryb2tlQ29sb3IpXG4gICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgYnViYmxlU3Ryb2tlV2lkdGgpXG5cbiAgICAgIHZhciB0ZXh0ID0gc2FmZVNlbGVjdCh0LCAndGV4dCcpXG4gICAgICB0ZXh0LnRleHQoY2F0KVxuICAgICAgLmF0dHIoJ3RleHQtYW5jaG9yJywgJ21pZGRsZScpXG4gICAgICAuYXR0cihcInRyYW5zZm9ybVwiLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgICAgdmFyXG4gICAgICAgIHggPSBjeCxcbiAgICAgICAgeSA9IGN5ICsgdGV4dC5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0IC8gNCxcbiAgICAgICAgdCA9ICd0cmFuc2xhdGUoJyt4KycsJyt5KycpJ1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfSlcblxuICAgIH0pXG5cblxuICB9XG5cbiAgcmV0dXJuIGxlZ2VuZFxufVxuIiwiaW1wb3J0IHtoeXBlbmF0ZSwgc2FmZVNlbGVjdCwgbW9kaWZ5SGV4aWRlY2ltYWxDb2xvckx1bWluYW5jZSwgZXh0cmFjdFZpb2xpblZhbHVlcywgcXVhcnRpbGVzfSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtzZXR1cENvbnRhaW5lciwgY2FsY3VsYXRlV2lkdGhPZk9iamVjdCwgY2FsY3VsYXRlV2lkdGhPZlNwYWNlcn0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQge3VuaXF1ZSwgaGFzUSwgZmxhdHRlbiwgd2hpY2hCaW59IGZyb20gJy4vYXJyYXktZnVuY3Rpb25zJztcbmltcG9ydCB7Z3JvdXBpbmdTcGFjZXJ9IGZyb20gJy4vZ3JvdXBpbmctc3BhY2VyJztcbmltcG9ydCB7Y29sb3JGdW5jdGlvbiBhcyBDRn0gZnJvbSAnLi9jb2xvci1mdW5jdGlvbic7XG5pbXBvcnQge3Rvb2x0aXAgYXMgVFRpcH0gZnJvbSAnLi90b29sdGlwJztcbmltcG9ydCB7bGFzc299IGZyb20gJy4vbGFzc28nO1xuaW1wb3J0ICcuL2QzLXByb3RvdHlwZXMnO1xuXG5leHBvcnQgZnVuY3Rpb24gbGFzc29XaWRnZXQoIHNlbGVjdGlvbiApIHtcbiAgdmFyXG4gIG5hbWVzcGFjZSA9ICdkM3NtLWxhc3NvJyxcbiAgc2VsZWN0aW9uID0gc2VsZWN0aW9uLFxuICBzdmcsXG4gIGNoYXJ0Q29udGFpbmVyLFxuICBvYmplY3RDb250YWluZXIsXG4gIG9iamVjdENsYXNzLFxuICBsYXNzb0xpbmUgPSBkMy5saW5lKClcbiAgLngoZnVuY3Rpb24oZCwgaSl7cmV0dXJuIGRbMF19KVxuICAueShmdW5jdGlvbihkLCBpKXtyZXR1cm4gZFsxXX0pXG4gIC5jdXJ2ZShkMy5jdXJ2ZUxpbmVhckNsb3NlZCksXG4gIHBhdGgsXG4gIGNvbG9yRnVuY3Rpb24gPSBDRigpLFxuICBtYXhOdW1iZXJPZkdyb3VwcyxcbiAgZGF0YUV4dHJhY3RvcixcbiAgeFNjYWxlLFxuICB5U2NhbGVcblxuICBmdW5jdGlvbiBvbkVycm9yKG1zZywgc3R5bGUpe1xuICAgIGNvbnNvbGUubG9nKG1zZywgc3R5bGUpXG4gIH1cbiAgLy8gc2V0dXAgdGhlIGNvbnRhaW5lclxuICBzZXR1cERhdGFzZWxlY3RDb250YWluZXIoKVxuXG4gIGxhc3NvV2lkZ2V0Lm9iamVjdENsYXNzID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q2xhc3M9Jy4nK18ucmVwbGFjZSgnLicsJycpLCBsYXNzb1dpZGdldCkgOiBvYmplY3RDbGFzc31cbiAgbGFzc29XaWRnZXQuc3ZnID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3ZnPV8sIGxhc3NvV2lkZ2V0KSA6IHN2Z31cbiAgbGFzc29XaWRnZXQuc3VibWl0ID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3VibWl0PV8sIGxhc3NvV2lkZ2V0KSA6IHN1Ym1pdH1cbiAgbGFzc29XaWRnZXQubWF4TnVtYmVyT2ZHcm91cHMgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChtYXhOdW1iZXJPZkdyb3Vwcz1fLCBsYXNzb1dpZGdldCkgOiBtYXhOdW1iZXJPZkdyb3Vwc31cbiAgbGFzc29XaWRnZXQub25FcnJvciA9IGZ1bmN0aW9uKF8pe3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9uRXJyb3I9XywgbGFzc29XaWRnZXQpIDogb25FcnJvcn1cbiAgbGFzc29XaWRnZXQub2JqZWN0Q29udGFpbmVyID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q29udGFpbmVyPV8sIGxhc3NvV2lkZ2V0KSA6IG9iamVjdENvbnRhaW5lcn1cbiAgbGFzc29XaWRnZXQuY2hhcnRDb250YWluZXIgPSBmdW5jdGlvbihfKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjaGFydENvbnRhaW5lcj1fLCBsYXNzb1dpZGdldCkgOiBjaGFydENvbnRhaW5lcn1cbiAgbGFzc29XaWRnZXQuZGF0YUV4dHJhY3RvciA9IGZ1bmN0aW9uKF8pe3JldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRhdGFFeHRyYWN0b3I9XywgbGFzc29XaWRnZXQpIDogZGF0YUV4dHJhY3Rvcn1cbiAgbGFzc29XaWRnZXQueFNjYWxlID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeFNjYWxlPV8sIGxhc3NvV2lkZ2V0KSA6IHhTY2FsZX1cbiAgbGFzc29XaWRnZXQueVNjYWxlID0gZnVuY3Rpb24oXyl7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeVNjYWxlPV8sIGxhc3NvV2lkZ2V0KSA6IHlTY2FsZX1cblxuICBmdW5jdGlvbiBzdHlsZXMoKSB7XG4gICAgdmFyIHMgPSBkMy5zZWxlY3QoXCJodG1sXCIpLnNlbGVjdChcInN0eWxlLlwiK25hbWVzcGFjZSsnbGFzc28td2lkZ2V0JylcbiAgICBpZiAocy5lbXB0eSgpKSB7XG4gICAgICBkMy5zZWxlY3QoXCJodG1sXCIpLmFwcGVuZChcInN0eWxlXCIpXG4gICAgICAuY2xhc3NlZChuYW1lc3BhY2UrJ2xhc3NvLXdpZGdldCcsIHRydWUpXG4gICAgICAuaHRtbChcbiAgICAgICAgXCIuXCIraHlwZW5hdGUobmFtZXNwYWNlLCBcImRhdGEtdGFibGVcIikgKyBcIntcXFxuICAgICAgICAgIGhlaWdodDoxMDBweDtcXFxuICAgICAgICAgIG92ZXJmbG93OmF1dG87XFxcbiAgICAgICAgfVwiXG4gICAgICApXG4gICAgfVxuICB9XG5cblxuICBmdW5jdGlvbiBsYXNzb1dpZGdldCgpIHtcbiAgICBzdHlsZXMoKVxuXG4gIH1cblxuICBmdW5jdGlvbiBzdWJtaXQoZGF0YSkge1xuICAgIGNvbnNvbGUubG9nKGRhdGEpXG4gIH1cblxuICBmdW5jdGlvbiBwbHVzVGFiKHRhYkxpc3QpIHtcbiAgICB2YXIgdGFiID0gc2FmZVNlbGVjdCh0YWJMaXN0LCAnbGknLCBoeXBlbmF0ZShuYW1lc3BhY2UsICdwbHVzLXRhYicpKVxuICAgIC5jbGFzc2VkKCdtbC1hdXRvJywgdHJ1ZSlcbiAgICAuY2xhc3NlZCgnbmF2LWl0ZW0nLCB0cnVlKVxuICAgIC5vbignY2xpY2snLCBtYWtlTmV3R3JvdXApLFxuXG4gICAgYW5jaG9yID0gc2FmZVNlbGVjdCh0YWIsICdhJywgJ25hdi1saW5rJyksXG4gICAgaWNvbiA9IHNhZmVTZWxlY3QoYW5jaG9yLCAnaScsICdmYScpXG4gICAgLmNsYXNzZWQoJ2ZhLXBsdXMgZmEtMnggdGV4dC1zdWNjZXNzJywgdHJ1ZSlcbiAgfVxuXG4gIGZ1bmN0aW9uIHNlbmRUYWIodGFiTGlzdCkge1xuICAgIHZhciB0YWIgPSBzYWZlU2VsZWN0KHRhYkxpc3QsICdsaScsIGh5cGVuYXRlKG5hbWVzcGFjZSwgJ3NlbmQtdGFiJykpXG4gICAgLmNsYXNzZWQoJ21sLWF1dG8nLCB0cnVlKVxuICAgIC5jbGFzc2VkKCduYXYtaXRlbScsIHRydWUpXG4gICAgLm9uKCdjbGljaycsIGNsaWNrU2VuZClcbiAgICAsXG5cbiAgICBhbmNob3IgPSBzYWZlU2VsZWN0KHRhYiwgJ2EnLCAnbmF2LWxpbmsnKSxcbiAgICBpY29uID0gc2FmZVNlbGVjdChhbmNob3IsICdpJywgJ2ZhJylcbiAgICAuY2xhc3NlZCgnZmEtcGFwZXItcGxhbmUtbyBmYS0yeCB0ZXh0LXByaW1hcnknLCB0cnVlKVxuICB9XG5cbiAgZnVuY3Rpb24gY2xpY2tTZW5kKCkge1xuICAgIHZhciBkYXRhID0gZ2F0aGVyRGF0YUxpc3RzKClcbiAgICBzdWJtaXQoZGF0YSlcbiAgfVxuXG4gIGZ1bmN0aW9uIGNsb3NlVGFiKHRhYkxpc3QpIHtcbiAgICB2YXIgdGFiID0gc2FmZVNlbGVjdCh0YWJMaXN0LCAnbGknLCBoeXBlbmF0ZShuYW1lc3BhY2UsICdjbG9zZS10YWInKSlcbiAgICAuY2xhc3NlZCgnbWwtYXV0bycsIHRydWUpXG4gICAgLmNsYXNzZWQoJ25hdi1pdGVtJywgdHJ1ZSlcbiAgICAub24oJ2NsaWNrJywgZnVuY3Rpb24oKXtcbiAgICAgIHZhciBtID0gZDMubW91c2UoZDMuc2VsZWN0KFwiaHRtbFwiKS5ub2RlKCkpXG4gICAgICBzZWxlY3Rpb24uc2VsZWN0KCdkaXYuY2FyZCcpLnN0eWxlKFwicG9zaXRpb25cIiwgJ3JlbGF0aXZlJylcbiAgICAgIC50cmFuc2l0aW9uKCkuZHVyYXRpb24oMTAwMClcbiAgICAgIC5lYXNlKGQzLmVhc2VCYWNrKVxuICAgICAgLnN0eWxlKCdsZWZ0Jywgd2luZG93Lm91dGVyV2lkdGggKydweCcpXG4gICAgICAucmVtb3ZlKClcbiAgICB9KVxuICAgICxcblxuICAgIGFuY2hvciA9IHNhZmVTZWxlY3QodGFiLCAnYScsICduYXYtbGluaycpLFxuICAgIGljb24gPSBzYWZlU2VsZWN0KGFuY2hvciwgJ2knLCAnZmEnKVxuICAgIC5jbGFzc2VkKCdmYS13aW5kb3ctY2xvc2UtbyBmYS0yeCB0ZXh0LWRhbmdlcicsIHRydWUpXG4gIH1cblxuXG5cbiAgZnVuY3Rpb24gc2V0dXBEYXRhc2VsZWN0Q29udGFpbmVyKCkge1xuICAgIHZhclxuICAgIGNhcmQgPSBzYWZlU2VsZWN0KHNlbGVjdGlvbiwgJ2RpdicsICdjYXJkJyksXG4gICAgY2FyZEhlYWRlciA9IHNhZmVTZWxlY3QoY2FyZCwgJ2RpdicsICdjYXJkLWhlYWRlcicpLFxuXG4gICAgdGFiTGlzdCA9IHNhZmVTZWxlY3QoY2FyZEhlYWRlciwgJ3VsJywgJ25hdicpXG4gICAgLmNsYXNzZWQoJ25hdi10YWJzIGNhcmQtaGVhZGVyLXRhYnMnLCB0cnVlKVxuICAgIC5jbGFzc2VkKGh5cGVuYXRlKG5hbWVzcGFjZSwgJ3RhYi1saXN0JyksIHRydWUpXG4gICAgLmF0dHIoJ3JvbGUnLCAndGFibGlzdCcpLFxuXG4gICAgY2FyZEJvZHkgPSBzYWZlU2VsZWN0KGNhcmQsICdkaXYnLCAnY2FyZC1ib2R5JyksXG4gICAgdGFiQ29udGVudCA9IHNhZmVTZWxlY3QoY2FyZEJvZHksICdkaXYnLCAndGFiLWNvbnRlbnQnKVxuICAgIC5jbGFzc2VkKGh5cGVuYXRlKG5hbWVzcGFjZSwgJ3RhYi1jb250ZW50JyksIHRydWUpLFxuXG4gICAgLy8gbGVmdFRhYnMgPSBzYWZlU2VsZWN0KHRhYkxpc3QsICdkaXYnLCAnbmF2IG1yLWF1dG8gbGVmdC1hbGlnbmVkLXRhYnMnKVxuICAgIHJpZ2h0VGFicyA9IHNhZmVTZWxlY3QodGFiTGlzdCwgJ2RpdicsICdyaWdodC1hbGlnbmVkLXRhYnMnKS5jbGFzc2VkKCduYXYgbWwtYXV0byAnLCB0cnVlKVxuXG4gICAgcGx1c1RhYihyaWdodFRhYnMpXG4gICAgc2VuZFRhYihyaWdodFRhYnMpXG4gICAgY2xvc2VUYWIocmlnaHRUYWJzKVxuICAgIHZhclxuICAgIGRlZmF1bHRUYWIgPSBzYWZlU2VsZWN0KHRhYkNvbnRlbnQsICdkaXYnLCAndGFiLXBhbmUnKVxuICAgIC5jbGFzc2VkKGh5cGVuYXRlKG5hbWVzcGFjZSwnZGVmYXVsdC10YWInKSwgdHJ1ZSlcbiAgICAuY2xhc3NlZChcImFjdGl2ZVwiLCB0cnVlKVxuICAgIC5jbGFzc2VkKCd0ZXh0LWxlZnQnLCB0cnVlKSxcblxuICAgIHAgPSBzYWZlU2VsZWN0KGRlZmF1bHRUYWIsICdkaXYnKVxuICAgIC5odG1sKFxuICAgICAgXCJDbGljayA8a2JkPjxpIGNsYXNzPSdmYSBmYS1wbHVzIHRleHQtc3VjY2Vzcyc+PC9pPjwva2JkPiB0byBhZGQgYSBuZXcgZ3JvdXAuPGJyPlwiK1xuICAgICAgXCJDbGljayA8a2JkPjxpIGNsYXNzPSdmYSBmYS1wYXBlci1wbGFuZS1vIHRleHQtcHJpbWFyeSc+PC9pPjwva2JkPiB0byBzdWJtaXQgZm9yIHJlLWFuYWx5c2lzLjxicj5cIitcbiAgICAgIFwiQ2xpY2sgPGtiZD48aSBjbGFzcz0nZmEgZmEtd2luZG93LWNsb3NlLW8gdGV4dC1kYW5nZXInPjwvaT48L2tiZD4gdG8gY2xvc2UgdGhlIGRhdGFzZWxlY3Qgd2lkZ2V0LlwiXG4gICAgKVxuICAgIC8vIC50ZXh0KCdDbGljayB0aGUgZ3JlZW4gcGx1cyB0byBhZGQgYSBuZXcgZ3JvdXAuJylcbiAgfVxuXG5cbiAgZnVuY3Rpb24gbWFrZVJlbW92ZUJ1dHRvbihwYW5lQnRuTGlzdCkge1xuICAgIHZhclxuICAgIGJ0biA9IHNhZmVTZWxlY3QocGFuZUJ0bkxpc3QsICdidXR0b24nLCAncmVtb3ZlLWJ0bicpXG4gICAgLmNsYXNzZWQoJ2J0biBidG4tZGFuZ2VyJywgdHJ1ZSlcbiAgICAub24oJ2NsaWNrJywgcmVtb3ZlQnRuQ2xpY2tUb1JlbW92ZSksXG4gICAgaSA9IHNhZmVTZWxlY3QoYnRuLCAnaScsICdmYScpLmNsYXNzZWQoJ2ZhLXRyYXNoLW8nLCB0cnVlKSxcbiAgICBzID0gc2FmZVNlbGVjdChidG4sICdzcGFuJykudGV4dCgnUmVtb3ZlIGdyb3VwJylcbiAgICByZXR1cm4gYnRuXG4gIH1cblxuICBmdW5jdGlvbiByZW1vdmVCdG5DbGlja1RvUmVtb3ZlKGQsIGkpIHtcbiAgICB2YXJcbiAgICB0YWIgPSBzZWxlY3Rpb24uc2VsZWN0KCcjJytoeXBlbmF0ZShuYW1lc3BhY2UsJ3RhYicsZCkpLFxuICAgIHBhbmUgPSBzZWxlY3Rpb24uc2VsZWN0KCcjJytoeXBlbmF0ZShuYW1lc3BhY2UsJ3RhYicsJ3BhbmUnLGQpKVxuXG4gICAgdGFiLnJlbW92ZSgpXG4gICAgcGFuZS5yZW1vdmUoKVxuXG4gICAgc2hvd1JlbWFpbmluZ1BhbmVzKClcbiAgICB1cGRhdGVUYWJBbmRQYW5lTnVtYmVycygpXG4gIH1cblxuXG4gIGZ1bmN0aW9uIHRvZ2dsZVBhbmVCeUlkKGlkKSB7XG4gICAgdmFyIHBhbmVzID0gc2VsZWN0aW9uLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCAndGFiLWNvbnRlbnQnKSlcbiAgICBwYW5lcy5zZWxlY3RBbGwoJ2Rpdi50YWItcGFuZScpXG4gICAgLmVhY2goZnVuY3Rpb24oZCwgaSl7XG4gICAgICBkMy5zZWxlY3QodGhpcykuY2xhc3NlZCgnYWN0aXZlIHNob3cnLCBkMy5zZWxlY3QodGhpcykuYXR0cignaWQnKSA9PSBpZClcbiAgICB9KVxuICB9XG5cbiAgZnVuY3Rpb24gaW5zZXJ0VGFiKHRhYnMsIG4pIHtcblxuICAgIC8vIHZhciBsaSA9IHRhYnMuaW5zZXJ0KFwibGlcIiwgJzpudGgtY2hpbGQoJysobikrJyknKVxuICAgIHZhciBsaSA9IHRhYnMuaW5zZXJ0KFwibGlcIiwgJy5yaWdodC1hbGlnbmVkLXRhYnMnKVxuICAgIC5jbGFzc2VkKCduYXYtaXRlbScsIHRydWUpXG4gICAgLmNsYXNzZWQoJ2FsZXJ0JywgdHJ1ZSlcbiAgICAuY2xhc3NlZCgnYWxlcnQtc2Vjb25kYXJ5JywgdHJ1ZSlcbiAgICAuY2xhc3NlZCgnYWxlcnQtZGlzbWlzc2FibGUnLCB0cnVlKVxuICAgIC5jbGFzc2VkKCdmYWRlJywgdHJ1ZSlcbiAgICAuY2xhc3NlZCgnc2hvdycsIHRydWUpXG4gICAgLy8gLmNsYXNzZWQoJ21yLWF1dG8nLCB0cnVlKVxuICAgIC5hdHRyKFwicm9sZVwiLCAnYWxlcnQnKVxuICAgIC5hdHRyKFwiaWRcIiwgaHlwZW5hdGUobmFtZXNwYWNlLCd0YWInLG4pKVxuICAgIC5jbGFzc2VkKGh5cGVuYXRlKG5hbWVzcGFjZSwndGFiJyksIHRydWUpXG5cbiAgICB2YXIgYSA9IHNhZmVTZWxlY3QobGksICdhJylcbiAgICAuYXR0cignZGF0YS10b2dnbGUnLCAndGFiJylcbiAgICAudGV4dCgnR3JvdXAgJyArIG4pXG4gICAgLmF0dHIoJ2hyZWYnLCAnIycraHlwZW5hdGUobmFtZXNwYWNlLCd0YWInLCdwYW5lJyxuKSlcbiAgICAub24oJ2RibGNsaWNrJywgZnVuY3Rpb24oZCwgaSl7XG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgICAgdC5hdHRyKCdjb250ZW50ZWRpdGFibGUnLCB0cnVlKVxuICAgICAgZDMuc2VsZWN0KHQubm9kZSgpLnBhcmVudE5vZGUpXG4gICAgICAuY2xhc3NlZCgnYWxlcnQtc2Vjb25kYXJ5JywgZmFsc2UpXG4gICAgICAuY2xhc3NlZCgnYWxlcnQtd2FybmluZycsIHRydWUpXG5cbiAgICAgIC8vIGQzLnNlbGVjdChcImh0bWxcIikub24oXCJjbGlja1wiLCBkaXNwYXRjaEJsdXIpXG4gICAgICAvL1xuICAgICAgLy8gZnVuY3Rpb24gZGlzcGF0Y2hCbHVyKGQsIGkpIHtcbiAgICAgIC8vICAgaWYgKGQzLmV2ZW50LnRhcmdldCAhPSBkMy5zZWxlY3QodGhpcykpIHtcbiAgICAgIC8vICAgICBkMy5zZWxlY3QodGhpcykuZGlzcGF0Y2goXCJibHVyXCIpXG4gICAgICAvLyAgIH1cbiAgICAgIC8vIH1cblxuXG4gICAgfSlcbiAgICAub24oJ2JsdXInLCBmdW5jdGlvbihkLCBpKXtcblxuICAgICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcylcbiAgICAgIHQuYXR0cignY29udGVudGVkaXRhYmxlJywgZmFsc2UpXG4gICAgICBkMy5zZWxlY3QodC5ub2RlKCkucGFyZW50Tm9kZSlcbiAgICAgIC5jbGFzc2VkKCdhbGVydC1zZWNvbmRhcnknLCB0cnVlKVxuICAgICAgLmNsYXNzZWQoJ2FsZXJ0LXdhcm5pbmcnLCBmYWxzZSlcblxuICAgIH0pXG4gICAgLm9uKCdpbnB1dCcsIGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcylcbiAgICAgIHZhciB0eHQgPSB0LnRleHQoKVxuICAgICAgZDMuc2VsZWN0KHQuYXR0cignaHJlZicpKS5zZWxlY3QoXCJwLmxlYWRcIikudGV4dCh0eHQpXG4gICAgfSlcblxuXG4gICAgcmV0dXJuIGxpXG4gIH1cblxuICBmdW5jdGlvbiBtYWtlVGFiUGFuZShwYW5lcywgbikge1xuICAgIHZhciBwYW5lID0gcGFuZXMuYXBwZW5kKCdkaXYnKVxuICAgIC5kYXR1bShuKVxuICAgIC5hdHRyKCdyb2xlJywgJ3RhYnBhbmVsJylcbiAgICAuY2xhc3NlZCgndGFiLXBhbmUnLCB0cnVlKVxuICAgIC5jbGFzc2VkKCd0ZXh0LWxlZnQnLCB0cnVlKVxuICAgIC5jbGFzc2VkKGh5cGVuYXRlKG5hbWVzcGFjZSwndGFiJywncGFuZScpLCB0cnVlKVxuICAgIC5hdHRyKCdpZCcsIGh5cGVuYXRlKG5hbWVzcGFjZSwndGFiJywncGFuZScsbikpXG4gICAgcmV0dXJuIHBhbmVcbiAgfVxuXG4gIGZ1bmN0aW9uIHBvcHVsYXRlUGFuZShwYW5lLCBuKSB7XG4gICAgdmFyXG4gICAgbGVhZCA9IHNhZmVTZWxlY3QocGFuZSwgJ3AnLCAnbGVhZCcpLnRleHQoJ0dyb3VwICcrbiksXG5cbiAgICB0YWJsZUNvbnRhaW5lciA9IHNhZmVTZWxlY3QocGFuZSwgJ2RpdicsICd0YWJsZS1yZXNwb25zaXZlJylcbiAgICAuYXR0cihcImNsYXNzXCIsIGh5cGVuYXRlKG5hbWVzcGFjZSwgXCJkYXRhLXRhYmxlXCIpKSxcblxuICAgIHRhYmxlID0gc2FmZVNlbGVjdCh0YWJsZUNvbnRhaW5lciwgXCJ0YWJsZVwiLCBcInRhYmxlXCIpXG4gICAgLmNsYXNzZWQoXCJ0YWJsZS1zbVwiLCB0cnVlKS5jbGFzc2VkKFwidGFibGUtaG92ZXJcIiwgdHJ1ZSksXG5cbiAgICBjYXB0aW9uID0gc2FmZVNlbGVjdCh0YWJsZSwgXCJjYXB0aW9uXCIsIFwiY2FwdGlvblwiKS5odG1sKFwiTGlzdCBvZiBzZWxlY3RlZFwiKSxcblxuICAgIGJ0bnMgPSBzYWZlU2VsZWN0KHBhbmUsICdkaXYnLCAndGV4dC1yaWdodCcpLFxuXG4gICAgY04gPSBuICUgY29sb3JGdW5jdGlvbi5jb2xvcnMoKS5sZW5ndGhcbiAgICBpZiAobiAlIDIgIT0gMCkgeyBjTiA9IChjb2xvckZ1bmN0aW9uLmNvbG9ycygpLmxlbmd0aCAtIDEpIC0gY04gfVxuXG5cblxuXG5cbiAgICB2YXIgbGFzc29CdG4gPSBtYWtlTGFzc29CdXR0b24oYnRucylcbiAgICB2YXIgY3VycmVudExhc3NvID0gbWFrZUxhc3NvRnVuY3Rpb24obiwgY29sb3JGdW5jdGlvbi5jb2xvcnMoKVtjTl0pXG4gICAgdmFyIGNsZWFyQnRuID0gbWFrZUNsZWFyQnV0dG9uKGJ0bnMpXG5cbiAgICBiaW5kQnV0dG9ucyhsYXNzb0J0biwgY2xlYXJCdG4sIGN1cnJlbnRMYXNzbywgdGFibGUpXG5cbiAgICB2YXIgcmVtb3ZlQnRuID0gbWFrZVJlbW92ZUJ1dHRvbihidG5zKVxuXG4gICAgbGVhZC5vbihcIm1vdXNlb3ZlclwiLCBmdW5jdGlvbigpe1xuICAgICAgY3VycmVudExhc3NvLmRyYXcoKVxuICAgIH0pXG4gICAgbGVhZC5vbihcIm1vdXNlb3V0XCIsIGZ1bmN0aW9uKCl7XG4gICAgICBjdXJyZW50TGFzc28ucmVtb3ZlKClcbiAgICB9KVxuXG4gIH1cblxuICBmdW5jdGlvbiBtYWtlTGFzc29CdXR0b24oYnRucykge1xuICAgIHZhciBidG4gPSBzYWZlU2VsZWN0KGJ0bnMsICdidXR0b24nLCAnbGFzc28tYnRuJylcbiAgICAuY2xhc3NlZCgnYnRuIGJ0bi1pbmZvJywgdHJ1ZSlcbiAgICAuY2xhc3NlZChuYW1lc3BhY2UsIHRydWUpXG4gICAgLy8gLmRhdHVtKFtsYXNzb10pXG4gICAgdmFyIGkgPSBzYWZlU2VsZWN0KGJ0biwgJ2knLCAnZmEnKS5jbGFzc2VkKCdmYS1oYW5kLXBvaW50ZXItbycsIHRydWUpXG4gICAgdmFyIHMgPSBzYWZlU2VsZWN0KGJ0biwgJ3NwYW4nKS50ZXh0KCdMYXNzbyBzZWxlY3QnKVxuICAgIHJldHVybiBidG5cblxuICB9XG5cbiAgZnVuY3Rpb24gbWFrZUNsZWFyQnV0dG9uKGJ0bnMpIHtcbiAgICB2YXIgYnRuID0gc2FmZVNlbGVjdChidG5zLCAnYnV0dG9uJywgJ2NsZWFyLWJ0bicpXG4gICAgLmNsYXNzZWQoJ2J0biBidG4tbGlnaHQnLCB0cnVlKVxuICAgIC5jbGFzc2VkKG5hbWVzcGFjZSwgdHJ1ZSlcbiAgICB2YXIgaSA9IHNhZmVTZWxlY3QoYnRuLCAnaScsICdmYScpLmNsYXNzZWQoJ2ZhLWVyYXNlcicsIHRydWUpXG4gICAgdmFyIHMgPSBzYWZlU2VsZWN0KGJ0biwgJ3NwYW4nKS50ZXh0KCdDbGVhciBzZWxlY3Rpb24nKVxuICAgIHJldHVybiBidG5cbiAgfVxuXG4gIGZ1bmN0aW9uIG1ha2VMYXNzb0Z1bmN0aW9uKGluc3RhbmNlLCBjb2xvcikge1xuICAgIHZhciBjdXJyZW50TGFzc28gPSBsYXNzbygpXG4gICAgLm5hbWVzcGFjZShuYW1lc3BhY2UpXG4gICAgLnN2ZyhzdmcpXG4gICAgLm9iamVjdENsYXNzKG9iamVjdENsYXNzKVxuICAgIC5jaGFydENvbnRhaW5lcihjaGFydENvbnRhaW5lcilcbiAgICAub2JqZWN0Q29udGFpbmVyKG9iamVjdENvbnRhaW5lcilcbiAgICAuaW5zdGFuY2UoaW5zdGFuY2UpXG4gICAgLmNvbG9yKGNvbG9yKVxuICAgIC55U2NhbGUoeVNjYWxlKVxuICAgIC54U2NhbGUoeFNjYWxlKVxuXG4gICAgcmV0dXJuIGN1cnJlbnRMYXNzb1xuICB9XG5cbiAgZnVuY3Rpb24gYmluZEJ1dHRvbnMobGFzc29CdG4sIGNsZWFyQnRuLCBjdXJyZW50TGFzc28sIHRhYmxlKSB7XG4gICAgY3VycmVudExhc3NvLmV2ZW50Q2F0Y2hlcihsYXNzb0J0bilcbiAgICBsYXNzb0J0bi5ub2RlKCkuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGxhc3NvQnRuVG9nZ2xlKVxuXG4gICAgbGFzc29CdG4uZGF0dW0oW2N1cnJlbnRMYXNzb10pXG4gICAgLm9uKGh5cGVuYXRlKG5hbWVzcGFjZSwncmVuZGVyJyksIGZ1bmN0aW9uKCl7XG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKS5kYXR1bSgpWzBdLmRyYXcoKVxuICAgIH0pXG4gICAgLm9uKGh5cGVuYXRlKG5hbWVzcGFjZSxcImRyYWdcIiksIGZ1bmN0aW9uKGxhcyl7XG4gICAgICB2YXIgbm9kZXMgPSBjaGFydENvbnRhaW5lci5zZWxlY3RBbGwoXCIuaW4tbGFzc28tXCIrbGFzWzBdLmluc3RhbmNlKCkpLm5vZGVzKClcbiAgICAgIHZhciB0YWJsZURhdGEgPSBub2Rlcy5tYXAoZnVuY3Rpb24oZCwgaSl7XG4gICAgICAgIHZhciBleHRyYWN0ZWQgPSBkYXRhRXh0cmFjdG9yKGQzLnNlbGVjdChkKS5kYXR1bSgpKVxuICAgICAgICBleHRyYWN0ZWRbXCJfX25vZGVcIl0gPSBkXG4gICAgICAgIHJldHVybiBleHRyYWN0ZWRcbiAgICAgIH0pXG5cblxuICAgICAgbWFrZVRhYmxlKHRhYmxlLCB0YWJsZURhdGEsIGN1cnJlbnRMYXNzbylcbiAgICB9KVxuXG4gICAgY2xlYXJCdG4ub24oJ2NsaWNrJywgZnVuY3Rpb24oKXtcbiAgICAgIGN1cnJlbnRMYXNzby5hbGxQb2ludHMoW10pXG4gICAgICBjdXJyZW50TGFzc28uY3VycmVudFBvaW50cyhbXSlcbiAgICAgIGxhc3NvQnRuLmRpc3BhdGNoKGh5cGVuYXRlKG5hbWVzcGFjZSxcImRyYWdcIikpXG5cbiAgICB9KVxuXG4gIH1cblxuICBmdW5jdGlvbiBsYXNzb0J0blRvZ2dsZSgpIHtcbiAgICB2YXIgdGhhdCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgIHZhciBsYXMgPSB0aGF0LmRhdHVtKClbMF1cblxuICAgIGxhcy50b2dnbGUoKVxuICAgIHZhciBhY3RpdmVRID0gbGFzLmFjdGl2ZVEoKVxuXG4gICAgaWYgKGxhcy5hY3RpdmVRKCkpIHtcbiAgICAgIHRoYXQuY2xhc3NlZCgnYnRuLWluZm8nLCAhYWN0aXZlUSlcbiAgICAgIHRoYXQuY2xhc3NlZCgnYnRuLXdhcm5pbmcnLCBhY3RpdmVRKVxuICAgICAgdGhhdC5zZWxlY3QoXCJzcGFuXCIpLnRleHQoXCJMYXNzbyBzZWxlY3QgKGFjdGl2ZSlcIilcbiAgICAgIHNlbGVjdGlvbi5zZWxlY3RBbGwoXCIuXCIrbmFtZXNwYWNlK1wiLmxhc3NvLWJ0blwiKS5kaXNwYXRjaChoeXBlbmF0ZShuYW1lc3BhY2UsJ3JlbmRlcicpKVxuICAgICAgZDMuc2VsZWN0KFwiaHRtbFwiKS5ub2RlKCkuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgbW9uaXRvckxhc3NvQnV0dG9uU3RhdGUpXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoYXQuY2xhc3NlZCgnYnRuLWluZm8nLCAhYWN0aXZlUSlcbiAgICAgIHRoYXQuY2xhc3NlZCgnYnRuLXdhcm5pbmcnLCBhY3RpdmVRKVxuICAgICAgdGhhdC5zZWxlY3QoXCJzcGFuXCIpLnRleHQoXCJMYXNzbyBzZWxlY3RcIilcbiAgICAgIGQzLnNlbGVjdChcImh0bWxcIikubm9kZSgpLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIG1vbml0b3JMYXNzb0J1dHRvblN0YXRlKVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1vbml0b3JMYXNzb0J1dHRvblN0YXRlKGV2ZW50KSB7XG4gICAgICAvKlxuICAgICAgYWN0aXZlTGFzc28gc3RvcHMgZXZlbnQgc3RvcFByb3BhZ2F0aW9uLCBzbyB0aGlzIGV2ZW50IHdpbGwgbm90IHJlZ2lzdGVyIGluXG4gICAgICB0aGF0IGNhc2UuIFRodXMgd2Ugb25seSBuZWVkIHRvIGVuc3VyZSB0aGF0IHRoZSB1c3JlIGlzIGNsaWNraW5nIG9uIHRoZSBsYXNzbyBidXR0b25cbiAgICAgIG90aGVyd2lzZSwgZGUtc3Bhd24gbGFzc28uXG4gICAgICAqL1xuICAgICAgaWYgKFxuICAgICAgICBldmVudC50YXJnZXQgIT0gdGhhdC5ub2RlKCkgJiZcbiAgICAgICAgZXZlbnQudGFyZ2V0ICE9IHRoYXQuc2VsZWN0KFwic3BhblwiKS5ub2RlKCkgJiZcbiAgICAgICAgZXZlbnQudGFyZ2V0ICE9IHRoYXQuc2VsZWN0KFwiaVwiKS5ub2RlKClcbiAgICAgICkge1xuICAgICAgICAvLyBldmVudC5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICAgIC8vIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXG4gICAgICAgIGxhcy50b2dnbGUoZmFsc2UpXG4gICAgICAgIHRoYXQuY2xhc3NlZCgnYnRuLWluZm8nLCB0cnVlKVxuICAgICAgICB0aGF0LmNsYXNzZWQoJ2J0bi13YXJuaW5nJywgZmFsc2UpXG4gICAgICAgIHRoYXQuc2VsZWN0KFwic3BhblwiKS50ZXh0KFwiTGFzc28gc2VsZWN0XCIpXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHRoYXQsIHRoYXQubm9kZSgpKVxuICAgICAgICAvLyB0aGF0LmRpc3BhdGNoKFwiZm9jdXNvdXRcIilcbiAgICAgIH1cbiAgICB9XG5cbiAgfVxuXG5cbiAgZnVuY3Rpb24gdXBkYXRlVGFibGVIZWFkZXJDb2x1bW5zKGhlYWRSLCB0YWJsZURhdGEpIHtcbiAgICB2YXIgaGVhZGVyS2V5cyA9IGQzLmtleXModGFibGVEYXRhWzBdKS5maWx0ZXIoaz0+ayE9XCJfX25vZGVcIilcbiAgICBpZiAoaGVhZGVyS2V5cy5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBoZWFkZXJLZXlzID0gW1wicmVtb3ZlXCJdLmNvbmNhdChoZWFkZXJLZXlzKVxuICAgICAgaGVhZGVyS2V5cy5wdXNoKFwicmVtb3ZlXCIpXG4gICAgfVxuXG4gICAgdmFyIGhlYWRlckNvbHMgPSBoZWFkUi5zZWxlY3RBbGwoXCJ0aFwiKVxuXG4gICAgaGVhZGVyQ29scyA9IGhlYWRlckNvbHMuZGF0YShoZWFkZXJLZXlzKVxuICAgIGhlYWRlckNvbHMuZXhpdCgpLnJlbW92ZSgpXG4gICAgaGVhZGVyQ29scyA9IGhlYWRlckNvbHMubWVyZ2UoaGVhZGVyQ29scy5lbnRlcigpLmFwcGVuZChcInRoXCIpLmF0dHIoXCJzY29wZVwiLFwiY29sXCIpKVxuICAgIC50ZXh0KGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkfSlcblxuICAgIHJldHVybiBoZWFkZXJLZXlzXG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVUYWJsZVJvd3MoYm9keSwgdGFibGVEYXRhKSB7XG4gICAgdmFyIGJvZHlSb3dzID0gYm9keS5zZWxlY3RBbGwoXCJ0clwiKVxuXG4gICAgYm9keVJvd3MgPSBib2R5Um93cy5kYXRhKHRhYmxlRGF0YSlcbiAgICBib2R5Um93cy5leGl0KCkucmVtb3ZlKClcbiAgICBib2R5Um93cyA9IGJvZHlSb3dzLm1lcmdlKGJvZHlSb3dzLmVudGVyKCkuYXBwZW5kKFwidHJcIikpXG5cbiAgICByZXR1cm4gYm9keVJvd3NcbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZVRhYmxlUm93Q29sdW1ucyhjb2xzLCBoZWFkZXJLZXlzLCByb3dEYXRhLCB0YWJsZURhdGEsIGxhc3NvLCB0YWJsZSkge1xuICAgIGNvbHMgPSBjb2xzLmRhdGEoaGVhZGVyS2V5cylcbiAgICBjb2xzLmV4aXQoKS5yZW1vdmUoKVxuICAgIGNvbHMgPSBjb2xzLm1lcmdlKGNvbHMuZW50ZXIoKS5hcHBlbmQoXCJ0ZFwiKSlcblxuICAgIGNvbHMuaHRtbChmdW5jdGlvbihkLCBpKXtcbiAgICAgIGlmIChkICE9IFwicmVtb3ZlXCIpIHsgcmV0dXJuIHJvd0RhdGFbZF0gfVxuICAgICAgcmV0dXJuIFwiPGkgY2xhc3M9J2ZhIGZhLWNsb3NlJz48L2k+XCJcbiAgICB9KS5jbGFzc2VkKFwidGV4dC1sZWZ0XCIsIGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgaWYgKGQgIT0gXCJyZW1vdmVcIikgeyByZXR1cm4gZmFsc2UgfVxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9KVxuICAgIC8vIC5hdHRyKFwic2NvcGVcIixmdW5jdGlvbihkLCBpKXtcbiAgICAvLyAgIGlmIChkICE9IFwicmVtb3ZlXCIpIHsgcmV0dXJuIGZhbHNlIH1cbiAgICAvLyAgIHJldHVybiB0cnVlXG4gICAgLy8gfSlcblxuICAgIGNvbHMuc2VsZWN0KFwiaS5mYS1jbG9zZVwiKS5vbihcImNsaWNrXCIsIGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgdmFyIG5vZGUgPSByb3dEYXRhW1wiX19ub2RlXCJdLFxuICAgICAgbiA9IGQzLnNlbGVjdChub2RlKVxuICAgICAgbi5jbGFzc2VkKFwiaW4tbGFzc29cIiwgZmFsc2UpXG4gICAgICBuLmNsYXNzZWQoXCJpbi1sYXNzby1cIitsYXNzby5pbnN0YW5jZSgpLCBmYWxzZSlcblxuICAgICAgdGFibGVEYXRhLm1hcChmdW5jdGlvbihkZCwgail7XG4gICAgICAgIGlmIChkZFtcIl9fbm9kZVwiXSA9PSBub2RlKSB7XG4gICAgICAgICAgdGFibGVEYXRhLnNwbGljZShqLCAxKVxuICAgICAgICAgIG1ha2VUYWJsZSh0YWJsZSwgdGFibGVEYXRhLCBsYXNzbylcbiAgICAgICAgfVxuICAgICAgfSlcblxuICAgIH0pXG4gIH1cblxuICBmdW5jdGlvbiBtYWtlVGFibGUodGFibGUsIHRhYmxlRGF0YSwgbGFzc28pIHtcbiAgICB2YXJcbiAgICBoZWFkID0gc2FmZVNlbGVjdCh0YWJsZSwgXCJ0aGVhZFwiKSxcbiAgICBoZWFkUiA9IHNhZmVTZWxlY3QoaGVhZCwgXCJ0clwiKSxcbiAgICBib2R5ID0gc2FmZVNlbGVjdCh0YWJsZSwgXCJ0Ym9keVwiKSxcblxuICAgIGhlYWRlcktleXMgPSB1cGRhdGVUYWJsZUhlYWRlckNvbHVtbnMoaGVhZFIsIHRhYmxlRGF0YSksXG5cbiAgICBib2R5Um93cyA9IHVwZGF0ZVRhYmxlUm93cyhib2R5LCB0YWJsZURhdGEpXG5cbiAgICBib2R5Um93cy5lYWNoKGZ1bmN0aW9uKHJvd0RhdGEsIGkpe1xuICAgICAgdmFyIHQgPSBkMy5zZWxlY3QodGhpcylcbiAgICAgIHZhciBjb2xzID0gdC5zZWxlY3RBbGwoXCJ0ZFwiKVxuXG4gICAgICB1cGRhdGVUYWJsZVJvd0NvbHVtbnMoY29scywgaGVhZGVyS2V5cywgcm93RGF0YSwgdGFibGVEYXRhLCBsYXNzbywgdGFibGUpXG5cbiAgICAgIHQub24oXCJtb3VzZW92ZXJcIiwgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICBsYXNzby5hcHBseU9iamVjdEF0dHJpYnV0ZXMoZDMuc2VsZWN0KGRbXCJfX25vZGVcIl0pLHRydWUpXG4gICAgICB9KVxuICAgICAgLm9uKFwibW91c2VvdXRcIiwgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICBsYXNzby5hcHBseU9iamVjdEF0dHJpYnV0ZXMoZDMuc2VsZWN0KGRbXCJfX25vZGVcIl0pLGZhbHNlKVxuICAgICAgfSlcbiAgICB9KVxuXG5cbiAgfVxuXG5cblxuXG5cblxuXG4gIGZ1bmN0aW9uIG1ha2VOZXdHcm91cChkLCBpKSB7XG5cbiAgICB2YXIgdGFicyA9IHNlbGVjdGlvbi5zZWxlY3QoJy4nK2h5cGVuYXRlKG5hbWVzcGFjZSwgJ3RhYi1saXN0JykpLFxuICAgIHBhbmVzID0gc2VsZWN0aW9uLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCAndGFiLWNvbnRlbnQnKSksXG4gICAgbiA9IG5ld0dyb3VwTnVtYmVyKClcblxuICAgIGlmICh0YWJzLnNlbGVjdEFsbCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCd0YWInKSkuc2l6ZSgpID09IG1heE51bWJlck9mR3JvdXBzKSB7XG4gICAgICBvbkVycm9yKCdvbmx5ICcrbWF4TnVtYmVyT2ZHcm91cHMrJyBhbGxvd2VkLicsICd3YXJuaW5nJylcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHZhclxuICAgIHRhYiA9IGluc2VydFRhYih0YWJzLCBuKSxcbiAgICBwYW5lID0gbWFrZVRhYlBhbmUocGFuZXMsIG4pXG5cbiAgICBwb3B1bGF0ZVBhbmUocGFuZSwgbilcbiAgICB0b2dnbGVQYW5lQnlJZChwYW5lLmF0dHIoJ2lkJykpXG5cbiAgfVxuXG4gIGZ1bmN0aW9uIG5ld0dyb3VwTnVtYmVyKCkge1xuICAgIHZhciB0YWJzID0gc2VsZWN0aW9uLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCAndGFiLWxpc3QnKSkvLyxcbiAgICB2YXJcbiAgICBuID0gdGFicy5zZWxlY3RBbGwoJ2xpJykuc2l6ZSgpIC0gMywgLy8gbWludXMgMSBmb3IgcGx1cyB0YWJcbiAgICBzID0gJ0dyb3VwICcgKyBuLFxuICAgIGdzID0gW11cbiAgICB0YWJzLmVhY2goZnVuY3Rpb24oZCwgaSl7IHJldHVybiBncy5wdXNoKGQzLnNlbGVjdCh0aGlzKS5zZWxlY3QoXCJhXCIpLnRleHQoKSkgfSlcbiAgICB3aGlsZSAoZ3MuaW5jbHVkZXMocykpIHsgbis9MTsgcyA9ICdHcm91cCAnICsgbjsgfVxuICAgIHJldHVybiBuXG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVUYWJBbmRQYW5lTnVtYmVycygpIHtcbiAgICB2YXJcbiAgICB0YWJzID0gc2VsZWN0aW9uLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCAndGFiLWxpc3QnKSksXG4gICAgcGFuZXMgPSBzZWxlY3Rpb24uc2VsZWN0KCcuJytoeXBlbmF0ZShuYW1lc3BhY2UsICd0YWItY29udGVudCcpKVxuXG4gICAgdGFicyA9IHRhYnMuc2VsZWN0QWxsKCcuJytoeXBlbmF0ZShuYW1lc3BhY2UsJ3RhYicpKVxuICAgIHBhbmVzID0gcGFuZXMuc2VsZWN0QWxsKCcuJytoeXBlbmF0ZShuYW1lc3BhY2UsJ3RhYicsICdwYW5lJykpXG5cbiAgICB0YWJzLmVhY2goZnVuY3Rpb24oZCwgaSl7XG4gICAgICBkMy5zZWxlY3QodGhpcykuZGF0dW0oaSlcbiAgICAgIC5hdHRyKFwiaWRcIiwgaHlwZW5hdGUobmFtZXNwYWNlLCd0YWInLGkpKVxuICAgICAgLnNlbGVjdCgnYScpXG4gICAgICAuYXR0cignaHJlZicsICcjJytoeXBlbmF0ZShuYW1lc3BhY2UsJ3RhYicsJ3BhbmUnLGkpKVxuICAgICAgLnRleHQoZnVuY3Rpb24oZGQsIGlpKXtcbiAgICAgICAgdmFyIGN1clRleHQgPSBkMy5zZWxlY3QodGhpcykudGV4dCgpO1xuICAgICAgICBpZiAoY3VyVGV4dC5zcGxpdCgnICcpWzBdID09ICdHcm91cCcpIHtcbiAgICAgICAgICAgIHJldHVybiAnR3JvdXAgJyArIGlcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY3VyVGV4dFxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgcGFuZXMuZWFjaChmdW5jdGlvbihkLCBpKXtcbiAgICAgIGQzLnNlbGVjdCh0aGlzKS5kYXR1bShpKVxuICAgICAgLmF0dHIoJ2lkJywgaHlwZW5hdGUobmFtZXNwYWNlLCd0YWInLCdwYW5lJyxpKSlcbiAgICAgIHNhZmVTZWxlY3QoZDMuc2VsZWN0KHRoaXMpLCAncCcsICdsZWFkJylcbiAgICAgIC50ZXh0KGZ1bmN0aW9uKGRkLCBpaSl7XG4gICAgICAgIHZhciBjdXJUZXh0ID0gZDMuc2VsZWN0KHRoaXMpLnRleHQoKTtcbiAgICAgICAgaWYgKGN1clRleHQuc3BsaXQoJyAnKVswXSA9PSAnR3JvdXAnKSB7XG4gICAgICAgICAgICByZXR1cm4gJ0dyb3VwICcgKyBpXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGN1clRleHRcbiAgICAgIH0pXG4gICAgICBzYWZlU2VsZWN0KGQzLnNlbGVjdCh0aGlzKSwgJ2J1dHRvbicsICdyZW1vdmUtYnRuJylcbiAgICAgIC5vbignY2xpY2snLCByZW1vdmVCdG5DbGlja1RvUmVtb3ZlKVxuICAgIH0pXG5cbiAgfVxuXG4gIGZ1bmN0aW9uIGdhdGhlckRhdGFMaXN0cygpIHtcbiAgICB2YXIgdGFicyA9IHNlbGVjdGlvbi5zZWxlY3QoJy4nK2h5cGVuYXRlKG5hbWVzcGFjZSwgJ3RhYi1saXN0JykpXG4gICAgdmFyIHBhbmVzID0gc2VsZWN0aW9uLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCAndGFiLWNvbnRlbnQnKSlcbiAgICB2YXIgdGFibGVzID0gcGFuZXMuc2VsZWN0QWxsKCcuJytoeXBlbmF0ZShuYW1lc3BhY2UsIFwiZGF0YS10YWJsZVwiKSlcbiAgICB2YXIgZGF0YSA9IHt9XG5cbiAgICB2YXIgdGV4dEdyb3VwcyA9IHRhYnMuc2VsZWN0QWxsKCdsaS4nK2h5cGVuYXRlKG5hbWVzcGFjZSwndGFiJykgKyAnID4gYScpXG4gICAgLm5vZGVzKCkubWFwKGZ1bmN0aW9uKGQsIGkpe3JldHVybiBkMy5zZWxlY3QoZCkudGV4dCgpfSlcblxuICAgIHRleHRHcm91cHMubWFwKGZ1bmN0aW9uKGUsIGkpe1xuICAgICAgZGF0YVtlXSA9IFtdXG4gICAgfSlcblxuXG4gICAgdGFibGVzLmVhY2goZnVuY3Rpb24oZCwgaSl7XG4gICAgICB2YXIgdGFibGUgPSBkMy5zZWxlY3QodGhpcykuc2VsZWN0KFwidGJvZHlcIilcbiAgICAgIGRhdGFbdGV4dEdyb3Vwc1tpXV0gPSB0YWJsZS5zZWxlY3RBbGwoJ3RyJykuZGF0YSgpXG4gICAgfSlcblxuICAgIHJldHVybiBkYXRhXG4gIH1cblxuICBmdW5jdGlvbiBzaG93UmVtYWluaW5nUGFuZXMoKSB7XG4gICAgdmFyXG4gICAgdGFicyA9IHNlbGVjdGlvbi5zZWxlY3QoJy4nK2h5cGVuYXRlKG5hbWVzcGFjZSwgJ3RhYi1saXN0JykpLFxuICAgIHBhbmVzID0gc2VsZWN0aW9uLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCAndGFiLWNvbnRlbnQnKSksXG4gICAgcmVtYWluaW5nVGFicyA9IHRhYnMuc2VsZWN0QWxsKCcuJytoeXBlbmF0ZShuYW1lc3BhY2UsJ3RhYicpKVxuXG4gICAgaWYgKHJlbWFpbmluZ1RhYnMuc2l6ZSgpID09IDApIHtcbiAgICAgIHBhbmVzLnNlbGVjdCgnLicraHlwZW5hdGUobmFtZXNwYWNlLCdkZWZhdWx0LXRhYicpKVxuICAgICAgLmNsYXNzZWQoXCJhY3RpdmVcIiwgdHJ1ZSlcbiAgICAgIC5jbGFzc2VkKCd0ZXh0LWxlZnQnLCB0cnVlKVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHZhciBsYXN0VGFiID0gcmVtYWluaW5nVGFicy5ub2RlcygpW3JlbWFpbmluZ1RhYnMuc2l6ZSgpLTFdLFxuICAgICAgbGFzdFBhbmVJZCA9IGQzLnNlbGVjdChsYXN0VGFiKS5zZWxlY3QoJ2EnKS5hdHRyKCdocmVmJylcbiAgICAgIHBhbmVzLnNlbGVjdChsYXN0UGFuZUlkKVxuICAgICAgLmNsYXNzZWQoXCJhY3RpdmVcIiwgdHJ1ZSlcbiAgICAgIC5jbGFzc2VkKCd0ZXh0LWxlZnQnLCB0cnVlKVxuICAgIH1cbiAgfVxuXG5cbiAgcmV0dXJuIGxhc3NvV2lkZ2V0XG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHtzZXR1cENvbnRhaW5lciwgY2FsY3VsYXRlV2lkdGhPZk9iamVjdCwgY2FsY3VsYXRlV2lkdGhPZlNwYWNlciwgbG9nfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7dW5pcXVlLCBmbGF0dGVufSBmcm9tICcuL2FycmF5LWZ1bmN0aW9ucyc7XG5pbXBvcnQge2dyb3VwaW5nU3BhY2VyfSBmcm9tICcuL2dyb3VwaW5nLXNwYWNlcic7XG5pbXBvcnQge2NvbG9yRnVuY3Rpb24gYXMgQ0Z9IGZyb20gJy4vY29sb3ItZnVuY3Rpb24nO1xuaW1wb3J0IHt0b29sdGlwIGFzIFRUaXB9IGZyb20gJy4vdG9vbHRpcCc7XG5leHBvcnQgZnVuY3Rpb24gdXBzZXQgKCBzZWxlY3Rpb24gKSB7XG4gIHZhclxuICBkYXRhLFxuICBvcmllbnQ9J2hvcml6b250YWwnLFxuICBzcGFjZVgsXG4gIHNwYWNlWSxcbiAgb3ZlcmZsb3dRPWZhbHNlLFxuICBtaW5PYmplY3RTaXplPTIwLFxuICBtYXhPYmplY3RTaXplPTUwLFxuICBjaXJjbGVTdHJva2VXaWR0aD0yLFxuICAvLyBjb2xvckZ1bmN0aW9uPVxuICBiYWNrZ3JvdW5kRmlsbCA9ICd0cmFuc3BhcmVudCcsXG4gIG5hbWVzcGFjZT0nZDNzbS11cHNldCcsXG4gIG9iamVjdENsYXNzID0gJ3Vwc2V0JyxcblxuICB0cmFuc2l0aW9uRHVyYXRpb24gPSAxMDAwLFxuICBlYXNlRnVuYyA9IGQzLmVhc2VFeHAsXG5cbiAgc2V0S2V5ID0gXCJzZXRcIixcbiAgaW50ZXJzZWN0aW9uS2V5ID0gXCJpbnRlcnNlY3Rpb25cIixcbiAgZWxlbWVudHNLZXkgPSBcImVsZW1lbnRzXCIsXG5cbiAgc2V0RXh0cmFjdG9yID0gZnVuY3Rpb24oa2V5LCBpKSB7cmV0dXJuIGRhdGFba2V5XVtzZXRLZXldfSxcbiAgaW50ZXJzZWN0aW9uRXh0cmFjdG9yID0gZnVuY3Rpb24oa2V5LCBpKSB7cmV0dXJuIGRhdGFba2V5XVtpbnRlcnNlY3Rpb25LZXldfSxcbiAgZWxlbWVudEV4dHJhY3RvciA9IGZ1bmN0aW9uKGtleSwgaSkge3JldHVybiBkYXRhW2tleV1bZWxlbWVudHNLZXldfSxcblxuICBjZWxsS2V5cyxcbiAgc2V0VmFsdWVzLFxuICBpbnRlcnNlY3Rpb25WYWx1ZXMsXG4gIGVsZW1lbnRWYWx1ZXMsXG5cbiAgeE9iamVjdFNwYWNlciA9IDAuMDUsXG4gIHlPYmplY3RTcGFjZXIgPSAwLjA1LFxuICByYWRpdXMsXG5cbiAgLy8gbGlzdERlbGltID0gJzsnXG5cbiAgeU9iamVjdFNpemUsXG4gIHlTcGFjZXJTaXplLFxuICB4T2JqZWN0U2l6ZSxcbiAgeFNwYWNlclNpemUsXG5cbiAgc2V0S2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gc2V0VmFsdWVzLmluZGV4T2Yoc2V0RXh0cmFjdG9yKGEpKSAtIHNldFZhbHVlcy5pbmRleE9mKHNldEV4dHJhY3RvcihiKSkgfSxcbiAgaW50ZXJzZWN0aW9uS2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gaW50ZXJzZWN0aW9uVmFsdWVzLmluZGV4T2YoaW50ZXJzZWN0aW9uRXh0cmFjdG9yKGEpKSAtIGludGVyc2VjdGlvblZhbHVlcy5pbmRleE9mKGludGVyc2VjdGlvbkV4dHJhY3RvcihiKSkgfVxuXG5cbiAgdXBzZXQuc2VsZWN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZWxlY3Rpb24gPSBfLCB1cHNldCkgOiBzZWxlY3Rpb247IH07XG4gIHVwc2V0LmRhdGEgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRhdGEgPSBfLCB1cHNldCkgOiBkYXRhOyB9O1xuICB1cHNldC5vcmllbnQgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9yaWVudCA9IF8sIHVwc2V0KSA6IG9yaWVudDsgfTtcbiAgdXBzZXQuc3BhY2VYID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzcGFjZVggPSBfLCB1cHNldCkgOiBzcGFjZVg7IH07XG4gIHVwc2V0LnNwYWNlWSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3BhY2VZID0gXywgdXBzZXQpIDogc3BhY2VZOyB9O1xuICB1cHNldC5vdmVyZmxvd1EgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG92ZXJmbG93USA9IF8sIHVwc2V0KSA6IG92ZXJmbG93UTsgfTtcbiAgdXBzZXQubWluT2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobWluT2JqZWN0U2l6ZSA9IF8sIHVwc2V0KSA6IG1pbk9iamVjdFNpemU7IH07XG4gIHVwc2V0Lm1heE9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG1heE9iamVjdFNpemUgPSBfLCB1cHNldCkgOiBtYXhPYmplY3RTaXplOyB9O1xuICB1cHNldC5jaXJjbGVTdHJva2VXaWR0aCA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY2lyY2xlU3Ryb2tlV2lkdGggPSBfLCB1cHNldCkgOiBjaXJjbGVTdHJva2VXaWR0aDsgfTtcbiAgdXBzZXQuYmFja2dyb3VuZEZpbGwgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGJhY2tncm91bmRGaWxsID0gXywgdXBzZXQpIDogYmFja2dyb3VuZEZpbGw7IH07XG4gIHVwc2V0Lm5hbWVzcGFjZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobmFtZXNwYWNlID0gXywgdXBzZXQpIDogbmFtZXNwYWNlOyB9O1xuICB1cHNldC5vYmplY3RDbGFzcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAob2JqZWN0Q2xhc3MgPSBfLCB1cHNldCkgOiBvYmplY3RDbGFzczsgfTtcbiAgdXBzZXQudHJhbnNpdGlvbkR1cmF0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0cmFuc2l0aW9uRHVyYXRpb24gPSBfLCB1cHNldCkgOiB0cmFuc2l0aW9uRHVyYXRpb247IH07XG4gIHVwc2V0LmVhc2VGdW5jID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChlYXNlRnVuYyA9IF8sIHVwc2V0KSA6IGVhc2VGdW5jOyB9O1xuICB1cHNldC5jZWxsS2V5cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY2VsbEtleXMgPSBfLCB1cHNldCkgOiBjZWxsS2V5czsgfTtcbiAgdXBzZXQuc2V0VmFsdWVzID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzZXRWYWx1ZXMgPSBfLCB1cHNldCkgOiBzZXRWYWx1ZXM7IH07XG4gIHVwc2V0LmludGVyc2VjdGlvblZhbHVlcyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaW50ZXJzZWN0aW9uVmFsdWVzID0gXywgdXBzZXQpIDogaW50ZXJzZWN0aW9uVmFsdWVzOyB9O1xuICB1cHNldC54T2JqZWN0U3BhY2VyID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4T2JqZWN0U3BhY2VyID0gXywgdXBzZXQpIDogeE9iamVjdFNwYWNlcjsgfTtcbiAgdXBzZXQueU9iamVjdFNwYWNlciA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeU9iamVjdFNwYWNlciA9IF8sIHVwc2V0KSA6IHlPYmplY3RTcGFjZXI7IH07XG4gIHVwc2V0LnJhZGl1cyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocmFkaXVzID0gXywgdXBzZXQpIDogcmFkaXVzOyB9O1xuICB1cHNldC5zZXRFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNldEV4dHJhY3RvciA9IF8sIHVwc2V0KSA6IHNldEV4dHJhY3RvcjsgfTtcbiAgdXBzZXQuaW50ZXJzZWN0aW9uRXh0cmFjdG9yID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChpbnRlcnNlY3Rpb25FeHRyYWN0b3IgPSBfLCB1cHNldCkgOiBpbnRlcnNlY3Rpb25FeHRyYWN0b3I7IH07XG4gIHVwc2V0LmVsZW1lbnRFeHRyYWN0b3IgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGVsZW1lbnRFeHRyYWN0b3IgPSBfLCB1cHNldCkgOiBlbGVtZW50RXh0cmFjdG9yOyB9O1xuICB1cHNldC5zZXRLZXlTb3J0aW5nRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNldEtleVNvcnRpbmdGdW5jdGlvbiA9IF8sIHVwc2V0KSA6IHNldEtleVNvcnRpbmdGdW5jdGlvbjsgfTtcbiAgdXBzZXQuaW50ZXJzZWN0aW9uS2V5U29ydGluZ0Z1bmN0aW9uID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChpbnRlcnNlY3Rpb25LZXlTb3J0aW5nRnVuY3Rpb24gPSBfLCB1cHNldCkgOiBpbnRlcnNlY3Rpb25LZXlTb3J0aW5nRnVuY3Rpb247IH07XG5cbiAgdXBzZXQueU9iamVjdFNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHlPYmplY3RTaXplID0gXywgdXBzZXQpIDogeU9iamVjdFNpemU7IH07XG4gIHVwc2V0LnlTcGFjZXJTaXplID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5U3BhY2VyU2l6ZSA9IF8sIHVwc2V0KSA6IHlTcGFjZXJTaXplOyB9O1xuICB1cHNldC54T2JqZWN0U2l6ZSA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeE9iamVjdFNpemUgPSBfLCB1cHNldCkgOiB4T2JqZWN0U2l6ZTsgfTtcbiAgdXBzZXQueFNwYWNlclNpemUgPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHhTcGFjZXJTaXplID0gXywgdXBzZXQpIDogeFNwYWNlclNpemU7IH07XG5cbiAgZnVuY3Rpb24gdXBzZXQoKSB7XG4gICAgLy8gZm9yIGNvbnZlbmllbmNlIGluIGhhbmRsaW5nIG9yaWVudGF0aW9uIHNwZWNpZmljIHZhbHVlc1xuICAgIHZhciBob3Jpem9udGFsUSA9IChvcmllbnQgPT0gJ2hvcml6b250YWwnKSA/IHRydWUgOiBmYWxzZVxuICAgIHZhciB2ZXJ0aWNhbFEgPSAhaG9yaXpvbnRhbFFcblxuICAgIC8vIGJhY2tncm91bmQgY2xpcGluZyByZWN0YW5nbGVcbiAgICB2YXIgYmdjcFJlY3QgPSB7eDowLCB5OjAsIHdpZHRoOiBzcGFjZVgsIGhlaWdodDpzcGFjZVl9XG4gICAgdmFyIGNvbnRhaW5lciA9IHNldHVwQ29udGFpbmVyKCBzZWxlY3Rpb24sIG5hbWVzcGFjZSwgYmdjcFJlY3QsIGJhY2tncm91bmRGaWxsICk7XG5cblxuICAgIGNlbGxLZXlzID0gZDMua2V5cyhkYXRhKVxuICAgIHNldFZhbHVlcyA9IHVuaXF1ZShjZWxsS2V5cy5tYXAoc2V0RXh0cmFjdG9yKSkuc29ydCgpXG4gICAgaW50ZXJzZWN0aW9uVmFsdWVzID0gdW5pcXVlKGNlbGxLZXlzLm1hcChpbnRlcnNlY3Rpb25FeHRyYWN0b3IpKS5zb3J0KCkuc29ydChmdW5jdGlvbihhLCBiKXtcbiAgICAgIHJldHVybiBhLnNwbGl0KCc7JykubGVuZ3RoIC0gYi5zcGxpdCgnOycpLmxlbmd0aFxuICAgIH0pXG5cbiAgICBpZiAoIWhvcml6b250YWxRKSB7XG4gICAgICBjZWxsS2V5cy5zb3J0KGZ1bmN0aW9uKGEsIGIpeyByZXR1cm4gc2V0S2V5U29ydGluZ0Z1bmN0aW9uKGEsIGIpIHx8IGludGVyc2VjdGlvbktleVNvcnRpbmdGdW5jdGlvbihhLCBiKSB9KVxuICAgIH0gZWxzZSB7XG4gICAgICBjZWxsS2V5cy5zb3J0KGZ1bmN0aW9uKGEsIGIpeyByZXR1cm4gaW50ZXJzZWN0aW9uS2V5U29ydGluZ0Z1bmN0aW9uKGEsIGIpIHx8IHNldEtleVNvcnRpbmdGdW5jdGlvbihhLCBiKSB9KVxuICAgIH1cblxuXG5cblxuICAgIHZhclxuICAgIHhWYWx1ZXMgPSBob3Jpem9udGFsUSA/IGludGVyc2VjdGlvblZhbHVlcyA6IHNldFZhbHVlcyxcbiAgICB5VmFsdWVzID0gaG9yaXpvbnRhbFEgPyBzZXRWYWx1ZXMgOiBpbnRlcnNlY3Rpb25WYWx1ZXMsXG4gICAgeERpbSA9IGhvcml6b250YWxRID8geFZhbHVlcy5sZW5ndGggOiB5VmFsdWVzLmxlbmd0aCxcbiAgICB5RGltID0gaG9yaXpvbnRhbFEgPyB5VmFsdWVzLmxlbmd0aCA6IHhWYWx1ZXMubGVuZ3RoXG5cbiAgICAvLyBjb25zb2xlLmxvZyh4VmFsdWVzLCB5VmFsdWVzKVxuXG5cbiAgICB4T2JqZWN0U2l6ZSA9IGNhbGN1bGF0ZVdpZHRoT2ZPYmplY3Qoc3BhY2VYLCB4RGltLCBtaW5PYmplY3RTaXplLCBtYXhPYmplY3RTaXplLCB4T2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgeU9iamVjdFNpemUgPSBjYWxjdWxhdGVXaWR0aE9mT2JqZWN0KHNwYWNlWSwgeURpbSwgbWluT2JqZWN0U2l6ZSwgbWF4T2JqZWN0U2l6ZSwgeU9iamVjdFNwYWNlciwgb3ZlcmZsb3dRKVxuICAgIHhTcGFjZXJTaXplID0gY2FsY3VsYXRlV2lkdGhPZlNwYWNlcih4VmFsdWVzLCBzcGFjZVgsIHhPYmplY3RTaXplLCB4RGltLCB4T2JqZWN0U3BhY2VyLCBvdmVyZmxvd1EpXG4gICAgeVNwYWNlclNpemUgPSBjYWxjdWxhdGVXaWR0aE9mU3BhY2VyKHlWYWx1ZXMsIHNwYWNlWSwgeU9iamVjdFNpemUsIHlEaW0sIHlPYmplY3RTcGFjZXIsIG92ZXJmbG93USlcblxuICAgIHZhciB5U3BhY2VyID0gZ3JvdXBpbmdTcGFjZXIoKVxuICAgIC5ob3Jpem9udGFsUShmYWxzZSlcbiAgICAubW92ZWJ5KCdjYXRlZ29yeScpLm51bWJlck9mT2JqZWN0cyh5RGltKVxuICAgIC5vYmplY3RTaXplKHlPYmplY3RTaXplKS5zcGFjZXJTaXplKHlTcGFjZXJTaXplKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlRnVuYyhlYXNlRnVuYylcblxuICAgIHZhciB4U3BhY2VyID0gZ3JvdXBpbmdTcGFjZXIoKVxuICAgIC5ob3Jpem9udGFsUSh0cnVlKVxuICAgIC5tb3ZlYnkoJ2NhdGVnb3J5JykubnVtYmVyT2ZPYmplY3RzKHhEaW0pXG4gICAgLm9iamVjdENsYXNzKG9iamVjdENsYXNzKVxuICAgIC5vYmplY3RTaXplKHhPYmplY3RTaXplKS5zcGFjZXJTaXplKHhTcGFjZXJTaXplKVxuICAgIC50cmFuc2l0aW9uRHVyYXRpb24odHJhbnNpdGlvbkR1cmF0aW9uKS5lYXNlRnVuYyhlYXNlRnVuYylcblxuXG5cbiAgICBpZiAodmVydGljYWxRKSB7XG4gICAgICB4U3BhY2VyLm9iamVjdENsYXNzKG9iamVjdENsYXNzKVxuICAgICAgeVNwYWNlci5uYW1lc3BhY2UoJ2Fjcm9zcycpLm9iamVjdENsYXNzKGh5cGVuYXRlKG9iamVjdENsYXNzLCAnYWNyb3NzJykpXG5cbiAgICAgIHlTcGFjZXIoY29udGFpbmVyLCB5VmFsdWVzLCAwKVxuICAgICAgY29udGFpbmVyLnNlbGVjdEFsbCgnZy4nK2h5cGVuYXRlKG9iamVjdENsYXNzLCAnYWNyb3NzJykpXG4gICAgICAuZWFjaChmdW5jdGlvbihkLCBpKXsgeFNwYWNlcihkMy5zZWxlY3QodGhpcyksIHhWYWx1ZXMsIDApIH0pXG4gICAgfSBlbHNlIHtcbiAgICAgIHhTcGFjZXIubmFtZXNwYWNlKCdhY3Jvc3MnKS5vYmplY3RDbGFzcyhoeXBlbmF0ZShvYmplY3RDbGFzcywgJ2Fjcm9zcycpKVxuICAgICAgeVNwYWNlci5vYmplY3RDbGFzcyhvYmplY3RDbGFzcylcblxuICAgICAgeFNwYWNlcihjb250YWluZXIsIHhWYWx1ZXMsIDApXG4gICAgICBjb250YWluZXIuc2VsZWN0QWxsKCdnLicraHlwZW5hdGUob2JqZWN0Q2xhc3MsICdhY3Jvc3MnKSlcbiAgICAgIC5lYWNoKGZ1bmN0aW9uKGQsIGkpeyB5U3BhY2VyKGQzLnNlbGVjdCh0aGlzKSwgeVZhbHVlcywgMCkgfSlcbiAgICB9XG5cblxuICAgIHZhciBjZWxscyA9IGNvbnRhaW5lci5zZWxlY3RBbGwoJ2c6bm90KC50by1yZW1vdmUpLicrb2JqZWN0Q2xhc3MpXG4gICAgdmFyIGxvb2t1cCA9IHt9XG4gICAgY2VsbEtleXMubWFwKGZ1bmN0aW9uKGssIGkpe1xuICAgICAgbG9va3VwW3NldEV4dHJhY3RvcihrKSsnOjonK2ludGVyc2VjdGlvbkV4dHJhY3RvcihrKV0gPSBrXG4gICAgfSlcblxuICAgIC8vIHZhciBwb3NpdGlvbmVkQ2VsbEtleXMgPSBbXVxuICAgIC8vIGZvciAodmFyIGkgPSAwOyBpIDwgc2V0VmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgLy8gICBmb3IgKHZhciBqID0gMDsgaiA8IGludGVyc2VjdGlvblZhbHVlcy5sZW5ndGg7IGorKykge1xuICAgIC8vICAgICB2YXIgbG9va3VwVmFsdWUgPSBsb29rdXBbc2V0VmFsdWVzW2pdK1wiOjpcIitpbnRlcnNlY3Rpb25WYWx1ZXNbaV1dXG4gICAgLy8gICAgIGlmIChsb29rdXBWYWx1ZSA9PSB1bmRlZmluZWQpIHtcbiAgICAvLyAgICAgICBwb3NpdGlvbmVkQ2VsbEtleXMucHVzaCh1bmRlZmluZWQpXG4gICAgLy8gICAgIH0gZWxzZSB7XG4gICAgLy8gICAgICAgcG9zaXRpb25lZENlbGxLZXlzLnB1c2gobG9va3VwVmFsdWUpXG4gICAgLy8gICAgIH1cbiAgICAvLyAgICAgY29uc29sZS5sb2coaSwgaiwgbG9va3VwVmFsdWUpXG4gICAgLy8gICB9XG4gICAgLy8gfVxuICAgIC8vXG4gICAgLy8gLy8gY29uc29sZS5sb2cocG9zaXRpb25lZENlbGxLZXlzKVxuICAgIC8vXG4gICAgLy8gY2VsbHMuZGF0YShwb3NpdGlvbmVkQ2VsbEtleXMpO1xuXG5cbiAgICBjZWxscy5kYXRhKGNlbGxLZXlzKTtcblxuICAgIGNlbGxzLmVhY2goZnVuY3Rpb24oa2V5LCBpKSB7XG4gICAgICB2YXIgdCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgICAgaWYgKGtleSA9PSB1bmRlZmluZWQpIHtyZXR1cm4gfVxuICAgICAgdmFyXG4gICAgICBjdXJyZW50RGF0YSA9IGRhdGFba2V5XVxuICAgICAgLy8gY29uc29sZS5sb2coa2V5LCBjdXJyZW50RGF0YSlcbiAgICAgIHZhclxuICAgICAgc2V0ID0gc2V0RXh0cmFjdG9yKGtleSwgaSksXG4gICAgICBpbnRlcnNlY3Rpb24gPSBpbnRlcnNlY3Rpb25FeHRyYWN0b3Ioa2V5LCBpKVxuXG4gICAgICAvLyBjb25zb2xlLmxvZyhzZXQsIGludGVyc2VjdGlvbilcblxuICAgICAgdC5jbGFzc2VkKGludGVyc2VjdGlvbiwgdHJ1ZSlcbiAgICAgIHQuY2xhc3NlZChzZXQsIHRydWUpXG5cbiAgICAgIHZhciBjID0gc2FmZVNlbGVjdCh0LCAnY2lyY2xlJywgaHlwZW5hdGUob2JqZWN0Q2xhc3MsJ2NpcmNsZScpKVxuICAgICAgYy5hdHRyKCdjeCcsIHhPYmplY3RTaXplIC8gMilcbiAgICAgIC5hdHRyKCdjeScsIHlPYmplY3RTaXplIC8gMiApXG4gICAgICAuYXR0cigncicsIHJhZGl1cyA9PSB1bmRlZmluZWQgPyBNYXRoLm1pbih4T2JqZWN0U2l6ZSwgeU9iamVjdFNpemUpIC8gMiA6IHJhZGl1cylcbiAgICAgIC5hdHRyKCdmaWxsJywgaW50ZXJzZWN0aW9uLmluY2x1ZGVzKHNldCkgPyBcImJsYWNrXCI6ICdyZ2IoMjMzLDIzMywyMzMpJylcbiAgICAgIC5hdHRyKCdzdHJva2UnLCBcImJsYWNrXCIpXG4gICAgICAuYXR0cihcImluLWludGVyc2VjdGlvblwiLCBpbnRlcnNlY3Rpb24uaW5jbHVkZXMoc2V0KSlcbiAgICB9KVxuXG5cblxuICB9XG5cbiAgZnVuY3Rpb24gaW50ZXJzZWN0aW9uVG90YWxzKCkge1xuICAgIHZhciB0b3RhbHMgPSB7fVxuICAgIC8vIGludGVyc2VjdGlvblZhbHVlcy5zb3J0KGZ1bmN0aW9uKGEsIGIpeyByZXR1cm4gaW50ZXJzZWN0aW9uS2V5U29ydGluZ0Z1bmN0aW9uKGEsIGIpIH0pXG5cbiAgICBpbnRlcnNlY3Rpb25WYWx1ZXMubWFwKGZ1bmN0aW9uKGssIGkpeyB0b3RhbHNba10gPSB7J3RvdGFsJzogMH0gfSlcbiAgICBjZWxsS2V5cy5tYXAoZnVuY3Rpb24oaywgaSl7XG4gICAgICB2YXIgZSA9IGVsZW1lbnRFeHRyYWN0b3IoaywgaSk7XG4gICAgICBpZiAodG90YWxzW2ludGVyc2VjdGlvbkV4dHJhY3RvcihrLCBpKV1bJ3RvdGFsJ10gPT0gMCkge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShlKSkge1xuICAgICAgICAgIHRvdGFsc1tpbnRlcnNlY3Rpb25FeHRyYWN0b3IoaywgaSldWyd0b3RhbCddKz0gZS5sZW5ndGhcbiAgICAgICAgICB0b3RhbHNbaW50ZXJzZWN0aW9uRXh0cmFjdG9yKGssIGkpXVsndmFsdWVzJ10gPSBlXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdG90YWxzW2ludGVyc2VjdGlvbkV4dHJhY3RvcihrLCBpKV1bJ3RvdGFsJ10rPSBlXG4gICAgICAgIH1cblxuICAgICAgfVxuICAgIH0pXG4gICAgcmV0dXJuIHRvdGFsc1xuICB9XG5cbiAgZnVuY3Rpb24gc2V0VG90YWxzKCl7XG4gICAgdmFyIHRvdGFscyA9IHt9XG4gICAgLy8gaW50ZXJzZWN0aW9uVmFsdWVzLnNvcnQoZnVuY3Rpb24oYSwgYil7IHJldHVybiBpbnRlcnNlY3Rpb25LZXlTb3J0aW5nRnVuY3Rpb24oYSwgYikgfSlcblxuICAgIHNldFZhbHVlcy5tYXAoZnVuY3Rpb24oaywgaSl7IHRvdGFsc1trXSA9IHsndG90YWwnOiAwfSB9KVxuXG4gICAgY2VsbEtleXMubWFwKGZ1bmN0aW9uKGssIGkpe1xuICAgICAgdmFyIGUgPSBlbGVtZW50RXh0cmFjdG9yKGssIGkpO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZSkpIHtcbiAgICAgICAgdG90YWxzW3NldEV4dHJhY3RvcihrLCBpKV1bJ3RvdGFsJ10rPSBlLmxlbmd0aFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdG90YWxzW3NldEV4dHJhY3RvcihrLCBpKV1bJ3RvdGFsJ10rPSBlXG4gICAgICB9XG4gICAgfSlcbiAgICByZXR1cm4gdG90YWxzXG4gIH1cblxuICB1cHNldC5pbnRlcnNlY3Rpb25Ub3RhbHMgPSBpbnRlcnNlY3Rpb25Ub3RhbHNcbiAgdXBzZXQuc2V0VG90YWxzID0gc2V0VG90YWxzXG5cbiAgcmV0dXJuIHVwc2V0XG59XG4iLCJpbXBvcnQge2h5cGVuYXRlLCBzYWZlU2VsZWN0fSBmcm9tICcuL2hlbHBlcnMnO1xuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlclRhYmxlKHNlbGVjdGlvbikge1xuICB2YXJcbiAgZGF0YSxcbiAgbmFtZXNwYWNlID0gJ2Qzc20tZmlsdGVyLXRhYmxlJyxcbiAgc29ydFEgPSBmYWxzZSxcbiAgZmllbGRGdW5jdGlvbiA9IGZ1bmN0aW9uKHJlY29yZCwgY29sdW1uS2V5LCByZWNvcmRWYWx1ZSkge3JldHVybiByZWNvcmRWYWx1ZX1cblxuICBmaWx0ZXJUYWJsZS5kYXRhID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkYXRhID0gXywgZmlsdGVyVGFibGUpIDogZGF0YX1cbiAgZmlsdGVyVGFibGUubmFtZXNwYWNlID0gZnVuY3Rpb24oXykgeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChuYW1lc3BhY2UgPSBfLCBmaWx0ZXJUYWJsZSkgOiBuYW1lc3BhY2V9XG4gIGZpbHRlclRhYmxlLmZpZWxkRnVuY3Rpb24gPSBmdW5jdGlvbihfKSB7IHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGZpZWxkRnVuY3Rpb24gPSBfLCBmaWx0ZXJUYWJsZSkgOiBmaWVsZEZ1bmN0aW9ufVxuXG4gIGZ1bmN0aW9uIGZpbHRlclRhYmxlICgpIHtcblxuICAgIHZhclxuICAgIGNvbnRhaW5lciA9IHNhZmVTZWxlY3Qoc2VsZWN0aW9uLCAnZGl2JywgJ2ZpbHRlci10YWJsZScpLmNsYXNzZWQoaHlwZW5hdGUobmFtZXNwYWNlLCdjb250YWluZXInKSx0cnVlKSxcblxuICAgIGlucHV0R3JvdXAgPSBzYWZlU2VsZWN0KGNvbnRhaW5lciwgJ2RpdicsICdmaWx0ZXItaW5wdXQtZ3JvdXAnKS5jbGFzc2VkKCdpbnB1dC1ncm91cCcsdHJ1ZSksXG4gICAgICBpbnB1dFByZXBlbmQgPSBzYWZlU2VsZWN0KGlucHV0R3JvdXAsICdkaXYnLCAnaW5wdXQtZ3JvdXAtcHJlcGVuZCcpLFxuICAgICAgICBpbnB1dFByZXBlbmRTcGFuID0gc2FmZVNlbGVjdChpbnB1dFByZXBlbmQsICdzcGFuJywgJ2lucHV0LWdyb3VwLXRleHQnKS5jbGFzc2VkKCdzZWFyY2gtYnV0dG9uJywgdHJ1ZSksXG4gICAgICAgICAgaW5wdXRQcmVwZW5kU3Bhbkljb24gPSBzYWZlU2VsZWN0KGlucHV0UHJlcGVuZFNwYW4sJ2knLCdmYSBmYS1zZWFyY2gnKSxcblxuICAgICAgaW5wdXQgPSBzYWZlU2VsZWN0KGlucHV0R3JvdXAsICdpbnB1dCcsICdmb3JtLWNvbnRyb2wnKS5hdHRyKCdwbGFjZWhvbGRlcicsICdmaWx0ZXInKS5hdHRyKCd0eXBlJywgJ3RleHQnKSxcbiAgICAgIGlucHV0QXBwZW5kID0gc2FmZVNlbGVjdChpbnB1dEdyb3VwLCAnZGl2JywgJ2lucHV0LWdyb3VwLWFwcGVuZCcpLFxuICAgICAgICBpbnB1dEFwcGVuZEJ1dHRvbiA9IHNhZmVTZWxlY3QoaW5wdXRBcHBlbmQsICdhJywgJ2Nsb3NlLWJ1dHRvbicpLmNsYXNzZWQoJ2J0biBidG4tb3V0bGluZS1zZWNvbmRhcnknLCB0cnVlKSxcbiAgICAgICAgICBpbnB1dEFwcGVuZEJ1dHRvbkljb24gPSBzYWZlU2VsZWN0KGlucHV0QXBwZW5kQnV0dG9uLCAnaScsICdmYSBmYS1jbG9zZScpLFxuXG5cbiAgICBjbG9zZUJ1dHRvbiA9IGlucHV0QXBwZW5kQnV0dG9uLFxuXG4gICAgclRhYmxlID0gc2FmZVNlbGVjdChjb250YWluZXIsICdkaXYnLCAndGFibGUtcmVzcG9uc2l2ZScpLFxuICAgICAgdGFibGUgPSBzYWZlU2VsZWN0KHJUYWJsZSwgJ3RhYmxlJywgJ3RhYmxlJylcbiAgICAgIC5jbGFzc2VkKCd0YWJsZS1ob3ZlcicsIHRydWUpXG4gICAgICAuY2xhc3NlZCgndGFibGUtYm9yZGVyZWQnLCB0cnVlKVxuICAgICAgLmNsYXNzZWQoXCJ0YWJsZS1zdHJpcGVkXCIsIHRydWUpLFxuICAgICAgICB0SGVhZCA9IHNhZmVTZWxlY3QodGFibGUsICd0aGVhZCcpXG4gICAgICAgIC5jbGFzc2VkKFwidGhlYWQtZGFya1wiLCB0cnVlKSxcbiAgICAgICAgICBoZWFkZXIgPSBzYWZlU2VsZWN0KHRIZWFkLCAndHInKSxcbiAgICAgICAgdEJvZHkgPSBzYWZlU2VsZWN0KHRhYmxlLCAndGJvZHknKVxuXG5cbiAgICB2YXJcbiAgICByb3dzID0gZDMua2V5cyhkYXRhKSxcbiAgICBjb2xzID0gZDMua2V5cyhkYXRhW3Jvd3NbMF1dKVxuXG4gICAgdmFyIHRoID0gbWFrZUNvbHVtbnMoaGVhZGVyLCBjb2xzKVxuICAgIHZhciB0ciA9IG1ha2VSb3dzKHRCb2R5LCByb3dzKVxuICAgIHZhciB0ciA9IHBvcHVsYXRlUmVjb3Jkcyh0ciwgY29scylcblxuXG5cbiAgICBpbnB1dC5vbignaW5wdXQnLCBmdW5jdGlvbihkLCBpKXtcbiAgICAgIHZhclxuICAgICAgdmFsID0gaW5wdXQucHJvcGVydHkoJ3ZhbHVlJyksXG4gICAgICByZWcgPSBuZXcgUmVnRXhwKHZhbCwgJ2dpJyksXG4gICAgICB1c2VcbiAgICAgIGlmICh2YWwgPT0gJycpIHt1c2UgPSByb3dzfSBlbHNlIHtcbiAgICAgICAgdXNlID0gW11cbiAgICAgICAgcm93cy5tYXAoZnVuY3Rpb24ociwgaSl7XG4gICAgICAgICAgdmFyIHJvdyA9IGRhdGFbcl1cbiAgICAgICAgICB2YXIgZmllbGRKb2luID0gY29scy5tYXAoZnVuY3Rpb24oYywgail7XG4gICAgICAgICAgICByZXR1cm4gZmllbGRGdW5jdGlvbihyb3csIGMsIHJvd1tjXSlcbiAgICAgICAgICAgIC8vIHJldHVybiByb3dbY11cbiAgICAgICAgICB9KS5qb2luKCcnKVxuICAgICAgICAgIHZhciBtYXRjaCA9IGZpZWxkSm9pbi5tYXRjaChyZWcpXG4gICAgICAgICAgaWYgKG1hdGNoID09IG51bGwgfHwgbWF0Y2guam9pbignJykgPT0gJycpIHt9XG4gICAgICAgICAgZWxzZSB7IHVzZS5wdXNoKHIpIH1cbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgdHIgPSBtYWtlUm93cyh0Qm9keSwgdXNlKVxuICAgICAgdHIgPSBwb3B1bGF0ZVJlY29yZHModHIsIGNvbHMpXG4gICAgfSlcblxuICAgIGNsb3NlQnV0dG9uLm9uKCdjbGljaycsIGZ1bmN0aW9uKGQsIGkpe1xuICAgICAgaW5wdXQucHJvcGVydHkoJ3ZhbHVlJywgJycpLmRpc3BhdGNoKCdpbnB1dCcpXG4gICAgfSlcblxuICB9XG5cbiAgZnVuY3Rpb24gbWFrZUNvbHVtbnMoaGVhZGVyLCBjb2xzKSB7XG4gICAgdmFyIHRoID0gaGVhZGVyLnNlbGVjdEFsbCgndGgnKVxuICAgIHRoID0gdGguZGF0YShjb2xzKVxuICAgIHRoLmV4aXQoKS5yZW1vdmUoKVxuICAgIHRoID0gdGgubWVyZ2UodGguZW50ZXIoKS5hcHBlbmQoJ3RoJykpXG4gICAgdGguYXR0cignc2NvcGUnLCAnY29sJykudGV4dChmdW5jdGlvbihkLCBpKXtyZXR1cm4gZH0pXG4gICAgcmV0dXJuIHRoXG4gIH1cblxuICBmdW5jdGlvbiBtYWtlUm93cyhib2R5LCByb3dzKSB7XG4gICAgdmFyIHRyID0gYm9keS5zZWxlY3RBbGwoJ3RyJylcbiAgICB0ciA9IHRyLmRhdGEocm93cylcbiAgICB0ci5leGl0KCkucmVtb3ZlKClcbiAgICB0ciA9IHRyLm1lcmdlKHRyLmVudGVyKCkuYXBwZW5kKCd0cicpKVxuICAgIHJldHVybiB0clxuICB9XG5cbiAgZnVuY3Rpb24gcG9wdWxhdGVSZWNvcmRzKHJvd3MsIGNvbHMpIHtcbiAgICByb3dzLmVhY2goZnVuY3Rpb24ociwgaSl7XG4gICAgICB2YXIgcmVjb3JkID0gZGF0YVtyXSxcbiAgICAgIHQgPSBkMy5zZWxlY3QodGhpcylcblxuICAgICAgdmFyIGZpZWxkcyA9IHQuc2VsZWN0QWxsKCd0ZCcpXG4gICAgICBmaWVsZHMgPSBmaWVsZHMuZGF0YShjb2xzKVxuICAgICAgZmllbGRzLmV4aXQoKS5yZW1vdmUoKVxuICAgICAgZmllbGRzID0gZmllbGRzLm1lcmdlKGZpZWxkcy5lbnRlcigpLmFwcGVuZCgndGQnKSlcblxuICAgICAgZmllbGRzLmF0dHIoJ3Njb3BlJywgZnVuY3Rpb24oZiwgail7IHJldHVybiBqID09IDAgfSlcbiAgICAgIC5odG1sKGZ1bmN0aW9uKGYsIGopeyByZXR1cm4gZmllbGRGdW5jdGlvbihyZWNvcmQsIGYsIHJlY29yZFtmXSkgfSlcblxuICAgIH0pXG4gICAgcmV0dXJuIHJvd3NcbiAgfVxuXG5cblxuICByZXR1cm4gZmlsdGVyVGFibGVcbn1cbiJdLCJuYW1lcyI6WyJ1bmlxdWVFbGVtZW50cyIsInZhbHVlIiwiaW5kZXgiLCJzZWxmIiwiaW5kZXhPZiIsImdldFRyYW5zbGF0aW9uIiwidHJhbnNmb3JtIiwiZyIsImRvY3VtZW50IiwiY3JlYXRlRWxlbWVudE5TIiwidW5kZWZpbmVkIiwic2V0QXR0cmlidXRlTlMiLCJtYXRyaXgiLCJiYXNlVmFsIiwiY29uc29saWRhdGUiLCJlIiwiZiIsIm1vZGlmeUhleGlkZWNpbWFsQ29sb3JMdW1pbmFuY2UiLCJoZXgiLCJsdW0iLCJTdHJpbmciLCJyZXBsYWNlIiwibGVuZ3RoIiwiYyIsImkiLCJyZ2IiLCJwYXJzZUludCIsInN1YnN0ciIsIk1hdGgiLCJyb3VuZCIsIm1pbiIsIm1heCIsInRvU3RyaW5nIiwicXVhcnRpbGVzIiwiZGF0YSIsInFLZXlzIiwicTIiLCJkMyIsIm1lZGlhbiIsImxvd2VyIiwiZmlsdGVyIiwieCIsInVwcGVyIiwicTEiLCJxMCIsInEzIiwicTQiLCJrMCIsImsxIiwiazIiLCJrMyIsIms0Iiwib2JqIiwiaHlwZW5hdGUiLCJBcnJheSIsInByb3RvdHlwZSIsInNsaWNlIiwiY2FsbCIsImFyZ3VtZW50cyIsImpvaW4iLCJudW1iZXIiLCJwcmVjaXNpb24iLCJzaGlmdCIsInJldmVyc2VTaGlmdCIsIm51bUFycmF5Iiwic3BsaXQiLCJnZXRDb250YWluaW5nU1ZHIiwiZWxlbWVudCIsInBhcmVudCIsInBhcmVudEVsZW1lbnQiLCJ0YWciLCJ0YWdOYW1lIiwidG9Mb3dlckNhc2UiLCJzYWZlU2VsZWN0Iiwic2VsIiwiY2xzIiwiY2xzU3RyIiwic1NlbCIsInNlbGVjdCIsImVtcHR5IiwiYXBwZW5kIiwiY2xhc3NlZCIsImF0dHIiLCJ0aWNrUmFuZ2UiLCJuIiwiYSIsInMiLCJwdXNoIiwiaGFzUSIsImFycmF5IiwiaXRlbSIsImluY2x1ZGVzIiwidW5pcXVlIiwiZmxhdHRlbiIsImZsYXQiLCJtYXAiLCJpc0FycmF5IiwiY29uY2F0Iiwid2hpY2hCaW4iLCJiaW5zIiwiaiIsImNvbnNvbGVHcm91cCIsIm5hbWUiLCJ3aW5kb3ciLCJkM3NtIiwiZGVidWdRIiwiZ3JvdXAiLCJjb25zb2xlR3JvdXBFbmQiLCJncm91cEVuZCIsImxvZyIsImZ1bmMiLCJtc2ciLCJ0YWJsZSIsInNldHVwQ29udGFpbmVyIiwic2VsZWN0aW9uIiwibmFtZXNwYWNlIiwicmVjdCIsImZpbGwiLCJjb250YWluZXIiLCJ5Iiwid2lkdGgiLCJoZWlnaHQiLCJiZ1JlY3QiLCJkZWZzIiwiY3BSZWN0IiwicmFpc2UiLCJjYWxjdWxhdGVXaWR0aE9mT2JqZWN0IiwiZnJlZVNwYWNlIiwibnVtYmVyT2ZPYmplY3RzIiwibWluT2JqZWN0V2lkdGgiLCJtYXhPYmplY3RXaWR0aCIsInNpemVPZlNwYWNlciIsIm92ZXJmbG93USIsInJlbWFpbmluZ1NwYWNlIiwib2JqZWN0V2lkdGgiLCJjYWxjdWxhdGVXaWR0aE9mU3BhY2VyIiwiYmFzZVNwYWNlclNpemUiLCJzcGFjZXJzQXRFYWNoTGV2ZWwiLCJzcGFjZXJzTmVlZGVkQXRFYWNoTGV2ZWwiLCJsZXZlbCIsImxldmVsRGF0YSIsInJlZHVjZSIsImIiLCJpc05hTiIsIndoaXNrZXJQYXRoIiwiZGlyIiwidyIsImgiLCJwZXIiLCJvIiwiaGgiLCJ3dyIsInAiLCJncm91cGluZ1NwYWNlciIsInNjYWxlTGluZWFyIiwiZWFzZVNpbiIsImN1ciIsImQiLCJob3Jpem9udGFsUSIsIm91dGVyV2lkdGgiLCJjdXJyZW50IiwiY3VycmVudE5vZGUiLCJub2RlIiwic2VsZWN0QWxsIiwidHJhbnNpdGlvbiIsImR1cmF0aW9uIiwidHJhbnNpdGlvbkR1cmF0aW9uIiwiZWFzZSIsImVhc2VGdW5jIiwicmVtb3ZlIiwicmVjdXJzaXZlbHlQb3NpdGlvbiIsImN1cnJlbnRTZWxlY3Rpb24iLCJlbnRlciIsImV4aXQiLCJtZXJnZSIsImV4aXRGdW5jdGlvbiIsImVhY2giLCJ0aGlzIiwibGV2ZWxTcGFjZXIiLCJzcGFjZXJTaXplIiwibW92ZSIsImN1cnJlbnRFbGVtZW50IiwidCIsImVudGVyRnVuY3Rpb24iLCJtb3ZlYnkiLCJzY2FsZSIsInRvUmVtb3ZlIiwib2JqZWN0Q2xhc3MiLCJvYmplY3RTaXplIiwic2l6ZSIsIl8iLCJjb2xvckZ1bmN0aW9uIiwiaW50ZXJwb2xhdGVSZ2IiLCJjb2xvcnMiLCJrIiwidiIsImNhdGVnb3J5IiwiaW50ZXJwb2xhdGUiLCJpbnRlcnBvbGF0aW9uIiwiZG9tYWluIiwiZGF0YUV4dGVudCIsInJhbmdlIiwiaGVscGVyU2NhbGUiLCJtYXRjaCIsImtleSIsInR5cGUiLCJob3ZlclEiLCJvcGFjIiwiZmlsbE9wYWNpdHkiLCJzdHJva2VPcGFjaXR5IiwiY29sb3JCeSIsImNhdGVnb3JpZXMiLCJtb2RpZnlPcGFjaXR5IiwidmFsdWVFeHRyYWN0b3IiLCJjYXQiLCJjYXRlZ29yeUV4dHJhY3RvciIsInRvb2x0aXAiLCJrZXlzIiwidmFsdWVzIiwiaGVhZGVyIiwib24iLCJtb3VzZW1vdmUiLCJjdXJyZW50RGF0YSIsIm1vdXNlIiwiZGl2Iiwic3R5bGUiLCJjYXJkQm9keSIsInRCb2R5IiwidGV4dCIsInRyIiwicm93S2V5Iiwicm93SW5kZXgiLCJiYm94IiwiZ2V0Qm91bmRpbmdDbGllbnRSZWN0IiwiaW5uZXJXaWR0aCIsInNjcm9sbFgiLCJldmVudCIsInBhZ2VYIiwiaW5uZXJIZWlnaHQiLCJzY3JvbGxZIiwicGFnZVkiLCJzZWxlY3RGaWx0ZXIiLCJzZWxlY3Rpb25OYW1lIiwiZGVmYXVsdFZhbHVlIiwibGFzdFZhbHVlIiwic2VsZWN0QXBwZW5kQnV0dG9uIiwiaW5wdXRHcm91cCIsImlucHV0IiwiaW5wdXRBcHBlbmRCdXR0b24iLCJvcHRpb25zIiwiY2xvc2VCdXR0b24iLCJjdXJyZW50U3R5bGUiLCJwcm9wZXJ0eSIsImRpc3BhdGNoIiwidXNlIiwidmFsIiwicmVnIiwiUmVnRXhwIiwib3B0aW9uIiwiY3VycmVudE9wdGlvbiIsInBhcnNlRmxvYXQiLCJsYXNzbyIsInN2ZyIsImNoYXJ0Q29udGFpbmVyIiwiY2hhcnRPZmZzZXQiLCJvYmplY3RzT2Zmc2V0IiwiZXZlbnRDYXRjaGVyIiwieFNjYWxlIiwicGF0aCIsImxpbmUiLCJ5U2NhbGUiLCJjdXJ2ZSIsImN1cnZlTGluZWFyQ2xvc2VkIiwiaW5zdGFuY2UiLCJhbmltYXRpb25SYXRlIiwib3BhY2l0eSIsImRhc2hBcnJheSIsInN0cm9rZSIsInN0cm9rZVdpZHRoIiwibGFzc29lZFN0cm9rZSIsImxhc3NvZWRTdHJva2VXaWR0aCIsImVhc2VFeHAiLCJwYXRocyIsInBFbnRlciIsImFjdGl2ZVEiLCJvYmplY3RDb250YWluZXIiLCJhbGxQb2ludHMiLCJyZW5kZXIiLCJwcmV2ZW50RGVmYXVsdCIsInN0b3BQcm9wYWdhdGlvbiIsImFkZEV2ZW50TGlzdGVuZXIiLCJkcmFnIiwicmVtb3ZlRXZlbnRMaXN0ZW5lciIsImN1cnJlbnRQb2ludHMiLCJhcHBseVBhdGhBdHRyaWJ1dGVzIiwiY29sb3IiLCJ3aGljaCIsInB0IiwiaW52ZXJ0IiwibGFzdFB0IiwicDEiLCJwMiIsInNxcnQiLCJldWNsaWRlYW5EaXN0YW5jZSIsInRpY2tEaXN0YW5jZSIsInRpY2siLCJkZXRlY3QiLCJsYXNzb3MiLCJib3giLCJhYnNvbHV0ZVBvc2l0aW9uIiwibGVmdCIsInRvcCIsInJpZ2h0IiwiYm90dG9tIiwiYm94UHRzIiwiaW5BbnlMYXNzb1EiLCJsYXNzb1BvaW50cyIsImV2ZXJ5IiwicG9seWdvbkNvbnRhaW5zIiwiY29vcmQiLCJ1cGRhdGVPYmplY3RzIiwiYXBwbHlPYmplY3RBdHRyaWJ1dGVzIiwic2V0USIsInByZUxhc3NvRmlsbCIsInByZUxhc3NvU3Ryb2tlIiwicHJlTGFzc29TdHJva2VXaWR0aCIsImxhc3NvZWRGaWxsIiwia2V5RnJhbWVzIiwiaHRtbCIsImRyYXciLCJ0b2dnbGUiLCJzdGF0ZSIsInRoaXNTVkciLCJhYnNvbHV0ZSIsImVsZW1lbnRQb3NpdGlvbiIsInN2Z1Bvc2l0aW9uIiwicmVsYXRpdmVQb3NpdGlvblRvIiwiYXhpcyIsImxhYmVsIiwidGlja1RpY2tMYWJlbFNwYWNlciIsInRpY2tMYWJlbE1hcmdpbiIsInJldmVyc2VTY2FsZVEiLCJvcmllbnQiLCJ2ZXJ0aWNhbFEiLCJiZ2NwUmVjdCIsInNwYWNlWCIsInNwYWNlWSIsImd1aWRlTGluZXNRIiwiZ3VpZGVsaW5lU3BhY2UiLCJ0aWNrTGFiZWxNYXhGb250U2l6ZSIsImJhY2tncm91bmRGaWxsIiwidGlja0xhYmVsVGV4dEFuY2hvciIsInRpY2tMYWJlbFJvdGF0aW9uIiwidGlja0RhdGEiLCJjYXRlZ29yaWNhbFEiLCJncm91cGluZyIsInRpY2tMYWJlbHMiLCJudW1iZXJPZlRpY2tzIiwiZXh0ZW50IiwidGlja1ZhbHVlcyIsImZsYXRUaWNrRGF0YSIsInNwYWNlIiwicmV2ZXJzZSIsImRvbWFpblBhZGRpbmciLCJtaW5PYmplY3RTaXplIiwibWF4T2JqZWN0U2l6ZSIsIm9iamVjdFNwYWNlciIsIm9iakNsYXNzIiwic3BhY2VyRnVuY3Rpb24iLCJtb3ZlWEJ5IiwibW92ZVlCeSIsIm10IiwiZGF0dW0iLCJkaXN0IiwibGFiZWxOYW1lR3JvdXAiLCJsYWJlbEVsZW1lbnQiLCJ0aGF0IiwidGlja0xlbmd0aCIsInRpY2tTdHJva2UiLCJ0aWNrU3Ryb2tlV2lkdGgiLCJzdHJpbmciLCJjaGFycyIsInJvdW5kVG8iLCJ0aWNrTGFiZWxGb250U2l6ZSIsImdldENvbXB1dGVkVGV4dExlbmd0aCIsImxhYmVsSG92ZXIiLCJsYWJlbEhvdmVyT2ZmIiwidGlja0xhYmVsT25DbGljayIsImd1aWRlTGluZVN0cm9rZSIsImd1aWRlTGluZVN0cm9rZVdpZHRoIiwibGluZVN0cm9rZSIsImxpbmVTdHJva2VXaWR0aCIsInBhcmVudE5vZGUiLCJ0aWNrTGFiZWxPbkhvdmVyRnVuYyIsImdsaW5lIiwibWlub3JRIiwiaWkiLCJ0aWNrTGFiZWxNaW5Gb250U2l6ZSIsInRpY2tMYWJlbEZ1bmMiLCJiYXIiLCJrZXlBIiwia2V5QiIsImRlc2NlbmRpbmciLCJDRiIsIlRUaXAiLCJiYXJQZXJjZW50IiwiYmFyS2V5cyIsIm9yZGVyZWQiLCJzb3J0Iiwic29ydGluZ0Z1bmN0aW9uIiwiYmFyVmFsdWVzIiwiZGVmYXVsdEV4aXQiLCJub2RlcyIsInBhcmVudEluZGV4QXJyYXkiLCJOdW1iZXIiLCJmaWxsQ29sb3IiLCJzdHJva2VDb2xvciIsImJhclN0cm9rZVdpZHRoIiwiYnViYmxlSGVhdG1hcCIsInhLZXkiLCJ5S2V5IiwicktleSIsInZLZXkiLCJ4S2V5U29ydGluZ0Z1bmN0aW9uIiwieEV4dHJhY3RvciIsInlLZXlTb3J0aW5nRnVuY3Rpb24iLCJ5RXh0cmFjdG9yIiwiYmhtIiwiY2VsbEtleXMiLCJyRXh0cmFjdG9yIiwidkV4dHJhY3RvciIsInhWYWx1ZXMiLCJ5VmFsdWVzIiwieERpbSIsInlEaW0iLCJyVmFsdWVzIiwieVNpemUiLCJ4U2l6ZSIsInlTcGFjZXIiLCJ5U3BhY2VyU2l6ZSIsInhTcGFjZXIiLCJ4U3BhY2VyU2l6ZSIsImNlbGxzIiwidlZhbHVlcyIsInJhZGl1cyIsInNjYWxlZCIsImJ1YmJsZVN0cm9rZVdpZHRoIiwiaGVhdG1hcCIsImhtIiwieU1pbk9iamVjdFNpemUiLCJ5TWF4T2JqZWN0U2l6ZSIsInhNaW5PYmplY3RTaXplIiwieE1heE9iamVjdFNpemUiLCJsb29rdXAiLCJwb3NpdGlvbmVkQ2VsbEtleXMiLCJsb29rdXBWYWx1ZSIsIm9iamVjdFN0cm9rZVdpZHRoIiwiYm94d2hpc2tlciIsInF1YXJ0aWxlc0tleSIsInF1YXJ0aWxlc0tleXMiLCJib3hLZXlzIiwiYm94VmFsdWVzIiwid2hpc2siLCJ1V2hpc2siLCJsV2hpc2siLCJxdWFydCIsInVRdWFydCIsImxRdWFydCIsIm1RdWFydCIsImJveFN0cm9rZVdpZHRoIiwiciIsImRpZiIsImRkIiwid2hpc2tlcldpZHRoUGVyY2VudCIsIndoaXNrZXJTdHJva2VXaWR0aCIsImRhdGF0b2dnbGUiLCJ4QXhpc09wdGlvbnMiLCJ5QXhpc09wdGlvbnMiLCJ5QXhpc1NlbGVjdFEiLCJ4QXhpc1NlbGVjdFEiLCJ1cGRhdGVGdW5jdGlvbiIsImN1cnJlbnRLZXlzIiwidmFscyIsImZpbHRlclNlbGVjdHMiLCJkYXRhb3B0cyIsImRvRW50ZXIiLCJzZiIsInNjYXR0ZXIiLCJwb2ludEtleXMiLCJ2YWx1ZUV4dHJhY3RvclgiLCJ2YWx1ZUV4dHJhY3RvclkiLCJ2YWx1ZUV4dHJhY3RvclIiLCJleHRlbnRYIiwidmFsdWVzWCIsImRvbWFpblBhZGRpbmdYIiwiZXh0ZW50WSIsInZhbHVlc1kiLCJkb21haW5QYWRkaW5nWSIsImV4dGVudFIiLCJ2YWx1ZXNSIiwiZG9tYWluUGFkZGluZ1IiLCJtaW5SYWRpdXMiLCJtYXhSYWRpdXMiLCJwb2ludHMiLCJwRXhpdCIsInNjYWxlWCIsInNjYWxlWSIsInNjYWxlUiIsInBvaW50U3Ryb2tlV2lkdGgiLCJwbG90Wm9vbSIsImNoYXJ0IiwieEF4aXMiLCJ5QXhpcyIsImNoYXJ0U2VsIiwieEF4aXNTZWwiLCJ5QXhpc1NlbCIsInNldExvY2tzIiwiY2hhcnRPYmpTZWwiLCJjaGFydE9ialRyYW5zIiwiY29zIiwiZ2V0QkJveCIsInhMb2NrIiwieUxvY2siLCJ6b29tIiwiY2hhcnRCb3giLCJ4QXhpc0JveCIsInlBeGlzQm94IiwiZXZlbnRUeXBlIiwiZGVsdGFZIiwid2hlZWxTcGVlZCIsInNoaWZ0USIsInNoaWZ0S2V5IiwiYXBwbHlYIiwiYXBwbHlZIiwieEF4aXNPYmpTZWwiLCJ5QXhpc09ialNlbCIsInJlc2V0IiwibXVsdGlQbG90Wm9vbSIsInhDb21wb25lbnRzIiwieUNvbXBvbmVudHMiLCJ4Q29tcG9uZW50c1NlbCIsInlDb21wb25lbnRzU2VsIiwieENvbXBvbmVudE9ialNlbCIsInlDb21wb25lbnRPYmpTZWwiLCJ2aW9saW4iLCJiYXNlIiwibWluTWF4SGV4U2NhbGUiLCJzY2FsZWRDb2xvciIsIm1vZCIsInF1YXJ0aWxlS2V5cyIsInBvaW50c1Rvb2x0aXAiLCJ2aW9saW5LZXkiLCJ2aW9saW5EYXRhIiwidmlvbGluUG9pbnRLZXkiLCJ2aW9saW5Qb2ludERhdGEiLCJjYWxjVmFsdWVzIiwiY2FsY3VsYXRlVmlvbGluVmFsdWVzIiwidmlvbGluUG9pbnRzIiwidmlvbGluUG9pbnRzRXh0cmFjdG9yIiwidmlvbGluUG9pbnRzS2V5cyIsInZpb2xpblBvaW50c1ZhbHVlcyIsInBrIiwidmlvbGluUG9pbnRWYWx1ZUV4dHJhY3RvciIsInBvaW50UXVhcnRpbGVzIiwiYmlubmVkIiwiaGlzdG9ncmFtIiwiZnJlcXVlbmNpZXMiLCJiaW4iLCJtaW5Db250b3VyUG9pbnQiLCJtYXhDb250b3VyUG9pbnQiLCJ2aW9saW5Db250b3VyUG9pbnRzIiwieDAiLCJ4MSIsImNvbnRvdXIiLCJwb2ludFZhbHVlcyIsIm5lZWRlZFZpb2xpblZhbHVlcyIsInZrIiwidmlvbGluS2V5cyIsImZyZXF1ZW5jeU1heCIsInZTY2FsZSIsImxBcmVhIiwiY3VydmVCYXNpcyIsInJBcmVhIiwiYXJlYSIsImxhIiwicmEiLCJxdWFydHMiLCJwb2ludHNRIiwicHRzQ29udGFpbmVyIiwicHRzIiwicHRzRW50ZXIiLCJwTWluIiwicE1heCIsInBvaW50UmFkaXVzIiwicG9pbnRLZXkiLCJyYW5kb20iLCJwb2ludENvbG9yRnVuYyIsImNyZWF0ZUV2ZW50IiwiaW5pdEV2ZW50IiwiZGlzcGF0Y2hFdmVudCIsInRvb2x0aXBLZXkiLCJxdWFydGlsZUtleSIsInZpb2xpblZhbHVlcyIsIm51bWVyaWNMZWdlbmQiLCJmb250U2l6ZSIsInRleHRDb2xvciIsImxlZ2VuZCIsImxpbmVhckdyYWRpZW50IiwibSIsImNhdGVnb3JpY0xlZ2VuZCIsImFzY2VuZGluZyIsImNhdEtleXMiLCJjeCIsImN5IiwibGFzc29XaWRnZXQiLCJtYXhOdW1iZXJPZkdyb3VwcyIsImRhdGFFeHRyYWN0b3IiLCJvbkVycm9yIiwic3VibWl0IiwiY2xpY2tTZW5kIiwicmVtb3ZlQnRuQ2xpY2tUb1JlbW92ZSIsInRhYnMiLCJwYW5lcyIsInJlbWFpbmluZ1RhYnMiLCJsYXN0VGFiIiwiY3VyVGV4dCIsInBvcHVsYXRlUGFuZSIsInBhbmUiLCJsZWFkIiwiYnRucyIsImNOIiwiYnRuIiwibGFzc29CdG4iLCJtYWtlTGFzc29CdXR0b24iLCJjdXJyZW50TGFzc28iLCJjbGVhckJ0biIsImxhc3NvQnRuVG9nZ2xlIiwibGFzIiwidGFibGVEYXRhIiwiZXh0cmFjdGVkIiwibWFrZUNsZWFyQnV0dG9uIiwibW9uaXRvckxhc3NvQnV0dG9uU3RhdGUiLCJ0YXJnZXQiLCJtYWtlVGFibGUiLCJoZWFkUiIsImJvZHkiLCJoZWFkZXJLZXlzIiwiaGVhZGVyQ29scyIsInVwZGF0ZVRhYmxlSGVhZGVyQ29sdW1ucyIsImJvZHlSb3dzIiwidXBkYXRlVGFibGVSb3dzIiwicm93RGF0YSIsImNvbHMiLCJzcGxpY2UiLCJtYWtlTmV3R3JvdXAiLCJncyIsIm5ld0dyb3VwTnVtYmVyIiwibGkiLCJpbnNlcnQiLCJ0eHQiLCJpbnNlcnRUYWIiLCJtYWtlVGFiUGFuZSIsImNhcmQiLCJ0YWJMaXN0IiwidGFiQ29udGVudCIsInJpZ2h0VGFicyIsInVwc2V0Iiwic2V0VmFsdWVzIiwiaW50ZXJzZWN0aW9uVmFsdWVzIiwieE9iamVjdFNpemUiLCJjaXJjbGVTdHJva2VXaWR0aCIsInNldEV4dHJhY3RvciIsImludGVyc2VjdGlvbkV4dHJhY3RvciIsImVsZW1lbnRFeHRyYWN0b3IiLCJlbGVtZW50VmFsdWVzIiwieU9iamVjdFNwYWNlciIsInNldEtleVNvcnRpbmdGdW5jdGlvbiIsImludGVyc2VjdGlvbktleVNvcnRpbmdGdW5jdGlvbiIsInhPYmplY3RTcGFjZXIiLCJ5T2JqZWN0U2l6ZSIsInNldCIsImludGVyc2VjdGlvbiIsImludGVyc2VjdGlvblRvdGFscyIsInRvdGFscyIsInRvdGFsIiwic2V0VG90YWxzIiwiZmlsdGVyVGFibGUiLCJzb3J0USIsInJlY29yZCIsImNvbHVtbktleSIsInJlY29yZFZhbHVlIiwicm93cyIsInRoIiwibWFrZUNvbHVtbnMiLCJwb3B1bGF0ZVJlY29yZHMiLCJtYWtlUm93cyIsInJvdyIsImZpZWxkRnVuY3Rpb24iLCJmaWVsZHMiLCJleHRyYWN0VmlvbGluVmFsdWVzIiwidmFsdWVFeHRyYWN0b3JGdW5jdGlvbiIsInFLZXkiLCJtaW5Qb2ludCIsIm1heFBvaW50IiwiaW50ZXJwb2xhdGVDb2xvcnMiLCJpbnRlcnBvbGF0ZVJnYkJhc2lzIiwidHJ1bmNhdGVUZXh0Iiwic2V0dXBTdGFuZGFyZENoYXJ0Q29udGFpbmVycyIsIm1hcmdpbnMiLCJheGVzIiwibGVnIiwibWFyZ2luIiwicG9zIiwiSGVpZ2h0Iiwic3ZnU3BhY2UiLCJtYXJnUHgiLCJjaGFydFNwYWNlIiwiYXhlc1NwYWNlIiwibGVnUmVjdCIsImRyYXdpbmdTcGFjZSIsInlBeGlzUmVjdCIsInBsb3RSZWN0IiwieEF4aXNSZWN0IiwibXlMb2ciLCJ3YXJuIiwiY29uc29sZSIsImluZm8iLCJlcnJvciIsInJlc2l6ZURlYm91bmNlIiwid2FpdCIsInJlc2l6ZSIsImltbWVkaWF0ZSIsInRpbWVvdXQiLCJjb250ZXh0IiwiYXJncyIsImNhbGxOb3ciLCJzZXRUaW1lb3V0IiwiYXBwbHkiLCJkZWJvdW5jZSJdLCJtYXBwaW5ncyI6ImtDQWVPLFNBQVNBLEVB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 diff --git a/build/js/d3sm.v0.0.3.js b/build/js/d3sm.v0.0.3.js deleted file mode 100644 index 7b314051172ed74f2b2b74bbe5199be762350c1b..0000000000000000000000000000000000000000 --- a/build/js/d3sm.v0.0.3.js +++ /dev/null @@ -1,10613 +0,0 @@ -var d3sm = (function (exports) { - 'use strict'; - - // import {hasQ} from './array-functions'; - /******************************************************************************* - ** ** - ** ** - ** HELPERS ** - ** ** - ** ** - *******************************************************************************/ - /** - * Helper function for Array.filter to get unique elements of the array - * @param {*} value current value as mapping over array (self) - * @param {number} index current index in the array - * @param {Array} self passed array from Array.filter method - * @returns {boolean} whether or not value is the first of its kind (i.e. indexOf(value) == index) - */ - function uniqueElements(value, index, self) { - return self.indexOf(value) === index; - } - - /** - * Extracts x and y of translate from transform property - * @param {string} transform transform property of svg element - * @returns {number[]} x, y of translate(x, y) - */ - function getTranslation(transform) { - // Create a dummy g for calculation purposes only. This will never - // be appended to the DOM and will be discarded once this function - // returns. - var g = document.createElementNS('http://www.w3.org/2000/svg', 'g'); - // Set the transform attribute to the provided string value. - transform = transform == undefined ? 'translate(0,0)' : transform; - g.setAttributeNS(null, 'transform', transform); - // consolidate the SVGTransformList containing all transformations - // to a single SVGTransform of type SVG_TRANSFORM_MATRIX and get - // its SVGMatrix. - var matrix = g.transform.baseVal.consolidate().matrix; - // As per definition values e and f are the ones for the translation. - return [matrix.e, matrix.f]; - } - - /** - * Modifies luminance of hexidecimal number - * @param {string} hex should be hexidecimal value with or without the proceeding octotrope - * @param {number} lum value to increase or decrease luminosity by - * @returns {string} updated hexidecimal value without the proceeding octotrope - */ - function modifyHexidecimalColorLuminance(hex, lum) { - // validate hex string - var hex = String(hex).replace(/[^0-9a-f]/gi, ''); - - if (hex.length < 6) { - hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; - } - lum = lum || 0; - - // convert to decimal and change luminosity - var rgb = '#', - c, - i; - for (i = 0; i < 3; i++) { - c = parseInt(hex.substr(i * 2, 2), 16); - c = Math.round(Math.min(Math.max(0, c + c * lum), 255)).toString(16); - rgb += ('00' + c).substr(c.length); - } - - return rgb; - } - - /** - * Calculated the quartiles of the passed data and stores them with qKeys - * @param {number[]} data list of numerical values - * @param {string[]} [qKeys=['q0', 'q1', 'q2', 'q3', 'q4']] how returned object with quartiles should be stored - * @returns {Object} with keys qKeys giving only the numerical values for the quartiles - */ - function quartiles(data, qKeys) { - var q2 = d3.median(data), - lower = data.filter(function (x) { - return x < q2; - }), - upper = data.filter(function (x) { - return x > q2; - }), - q1 = d3.median(lower), - q1 = q1 == undefined ? q2 : q1, - q0 = d3.min(lower), - q0 = q0 == undefined ? q1 : q0, - q3 = d3.median(upper), - q3 = q3 == undefined ? q2 : q3, - q4 = d3.max(upper), - q4 = q4 == undefined ? q3 : q4, - k0 = 'q0', - k1 = 'q1', - k2 = 'q2', - k3 = 'q3', - k4 = 'q4', - obj = {}; - if (qKeys != undefined && qKeys.length == 5) { - k0 = qKeys[0];k1 = qKeys[1];k2 = qKeys[2];k3 = qKeys[3];k4 = qKeys[4]; - } - obj[k0] = q0;obj[k1] = q1;obj[k2] = q2;obj[k3] = q3;obj[k4] = q4; - - return obj; - } - - /** - * Helper function to get all values needed in making violin plots - * @param {string[]} violinKeys - * @param {number[]} data - * @param {Function} valueExtractorFunction how to get values from data[violinKeys[i]] - * @param {boolean} horizontalQ whether or not violins will be rendered horizontally or vertically - * @param {string} qKey how the object containing the quartiles should be labeled as - * @param {string[]} qKeys how each quartile should be labeled as - * @returns {Object} required for @see{@link violin} containing keys values, binnned, frequencies, points, and quartiles - * @see{@link quartiles} - */ - function extractViolinValues(violinKeys, data, valueExtractorFunction, horizontalQ, qKey, qKeys) { - var obj = {}; - violinKeys.map(function (k, i) { - var d = valueExtractorFunction(k, i, data), - binned = d3.histogram()(d), - frequencies = binned.map(function (x) { - return x.length; - }), - minPoint = horizontalQ ? { y: d3.min(d), x: 0 } : { x: d3.min(d), y: 0 }, - maxPoint = horizontalQ ? { y: d3.max(d), x: 0 } : { x: d3.max(d), y: 0 }, - points = binned.map(function (bin, i) { - return horizontalQ ? { y: bin.length ? d3.median(bin) : d3.median([bin.x0, bin.x1]), x: frequencies[i] } : { x: bin.length ? d3.median(bin) : d3.median([bin.x0, bin.x1]), y: frequencies[i] }; - }), - quarts = quartiles(d, qKeys), - o = { - values: d, - binned: binned, - frequencies: frequencies, - points: [minPoint].concat(points).concat([maxPoint]) - }; - o[qKey] = quarts; - obj[k] = o; - }); - return obj; - } - - /** - * Hypenates all strings together - * @param {string[]} arguments - * @returns {string} "arg1-arg2-...-argn" - */ - function hypenate() { - return Array.prototype.slice.call(arguments).join('-'); - } - - /** - * Rounds decimals of number to precision - * @param {number} number - * @param {number} precision - * @returns {number} rounded to precision - */ - function round(number, precision) { - var shift = function shift(number, precision, reverseShift) { - if (reverseShift) { - precision = -precision; - } - var numArray = ('' + number).split('e'); - return +(numArray[0] + 'e' + (numArray[1] ? +numArray[1] + precision : precision)); - }; - return shift(Math.round(shift(number, precision, false)), precision, true); - } - - /** - * recursively ascends element.parentElement to find a svg tag - * @param {Element} element - * @returns {Element | undefined} - */ - function getContainingSVG(element) { - var parent = element.parentElement; - var tag = parent.tagName.toLowerCase(); - if (tag === 'svg') { - return parent; - } - if (tag === 'html') { - return undefined; - } - return getContainingSVG(parent); - } - - /** - * Maps arguments in to d3.interpolateRgbBasis - * @param arguments - * @returns {Function} - */ - function interpolateColors() { - return d3.interpolateRgbBasis(arguments); - } - - /** - * Trys to reduce text to fit in specified area, made for tick labels as called by - * @see{@link axis} - * @param {d3.selection} t container for specific axis tick - * @param {string} text to be the label of the passed axis tick - * @param {boolean} orient of the axis, true is horizontal, false is vertical - * @param {number} tickLength is the length of the text - * @param {number} space is the amount of availble space for the text and the tick to fit in - * @param {boolean} overflowQ whether or not allowed to go over the alloted space - * @returns {none} - */ - function truncateText(t, text, orient, tickLength, space, overflowQ) { - var rect = t.node().getBoundingClientRect(); - t.text(text); - while (Math.max(rect.width, rect.height) > space - tickLength) { - text = String(text); - text = text.slice(0, text.length - 1); - t.text(text + '...'); - rect = t.node().getBoundingClientRect(); - if (text.length == 0) break; - } - } - - function truncateString(string, space, font) { - var chars = space / font; - if (chars < string.length) { - return string.slice(0, Math.round(chars - 5)) + '...'; - } else { - return string; - } - } - - /** - * Trys to use d3.selection to get element, if it doesnt exist, makes one - * @param {d3.selection} sel selection in which to try and find object - * @param {string} tag tag of which to try and select - * @param {string} [cls=''] class of tag to try and grab - * @returns {d3.selection} of either append or selected tag.cls within sel - */ - function safeSelect(sel, tag, cls) { - var clsStr = cls == undefined ? '' : '.' + cls; - var sSel = sel.select(tag + clsStr).empty() ? sel.append(tag) : sel.select(tag + clsStr); - return sSel.classed(clsStr.replace('.', ''), true).attr('transform', sSel.attr('transform') == undefined ? 'translate(0,0)' : sSel.attr('transform')); - } - - /** - * evenly partitions the range [min, max] into n parts - * @param {number} min - * @param {number} max - * @param {number} n - * @returns {number[]} array of length n evenly partitioned between min and max - */ - function tickRange(min, max, n) { - var a = [min]; - var d = max - min; - var s = d / (n - 1); - for (var i = 0; i < n - 2; i++) { - a.push(min + s * (i + 1)); - } - a.push(max); - return a; - } - - function euclideanDistance(p1, p2) { - var a = p1[0] - p2[0], - b = p1[1] - p2[1]; - return Math.sqrt(a * a + b * b); - } - - /** - * Short-hand for array.includes(item); - * @param {Array} array - * @param {*} item to test if contained in {array} - * @returns {boolean} - */ - function hasQ(array, item) { - return array.includes(item); - } - - /** - * Calculates the total value of numbers in passed array - * @param {number[]} array of numerical values - * @returns {number} sum over elements in array - */ - function total(array) { - return array.reduce(function (a, b) { - return a + b; - }, 0); - } - /** - * Removes duplicates in array - * @param {Array} array of items - * @returns {Array} of items such that item_i != item_j for all i < j - * @see{@link uniqueElements} for the filtering function - */ - function unique(array) { - return array.filter(uniqueElements); - } - - /** - * Concats all nested arrays in passed array to form a single array - * @param {Array} array of putatively nested arrays - * @param {Array} [flat=[]] current flattened array - * @returns {Array} with every element in the same level - */ - function flatten(array, flat) { - flat = flat == undefined ? [] : flat; - array.map(function (e, i) { - if (Array.isArray(e)) { - flat = flat.concat(flatten(e)); - } else { - flat.push(e); - } - }); - return flat; - } - - /** - * Search of list of lists to find which - if any - passed value is in - * @param {Array[]} bins list of lists of values - * @param {*} value item to test if in any of the bins - * @returns {number} indicating the index of the bin in which value was found - */ - function whichBin(bins, value) { - var i = -1; - for (var j = 0; j < bins.length; j++) { - if (hasQ(bins[j], value)) { - return j; - } - } - return i; - } - - /** - * calls console.group if d3sm.debugQ == true - * @param {string} name of the group - * @returns {undefined} - */ - function consoleGroup(name) { - if (window.d3sm.debugQ === true) { - console.group(name); - } - } - - /** - * calls console.groupEnd if d3sm.debugQ == true - * @returns {undefined} - */ - function consoleGroupEnd() { - if (window.d3sm.debugQ === true) { - console.groupEnd(); - } - } - - /** - * Calls console.log if d3sm.debugQ == true - * @param {string} func name of the function logging - * @param {string} msg to log - * @param {Object} data to be logged along side the message - * @returns {undefined} - */ - function log(func, msg, data) { - if (window.d3sm.debugQ === true) { - console.log('%c[d3sm::' + func + ']:\t' + msg, ['background: #6cd1ef', 'border-radius: 5000px', 'padding: 0px 2px', 'font-size: 14px'].join(';')); - console.table(data); - // console.trace() - } - } - - /** - * Calls console.warn if d3sm.debugQ == true - * @param {string} func name of the function warning - * @param {string} msg to display - * @param {Object} data to be displayed along side the message - * @returns {undefined} - */ - function warn(func, msg, data) { - if (window.d3sm.debugQ === true) console.warn('%c[d3sm::' + func + ']:\t' + msg, ['background: #ffd53e', 'border-radius: 5000px', 'padding: 0px 2px', 'font-size: 14px'].join(';')); - console.table(data); - } - /** - * Calls the console.info if d3sm.debugQ == true - * @param {string} func name of the function providing info - * @param {string} msg to display - * @param {Object} data to be displayed along side the message - * @returns {undefined} - */ - function info(func, msg, data) { - if (window.d3sm.debugQ) console.info('%c[d3sm::' + func + ']:\t' + msg, ['background: #009ccd', 'border-radius: 5000px', 'padding: 0px 2px', 'font-size: 14px'].join(';')); - console.table(data); - } - - /** - * Calls console.error if d3sm.debugQ == true - * @param {string} func name of the function which sends the error - * @param {string} msg to display - * @param {Object} data to be displayed along side the message - * @returns {undefined} - */ - function error(func, msg, data) { - if (window.d3sm.debugQ) console.error('[d3sm::' + func + ']:\t' + msg + '\t%o', data); - } - - /** - * Function for setting up containers for most plots with the y axis container - * positioned on the left and the x axis container positioned on the bottom - * @param {d3.selection} selection selection of container in which the svg is or should be made - * @param {string} namespace namespace of the chart - * @param {Object} [space={w:window.innerWidth, h:window.innerHeight}] the width (w) and height (h) availble - * @param {number} [space.w=window.innerWidth] the available width in which to render the chart - * @param {number} [space.h=window.innerHeight] the available height in which to render the chart - - * @param {Object} [margins={top: 0.01, bottom: 0.01, left: 0.01, right: 0.01}] the margins for the chart - * @param {number} [margins.top=0.01] the top margin of the chart - * @param {number} [margins.bottom=0.01] the bottom margin of the chart - * @param {number} [margins.left=0.01] the left margin of the chart - * @param {number} [margins.right=0.01] the right margin of the chart - - - * @param {Object} [percentages = {axes:{x:0.1,y:0.1},space:{w:0.8,h:0.6}}] percentages of the paramater space of which to make the x and y axes as well as the percent of the availble space in which to render the plot - * @param {Object} [percentages.axes={x:0.1,y:0.1}] the percentages of the paramater space, of which the x and y axes will take up - * @param {number} [percentages.axes.xAxisPercent=0.1] the percentages of the paramater space, of which the x axis will take up - * @param {number} [percentages.axes.yAxisPercent=0.1] the percentages of the paramater space, of which the y axis will take up - - * @param {Object} [percentages.space={w:0.8,h:0.6}] the percentages of the paramater space, of which the SVG's width and height will be set - * @param {number} [percentages.space.percentOfSpaceForWidth=0.1] the percentages of the paramater space, of which the SVG's width will be set - * @param {number} [percentages.space.percentOfSpaceForHeight=0.1] the percentages of the paramater space, of which the SVG's height will be set - - * @returns {Object} returns the selection and "boundingRects" of the plot container, x-axis container and y-axis container - * as - * - * { - * - * plot: {selection: plotSelection, rect: plotRect}, - * - * xAxis:{selection:xAxisSelection, rect:xAxisRect}, - * - * yAxis: {selection:yAxisSelection, rect:yAxisRect} - * - * } - * - * where each rect has form: - * - * {x: #, y: #, h: #, w: #} - * - * depicting the starting x and y coordinate of the coresponding container (also their default transform values) as well their height (h) ans width (w) - */ - // export function setupStandardChartContainers( selection, namespace, space, margins, percentages) { - // export function setupStandardChartContainers( - // selection, - // namespace, - // space={w:availableWidth=window.innerWidth, h:availableHeight=window.innerHeight}, - // margins={top:0.01, bottom:0.01, left:0.01, right:0.01}, - // percentages={axes: {x: xAxisPercent=0.1, y: yAxisPercent=0.1}, space: {w: percentOfSpaceForWidth, h: percentOfSpaceForHeight}} - // ) { - // if (space == undefined) { space = {w: window.innerWidth, h: window.innerHeight} } - // if (margins == undefined) { margins = {top: 0.01, bottom: 0.01, left: 0.01, right: 0.01} } - // if (percentages == undefined) { percentages = {}; } - // if (percentages.axes == undefined) { percentages.axes = { x:0.1, y:0.1 } } - // if (percentages.space == undefined) { percentages.space = { w: 0.8, h: 0.6 } } - // - // // SVG width and height - // var svgSpace = { - // w: space.w * percentages.space.w, - // h: space.h * percentages.space.h - // }, - // - // // Space after removing margins - // chartSpace = { - // w: svgSpace.w - (margins.left * space.w) - (margins.right * space.w), - // h: svgSpace.h - (margins.top * space.h) - (margins.bottom * space.h) - // }, - // - // // main dimension of x and y axies - // // e.g. defines how tall x axis is as length is determined by plotRect.w - // axesSpace = { - // x: chartSpace.h * percentages.axes.x, - // y: chartSpace.w * percentages.axes.y - // }, - // - // // space left for drawing the chart properly (e.g. bars, violins, etc) - // drawingSpace = { - // x: chartSpace.w - axesSpace.y, - // y: chartSpace.h - axesSpace.x - // }, - // - // - // yAxisRect = { - // x: axesSpace.y + (margins.left * space.w), - // y: (margins.top * space.h), - // w: axesSpace.y, - // h: drawingSpace.y - // }, - // - // plotRect = { - // x: axesSpace.y + (margins.left * space.w), - // y: (margins.top * space.h), - // w: drawingSpace.x, - // h: drawingSpace.y - // }, - // - // xAxisRect = { - // x: axesSpace.y + (margins.left * space.w), - // y: (margins.top * space.h + plotRect.h), - // w: drawingSpace.x, - // h: axesSpace.x - // } - // - // - // var container = safeSelect(selection, 'svg', namespace) - // .style('width', svgSpace.w+'px') - // .style('height', svgSpace.h+'px') - // - // var axes = safeSelect(container, 'g', hypenate(namespace, 'axes')) - // - // // .attr('transform', "translate("+plotRect.x+","+plotRect.y+")"), - // - // var plot = safeSelect(container, 'g', hypenate(namespace, 'plot')) - // .attr('transform', "translate("+plotRect.x+","+plotRect.y+")") - // - // var xAxis = safeSelect(axes, 'g', hypenate(namespace, 'x-axis')) - // .attr('transform', "translate("+xAxisRect.x+","+xAxisRect.y+")") - // - // var yAxis = safeSelect(axes, 'g', hypenate(namespace, 'y-axis')) - // .attr('transform', "translate("+yAxisRect.x+","+yAxisRect.y+")") - // - // return { - // svg: { - // selection: container, - // rect: svgSpace - // }, - // plot: { - // selection: plot, - // rect: plotRect - // }, - // xAxis: { - // selection: xAxis, - // rect: xAxisRect - // }, - // yAxis: { - // selection: yAxis, - // rect: yAxisRect - // } - // } - // - // // return [plot, xAxis, yAxis] - // } - // - // - - - function setupStandardChartContainers(selection, namespace, container) { - var margins = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { top: 0.01, bottom: 0.01, left: 0.01, right: 0.01 }; - var svg = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : { w: 0.8, h: 0.6 }; - var axes = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : { y: 0.1, x: 0.1 }; - var leg = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : { x: 0, margin: 0, pos: 'left' // absolute width of legend and space on either size - }; - - if (container == undefined) { - container = { w: window.innerWidth, h: window.Height }; - } - // SVG width and height - - var svgSpace = { - w: container.w * svg.w, - h: container.h * svg.h - }; - - var margPx = { - top: margins.top * svgSpace.h, - bottom: margins.bottom * svgSpace.h, - left: margins.left * svgSpace.w, - right: margins.right * svgSpace.w - }, - - - // Space after removing margins - chartSpace = { - w: svgSpace.w - margPx.left - margPx.right, - h: svgSpace.h - margPx.top - margPx.bottom - }, - - - // main dimension of x and y axies - // e.g. defines how tall x axis is as length is determined by plotRect.w - axesSpace = { - x: chartSpace.h * axes.x, - y: chartSpace.w * axes.y - }, - - - // space left for drawing the chart properly (e.g. bars, violins, etc) - drawingSpace = { - x: chartSpace.w - axesSpace.y - leg.x - 2 * leg.margin, - y: chartSpace.h - axesSpace.x - }, - legRect = { - x: leg.margin + margPx.left + (leg.pos == 'left' ? 0 : drawingSpace.x + axesSpace.y), - y: margPx.top, // this is soomehow getting calculated incorectly - w: leg.x, - h: drawingSpace.y - }, - yAxisRect = { - x: axesSpace.y + margPx.left + (leg.pos == 'left' ? leg.x + 2 * leg.margin : 0), - y: margPx.top, - w: axesSpace.y, - h: drawingSpace.y - }, - plotRect = { - x: axesSpace.y + margPx.left + (leg.pos == 'left' ? leg.x + 2 * leg.margin : 0), - y: margPx.top, - w: drawingSpace.x, - h: drawingSpace.y - }, - xAxisRect = { - x: axesSpace.y + margPx.left + (leg.pos == 'left' ? leg.x + 2 * leg.margin : 0), - y: margPx.top + drawingSpace.y, - w: drawingSpace.x, - h: axesSpace.x - }; - - container = d3sm.safeSelect(selection, 'svg', namespace).style('width', svgSpace.w + 'px').style('height', svgSpace.h + 'px'); - - var axes = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'axes')); - - var leg = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'legend')).attr('transform', "translate(" + legRect.x + "," + legRect.y + ")"); - - var plot = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'plot')).attr('transform', "translate(" + plotRect.x + "," + plotRect.y + ")"); - - var xAxis = d3sm.safeSelect(axes, 'g', d3sm.hypenate(namespace, 'x-axis')).attr('transform', "translate(" + xAxisRect.x + "," + xAxisRect.y + ")"); - - var yAxis = d3sm.safeSelect(axes, 'g', d3sm.hypenate(namespace, 'y-axis')).attr('transform', "translate(" + yAxisRect.x + "," + yAxisRect.y + ")"); - - return { - svg: { - selection: container, - rect: svgSpace - }, - plot: { - selection: plot, - rect: plotRect - }, - xAxis: { - selection: xAxis, - rect: xAxisRect - }, - yAxis: { - selection: yAxis, - rect: yAxisRect - }, - legend: { - selection: leg, - rect: legRect - } - }; - } - - /** - * Adds a clip-path rect and binds it to container - * @param {d3.selection} container in which to add the clip-path and to which to bind the cliping path to - * @param {Object} rect the coordinates (x, y, width, height) of the clip-path - * @param {string} namespace - * @returns {d3.selection} of the clip-path rect - */ - function cpRect(container, rect, namespace) { - var defs = safeSelect(container, 'defs', hypenate(namespace, 'definitions')); - var cp = safeSelect(defs, 'clipPath', hypenate(namespace, 'clip-path')).attr('id', hypenate(namespace, 'clip-path')); - - var cpRect = safeSelect(cp, 'rect').attr('x', rect.x).attr('y', rect.y).attr('width', rect.width).attr('height', rect.height); - - defs.raise(); - // set clipping path to container - container.attr('clip-path', 'url(#' + hypenate(namespace, 'clip-path') + ')'); - - return cpRect; - } - - /** - * Adds a background rect t to container - * @param {d3.selection} container in which to add the background rectangle - * @param {Object} rect the coordinates (x, y, width, height) of the background - * @param {string} fill the color of the background - * @returns {d3.selection} of the background fill - */ - function bgRect(container, rect, fill) { - return safeSelect(container, 'rect', 'bg').attr('x', rect.x).attr('y', rect.y).attr('width', rect.width).attr('height', rect.height).attr('fill', fill); - } - - /** - * Sets up the container for making chart elements. This includes making - * a clip-path rect bound to the passed container, a background rect, and - * a g element with class -object-container. - * @param {d3.selection} container in which to add the clip-path and background - * @param {string} namespace - * @param {Object} rect the coordinates (x, y, width, height) of the background and clip-path - * @param {string} fill the color of the background - * @returns {d3.selection} of g.-object-container - * - * @see{@link bgRect} - * @see{@link cpRect} - */ - function setupContainer(selection, namespace, rect, fill) { - // the container for three main items, bg, defs, and object-container - var container = safeSelect(selection, 'g', namespace), - bg = bgRect(container, rect, fill), - cp = cpRect(container, rect, namespace), - objectContainer = safeSelect(container, 'g', hypenate(namespace, 'object-container')); - return objectContainer; - } - - /** - * determines the width of an object for the calling plotting function - * @param {number} freeSpace how much space is avalible - * @param {number} numberOfObjects how many object do we need - * @param {number} minObjectWidth how small are these objects allowed to be - * @param {number} maxObjectWidth how large are these object allowed to be - * @param {number} sizeOfSpacer percent of freeSpace that a single spacer should take up (need numberOfObjects - 1 spacers) - * @param {boolean} overflowQ can we go beyond alloted space - * @returns {number} how large object should be - * function tries to keep object within min / max width, but wil default to - * 5e-10 (smallest consistenly visible by svg size of element) if overflowQ is false - */ - function calculateWidthOfObject(freeSpace, numberOfObjects, minObjectWidth, maxObjectWidth, sizeOfSpacer, overflowQ) { - var sizeOfSpacer = sizeOfSpacer == 0 || sizeOfSpacer > 1 ? sizeOfSpacer : freeSpace * sizeOfSpacer; - - var numberOfSpacers = numberOfObjects - 1; - var spaceTakenBySpacers = numberOfSpacers * sizeOfSpacer; - var remainingSpace = freeSpace - spaceTakenBySpacers; - remainingSpace = remainingSpace < 0 ? 0 : remainingSpace; - var objectWidth = remainingSpace / numberOfObjects; - - if (overflowQ && minObjectWidth != undefined && objectWidth < minObjectWidth) { - objectWidth = minObjectWidth; - } - // if ( maxObjectWidth != undefined && objectWidth > maxObjectWidth ) { objectWidth = maxObjectWidth } - if (overflowQ && maxObjectWidth != undefined && objectWidth < maxObjectWidth) { - objectWidth = maxObjectWidth; - } - return Math.max(objectWidth, 5e-10); - } - - /** - * @param {Array[]} data list data (can be nested). If nested will create more complex spacer size - * @param {number} freeSpace how much space is avalible - * @param {number} objectWidth @see{@link calculateWidthOfObject} - * @param {number} numberOfObjects how many object do we need - * @param {number} baseSpacerSize percent of freeSpace that a single spacer should take up (need numberOfObjects - 1 spacers) - * @param {boolean} overflowQ can we go beyond alloted space - * @returns {number} returns size that spacer should be at level=0 - */ - function calculateWidthOfSpacer(data, freeSpace, objectWidth, numberOfObjects, baseSpacerSize, overflowQ) { - if (overflowQ) { - // var limitedNumberOfObjects = numberOfObjects > 6 ? 6 : numberOfObjects - // var spaceLeft = freeSpace - limitedNumberOfObjects * objectWidth - // return spaceLeft / (limitedNumberOfObjects - 1) - return freeSpace * baseSpacerSize; - } - var spacersAtEachLevel = spacersNeededAtEachLevel(data); - var totalSpacerPercent = total(spacersAtEachLevel.map(function (e, i) { - return e * 1 / (i + 1); - })); - var baseSpacerSize = (freeSpace - objectWidth * numberOfObjects) / totalSpacerPercent; - // console.log(freeSpace, objectWidth, numberOfObjects, totalSpacerPercent) - // console.log(totalSpacerPercent, baseSpacerSize, totalSpacerPercent * baseSpacerSize) - return isNaN(baseSpacerSize) ? 0 : baseSpacerSize; - } - - /** - * Calculates number of spacers needed to seperate elements at each level. - * @param {Array[]} array list data (can be nested). If nested will create more complex spacer size - * @param {number} [level=0] current level, used in recusrion - * @param {Array} [levelData=[]] how many spacers needed at a given level - * @returns {Array} levelData - * - * @example - * array = [[1,2], [3,4]] - * // returns [1, 2] - * as at level=0 the only spacer needed is between [1,2] and [3,4] - * and at level=1 the only two spacers needed is between 1 and 2 as well as - * 3 and 4 since the spacer between 2 and 3 is handled at level=0 - */ - function spacersNeededAtEachLevel(array, level, levelData) { - if (level == undefined) { - level = 0; - } else { - level += 1; - } - if (levelData == undefined) { - levelData = []; - } - if (level >= levelData.length) { - levelData.push(array.length - 1); - } else { - levelData[level] += array.length - 1; - } - array.map(function (e, i) { - if (Array.isArray(e)) { - spacersNeededAtEachLevel(e, level, levelData); - } - }); - return levelData; - } - - /** - * Draws a whisker for @see{@link boxwhisker} - * @param {boolean} dir direction to draw whisker, should be either true (up, top) or false (down or bottom) - * @param {number} x starting x coordinate in which to draw whisker - * @param {number} y starting y coordinate in which to draw whisker - * @param {number} w width of space in which to draw whisker - * @param {number} h height of space in which to draw whisker - * @param {number} per percentage of w or h (depends on o) to make whisker - * @param {boolean} o orientation, true is horizontal and false is vertical - * @returns {string} representing the svg path (i.e. the d attribute for a path tag) - */ - function whiskerPath(dir, x, y, w, h, per, o) { - // d = direction (true is up), p = percent width - if (dir == 'up' || dir == 'top' || dir == true) { - dir = true; - } - if (dir == 'down' || dir == 'bottom' || dir == false) { - dir = false; - } - o = o == undefined ? 'horizontal' : o; - per = per == undefined ? 1 : per; - if (o != "horizontal") { - var hh = h * per, - w = dir ? w : -w, - a = dir ? x + w : x, - b = dir ? x : x + w, - c = dir ? a : b; - p = "M " + a + ' ' + h / 2 + ' ' + 'L ' + b + ' ' + h / 2 + ' ' + 'M ' + c + ' ' + (h / 2 - hh / 2) + ' ' + 'L ' + c + ' ' + (h / 2 + hh / 2) + ' '; - - return p; - } - var ww = w * per, - a = dir ? y + h : y, - b = dir ? y : y + h, - p = "M " + w / 2 + ' ' + a + ' ' // straight line part - + 'L ' + w / 2 + ' ' + b + ' ' // straight line part - + 'h ' + -ww / 2 + ' ' + 0 + ' ' // horizontal line part - + 'h ' + ww + ' ' + 0 + ' '; - return p; - } - - function resizeDebounce(f, wait) { - var resize = debounce(function () { - f(); - }, wait); - window.addEventListener('resize', resize); - } - - function debounce(func, wait, immediate) { - var timeout; - return function () { - var context = this, - args = arguments; - var later = function later() { - timeout = null; - if (!immediate) func.apply(context, args); - }; - var callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) func.apply(context, args); - }; - } - - /******************************************************************************* - ** ** - ** ** - ** SPACEGROUPING ** - ** ** - ** ** - *******************************************************************************/ - /** - * Produces a function for spacing objects by an arbitrarly complex grouping - * @returns {recursivelyPosition} the function for moving the objects - * (see {@link groupingSpacer#recursivelyPosition}) - * @namespace groupingSpacer - */ - function groupingSpacer() { - var - /*@var {boolean} horizontalQ @default*/ - - /** - * Whether or not to space objects horizontally or vertically. - * (see {@link groupingSpacer.horizontalQ}) - * @param {boolean} [horizontalQ=true] - * @memberof groupingSpacer# - * @instance - */ - horizontalQ = true, - - /** - * The scale to use to position elements if {@link groupingSpacer#moveby}="string" - * (see {@link groupingSpacer.scale}) - * @param {d3.scale} [scale=d3.scaleLinear()] - * @memberof groupingSpacer# - * @instance - */ - scale = d3.scaleLinear(), - - /** - * How elements in the complex grouping should be moved over by. - * By default, moveby="category", which moves objects by the complex grouping - * But objects can also be moved over by scale. - * (see {@link groupingSpacer.moveby}) - * @param {string} [moveby="category"] - * @memberof groupingSpacer# - * @instance - */ - moveby = 'category', - - /** - * How many objects are there in total - * (see {@link groupingSpacer.numberOfObjects}) - * @param {number} [numberOfObjects=none] - * @memberof groupingSpacer# - * @instance - */ - numberOfObjects, - - /** - * The class given to an nested tag whose parent(s) have the correct transition - * properties - * (see {@link groupingSpacer.numberOfObjects}) - * @param {string} [numberOfObjects='d3sm-groupped-item'] - * @memberof groupingSpacer# - * @instance - */ - objectClass = 'd3sm-groupped-item', - - /** - * The size of the objects being positioned - * (see {@link groupingSpacer.objectSize}) - * @param {number} [objectSize=none] - * @memberof groupingSpacer# - * @instance - */ - objectSize, - - /** - * The size of the un-nested spacer between objects - * (see {@link groupingSpacer.spacerSize}) - * @param {number} [spacerSize=none] - * @memberof groupingSpacer# - * @instance - */ - spacerSize, - - /** - * The duration of transitions in ms - * (see {@link groupingSpacer.transitionDuration}) - * @param {number} [transitionDuration=1000] - * @memberof groupingSpacer# - * @instance - */ - transitionDuration = 1000, - - /** - * The ease function for the transitions - * (see {@link groupingSpacer.easeFunc}) - * @param {d3.ease} [easeFunc=d3.easeSin] - * @memberof groupingSpacer# - * @instance - */ - easeFunc = d3.easeSin, - - /** - * The namespace for the objects being moved - * (see {@link groupingSpacer.namespace}) - * @param {string} [namespace='spacer'] - * @memberof groupingSpacer# - * @instance - */ - namespace = 'spacer', - - /** - * The animation for new objects being added - * (see {@link groupingSpacer.enterFunction}) - * @param {function} enterFunction - * @memberof groupingSpacer# - * @instance - * @example - * // by default - * function(newObjectSelection) { - * newObjectSelection.attr('transform', function(d, i){ - * var - * x = horizontalQ ? objectSize * numberOfObjects + spacerSize * (numberOfObjects - 1) : 0, - * y = !horizontalQ ? objectSize * numberOfObjects + spacerSize * (numberOfObjects - 1) : 0, - * t = 'translate('+x+','+y+')' - * return t - * }) - * } - */ - enterFunction = function enterFunction(cur) { - cur.attr('transform', function (d, i) { - var - // x = horizontalQ ? objectSize * numberOfObjects + spacerSize * (numberOfObjects - 1) : 0, - // y = !horizontalQ ? objectSize * numberOfObjects + spacerSize * (numberOfObjects - 1) : 0, - x = horizontalQ ? window.outerWidth : 0, - y = !horizontalQ ? window.outerWidth : 0, - t = 'translate(' + x + ',' + y + ')'; - // if(y == undefined) {console.log(cur.node(), y, d)} - return t; - }); - }, - - /** - * The animation for old objects being removed - * (see {@link groupingSpacer.exitFunction}) - * @param {function} exitFunction - * @memberof groupingSpacer# - * @instance - * @example - * // by default - * oldObjectSelection.transition().duration(transitionDuration).ease(easeFunc) - * .attr('transform', function(d, i){ - * var - * x = horizontalQ ? objectSize * numberOfObjects + spacerSize * (numberOfObjects - 1) : 0, - * y = !horizontalQ ? objectSize * numberOfObjects + spacerSize * (numberOfObjects - 1) : 0, - * t = 'translate('+x+','+y+')' - * return t - * }).remove() - */ - exitFunction = function exitFunction(cur) { - log("groupingSpacer", "exiting with", { current: cur, currentNode: cur.node() }); - cur.selectAll('g').classed('to-remove', true); - - cur.transition().duration(transitionDuration * 0.9).ease(easeFunc).attr('transform', function (d, i) { - var - // x = horizontalQ ? objectSize * numberOfObjects + spacerSize * (numberOfObjects - 1) : 0, - // y = !horizontalQ ? objectSize * numberOfObjects + spacerSize * (numberOfObjects - 1) : 0, - x = horizontalQ ? window.outerWidth : 0, - y = !horizontalQ ? window.outerWidth : 0, - t = 'translate(' + x + ',' + y + ')'; - // if(y == undefined) {console.log(cur.node(), y, d)} - return t; - }).remove(); - }; - - /** - * Gets / sets horizontalQ (whether or not to space objects horizontally or vertically). - * (see {@link groupingSpacer#horizontalQ}) - * @param {string} [_=none] - * @returns {groupingSpacer | string} - * @memberof groupingSpacer - * @static - */ - recursivelyPosition.horizontalQ = function (_) { - return arguments.length ? (horizontalQ = _, recursivelyPosition) : horizontalQ; - }; - /** - * Gets / sets the scale to use to position elements if {@link groupingSpacer#moveby}="string" - * (see {@link groupingSpacer#scale}) - * @param {d3.scale} [_=none] - * @returns {groupingSpacer | d3.scale} - * @memberof groupingSpacer - * @static - */ - recursivelyPosition.scale = function (_) { - return arguments.length ? (scale = _, recursivelyPosition) : scale; - }; - /** - * Gets / sets moveby (whether or not to move by scale or by grouping). - * (see {@link groupingSpacer#moveby}) - * @param {string} [_=none] - * @returns {groupingSpacer | string} - * @memberof groupingSpacer - * @static - */ - recursivelyPosition.moveby = function (_) { - return arguments.length ? (moveby = _, recursivelyPosition) : moveby; - }; - /** - * Gets / sets numberOfObjects. - * (see {@link groupingSpacer#numberOfObjects}) - * @param {number} [_=none] - * @returns {groupingSpacer | number} - * @memberof groupingSpacer - * @static - */ - recursivelyPosition.numberOfObjects = function (_) { - return arguments.length ? (numberOfObjects = _, recursivelyPosition) : numberOfObjects; - }; - /** - * Gets / sets the objectClass (will be applied to elements). - * (see {@link groupingSpacer#objectClass}) - * @param {string} [_=none] - * @returns {groupingSpacer | string} - * @memberof groupingSpacer - * @static - */ - recursivelyPosition.objectClass = function (_) { - return arguments.length ? (objectClass = _, recursivelyPosition) : objectClass; - }; - /** - * Gets / sets the objectSize. - * (see {@link groupingSpacer#objectSize}) - * @param {number} [_=none] - * @returns {groupingSpacer | number} - * @memberof groupingSpacer - * @static - */ - recursivelyPosition.objectSize = function (_) { - return arguments.length ? (objectSize = _, recursivelyPosition) : objectSize; - }; - /** - * Gets / sets the spacerSize. - * (see {@link groupingSpacer#spacerSize}) - * @param {number} [_=none] - * @returns {groupingSpacer | number} - * @memberof groupingSpacer - * @static - */ - recursivelyPosition.spacerSize = function (_) { - return arguments.length ? (spacerSize = _, recursivelyPosition) : spacerSize; - }; - /** - * Gets / sets the transitionDuration. - * (see {@link groupingSpacer#transitionDuration}) - * @param {number} [_=none] - * @returns {groupingSpacer | number} - * @memberof groupingSpacer - * @static - */ - recursivelyPosition.transitionDuration = function (_) { - return arguments.length ? (transitionDuration = _, recursivelyPosition) : transitionDuration; - }; - /** - * Gets / sets the easeFunc. - * (see {@link groupingSpacer#easeFunc}) - * @param {d3.ease} [_=none] - * @returns {groupingSpacer | d3.ease} - * @memberof groupingSpacer - * @static - */ - recursivelyPosition.easeFunc = function (_) { - return arguments.length ? (easeFunc = _, recursivelyPosition) : easeFunc; - }; - /** - * Gets / sets the namespace. - * (see {@link groupingSpacer#namespace}) - * @param {string} [_=none] - * @returns {groupingSpacer | string} - * @memberof groupingSpacer - * @static - */ - recursivelyPosition.namespace = function (_) { - return arguments.length ? (namespace = _, recursivelyPosition) : namespace; - }; - /** - * Gets / sets the enterFunction. - * (see {@link groupingSpacer#enterFunction}) - * @param {function} [_=none] - * @returns {groupingSpacer | function} - * @memberof groupingSpacer - * @static - */ - recursivelyPosition.enterFunction = function (_) { - return arguments.length ? (enterFunction = _, recursivelyPosition) : enterFunction; - }; - /** - * Gets / sets the exitFunction. - * (see {@link groupingSpacer#exitFunction}) - * @param {function} [_=none] - * @returns {groupingSpacer | function} - * @memberof groupingSpacer - * @static - */ - recursivelyPosition.exitFunction = function (_) { - return arguments.length ? (exitFunction = _, recursivelyPosition) : exitFunction; - }; - - /** - * recursively position the objects inside of the selection. - * @param {d3.selection} selection - * @param {Object} data - * @param {level} [level=0] recursion depth - * @returns {number} (how much to move next element) - * @memberof groupingSpacer# - */ - function recursivelyPosition(selection, data, level) { - if (level == undefined) { - level = 0; - } - - var currentSelection = selection.selectAll('g.' + namespace + '[level="' + level + '"]').data(data); - var enter = currentSelection.enter().append('g').attr('level', level).attr('class', namespace); - var exit = currentSelection.exit(); - currentSelection = currentSelection.merge(enter); - - if (typeof exitFunction == 'function') { - exit.each(function (d, i) { - exitFunction(d3.select(this)); - }); - } else { - exit.remove(); - } - // spacer for current level - var levelSpacer = spacerSize / (level + 1); - // movement for current level - var move = 0; - currentSelection.each(function (currentElement, index) { - var t = d3.select(this); - if (t.attr('transform') == undefined && typeof enterFunction == 'function') { - enterFunction(t); - } - - t.transition().duration(transitionDuration).ease(easeFunc).attr('transform', function (d, i) { - var x = horizontalQ ? moveby == "scale" ? scale(d) : move : 0, - y = !horizontalQ ? moveby == "scale" ? scale(d) : move : 0, - t = 'translate(' + x + ',' + y + ')'; - return t; - }); - - if (Array.isArray(currentElement)) { - move += recursivelyPosition(t, currentElement, level + 1); - var toRemove = t.selectAll('g.' + namespace + '[level="' + level + '"] > g.' + objectClass + '.' + namespace); - if (typeof exitFunction == 'function') { - toRemove.each(function (d, i) { - exitFunction(d3.select(this)); - }); - } else { - toRemove.remove(); - } - } else { - move += objectSize; - var obj = t.select('g.' + namespace + '[level="' + level + '"] > g.' + objectClass + '.' + namespace); - if (obj.empty()) { - obj = t.append('g').attr('class', objectClass).classed(namespace, true); - } - obj.attr('parent-index', index); - var toRemove = t.selectAll('g.' + namespace + '[level="' + (level + 1) + '"]'); - - if (typeof exitFunction == 'function') { - toRemove.each(function (d, i) { - exitFunction(d3.select(this)); - }); - } else { - toRemove.remove(); - } - } - move += index == currentSelection.size() - 1 ? 0 : levelSpacer; - }); - return move; - } - return recursivelyPosition; - } - - var slicedToArray = function () { - function sliceIterator(arr, i) { - var _arr = []; - var _n = true; - var _d = false; - var _e = undefined; - - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - - if (i && _arr.length === i) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"]) _i["return"](); - } finally { - if (_d) throw _e; - } - } - - return _arr; - } - - return function (arr, i) { - if (Array.isArray(arr)) { - return arr; - } else if (Symbol.iterator in Object(arr)) { - return sliceIterator(arr, i); - } else { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } - }; - }(); - - var toConsumableArray = function (arr) { - if (Array.isArray(arr)) { - for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; - - return arr2; - } else { - return Array.from(arr); - } - }; - - /******************************************************************************* - ** ** - ** ** - ** AXIS ** - ** ** - ** ** - *******************************************************************************/ - - /** - * Creates an axis - * - * {@link https://sumneuron.gitlab.io/d3sm/demos/axes/index.html Demo} - * @constructor axis - * @param {d3.selection} selection - * @namespace axis - * @returns {function} axis - */ - function axis(selection) { - var - /** - * The orientation of the axis - * (see {@link axis#orient}) - * @param {string} [orient='bottom'] - * @memberof axis# - * @property - */ - orient = 'bottom', - // direction of the axis - - /** - * Amount of horizontal space (in pixels) avaible to render the axis in - * (see {@link axis#spaceX}) - * @param {number} [spaceX=0] - * @memberof axis# - * @property - */ - spaceX = 0, - - /** - * Amount of vertical space (in pixels) avaible to render the axis in - * (see {@link axis.spaceY}) - * @param {number} [spaceY=0] - * @memberof axis# - * @property - */ - spaceY = 0, - - - /** - * Whether or not to allow axis to render elements pass the main spatial dimension - * given the orientation (see {@link axis#orient}), where {@link axis#orient}="bottom" or {@link axis#orient}="top" - * the main dimension is {@link axis#spaceX} and where {@link axis#orient}="left" or {@link axis#orient}="right" - * the main dimension is {@link axis#spaceY} - * @param {boolean} [overflowQ=false] - * @memberof axis# - * @property - */ - overflowQ = false, - // whether or not to allow overflow - /** - * Whether or not the axis labels are for categorical data. If false, - * will use {@link axis#scale} to position ticks. - * @param {boolean} [categoricalQ=false] - * @memberof axis# - * @property - */ - categoricalQ = false, - // whether or not the axis is showing values or groups - /** - * Whether or not the axis ticks should have guidelines - * @param {boolean} [categoricalQ=false] - * @memberof axis# - * @property - */ - guideLinesQ = false, - // whether or not to allow overflow - - - /** - * How to group the tick labels - * @param {Array[]} [grouping=undefined] list of putatively other lists, which should correspond to tickLabels - * will space tick labels in nested lists closer together than outer lists - * @memberof axis# - * @property - */ - grouping, - - - /** - * The scale for which non-categorial (see {@link axis#categoricalQ}) ticks should be spaced - * @param {d3.scale} [scale=d3.scaleLinear] - * @memberof axis# - * @property - */ - - scale = d3.scaleLinear(), - - /** - * The padding for the domain of the scale (see {@link axis#scale}) - * @param {d3.scale} [scale=d3.scaleLinear] - * @memberof axis# - * @property - */ - domainPadding = 0.5, - - - /** - * Default space for the spacer (percentage) of main dimension given the orientation - * (see {@link axis#orient}), where {@link axis#orient}="bottom" or {@link axis#orient}="top" - * the main dimension is {@link axis#spaceX} and where {@link axis#orient}="left" or {@link axis#orient}="right" - * the main dimension is {@link axis#spaceY}between ticks - * @param {number} [objectSpacer=0.05] - * @memberof axis# - * @property - */ - objectSpacer = 0.05, - - /** - * The minimum size that an object can be if {@link axis#categoricalQ} is set to true - * @param {number} [minObjectSize=15] - * @memberof axis# - * @property - */ - minObjectSize = 15, - - /** - * The maximum size that an object can be if {@link axis#categoricalQ} is set to true - * @param {number} [maxObjectSize=15] - * @memberof axis# - * @property - */ - maxObjectSize = 50, - - - /** - * Color of the background - * @param {string} [backgroundFill="transparent"] - * @memberof axis# - * @property - */ - backgroundFill = 'transparent', - - /** - * Namespace for all items made by this instance of axis - * @param {string} [namespace="d3sm-axis"] - * @memberof axis# - * @property - */ - namespace = 'd3sm-axis', - - /** - * Class name for tick container ( element) - * @param {string} [objectClass="tick-group"] - * @memberof axis# - * @property - */ - objectClass = 'tick-group', - - - /** - * Values to show at each tick. Only used if categoricalQ is set true. See {@link axis#categoricalQ} - * @param {string[]} [tickLabels=undefined] - * @memberof axis# - * @property - */ - tickLabels, - // what to place at ticks - /** - * Values to show at each tick. Only used if categoricalQ is set false. See {@link axis#categoricalQ} - * @param {string[] | number[]} [objectClass=undefined] - * @memberof axis# - * @property - */ - tickValues, - // where to place ticks if not - /** - * Number of ticks to display if categoricalQ is false. See {@link axis#categoricalQ} - * @param {number} [numberOfTicks=5] - * @memberof axis# - * @property - */ - numberOfTicks = 5, - - - /** - * Stroke color of the main axis line - * @param {string} [lineStroke='black'] - * @memberof axis# - * @property - */ - lineStroke = 'black', - - /** - * Stroke width of the main axis line - * @param {number} [lineStrokeWidth=3] - * @memberof axis# - * @property - */ - lineStrokeWidth = 3, - - - /** - * Stroke color of ticks - * @param {string} [tickStroke='black'] - * @memberof axis# - * @property - */ - tickStroke = 'black', - - /** - * Stroke number of ticks - * @param {string} [tickStrokeWidth=2] - * @memberof axis# - * @property - */ - tickStrokeWidth = 2, - - /** - * Length - in pixels - of ticks - * @param {number} [tickLength=10] - * @memberof axis# - * @property - */ - tickLength = 10, - tickTickLabelSpacer = 10, - tickLabelMargin = 10, - - - /** - * Font size of tick labels - * @param {number} [tickLabelFontSize=14] - * @memberof axis# - * @property - */ - tickLabelFontSize = 14, - - /** - * Min font size of tick labels - * @param {number} [tickLabelMinFontSize=8] - * @memberof axis# - * @property - */ - tickLabelMinFontSize = 8, - - /** - * Max font size of tick labels - * @param {number} [tickLabelMaxFontSize=20] - * @memberof axis# - * @property - */ - tickLabelMaxFontSize = 20, - - - /** - * Text anchor of tick labels - * @param {string} [tickLabelTextAnchor="middle"] - * @memberof axis# - * @property - */ - tickLabelTextAnchor, - - /** - * Rotation of tick labels - * @param {number} [tickLabelRotation=0] - * @memberof axis# - * @property - */ - tickLabelRotation, - - /** - * Optional function for extracting the tick label from data - * @param {function} [tickLabelFunc=undefined] - * @memberof axis# - * @property - */ - tickLabelFunc = undefined, - - - /** - * Optional function for what to do when label is clicked - * @param {function} [tickLabelOnClick=function(d, i){}] - * @memberof axis# - * @property - */ - tickLabelOnClick = function tickLabelOnClick(d, i) {}, - - - /** - * Optional function for what to do when label is hovered - * @param {function} [tickLabelOnHoverFunc=function(d, i){}] - * @memberof axis# - * @property - */ - tickLabelOnHoverFunc = function tickLabelOnHoverFunc(d, i) { - return String(d).replace('-', ' ').replace('_', ' '); - }, - - - /** - * Length of guidelines - * @param {function} [guidelineSpace=undefined] - * @memberof axis# - * @property - */ - guidelineSpace, - - /** - * Stroke color of guidlines - * @param {string} [guidelineSpace="#333333"] - * @memberof axis# - * @property - */ - guideLineStroke = '#333333', - - /** - * Stroke width of guidlines - * @param {number} [guidelineSpace=2] - * @memberof axis# - * @property - */ - guideLineStrokeWidth = 2, - - - /** - * Duration of all transitions of this element - * @param {number} [transitionDuration=1000] - * @memberof axis# - * @property - */ - transitionDuration = 1000, - - /** - * Easing function for transitions - * @param {d3.ease} [easeFunc=d3.easeExp] - * @memberof axis# - * @property - */ - easeFunc = d3.easeExp, - - - /** - * Closure variable for getting object size after calculation - * @param {number} [objectSize=undefined] - * @memberof axis# - * @property - */ - objectSize, - - /** - * Closure variable for getting spacer size after calculation - * @param {number} [spacerSize=undefined] - * @memberof axis# - * @property - */ - spacerSize, - - - /** - * Decimal percision to round numerical tick labels to - * @param {number} [roundTo=2] - * @memberof axis# - * @property - */ - roundTo = 2, - label, - reverseScaleQ = false; - - axis.label = function (_) { - return arguments.length ? (label = _, axis) : label; - }; - axis.tickTickLabelSpacer = function (_) { - return arguments.length ? (tickTickLabelSpacer = _, axis) : tickTickLabelSpacer; - }; - axis.tickLabelMargin = function (_) { - return arguments.length ? (tickLabelMargin = _, axis) : tickLabelMargin; - }; - /** - * Gets or sets the selection in which items are manipulated - * @param {d3.selection} [_=none] - * @returns {axis | d3.selection} - * @memberof axis - * @property - * by default selection = selection - */ - - axis.selection = function (_) { - return arguments.length ? (selection = _, axis) : selection; - }; - - /** - * Gets or sets the orientation in which items are manipulated - * (see {@link axis#orient}) - * @param {string} [_=none] should be horizontal or vertical - * @returns {axis | string} - * @memberof axis - * @property - * by default orient="bottom" - */ - axis.orient = function (_) { - return arguments.length ? (orient = _, axis) : orient; - }; - /** - * Gets or sets the amount of horizontal space in which items are manipulated - * (see {@link axis#spaceX}) - * @param {number} [_=none] should be a number > 0 - * @returns {axis | number} - * @memberof axis - * @property - * by default spaceX = undefined - */ - axis.spaceX = function (_) { - return arguments.length ? (spaceX = _, axis) : spaceX; - }; - /** - * Gets or sets the amount of vertical space in which items are manipulated - * (see {@link axis#spaceY}) - * @param {number} [_=none] should be a number > 0 - * @returns {axis | number} - * @memberof axis - * @property - * by default spaceY = undefined - */ - axis.spaceY = function (_) { - return arguments.length ? (spaceY = _, axis) : spaceY; - }; - - /** - * Gets / sets whether or not axis is allowed to go beyond specified dimensions - * (see {@link axis#spaceX}) - * @param {boolean} [_=none] - * @returns {axis | boolean} - * @memberof axis - * @property - * by default overflowQ = false - */ - axis.overflowQ = function (_) { - return arguments.length ? (overflowQ = _, axis) : overflowQ; - }; - /** - * Gets / sets whether or not axis will display categorial ticks or by numerical value - * (see {@link axis#categoricalQ}) - * @param {boolean} [_=none] - * @returns {axis | boolean} - * @memberof axis - * @property - * by default categoricalQ = false - */ - axis.categoricalQ = function (_) { - return arguments.length ? (categoricalQ = _, axis) : categoricalQ; - }; - /** - * Gets / sets whether or not axis ticks should have guidelines - * (see {@link axis#guideLinesQ}) - * @param {boolean} [_=none] - * @returns {axis | boolean} - * @memberof axis - * @property - * by default guideLinesQ = false - */ - axis.guideLinesQ = function (_) { - return arguments.length ? (guideLinesQ = _, axis) : guideLinesQ; - }; - - /** - * Gets / sets how ticks should be groupped - * (see {@link axis#grouping}) - * @param {Array[]} [_=none] list of putatively other lists, which should correspond to tickLabels - * will space tick labels in nested lists closer together than outer lists - * @returns {axis | Array[]} - * @memberof axis - * @property - * by default grouping = undefined - */ - axis.grouping = function (_) { - return arguments.length ? (grouping = _, axis) : grouping; - }; - - /** - * Gets / sets the scale for which non-categorial ticks should - * be spaced - * (see {@link axis#scale}) - * @param {d3.scale} [_=none] - * @returns {axis | d3.scale} - * @memberof axis - * @property - * by default scale = d3.scaleLinear() - */ - axis.scale = function (_) { - return arguments.length ? (scale = _, axis) : scale; - }; - /** - * Gets / sets the padding for the domain of the scale - * (see {@link axis#domainPadding}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default domainPadding = 0.5 - */ - axis.domainPadding = function (_) { - return arguments.length ? (domainPadding = _, axis) : domainPadding; - }; - - /** - * Gets / sets objectSpacer - * (see {@link axis#objectSpacer}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default objectSpacer = 0.05 - */ - axis.objectSpacer = function (_) { - return arguments.length ? (objectSpacer = _, axis) : objectSpacer; - }; - /** - * Gets / sets the minObjectSize - * (see {@link axis#minObjectSize}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default minObjectSize = 15 - */ - axis.minObjectSize = function (_) { - return arguments.length ? (minObjectSize = _, axis) : minObjectSize; - }; - /** - * Gets / sets the maxObjectSize - * (see {@link axis#maxObjectSize}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default maxObjectSize = 50 - */ - axis.maxObjectSize = function (_) { - return arguments.length ? (maxObjectSize = _, axis) : maxObjectSize; - }; - - /** - * Gets / sets the namespace - * (see {@link axis#namespace}) - * @param {string} [_=none] - * @returns {axis | string} - * @memberof axis - * @property - * by default namespace = 'd3sm-axis' - */ - axis.namespace = function (_) { - return arguments.length ? (namespace = _, axis) : namespace; - }; - /** - * Gets / sets the backgroundFill - * (see {@link axis#backgroundFill}) - * @param {string} [_=none] - * @returns {axis | string} - * @memberof axis - * @property - * by default backgroundFill = 'transparent' - */ - axis.backgroundFill = function (_) { - return arguments.length ? (backgroundFill = _, axis) : backgroundFill; - }; - /** - * Gets / sets the objectClass - * (see {@link axis#objectClass}) - * @param {string} [_=none] - * @returns {axis | string} - * @memberof axis - * @property - * by default objectClass = 'tick-group' - */ - axis.objectClass = function (_) { - return arguments.length ? (objectClass = _, axis) : objectClass; - }; - - /** - * Gets / sets the tickLabels - * (see {@link axis#tickLabels}) - * @param {string[]} [_=none] - * @returns {axis | string[]} - * @memberof axis - * @property - * by default tickLabels = undefined - */ - axis.tickLabels = function (_) { - return arguments.length ? (tickLabels = _, axis) : tickLabels; - }; - /** - * Gets / sets the tickValues - * (see {@link axis#tickValues}) - * @param {number[]} [_=none] - * @returns {axis | number[]} - * @memberof axis - * @property - * by default tickValues = undefined - */ - axis.tickValues = function (_) { - return arguments.length ? (tickValues = _, axis) : tickValues; - }; - /** - * Gets / sets the tickValues - * (see {@link axis#numberOfTicks}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default numberOfTicks = 5 - */ - axis.numberOfTicks = function (_) { - return arguments.length ? (numberOfTicks = _, axis) : numberOfTicks; - }; - - /** - * Gets / sets the lineStroke - * (see {@link axis#lineStroke}) - * @param {string} [_=none] - * @returns {axis | string} - * @memberof axis - * @property - * by default lineStroke = 'black' - */ - axis.lineStroke = function (_) { - return arguments.length ? (lineStroke = _, axis) : lineStroke; - }; - /** - * Gets / sets the lineStrokeWidth - * (see {@link axis#lineStrokeWidth}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default lineStrokeWidth = 3 - */ - axis.lineStrokeWidth = function (_) { - return arguments.length ? (lineStrokeWidth = _, axis) : lineStrokeWidth; - }; - - /** - * Gets / sets the tickStroke - * (see {@link axis#tickStroke}) - * @param {string} [_=none] - * @returns {axis | string} - * @memberof axis - * @property - * by default tickStroke = 'black' - */ - axis.tickStroke = function (_) { - return arguments.length ? (tickStroke = _, axis) : tickStroke; - }; - /** - * Gets / sets the tickStrokeWidth - * (see {@link axis#tickStrokeWidth}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default tickStrokeWidth = 2 - */ - axis.tickStrokeWidth = function (_) { - return arguments.length ? (tickStrokeWidth = _, axis) : tickStrokeWidth; - }; - /** - * Gets / sets the tickLength - * (see {@link axis#tickLength}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default tickLength = 10 - */ - axis.tickLength = function (_) { - return arguments.length ? (tickLength = _, axis) : tickLength; - }; - - /** - * Gets / sets the tickLabelFontSize - * (see {@link axis#tickLabelFontSize}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default tickLabelFontSize = 14 - */ - axis.tickLabelFontSize = function (_) { - return arguments.length ? (tickLabelFontSize = _, axis) : tickLabelFontSize; - }; - /** - * Gets / sets the tickLabelMinFontSize - * (see {@link axis#tickLabelMinFontSize}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default tickLabelMinFontSize = 8 - */ - axis.tickLabelMinFontSize = function (_) { - return arguments.length ? (tickLabelMinFontSize = _, axis) : tickLabelMinFontSize; - }; - /** - * Gets / sets the tickLabelMaxFontSize - * (see {@link axis#tickLabelMaxFontSize}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default tickLabelMaxFontSize = 20 - */ - axis.tickLabelMaxFontSize = function (_) { - return arguments.length ? (tickLabelMaxFontSize = _, axis) : tickLabelMaxFontSize; - }; - - /** - * Gets / sets the tickLabelTextAnchor - * (see {@link axis#tickLabelTextAnchor}) - * @param {string} [_=none] - * @returns {axis | string} - * @memberof axis - * @property - * by default tickLabelTextAnchor = 'center' - */ - axis.tickLabelTextAnchor = function (_) { - return arguments.length ? (tickLabelTextAnchor = _, axis) : tickLabelTextAnchor; - }; - /** - * Gets / sets the tickLabelRotation - * (see {@link axis#tickLabelRotation}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default tickLabelRotation = 0 - */ - axis.tickLabelRotation = function (_) { - return arguments.length ? (tickLabelRotation = _, axis) : tickLabelRotation; - }; - /** - * Gets / sets the tickLabelFunc - * (see {@link axis#tickLabelFunc}) - * @param {function} [_=none] - * @returns {axis | function} - * @memberof axis - * @property - * by default tickLabelFunc = undefined - */ - axis.tickLabelFunc = function (_) { - return arguments.length ? (tickLabelFunc = _, axis) : tickLabelFunc; - }; - - /** - * Gets / sets the tickLabelOnClick - * (see {@link axis#tickLabelOnClick}) - * @param {function} [_=none] - * @returns {axis | function} - * @memberof axis - * @property - */ - axis.tickLabelOnClick = function (_) { - return arguments.length ? (tickLabelOnClick = _, axis) : tickLabelOnClick; - }; - - /** - * Gets / sets the guidelineSpace - * (see {@link axis#guidelineSpace}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default guidelineSpace = undefined - */ - axis.guidelineSpace = function (_) { - return arguments.length ? (guidelineSpace = _, axis) : guidelineSpace; - }; - /** - * Gets / sets the guideLineStroke - * (see {@link axis#guideLineStroke}) - * @param {string} [_=none] - * @returns {axis | string} - * @memberof axis - * @property - * by default guideLineStroke = "#333333" - */ - axis.guideLineStroke = function (_) { - return arguments.length ? (guideLineStroke = _, axis) : guideLineStroke; - }; - /** - * Gets / sets the guideLineStrokeWidth - * (see {@link axis#guideLineStrokeWidth}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default guideLineStrokeWidth = 2 - */ - axis.guideLineStrokeWidth = function (_) { - return arguments.length ? (guideLineStrokeWidth = _, axis) : guideLineStrokeWidth; - }; - - /** - * Gets / sets the transitionDuration - * (see {@link axis#transitionDuration}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default transitionDuration = 1000 - */ - axis.transitionDuration = function (_) { - return arguments.length ? (transitionDuration = _, axis) : transitionDuration; - }; - /** - * Gets / sets the easeFunc - * (see {@link axis#easeFunc}) - * @param {d3.ease} [_=none] - * @returns {axis | d3.ease} - * @memberof axis - * @property - * by default easeFunc = d3.easeExp - */ - axis.easeFunc = function (_) { - return arguments.length ? (easeFunc = _, axis) : easeFunc; - }; - - /** - * Gets / sets the objectSize - * (see {@link axis#objectSize}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default objectSize = undefined - */ - axis.objectSize = function (_) { - return arguments.length ? (objectSize = _, axis) : objectSize; - }; - /** - * Gets / sets the spacerSize - * (see {@link axis#spacerSize}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default spacerSize = undefined - */ - axis.spacerSize = function (_) { - return arguments.length ? (spacerSize = _, axis) : spacerSize; - }; - - /** - * Gets / sets the roundTo - * (see {@link axis#roundTo}) - * @param {number} [_=none] - * @returns {axis | number} - * @memberof axis - * @property - * by default roundTo = 2 - */ - axis.roundTo = function (_) { - return arguments.length ? (roundTo = _, axis) : roundTo; - }; - axis.reverseScaleQ = function (_) { - return arguments.length ? (reverseScaleQ = _, axis) : reverseScaleQ; - }; - - axis.tickLabelOnHoverFunc = function (_) { - return arguments.length ? (tickLabelOnHoverFunc = _, axis) : tickLabelOnHoverFunc; - }; - - function axis() { - // for convenience in handling orientation specific values - var horizontalQ = hasQ(['top', 'bottom', 'horizontal'], orient) ? true : false; - var verticalQ = !horizontalQ; - - // background cliping rectangle - var bgcpRect = { x: 0, y: 0, width: spaceX, height: spaceY - // modify the rect based on axis orientation - };if (orient == "left") { - bgcpRect.x -= spaceX; - if (guideLinesQ) { - bgcpRect.width += guidelineSpace; - } /* these two lines increase the clipping rect to allow for text at the edge of the axis */ - bgcpRect.y -= tickLabelMaxFontSize; - bgcpRect.height += 2 * tickLabelMaxFontSize; - } - if (orient == "bottom") { - bgcpRect.y = bgcpRect.y; - if (guideLinesQ) { - bgcpRect.y -= guidelineSpace;bgcpRect.height += guidelineSpace; - } /* these two lines increase the clipping rect to allow for text at the edge of the axis */ - bgcpRect.x -= tickLabelMaxFontSize; - bgcpRect.width += 2 * tickLabelMaxFontSize; - } - if (orient == "top") { - bgcpRect.y -= spaceY; - if (guideLinesQ) { - bgcpRect.height += guidelineSpace; - } /* these two lines increase the clipping rect to allow for text at the edge of the axis */ - bgcpRect.y -= tickLabelMaxFontSize; - bgcpRect.height += 2 * tickLabelMaxFontSize; - } - if (orient == "right") { - bgcpRect.x = 0; - if (guideLinesQ) { - bgcpRect.width += guidelineSpace;bgcpRect.x -= guidelineSpace; - } /* these two lines increase the clipping rect to allow for text at the edge of the axis */ - bgcpRect.y -= tickLabelMaxFontSize; - bgcpRect.height += 2 * tickLabelMaxFontSize; - } - - var container = setupContainer(selection, namespace, bgcpRect, backgroundFill); - - // defaults for text-anchor and text rotation - if (orient == 'top') { - tickLabelTextAnchor = tickLabelTextAnchor == undefined ? 'start' : tickLabelTextAnchor; - tickLabelRotation = tickLabelRotation == undefined ? -90 : tickLabelRotation; - } - if (orient == 'bottom') { - tickLabelTextAnchor = tickLabelTextAnchor == undefined ? 'end' : tickLabelTextAnchor; - tickLabelRotation = tickLabelRotation == undefined ? -90 : tickLabelRotation; - } - if (orient == 'left') { - tickLabelTextAnchor = tickLabelTextAnchor == undefined ? 'end' : tickLabelTextAnchor; - tickLabelRotation = tickLabelRotation == undefined ? 0 : tickLabelRotation; - } - if (orient == 'right') { - tickLabelTextAnchor = tickLabelTextAnchor == undefined ? 'start' : tickLabelTextAnchor; - tickLabelRotation = tickLabelRotation == undefined ? 0 : tickLabelRotation; - } - - /* - If categorical: - -> use grouping if defined, - -> else use the labels provided - else: - if grouping undefined - and no specified number of tickes - -> make numberOfTick ticks - -> else use provided tick values - -> use grouping - */ - var tickData = categoricalQ ? grouping == undefined ? tickLabels : grouping : grouping == undefined ? numberOfTicks != undefined ? - // ? (tickValues.length < numberOfTicks) - tickRange.apply(undefined, toConsumableArray(d3.extent(tickValues)).concat([numberOfTicks])) : tickValues : grouping; - - var flatTickData = flatten(tickData); - var numberOfObjects = flatTickData.length; - var space = horizontalQ ? spaceX : spaceY; - var extent = d3.extent(flatTickData); - - if (reverseScaleQ) { - extent.reverse(); - } - var domain = reverseScaleQ ? [extent[0] + domainPadding, extent[1] - domainPadding] : [extent[0] - domainPadding, extent[1] + domainPadding]; - - scale.domain(domain).range([horizontalQ ? 0 : spaceY, horizontalQ ? spaceX : 0]); - - /* - Scales are based on the values of the chart and correspond to the spacings of the - chart. If the chart has already been rendered, these values (expensive to caluclate) can - be passed to axis to prevent recalculation. - */ - - // calculate object size if needed - objectSize = objectSize == undefined ? calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ) : objectSize; - - // calculate spacer size if needed - spacerSize = spacerSize == undefined ? calculateWidthOfSpacer(flatTickData, space, objectSize, numberOfObjects, objectSpacer, overflowQ) : spacerSize; - - var objClass = hypenate(namespace, categoricalQ ? objectClass + '-categorical' : objectClass); - - var spacerFunction = groupingSpacer().horizontalQ(horizontalQ).scale(scale).moveby(categoricalQ ? 'category' : 'scale').numberOfObjects(numberOfObjects).objectClass(objClass).objectSize(objectSize).spacerSize(spacerSize).transitionDuration(transitionDuration).easeFunc(easeFunc).namespace(namespace); - - var tickEnterAnimation = function tickEnterAnimation(sel) { - var mt = scale(sel.datum()), - dist = scale(extent[1]) * 2, - k = mt < extent[1] / 2 ? 1 : -1; - k = horizontalQ ? k * -1 : k; - sel.attr('transform', function (d, i) { - var x = horizontalQ ? dist * k : 0, - y = !horizontalQ ? dist * k : 0, - t = 'translate(' + x + ',' + y + ')'; - return t; - }); - }; - var tickExitAnimation = function tickExitAnimation(sel) { - var mt = scale(sel.datum()), - dist = scale(extent[1]) * 2, - k = mt < extent[1] / 2 ? 1 : -1; - k = horizontalQ ? k * -1 : k; - sel.transition().duration(transitionDuration).ease(easeFunc).style('opacity', 0).attr('transform', function (d, i) { - var x = horizontalQ ? dist * k : 0, - y = !horizontalQ ? dist * k : 0, - t = 'translate(' + x + ',' + y + ')'; - return t; - }).remove(); - }; - - if (!categoricalQ) { - spacerFunction.enterFunction(tickEnterAnimation); - spacerFunction.exitFunction(tickExitAnimation); - } - - // move tick containers - spacerFunction(container, tickData, 0); - - // move by for x and y needed to center categorical ticks, labels, and guidelines - function moveXBy(d, i, horizontalQ, categoricalQ, objectSize) { - return horizontalQ ? categoricalQ ? objectSize / 2 : 0 : 0; - } - - function moveYBy(d, i, verticalQ, categoricalQ, objectSize) { - return verticalQ ? categoricalQ ? objectSize / 2 : 0 : 0; - } - - var labelNameGroup = safeSelect(selection, 'g', hypenate(namespace, 'axis-name')); - - var labelElement = safeSelect(labelNameGroup, 'text', hypenate(namespace, 'name')); - if (labelElement != undefined) { - labelElement.text(label); - - if (orient == 'left' || orient == 'right') { - labelElement.attr('transform', 'rotate(-90)'); - } - - var bbox = labelElement.node().getBoundingClientRect(); - labelNameGroup.attr('transform', function (d, i) { - var x = 0, - y = 0, - t; - - if (orient == 'bottom') { - x = spaceX - bbox.width - tickLabelMargin; - y = -tickTickLabelSpacer; - } else if (orient == 'top') { - x = spaceX - bbox.width - tickLabelMargin; - x = tickLabelMargin; - y = bbox.height + tickTickLabelSpacer; - } else if (orient == 'left') { - x = bbox.width + tickTickLabelSpacer; - y = bbox.height + tickLabelMargin; - } else if (orient == 'right') { - x = -(bbox.width + tickTickLabelSpacer); - y = bbox.height + tickLabelMargin; - } - t = 'translate(' + x + ',' + y + ')'; - return t; - }); - } else { - labelElement.remove(); - } - /* - Idea from Stack Overflow - https://stackoverflow.com/questions/50579535/d3-js-v4-truncate-text-to-fit-in-fixed-space/50585022?noredirect=1#comment88235562_50585022 - to use clip path to make things fit in fixed size. Have yet got this to work nicely. - */ - // var defs = d3.select(container.node().parentNode).select('defs') - // var tickLabelClipPath = safeSelect(defs, 'clipPath', hypenate(namespace,'tick-label-clip-path')).attr('id', hypenate(namespace,'tick-label-clip-path')) - // var tickLabelClipPathRect = safeSelect(tickLabelClipPath, 'rect', hypenate(namespace,'tick-label-clip-path-rect')) - // .attr('x', 0) - // .attr('y', 0) - // .attr('width', function(d, i){ - // if (horizontalQ) { return tickLabelFontSize } - // if (verticalQ) { return spaceX - tickLength } - // }) - // .attr('height', function(d, i){ - // if (verticalQ) { return tickLabelFontSize } - // if (horizontalQ) { return spaceY - tickLength } - // }) - - - // for each tick container - var ticks = container.selectAll('g:not(.to-remove).' + objClass).each(function (d, i) { - var that = d3.select(this).style('opacity', 1); - - // make and move tick - var tick = safeSelect(that, 'line', hypenate(namespace, 'tick')).attr("x1", 0).attr("x2", horizontalQ ? 0 : orient == "left" ? -tickLength : tickLength).attr("y1", 0).attr('y2', verticalQ ? 0 : orient == "top" ? -tickLength : tickLength).attr('stroke', tickStroke).attr('stroke-width', tickStrokeWidth).attr('transform', function (d, i) { - var x = moveXBy(d, i, horizontalQ, categoricalQ, objectSize), - y = moveYBy(d, i, verticalQ, categoricalQ, objectSize), - t = 'translate(' + x + ',' + y + ')'; - return t; - }); - - // make and move label - var label = safeSelect(that, 'text', hypenate(namespace, 'label')).text(function (d, i) { - var s = typeof d == 'number' ? round(d, roundTo) : d; - s = truncateString(String(s), (horizontalQ ? spaceY : spaceX) - tickLength - tickLabelMargin - tickTickLabelSpacer, tickLabelFontSize * 0.45); - return s; - }).attr('font-size', tickLabelFontSize).attr('text-anchor', tickLabelTextAnchor); - // truncateText(label, label.text(), orient, tickLength, horizontalQ ? spaceY : spaceX, overflowQ) - - label.attr('transform', function (d, i) { - var rect = d3.select(this).node().getBoundingClientRect(), - leng = d3.select(this).node().getComputedTextLength(), - x = moveXBy(d, i, horizontalQ, categoricalQ, objectSize), - y = moveYBy(d, i, verticalQ, categoricalQ, objectSize); - - if (orient == 'top') { - y = -(tickLength + tickTickLabelSpacer); - // y = tickLength+tickTickLabelSpacer; - - // y -= Math.max(rect.height, rect.width); - x += Math.min(rect.height, rect.width) * 0.25; - // x -= leng * 0.25 + s - } - if (orient == 'bottom') { - y = tickLength + tickTickLabelSpacer; - x += Math.min(rect.height, rect.width) * 0.25; - // x += leng * 0.25 - s - } - if (orient == 'left') { - x -= tickLength + tickTickLabelSpacer; - // y += rect.height * 0.5; y-= rect.height/4 - y += Math.min(rect.height, rect.width) * 0.25; - // y += leng * 0.25 - } - if (orient == 'right') { - x += tickLength + tickTickLabelSpacer; - // y += Math.min(rect.height, rect.width) * 0.25 - // y += leng * 0.25 - y += rect.height * 0.5;y -= rect.height / 4; - } - - var t = 'translate(' + x + ',' + y + ')', - r = 'rotate(' + tickLabelRotation + ')'; - return t + r; - }).on('mousemove', labelHover).on('mouseout', labelHoverOff).on('click', tickLabelOnClick); - // .attr('clip-path', 'url(#'+hypenate(namespace,'tick-label-clip-path')+')') - - // add guidlines as needed - if (guideLinesQ) { - var gline = safeSelect(that, 'line', hypenate(namespace, 'guideline')).transition().duration(transitionDuration).ease(easeFunc).attr("x1", 0).attr("x2", horizontalQ ? 0 : orient == "left" ? guidelineSpace : -guidelineSpace).attr("y1", 0).attr('y2', verticalQ ? 0 : orient == "top" ? guidelineSpace : -guidelineSpace).attr('transform', function (d, i) { - var x = moveXBy(d, i, horizontalQ, categoricalQ, objectSize), - y = moveYBy(d, i, verticalQ, categoricalQ, objectSize), - t = 'translate(' + x + ',' + y + ')'; - return t; - }); - } else { - that.select('line.' + hypenate(namespace, 'guideline')).remove(); - } - }); - - // apply alternating guidline thickness - if (guideLinesQ) { - container.selectAll('.' + hypenate(namespace, 'guideline')).attr('stroke', function (d, i) { - if (i % 2 == 0) { - return modifyHexidecimalColorLuminance(guideLineStroke, 0.8); - } - return guideLineStroke; - }).attr('stroke-width', function (d, i) { - if (i % 2 == 0) { - return guideLineStrokeWidth * 0.8; - } - return guideLineStrokeWidth; - }).attr('minor', function (d, i) { - return i % 2 == 0; - }); - } - - /*************************************************************************** - ** Make the line of the axis - ***************************************************************************/ - var line = safeSelect(selection, 'path', hypenate(namespace, 'line')) - // .attr('x1', 0) - // .attr('x2', horizontalQ ? spaceX : 0) - // .attr('y1', 0) - // .attr('y2', horizontalQ ? 0 : spaceY) - .attr('d', horizontalQ ? 'M 0,0 H' + spaceX + ',0' : 'M 0,0 V 0,' + spaceY).attr('stroke', lineStroke).attr('stroke-width', lineStrokeWidth).classed('axis-line', true); - } - - // hover of label show full text label in case it is truncated - function labelHover(d, i) { - var t = d3.select(this).style('fill', 'red'); - d3.select(t.node().parentNode).select("line." + hypenate(namespace, 'tick')).attr("stroke", 'red').attr("stroke-width", tickStrokeWidth * 2); - - if (guideLinesQ) { - d3.select(t.node().parentNode).select('line.' + hypenate(namespace, 'guideline')).attr('stroke', 'red').attr('stroke-width', guideLineStrokeWidth * 2); - } - - var s = typeof d == 'number' ? round(d, roundTo) : d; - - var m = d3.mouse(d3.select('html').node()); - var div = safeSelect(d3.select('body'), 'div', hypenate(namespace, 'guideline-tooltip')).attr('id', hypenate(namespace, 'guideline-tooltip')).style('position', 'absolute').style('left', d3.event.pageX + 15 + 'px').style('top', d3.event.pageY + 15 + 'px').style('background-color', 'white').style('border-color', 'black') - // .style('min-width', (tickLabelFontSize * (String(s).split('.')[0].length+3))+'px') - // .style('min-height', (tickLabelFontSize * (String(s).split('.')[0].length+3))+'px') - .style('border-radius', '10px').style('display', 'flex').style('justify-content', 'center').style('text-align', 'middle').style('padding', 4 + "px").style('border-style', 'solid').style('border-width', 2); - - var text = safeSelect(div, 'div').text(tickLabelOnHoverFunc(s, i)).style('color', 'black').style('align-self', 'center'); - - var bbox = div.node().getBoundingClientRect(); - if (bbox.x + bbox.width > window.innerWidth) { - div.style('left', d3.event.pageX - 15 - 300 + 'px'); - } - } - - function labelHoverOff(d, i) { - var t = d3.select(this).style('fill', 'black'); - d3.select(t.node().parentNode).select("line." + hypenate(namespace, 'tick')).attr("stroke", tickStroke).attr("stroke-width", tickStrokeWidth); - - if (guideLinesQ) { - var gline = d3.select(t.node().parentNode).select('line.' + hypenate(namespace, 'guideline')); - var minorQ = gline.attr('minor'); - gline.attr('stroke', function (d, ii) { - if (minorQ == 'true') { - return modifyHexidecimalColorLuminance(guideLineStroke, 0.8); - } - return guideLineStroke; - }).attr('stroke-width', function (d, ii) { - if (minorQ == 'true') { - return guideLineStrokeWidth * 0.8; - } - return guideLineStrokeWidth; - }); - } - d3.select("#" + hypenate(namespace, 'guideline-tooltip')).remove(); - } - - return axis; - } - - /** - * Creates a colorFunction - * @constructor colorFunction - * @namespace colorFunction - * @returns {function} colorFunction - */ - function colorFunction() { - var /** - * Default colors to use - * @param {number[]} [colors=["#2c7bb6", "#00a6ca", "#00ccbc", "#90eb9d", "#ffff8c", "#f9d057", "#f29e2e", "#e76818", "#d7191c"]] - * @memberof colorFunction# - * @property - */ - colors = ["#2c7bb6", "#00a6ca", "#00ccbc", "#90eb9d", "#ffff8c", "#f9d057", "#f29e2e", "#e76818", "#d7191c"], - - /** - * Interpolator for colors - * @param {d3.interpolation} [interpolation=d3.interpolateRgb] - * @memberof colorFunction# - * @property - */ - interpolation = d3.interpolateRgb, - - /** - * Function for modifying color luminance - * @param {function} [modifyOpacity=modifyHexidecimalColorLuminance] - * @memberof colorFunction# - * @property - */ - modifyOpacity = modifyHexidecimalColorLuminance, - - /** - * How to modify color for stroke - * @param {number} [strokeOpacity=0] - * @memberof colorFunction# - * @property - */ - strokeOpacity = 0, - - /** - * How to modify color for fill - * @param {number} [fillOpacity=0.4] - * @memberof colorFunction# - * @property - */ - fillOpacity = 0.4, - - /** - * How to determine the color to use - * @param {string} [colorBy='index'] - * @memberof colorFunction# - * @property - */ - colorBy = 'index', - - /** - * Sets the scale for interpolating the colors - * @param {number[]} [dataExtent=[0, colors.length - 1]] - * @memberof colorFunction# - * @property - */ - dataExtent = [0, colors.length - 1], - - /** - * Extracts the value to color by - * @param {function} [valueExtractor=function(k, v, i) {return v}] - * @memberof colorFunction# - * @property - */ - valueExtractor = function valueExtractor(k, v, i) { - return v; - }, - - - /** - * Extracts the category to color by - * @param {function} [categoryExtractor=function(k, v, i) {return v.category}] - * @memberof colorFunction# - * @property - */ - categoryExtractor = function categoryExtractor(k, v, i) { - return v.category; - }, - - - /** - * The different type of categories of which to color by - * @param {string[]} [categories=undefined] - * @memberof colorFunction# - * @property - */ - categories, - - - /** - * Scale for interpolating the colors - * @param {d3.scale} [scale=d3.scaleLinear()] - * @memberof colorFunction# - * @property - */ - scale = d3.scaleLinear().interpolate(interpolation).domain(dataExtent).range(colors), - helperScale = d3.scaleLinear(); - - // var h = x => '#' + x.match(/\d+/g).map(y = z => ((+z < 16)?'0':'') + (+z).toString(16)).join(''); - var h = function h(x) { - return "#" + x.match(/\d+/g).map(function (y, i) { - return (+y < 16 ? '0' : '') + (+y).toString(16); - }).join(''); - }; - - /** - * Gets or sets the default colors - * (see {@link colorFunction#colors}) - * @param {number[]} [_=none] - * @returns {colorFunction | number[]} - * @memberof colorFunction - * @property - */ - colorFunction.colors = function (_) { - return arguments.length ? (colors = _, scale.range(colors), colorFunction) : colors; - }; - /** - * Gets or sets the function for interpolating the colors - * (see {@link colorFunction#interpolation}) - * @param {d3.interpolation} [_=none] - * @returns {colorFunction | d3.interpolation} - * @memberof colorFunction - * @property - */ - colorFunction.interpolation = function (_) { - return arguments.length ? (interpolation = _, scale.interpolate(interpolation).range(colors), colorFunction) : interpolation; - }; - /** - * Gets or sets the values for the scale which transforms the value to a color - * (see {@link colorFunction#dataExtent}) - * @param {number[]} [_=none] - * @returns {colorFunction | number[]} - * @memberof colorFunction - * @property - */ - colorFunction.dataExtent = function (_) { - return arguments.length ? (dataExtent = _, scale.domain(dataExtent).interpolate(scale.interpolate()), colorFunction) : dataExtent; - }; - /** - * Gets or sets the vthe scale which transforms the value to a color - * (see {@link colorFunction#scale}) - * @param {d3.scale} [_=none] - * @returns {colorFunction | d3.scale} - * @memberof colorFunction - * @property - */ - colorFunction.scale = function (_) { - return arguments.length ? (_ = _.domain(scale.domain()).interpolate(scale.interpolate()).range(scale.range()), scale = _, colorFunction) : scale; - }; - /** - * Gets or sets the function for modify opacity - * (see {@link colorFunction#modifyOpacity}) - * @param {function} [_=none] - * @returns {colorFunction | function} - * @memberof colorFunction - * @property - */ - colorFunction.modifyOpacity = function (_) { - return arguments.length ? (modifyOpacity = _, colorFunction) : modifyOpacity; - }; - /** - * Gets or sets the value to modify the color for the stroke via {@link colorFunction#modifyOpacity} - * (see {@link colorFunction#strokeOpacity}) - * @param {number} [_=none] - * @returns {colorFunction | number} - * @memberof colorFunction - * @property - */ - colorFunction.strokeOpacity = function (_) { - return arguments.length ? (strokeOpacity = _, colorFunction) : strokeOpacity; - }; - /** - * Gets or sets the value to modify the color for the stroke via {@link colorFunction#fillOpacity} - * (see {@link colorFunction#fillOpacity}) - * @param {number} [_=none] - * @returns {colorFunction | number} - * @memberof colorFunction - * @property - */ - colorFunction.fillOpacity = function (_) { - return arguments.length ? (fillOpacity = _, colorFunction) : fillOpacity; - }; - /** - * Gets or sets the value to colorBy - * (see {@link colorFunction#colorBy}) - * @param {string} [_=none] - * @returns {colorFunction | string} - * @memberof colorFunction - * @property - */ - colorFunction.colorBy = function (_) { - return arguments.length ? (colorBy = _, colorFunction) : colorBy; - }; - /** - * Gets or sets the value of valueExtractor - * (see {@link colorFunction#valueExtractor}) - * @param {function} [_=none] - * @returns {colorFunction | function} - * @memberof colorFunction - * @property - */ - colorFunction.valueExtractor = function (_) { - return arguments.length ? (valueExtractor = _, colorFunction) : valueExtractor; - }; - - /** - * Gets or sets the value of categoryExtractor - * (see {@link colorFunction#categoryExtractor}) - * @param {function} [_=none] - * @returns {colorFunction | function} - * @memberof colorFunction - * @property - */ - colorFunction.categoryExtractor = function (_) { - return arguments.length ? (categoryExtractor = _, colorFunction) : categoryExtractor; - }; - /** - * Gets or sets the value of categoryExtractor - * (see {@link colorFunction#categories}) - * @param {string[]} [_=none] - * @returns {colorFunction | string[]} - * @memberof colorFunction - * @property - */ - colorFunction.categories = function (_) { - return arguments.length ? (categories = _, colorFunction) : categories; - }; - - function colorFunction(key, value, index, type, hoverQ) { - var c, - opac = type == "fill" ? fillOpacity : strokeOpacity; - - updateScale(); - - if (colorBy == "index") { - c = type != undefined ? modifyOpacity(h(scale(index)), opac) : h(scale(index)); - } else if (colorBy == 'value') { - var v = valueExtractor(key, value, index); - // if (v < dataExtent[0]) {dataExtent[0] = v; updateScale()} - // if (v > dataExtent[1]) {dataExtent[1] = v; updateScale()} - - c = type != undefined ? modifyOpacity(h(scale(v)), opac) : h(scale(v)); - } else if (colorBy == 'category') { - var cat = categoryExtractor(key, value, index); - var v = categories.indexOf(cat); - c = type != undefined ? modifyOpacity(h(scale(v)), opac) : h(scale(v)); - } else { - c = type != undefined ? modifyOpacity(h(scale(index)), opac) : h(scale(index)); - } - - return c; - } - - function updateScale() { - - helperScale.domain([0, colors.length]); - if (colorBy == 'category' && categories != undefined) { - helperScale.range([0, categories.length]); - } else { - helperScale.range(dataExtent); - } - - var a = Array(colors.length).fill(0).map(function (d, i) { - return helperScale(i); - }); - scale.domain(a); - } - - return colorFunction; - } - - /******************************************************************************* - ** ** - ** ** - ** TOOLTIP ** - ** ** - ** ** - *******************************************************************************/ - /** - * Produces a function for handling the tooltip - * - * {@link https://sumneuron.gitlab.io/d3sm/demos/tooltip-design/index.html Demo} - * @param {d3.selection} selection - * @returns {tooltip} - * @namespace tooltip - */ - function tooltip(selection) { - - var keys, values, header, data, selection; - - /** - * Gets / sets the keys to be displayed in the tooltip. - * If not set, uses d3.keys(data[key]) - * @param {string[]} [_=none] - * @returns {tooltip | string[]} - * @memberof tooltip - */ - tooltip.keys = function (_) { - return arguments.length ? (keys = _, tooltip) : keys; - }; - /** - * Gets / sets the values to be displayed next to the keys. - * If not set, uses data[key][keys[i]]. - * If a function, gets passed currentData (data[key]) and keys[i]. - * @param {*[]} [_=none] - * @returns {tooltip | *[]} - * @memberof tooltip - */ - tooltip.values = function (_) { - return arguments.length ? (values = _, tooltip) : values; - }; - /** - * Gets / sets the header to be displayed in the tooltip. - * If not set, uses key - * @param {string} [_=none] - * @returns {tooltip | string} - * @memberof tooltip - */ - tooltip.header = function (_) { - return arguments.length ? (header = _, tooltip) : header; - }; - /** - * Gets / sets the data (over the selection) to be used for the tooltip - * @param {Object} [_=none] - * @returns {tooltip | Object} - * @memberof tooltip - */ - tooltip.data = function (_) { - return arguments.length ? (data = _, tooltip) : data; - }; - /** - * Gets / sets the selection for the tooltip to be applied on - * @param {d3.selection} [_=none] - * @returns {tooltip | d3.selection} - * @memberof tooltip - */ - tooltip.selection = function (_) { - return arguments.length ? (selection = _, tooltip) : selection; - }; - - /** - * Bind, via selection.on(), the mousemove and mouseout events - * @returns undefined - */ - function tooltip() { - selection.on('mouseover', mousemove); - selection.on('mousemove', mousemove); - selection.on('mouseout', function () { - d3.selectAll(".d3sm-tooltip").remove(); - }); - } - - /** - * Produces the tooltip on mousemove - * @param {string} key of the object targeted by the mousemove - * @param {number} i (index) of the object targeted by mousemove - * @memberof tooltip - * @private - */ - function mousemove(key, i) { - consoleGroup('d3sm-tooltip'); - var currentData = data[key]; - - var _d3$mouse = d3.mouse(d3.select("html").node()), - _d3$mouse2 = slicedToArray(_d3$mouse, 2), - x = _d3$mouse2[0], - y = _d3$mouse2[1]; - - log('tooltip', 'mousemove detected', { key: key, index: i, x: x, y: y }); - log('tooltip', 'current data', currentData); - - var div = safeSelect(d3.select('html'), 'tooltip', 'd3sm-tooltip').classed('card', true).style('max-width', '300px').style('background-color', "#212529").style('color', 'white'); - - var cardBody = safeSelect(div, 'div', 'card-body'); - var cardTitle = safeSelect(cardBody, 'h5', 'card-title').text(header == undefined ? key : typeof header == 'function' ? header(key, currentData, i) : header).style('color', 'cyan'); - - var table = safeSelect(cardBody, 'table', 'table').classed('table-dark', true); - var tBody = safeSelect(table, 'tbody'); - - tBody = tBody.selectAll('tr'); - tBody = tBody.data(keys == undefined ? d3.keys(currentData) : keys); - tBody.exit().remove(); - - var tr = tBody.enter().append('tr').style('max-width', '300px'); - tr.append('td').attr('class', function (d, i) { - return 'tooltip-key'; - }); - tr.append('td').attr('class', function (d, i, j) { - return 'tooltip-value'; - }).attr('tooltip-row-index', function (d, i) { - return i; - }); - - // tBody = tBody.merge(tr) - consoleGroup('tooltip-rows'); - tBody.selectAll('.tooltip-key').text(function (d, i) { - return d; - }); - tBody.selectAll('tr .tooltip-value').text(function (d, i) { - log('tooltip', 'trying to set value', { rowKey: d, rowIndex: i }); - var i = d3.select(this).attr('tooltip-row-index'); - var v = currentData[d]; - - if (values != undefined) { - v = values[i];if (typeof v == "function") { - v = v(currentData, d); - } - } - return typeof v == 'number' ? round(v, 5) : v; - }); - consoleGroupEnd(); - consoleGroupEnd(); - - x += 15; - // x += 15 - var bbox = div.node().getBoundingClientRect(); - if (x + bbox.width > window.innerWidth - window.scrollX) { - x = d3.event.pageX - bbox.width - 15; - } - if (y + bbox.height > window.innerHeight - window.scrollY) { - y = d3.event.pageY - bbox.height - 15; - } - div.style('position') == "relative" ? div.style('position', 'absolute').style('left', x + 'px').style('top', y + 'px') : div.style('left', x + 'px').style('top', y + 'px'); - // .transition().duration(200).ease(d3.easeSin) - - // if (bbox.x + bbox.width > window.innerWidth) { - // div.style('left', (d3.event.pageX-15-bbox.width)+'px') - // } - // if (bbox.y + bbox.height > window.innerHeight) { - // div.style('top', (d3.event.pageY-15-bbox.height)+'px') - // } - - div.attr('z-index', 10000); - } - - return tooltip; - } - - /******************************************************************************* - ** ** - ** ** - ** BAR ** - ** ** - ** ** - *******************************************************************************/ - - /** - * Creates a bar - * - * {@link https://sumneuron.gitlab.io/d3sm/demos/bar-chart-same-data-complex-grouping/index.html Demo} - * @constructor bar - * @param {d3.selection} selection - * @namespace bar - * @returns {function} bar - */ - function bar(selection) { - /* - Assumes that data is list an object. - The keys of data will be bound to the bars. - The valueExtractor function will extract the value from data[key]. - Grouping can be used if desired. It should be an arbitrary complex list where - the values are strings matching keys in data. - */ - var - /** - * Data to plot. Assumed to be a object, where each key corresponds to a bar - * (see {@link bar#data}) - * @param {Object} [data=undefined] - * @memberof bar# - * @property - */ - data, - - /** - * Which direction to render the bars in - * (see {@link bar#orient}) - * @param {number} [orient='horizontal'] - * @memberof bar# - * @property - */ - orient = 'horizontal', - - /** - * Amount of horizontal space (in pixels) avaible to render the bar in - * (see {@link bar#spaceX}) - * @param {number} [spaceX=undefined] - * @memberof bar# - * @property - */ - spaceX, - - /** - * Amount of vertical space (in pixels) avaible to render the bar in - * (see {@link bar.spaceY}) - * @param {number} [spaceY=undefined] - * @memberof bar# - * @property - */ - spaceY, - - - /** - * Whether or not to allow bar to render elements pass the main spatial dimension - * given the orientation (see {@link bar#orient}), where {@link bar#orient}="horizontal" - * the main dimension is {@link bar#spaceX} and where {@link bar#orient}="vertical" - * the main dimension is {@link bar#spaceY} - * @param {boolean} [overflowQ=false] - * @memberof bar# - * @property - */ - overflowQ = false, - - - /** - * An array - putatively of other arrays - depicting how bars should be arranged - * @param {Array[]} [grouping=undefined] - * @memberof bar# - * @property - */ - grouping, - - - /** - * How to get the value of the bar - * @param {function} [valueExtractor=function(key, index) { return data[key] }] - * @memberof bar# - * @property - */ - valueExtractor = function valueExtractor(key, index) { - return data[key]; - }, - - /** - * How to sort the bars - if {@link bar#grouping} is not provided. - * @param {function} [sortingFunction=function(keyA, keyB) {return d3.descending(data[keyA], data[keyB])}] - * @memberof bar# - * @property - */ - sortingFunction = function sortingFunction(keyA, keyB) { - return d3.descending(data[keyA], data[keyB]); - }, - - - /** - * The scale for which bar values should be transformed by - * @param {d3.scale} [scale=d3.scaleLinear] - * @memberof bar# - * @property - */ - scale = d3.scaleLinear(), - - /** - * The padding for the domain of the scale (see {@link bar#scale}) - * @param {number} [domainPadding=0.5] - * @memberof bar# - * @property - */ - domainPadding = 0.5, - - - /** - * Default space for the spacer (percentage) of main dimension given the orientation - * (see {@link bar#orient}), where {@link bar#orient}="horizontal" - * the main dimension is {@link bar#spaceX} and where {@link bar#orient}="vertical" - * the main dimension is {@link bar#spaceY} between bars - * @param {number} [objectSpacer=0.05] - * @memberof bar# - * @property - */ - objectSpacer = 0.05, - - /** - * The minimum size that an object can be - * @param {number} [minObjectSize=50] - * @memberof bar# - * @property - */ - minObjectSize = 50, - - /** - * The maximum size that an object can be - * @param {number} [maxObjectSize=100] - * @memberof bar# - * @property - */ - maxObjectSize = 100, - - - /** - * The stroke width of the bars - * @param {number} [barStrokeWidth=2] - * @memberof bar# - * @property - */ - barStrokeWidth = 2, - - /** - * Instance of ColorFunction - * @param {function} [colorFunction = colorFunction()] - * @memberof bar# - * @property - */ - colorFunction$$1 = colorFunction(), - - - /** - * Color of the background - * @param {string} [backgroundFill="transparent"] - * @memberof bar# - * @property - */ - backgroundFill = 'transparent', - - /** - * Namespace for all items made by this instance of bar - * @param {string} [namespace="d3sm-bar"] - * @memberof bar# - * @property - */ - namespace = 'd3sm-bar', - - /** - * Class name for bar container ( element) - * @param {string} [objectClass="bar"] - * @memberof bar# - * @property - */ - objectClass = 'bar', - - - /** - * Duration of all transitions of this element - * @param {number} [transitionDuration=1000] - * @memberof bar# - * @property - */ - transitionDuration = 1000, - - /** - * Easing function for transitions - * @param {d3.ease} [easeFunc=d3.easeExp] - * @memberof bar# - * @property - */ - easeFunc = d3.easeExp, - - - // useful values to extract to prevent re-calculation - /** - * The keys of the bars - * @param {string[]} [barKeys=undefined] - * @memberof bar# - * @property - */ - barKeys, - - /** - * The values of the bars - * @param {number[]} [barValues=undefined] - * @memberof bar# - * @property - */ - barValues, - - /** - * The objectSize (actual width) used by the bars - * @param {number} [objectSize=undefined] - * @memberof bar# - * @property - */ - objectSize, - - /** - * The spacerSize (actual width) used by the spacers between the bars - * @param {number} [spacerSize=undefined] - * @memberof bar# - * @property - */ - spacerSize, - - /** - * Instance of Tooltip - * @param {function} [tooltip=tooltip()] - * @memberof bar# - * @property - */ - tooltip$$1 = tooltip(), - barPercent = 1; - - /** - * Gets or sets the selection in which items are manipulated - * @param {d3.selection} [_=none] - * @returns {bar | d3.selection} - * @memberof bar - * @property - * by default selection = selection - */ - bar.selection = function (_) { - return arguments.length ? (selection = _, bar) : selection; - }; - /** - * Gets or sets the data - * (see {@link bar#data}) - * @param {number} [_=none] - * @returns {bar | object} - * @memberof bar - * @property - */ - bar.data = function (_) { - return arguments.length ? (data = _, bar) : data; - }; - /** - * Gets or sets the orient of the bars - * (see {@link bar#orient}) - * @param {number} [_=none] - * @returns {bar | object} - * @memberof bar - * @property - */ - bar.orient = function (_) { - return arguments.length ? (orient = _, bar) : orient; - }; - /** - * Gets or sets the amount of horizontal space in which items are manipulated - * (see {@link bar#spaceX}) - * @param {number} [_=none] should be a number > 0 - * @returns {bar | number} - * @memberof bar - * @property - * by default spaceX = undefined - */ - bar.spaceX = function (_) { - return arguments.length ? (spaceX = _, bar) : spaceX; - }; - /** - * Gets or sets the amount of vertical space in which items are manipulated - * (see {@link bar#spaceY}) - * @param {number} [_=none] should be a number > 0 - * @returns {bar | number} - * @memberof bar - * @property - * by default spaceY = undefined - */ - bar.spaceY = function (_) { - return arguments.length ? (spaceY = _, bar) : spaceY; - }; - - /** - * Gets / sets whether or not bar is allowed to go beyond specified dimensions - * (see {@link bar#spaceX}) - * @param {boolean} [_=none] - * @returns {bar | boolean} - * @memberof bar - * @property - * by default overflowQ = false - */ - bar.overflowQ = function (_) { - return arguments.length ? (overflowQ = _, bar) : overflowQ; - }; - /** - * Gets / sets the grouping of the bars - * (see {@link bar#grouping}) - * @param {Array[]} [_=none] - * @returns {bar | Array[]} - * @memberof bar - * @property - * by default grouping = undefined - */ - bar.grouping = function (_) { - return arguments.length ? (grouping = _, bar) : grouping; - }; - /** - * Gets / sets the valueExtractor - * (see {@link bar#valueExtractor}) - * @param {function} [_=none] - * @returns {bar | function} - * @memberof bar - * @property - * by default valueExtractor = function(key, index) { return data[key] }, - */ - bar.valueExtractor = function (_) { - return arguments.length ? (valueExtractor = _, bar) : valueExtractor; - }; - /** - * Gets / sets the sortingFunction - * (see {@link bar#sortingFunction}) - * @param {function} [_=none] - * @returns {bar | function} - * @memberof bar - * @property - * by default sortingFunction = function(keyA, keyB) {return d3.descending(data[keyA], data[keyB])}, - */ - bar.sortingFunction = function (_) { - return arguments.length ? (sortingFunction = _, bar) : sortingFunction; - }; - /** - * Gets / sets the scale for which the bar values should be transformed by - * (see {@link bar#scale}) - * @param {d3.scale} [_=none] - * @returns {bar | d3.scale} - * @memberof bar - * @property - * by default scale = d3.scaleLinear() - */ - bar.scale = function (_) { - return arguments.length ? (scale = _, bar) : scale; - }; - /** - * Gets / sets the padding for the domain of the scale - * (see {@link bar#domainPadding}) - * @param {number} [_=none] - * @returns {bar | number} - * @memberof bar - * @property - * by default domainPadding = 0.5 - */ - bar.domainPadding = function (_) { - return arguments.length ? (domainPadding = _, bar) : domainPadding; - }; - /** - * Gets / sets objectSpacer - * (see {@link bar#objectSpacer}) - * @param {number} [_=none] - * @returns {bar | number} - * @memberof bar - * @property - * by default objectSpacer = 0.05 - */ - bar.objectSpacer = function (_) { - return arguments.length ? (objectSpacer = _, bar) : objectSpacer; - }; - /** - * Gets / sets the minObjectSize - * (see {@link bar#minObjectSize}) - * @param {number} [_=none] - * @returns {bar | number} - * @memberof bar - * @property - * by default minObjectSize = 50 - */ - bar.minObjectSize = function (_) { - return arguments.length ? (minObjectSize = _, bar) : minObjectSize; - }; - /** - * Gets / sets the maxObjectSize - * (see {@link bar#maxObjectSize}) - * @param {number} [_=none] - * @returns {bar | number} - * @memberof bar - * @property - * by default maxObjectSize = 100 - */ - bar.maxObjectSize = function (_) { - return arguments.length ? (maxObjectSize = _, bar) : maxObjectSize; - }; - - /** - * Gets / sets the barStrokeWidth - * (see {@link bar#barStrokeWidth}) - * @param {number} [_=none] - * @returns {bar | number} - * @memberof bar - * @property - * by default barStrokeWidth = 2 - */ - bar.barStrokeWidth = function (_) { - return arguments.length ? (barStrokeWidth = _, bar) : barStrokeWidth; - }; - /** - * Gets / sets the colorFunction - * (see {@link bar#colorFunction}) - * @param {number} [_=none] - * @returns {bar | number} - * @memberof bar - * @property - * by default colorFunction = colorFunction() - */ - bar.colorFunction = function (_) { - return arguments.length ? (colorFunction$$1 = _, bar) : colorFunction$$1; - }; - - /** - * Gets / sets the backgroundFill - * (see {@link bar#backgroundFill}) - * @param {string} [_=none] - * @returns {bar | string} - * @memberof bar - * @property - * by default backgroundFill = 'transparent' - */ - bar.backgroundFill = function (_) { - return arguments.length ? (backgroundFill = _, bar) : backgroundFill; - }; - /** - * Gets / sets the namespace - * (see {@link bar#namespace}) - * @param {string} [_=none] - * @returns {bar | string} - * @memberof bar - * @property - * by default namespace = 'd3sm-bar' - */ - bar.namespace = function (_) { - return arguments.length ? (namespace = _, bar) : namespace; - }; - /** - * Gets / sets the objectClass - * (see {@link bar#objectClass}) - * @param {string} [_=none] - * @returns {bar | string} - * @memberof bar - * @property - * by default objectClass = 'tick-group' - */ - bar.objectClass = function (_) { - return arguments.length ? (objectClass = _, bar) : objectClass; - }; - /** - * Gets / sets the transitionDuration - * (see {@link bar#transitionDuration}) - * @param {number} [_=none] - * @returns {bar | number} - * @memberof bar - * @property - * by default transitionDuration = 1000 - */ - bar.transitionDuration = function (_) { - return arguments.length ? (transitionDuration = _, bar) : transitionDuration; - }; - /** - * Gets / sets the easeFunc - * (see {@link bar#easeFunc}) - * @param {d3.ease} [_=none] - * @returns {bar | d3.ease} - * @memberof bar - * @property - * by default easeFunc = d3.easeExp - */ - bar.easeFunc = function (_) { - return arguments.length ? (easeFunc = _, bar) : easeFunc; - }; - - /** - * Gets / sets the barKeys - * (see {@link bar#barKeys}) - * @param {string[]} [_=none] - * @returns {bar | string[]} - * @memberof bar - * @property - * by default barKeys = undefined - */ - bar.barKeys = function (_) { - return arguments.length ? (barKeys = _, bar) : barKeys; - }; - /** - * Gets / sets the barValues - * (see {@link bar#barValues}) - * @param {number[]} [_=none] - * @returns {bar | number[]} - * @memberof bar - * @property - * by default barValues = undefined - */ - bar.barValues = function (_) { - return arguments.length ? (barValues = _, bar) : barValues; - }; - /** - * Gets / sets the objectSize - * (see {@link bar#objectSize}) - * @param {number} [_=none] - * @returns {bar | number} - * @memberof bar - * @property - * by default objectSize = undefined - */ - bar.objectSize = function (_) { - return arguments.length ? (objectSize = _, bar) : objectSize; - }; - /** - * Gets / sets the spacerSize - * (see {@link bar#spacerSize}) - * @param {number} [_=none] - * @returns {bar | number} - * @memberof bar - * @property - * by default spacerSize = undefined - */ - bar.spacerSize = function (_) { - return arguments.length ? (spacerSize = _, bar) : spacerSize; - }; - - /** - * Gets / sets the tooltip - * (see {@link bar#tooltip}) - * @param {tooltip} [_=none] - * @returns {bar | tooltip} - * @memberof bar - * @property - * by default tooltip = tooltip() - */ - bar.tooltip = function (_) { - return arguments.length ? (tooltip$$1 = _, bar) : tooltip$$1; - }; - - bar.barPercent = function (_) { - return arguments.length ? (barPercent = _, bar) : barPercent; - }; - - function bar() { - // for convenience in handling orientation specific values - var horizontalQ = orient == 'horizontal' || orient == 'bottom' || orient == 'top' ? true : false; - var verticalQ = !horizontalQ; - - // background cliping rectangle - var bgcpRect = { x: 0, y: 0, width: spaceX, height: spaceY }; - var container = setupContainer(selection, namespace, bgcpRect, backgroundFill); - - // to prevent re-calculation and getters to be passed to axes - barKeys = d3.keys(data); - barValues = barKeys.map(valueExtractor); - - // if grouping is undefined sort barKeys by sortingFunction - var ordered = grouping == undefined ? barKeys.sort(sortingFunction) : grouping; - // ordered might be nested depending on grouping - barKeys = flatten(ordered); - - var numberOfObjects = barKeys.length; - var extent = [Math.min.apply(Math, toConsumableArray(barValues)) - domainPadding, Math.max.apply(Math, toConsumableArray(barValues)) + domainPadding]; - - // set the scale - - scale.domain(extent).range(horizontalQ ? [0, spaceY] : orient == 'right' ? [0, spaceX] : [spaceX, 0]); - var space = horizontalQ ? spaceX : spaceY; - // calculate object size - objectSize = objectSize == undefined ? calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ) : objectSize; - - // calculate spacer size if needed - spacerSize = spacerSize == undefined ? calculateWidthOfSpacer(barKeys, space, objectSize, numberOfObjects, objectSpacer, overflowQ) : spacerSize; - // make the nested groups - var spacerFunction = groupingSpacer().horizontalQ(horizontalQ).scale(scale).moveby('category').numberOfObjects(numberOfObjects).objectClass(objectClass).objectSize(objectSize).spacerSize(spacerSize).transitionDuration(transitionDuration).easeFunc(easeFunc).namespace(namespace); - // safe default function - var defaultExit = spacerFunction.exitFunction(); - - spacerFunction.exitFunction(function (sel) { - // use default to move objects off screen - // console.log("EXIT", sel.nodes(), objectSize, scale(extent[1])) - if (objectSize == undefined) { - console.log(sel.nodes(), objectSize); - } - defaultExit(sel); - sel.selectAll('g').classed("to-remove", true); - // shrink rectangles in addition - sel.selectAll('* > rect').transition().duration(transitionDuration).attr('transform', function (d, i) { - var x = horizontalQ ? 0 : 0, - y = verticalQ ? 0 : scale(extent[1]), - t = 'translate(' + x + ',' + y + ')'; - return t; - }).attr('width', horizontalQ ? objectSize : 0).attr('height', verticalQ ? objectSize : 0).remove(); - }); - - // move stuff - spacerFunction(container, ordered, 0); - - var parentIndexArray = []; - container.selectAll('g:not(.to-remove).' + objectClass).each(function (d, i) { - parentIndexArray.push(Number(d3.select(this).attr('parent-index'))); - }); - - colorFunction$$1 = colorFunction$$1.colorBy() == 'index' ? colorFunction$$1.dataExtent([0, Math.max.apply(Math, parentIndexArray)]) : colorFunction$$1.dataExtent(extent); - - container.selectAll('g.' + objectClass + ':not(.to-remove)').each(function (key, i) { - // console.log(key, scale(extent[1]) - scale(valueExtractor(key, i))) - var t = d3.select(this), - currentData = data[key], - value = valueExtractor(key, i), - i = t.attr('parent-index') == undefined ? i : t.attr('parent-index'), - fillColor = colorFunction$$1(key, value, i, 'fill'), - // prevent duplicate computation - strokeColor = colorFunction$$1(key, value, i, 'stroke'); - - var bar = safeSelect(t, 'rect', 'bar-rect'); - - if (bar.attr('transform') == undefined) { - bar.attr('transform', function (d, i) { - var x = horizontalQ ? 0 : 0, - y = verticalQ ? 0 : scale(extent[1]), - t = 'translate(' + x + ',' + y + ')'; - return t; - }).attr('width', horizontalQ ? objectSize : 0).attr('height', verticalQ ? objectSize : 0); - } - - bar.transition().duration(transitionDuration).ease(easeFunc).attr('transform', function (d, i) { - var x = horizontalQ ? objectSize - objectSize * barPercent : orient == 'right' ? scale(extent[1]) - scale(value) : objectSize - objectSize * barPercent, - y = verticalQ ? objectSize - objectSize * barPercent : scale(extent[1]) - scale(value), - t = 'translate(' + x + ',' + y + ')'; - return t; - }).attr('width', horizontalQ ? objectSize * barPercent : scale(value)).attr('height', verticalQ ? objectSize * barPercent : scale(value)).attr('fill', fillColor).attr('stroke', strokeColor).attr('stroke-width', barStrokeWidth); - - t.on('mouseover', function (d, i) { - container.selectAll('g.' + objectClass).style('opacity', 0.2); - t.style('opacity', 1); - bar.attr('stroke-width', barStrokeWidth * 2); - }); - t.on('mouseout', function () { - container.selectAll('g.' + objectClass).style('opacity', 1); - bar.attr('stroke-width', barStrokeWidth); - }); - }); - - tooltip$$1.selection(container.selectAll('.bar-rect')).data(data); - - tooltip$$1(); - } - return bar; - } - - /** - * Creates a bubbleHeatmap - * - * {@link https://sumneuron.gitlab.io/d3sm/demos/bubble-heatmap/index.html Demo} - * @constructor bubbleHeatmap - * @param {d3.selection} selection - * @namespace bubbleHeatmap - * @returns {function} bubbleHeatmap - */ - function bubbleHeatmap(selection) { - var - /** - * Data to plot. Assumed to be a object, where each key corresponds to a cell - * (see {@link bubbleHeatmap#data}) - * @param {Object} [data=undefined] - * @memberof bubbleHeatmap# - * @property - */ - data, - - - /** - * Amount of horizontal space (in pixels) avaible to render the bubbleHeatmap in - * (see {@link bubbleHeatmap#spaceX}) - * @param {number} [spaceX=undefined] - * @memberof bubbleHeatmap# - * @property - */ - spaceX, - - /** - * Amount of vertical space (in pixels) avaible to render the bubbleHeatmap in - * (see {@link bubbleHeatmap.spaceY}) - * @param {number} [spaceY=undefined] - * @memberof bubbleHeatmap# - * @property - */ - spaceY, - - - /** - * The internal key of the cell specifiying to which x axis key it belongs - * (see {@link bubbleHeatmap.xKey}) - * @param {string} [xKey='x'] - * @memberof bubbleHeatmap# - * @property - */ - xKey = 'x', - - /** - * The internal key of the cell specifiying to which y axis key it belongs - * (see {@link bubbleHeatmap.yKey}) - * @param {string} [yKey='y'] - * @memberof bubbleHeatmap# - * @property - */ - yKey = 'y', - - /** - * The internal key of the cell specifiying what value to use to determine the radius - * (see {@link bubbleHeatmap.rKey}) - * @param {string} [rKey='r'] - * @memberof bubbleHeatmap# - * @property - */ - rKey = 'r', - - /** - * The internal key of the cell specifiying what value to use to determine the color - * (see {@link bubbleHeatmap.vKey}) - * @param {string} [vKey='v'] - * @memberof bubbleHeatmap# - * @property - */ - vKey = 'v', - - - /** - * Function for extracting the the value from xKey. - * (see {@link bubbleHeatmap.xExtractor}) - * @param {function} [xExtractor=function(key, i) { return data[key][xKey] }] - * @returns {string} - * @memberof bubbleHeatmap# - * @property - */ - xExtractor = function xExtractor(key, i) { - return data[key][xKey]; - }, - - /** - * Function for extracting the the value from yKey. - * (see {@link bubbleHeatmap.yExtractor}) - * @param {function} [yExtractor=function(key, i) { return data[key][yKey] }] - * @returns {string} - * @memberof bubbleHeatmap# - * @property - */ - yExtractor = function yExtractor(key, i) { - return data[key][yKey]; - }, - - /** - * Function for extracting the the value from rKey. - * (see {@link bubbleHeatmap.rExtractor}) - * @param {function} [rExtractor=function(key, i) { return data[key][rKey] }] - * @returns {number} - * @memberof bubbleHeatmap# - * @property - */ - rExtractor = function rExtractor(key, i) { - return data[key][rKey]; - }, - - /** - * Function for extracting the the value from vKey. - * (see {@link bubbleHeatmap.vExtractor}) - * @param {function} [vExtractor=function(key, i) { return data[key][vKey] }] - * @returns {number} - * @memberof bubbleHeatmap# - * @property - */ - vExtractor = function vExtractor(key, i) { - return data[key][vKey]; - }, - - - /** - * Whether or not to allow bubbleHeatmap to render elements pass the main spatial dimension - * given the orientation (see {@link bubbleHeatmap#orient}), where {@link bubbleHeatmap#orient}="bottom" or {@link bubbleHeatmap#orient}="top" - * the main dimension is {@link bubbleHeatmap#spaceX} and where {@link bubbleHeatmap#orient}="left" or {@link bubbleHeatmap#orient}="right" - * the main dimension is {@link bubbleHeatmap#spaceY} - * @param {boolean} [overflowQ=false] - * @memberof bubbleHeatmap# - * @property - */ - overflowQ = false, - - - /** - * The scale for which the radius values should be transformed by - * @param {d3.scale} [scale=d3.scaleLinear] - * @memberof bubbleHeatmap# - * @property - */ - scale = d3.scaleLinear(), - - /** - * The padding for the domain of the scale (see {@link bubbleHeatmap#scale}) - * @param {number} [domainPadding=0.5] - * @memberof bubbleHeatmap# - * @property - */ - domainPadding = 0.5, - - - /** - * Default space for the spacer (percentage) of main dimension given the orientation - * (see {@link bubbleHeatmap#orient}), where {@link bubbleHeatmap#orient}="horizontal" - * the main dimension is {@link bubbleHeatmap#spaceX} and where {@link bubbleHeatmap#orient}="vertical" - * the main dimension is {@link bubbleHeatmap#spaceY} between bubbles - * @param {number} [objectSpacer=0.0] - * @memberof bubbleHeatmap# - * @property - */ - objectSpacer = 0.0, - - /** - * The minimum size that an object can be - * @param {number} [minObjectSize=50] - * @memberof bubbleHeatmap# - * @property - */ - minObjectSize = 50, - - /** - * The maximum size that an object can be - * @param {number} [maxObjectSize=100] - * @memberof bubbleHeatmap# - * @property - */ - maxObjectSize = 100, - - - /** - * The stroke width of the bubbles - * @param {number} [bubbleStrokeWidth=2] - * @memberof bubbleHeatmap# - * @property - */ - bubbleStrokeWidth = 2, - - // colorFunc = colorFunction(), - - /** - * Color of the background - * @param {string} [backgroundFill="transparent"] - * @memberof bubbleHeatmap# - * @property - */ - backgroundFill = 'transparent', - - /** - * Namespace for all items made by this instance of bubbleHeatmap - * @param {string} [namespace="d3sm-bubble"] - * @memberof bubbleHeatmap# - * @property - */ - namespace = 'd3sm-bubble', - - /** - * Class name for bubble container ( element) - * @param {string} [objectClass="bubble"] - * @memberof bubbleHeatmap# - * @property - */ - objectClass = 'bubble', - - /** - * Duration of all transitions of this element - * @param {number} [transitionDuration=1000] - * @memberof bubbleHeatmap# - * @property - */ - transitionDuration = 1000, - - /** - * Easing function for transitions - * @param {d3.ease} [easeFunc=d3.easeExp] - * @memberof bubbleHeatmap# - * @property - */ - easeFunc = d3.easeExp, - - - /** - * Stores the keys of all the cells - * Calculated after bubbleHeatmap called. - * @param {string[]} [cellKeys=undefined] - * @memberof bubbleHeatmap# - * @property - */ - cellKeys, - - /** - * Stores the list of unique xValues - * Calculated after bubbleHeatmap called. - * @param {string[]} [xValues=undefined] - * @memberof bubbleHeatmap# - * @property - */ - xValues, - - /** - * Stores the list of unique yValues - * Calculated after bubbleHeatmap called. - * @param {string[]} [yValues=undefined] - * @memberof bubbleHeatmap# - * @property - */ - yValues, - - /** - * Stores the list of unique rValues - * Calculated after bubbleHeatmap called. - * @param {string[]} [rValues=undefined] - * @memberof bubbleHeatmap# - * @property - */ - rValues, - - /** - * Stores the list of unique vValues - * Calculated after bubbleHeatmap called. - * @param {string[]} [vValues=undefined] - * @memberof bubbleHeatmap# - * @property - */ - vValues, - xKeySortingFunction = function xKeySortingFunction(a, b) { - return xExtractor(a) - xExtractor(b); - }, - yKeySortingFunction = function yKeySortingFunction(a, b) { - return yExtractor(a) - yExtractor(b); - }, - /** - * Instance of ColorFunction with .colorBy set to 'category' - * @function colorFunction - * @memberof bubbleHeatmap# - * @property - */ - colorFunction$$1 = colorFunction().colorBy('value'), - - /** - * Instance of Tooltip - * @function tooltip - * @memberof bubbleHeatmap# - * @property - */ - tooltip$$1 = tooltip(), - - - /** - * store the size the bubble could be in the x dimension - * the actuall size of the bubble will be the min of xSize and {@link bubbleHeatmap#ySize} - * Calculated after bubbleHeatmap called. - * @param {string[]} [xSize=undefined] - * @memberof bubbleHeatmap# - * @property - */ - xSize, - - /** - * store the size of the spacer in the x dimension - * Calculated after bubbleHeatmap called. - * @param {string[]} [xSpacerSize=undefined] - * @memberof bubbleHeatmap# - * @property - */ - xSpacerSize, - - - /** - * store the size the bubble could be in the y dimension - * the actuall size of the bubble will be the min of xSize and {@link bubbleHeatmap#xSize} - * Calculated after bubbleHeatmap called. - * @param {string[]} [ySize=undefined] - * @memberof bubbleHeatmap# - * @property - */ - ySize, - - /** - * store the size of the spacer in the y dimension. - * Calculated after bubbleHeatmap called. - * @param {string[]} [xSpacerSize=undefined] - * @memberof bubbleHeatmap# - * @property - */ - ySpacerSize; - - /** - * Gets or sets the selection in which items are manipulated - * @param {d3.selection} [_=none] - * @returns {bubbleHeatmap | d3.selection} - * @memberof bubbleHeatmap - * @property - * by default selection = selection - */ - bhm.selection = function (_) { - return arguments.length ? (selection = _, bhm) : selection; - }; - /** - * Gets or sets the data - * (see {@link bubbleHeatmap#data}) - * @param {number} [_=none] - * @returns {bubbleHeatmap | object} - * @memberof bubbleHeatmap - * @property - */ - bhm.data = function (_) { - return arguments.length ? (data = _, bhm) : data; - }; - // bhm.orient = function(_) { return arguments.length ? (orient = _, bhm) : orient; } - /** - * Gets or sets the amount of horizontal space in which items are manipulated - * (see {@link bubbleHeatmap#spaceX}) - * @param {number} [_=none] should be a number > 0 - * @returns {bubbleHeatmap | number} - * @memberof bubbleHeatmap - * @property - * by default spaceX = undefined - */ - bhm.spaceX = function (_) { - return arguments.length ? (spaceX = _, bhm) : spaceX; - }; - /** - * Gets or sets the amount of vertical space in which items are manipulated - * (see {@link bubbleHeatmap#spaceY}) - * @param {number} [_=none] should be a number > 0 - * @returns {bubbleHeatmap | number} - * @memberof bubbleHeatmap - * @property - * by default spaceY = undefined - */ - bhm.spaceY = function (_) { - return arguments.length ? (spaceY = _, bhm) : spaceY; - }; - - /** - * Gets or sets the xKey - * (see {@link bubbleHeatmap#xKey}) - * @param {string} [_=none] - * @returns {bubbleHeatmap | string} - * @memberof bubbleHeatmap - * @property - * by default xKey = 'x' - */ - bhm.xKey = function (_) { - return arguments.length ? (xKey = _, bhm) : xKey; - }; - /** - * Gets or sets the yKey - * (see {@link bubbleHeatmap#yKey}) - * @param {string} [_=none] - * @returns {bubbleHeatmap | string} - * @memberof bubbleHeatmap - * @property - * by default yKey = 'y' - */ - bhm.yKey = function (_) { - return arguments.length ? (yKey = _, bhm) : yKey; - }; - /** - * Gets or sets the rKey - * (see {@link bubbleHeatmap#rKey}) - * @param {string} [_=none] - * @returns {bubbleHeatmap | string} - * @memberof bubbleHeatmap - * @property - * by default rKey = 'r' - */ - bhm.rKey = function (_) { - return arguments.length ? (rKey = _, bhm) : rKey; - }; - /** - * Gets or sets the vKey - * (see {@link bubbleHeatmap#vKey}) - * @param {string} [_=none] - * @returns {bubbleHeatmap | string} - * @memberof bubbleHeatmap - * @property - * by default vKey = 'y' - */ - bhm.vKey = function (_) { - return arguments.length ? (vKey = _, bhm) : vKey; - }; - - /** - * Gets or sets the cellKeys - * (see {@link bubbleHeatmap#cellKeys}) - * @param {string[]} [_=none] - * @returns {bubbleHeatmap | string[]} - * @memberof bubbleHeatmap - * @property - * by default cellKeys = undefined - */ - bhm.cellKeys = function (_) { - return arguments.length ? (cellKeys = _, bhm) : cellKeys; - }; - /** - * Gets or sets the xValues - * (see {@link bubbleHeatmap#xValues}) - * @param {string[]} [_=none] - * @returns {bubbleHeatmap | string[]} - * @memberof bubbleHeatmap - * @property - * by default xValues = undefined - */ - bhm.xValues = function (_) { - return arguments.length ? (xValues = _, bhm) : xValues; - }; - /** - * Gets or sets the yValues - * (see {@link bubbleHeatmap#yValues}) - * @param {string[]} [_=none] - * @returns {bubbleHeatmap | string[]} - * @memberof bubbleHeatmap - * @property - * by default yValues = undefined - */ - bhm.yValues = function (_) { - return arguments.length ? (yValues = _, bhm) : yValues; - }; - /** - * Gets or sets the rValues - * (see {@link bubbleHeatmap#rValues}) - * @param {number[]} [_=none] - * @returns {bubbleHeatmap | number[]} - * @memberof bubbleHeatmap - * @property - * by default rValues = undefined - */ - bhm.rValues = function (_) { - return arguments.length ? (rValues = _, bhm) : rValues; - }; - /** - * Gets or sets the vValues - * (see {@link bubbleHeatmap#vValues}) - * @param {number[]} [_=none] - * @returns {bubbleHeatmap | number[]} - * @memberof bubbleHeatmap - * @property - * by default vValues = undefined - */ - bhm.vValues = function (_) { - return arguments.length ? (vValues = _, bhm) : vValues; - }; - - /** - * Gets or sets the xExtractor - * (see {@link bubbleHeatmap#xExtractor}) - * @param {function} [_=none] - * @returns {bubbleHeatmap | function} - * @memberof bubbleHeatmap - * @property - * by default xExtractor = undefined - */ - bhm.xExtractor = function (_) { - return arguments.length ? (xExtractor = _, bhm) : xExtractor; - }; - /** - * Gets or sets the yExtractor - * (see {@link bubbleHeatmap#yExtractor}) - * @param {function} [_=none] - * @returns {bubbleHeatmap | function} - * @memberof bubbleHeatmap - * @property - * by default yExtractor = undefined - */ - bhm.yExtractor = function (_) { - return arguments.length ? (yExtractor = _, bhm) : yExtractor; - }; - /** - * Gets or sets the rExtractor - * (see {@link bubbleHeatmap#rExtractor}) - * @param {function} [_=none] - * @returns {bubbleHeatmap | function} - * @memberof bubbleHeatmap - * @property - * by default rExtractor = undefined - */ - bhm.rExtractor = function (_) { - return arguments.length ? (rExtractor = _, bhm) : rExtractor; - }; - /** - * Gets or sets the vExtractor - * (see {@link bubbleHeatmap#vExtractor}) - * @param {function} [_=none] - * @returns {bubbleHeatmap | function} - * @memberof bubbleHeatmap - * @property - * by default vExtractor = undefined - */ - bhm.vExtractor = function (_) { - return arguments.length ? (vExtractor = _, bhm) : vExtractor; - }; - - /** - * Gets / sets whether or not bubbleHeatmap is allowed to go beyond specified dimensions - * (see {@link bubbleHeatmap#spaceX}) - * @param {boolean} [_=none] - * @returns {bubbleHeatmap | boolean} - * @memberof bubbleHeatmap - * @property - * by default overflowQ = false - */ - bhm.overflowQ = function (_) { - return arguments.length ? (overflowQ = _, bhm) : overflowQ; - }; - /** - * Gets / sets the scale for which the radius of bubbles should be transformed by - * (see {@link bubbleHeatmap#scale}) - * @param {d3.scale} [_=none] - * @returns {bubbleHeatmap | d3.scale} - * @memberof bubbleHeatmap - * @property - * by default scale = d3.scaleLinear() - */ - bhm.scale = function (_) { - return arguments.length ? (scale = _, bhm) : scale; - }; - /** - * Gets / sets the padding for the domain of the scale - * (see {@link bubbleHeatmap#domainPadding}) - * @param {number} [_=none] - * @returns {bubbleHeatmap | number} - * @memberof bubbleHeatmap - * @property - * by default domainPadding = 0.5 - */ - bhm.domainPadding = function (_) { - return arguments.length ? (domainPadding = _, bhm) : domainPadding; - }; - /** - * Gets / sets objectSpacer - * (see {@link bubbleHeatmap#objectSpacer}) - * @param {number} [_=none] - * @returns {bubbleHeatmap | number} - * @memberof bubbleHeatmap - * @property - * by default objectSpacer = 0.0 - */ - bhm.objectSpacer = function (_) { - return arguments.length ? (objectSpacer = _, objectSpacer) : data; - }; - /** - * Gets / sets the minObjectSize - * (see {@link bubbleHeatmap#minObjectSize}) - * @param {number} [_=none] - * @returns {bubbleHeatmap | number} - * @memberof bubbleHeatmap - * @property - * by default minObjectSize = 50 - */ - bhm.minObjectSize = function (_) { - return arguments.length ? (minObjectSize = _, bhm) : minObjectSize; - }; - /** - * Gets / sets the maxObjectSize - * (see {@link bubbleHeatmap#maxObjectSize}) - * @param {number} [_=none] - * @returns {bubbleHeatmap | number} - * @memberof bubbleHeatmap - * @property - * by default maxObjectSize = 100 - */ - bhm.maxObjectSize = function (_) { - return arguments.length ? (maxObjectSize = _, bhm) : maxObjectSize; - }; - /** - * Gets / sets the bubbleStrokeWidth - * (see {@link bubbleHeatmap#bubbleStrokeWidth}) - * @param {number} [_=none] - * @returns {bubbleHeatmap | number} - * @memberof bubbleHeatmap - * @property - * by default bubbleStrokeWidth = 2 - */ - bhm.bubbleStrokeWidth = function (_) { - return arguments.length ? (bubbleStrokeWidth = _, bhm) : bubbleStrokeWidth; - }; - /** - * Gets / sets the backgroundFill - * (see {@link bubbleHeatmap#backgroundFill}) - * @param {string} [_=none] - * @returns {bubbleHeatmap | string} - * @memberof bubbleHeatmap - * @property - * by default backgroundFill = 'transparent' - */ - bhm.backgroundFill = function (_) { - return arguments.length ? (backgroundFill = _, bhm) : backgroundFill; - }; - /** - * Gets / sets the namespace - * (see {@link bubbleHeatmap#namespace}) - * @param {string} [_=none] - * @returns {bubbleHeatmap | string} - * @memberof bubbleHeatmap - * @property - * by default namespace = 'd3sm-bubbleHeatmap' - */ - bhm.namespace = function (_) { - return arguments.length ? (namespace = _, bhm) : namespace; - }; - /** - * Gets / sets the objectClass - * (see {@link bubbleHeatmap#objectClass}) - * @param {string} [_=none] - * @returns {bubbleHeatmap | string} - * @memberof bubbleHeatmap - * @property - * by default objectClass = 'tick-group' - */ - bhm.objectClass = function (_) { - return arguments.length ? (objectClass = _, bhm) : objectClass; - }; - /** - * Gets / sets the transitionDuration - * (see {@link bubbleHeatmap#transitionDuration}) - * @param {number} [_=none] - * @returns {bubbleHeatmap | number} - * @memberof bubbleHeatmap - * @property - * by default transitionDuration = 1000 - */ - bhm.transitionDuration = function (_) { - return arguments.length ? (transitionDuration = _, bhm) : transitionDuration; - }; - /** - * Gets / sets the easeFunc - * (see {@link bubbleHeatmap#easeFunc}) - * @param {d3.ease} [_=none] - * @returns {bubbleHeatmap | d3.ease} - * @memberof bubbleHeatmap - * @property - * by default easeFunc = d3.easeExp - */ - bhm.easeFunc = function (_) { - return arguments.length ? (easeFunc = _, bhm) : easeFunc; - }; - - /** - * Gets / sets the tooltip - * (see {@link bubbleHeatmap#tooltip}) - * @param {tooltip} [_=none] - * @returns {bubbleHeatmap | tooltip} - * @memberof bubbleHeatmap - * @property - * by default tooltip = tooltip() - */ - bhm.tooltip = function (_) { - return arguments.length ? (tooltip$$1 = _, bhm) : tooltip$$1; - }; - - /** - * Gets / sets the colorFunction - * (see {@link bubbleHeatmap#colorFunction}) - * @param {colorFunction} [_=none] - * @returns {bubbleHeatmap | colorFunction} - * @memberof bubbleHeatmap - * @property - * by default colorFunction = colorFunction() - */ - bhm.colorFunction = function (_) { - return arguments.length ? (colorFunction$$1 = _, bhm) : colorFunction$$1; - }; - - /** - * Gets / sets the xSize - * (see {@link bubbleHeatmap#xSize}) - * @param {number} [_=none] - * @returns {bubbleHeatmap | number} - * @memberof bubbleHeatmap - * @property - * by default xSize = undefined - */ - bhm.xSize = function (_) { - return arguments.length ? (xSize = _, bhm) : xSize; - }; - /** - * Gets / sets the xSpacerSize - * (see {@link bubbleHeatmap#xSpacerSize}) - * @param {number} [_=none] - * @returns {bubbleHeatmap | number} - * @memberof bubbleHeatmap - * @property - * by default xSpacerSize = undefined - */ - bhm.xSpacerSize = function (_) { - return arguments.length ? (xSpacerSize = _, bhm) : xSpacerSize; - }; - /** - * Gets / sets the ySize - * (see {@link bubbleHeatmap#ySize}) - * @param {number} [_=none] - * @returns {bubbleHeatmap | number} - * @memberof bubbleHeatmap - * @property - * by default ySize = undefined - */ - bhm.ySize = function (_) { - return arguments.length ? (ySize = _, bhm) : ySize; - }; - /** - * Gets / sets the ySpacerSize - * (see {@link bubbleHeatmap#ySpacerSize}) - * @param {number} [_=none] - * @returns {bubbleHeatmap | number} - * @memberof bubbleHeatmap - * @property - * by default ySpacerSize = undefined - */ - bhm.ySpacerSize = function (_) { - return arguments.length ? (ySpacerSize = _, bhm) : ySpacerSize; - }; - // bhm.yKeySortingFunction = function(_) { return arguments.length ? (yKeySortingFunction = _, bhm) : yKeySortingFunction; } - // bhm.xKeySortingFunction = function(_) { return arguments.length ? (xKeySortingFunction = _, bhm) : xKeySortingFunction; } - - - function bhm() { - var bgcpRect = { x: 0, y: 0, width: spaceX, height: spaceY }; - var container = setupContainer(selection, namespace, bgcpRect, backgroundFill); - - cellKeys = d3.keys(data); - cellKeys.sort(function (a, b) { - return xKeySortingFunction(a, b) || yKeySortingFunction(a, b); - }); - log('bubbleHeatmap', 'cells are sorted by', cellKeys); - - xValues = unique(cellKeys.map(xExtractor)); - yValues = unique(cellKeys.map(yExtractor)); - rValues = unique(cellKeys.map(rExtractor)); - vValues = unique(cellKeys.map(vExtractor)); - log('bubbleHeatmap', 'x and y keys are', { x: xValues, y: yValues }); - - var xDim = xValues.length, - yDim = yValues.length; - - var extent = [Math.min.apply(Math, toConsumableArray(rValues)) - domainPadding, Math.max.apply(Math, toConsumableArray(rValues)) + domainPadding]; - - ySize = calculateWidthOfObject(spaceY, yDim, minObjectSize, maxObjectSize, objectSpacer, overflowQ); - xSize = calculateWidthOfObject(spaceX, xDim, minObjectSize, maxObjectSize, objectSpacer, overflowQ); - ySpacerSize = calculateWidthOfSpacer(yValues, spaceY, ySize, yDim, objectSpacer, overflowQ); - xSpacerSize = calculateWidthOfSpacer(xValues, spaceX, xSize, xDim, objectSpacer, overflowQ); - log('bubbleHeatmap', 'size of', { x: xSize, y: ySize }); - - scale.domain(extent).range([Math.min(minObjectSize / 2, Math.min(ySize, xSize) / 2), Math.min(ySize, xSize) / 2]); - - var ySpacer = groupingSpacer().horizontalQ(false).moveby('category').numberOfObjects(yDim).objectClass(hypenate(objectClass, 'row')).objectSize(ySize).spacerSize(ySpacerSize).transitionDuration(transitionDuration).easeFunc(easeFunc).namespace('row'); - - var xSpacer = groupingSpacer().horizontalQ(true).moveby('category').numberOfObjects(xDim).objectClass(objectClass).objectSize(xSize).spacerSize(xSpacerSize).transitionDuration(transitionDuration).easeFunc(easeFunc); - - ySpacer(container, yValues, 0); - container.selectAll('g.' + hypenate(objectClass, 'row')).each(function (d, i) { - xSpacer(d3.select(this), xValues, 0); - }); - var cells = container.selectAll('g:not(.to-remove).' + objectClass).data(cellKeys); - - var parentIndexArray = []; - cells.each(function (d, i) { - parentIndexArray.push(Number(d3.select(this).attr('parent-index'))); - }); - - colorFunction$$1 = colorFunction$$1.colorBy() == 'index' ? colorFunction$$1.dataExtent([0, Math.max.apply(Math, parentIndexArray)]) : colorFunction$$1.dataExtent([0, Math.max.apply(Math, toConsumableArray(vValues))]); - - cells.each(function (key, i) { - log('bubbleHeatmap', 'each cell', { key: key, index: i, node: d3.select(this).node() }); - - var t = d3.select(this), - currentData = data[key], - value = vExtractor(key, i), - radius = rExtractor(key, i), - i = t.attr('parent-index') == undefined ? i : t.attr('parent-index'), - fillColor = colorFunction$$1(key, value, i, 'fill'), - // prevent duplicate computation - strokeColor = colorFunction$$1(key, value, i, 'stroke'); - - log('bubbleHeatmap', 'radius', { radius: radius, scaled: scale(radius), extent: extent, range: scale.range() }); - - var c = safeSelect(t, 'circle', hypenate(objectClass, 'circle')); - c.attr('cx', xSize / 2).attr('cy', ySize / 2).attr('r', scale(radius)).attr('fill', fillColor).attr('stroke', strokeColor).attr('stroke-width', bubbleStrokeWidth); - }); - - tooltip$$1.selection(cells.selectAll('circle.' + hypenate(objectClass, 'circle'))).data(data); - // .keys(['r', 'v']) - // .header(function(d, i){return hypenate(data[d][xKey], data[d][yKey]) }) - - tooltip$$1(); - } - - return bhm; - } - - /** - * Creates a heatmap - * - * {@link https://sumneuron.gitlab.io/d3sm/demos/heatmap-heatmap/index.html Demo} - * @constructor heatmap - * @param {d3.selection} selection - * @namespace heatmap - * @returns {function} heatmap - */ - function heatmap(selection) { - var - /** - * Data to plot. Assumed to be a object, where each key corresponds to a cell - * (see {@link heatmap#data}) - * @param {Object} [data=undefined] - * @memberof heatmap# - * @property - */ - data, - - - /** - * Amount of horizontal space (in pixels) avaible to render the heatmap in - * (see {@link heatmap#spaceX}) - * @param {number} [spaceX=undefined] - * @memberof heatmap# - * @property - */ - spaceX, - - /** - * Amount of vertical space (in pixels) avaible to render the heatmap in - * (see {@link heatmap.spaceY}) - * @param {number} [spaceY=undefined] - * @memberof heatmap# - * @property - */ - spaceY, - - - /** - * The internal key of the cell specifiying to which x axis key it belongs - * (see {@link heatmap.xKey}) - * @param {string} [xKey='x'] - * @memberof heatmap# - * @property - */ - xKey = 'x', - - /** - * The internal key of the cell specifiying to which y axis key it belongs - * (see {@link heatmap.yKey}) - * @param {string} [yKey='y'] - * @memberof heatmap# - * @property - */ - yKey = 'y', - - - /** - * The internal key of the cell specifiying what value to use to determine the color - * (see {@link heatmap.vKey}) - * @param {string} [vKey='v'] - * @memberof heatmap# - * @property - */ - vKey = 'v', - - - /** - * Function for extracting the the value from xKey. - * (see {@link heatmap.xExtractor}) - * @param {function} [xExtractor=function(key, i) { return data[key][xKey] }] - * @returns {string} - * @memberof heatmap# - * @property - */ - xExtractor = function xExtractor(key, i) { - return data[key][xKey]; - }, - - /** - * Function for extracting the the value from yKey. - * (see {@link heatmap.yExtractor}) - * @param {function} [yExtractor=function(key, i) { return data[key][yKey] }] - * @returns {string} - * @memberof heatmap# - * @property - */ - yExtractor = function yExtractor(key, i) { - return data[key][yKey]; - }, - - - /** - * Function for extracting the the value from vKey. - * (see {@link heatmap.vExtractor}) - * @param {function} [vExtractor=function(key, i) { return data[key][vKey] }] - * @returns {number} - * @memberof heatmap# - * @property - */ - vExtractor = function vExtractor(key, i) { - return data[key][vKey]; - }, - - - /** - * Whether or not to allow heatmap to render elements pass the main spatial dimension - * given the orientation (see {@link heatmap#orient}), where {@link heatmap#orient}="bottom" or {@link heatmap#orient}="top" - * the main dimension is {@link heatmap#spaceX} and where {@link heatmap#orient}="left" or {@link heatmap#orient}="right" - * the main dimension is {@link heatmap#spaceY} - * @param {boolean} [overflowQ=false] - * @memberof heatmap# - * @property - */ - overflowQ = false, - - - /** - * Default space for the spacer (percentage) of main dimension given the orientation - * (see {@link heatmap#orient}), where {@link heatmap#orient}="horizontal" - * the main dimension is {@link heatmap#spaceX} and where {@link heatmap#orient}="vertical" - * the main dimension is {@link heatmap#spaceY} between bubbles - * @param {number} [objectSpacer=0.0] - * @memberof heatmap# - * @property - */ - objectSpacer = 0.0, - - /** - * The minimum size that an object can be in the y dimension - * @param {number} [minObjectSize=50] - * @memberof heatmap# - * @property - */ - yMinObjectSize = 50, - - /** - * The minimum size that an object can be in the x dimension - * @param {number} [minObjectSize=50] - * @memberof heatmap# - * @property - */ - xMinObjectSize = 50, - - /** - * The maximum size that an object can be in the x dimension - * @param {number} [maxObjectSize=100] - * @memberof heatmap# - * @property - */ - xMaxObjectSize = 100, - - /** - * The maximum size that an object can be in the y dimension - * @param {number} [maxObjectSize=100] - * @memberof heatmap# - * @property - */ - yMaxObjectSize = 100, - - - /** - * The stroke width of the bubbles - * @param {number} [objectStrokeWidth=2] - * @memberof heatmap# - * @property - */ - objectStrokeWidth = 2, - - // colorFunc = colorFunction(), - - /** - * Color of the background - * @param {string} [backgroundFill="transparent"] - * @memberof heatmap# - * @property - */ - backgroundFill = 'transparent', - - /** - * Namespace for all items made by this instance of heatmap - * @param {string} [namespace="d3sm-heatmap"] - * @memberof heatmap# - * @property - */ - namespace = 'd3sm-heatmap', - - /** - * Class name for heatmap container ( element) - * @param {string} [objectClass="heatmap"] - * @memberof heatmap# - * @property - */ - objectClass = 'heatmap', - - /** - * Duration of all transitions of this element - * @param {number} [transitionDuration=1000] - * @memberof heatmap# - * @property - */ - transitionDuration = 1000, - - /** - * Easing function for transitions - * @param {d3.ease} [easeFunc=d3.easeExp] - * @memberof heatmap# - * @property - */ - easeFunc = d3.easeExp, - - - /** - * Stores the keys of all the cells - * Calculated after heatmap called. - * @param {string[]} [cellKeys=undefined] - * @memberof heatmap# - * @property - */ - cellKeys, - - /** - * Stores the list of unique xValues - * Calculated after heatmap called. - * @param {string[]} [xValues=undefined] - * @memberof heatmap# - * @property - */ - xValues, - - /** - * Stores the list of unique yValues - * Calculated after heatmap called. - * @param {string[]} [yValues=undefined] - * @memberof heatmap# - * @property - */ - yValues, - - /** - * Stores the list of unique vValues - * Calculated after heatmap called. - * @param {string[]} [vValues=undefined] - * @memberof heatmap# - * @property - */ - vValues, - xKeySortingFunction = function xKeySortingFunction(a, b) { - return xValues.indexOf(xExtractor(a)) - xValues.indexOf(xExtractor(b)); - }, - yKeySortingFunction = function yKeySortingFunction(a, b) { - return yValues.indexOf(yExtractor(a)) - yValues.indexOf(yExtractor(b)); - }, - /** - * Instance of ColorFunction with .colorBy set to 'category' - * @function colorFunction - * @memberof heatmap# - * @property - */ - colorFunction$$1 = colorFunction().colorBy('category'), - - /** - * Instance of Tooltip - * @function tooltip - * @memberof heatmap# - * @property - */ - tooltip$$1 = tooltip(), - - - /** - * store the size the heatmap could be in the x dimension - * the actuall size of the heatmap will be the min of xSize and {@link heatmap#ySize} - * Calculated after heatmap called. - * @param {string[]} [xSize=undefined] - * @memberof heatmap# - * @property - */ - xSize, - - /** - * store the size of the spacer in the x dimension - * Calculated after heatmap called. - * @param {string[]} [xSpacerSize=undefined] - * @memberof heatmap# - * @property - */ - xSpacerSize, - - - /** - * store the size the heatmap could be in the y dimension - * the actuall size of the heatmap will be the min of xSize and {@link heatmap#xSize} - * Calculated after heatmap called. - * @param {string[]} [ySize=undefined] - * @memberof heatmap# - * @property - */ - ySize, - - /** - * store the size of the spacer in the y dimension. - * Calculated after heatmap called. - * @param {string[]} [xSpacerSize=undefined] - * @memberof heatmap# - * @property - */ - ySpacerSize; - - /** - * Gets or sets the selection in which items are manipulated - * @param {d3.selection} [_=none] - * @returns {heatmap | d3.selection} - * @memberof heatmap - * @property - * by default selection = selection - */ - hm.selection = function (_) { - return arguments.length ? (selection = _, hm) : selection; - }; - /** - * Gets or sets the data - * (see {@link heatmap#data}) - * @param {number} [_=none] - * @returns {heatmap | object} - * @memberof heatmap - * @property - */ - hm.data = function (_) { - return arguments.length ? (data = _, hm) : data; - }; - // hm.orient = function(_) { return arguments.length ? (orient = _, hm) : orient; } - /** - * Gets or sets the amount of horizontal space in which items are manipulated - * (see {@link heatmap#spaceX}) - * @param {number} [_=none] should be a number > 0 - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default spaceX = undefined - */ - hm.spaceX = function (_) { - return arguments.length ? (spaceX = _, hm) : spaceX; - }; - /** - * Gets or sets the amount of vertical space in which items are manipulated - * (see {@link heatmap#spaceY}) - * @param {number} [_=none] should be a number > 0 - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default spaceY = undefined - */ - hm.spaceY = function (_) { - return arguments.length ? (spaceY = _, hm) : spaceY; - }; - - /** - * Gets or sets the xKey - * (see {@link heatmap#xKey}) - * @param {string} [_=none] - * @returns {heatmap | string} - * @memberof heatmap - * @property - * by default xKey = 'x' - */ - hm.xKey = function (_) { - return arguments.length ? (xKey = _, hm) : xKey; - }; - /** - * Gets or sets the yKey - * (see {@link heatmap#yKey}) - * @param {string} [_=none] - * @returns {heatmap | string} - * @memberof heatmap - * @property - * by default yKey = 'y' - */ - hm.yKey = function (_) { - return arguments.length ? (yKey = _, hm) : yKey; - }; - - /** - * Gets or sets the vKey - * (see {@link heatmap#vKey}) - * @param {string} [_=none] - * @returns {heatmap | string} - * @memberof heatmap - * @property - * by default vKey = 'y' - */ - hm.vKey = function (_) { - return arguments.length ? (vKey = _, hm) : vKey; - }; - - /** - * Gets or sets the cellKeys - * (see {@link heatmap#cellKeys}) - * @param {string[]} [_=none] - * @returns {heatmap | string[]} - * @memberof heatmap - * @property - * by default cellKeys = undefined - */ - hm.cellKeys = function (_) { - return arguments.length ? (cellKeys = _, hm) : cellKeys; - }; - /** - * Gets or sets the xValues - * (see {@link heatmap#xValues}) - * @param {string[]} [_=none] - * @returns {heatmap | string[]} - * @memberof heatmap - * @property - * by default xValues = undefined - */ - hm.xValues = function (_) { - return arguments.length ? (xValues = _, hm) : xValues; - }; - /** - * Gets or sets the yValues - * (see {@link heatmap#yValues}) - * @param {string[]} [_=none] - * @returns {heatmap | string[]} - * @memberof heatmap - * @property - * by default yValues = undefined - */ - hm.yValues = function (_) { - return arguments.length ? (yValues = _, hm) : yValues; - }; - /** - * Gets or sets the vValues - * (see {@link heatmap#vValues}) - * @param {number[]} [_=none] - * @returns {heatmap | number[]} - * @memberof heatmap - * @property - * by default vValues = undefined - */ - hm.vValues = function (_) { - return arguments.length ? (vValues = _, hm) : vValues; - }; - - /** - * Gets or sets the xExtractor - * (see {@link heatmap#xExtractor}) - * @param {function} [_=none] - * @returns {heatmap | function} - * @memberof heatmap - * @property - * by default xExtractor = undefined - */ - hm.xExtractor = function (_) { - return arguments.length ? (xExtractor = _, hm) : xExtractor; - }; - /** - * Gets or sets the yExtractor - * (see {@link heatmap#yExtractor}) - * @param {function} [_=none] - * @returns {heatmap | function} - * @memberof heatmap - * @property - * by default yExtractor = undefined - */ - hm.yExtractor = function (_) { - return arguments.length ? (yExtractor = _, hm) : yExtractor; - }; - /** - * Gets or sets the vExtractor - * (see {@link heatmap#vExtractor}) - * @param {function} [_=none] - * @returns {heatmap | function} - * @memberof heatmap - * @property - * by default vExtractor = undefined - */ - hm.vExtractor = function (_) { - return arguments.length ? (vExtractor = _, hm) : vExtractor; - }; - - /** - * Gets / sets whether or not heatmap is allowed to go beyond specified dimensions - * (see {@link heatmap#spaceX}) - * @param {boolean} [_=none] - * @returns {heatmap | boolean} - * @memberof heatmap - * @property - * by default overflowQ = false - */ - hm.overflowQ = function (_) { - return arguments.length ? (overflowQ = _, hm) : overflowQ; - }; - /** - * Gets / sets objectSpacer - * (see {@link heatmap#objectSpacer}) - * @param {number} [_=none] - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default objectSpacer = 0.0 - */ - hm.objectSpacer = function (_) { - return arguments.length ? (objectSpacer = _, objectSpacer) : data; - }; - /** - * Gets / sets the minObjectSize - * (see {@link heatmap#minObjectSize}) - * @param {number} [_=none] - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default minObjectSize = 50 - */ - hm.yMinObjectSize = function (_) { - return arguments.length ? (yMinObjectSize = _, hm) : yMinObjectSize; - }; - /** - * Gets / sets the maxObjectSize - * (see {@link heatmap#maxObjectSize}) - * @param {number} [_=none] - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default maxObjectSize = 100 - */ - hm.yMaxObjectSize = function (_) { - return arguments.length ? (yMaxObjectSize = _, hm) : yMaxObjectSize; - }; - /** - * Gets / sets the minObjectSize - * (see {@link heatmap#minObjectSize}) - * @param {number} [_=none] - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default minObjectSize = 50 - */ - hm.xMinObjectSize = function (_) { - return arguments.length ? (xMinObjectSize = _, hm) : xMinObjectSize; - }; - /** - * Gets / sets the maxObjectSize - * (see {@link heatmap#maxObjectSize}) - * @param {number} [_=none] - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default maxObjectSize = 100 - */ - hm.xMaxObjectSize = function (_) { - return arguments.length ? (xMaxObjectSize = _, hm) : xMaxObjectSize; - }; - /** - * Gets / sets the objectStrokeWidth - * (see {@link heatmap#objectStrokeWidth}) - * @param {number} [_=none] - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default objectStrokeWidth = 2 - */ - hm.objectStrokeWidth = function (_) { - return arguments.length ? (objectStrokeWidth = _, hm) : objectStrokeWidth; - }; - /** - * Gets / sets the backgroundFill - * (see {@link heatmap#backgroundFill}) - * @param {string} [_=none] - * @returns {heatmap | string} - * @memberof heatmap - * @property - * by default backgroundFill = 'transparent' - */ - hm.backgroundFill = function (_) { - return arguments.length ? (backgroundFill = _, hm) : backgroundFill; - }; - /** - * Gets / sets the namespace - * (see {@link heatmap#namespace}) - * @param {string} [_=none] - * @returns {heatmap | string} - * @memberof heatmap - * @property - * by default namespace = 'd3sm-heatmap' - */ - hm.namespace = function (_) { - return arguments.length ? (namespace = _, hm) : namespace; - }; - /** - * Gets / sets the objectClass - * (see {@link heatmap#objectClass}) - * @param {string} [_=none] - * @returns {heatmap | string} - * @memberof heatmap - * @property - * by default objectClass = 'tick-group' - */ - hm.objectClass = function (_) { - return arguments.length ? (objectClass = _, hm) : objectClass; - }; - /** - * Gets / sets the transitionDuration - * (see {@link heatmap#transitionDuration}) - * @param {number} [_=none] - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default transitionDuration = 1000 - */ - hm.transitionDuration = function (_) { - return arguments.length ? (transitionDuration = _, hm) : transitionDuration; - }; - /** - * Gets / sets the easeFunc - * (see {@link heatmap#easeFunc}) - * @param {d3.ease} [_=none] - * @returns {heatmap | d3.ease} - * @memberof heatmap - * @property - * by default easeFunc = d3.easeExp - */ - hm.easeFunc = function (_) { - return arguments.length ? (easeFunc = _, hm) : easeFunc; - }; - - /** - * Gets / sets the tooltip - * (see {@link heatmap#tooltip}) - * @param {tooltip} [_=none] - * @returns {heatmap | tooltip} - * @memberof heatmap - * @property - * by default tooltip = tooltip() - */ - hm.tooltip = function (_) { - return arguments.length ? (tooltip$$1 = _, hm) : tooltip$$1; - }; - - /** - * Gets / sets the colorFunction - * (see {@link heatmap#colorFunction}) - * @param {colorFunction} [_=none] - * @returns {heatmap | colorFunction} - * @memberof heatmap - * @property - * by default colorFunction = colorFunction() - */ - hm.colorFunction = function (_) { - return arguments.length ? (colorFunction$$1 = _, hm) : colorFunction$$1; - }; - - /** - * Gets / sets the xSize - * (see {@link heatmap#xSize}) - * @param {number} [_=none] - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default xSize = undefined - */ - hm.xSize = function (_) { - return arguments.length ? (xSize = _, hm) : xSize; - }; - /** - * Gets / sets the xSpacerSize - * (see {@link heatmap#xSpacerSize}) - * @param {number} [_=none] - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default xSpacerSize = undefined - */ - hm.xSpacerSize = function (_) { - return arguments.length ? (xSpacerSize = _, hm) : xSpacerSize; - }; - /** - * Gets / sets the ySize - * (see {@link heatmap#ySize}) - * @param {number} [_=none] - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default ySize = undefined - */ - hm.ySize = function (_) { - return arguments.length ? (ySize = _, hm) : ySize; - }; - /** - * Gets / sets the ySpacerSize - * (see {@link heatmap#ySpacerSize}) - * @param {number} [_=none] - * @returns {heatmap | number} - * @memberof heatmap - * @property - * by default ySpacerSize = undefined - */ - hm.ySpacerSize = function (_) { - return arguments.length ? (ySpacerSize = _, hm) : ySpacerSize; - }; - // hm.yKeySortingFunction = function(_) { return arguments.length ? (yKeySortingFunction = _, hm) : yKeySortingFunction; } - // hm.xKeySortingFunction = function(_) { return arguments.length ? (xKeySortingFunction = _, hm) : xKeySortingFunction; } - - - function hm() { - var bgcpRect = { x: 0, y: 0, width: spaceX, height: spaceY }; - var container = setupContainer(selection, namespace, bgcpRect, backgroundFill); - - cellKeys = d3.keys(data); - - xValues = unique(cellKeys.map(xExtractor)); - yValues = unique(cellKeys.map(yExtractor)); - vValues = unique(cellKeys.map(vExtractor)); - - cellKeys.sort(function (a, b) { - return xKeySortingFunction(a, b) || yKeySortingFunction(a, b); - }); - log('heatmap', 'cells are sorted by', cellKeys); - - log('heatmap', 'x and y keys are', { x: xValues, y: yValues }); - - var xDim = xValues.length, - yDim = yValues.length; - - ySize = calculateWidthOfObject(spaceY, yDim, yMinObjectSize, yMaxObjectSize, objectSpacer, overflowQ); - xSize = calculateWidthOfObject(spaceX, xDim, xMinObjectSize, xMaxObjectSize, objectSpacer, overflowQ); - ySpacerSize = calculateWidthOfSpacer(yValues, spaceY, ySize, yDim, objectSpacer, overflowQ); - xSpacerSize = calculateWidthOfSpacer(xValues, spaceX, xSize, xDim, objectSpacer, overflowQ); - // console.table({ - // x:{ - // object: xSize, - // spacer: xSpacerSize, - // dim: xDim - // }, - // y:{ - // object: ySize, - // spacer: ySpacerSize, - // dim: yDim - // } - // - // }) - log('heatmap', 'size of', { x: xSize, y: ySize }); - - var ySpacer = groupingSpacer().horizontalQ(false).moveby('category').numberOfObjects(yDim).objectClass(hypenate(objectClass, 'row')).objectSize(ySize + ySpacerSize).spacerSize(0).transitionDuration(transitionDuration).easeFunc(easeFunc).namespace('row'); - - var xSpacer = groupingSpacer().horizontalQ(true).moveby('category').numberOfObjects(xDim).objectClass(objectClass).objectSize(xSize + xSpacerSize).spacerSize(0).transitionDuration(transitionDuration).easeFunc(easeFunc); - - ySpacer(container, yValues, 0); - container.selectAll('g.' + hypenate(objectClass, 'row')).each(function (d, i) { - xSpacer(d3.select(this), xValues, 0); - }); - - var cells = container.selectAll('g:not(.to-remove).' + objectClass); - - if (cellKeys.length != yValues.length * xValues.length) { - var lookup = {}; - cellKeys.map(function (k, i) { - lookup[xExtractor(k) + '::' + yExtractor(k)] = k; - }); - - var positionedCellKeys = []; - for (var i = 0; i < yValues.length; i++) { - for (var j = 0; j < xValues.length; j++) { - var lookupValue = lookup[xValues[j] + "::" + yValues[i]]; - if (lookupValue == undefined) { - positionedCellKeys.push(undefined); - } else { - positionedCellKeys.push(lookupValue); - } - } - } - - cells.data(positionedCellKeys); - - // maybe breaks this - // !!!!!! IMPORTANT NOTE TODO LOOK HERE BUG - cellKeys = positionedCellKeys; - } else { - cells.data(cellKeys); - } - - var parentIndexArray = []; - cells.each(function (d, i) { - parentIndexArray.push(Number(d3.select(this).attr('parent-index'))); - }); - - colorFunction$$1 = colorFunction$$1.colorBy() == 'index' ? colorFunction$$1.dataExtent([0, Math.max.apply(Math, parentIndexArray)]) : colorFunction$$1.dataExtent([0, Math.max.apply(Math, toConsumableArray(vValues))]); - - cells.each(function (key, i) { - log('heatmap', 'each cell', { key: key, index: i, node: d3.select(this).node() }); - - var t = d3.select(this); - if (key == undefined) { - return; - } - var currentData = data[key], - value = vExtractor(key, i), - i = t.attr('parent-index') == undefined ? i : t.attr('parent-index'), - fillColor = colorFunction$$1(key, value, i, 'fill'), - // prevent duplicate computation - strokeColor = colorFunction$$1(key, value, i, 'stroke'); - - var c = safeSelect(t, 'rect', hypenate(objectClass, 'rect')); - c.attr('width', xSize + xSpacerSize - objectStrokeWidth).attr('height', ySize + ySpacerSize - objectStrokeWidth).attr('fill', fillColor).attr('x', objectStrokeWidth / 2).attr('y', objectStrokeWidth / 2).attr('stroke', "#000").attr('stroke-width', objectStrokeWidth); - }); - - tooltip$$1.selection(cells.selectAll('rect.' + hypenate(objectClass, 'rect'))).data(data); - // .keys(['r', 'v']) - // .header(function(d, i){return hypenate(data[d][xKey], data[d][yKey]) }) - - tooltip$$1(); - } - - return hm; - } - - /******************************************************************************* - ** ** - ** ** - ** BOX AND WHISKER ** - ** ** - ** ** - *******************************************************************************/ - /** - * Creates a boxwhisker - * - * {@link https://sumneuron.gitlab.io/d3sm/demos/box-whiskers/index.html Demo} - * @constructor boxwhisker - * @param {d3.selection} selection - * @namespace boxwhisker - * @returns {function} boxwhisker - */ - function boxwhisker(selection) { - var - /** - * Data to plot. Assumed to be a object, where each key corresponds to a box - * (see {@link boxwhisker#data}) - * @param {Object} [data=undefined] - * @memberof boxwhisker# - * @property - */ - data, - - /** - * Which direction to render the boxes in - * (see {@link boxwhisker#orient}) - * @param {number} [orient='horizontal'] - * @memberof boxwhisker# - * @property - */ - orient = 'horizontal', - - /** - * Amount of horizontal space (in pixels) avaible to render the boxwhisker in - * (see {@link boxwhisker#spaceX}) - * @param {number} [spaceX=undefined] - * @memberof boxwhisker# - * @property - */ - spaceX, - - /** - * Amount of vertical space (in pixels) avaible to render the boxwhisker in - * (see {@link boxwhisker.spaceY}) - * @param {number} [spaceY=undefined] - * @memberof boxwhisker# - * @property - */ - spaceY, - - /** - * Whether or not to allow boxwhisker to render elements pass the main spatial dimension - * given the orientation (see {@link boxwhisker#orient}), where {@link boxwhisker#orient}="horizontal" - * the main dimension is {@link boxwhisker#spaceX} and where {@link boxwhisker#orient}="vertical" - * the main dimension is {@link boxwhisker#spaceY} - * @param {boolean} [overflowQ=false] - * @memberof boxwhisker# - * @property - */ - overflowQ = true, - - - /** - * An array - putatively of other arrays - depicting how boxes should be arranged - * @param {Array[]} [grouping=undefined] - * @memberof boxwhisker# - * @property - */ - grouping, - quartilesKey = 'quartiles', - // key in object where quartiles are stored - quartilesKeys = ["0.00", "0.25", "0.50", "0.75", "1.00"], - // keys in quartiles object mapping values to min, q1, q2, q3 and max - - - /** - * How to get the value of the boxwhisker - * @param {function} [valueExtractor=function(key, index) { return data[key][quartilesKey] }] - * @memberof boxwhisker# - * @property - */ - valueExtractor = function valueExtractor(key, index) { - return data[key][quartilesKey]; - }, - - /** - * How to sort the boxes - if {@link boxwhisker#grouping} is not provided. - * @param {function} [sortingFunction=descending] - * @memberof boxwhisker# - * @property - * default - * function(keyA, keyB) {return d3.descending( - * valueExtractor(keyA)[quartilesKeys[4]], - * valueExtractor(keyB)[quartilesKeys[4]] - * )} - */ - sortingFunction = function sortingFunction(keyA, keyB) { - return d3.descending(valueExtractor(keyA)[quartilesKeys[4]], valueExtractor(keyB)[quartilesKeys[4]]); - }, - - /** - * The scale for which boxwhisker values should be transformed by - * @param {d3.scale} [scale=d3.scaleLinear] - * @memberof boxwhisker# - * @property - */ - scale = d3.scaleLinear(), - - /** - * The padding for the domain of the scale (see {@link boxwhisker#scale}) - * @param {number} [domainPadding=0.5] - * @memberof boxwhisker# - * @property - */ - domainPadding = 0.5, - - /** - * Default space for the spacer (percentage) of main dimension given the orientation - * (see {@link boxwhisker#orient}), where {@link boxwhisker#orient}="horizontal" - * the main dimension is {@link boxwhisker#spaceX} and where {@link boxwhisker#orient}="vertical" - * the main dimension is {@link boxwhisker#spaceY} between boxes - * @param {number} [objectSpacer=0.05] - * @memberof boxwhisker# - * @property - */ - objectSpacer = 0.05, - - /** - * The minimum size that an object can be - * @param {number} [minObjectSize=15] - * @memberof boxwhisker# - * @property - */ - minObjectSize = 15, - - /** - * The maximum size that an object can be - * @param {number} [maxObjectSize=50] - * @memberof boxwhisker# - * @property - */ - maxObjectSize = 50, - - /** - * Percent of box and whisker size that whiskers will be rendered - * see {@link boxwhisker#objectSize} - * @param {number} [whiskerWidthPercent=0.6] - * @memberof boxwhisker# - * @property - */ - whiskerWidthPercent = .6, - - /** - * Instance of ColorFunction - * @param {function} [colorFunction = colorFunction()] - * @memberof boxwhisker# - * @property - */ - colorFunction$$1 = colorFunction(), - - /** - * The stroke width of the boxes - * @param {number} [boxStrokeWidth=2] - * @memberof boxwhisker# - * @property - */ - boxStrokeWidth = 2, - - /** - * The stroke width of the whiskers - * @param {number} [whiskerStrokeWidth=2] - * @memberof boxwhisker# - * @property - */ - whiskerStrokeWidth = 2, - - - /** - * Color of the background - * @param {string} [backgroundFill="transparent"] - * @memberof boxwhisker# - * @property - */ - backgroundFill = 'transparent', - - /** - * Namespace for all items made by this instance of boxwhisker - * @param {string} [namespace="d3sm-box-whisker"] - * @memberof boxwhisker# - * @property - */ - namespace = 'd3sm-box-whisker', - - /** - * Class name for boxwhisker container ( element) - * @param {string} [objectClass="box-whisk"] - * @memberof boxwhisker# - * @property - */ - objectClass = 'box-whisk', - - - /** - * Duration of all transitions of this element - * @param {number} [transitionDuration=1000] - * @memberof boxwhisker# - * @property - */ - transitionDuration = 1000, - - /** - * Easing function for transitions - * @param {d3.ease} [easeFunc=d3.easeExp] - * @memberof boxwhisker# - * @property - */ - easeFunc = d3.easeExp, - - - /** - * The keys of the boxes - * @param {string[]} [boxKeys=undefined] - * @memberof boxwhisker# - * @property - */ - boxKeys, - - /** - * The values of the boxes - * @param {string[]} [boxValues=undefined] - * @memberof boxwhisker# - * @property - */ - boxValues, - - /** - * The objectSize (actual width) used by the boxes - * @param {number} [objectSize=undefined] - * @memberof boxwhisker# - * @property - */ - objectSize, - - /** - * The spacerSize (actual width) used by the spacers between the boxes - * @param {number} [spacerSize=undefined] - * @memberof boxwhisker# - * @property - */ - spacerSize, - - /** - * Instance of Tooltip - * @param {function} [tooltip=tooltip()] - * @memberof boxwhisker# - * @property - */ - tooltip$$1 = tooltip(); - /** - * Gets or sets the selection in which items are manipulated - * @param {d3.selection} [_=none] - * @returns {boxwhisker | d3.selection} - * @memberof boxwhisker - * @property - * by default selection = selection - */ - boxwhisker.selection = function (_) { - return arguments.length ? (selection = _, boxwhisker) : selection; - }; - /** - * Gets or sets the data - * (see {@link boxwhisker#data}) - * @param {number} [_=none] - * @returns {boxwhisker | object} - * @memberof boxwhisker - * @property - */ - boxwhisker.data = function (_) { - return arguments.length ? (data = _, boxwhisker) : data; - }; - /** - * Gets or sets the orient of the boxes - * (see {@link boxwhisker#orient}) - * @param {number} [_=none] - * @returns {boxwhisker | object} - * @memberof boxwhisker - * @property - */ - boxwhisker.orient = function (_) { - return arguments.length ? (orient = _, boxwhisker) : orient; - }; - /** - * Gets or sets the amount of horizontal space in which items are manipulated - * (see {@link boxwhisker#spaceX}) - * @param {number} [_=none] should be a number > 0 - * @returns {boxwhisker | number} - * @memberof boxwhisker - * @property - * by default spaceX = undefined - */ - boxwhisker.spaceX = function (_) { - return arguments.length ? (spaceX = _, boxwhisker) : spaceX; - }; - /** - * Gets or sets the amount of vertical space in which items are manipulated - * (see {@link boxwhisker#spaceY}) - * @param {number} [_=none] should be a number > 0 - * @returns {boxwhisker | number} - * @memberof boxwhisker - * @property - * by default spaceY = undefined - */ - boxwhisker.spaceY = function (_) { - return arguments.length ? (spaceY = _, boxwhisker) : spaceY; - }; - /** - * Gets / sets whether or not boxwhisker is allowed to go beyond specified dimensions - * (see {@link boxwhisker#overflowQ}) - * @param {boolean} [_=none] - * @returns {boxwhisker | boolean} - * @memberof boxwhisker - * @property - * by default overflowQ = false - */ - boxwhisker.overflowQ = function (_) { - return arguments.length ? (overflowQ = _, boxwhisker) : overflowQ; - }; - /** - * Gets / sets the grouping of the boxes - * (see {@link boxwhisker#grouping}) - * @param {Array[]} [_=none] - * @returns {boxwhisker | Array[]} - * @memberof boxwhisker - * @property - * by default grouping = undefined - */ - boxwhisker.grouping = function (_) { - return arguments.length ? (grouping = _, boxwhisker) : grouping; - }; - /** - * Gets / sets the quartilesKey - * (see {@link boxwhisker#quartilesKey}) - * @param {string} [_=none] - * @returns {boxwhisker | string} - * @memberof boxwhisker - * @property - * by default quartilesKey = quartiles - */ - boxwhisker.quartilesKey = function (_) { - return arguments.length ? (quartilesKey = _, boxwhisker) : quartilesKey; - }; - /** - * Gets / sets the quartilesKeys - * (see {@link boxwhisker#quartilesKeys}) - * @param {string[]} [_=none] - * @returns {boxwhisker | string[]} - * @memberof boxwhisker - * @property - * by default quartilesKeys = [Q0, Q1, Q2, Q3, Q4] - */ - boxwhisker.quartilesKeys = function (_) { - return arguments.length ? (quartilesKeys = _, boxwhisker) : quartilesKeys; - }; - /** - * Gets / sets the valueExtractor - * (see {@link boxwhisker#valueExtractor}) - * @param {function} [_=none] - * @returns {boxwhisker | function} - * @memberof boxwhisker - * @property - * by default valueExtractor = function(key, index) { return data[key][quartilesKey] }, - */ - - boxwhisker.valueExtractor = function (_) { - return arguments.length ? (valueExtractor = _, boxwhisker) : valueExtractor; - }; - /** - * Gets / sets the sortingFunction - * (see {@link boxwhisker#sortingFunction}) - * @param {function} [_=none] - * @returns {boxwhisker | function} - * @memberof boxwhisker - * @property - * by default sortingFunction = function(keyA, keyB) {return d3.descending( - * valueExtractor(keyA)[quartilesKeys[4]], - * valueExtractor(keyB)[quartilesKeys[4]] - * )}, - */ - boxwhisker.sortingFunction = function (_) { - return arguments.length ? (sortingFunction = _, boxwhisker) : sortingFunction; - }; - /** - * Gets / sets the scale for which the boxwhisker values should be transformed by - * (see {@link boxwhisker#scale}) - * @param {d3.scale} [_=none] - * @returns {boxwhisker | d3.scale} - * @memberof boxwhisker - * @property - * by default scale = d3.scaleLinear() - */ - boxwhisker.scale = function (_) { - return arguments.length ? (scale = _, boxwhisker) : scale; - }; - /** - * Gets / sets the padding for the domain of the scale - * (see {@link boxwhisker#domainPadding}) - * @param {number} [_=none] - * @returns {boxwhisker | number} - * @memberof boxwhisker - * @property - * by default domainPadding = 0.5 - */ - boxwhisker.domainPadding = function (_) { - return arguments.length ? (domainPadding = _, boxwhisker) : domainPadding; - }; - /** - * Gets / sets objectSpacer - * (see {@link boxwhisker#objectSpacer}) - * @param {number} [_=none] - * @returns {boxwhisker | number} - * @memberof boxwhisker - * @property - * by default objectSpacer = 0.05 - */ - boxwhisker.objectSpacer = function (_) { - return arguments.length ? (objectSpacer = _, boxwhisker) : objectSpacer; - }; - /** - * Gets / sets the minObjectSize - * (see {@link boxwhisker#minObjectSize}) - * @param {number} [_=none] - * @returns {boxwhisker | number} - * @memberof boxwhisker - * @property - * by default minObjectSize = 15 - */ - boxwhisker.minObjectSize = function (_) { - return arguments.length ? (minObjectSize = _, boxwhisker) : minObjectSize; - }; - /** - * Gets / sets the maxObjectSize - * (see {@link boxwhisker#maxObjectSize}) - * @param {number} [_=none] - * @returns {boxwhisker | number} - * @memberof boxwhisker - * @property - * by default maxObjectSize = 50 - */ - boxwhisker.maxObjectSize = function (_) { - return arguments.length ? (maxObjectSize = _, boxwhisker) : maxObjectSize; - }; - /** - * Gets / sets the whiskerWidthPercent - * (see {@link boxwhisker#whiskerWidthPercent}) - * @param {number} [_=none] - * @returns {boxwhisker | number} - * @memberof boxwhisker - * @property - * by default maxObjectSize = 0.6 - */ - boxwhisker.whiskerWidthPercent = function (_) { - return arguments.length ? (whiskerWidthPercent = _, boxwhisker) : whiskerWidthPercent; - }; - /** - * Gets / sets the colorFunction - * (see {@link boxwhisker#colorFunction}) - * @param {colorFunction} [_=none] - * @returns {boxwhisker | colorFunction} - * @memberof boxwhisker - * @property - * by default colorFunction = colorFunction() - */ - boxwhisker.colorFunction = function (_) { - return arguments.length ? (colorFunction$$1 = _, boxwhisker) : colorFunction$$1; - }; - /** - * Gets / sets the boxStrokeWidth - * (see {@link boxwhisker#boxStrokeWidth}) - * @param {number} [_=none] - * @returns {boxwhisker | number} - * @memberof boxwhisker - * @property - * by default boxStrokeWidth = 2 - */ - boxwhisker.boxStrokeWidth = function (_) { - return arguments.length ? (boxStrokeWidth = _, boxwhisker) : boxStrokeWidth; - }; - /** - * Gets / sets the whiskerStrokeWidth - * (see {@link boxwhisker#whiskerStrokeWidth}) - * @param {number} [_=none] - * @returns {boxwhisker | number} - * @memberof boxwhisker - * @property - * by default whiskerStrokeWidth = 2 - */ - boxwhisker.whiskerStrokeWidth = function (_) { - return arguments.length ? (whiskerStrokeWidth = _, boxwhisker) : whiskerStrokeWidth; - }; - - /** - * Gets / sets the backgroundFill - * (see {@link boxwhisker#backgroundFill}) - * @param {string} [_=none] - * @returns {boxwhisker | string} - * @memberof boxwhisker - * @property - * by default backgroundFill = 'transparent' - */ - boxwhisker.backgroundFill = function (_) { - return arguments.length ? (backgroundFill = _, boxwhisker) : backgroundFill; - }; - /** - * Gets / sets the namespace - * (see {@link boxwhisker#namespace}) - * @param {string} [_=none] - * @returns {boxwhisker | string} - * @memberof boxwhisker - * @property - * by default namespace = 'd3sm-boxwhisker' - */ - boxwhisker.namespace = function (_) { - return arguments.length ? (namespace = _, boxwhisker) : namespace; - }; - /** - * Gets / sets the objectClass - * (see {@link boxwhisker#objectClass}) - * @param {string} [_=none] - * @returns {boxwhisker | string} - * @memberof boxwhisker - * @property - * by default objectClass = 'tick-group' - */ - boxwhisker.objectClass = function (_) { - return arguments.length ? (objectClass = _, boxwhisker) : objectClass; - }; - /** - * Gets / sets the transitionDuration - * (see {@link boxwhisker#transitionDuration}) - * @param {number} [_=none] - * @returns {boxwhisker | number} - * @memberof boxwhisker - * @property - * by default transitionDuration = 1000 - */ - boxwhisker.transitionDuration = function (_) { - return arguments.length ? (transitionDuration = _, boxwhisker) : transitionDuration; - }; - /** - * Gets / sets the easeFunc - * (see {@link boxwhisker#easeFunc}) - * @param {d3.ease} [_=none] - * @returns {boxwhisker | d3.ease} - * @memberof boxwhisker - * @property - * by default easeFunc = d3.easeExp - */ - boxwhisker.easeFunc = function (_) { - return arguments.length ? (easeFunc = _, boxwhisker) : easeFunc; - }; - - /** - * Gets / sets the barKeys - * (see {@link boxwhisker#boxKeys}) - * @param {string[]} [_=none] - * @returns {boxwhisker | string[]} - * @memberof boxwhisker - * @property - * by default boxKeys = undefined - */ - boxwhisker.boxKeys = function (_) { - return arguments.length ? (boxKeys = _, boxwhisker) : boxKeys; - }; - /** - * Gets / sets the boxValues - * (see {@link boxwhisker#boxValues}) - * @param {number[]} [_=none] - * @returns {boxwhisker | number[]} - * @memberof boxwhisker - * @property - * by default boxValues = undefined - */ - boxwhisker.boxValues = function (_) { - return arguments.length ? (boxValues = _, boxwhisker) : boxValues; - }; - /** - * Gets / sets the objectSize - * (see {@link boxwhisker#objectSize}) - * @param {number} [_=none] - * @returns {boxwhisker | number} - * @memberof boxwhisker - * @property - * by default objectSize = undefined - */ - boxwhisker.objectSize = function (_) { - return arguments.length ? (objectSize = _, boxwhisker) : objectSize; - }; - /** - * Gets / sets the spacerSize - * (see {@link boxwhisker#spacerSize}) - * @param {number} [_=none] - * @returns {boxwhisker | number} - * @memberof boxwhisker - * @property - * by default spacerSize = undefined - */ - boxwhisker.spacerSize = function (_) { - return arguments.length ? (spacerSize = _, boxwhisker) : spacerSize; - }; - /** - * Gets / sets the tooltip - * (see {@link boxwhisker#tooltip}) - * @param {tooltip} [_=none] - * @returns {boxwhisker | tooltip} - * @memberof boxwhisker - * @property - * by default tooltip = tooltip() - */ - boxwhisker.tooltip = function (_) { - return arguments.length ? (tooltip$$1 = _, boxwhisker) : tooltip$$1; - }; - - function boxwhisker() { - // for convenience in handling orientation specific values - var horizontalQ = orient == 'horizontal' ? true : false; - var verticalQ = !horizontalQ; - - // background cliping rectangle - var bgcpRect = { x: 0, y: 0, width: spaceX, height: spaceY }; - var container = setupContainer(selection, namespace, bgcpRect, backgroundFill); - - // if grouping is undefined sort keys by sorting funct - var ordered = grouping == undefined ? d3.keys(data).sort(sortingFunction) : grouping; - // to prevent re-calculation and getters to be passed to axes - boxKeys = flatten(ordered); - boxValues = boxKeys.map(valueExtractor); - - var numberOfObjects = boxKeys.length; - var extent = [Math.min.apply(Math, toConsumableArray(boxValues.map(function (d, i) { - return d[quartilesKeys[0]]; - }))) - domainPadding, Math.max.apply(Math, toConsumableArray(boxValues.map(function (d, i) { - return d[quartilesKeys[4]]; - }))) + domainPadding]; - - // set the scale - scale.domain(extent).range(horizontalQ ? [0, spaceY] : [spaceX, 0]); - var space = horizontalQ ? spaceX : spaceY; - // calculate object size - objectSize = calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ); - // calculate spacer size if needed - spacerSize = calculateWidthOfSpacer(boxKeys, space, objectSize, numberOfObjects, objectSpacer, overflowQ); - // make the nested groups - var spacerFunction = groupingSpacer().horizontalQ(horizontalQ).scale(scale).moveby('category').numberOfObjects(numberOfObjects).objectClass(objectClass).objectSize(objectSize).spacerSize(spacerSize).transitionDuration(transitionDuration).easeFunc(easeFunc).namespace(namespace); - - // move stuff - spacerFunction(container, ordered, 0); - - var parentIndexArray = []; - container.selectAll('g:not(.to-remove).' + objectClass).each(function (d, i) { - if (hasQ(boxKeys, d)) { - parentIndexArray.push(Number(d3.select(this).attr('parent-index'))); - } - }); - - colorFunction$$1 = colorFunction$$1.colorBy() == 'index' ? colorFunction$$1.dataExtent([0, Math.max.apply(Math, parentIndexArray)]) : colorFunction$$1.dataExtent(extent); - - // set attributes for box and whiskers - container.selectAll('g:not(.to-remove).' + objectClass).each(function (key, i) { - var t = d3.select(this), - currentData = data[key], - quartiles$$1 = valueExtractor(key, i), - q0 = quartiles$$1[quartilesKeys[0]], - q1 = quartiles$$1[quartilesKeys[1]], - q2 = quartiles$$1[quartilesKeys[2]], - q3 = quartiles$$1[quartilesKeys[3]], - q4 = quartiles$$1[quartilesKeys[4]]; - - var i = t.attr('parent-index') == undefined ? i : t.attr('parent-index'), - fillColor = colorFunction$$1(key, q2, i, 'fill'), - // prevent duplicate computation - strokeColor = colorFunction$$1(key, q2, i, 'stroke'); - - var whisk = safeSelect(t, 'g', 'whisker'), - uWhisk = safeSelect(whisk, 'path', 'upper'), - lWhisk = safeSelect(whisk, 'path', 'lower'), - quart = safeSelect(t, 'g', 'quartile'), - uQuart = safeSelect(quart, 'rect', 'upper'), - lQuart = safeSelect(quart, 'rect', 'lower'), - mQuart = safeSelect(quart, 'circle', 'median'); - - // set upper quartile (q3) - uQuart.transition().duration(transitionDuration).ease(easeFunc).attr('width', horizontalQ ? objectSize : scale(q3) - scale(q2)).attr('height', verticalQ ? objectSize : scale(q3) - scale(q2)).attr('fill', fillColor).attr('stroke', strokeColor).attr('stroke-width', boxStrokeWidth).attr('transform', function (d, i) { - var x = horizontalQ ? 0 : scale(q2), - y = verticalQ ? 0 : scale(extent[1]) - scale(q3), - t = 'translate(' + x + ',' + y + ')'; - return t; - }); - - // set lower quartile (q1) - lQuart.transition().duration(transitionDuration).ease(easeFunc).attr('width', horizontalQ ? objectSize : scale(q2) - scale(q1)).attr('height', verticalQ ? objectSize : scale(q2) - scale(q1)).attr('fill', fillColor).attr('stroke', strokeColor).attr('stroke-width', boxStrokeWidth).attr('transform', function (d, i) { - var x = horizontalQ ? 0 : scale(q1), - y = verticalQ ? 0 : scale(extent[1]) - scale(q2), - t = 'translate(' + x + ',' + y + ')'; - return t; - }); - - // set median (q2) - mQuart.transition().duration(transitionDuration).ease(easeFunc).attr('r', function (d, i) { - var r = objectSize / 2; - var dif = (scale(q3) - scale(q1)) / 2; - return r > dif ? dif : r; - }).attr('fill', fillColor).attr('stroke', strokeColor).attr('stroke-width', boxStrokeWidth).attr('transform', function (d, i) { - var x = horizontalQ ? objectSize / 2 : scale(q2), - y = verticalQ ? objectSize / 2 : scale(extent[1]) - scale(q2), - t = 'translate(' + x + ',' + y + ')'; - return t; - }); - - // set lower whisker (min) - lWhisk.transition().duration(transitionDuration).ease(easeFunc).attr('d', function (dd, ii) { - var dir = false, - x = 0, - y = 0, - h = horizontalQ ? scale(q1) - scale(q0) : objectSize, - w = verticalQ ? scale(q1) - scale(q0) : objectSize; - return whiskerPath(dir, x, y, w, h, whiskerWidthPercent, orient); - }).attr('transform', function (d, i) { - var x = horizontalQ ? 0 : scale(q1), - y = verticalQ ? 0 : scale(extent[1]) - scale(q1), - t = 'translate(' + x + ',' + y + ')'; - return t; - }).attr('stroke', 'black').attr('stroke-width', whiskerStrokeWidth).attr('fill', 'none'); - - // set upper whisker (max) - uWhisk.transition().duration(transitionDuration).ease(easeFunc).attr('d', function (dd, ii) { - var dir = true, - x = 0, - y = 0, - h = horizontalQ ? scale(q4) - scale(q3) : objectSize, - w = verticalQ ? scale(q4) - scale(q3) : objectSize; - return whiskerPath(dir, x, y, w, h, whiskerWidthPercent, orient); - }).attr('transform', function (d, i) { - var x = horizontalQ ? 0 : scale(q3), - y = verticalQ ? 0 : scale(extent[1]) - scale(q4), - t = 'translate(' + x + ',' + y + ')'; - return t; - }).attr('stroke', 'black').attr('stroke-width', whiskerStrokeWidth).attr('fill', 'none'); - }); - - tooltip$$1.selection(container.selectAll('g:not(.to-remove).' + objectClass)).data(data); - tooltip$$1(); - } - - return boxwhisker; - } - - function selectFilter(selection) { - - var data, - namespace = 'd3sm-select-filter', - selectionName = 'Select options:', - defaultValue = undefined; - - var lastValue = undefined; - - selectFilter.data = function (_) { - return arguments.length ? (data = _, selectFilter) : data; - }; - selectFilter.namespace = function (_) { - return arguments.length ? (namespace = _, selectFilter) : namespace; - }; - selectFilter.selectionName = function (_) { - return arguments.length ? (selectionName = _, selectFilter) : selectionName; - }; - selectFilter.defaultValue = function (_) { - return arguments.length ? (defaultValue = _, selectFilter) : defaultValue; - }; - selectFilter.currentOption = currentOption; - - function selectFilter() { - var container = safeSelect(selection, 'div', 'input-group').classed(hypenate(namespace, 'container'), true), - selectPrepend = safeSelect(container, 'div', 'select-prepend').classed('input-group-prepend', true), - selectPrependSpan = safeSelect(selectPrepend, 'span', 'input-group-text').text(selectionName), - select = safeSelect(container, 'select', 'custom-select').classed(hypenate(namespace, 'select'), true), - selectAppend = safeSelect(container, 'div', 'select-append').classed('input-group-prepend', true), - selectAppendButton = safeSelect(selectAppend, 'a', 'filter-button').classed('btn btn-outline-secondary', true), - filterButtonIcon = safeSelect(selectAppendButton, 'i', 'fa fa-filter'), - inputGroup = safeSelect(container, 'div', 'filter-input-group').classed('input-group', true).classed('d-none', true), - inputPrepend = safeSelect(inputGroup, 'div', 'input-group-prepend'), - inputPrependSpan = safeSelect(inputPrepend, 'span', 'input-group-text').classed('search-button', true), - inputPrependSpanIcon = safeSelect(inputPrependSpan, 'i', 'fa fa-search'), - input = safeSelect(inputGroup, 'input', 'form-control').attr('placeholder', 'all').attr('type', 'text'), - inputAppend = safeSelect(inputGroup, 'div', 'input-group-append'), - inputAppendButton = safeSelect(inputAppend, 'a', 'close-button').classed('btn btn-outline-secondary', true), - inputAppendButtonIcon = safeSelect(inputAppendButton, 'i', 'fa fa-close'); - - var keys = d3.keys(data), - options = select.selectAll('option'); - - options = options.data(d3.keys(data)); - options = options.merge(options.enter().append('option')).attr('value', function (d, i) { - return d; - }).text(function (d, i) { - return d; - }); - - var filterButton = selectAppendButton, - closeButton = inputAppendButton; - - filterButton.on('click', function (d, i) { - var currentStyle = inputGroup.classed('d-none'); - inputGroup.classed('d-none', !currentStyle); - }); - - closeButton.on('click', function (d, i) { - input.property('value', '').dispatch('input'); - }); - - input.on('input', function (d, i) { - var val = input.property('value'), - reg = new RegExp(val, 'gi'), - use; - - if (val == '') { - use = keys; - } else { - use = []; - d3.keys(data).map(function (option, j) { - var match = option.match(reg); - if (match == null || match.join('') == '') ; else { - use.push(option); - } - }); - } - - options = select.selectAll('option'); - options = options.data(use); - options.exit().remove(); - options = options.merge(options.enter().append('option')).attr('value', function (d, i) { - return d; - }).text(function (d, i) { - return d; - }); - - var current = currentOption(); - if (lastValue != current) { - lastValue = current; - select.dispatch('change'); - } - }); - } - - function currentOption() { - var val = selection.select("select").property('value'); - return val == undefined || val == '' ? defaultValue == undefined ? d3.keys(data)[0] : defaultValue : val; - } - - return selectFilter; - } - - /******************************************************************************* - ** ** - ** ** - ** DATATOGGLE ** - ** ** - ** ** - *******************************************************************************/ - /** - * Creates a datatoggle - * @constructor datatoggle - * @param {d3.selection} selection - * @namespace datatoggle - * @returns {function} datatoggle - */ - function datatoggle(selection) { - var - /** - * What to do when a different key is clicked - * (see {@link datatoggle#updateFunction}) - * @param {function} [updateFunction=function(){}] - * @memberof datatoggle# - * @property - */ - updateFunction = function updateFunction() {}, - - /** - * Namespace for all items made by this instance of datatoggle - * @param {string} [namespace="d3sm-databar"] - * @memberof datatoggle# - * @property - */ - namespace = 'd3sm-databar', - - xAxisSelectQ = false, - xAxisOptions, - yAxisSelectQ = false, - yAxisOptions, - data; - toggle.xAxisSelectQ = function (_) { - return arguments.length ? (xAxisSelectQ = _, toggle) : xAxisSelectQ; - }; - toggle.yAxisSelectQ = function (_) { - return arguments.length ? (yAxisSelectQ = _, toggle) : yAxisSelectQ; - }; - toggle.xAxisOptions = function (_) { - return arguments.length ? (xAxisOptions = _, toggle) : xAxisOptions; - }; - toggle.yAxisOptions = function (_) { - return arguments.length ? (yAxisOptions = _, toggle) : yAxisOptions; - }; - toggle.data = function (_) { - return arguments.length ? (data = _, toggle) : data; - }; - - /** - * Gets / sets the updateFunction - * (see {@link datatoggle#updateFunction}) - * @function datatoggle.updateFunction - * @param {function} [_=none] - * @returns {datatoggle | function} - * @memberof datatoggle - * @property - * by default updateFunction = function(){} - */ - toggle.updateFunction = function (_) { - return arguments.length ? (updateFunction = _, toggle) : updateFunction; - }; - /** - * Gets / sets the namespace - * (see {@link datatoggle#namespace}) - * @function datatoggle.namespace - * @param {string} [_=none] - * @returns {datatoggle | string} - * @memberof datatoggle - * @property - * by default namespace = 'd3sm-databar' - */ - toggle.namespace = function (_) { - return arguments.length ? (namespace = _, toggle) : namespace; - }; - /** - * Gets / sets the currentKey - * (see {@link datatoggle#currentKey}) - * @function datatoggle.currentKey - * @param {string} [_=none] - * @returns {datatoggle | string} - * @memberof datatoggle - * @property - * by default currentKey = undefined - */ - toggle.currentKeys = function () { - var vals = {}; - d3.keys(filterSelects).map(function (k, i) { - vals[k] = filterSelects[k].currentOption(); - }); - return vals; - }; - - var filterSelects = {}; - function toggle() { - // selection options - - // selection.classed('d-flex flex-row', true) - // var filterButton = safeSelect(selection, 'a', 'slider-buttons') - // var filterI = safeSelect(filterButton, 'i', 'fa fa-sliders') - - /*BUG: unexpected behavior. - - when using bootstrap-eque way for collapse, clicking button submits to - the same page in applications (but not in demo), so using anchor () - - when using anchor, cause page to jump to that location - - when using show, the first open works, but the close does not. - */ - // filterButton.attr('class', 'btn btn-secondary') - // .attr('data-toggle', 'collapse') - // .attr('href', '#'+hypenate(namespace, 'data-toggle')) - // .attr('target', '_blank') - // .html(filterButton.html()+' Filters') - // .on('click', function(d, i){ - // d3.event.preventDefault() - // d3.event.stopPropagation() - // var dt = d3.select("#"+hypenate(namespace, 'data-toggle')) - // dt.classed('show', !dt.classed('show')) - // dt.classed('d-inline-flex', dt.classed('show')) - // - // filterButton.classed('btn-primary', dt.classed('show')) - // filterButton.classed('btn-secondary', !dt.classed('show')) - // }) - // .classed('d-inline-flex', true) - // .style("margin-right", '10px') - - - // var datatoggleCollapse = safeSelect(selection, 'div', hypenate(namespace,'collapse')) - // .attr('id', hypenate(namespace, 'data-toggle')) - // .classed('collapse', true) - - // var flexRow = safeSelect(datatoggleCollapse, 'div', 'd-inline-flex flex-row flex-wrap') - var flexRow = safeSelect(selection, 'div', 'd-inline-flex flex-row flex-wrap'); - - var dataopts = flexRow.selectAll('div.' + hypenate(namespace, 'select-filter')); - // remove excess - dataopts.exit().remove(); - // bind data - dataopts = dataopts.data(d3.keys(data)); - //enter - var doEnter = dataopts.enter().append('div').attr('class', 'select-filter'); - - dataopts = dataopts.merge(doEnter).style('margin-right', "10px"); - - dataopts.each(function (d, i) { - var t = d3.select(this); - var sf = selectFilter(t).data(data[d]).namespace(hypenate(namespace, d)).selectionName(d); - sf(); - filterSelects[d] = sf; - }); - - selection.selectAll('select').on('change', function () { - updateFunction(); - }); - // bind update function - // d3.selectAll - return toggle; - } - - return toggle; - } - - /******************************************************************************* - ** ** - ** ** - ** SCATTER ** - ** ** - ** ** - *******************************************************************************/ - /** - * Creates a scatter - * - * {@link https://sumneuron.gitlab.io/d3sm/demos/scatter/index.html Demo} - * @constructor scatter - * @param {d3.selection} selection - * @namespace scatter - * @returns {function} scatter - */ - function scatter(selection) { - - var - /** - * Data to plot. Assumed to be a object, where each key corresponds to a point - * (see {@link scatter#data}) - * @param {Object} [data=undefined] - * @memberof scatter# - * @property - */ - data, - - /** - * Amount of horizontal space (in pixels) avaible to render the scatter in - * (see {@link scatter#spaceX}) - * @param {number} [spaceX=undefined] - * @memberof scatter# - * @property - */ - spaceX, - - /** - * Amount of vertical space (in pixels) avaible to render the scatter in - * (see {@link scatter.spaceY}) - * @param {number} [spaceY=undefined] - * @memberof scatter# - * @property - */ - spaceY, - - - /** - * The scale for which scatter x values should be transformed by - * @param {d3.scale} [scaleX=d3.scaleLinear] - * @memberof scatter# - * @property - */ - scaleX = d3.scaleLinear(), - - /** - * The padding for the domain of the scaleX (see {@link scatter#scaleX}) - * @param {number} [domainPaddingX=0.5] - * @memberof scatter# - * @property - */ - domainPaddingX = 0.5, - - /** - * The function for getting the x value of the current point - * @param {function} [valueExtractorX=function(d, i){return data[d]['x']}] - * @memberof scatter# - * @property - */ - valueExtractorX = function valueExtractorX(d, i) { - return data[d]['x']; - }, - - - /** - * The scale for which scatter y values should be transformed by - * @param {d3.scale} [scaleY=d3.scaleLinear] - * @memberof scatter# - * @property - */ - scaleY = d3.scaleLinear(), - - /** - * The padding for the domain of the scaleY (see {@link scatter#scaleY}) - * @param {number} [domainPaddingY=0.5] - * @memberof scatter# - * @property - */ - domainPaddingY = 0.5, - - /** - * The function for getting the y value of the current point - * @param {function} [valueExtractorY=function(d, i){return data[d]['y']}] - * @memberof scatter# - * @property - */ - valueExtractorY = function valueExtractorY(d, i) { - return data[d]['y']; - }, - - - /** - * The scale for which scatter r values should be transformed by - * @param {d3.scale} [scaleR=d3.scaleLinear] - * @memberof scatter# - * @property - */ - scaleR = d3.scaleLinear(), - - /** - * The padding for the domain of the scaleR (see {@link scatter#scaleR}) - * @param {number} [domainPaddingR=0.5] - * @memberof scatter# - * @property - */ - domainPaddingR = 0.5, - - /** - * The function for getting the r value of the current point - * @param {function} [valueExtractorR=function(d, i){return 2}] - * @memberof scatter# - * @property - */ - valueExtractorR = function valueExtractorR(d, i) { - return 2; - }, - - /** - * The min radius a point can have - * @param {function} [minRadius=2] - * @memberof scatter# - * @property - */ - minRadius = 2, - - /** - * The min radius a point can have - * @param {function} [maxRadius=10] - * @memberof scatter# - * @property - */ - maxRadius = 10, - - - /** - * The stroke width of the points - * @param {number} [pointStrokeWidth=2] - * @memberof scatter# - * @property - */ - pointStrokeWidth = 2, - - /** - * Instance of ColorFunction - * @param {function} [colorFunction = colorFunction()] - * @memberof scatter# - * @property - */ - colorFunction$$1 = colorFunction(), - - /** - * Color of the background - * @param {string} [backgroundFill="transparent"] - * @memberof scatter# - * @property - */ - backgroundFill = 'transparent', - - /** - * Namespace for all items made by this instance of scatter - * @param {string} [namespace="d3sm-scatter"] - * @memberof scatter# - * @property - */ - namespace = 'd3sm-scatter', - - /** - * Class name for scatter container ( element) - * @param {string} [objectClass="scatter-point"] - * @memberof scatter# - * @property - */ - objectClass = 'scatter-point', - - /** - * Duration of all transitions of this element - * @param {number} [transitionDuration=1000] - * @memberof scatter# - * @property - */ - transitionDuration = 1000, - - /** - * Easing function for transitions - * @param {d3.ease} [easeFunc=d3.easeExp] - * @memberof scatter# - * @property - */ - easeFunc = d3.easeExp, - - - // useful values to extract to prevent re-calculation - /** - * The keys of the points - * @param {string[]} [pointKeys=undefined] - * @memberof scatter# - * @property - */ - pointKeys, - - /** - * The x values of the points - * @param {number[]} [valuesX=undefined] - * @memberof scatter# - * @property - */ - valuesX, - - /** - * The y values of the points - * @param {number[]} [valuesY=undefined] - * @memberof scatter# - * @property - */ - valuesY, - - /** - * The r values of the points - * @param {number[]} [valuesR=undefined] - * @memberof scatter# - * @property - */ - valuesR, - - - /** - * Instance of Tooltip - * @param {function} [tooltip=tooltip()] - * @memberof scatter# - * @property - */ - tooltip$$1 = tooltip(); - - /** - * Gets or sets the selection in which items are manipulated - * @param {d3.selection} [_=none] - * @returns {scatter | d3.selection} - * @memberof scatter - * @property - * by default selection = selection - */ - scatter.selection = function (_) { - return arguments.length ? (selection = _, scatter) : selection; - }; - /** - * Gets or sets the data - * (see {@link scatter#data}) - * @param {number} [_=none] - * @returns {scatter | object} - * @memberof scatter - * @property - */ - scatter.data = function (_) { - return arguments.length ? (data = _, scatter) : data; - }; - /** - * Gets or sets the amount of horizontal space in which items are manipulated - * (see {@link scatter#spaceX}) - * @param {number} [_=none] should be a number > 0 - * @returns {scatter | number} - * @memberof scatter - * @property - * by default spaceX = undefined - */ - scatter.spaceX = function (_) { - return arguments.length ? (spaceX = _, scatter) : spaceX; - }; - /** - * Gets or sets the amount of vertical space in which items are manipulated - * (see {@link scatter#spaceY}) - * @param {number} [_=none] should be a number > 0 - * @returns {scatter | number} - * @memberof scatter - * @property - * by default spaceY = undefined - */ - scatter.spaceY = function (_) { - return arguments.length ? (spaceY = _, scatter) : spaceY; - }; - - /** - * Gets / sets the x scale for which the scatter x values should be transformed by - * (see {@link scatter#scaleX}) - * @param {d3.scale} [_=none] - * @returns {scatter | d3.scale} - * @memberof scatter - * @property - * by default scaleX = d3.scaleLinear() - */ - scatter.scaleX = function (_) { - return arguments.length ? (scaleX = _, scatter) : scaleX; - }; - /** - * Gets / sets the padding for the domain of the x scale - * (see {@link scatter#domainPaddingX}) - * @param {number} [_=none] - * @returns {scatter | number} - * @memberof scatter - * @property - * by default domainPaddingX = 0.5 - */ - scatter.domainPaddingX = function (_) { - return arguments.length ? (domainPaddingX = _, scatter) : domainPaddingX; - }; - /** - * Gets / sets the valueExtractorX - * (see {@link scatter#valueExtractorX}) - * @param {function} [_=none] - * @returns {scatter | function} - * @memberof scatter - * @property - * by default valueExtractorX = function(key, index) { return data[key]['x'] } - */ - scatter.valueExtractorX = function (_) { - return arguments.length ? (valueExtractorX = _, scatter) : valueExtractorX; - }; - - /** - * Gets / sets the y scale for which the scatter y values should be transformed by - * (see {@link scatter#scaleY}) - * @param {d3.scale} [_=none] - * @returns {scatter | d3.scale} - * @memberof scatter - * @property - * by default scaleY = d3.scaleLinear() - */ - scatter.scaleY = function (_) { - return arguments.length ? (scaleY = _, scatter) : scaleY; - }; - /** - * Gets / sets the padding for the domain of the y scale - * (see {@link scatter#domainPaddingY}) - * @param {number} [_=none] - * @returns {scatter | number} - * @memberof scatter - * @property - * by default domainPaddingY = 0.5 - */ - scatter.domainPaddingY = function (_) { - return arguments.length ? (domainPaddingY = _, scatter) : domainPaddingY; - }; - /** - * Gets / sets the valueExtractorY - * (see {@link scatter#valueExtractorY}) - * @param {function} [_=none] - * @returns {scatter | function} - * @memberof scatter - * @property - * by default valueExtractorY = function(key, index) { return data[key]['y'] } - */ - scatter.valueExtractorY = function (_) { - return arguments.length ? (valueExtractorY = _, scatter) : valueExtractorY; - }; - - /** - * Gets / sets the r scale for which the scatter r values should be transformed by - * (see {@link scatter#scaleR}) - * @param {d3.scale} [_=none] - * @returns {scatter | d3.scale} - * @memberof scatter - * @property - * by default scaleR = d3.scaleLinear() - */ - scatter.scaleR = function (_) { - return arguments.length ? (scaleR = _, scatter) : scaleR; - }; - /** - * Gets / sets the padding for the domain of the r scale - * (see {@link scatter#domainPaddingR}) - * @param {number} [_=none] - * @returns {scatter | number} - * @memberof scatter - * @property - * by default domainPaddingR = 0.5 - */ - scatter.domainPaddingR = function (_) { - return arguments.length ? (domainPaddingR = _, scatter) : domainPaddingR; - }; - /** - * Gets / sets the valueExtractorR - * (see {@link scatter#valueExtractorR}) - * @param {function} [_=none] - * @returns {scatter | function} - * @memberof scatter - * @property - * by default valueExtractorR = function(key, index) { return data[key]['r'] } - */ - scatter.valueExtractorR = function (_) { - return arguments.length ? (valueExtractorR = _, scatter) : valueExtractorR; - }; - /** - * Gets / sets the minRadius - * (see {@link scatter#minRadius}) - * @param {number} [_=none] - * @returns {scatter | number} - * @memberof scatter - * @property - * by default minRadius = 2 - */ - scatter.minRadius = function (_) { - return arguments.length ? (minRadius = _, scatter) : minRadius; - }; - /** - * Gets / sets the maxRadius - * (see {@link scatter#maxRadius}) - * @param {number} [_=none] - * @returns {scatter | number} - * @memberof scatter - * @property - * by default maxRadius = 10 - */ - scatter.maxRadius = function (_) { - return arguments.length ? (maxRadius = _, scatter) : maxRadius; - }; - - /** - * Gets / sets the pointStrokeWidth - * (see {@link scatter#pointStrokeWidth}) - * @param {number} [_=none] - * @returns {scatter | number} - * @memberof scatter - * @property - * by default pointStrokeWidth = 2 - */ - scatter.pointStrokeWidth = function (_) { - return arguments.length ? (pointStrokeWidth = _, scatter) : pointStrokeWidth; - }; - /** - * Gets / sets the colorFunction - * (see {@link scatter#colorFunction}) - * @param {number} [_=none] - * @returns {scatter | number} - * @memberof scatter - * @property - * by default colorFunction = colorFunction() - */ - scatter.colorFunction = function (_) { - return arguments.length ? (colorFunction$$1 = _, scatter) : colorFunction$$1; - }; - /** - * Gets / sets the backgroundFill - * (see {@link scatter#backgroundFill}) - * @param {string} [_=none] - * @returns {scatter | string} - * @memberof scatter - * @property - * by default backgroundFill = 'transparent' - */ - scatter.backgroundFill = function (_) { - return arguments.length ? (backgroundFill = _, scatter) : backgroundFill; - }; - /** - * Gets / sets the namespace - * (see {@link scatter#namespace}) - * @param {string} [_=none] - * @returns {scatter | string} - * @memberof scatter - * @property - * by default namespace = 'd3sm-scatter' - */ - scatter.namespace = function (_) { - return arguments.length ? (namespace = _, scatter) : namespace; - }; - /** - * Gets / sets the objectClass - * (see {@link scatter#objectClass}) - * @param {string} [_=none] - * @returns {scatter | string} - * @memberof scatter - * @property - * by default objectClass = 'tick-group' - */ - scatter.objectClass = function (_) { - return arguments.length ? (objectClass = _, scatter) : objectClass; - }; - /** - * Gets / sets the transitionDuration - * (see {@link scatter#transitionDuration}) - * @param {number} [_=none] - * @returns {scatter | number} - * @memberof scatter - * @property - * by default transitionDuration = 1000 - */ - scatter.transitionDuration = function (_) { - return arguments.length ? (transitionDuration = _, scatter) : transitionDuration; - }; - /** - * Gets / sets the easeFunc - * (see {@link scatter#easeFunc}) - * @param {d3.ease} [_=none] - * @returns {scatter | d3.ease} - * @memberof scatter - * @property - * by default easeFunc = d3.easeExp - */ - scatter.easeFunc = function (_) { - return arguments.length ? (easeFunc = _, scatter) : easeFunc; - }; - - /** - * Gets / sets the pointKeys - * (see {@link scatter#pointKeys}) - * @param {string[]} [_=none] - * @returns {scatter | string[]} - * @memberof scatter - * @property - * by default pointKeys = undefined - */ - scatter.pointKeys = function (_) { - return arguments.length ? (pointKeys = _, scatter) : pointKeys; - }; - /** - * Gets / sets the valuesX - * (see {@link scatter#valuesX}) - * @param {number[]} [_=none] - * @returns {scatter | number[]} - * @memberof scatter - * @property - * by default valuesX = undefined - */ - scatter.valuesX = function (_) { - return arguments.length ? (valuesX = _, scatter) : valuesX; - }; - /** - * Gets / sets the valuesY - * (see {@link scatter#valuesY}) - * @param {number[]} [_=none] - * @returns {scatter | number[]} - * @memberof scatter - * @property - * by default valuesY = undefined - */ - scatter.valuesY = function (_) { - return arguments.length ? (valuesY = _, scatter) : valuesY; - }; - /** - * Gets / sets the valuesR - * (see {@link scatter#valuesR}) - * @param {number[]} [_=none] - * @returns {scatter | number[]} - * @memberof scatter - * @property - * by default valuesR = undefined - */ - scatter.valuesR = function (_) { - return arguments.length ? (valuesR = _, scatter) : valuesR; - }; - /** - * Gets / sets the tooltip - * (see {@link scatter#tooltip}) - * @param {tooltip} [_=none] - * @returns {scatter | tooltip} - * @memberof scatter - * @property - * by default tooltip = tooltip() - */ - - scatter.tooltip = function (_) { - return arguments.length ? (tooltip$$1 = _, scatter) : tooltip$$1; - }; - - function scatter() { - // background cliping rectangle - var bgcpRect = { x: 0, y: 0, width: spaceX, height: spaceY }; - var container = setupContainer(selection, namespace, bgcpRect, backgroundFill); - - pointKeys = d3.keys(data); - valuesX = pointKeys.map(valueExtractorX); - valuesY = pointKeys.map(valueExtractorY); - valuesR = pointKeys.map(valueExtractorR); - - var numberOfObjects = pointKeys.length; - var extentX = [Math.min.apply(Math, toConsumableArray(valuesX)) - domainPaddingX, Math.max.apply(Math, toConsumableArray(valuesX)) + domainPaddingX]; - var extentY = [Math.min.apply(Math, toConsumableArray(valuesY)) - domainPaddingY, Math.max.apply(Math, toConsumableArray(valuesY)) + domainPaddingY]; - var extentR = [Math.min.apply(Math, toConsumableArray(valuesR)) - domainPaddingR, Math.max.apply(Math, toConsumableArray(valuesR)) + domainPaddingR]; - - scaleX.domain(extentX).range([0, spaceX]); - scaleY.domain(extentY).range([spaceY, 0]); - scaleR.domain(extentR).range([minRadius, maxRadius]); - - var points = container.selectAll('.' + objectClass); - points = points.data(pointKeys); - var pEnter = points.enter().append('circle').attr('class', objectClass).attr('cx', 0).attr('cy', spaceY).attr('r', 0); - - var pExit = points.exit(); - - points = points.merge(pEnter); - - points.each(function (key, i) { - var t = d3.select(this), - currentData = data[key], - x = valuesX[i], - y = valuesY[i], - r = valuesR[i], - fillColor = colorFunction$$1(key, currentData, i, 'fill'), - strokeColor = colorFunction$$1(key, currentData, i, 'stroke'); - - t.transition().duration(transitionDuration).ease(easeFunc).attr('cx', scaleX(x)).attr('cy', scaleY(y)).attr('r', scaleR(r)).attr('fill', fillColor).attr('stroke', strokeColor).attr('stroke-width', pointStrokeWidth); - - t.on('mouseover', function (d, i) { - points.style('opacity', 0.2); - t.style('opacity', 1); - t.transition().duration(transitionDuration / 2).ease(easeFunc).attr('stroke-width', pointStrokeWidth * 2).attr('r', scaleR(r) * 1.5); - }); - t.node().addEventListener('mouseout', function () { - container.selectAll('.' + objectClass).style('opacity', 1); - t.transition().duration(transitionDuration / 2).ease(easeFunc).attr('stroke-width', pointStrokeWidth).attr('r', scaleR(r)); - }); - }); - - pExit.transition().duration(transitionDuration).ease(easeFunc).attr('cx', 0).attr('cy', spaceY).attr('r', 0).remove(); - - tooltip$$1.selection(points).data(data); - - tooltip$$1(); - } - - return scatter; - } - - /******************************************************************************* - - ** ** - ** ** - ** PLOTZOOM ** - ** ** - ** ** - *******************************************************************************/ - /** - * Creates an plotZoom instance, which can handle drag and scroll events - * @constructor plotZoom - * @param {function} chart a function instance of one of the d3sm plots (e.g. bar, boxwhisker, bubbleHeatmap, violin, etc) - * @param {axis} xAxis the axis instance responsible for the x axis - * @param {axis} yAxis the axis instance responsible for the y axis - * @namespace plotZoom - * @returns {function} zoom - */ - function plotZoom(chart, xAxis, yAxis) { - var - /** - * The event on which to fire - * (see {@link plotZoom#eventType}) - * @param {string} eventType which event it should handle. Currently supports scroll and wheel - * @memberof plotZoom# - * @property - */ - eventType, - - /** - * A scaling factor for the wheel "speed" - * (see {@link plotZoom#wheelSpeed}) - * @param {number} [wheelSpeed=20] scales the wheel translation by wheelSpeed - * @memberof plotZoom# - * @property - */ - wheelSpeed = 20, - - /** - * The orientation in which to allow scrolling: 'horizontal', 'vertical', or '2D' - * (see {@link plotZoom#orient}) - * @param {string} [orient=chart.orient() || 'horizontal'] - * @memberof plotZoom# - * @property - */ - orient = chart.orient == undefined ? 'horizontal' : chart.orient(), - - /** - * The max distance allowed to scroll in the x direction - * (see {@link plotZoom#xLock}) - * @param {number} [xLock=chart.spaceX()] ideally chart.overflowQ() == true and this value is the - * bounding rect across all elements in the chart minus the space in which to show. - * @memberof plotZoom# - * @property - */ - xLock = chart.spaceX(), - - /** - * The max distance allowed to scroll in the y direction - * (see {@link plotZoom#yLock}) - * @param {number} [yLock=chart.spaceY()] ideally chart.overflowQ() == true and this value is the - * bounding rect across all elements in the chart minus the space in which to show. - * @memberof plotZoom# - * @property - */ - yLock = chart.spaceY(), - chartSel = chart.selection(), - xAxisSel = xAxis.selection(), - yAxisSel = yAxis.selection(), - svg = d3.select(chartSel.thisSVG()); - - /** - * Gets or sets the event type in which to respond - * (see {@link plotZoom#eventType}) - * @param {string} [_=none] should be 'drag' or 'wheel' - * @returns {zoom | string} - * @memberof plotZoom - * @property - * by default plotZoom=undefined - */ - zoom.eventType = function (_) { - return arguments.length ? (eventType = _, zoom) : eventType; - }; - /** - * Gets or sets the wheel speed in which to scale the wheel scroll transform - * (see {@link plotZoom#wheelSpeed}) - * @param {number} [_=none] - * @returns {zoom | number} - * @memberof plotZoom - * @property - * by default wheelSpeed=20 - */ - zoom.wheelSpeed = function (_) { - return arguments.length ? (wheelSpeed = _, zoom) : wheelSpeed; - }; - /** - * Gets or sets the orientation in which items are manipulated - * (see {@link plotZoom#orient}) - * @param {string} [_=none] should be horizontal, vertical, or 2D - * @returns {zoom | string} - * @memberof plotZoom - * @property - * by default orient=chart.orient() || 'horizontal' - */ - zoom.orient = function (_) { - return arguments.length ? (orient = _, zoom) : orient; - }; - - /** - * Gets or sets the max distance in which to scroll X - * (see {@link plotZoom#xLock}) - * @param {number} [_=none] should be a positive value - * @returns {zoom | number} - * @memberof plotZoom - * @property - * by default xLock=chart.spaceX() - */ - zoom.xLock = function (_) { - return arguments.length ? (xLock = _, zoom) : xLock; - }; - /** - * Gets or sets the max distance in which to scroll Y - * (see {@link plotZoom#yLock}) - * @param {number} [_=none] should be a positive value - * @returns {zoom | number} - * @memberof plotZoom - * @property - * by default yLock=chart.spaceY() - */ - zoom.yLock = function (_) { - return arguments.length ? (yLock = _, zoom) : yLock; - }; - - function setLocks() { - var chartObjSel = chartSel.select('.' + hypenate(chart.namespace(), 'object-container')); - var chartObjTrans = getTranslation(chartObjSel.attr('transform')); - var cos = chartObjSel.attr('transform', 'translate(0,0)'); - xLock = chartSel.node().getBBox().width - chart.spaceX() * .9; - yLock = chartSel.node().getBBox().height - chart.spaceY() * .9; - cos.attr('transform', 'translate(' + chartObjTrans[0] + ',' + chartObjTrans[1] + ')'); - log('plotZoom', 'setLocks', { xLock: xLock, yLock: yLock }); - } - - /** - * Sets the x and y locks (how far one can scroll) - * (see {@link plotZoom#xLock} and {@link plotZoom#yLock}) - * @function plotZoom.setLocks - * @returns {undefined} - * @memberof plotZoom - * @property - */ - zoom.setLocks = setLocks; - - function zoom() { - setLocks(); - - var horizontalQ, verticalQ; - if (orient == '2D') { - horizontalQ = true;verticalQ = true; - } - if (orient == 'horizontal') { - horizontalQ = true;verticalQ = false; - } - if (orient == 'vertical') { - verticalQ = true;horizontalQ = false; - } - - // capture transform event - var transform = d3.event.transform; - - var chartBox = chartSel.node().getBBox(); - var xAxisBox = xAxisSel.node().getBBox(); - var yAxisBox = xAxisSel.node().getBBox(); - - var chartWidth = chartBox.width - chartBox.x; - var chartHeight = chartBox.height - chartBox.y; - var xAxisWidth = xAxisBox.width; // - xAxisBox.x - var xAxisHeight = xAxisBox.height; // - xAxisBox.y - var yAxisWidth = yAxisBox.width; // - yAxisBox.x - var yAxisHeight = yAxisBox.height; // -yAxisBox.y - - // enable wheel event - if (eventType == "wheel") { - var e = d3.event; - // prevent page scrolling - e.preventDefault(); - // event delta is very very slow, so speed it up with wheel speed - var w = d3.event.deltaY * wheelSpeed; - var shiftQ = d3.event.shiftKey; - - // d3 has no way to make custom transform, so make an object and add - // the necessary functions to make wheel event compatible with drag events - if (orient == '2D') { - transform = shiftQ ? { k: 1, x: w, y: 0 } : { k: 1, x: 0, y: w }; - } else { - transform = horizontalQ ? { k: 1, x: w, y: 0 } : { k: 1, x: 0, y: w }; - } - // the * -1 inverts the direction - transform.applyX = function (x) { - return x * this.k + this.x * -1; - }; - transform.applyY = function (y) { - return y * this.k + this.y * -1; - }; - } - - var chartObjSel = chartSel.select('.' + hypenate(chart.namespace(), 'object-container')); - var xAxisObjSel = xAxisSel.select('.' + hypenate(xAxis.namespace(), 'object-container')); - var yAxisObjSel = yAxisSel.select('.' + hypenate(yAxis.namespace(), 'object-container')); - - // xLock = chartSel.node().getBBox().width - chart.spaceX() - chartSel.node().getBBox().x - // yLock = chartSel.node().getBBox().height - chart.spaceY() - // console.table({'xLock':xLock, "yLock":yLock}) - // bhm.selection().node().getBBox().width - bhm.spaceX() - - - var chartObjTrans = getTranslation(chartObjSel.attr('transform')); - var xAxisObjTrans = getTranslation(xAxisObjSel.attr('transform')); - var yAxisObjTrans = getTranslation(yAxisObjSel.attr('transform')); - - var x = horizontalQ ? transform.applyX(chartObjTrans[0]) : 0; - if (horizontalQ) { - x = x < -xLock ? (transform.x = 0, -xLock) : (transform.x = 0, Math.min(x, 0)); - } - - var y = verticalQ ? transform.applyY(chartObjTrans[1]) : 0; - if (verticalQ) { - y = y < -yLock ? (transform.y = 0, -yLock) : (transform.y = 0, Math.min(y, 0)); - } - - chartObjSel.attr('transform', 'translate(' + x + ',' + y + ')'); - if (horizontalQ) { - xAxisObjSel.attr('transform', 'translate(' + x + ',' + 0 + ')'); - } - if (verticalQ) { - yAxisObjSel.attr('transform', 'translate(' + 0 + ',' + y + ')'); - } - - // var lasso = svg.select(".lasso-container") - // if (!lasso.empty()) { - // lasso.attr('transform', 'translate('+x+','+y+')') - // } - } - - zoom.reset = function () { - - var chartObjSel = chartSel.select('.' + hypenate(chart.namespace(), 'object-container')); - var xAxisObjSel = xAxisSel.select('.' + hypenate(xAxis.namespace(), 'object-container')); - var yAxisObjSel = yAxisSel.select('.' + hypenate(yAxis.namespace(), 'object-container')); - chartObjSel.attr('transform', 'translate(' + 0 + ',' + 0 + ')'); - xAxisObjSel.attr('transform', 'translate(' + 0 + ',' + 0 + ')'); - yAxisObjSel.attr('transform', 'translate(' + 0 + ',' + 0 + ')'); - }; - - return zoom; - } - - /******************************************************************************* - - ** ** - ** ** - ** PLOTZOOM ** - ** ** - ** ** - *******************************************************************************/ - /** - * Creates an plotZoom instance, which can handle drag and scroll events - * @constructor plotZoom - * @param {function} chart a function instance of one of the d3sm plots (e.g. bar, boxwhisker, bubbleHeatmap, violin, etc) - * @param {axis} xAxis the axis instance responsible for the x axis - * @param {axis} yAxis the axis instance responsible for the y axis - * @namespace plotZoom - * @returns {function} zoom - */ - function multiPlotZoom(chart) { - var - /** - * The event on which to fire - * (see {@link plotZoom#eventType}) - * @param {string} eventType which event it should handle. Currently supports scroll and wheel - * @memberof plotZoom# - * @property - */ - eventType, - - /** - * A scaling factor for the wheel "speed" - * (see {@link plotZoom#wheelSpeed}) - * @param {number} [wheelSpeed=20] scales the wheel translation by wheelSpeed - * @memberof plotZoom# - * @property - */ - wheelSpeed = 20, - - /** - * The orientation in which to allow scrolling: 'horizontal', 'vertical', or '2D' - * (see {@link plotZoom#orient}) - * @param {string} [orient=chart.orient() || 'horizontal'] - * @memberof plotZoom# - * @property - */ - orient = chart.orient == undefined ? 'horizontal' : chart.orient(), - - /** - * The max distance allowed to scroll in the x direction - * (see {@link plotZoom#xLock}) - * @param {number} [xLock=chart.spaceX()] ideally chart.overflowQ() == true and this value is the - * bounding rect across all elements in the chart minus the space in which to show. - * @memberof plotZoom# - * @property - */ - xLock = chart.spaceX(), - - /** - * The max distance allowed to scroll in the y direction - * (see {@link plotZoom#yLock}) - * @param {number} [yLock=chart.spaceY()] ideally chart.overflowQ() == true and this value is the - * bounding rect across all elements in the chart minus the space in which to show. - * @memberof plotZoom# - * @property - */ - yLock = chart.spaceY(), - chartSel = chart.selection(), - svg = d3.select(chartSel.thisSVG()), - xComponents = [], - yComponents = []; - - /** - * Gets or sets the event type in which to respond - * (see {@link plotZoom#eventType}) - * @param {string} [_=none] should be 'drag' or 'wheel' - * @returns {zoom | string} - * @memberof plotZoom - * @property - * by default plotZoom=undefined - */ - zoom.eventType = function (_) { - return arguments.length ? (eventType = _, zoom) : eventType; - }; - /** - * Gets or sets the wheel speed in which to scale the wheel scroll transform - * (see {@link plotZoom#wheelSpeed}) - * @param {number} [_=none] - * @returns {zoom | number} - * @memberof plotZoom - * @property - * by default wheelSpeed=20 - */ - zoom.wheelSpeed = function (_) { - return arguments.length ? (wheelSpeed = _, zoom) : wheelSpeed; - }; - /** - * Gets or sets the orientation in which items are manipulated - * (see {@link plotZoom#orient}) - * @param {string} [_=none] should be horizontal, vertical, or 2D - * @returns {zoom | string} - * @memberof plotZoom - * @property - * by default orient=chart.orient() || 'horizontal' - */ - zoom.orient = function (_) { - return arguments.length ? (orient = _, zoom) : orient; - }; - - /** - * Gets or sets the max distance in which to scroll X - * (see {@link plotZoom#xLock}) - * @param {number} [_=none] should be a positive value - * @returns {zoom | number} - * @memberof plotZoom - * @property - * by default xLock=chart.spaceX() - */ - zoom.xLock = function (_) { - return arguments.length ? (xLock = _, zoom) : xLock; - }; - /** - * Gets or sets the max distance in which to scroll Y - * (see {@link plotZoom#yLock}) - * @param {number} [_=none] should be a positive value - * @returns {zoom | number} - * @memberof plotZoom - * @property - * by default yLock=chart.spaceY() - */ - zoom.yLock = function (_) { - return arguments.length ? (yLock = _, zoom) : yLock; - }; - - zoom.xComponents = function (_) { - return arguments.length ? (xComponents = _, zoom) : xComponents; - }; - zoom.yComponents = function (_) { - return arguments.length ? (yComponents = _, zoom) : yComponents; - }; - - function setLocks() { - var chartObjSel = chartSel.select('.' + hypenate(chart.namespace(), 'object-container')); - var chartObjTrans = getTranslation(chartObjSel.attr('transform')); - var cos = chartObjSel.attr('transform', 'translate(0,0)'); - - xLock = chartSel.node().getBBox().width - chart.spaceX(); // * .9 - yLock = chartSel.node().getBBox().height - chart.spaceY(); // * .9 - cos.attr('transform', 'translate(' + chartObjTrans[0] + ',' + chartObjTrans[1] + ')'); - log('plotZoom', 'setLocks', { xLock: xLock, yLock: yLock }); - } - - /** - * Sets the x and y locks (how far one can scroll) - * (see {@link plotZoom#xLock} and {@link plotZoom#yLock}) - * @function plotZoom.setLocks - * @returns {undefined} - * @memberof plotZoom - * @property - */ - zoom.setLocks = setLocks; - - function zoom() { - setLocks(); - - var xComponentsSel = xComponents.map(function (d, i) { - return d.selection(); - }), - yComponentsSel = yComponents.map(function (d, i) { - return d.selection(); - }); - - var horizontalQ, verticalQ; - if (orient == '2D') { - horizontalQ = true;verticalQ = true; - } - if (orient == 'horizontal') { - horizontalQ = true;verticalQ = false; - } - if (orient == 'vertical') { - verticalQ = true;horizontalQ = false; - } - - // capture transform event - var transform = d3.event.transform; - - var chartBox = chartSel.node().getBBox(); - var xComponentsBox = xComponentsSel.map(function (d, i) { - return d.node().getBBox(); - }); - var yComponentsBox = xComponentsSel.map(function (d, i) { - return d.node().getBBox(); - }); - - var chartWidth = chartBox.width - chartBox.x; - var chartHeight = chartBox.height - chartBox.y; - - // enable wheel event - if (eventType == "wheel") { - var e = d3.event; - // prevent page scrolling - e.preventDefault(); - // event delta is very very slow, so speed it up with wheel speed - var w = d3.event.deltaY * wheelSpeed; - var shiftQ = d3.event.shiftKey; - - // d3 has no way to make custom transform, so make an object and add - // the necessary functions to make wheel event compatible with drag events - if (orient == '2D') { - transform = shiftQ ? { k: 1, x: w, y: 0 } : { k: 1, x: 0, y: w }; - } else { - transform = horizontalQ ? { k: 1, x: w, y: 0 } : { k: 1, x: 0, y: w }; - } - // * -1 is invert - transform.applyX = function (x) { - return x * this.k + this.x * -1; - }; - transform.applyY = function (y) { - return y * this.k + this.y * -1; - }; - } - - var chartObjSel = chartSel.select('.' + hypenate(chart.namespace(), 'object-container')); - var xComponentObjSel = xComponentsSel.map(function (d, i) { - return d.select('.' + hypenate(xComponents[i].namespace(), 'object-container')); - }); - var yComponentObjSel = yComponentsSel.map(function (d, i) { - return d.select('.' + hypenate(yComponents[i].namespace(), 'object-container')); - }); - - var chartObjTrans = getTranslation(chartObjSel.attr('transform')); - var xComponentsObjTrans = xComponentObjSel.map(function (d, i) { - return getTranslation(d.attr('transform')); - }); - var yComponentsObjTrans = yComponentObjSel.map(function (d, i) { - return getTranslation(d.attr('transform')); - }); - - var x = horizontalQ ? transform.applyX(chartObjTrans[0]) : 0; - if (horizontalQ) { - x = x < -xLock ? (transform.x = 0, -xLock) : (transform.x = 0, Math.min(x, 0)); - } - - var y = verticalQ ? transform.applyY(chartObjTrans[1]) : 0; - if (verticalQ) { - y = y < -yLock ? (transform.y = 0, -yLock) : (transform.y = 0, Math.min(y, 0)); - } - - chartObjSel.attr('transform', 'translate(' + x + ',' + y + ')'); - if (horizontalQ) { - // xAxisObjSel.attr('transform', 'translate('+x+','+0+')') - xComponentObjSel.map(function (d, i) { - d.attr('transform', 'translate(' + x + ',' + 0 + ')'); - }); - } - if (verticalQ) { - // yAxisObjSel.attr('transform', 'translate('+0+','+y+')') - yComponentObjSel.map(function (d, i) { - d.attr('transform', 'translate(' + 0 + ',' + y + ')'); - }); - } - } - - zoom.reset = function () { - - var chartObjSel = chartSel.select('.' + hypenate(chart.namespace(), 'object-container')); - var xAxisObjSel = xAxisSel.select('.' + hypenate(xAxis.namespace(), 'object-container')); - var yAxisObjSel = yAxisSel.select('.' + hypenate(yAxis.namespace(), 'object-container')); - chartObjSel.attr('transform', 'translate(' + 0 + ',' + 0 + ')'); - xAxisObjSel.attr('transform', 'translate(' + 0 + ',' + 0 + ')'); - yAxisObjSel.attr('transform', 'translate(' + 0 + ',' + 0 + ')'); - }; - - return zoom; - } - - /******************************************************************************* - ** ** - ** ** - ** VIOLIN ** - ** ** - ** ** - *******************************************************************************/ - - /** - * Creates a violin - * - * {@link https://sumneuron.gitlab.io/d3sm/demos/basic-violins/index.html Demo} - * @constructor violin - * @param {d3.selection} selection - * @namespace violin - * @returns {function} violin - */ - function violin(selection) { - var - /** - * Data to plot. Assumed to be a object, where each key corresponds to a violin - * (see {@link violin#data}) - * @param {Object} [data=undefined] - * @memberof violin# - * @property - */ - data, - - /** - * Which direction to render the bars in - * (see {@link violin#orient}) - * @param {number} [orient='horizontal'] - * @memberof violin# - * @property - */ - orient = 'horizontal', - - /** - * Amount of horizontal space (in pixels) avaible to render the violin in - * (see {@link violin#spaceX}) - * @param {number} [spaceX=undefined] - * @memberof violin# - * @property - */ - spaceX, - - /** - * Amount of vertical space (in pixels) avaible to render the violin in - * (see {@link violin.spaceY}) - * @param {number} [spaceY=undefined] - * @memberof violin# - * @property - */ - spaceY, - - /** - * Whether or not to allow violin to render elements pass the main spatial dimension - * given the orientation (see {@link violin#orient}), where {@link violin#orient}="horizontal" - * the main dimension is {@link violin#spaceX} and where {@link violin#orient}="vertical" - * the main dimension is {@link violin#spaceY} - * @param {boolean} [overflowQ=false] - * @memberof violin# - * @property - */ - overflowQ = true, - - /** - * Whether or not to display points inside the points - * @param {boolean} [pointsQ=false] - * @memberof violin# - * @property - */ - pointsQ = true, - - /** - * An array - putatively of other arrays - depicting how bars should be arranged - * @param {Array[]} [grouping=undefined] - * @memberof violin# - * @property - */ - grouping, - - /** - * How to get the value of the violin - * @param {function} [valueExtractor=function(key, index) { return data[key] }] - * @memberof violin# - * @property - */ - valueExtractor = function valueExtractor(key, index) { - return data[key]; - }, - - /** - * How to sort the bars - if {@link violin#grouping} is not provided. - * @param {function} [sortingFunction=function(keyA, keyB) {return d3.descending(data[keyA], data[keyB])}] - * @memberof violin# - * @property - */ - sortingFunction = function sortingFunction(keyA, keyB) { - return d3.descending(data[keyA], data[keyB]); - }, - - - /** - * The scale for which violin values should be transformed by - * @param {d3.scale} [scale=d3.scaleLinear] - * @memberof violin# - * @property - */ - scale = d3.scaleLinear(), - - /** - * The padding for the domain of the scale (see {@link violin#scale}) - * @param {number} [domainPadding=0.5] - * @memberof violin# - * @property - */ - domainPadding = 0.5, - - /** - * Default space for the spacer (percentage) of main dimension given the orientation - * (see {@link violin#orient}), where {@link violin#orient}="horizontal" - * the main dimension is {@link violin#spaceX} and where {@link violin#orient}="vertical" - * the main dimension is {@link violin#spaceY} between bars - * @param {number} [objectSpacer=0.05] - * @memberof violin# - * @property - */ - objectSpacer = 0.05, - - /** - * The minimum size that an object can be - * @param {number} [minObjectSize=50] - * @memberof violin# - * @property - */ - minObjectSize = 50, - - /** - * The maximum size that an object can be - * @param {number} [maxObjectSize=100] - * @memberof violin# - * @property - */ - maxObjectSize = 100, - - - /** - * The stroke width of the bars - * @param {number} [barStrokeWidth=2] - * @memberof violin# - * @property - */ - objectStrokeWidth = 2, - - /** - * Instance of ColorFunction - * @param {function} [colorFunction = colorFunction()] - * @memberof violin# - * @property - */ - colorFunction$$1 = colorFunction(), - - /** - * Instance of ColorFunction modified by a scale for the points - * @param {function} [pointColorFunc = colorFunction()] - * @memberof violin# - * @property - */ - pointColorFunc = function pointColorFunc(d, type, base, min, max) { - var minMaxHexScale = d3.scaleLinear().domain([min, max]).range([-0.25, 0.05]); - var scaledColor = modifyHexidecimalColorLuminance(base.replace('#', ''), minMaxHexScale(d)); - var mod = type == "stroke" ? 0 : 0.25; - return modifyHexidecimalColorLuminance(scaledColor.replace('#', ''), mod); - }, - - - /** - * The radius of a point - * @param {number} [pointRadius=3] - * @memberof violin# - * @property - */ - pointRadius = 3, - - /** - * The stroke width of the oints - * @param {number} [pointStrokeWidth=2] - * @memberof violin# - * @property - */ - pointStrokeWidth = 2, - - - /** - * Color of the background - * @param {string} [backgroundFill="transparent"] - * @memberof violin# - * @property - */ - backgroundFill = 'transparent', - - /** - * Namespace for all items made by this instance of violin - * @param {string} [namespace="d3sm-violin"] - * @memberof violin# - * @property - */ - namespace = 'd3sm-violin', - - /** - * Class name for violin container ( element) - * @param {string} [objectClass="violin"] - * @memberof violin# - * @property - */ - objectClass = 'violin', - - /** - * Duration of all transitions of this element - * @param {number} [transitionDuration=1000] - * @memberof violin# - * @property - */ - transitionDuration = 1000, - - /** - * Easing function for transitions - * @param {d3.ease} [easeFunc=d3.easeExp] - * @memberof violin# - * @property - */ - easeFunc = d3.easeExp, - - - /** - * The keys corresponding to each quartile - * @param {string[]} [quartileKeys=["Q0", "Q1", "Q2", "Q3", "Q4"]] - * @memberof violin# - * @property - */ - quartileKeys = ["Q0", "Q1", "Q2", "Q3", "Q4"], - - - /** - * The keys of the bars - * @param {string[]} [violinKeys=undefined] - * @memberof violin# - * @property - */ - violinKeys, - - /** - * The values of the bars - * @param {number[]} [violinValues=undefined] - * @memberof violin# - * @property - */ - violinValues, - - /** - * The objectSize (actual width) used by the bars - * @param {number} [objectSize=undefined] - * @memberof violin# - * @property - */ - objectSize, - - /** - * The spacerSize (actual width) used by the spacers between the bars - * @param {number} [spacerSize=undefined] - * @memberof violin# - * @property - */ - spacerSize, - - - /** - * Instance of Tooltip - * @param {function} [tooltip=tooltip()] - * @memberof violin# - * @property - */ - tooltip$$1 = tooltip().keys([quartileKeys[4], quartileKeys[3], quartileKeys[2], quartileKeys[1], quartileKeys[0]]), - pointsTooltip = tooltip(), - - // pointKeyExtractor = function(violinKey, violinData, violinValues) {return d3.keys(violinValues[violinKey].values)}, - // pointValueExtractor = function(pointKey, violinKey, violinData, violinValues) {return violinValues[violinKey].values[pointKey]}, - - - /** - * Function which given the key of the violin and that key's associated value - * returns the object consiting of the points of the violin - * (see {@link violin#violinPointsExtractor}) - * @param {Object} [violinPointsExtractor=function(violinKey, violinData) { return violinData.points }] - * @memberof violin# - * @property - */ - violinPointsExtractor = function violinPointsExtractor(violinKey, violinData) { - return violinData.points; - }, - - /** - * Function which given the key of the current point and the object of points for the - * violin, returns the numerical value of the point - * (see {@link violin#violinPointValueExtractor}) - * @param {Object} [violinPointValueExtractor=function(violinPointKey, violinPointData) { return violinPointData[violinPointKey].value }] - * @memberof violin# - * @property - */ - violinPointValueExtractor = function violinPointValueExtractor(violinPointKey, violinPointData) { - return violinPointData[violinPointKey].value; - }; - - /** - * Gets or sets the violinPointsExtractor - * @param {function} [_=none] - * @returns {violin | function} - * @memberof violin - * @property - * by default violinPointsExtractor = function(violinKey, violinData) { return violinData.points } - */ - violin.violinPointsExtractor = function (_) { - return arguments.length ? (violinPointsExtractor = _, violin) : violinPointsExtractor; - }; - /** - * Gets or sets the violinPointValueExtractor - * @param {function} [_=none] - * @returns {violin | function} - * @memberof violin - * @property - * by default violinPointsExtractor = function(pointKey, violinKey, violinData, violinValues) {return violinValues[violinKey].values[pointKey]} - */ - violin.violinPointValueExtractor = function (_) { - return arguments.length ? (violinPointValueExtractor = _, violin) : violinPointValueExtractor; - }; - - /** - * Gets or sets the selection in which items are manipulated - * @param {d3.selection} [_=none] - * @returns {violin | d3.selection} - * @memberof violin - * @property - * by default selection = selection - */ - violin.selection = function (_) { - return arguments.length ? (selection = _, violin) : selection; - }; - /** - * Gets or sets the data - * (see {@link violin#data}) - * @param {number} [_=none] - * @returns {violin | object} - * @memberof violin - * @property - */ - violin.data = function (_) { - return arguments.length ? (data = _, violin) : data; - }; - /** - * Gets or sets the orient of the boxes - * (see {@link violin#orient}) - * @param {number} [_=none] - * @returns {violin | object} - * @memberof violin - * @property - */ - violin.orient = function (_) { - return arguments.length ? (orient = _, violin) : orient; - }; - /** - * Gets or sets the amount of horizontal space in which items are manipulated - * (see {@link violin#spaceX}) - * @param {number} [_=none] should be a number > 0 - * @returns {violin | number} - * @memberof violin - * @property - * by default spaceX = undefined - */ - violin.spaceX = function (_) { - return arguments.length ? (spaceX = _, violin) : spaceX; - }; - /** - * Gets or sets the amount of vertical space in which items are manipulated - * (see {@link violin#spaceY}) - * @param {number} [_=none] should be a number > 0 - * @returns {violin | number} - * @memberof violin - * @property - * by default spaceY = undefined - */ - violin.spaceY = function (_) { - return arguments.length ? (spaceY = _, violin) : spaceY; - }; - - /** - * Gets / sets whether or not violin is allowed to go beyond specified dimensions - * (see {@link violin#overflowQ}) - * @param {boolean} [_=none] - * @returns {violin | boolean} - * @memberof violin - * @property - * by default overflowQ = false - */ - violin.overflowQ = function (_) { - return arguments.length ? (overflowQ = _, violin) : overflowQ; - }; - /** - * Gets / sets whether or not to plot points with the violins - * (see {@link violin#pointsQ}) - * @param {boolean} [_=none] - * @returns {violin | boolean} - * @memberof violin - * @property - * by default pointsQ = false - */ - violin.pointsQ = function (_) { - return arguments.length ? (pointsQ = _, violin) : pointsQ; - }; - - /** - * Gets / sets the grouping of the boxes - * (see {@link violin#grouping}) - * @param {Array[]} [_=none] - * @returns {violin | Array[]} - * @memberof violin - * @property - * by default grouping = undefined - */ - violin.grouping = function (_) { - return arguments.length ? (grouping = _, violin) : grouping; - }; - /** - * Gets / sets the valueExtractor - * (see {@link violin#valueExtractor}) - * @param {function} [_=none] - * @returns {violin | function} - * @memberof violin - * @property - */ - violin.valueExtractor = function (_) { - return arguments.length ? (valueExtractor = _, violin) : valueExtractor; - }; - /** - * Gets / sets the sortingFunction - * (see {@link violin#sortingFunction}) - * @param {function} [_=none] - * @returns {violin | function} - * @memberof violin - * @property - */ - violin.sortingFunction = function (_) { - return arguments.length ? (sortingFunction = _, violin) : sortingFunction; - }; - - /** - * Gets / sets the scale for which the violin values should be transformed by - * (see {@link violin#scale}) - * @param {d3.scale} [_=none] - * @returns {violin | d3.scale} - * @memberof violin - * @property - * by default scale = d3.scaleLinear() - */ - violin.scale = function (_) { - return arguments.length ? (scale = _, violin) : scale; - }; - /** - * Gets / sets the padding for the domain of the scale - * (see {@link violin#domainPadding}) - * @param {number} [_=none] - * @returns {violin | number} - * @memberof violin - * @property - * by default domainPadding = 0.5 - */ - violin.domainPadding = function (_) { - return arguments.length ? (domainPadding = _, violin) : domainPadding; - }; - - /** - * Gets / sets objectSpacer - * (see {@link violin#objectSpacer}) - * @param {number} [_=none] - * @returns {violin | number} - * @memberof violin - * @property - * by default objectSpacer = 0.05 - */ - violin.objectSpacer = function (_) { - return arguments.length ? (objectSpacer = _, violin) : objectSpacer; - }; - /** - * Gets / sets the minObjectSize - * (see {@link violin#minObjectSize}) - * @param {number} [_=none] - * @returns {violin | number} - * @memberof violin - * @property - * by default minObjectSize = 15 - */ - violin.minObjectSize = function (_) { - return arguments.length ? (minObjectSize = _, violin) : minObjectSize; - }; - /** - * Gets / sets the maxObjectSize - * (see {@link violin#maxObjectSize}) - * @param {number} [_=none] - * @returns {violin | number} - * @memberof violin - * @property - * by default maxObjectSize = 50 - */ - violin.maxObjectSize = function (_) { - return arguments.length ? (maxObjectSize = _, violin) : maxObjectSize; - }; - - /** - * Gets / sets the objectStrokeWidth - * (see {@link violin#objectStrokeWidth}) - * @param {number} [_=none] - * @returns {violin | number} - * @memberof violin - * @property - * by default objectStrokeWidth = 2 - */ - violin.objectStrokeWidth = function (_) { - return arguments.length ? (objectStrokeWidth = _, violin) : objectStrokeWidth; - }; - - /** - * Gets / sets the colorFunction - * (see {@link violin#colorFunction}) - * @param {colorFunction} [_=none] - * @returns {violin | colorFunction} - * @memberof violin - * @property - * by default colorFunction = colorFunction() - */ - violin.colorFunction = function (_) { - return arguments.length ? (colorFunction$$1 = _, violin) : colorFunction$$1; - }; - /** - * Gets / sets the colorFunction - * (see {@link violin#colorFunction}) - * @param {colorFunction} [_=none] - * @returns {violin | colorFunction} - * @memberof violin - * @property - * by default colorFunction = colorFunction() - */ - violin.pointColorFunc = function (_) { - return arguments.length ? (pointColorFunc = _, violin) : pointColorFunc; - }; - - /** - * Gets / sets the pointRadius - * (see {@link violin#pointRadius}) - * @param {number} [_=none] - * @returns {violin | number} - * @memberof violin - * @property - * by default pointRadius = 2 - */ - violin.pointRadius = function (_) { - return arguments.length ? (pointRadius = _, violin) : pointRadius; - }; - /** - * Gets / sets the pointStrokeWidth - * (see {@link violin#pointStrokeWidth}) - * @param {number} [_=none] - * @returns {violin | number} - * @memberof violin - * @property - * by default pointStrokeWidth = 2 - */ - violin.pointStrokeWidth = function (_) { - return arguments.length ? (pointStrokeWidth = _, violin) : pointStrokeWidth; - }; - - /** - * Gets / sets the backgroundFill - * (see {@link violin#backgroundFill}) - * @param {string} [_=none] - * @returns {violin | string} - * @memberof violin - * @property - * by default backgroundFill = 'transparent' - */ - violin.backgroundFill = function (_) { - return arguments.length ? (backgroundFill = _, violin) : backgroundFill; - }; - /** - * Gets / sets the namespace - * (see {@link violin#namespace}) - * @param {string} [_=none] - * @returns {violin | string} - * @memberof violin - * @property - * by default namespace = 'd3sm-violin' - */ - violin.namespace = function (_) { - return arguments.length ? (namespace = _, violin) : namespace; - }; - /** - * Gets / sets the objectClass - * (see {@link violin#objectClass}) - * @param {string} [_=none] - * @returns {violin | string} - * @memberof violin - * @property - * by default objectClass = 'tick-group' - */ - violin.objectClass = function (_) { - return arguments.length ? (objectClass = _, violin) : objectClass; - }; - - /** - * Gets / sets the transitionDuration - * (see {@link violin#transitionDuration}) - * @param {number} [_=none] - * @returns {violin | number} - * @memberof violin - * @property - * by default transitionDuration = 1000 - */ - violin.transitionDuration = function (_) { - return arguments.length ? (transitionDuration = _, violin) : transitionDuration; - }; - /** - * Gets / sets the easeFunc - * (see {@link violin#easeFunc}) - * @param {d3.ease} [_=none] - * @returns {violin | d3.ease} - * @memberof violin - * @property - * by default easeFunc = d3.easeExp - */ - violin.easeFunc = function (_) { - return arguments.length ? (easeFunc = _, violin) : easeFunc; - }; - - /** - * Gets / sets the quartileKey - * (see {@link violin#quartileKey}) - * @param {string} [_=none] - * @returns {violin | string} - * @memberof violin - * @property - * by default quartileKey = "quartiles" - */ - violin.quartileKey = function (_) { - return arguments.length ? (quartileKey = _, violin) : quartileKey; - }; - /** - * Gets / sets the quartileKeys - * (see {@link violin#quartileKeys}) - * @param {string[]} [_=none] - * @returns {violin | string[]} - * @memberof violin - * @property - * by default quartileKeys = ["Q0","Q1","Q2","Q3","Q4"] - */ - violin.quartileKeys = function (_) { - return arguments.length ? (quartileKeys = _, violin) : quartileKeys; - }; - - /** - * Gets / sets the violinKeys - * (see {@link violin#violinKeys}) - * @param {string[]} [_=none] - * @returns {violin | string[]} - * @memberof violin - * @property - * by default violinKeys = undefined - */ - violin.violinKeys = function (_) { - return arguments.length ? (violinKeys = _, violin) : violinKeys; - }; - /** - * Gets / sets the violinValues - * (see {@link violin#violinValues}) - * @param {Object[]} [_=none] - * @returns {violin | Object[]} - * @memberof violin - * @property - * by default violinValues = undefined - */ - violin.violinValues = function (_) { - return arguments.length ? (violinValues = _, violin) : violinValues; - }; - - /** - * Gets / sets the objectSize - * (see {@link violin#objectSize}) - * @param {number} [_=none] - * @returns {violin | number} - * @memberof violin - * @property - * by default objectSize = undefined - */ - violin.objectSize = function (_) { - return arguments.length ? (objectSize = _, violin) : objectSize; - }; - /** - * Gets / sets the spacerSize - * (see {@link violin#spacerSize}) - * @param {number} [_=none] - * @returns {violin | number} - * @memberof violin - * @property - * by default spacerSize = undefined - */ - violin.spacerSize = function (_) { - return arguments.length ? (spacerSize = _, violin) : spacerSize; - }; - /** - * Gets / sets the tooltip - * (see {@link violin#tooltip}) - * @param {tooltip} [_=none] - * @returns {violin | tooltip} - * @memberof violin - * @property - * by default tooltip = tooltip() - */ - violin.tooltip = function (_) { - return arguments.length ? (tooltip$$1 = _, violin) : tooltip$$1; - }; - /** - * Gets / sets the pointsTooltip - * (see {@link violin#pointsTooltip}) - * @param {tooltip} [_=none] - * @returns {violin | tooltip} - * @memberof violin - * @property - * by default pointsTooltip = tooltip() - */ - violin.pointsTooltip = function (_) { - return arguments.length ? (pointsTooltip = _, violin) : pointsTooltip; - }; - - function violin() { - var _ref, _ref2, _ref3; - - // for convenience in handling orientation specific values - var horizontalQ = orient == 'horizontal' ? true : false; - - // background cliping rectangle - var bgcpRect = { x: 0, y: 0, width: spaceX, height: spaceY }; - var container = setupContainer(selection, namespace, bgcpRect, backgroundFill); - - // if grouping is undefined sort violinKeys by sortingFunction - var ordered = grouping == undefined ? d3.keys(data).sort(sortingFunction) : grouping; - - // console.log(ordered) - - violinKeys = flatten(ordered); - - var calcValues = neededViolinValues().horizontalQ(horizontalQ).quartileKeys(quartileKeys).violinPointsExtractor(violinPointsExtractor).violinPointValueExtractor(violinPointValueExtractor); - - // augment valus - violinKeys.map(function (vk, i) { - calcValues(vk, data); - }); - - var numberOfObjects = violinKeys.length; - - var min = (_ref = []).concat.apply(_ref, toConsumableArray(violinKeys.map(function (k, i) { - return data[k].quartiles[quartileKeys[0]]; - }))); - var max = (_ref2 = []).concat.apply(_ref2, toConsumableArray(violinKeys.map(function (k, i) { - return data[k].quartiles[quartileKeys[quartileKeys.length - 1]]; - }))); - var extent = [Math.min.apply(Math, toConsumableArray(min)) - domainPadding, Math.max.apply(Math, toConsumableArray(max)) + domainPadding]; - // console.log(extent, violinValues, ordered) - - // set the scale - scale.domain(extent).range(horizontalQ ? [0, spaceY] : [0, spaceX]); - var space = horizontalQ ? spaceX : spaceY; - // calculate object size - objectSize = calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ); - // calculate spacer size if needed - spacerSize = calculateWidthOfSpacer(ordered, space, objectSize, numberOfObjects, objectSpacer, overflowQ); - // make the nested groups - var spacerFunction = groupingSpacer().horizontalQ(horizontalQ).scale(scale).moveby('category').numberOfObjects(numberOfObjects).objectClass(objectClass).objectSize(objectSize).spacerSize(spacerSize).transitionDuration(transitionDuration).easeFunc(easeFunc).namespace(namespace); - - // move stuff - spacerFunction(container, ordered, 0); - // console.log(violinKeys, ordered, container.selectAll('g:not(.to-remove).'+objectClass).nodes()) - - // for color function - var parentIndexArray = []; - container.selectAll('g:not(.to-remove).' + objectClass).each(function (d, i) { - if (hasQ(violinKeys, d)) { - parentIndexArray.push(Number(d3.select(this).attr('parent-index'))); - } - }); - - // update color function - colorFunction$$1 = colorFunction$$1.colorBy() == 'index' ? colorFunction$$1.dataExtent([0, Math.max.apply(Math, parentIndexArray)]) : colorFunction$$1.dataExtent(extent); - - /* violiin specific needs */ - - var frequencyMax = Math.max.apply(Math, toConsumableArray((_ref3 = []).concat.apply(_ref3, toConsumableArray(violinKeys.map(function (k, i) { - return d3.max(data[k].frequencies); - }))))); - var vScale = d3.scaleLinear().domain([0, frequencyMax]).range([0, objectSize / 2]); - - var lArea = d3.line().x(function (d, i) { - return horizontalQ ? -vScale(d.x) : scale(d.x); - }).y(function (d, i) { - return horizontalQ ? scale(extent[1]) - scale(d.y) : -vScale(d.y); - }).curve(d3.curveBasis); - var rArea = d3.line().x(function (d, i) { - return horizontalQ ? vScale(d.x) : scale(d.x); - }).y(function (d, i) { - return horizontalQ ? scale(extent[1]) - scale(d.y) : vScale(d.y); - }).curve(d3.curveBasis); - - container.selectAll('g:not(.to-remove).' + objectClass).each(function (key, i) { - var t = d3.select(this), - currentData = data[key]; - // needed because bug in selecting .to-remove - if (!hasQ(violinKeys, key)) { - return; - } - var i = t.attr('parent-index') == undefined ? i : t.attr('parent-index'), - fillColor = colorFunction$$1(key, currentData, i, 'fill'), - // prevent duplicate computation - strokeColor = colorFunction$$1(key, currentData, i, 'stroke'), - area = safeSelect(t, 'g', 'area'), - la = safeSelect(area, 'path', 'left'), - ra = safeSelect(area, 'path', 'right'), - quarts = safeSelect(t, 'g', 'quarts'), - lq3 = safeSelect(quarts, 'line', 'q3'), - lq1 = safeSelect(quarts, 'line', 'q1'), - q3 = currentData.quartiles[quartileKeys[3]], - q2 = currentData.quartiles[quartileKeys[2]], - q1 = currentData.quartiles[quartileKeys[1]]; - - t.attr('transform', horizontalQ ? 'translate(' + objectSize / 2 + ',0)' : 'translate(0,' + objectSize / 2 + ')'); - // draw curve - la.transition().duration(transitionDuration).attr('d', function (dd, ii) { - return lArea(currentData.contour); - }).attr('fill', fillColor).attr('stroke', strokeColor).attr('stroke-width', objectStrokeWidth); - - ra.transition().duration(transitionDuration).attr('d', function (dd, ii) { - return rArea(currentData.contour); - }).attr('fill', fillColor).attr('stroke', strokeColor).attr('stroke-width', objectStrokeWidth); - - area.node().addEventListener('mouseover', function (dd, ii) { - container.selectAll('g.' + objectClass).style('opacity', 0.2); - t.style('opacity', 1); - la.attr('stroke-width', objectStrokeWidth * 2); - ra.attr('stroke-width', objectStrokeWidth * 2); - }); - area.node().addEventListener('mouseout', function (dd, ii) { - container.selectAll('g.' + objectClass).style('opacity', 1); - la.attr('stroke-width', objectStrokeWidth); - ra.attr('stroke-width', objectStrokeWidth); - }); - - if (pointsQ) { - var ptsContainer = safeSelect(t, 'g', 'points'); - var pts = ptsContainer.selectAll('.point').data(currentData.pointKeys); - pts.on('mouseover', null); - - var ptsExit = pts.exit().transition().ease(easeFunc).duration(transitionDuration).attr('r', 0).attr('cy', horizontalQ ? scale(extent[1]) - scale(q2) : vScale(0)).attr('cx', horizontalQ ? vScale(0) : scale(q2)).remove(); - - var ptsEnter = pts.enter().append('circle').attr('class', 'point').attr('r', 0).attr('cx', horizontalQ ? 0 : scale(q2)).attr('cy', horizontalQ ? scale(q2) : 0); - - pts = pts.merge(ptsEnter); - - // console.log(pointsTooltip.header()) - - var pTTips = tooltip().selection(pts).data(violinPointsExtractor(key, currentData)).header(pointsTooltip.header()).keys(pointsTooltip.keys()).values(pointsTooltip.values()); - - pTTips(); - - var pMin = d3.min(currentData.pointValues), - pMax = d3.max(currentData.pointValues); - - pts.transition().duration(transitionDuration).ease(easeFunc).attr('r', pointRadius).attr('cy', function (pointKey, ii) { - var dd = currentData.pointValues[ii]; - if (horizontalQ) { - return scale(extent[1]) - scale(dd); - } - var j = whichBin(currentData.binned, dd); - var r = Math.random(); - var n = vScale(r * currentData.frequencies[j] * 0.5); - var k = Math.random() > 0.5 ? n : -n; - return k; - }).attr('cx', function (pointKey, ii) { - var dd = currentData.pointValues[ii]; - if (horizontalQ) { - var j = whichBin(currentData.binned, dd); - var r = Math.random(); - var n = vScale(r * currentData.frequencies[j] * 0.5); - var k = Math.random() > 0.5 ? n : -n; - return k; - } - return scale(dd); - }).attr('stroke', function (dd, ii) { - var dd = currentData.pointValues[ii];return pointColorFunc(dd, 'stroke', strokeColor, pMin, pMax); - }).attr('fill', function (dd, ii) { - var dd = currentData.pointValues[ii];return pointColorFunc(dd, 'fill', strokeColor, pMin, pMax); - }).attr('stroke-width', pointStrokeWidth); - - ptsContainer.selectAll('circle.point').on('mouseover', function (dd, ii) { - container.selectAll('g.' + objectClass).style('opacity', 0.2); - t.style('opacity', 1); - la.attr('stroke-width', objectStrokeWidth * 2); - ra.attr('stroke-width', objectStrokeWidth * 2); - - container.selectAll('.point').style('opacity', 0.2); - d3.select(this).style('opacity', 1).attr('r', pointRadius * 2).attr('stroke-width', pointStrokeWidth * 2); - }); - ptsContainer.selectAll('circle.point').on('mouseout', function (dd, ii) { - var e = document.createEvent('SVGEvents'); - e.initEvent('mouseout', true, true); - area.node().dispatchEvent(e); - - container.selectAll('.point').style('opacity', 1); - d3.select(this).attr('stroke-width', pointStrokeWidth).attr('r', pointRadius); - }); - } else { - cV.selectAll('.point').transition().duration(transitionDuration).ease(easeFunc).attr('r', 0).attr('cy', horizontalQ ? scale(extent[1]) - scale(q2) : vScale(0)).attr('cx', horizontalQ ? vScale(0) : scale(q2)).remove(); - } - }); - - tooltip$$1.selection(container.selectAll('g:not(.to-remove).' + objectClass + ' .area')); - if (tooltip$$1.data() == undefined) { - tooltip$$1.data(data); - } - tooltip$$1(); - if (tooltip$$1.values() == undefined) { - tooltip$$1.values([function (currentData, tooltipKey) { - return currentData['quartiles'][tooltipKey]; - }, function (currentData, tooltipKey) { - return currentData['quartiles'][tooltipKey]; - }, function (currentData, tooltipKey) { - return currentData['quartiles'][tooltipKey]; - }, function (currentData, tooltipKey) { - return currentData['quartiles'][tooltipKey]; - }, function (currentData, tooltipKey) { - return currentData['quartiles'][tooltipKey]; - }]); - } - } - - return violin; - } - - /** - * Produces the function which manipulates the violin data to have values needed - * for rendering the violins as svg. - * @returns {function} calculateViolinValues - * @namespace neededViolinValues - */ - function neededViolinValues() { - var - /** - * Whether or not the orientation of the violins are horizontal - * (see {@link violin#orient}) - * @param {Object} [horizontalQ=true] - * @memberof neededViolinValues# - * @property - */ - horizontalQ = true, - - /** - * Keys to be put into the quartiles if they need to be calculated. - * (see {@link violin#quartileKeys}) - * @param {Object} [quartileKeys=['Q0', 'Q1', 'Q2', 'Q3', 'Q4']] - * @memberof neededViolinValues# - * @property - */ - quartileKeys = ['Q0', 'Q1', 'Q2', 'Q3', 'Q4'], - - /** - * Function which given the key of the violin and that key's associated value - * returns the object consiting of the points of the violin - * (see {@link violin#violinPointsExtractor}) - * @param {Object} [violinPointsExtractor=function(violinKey, violinData) { return violinData.points }] - * @memberof neededViolinValues# - * @property - */ - violinPointsExtractor, - - /** - * Function which given the key of the current point and the object of points for the - * violin, returns the numerical value of the point - * (see {@link violin#violinPointValueExtractor}) - * @param {Object} [violinPointValueExtractor=function(violinPointKey, violinPointData) { return violinPointData[violinPointKey].value }] - * @memberof neededViolinValues# - * @property - */ - violinPointValueExtractor; - - /** - * Gets / sets the horizontalQ - * (see {@link violin#orient}) - * @param {boolean} [_=none] - * @returns {calculateViolinValues | boolean} - * @memberof calculateViolinValues - * @property - * - * by default horizontalQ = true - */ - calculateViolinValues.horizontalQ = function (_) { - return arguments.length ? (horizontalQ = _, calculateViolinValues) : horizontalQ; - }; - /** - * Gets / sets the quartileKeys - * (see {@link violin#quartileKeys}) - * @param {string[]} [_=none] - * @returns {calculateViolinValues | string[]} - * @memberof calculateViolinValues - * @property - * - * by default quartileKeys = ["Q0","Q1","Q2","Q3","Q4"] - */ - calculateViolinValues.quartileKeys = function (_) { - return arguments.length ? (quartileKeys = _, calculateViolinValues) : quartileKeys; - }; - /** - * Gets / sets the violinPointsExtractor - * (see {@link violin#violinPointsExtractor}) - * @param {function} [_=none] - * @returns {calculateViolinValues | function} - * @memberof calculateViolinValues - * @property - * - * by default violinPointsExtractor = function(violinKey, violinData) { return violinData.points } - */ - calculateViolinValues.violinPointsExtractor = function (_) { - return arguments.length ? (violinPointsExtractor = _, calculateViolinValues) : violinPointsExtractor; - }; - /** - * Gets / sets the violinPointValueExtractor - * (see {@link violin#violinPointValueExtractor}) - * @param {function} [_=none] - * @returns {calculateViolinValues | function} - * @memberof calculateViolinValues - * @property - * - * by default violinPointValueExtractor = function(violinPointKey, violinPointData) { return violinPointData[violinPointKey].value } - */ - calculateViolinValues.violinPointValueExtractor = function (_) { - return arguments.length ? (violinPointValueExtractor = _, calculateViolinValues) : violinPointValueExtractor; - }; - - /** - * The function produced by neededViolinValues. - * - * Adds the data need to render the violin as an svg - * @param {string} violinKey the key of the current violin - * @param {object} data the object consisting of violinKey - values (violin data) pairs - * @returns {none} this function manipulates the passed data object adding the following keys - * - * data[violinKey].binned // the binned values of the points - * - * data[violinKey].frequencies // the list consisting of the length of each bin - * - * data[violinKey].contour // the points depicting the contour of 1/2 of the violin - * - * data[violinKey].quartiles // the quartiles of the points' values - * - * data[violinKey].pointKeys // the keys associated with the points - * - * data[violinKey].pointValues // the numerical values of the points - * - * @memberof neededViolinValues# - * @property - */ - function calculateViolinValues(violinKey, data) { - // data for the current violin - var violinData = data[violinKey]; - // the object of points - var violinPoints = violinPointsExtractor(violinKey, violinData); - // - var violinPointsKeys = d3.keys(violinPoints); - // the numerical values of those points - var violinPointsValues = violinPointsKeys.map(function (pk, i) { - return violinPointValueExtractor(pk, violinPoints); - }); - - // quartiles of those points - var pointQuartiles = quartiles(violinPointsValues, quartileKeys); - - // binned points - var binned = d3.histogram()(violinPointsValues); - // length of bins - var frequencies = binned.map(function (bin) { - return bin.length; - }); - // min and max countour points for nice drawings - var minContourPoint = horizontalQ ? { x: 0, y: d3.min(violinPointsValues) } : { x: d3.min(violinPointsValues), y: 0 }; - var maxContourPoint = horizontalQ ? { x: 0, y: d3.max(violinPointsValues) } : { x: d3.max(violinPointsValues), y: 0 }; - var violinContourPoints = binned.map(function (bin, i) { - return horizontalQ ? { y: bin.length ? d3.median(bin) : d3.median([bin.x0, bin.x1]), x: frequencies[i] } : { x: bin.length ? d3.median(bin) : d3.median([bin.x0, bin.x1]), y: frequencies[i] }; - }); - // points along which to draw the violin shpe - violinContourPoints = [minContourPoint].concat(violinContourPoints).concat([maxContourPoint]); - - // set data - violinData.binned = binned; - violinData.frequencies = frequencies; - violinData.contour = violinContourPoints; - violinData.quartiles = pointQuartiles; - violinData.pointKeys = violinPointsKeys; - violinData.pointValues = violinPointsValues; - } - - return calculateViolinValues; - } - - function numericLegend(selection) { - - var min = 0, - max = 1, - spaceX, - spaceY, - colorFunction$$1 = colorFunction(), - namespace = 'd3sm-linear-vertical-gradient', - fontSize = 12, - backgroundFill = 'transparent', - textColor = 'black', - roundTo = 2; - - legend.min = function (_) { - return arguments.length ? (min = _, legend) : min; - }; - legend.max = function (_) { - return arguments.length ? (max = _, legend) : max; - }; - legend.spaceX = function (_) { - return arguments.length ? (spaceX = _, legend) : spaceX; - }; - legend.spaceY = function (_) { - return arguments.length ? (spaceY = _, legend) : spaceY; - }; - legend.namespace = function (_) { - return arguments.length ? (namespace = _, legend) : namespace; - }; - legend.fontSize = function (_) { - return arguments.length ? (fontSize = _, legend) : fontSize; - }; - legend.backgroundFill = function (_) { - return arguments.length ? (backgroundFill = _, legend) : backgroundFill; - }; - legend.colorFunction = function (_) { - return arguments.length ? (colorFunction$$1 = _, legend) : colorFunction$$1; - }; - legend.textColor = function (_) { - return arguments.length ? (textColor = _, legend) : textColor; - }; - legend.roundTo = function (_) { - return arguments.length ? (roundTo = _, legend) : roundTo; - }; - - function legend() { - // background cliping rectangle - var bgcpRect = { x: 0, y: 0, width: spaceX, height: spaceY }; - var container = setupContainer(selection, namespace, bgcpRect, backgroundFill); - - var defs = safeSelect(selection, 'defs'); - var linearGradient = safeSelect(defs, 'linearGradient').attr("x1", "0%").attr("y1", "100%").attr("x2", "0%").attr("y2", "0%").attr('id', hypenate(namespace, 'numerical-legend-gradient')); - - colorFunction$$1.dataExtent([min, max]).colorBy('value').valueExtractor(function (k, v, i) { - return v; - }); - - linearGradient.selectAll('stop').data(colorFunction$$1.colors()).enter().append('stop').attr("offset", function (d, i) { - return i / (colorFunction$$1.colors().length - 1); - }).attr('stop-color', function (d) { - return d; - }); - - var rect = safeSelect(container, 'rect', 'legend').attr('transform', 'translate(0,' + fontSize + ')').style("fill", "url(#" + hypenate(namespace, 'numerical-legend-gradient') + ")").attr('x', 0).attr('y', 0).attr('width', spaceX).attr('height', spaceY - fontSize * 2).on('mousemove', function (d, i) { - legendMousemove(d, i, rect, d3.select(this)); - }).on('mouseout', function (d, i) { - d3.select("#" + hypenate(namespace, 'legend-tooltip')).remove(); - }); - - var minText = safeSelect(container, 'text', 'min').text(round(min, 2)).attr('text-anchor', 'middle').attr("font-size", fontSize + 'px').attr('transform', function (d, i) { - var x = spaceX / 2, - y = spaceY - fontSize / 4, - t = 'translate(' + x + ',' + y + ')'; - return t; - }); - - var maxText = safeSelect(container, 'text', 'max').text(round(max, 2)).attr('text-anchor', 'middle').attr("font-size", fontSize + 'px').attr('transform', function (d, i) { - var x = spaceX / 2, - y = fontSize, - t = 'translate(' + x + ',' + y + ')'; - return t; - }); - } - - function legendMousemove(d, i, rect, t) { - var s = d3.scaleLinear().domain([0, rect.attr('height')]).range([max, min]); - var m = d3.mouse(rect.node()); - var v = round(s(m[1]), roundTo); - - var strokeColor = colorFunction$$1(undefined, v, undefined, 'stroke'); - var fillColor = colorFunction$$1(undefined, v, undefined, 'fill'); - - var div = safeSelect(d3.select('body'), 'div', hypenate(namespace, 'legend-tooltip')).attr('id', hypenate(namespace, 'legend-tooltip')).style('position', 'absolute').style('left', d3.event.pageX + 15 + 'px').style('top', d3.event.pageY + 15 + 'px').style('background-color', fillColor).style('border-color', strokeColor).style('min-width', fontSize * (String(max).split('.')[0].length + 3) + 'px').style('min-height', fontSize * (String(max).split('.')[0].length + 3) + 'px').style('border-radius', '50%').style('border-radius', '5000px').style('display', 'flex').style('justify-content', 'center').style('text-align', 'middle').style('padding', 2 + "px").style('border-style', 'solid').style('border-width', 2); - - var text = safeSelect(div, 'div').text(v).style('color', textColor).style('align-self', 'center'); - } - - return legend; - } - - function categoricLegend(selection) { - var categories, - - - /** - * Data to plot. Assumed to be a object, where each key corresponds to a legend - * (see {@link legend#data}) - * @param {Object} [data=undefined] - * @memberof legend# - * @property - */ - data, - - /** - * Which direction to render the bars in - * (see {@link legend#orient}) - * @param {number} [orient='horizontal'] - * @memberof legend# - * @property - */ - orient = 'horizontal', - - /** - * Amount of horizontal space (in pixels) avaible to render the legend in - * (see {@link legend#spaceX}) - * @param {number} [spaceX=undefined] - * @memberof legend# - * @property - */ - spaceX, - - /** - * Amount of vertical space (in pixels) avaible to render the legend in - * (see {@link legend.spaceY}) - * @param {number} [spaceY=undefined] - * @memberof legend# - * @property - */ - spaceY, - - - /** - * Whether or not to allow legend to render elements pass the main spatial dimension - * given the orientation (see {@link legend#orient}), where {@link legend#orient}="horizontal" - * the main dimension is {@link legend#spaceX} and where {@link legend#orient}="vertical" - * the main dimension is {@link legend#spaceY} - * @param {boolean} [overflowQ=false] - * @memberof legend# - * @property - */ - overflowQ = false, - - - /** - * An array - putatively of other arrays - depicting how bars should be arranged - * @param {Array[]} [grouping=undefined] - * @memberof legend# - * @property - */ - grouping, - - - /** - * How to get the value of the legend - * @param {function} [valueExtractor=function(key, index) { return data[key] }] - * @memberof legend# - * @property - */ - valueExtractor = function valueExtractor(key, index) { - return data[key]; - }, - - /** - * How to sort the bars - if {@link bar#grouping} is not provided. - * @param {function} [sortingFunction=function(keyA, keyB) {return d3.descending(data[keyA], data[keyB])}] - * @memberof bar# - * @property - */ - sortingFunction = function sortingFunction(keyA, keyB) { - return d3.ascending(keyA, keyB); - }, - - /** - * Default space for the spacer (percentage) of main dimension given the orientation - * (see {@link legend#orient}), where {@link legend#orient}="horizontal" - * the main dimension is {@link legend#spaceX} and where {@link legend#orient}="vertical" - * the main dimension is {@link legend#spaceY} between bars - * @param {number} [objectSpacer=0.05] - * @memberof legend# - * @property - */ - objectSpacer = 0.05, - - /** - * The minimum size that an object can be - * @param {number} [minObjectSize=50] - * @memberof legend# - * @property - */ - minObjectSize = 10, - - /** - * The maximum size that an object can be - * @param {number} [maxObjectSize=100] - * @memberof legend# - * @property - */ - maxObjectSize = 100, - - - /** - * The stroke width of the bars - * @param {number} [barStrokeWidth=2] - * @memberof legend# - * @property - */ - bubbleStrokeWidth = 2, - - /** - * Instance of ColorFunction - * @param {function} [colorFunction = colorFunction()] - * @memberof legend# - * @property - */ - colorFunction$$1 = colorFunction(), - - - /** - * Color of the background - * @param {string} [backgroundFill="transparent"] - * @memberof legend# - * @property - */ - backgroundFill = 'transparent', - - /** - * Namespace for all items made by this instance of legend - * @param {string} [namespace="d3sm-legend"] - * @memberof legend# - * @property - */ - namespace = 'd3sm-legend', - - /** - * Class name for legend container ( element) - * @param {string} [objectClass="legend"] - * @memberof legend# - * @property - */ - objectClass = 'legend', - - - /** - * Duration of all transitions of this element - * @param {number} [transitionDuration=1000] - * @memberof legend# - * @property - */ - transitionDuration = 1000, - - /** - * Easing function for transitions - * @param {d3.ease} [easeFunc=d3.easeExp] - * @memberof legend# - * @property - */ - easeFunc = d3.easeExp; - - legend.categories = function (_) { - return arguments.length ? (categories = _, legend) : categories; - }; - - /** - * Gets or sets the selection in which items are manipulated - * @param {d3.selection} [_=none] - * @returns {legend | d3.selection} - * @memberof legend - * @property - * by default selection = selection - */ - legend.selection = function (_) { - return arguments.length ? (selection = _, legend) : selection; - }; - /** - * Gets or sets the data - * (see {@link legend#data}) - * @param {number} [_=none] - * @returns {legend | object} - * @memberof legend - * @property - */ - legend.data = function (_) { - return arguments.length ? (data = _, legend) : data; - }; - /** - * Gets or sets the orient of the bars - * (see {@link legend#orient}) - * @param {number} [_=none] - * @returns {legend | object} - * @memberof legend - * @property - */ - legend.orient = function (_) { - return arguments.length ? (orient = _, legend) : orient; - }; - /** - * Gets or sets the amount of horizontal space in which items are manipulated - * (see {@link legend#spaceX}) - * @param {number} [_=none] should be a number > 0 - * @returns {legend | number} - * @memberof legend - * @property - * by default spaceX = undefined - */ - legend.spaceX = function (_) { - return arguments.length ? (spaceX = _, legend) : spaceX; - }; - /** - * Gets or sets the amount of vertical space in which items are manipulated - * (see {@link legend#spaceY}) - * @param {number} [_=none] should be a number > 0 - * @returns {legend | number} - * @memberof legend - * @property - * by default spaceY = undefined - */ - legend.spaceY = function (_) { - return arguments.length ? (spaceY = _, legend) : spaceY; - }; - - /** - * Gets / sets whether or not legend is allowed to go beyond specified dimensions - * (see {@link legend#spaceX}) - * @param {boolean} [_=none] - * @returns {legend | boolean} - * @memberof legend - * @property - * by default overflowQ = false - */ - legend.overflowQ = function (_) { - return arguments.length ? (overflowQ = _, legend) : overflowQ; - }; - /** - * Gets / sets the grouping of the bars - * (see {@link legend#grouping}) - * @param {Array[]} [_=none] - * @returns {legend | Array[]} - * @memberof legend - * @property - * by default grouping = undefined - */ - legend.grouping = function (_) { - return arguments.length ? (grouping = _, legend) : grouping; - }; - /** - * Gets / sets the valueExtractor - * (see {@link legend#valueExtractor}) - * @param {function} [_=none] - * @returns {legend | function} - * @memberof legend - * @property - * by default valueExtractor = function(key, index) { return data[key] }, - */ - legend.valueExtractor = function (_) { - return arguments.length ? (valueExtractor = _, legend) : valueExtractor; - }; - /** - * Gets / sets the sortingFunction - * (see {@link bar#sortingFunction}) - * @param {function} [_=none] - * @returns {bar | function} - * @memberof bar - * @property - * by default sortingFunction = function(keyA, keyB) {return d3.descending(data[keyA], data[keyB])}, - */ - legend.sortingFunction = function (_) { - return arguments.length ? (sortingFunction = _, legend) : sortingFunction; - }; - /** - * Gets / sets objectSpacer - * (see {@link legend#objectSpacer}) - * @param {number} [_=none] - * @returns {legend | number} - * @memberof legend - * @property - * by default objectSpacer = 0.05 - */ - legend.objectSpacer = function (_) { - return arguments.length ? (objectSpacer = _, legend) : objectSpacer; - }; - /** - * Gets / sets the minObjectSize - * (see {@link legend#minObjectSize}) - * @param {number} [_=none] - * @returns {legend | number} - * @memberof legend - * @property - * by default minObjectSize = 50 - */ - legend.minObjectSize = function (_) { - return arguments.length ? (minObjectSize = _, legend) : minObjectSize; - }; - /** - * Gets / sets the maxObjectSize - * (see {@link legend#maxObjectSize}) - * @param {number} [_=none] - * @returns {legend | number} - * @memberof legend - * @property - * by default maxObjectSize = 100 - */ - legend.maxObjectSize = function (_) { - return arguments.length ? (maxObjectSize = _, legend) : maxObjectSize; - }; - - /** - * Gets / sets the barStrokeWidth - * (see {@link legend#barStrokeWidth}) - * @param {number} [_=none] - * @returns {legend | number} - * @memberof legend - * @property - * by default barStrokeWidth = 2 - */ - legend.bubbleStrokeWidth = function (_) { - return arguments.length ? (bubbleStrokeWidth = _, legend) : bubbleStrokeWidth; - }; - /** - * Gets / sets the colorFunction - * (see {@link legend#colorFunction}) - * @param {number} [_=none] - * @returns {legend | number} - * @memberof legend - * @property - * by default colorFunction = colorFunction() - */ - legend.colorFunction = function (_) { - return arguments.length ? (colorFunction$$1 = _, legend) : colorFunction$$1; - }; - - /** - * Gets / sets the backgroundFill - * (see {@link legend#backgroundFill}) - * @param {string} [_=none] - * @returns {legend | string} - * @memberof legend - * @property - * by default backgroundFill = 'transparent' - */ - legend.backgroundFill = function (_) { - return arguments.length ? (backgroundFill = _, legend) : backgroundFill; - }; - /** - * Gets / sets the namespace - * (see {@link legend#namespace}) - * @param {string} [_=none] - * @returns {legend | string} - * @memberof legend - * @property - * by default namespace = 'd3sm-legend' - */ - legend.namespace = function (_) { - return arguments.length ? (namespace = _, legend) : namespace; - }; - /** - * Gets / sets the objectClass - * (see {@link legend#objectClass}) - * @param {string} [_=none] - * @returns {legend | string} - * @memberof legend - * @property - * by default objectClass = 'tick-group' - */ - legend.objectClass = function (_) { - return arguments.length ? (objectClass = _, legend) : objectClass; - }; - /** - * Gets / sets the transitionDuration - * (see {@link legend#transitionDuration}) - * @param {number} [_=none] - * @returns {legend | number} - * @memberof legend - * @property - * by default transitionDuration = 1000 - */ - legend.transitionDuration = function (_) { - return arguments.length ? (transitionDuration = _, legend) : transitionDuration; - }; - /** - * Gets / sets the easeFunc - * (see {@link legend#easeFunc}) - * @param {d3.ease} [_=none] - * @returns {legend | d3.ease} - * @memberof legend - * @property - * by default easeFunc = d3.easeExp - */ - legend.easeFunc = function (_) { - return arguments.length ? (easeFunc = _, legend) : easeFunc; - }; - - function legend() { - var horizontalQ = orient == 'horizontal' ? true : false; - var verticalQ = !horizontalQ; - // background cliping rectangle - var bgcpRect = { x: 0, y: 0, width: spaceX, height: spaceY }; - var container = setupContainer(selection, namespace, bgcpRect, backgroundFill); - - colorFunction$$1.dataExtent([0, categories.length - 1]).colorBy('categories').categoryExtractor(function (k, v, i) { - return v; - }); - - var r = Math.min(spaceX, spaceY) / 2; - var numberOfObjects = categories.length; - - // if grouping is undefined sort barKeys by sortingFunction - var ordered = grouping == undefined ? categories.sort(sortingFunction) : grouping; - // ordered might be nested depending on grouping - var catKeys = flatten(ordered); - - var space = horizontalQ ? spaceX : spaceY; - // calculate object size - var objectSize = calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ); - // calculate spacer size if needed - var spacerSize = calculateWidthOfSpacer(catKeys, space, objectSize, numberOfObjects, objectSpacer, overflowQ); - // make the nested groups - var spacerFunction = groupingSpacer().horizontalQ(horizontalQ).scale(scale).moveby('category').numberOfObjects(numberOfObjects).objectClass(objectClass).objectSize(objectSize).spacerSize(spacerSize).transitionDuration(transitionDuration).easeFunc(easeFunc).namespace(namespace); - - spacerFunction(container, ordered, 0); - var r = Math.min(objectSize, spaceX, spaceY) / 2 - bubbleStrokeWidth; - - container.selectAll('g:not(.to-remove).' + objectClass).each(function (cat, i) { - var t = d3.select(this); - var c = safeSelect(t, 'circle'); - var fillColor = colorFunction$$1(undefined, cat, i, 'fill'), - // prevent duplicate computation - strokeColor = colorFunction$$1(undefined, cat, i, 'stroke'); - - var cx = horizontalQ ? r + bubbleStrokeWidth : (spaceX - r * 2) / 2 + r; - var cy = verticalQ ? r + bubbleStrokeWidth : (spaceX - r * 2) / 2 + r; - - c.attr("r", r).attr('cx', cx).attr('cy', cy).attr('fill', fillColor).attr('stroke', strokeColor).attr('stroke-width', bubbleStrokeWidth); - - var text = safeSelect(t, 'text'); - text.text(cat).attr('text-anchor', 'middle').attr("transform", function (d, i) { - var x = cx, - y = cy + text.node().getBoundingClientRect().height / 4, - t = 'translate(' + x + ',' + y + ')'; - return t; - }); - }); - } - - return legend; - } - - /******************************************************************************* - ** ** - ** ** - ** D3 EXTENSIONS ** - ** ** - ** ** - *******************************************************************************/ - /** - * Recursively ascends parents of selection until it finds an svg tag - * @function d3.selection.thisSVG - * @augments d3.selection - * @returns {Element} which is the svg tag, not the d3 selection of that tag - */ - d3.selection.prototype.thisSVG = function () { - return getContainingSVG(this.node()); - }; - - /** - * Helper for getting absolute position of the mouse - * @function d3.mouse.absolute - * @augments d3.mouse - * @returns {number[]} [x, y] as they relate to `html` not to local scope. - */ - d3.mouse.absolute = function () { - var html = d3.select('html').node(); - - var _ref = this(html), - _ref2 = slicedToArray(_ref, 2), - x = _ref2[0], - y = _ref2[1]; - - return [x, y]; - }; - - /** - * Gets position of the selection in relation to the containing svg - * @see{@link getContainingSVG} - * @function d3.selection.absolutePosition - * @augments d3.selection - * @returns {Object} with structure similar to getBoundingClientRect, e.g. - * top, left, bottom, right, height, width - */ - d3.selection.prototype.absolutePosition = function () { - var element = this.node(); - var elementPosition = element.getBoundingClientRect(); - var containerSVG = getContainingSVG(element); - var svgPosition = containerSVG.getBoundingClientRect(); - - return { - top: elementPosition.top - svgPosition.top, - left: elementPosition.left - svgPosition.left, - bottom: elementPosition.bottom - svgPosition.top, - right: elementPosition.right - svgPosition.left, - height: elementPosition.height, - width: elementPosition.width - }; - }; - - d3.selection.prototype.relativePositionTo = function (container) { - var element = this.node(); - var elementPosition = element.getBoundingClientRect(); - var containerSVG = container; - var svgPosition = containerSVG.getBoundingClientRect(); - - return { - top: elementPosition.top - svgPosition.top, - left: elementPosition.left - svgPosition.left, - bottom: elementPosition.bottom - svgPosition.top, - right: elementPosition.right - svgPosition.left, - height: elementPosition.height, - width: elementPosition.width - }; - }; - - function getTranslation$1(selection) { - var transform = selection.attr('transform'); - - var _transform$split = transform.split('translate('), - _transform$split2 = slicedToArray(_transform$split, 2), - junk = _transform$split2[0], - xy = _transform$split2[1]; - - var _xy$split = xy.split(','), - _xy$split2 = slicedToArray(_xy$split, 2), - x = _xy$split2[0], - y = _xy$split2[1]; - - junk = y.split(')'); - return [parseFloat(x), parseFloat(y)]; - } - - function lasso(selection) { - var svg, - // svg that is target of events - objectContainer, - // container which houses objects we are selecting (allows for transform to be applied to lasso) - objectClass, - // class of object we are selecting - namespace = "d3sm-lasso", - chartContainer, - chartOffset, - objectsOffset, - eventCatcher, - xScale, - // optional scale for the lasso currentPoints - yScale, - // optional scale for the lasso currentPoints - - activeQ = false, - // whether or not lasso is active - - currentPoints = [], - // mouse points for current lasso - allPoints = [], - // list of lists for all points of lassos - - line = d3.line().x(function (d, i) { - var x; - if (xScale != undefined) { - x = xScale(d[0]); - } else { - x = d[0]; - } - return x; //- chartOffset[0]// - objectsOffset[0] - }).y(function (d, i) { - var y; - if (yScale != undefined) { - y = yScale(d[1]); - } else { - y = d[1]; - } - return y; // - chartOffset[1]// - objectsOffset[1] - }).curve(d3.curveLinearClosed), - instance = 0, - // an indentifier for which instance this lasso is under the current svg - - tickDistance = 10, - - - // styles for lasso path - color = '#17a2b8', - animationRate = '10s', - opacity = 0.3, - dashArray = '5, 10', - stroke = 'black', - strokeWidth = 2, - - - // styles for lassoed objects - lassoedFill = "white", - lassoedStroke = 'black', - lassoedStrokeWidth = 3, - transitionDuration = 1000, - easeFunc = d3.easeExp; - - var path; - - lasso.svg = function (_) { - return arguments.length ? (svg = _, lasso) : svg; - }; - lasso.chartContainer = function (_) { - return arguments.length ? (chartContainer = _, lasso) : chartContainer; - }; - lasso.objectContainer = function (_) { - return arguments.length ? (objectContainer = _, lasso) : objectContainer; - }; - lasso.objectClass = function (_) { - return arguments.length ? (objectClass = _, lasso) : objectClass; - }; - lasso.namespace = function (_) { - return arguments.length ? (namespace = _, lasso) : namespace; - }; - lasso.xScale = function (_) { - return arguments.length ? (xScale = _, lasso) : xScale; - }; - lasso.yScale = function (_) { - return arguments.length ? (yScale = _, lasso) : yScale; - }; - lasso.activeQ = function (_) { - return arguments.length ? (activeQ = _, lasso) : activeQ; - }; - lasso.currentPoints = function (_) { - return arguments.length ? (currentPoints = _, lasso) : currentPoints; - }; - lasso.allPoints = function (_) { - return arguments.length ? (allPoints = _, lasso) : allPoints; - }; - lasso.instance = function (_) { - return arguments.length ? (instance = _, lasso) : instance; - }; - lasso.tickDistance = function (_) { - return arguments.length ? (tickDistance = _, lasso) : tickDistance; - }; - lasso.color = function (_) { - return arguments.length ? (color = _, lasso) : color; - }; - lasso.animationRate = function (_) { - return arguments.length ? (animationRate = _, lasso) : animationRate; - }; - lasso.opacity = function (_) { - return arguments.length ? (opacity = _, lasso) : opacity; - }; - lasso.dashArray = function (_) { - return arguments.length ? (dashArray = _, lasso) : dashArray; - }; - lasso.stroke = function (_) { - return arguments.length ? (stroke = _, lasso) : stroke; - }; - lasso.lassoedFill = function (_) { - return arguments.length ? (lassoedFill = _, lasso) : lassoedFill; - }; - lasso.lassoedStroke = function (_) { - return arguments.length ? (lassoedStroke = _, lasso) : lassoedStroke; - }; - lasso.lassoedStrokeWidth = function (_) { - return arguments.length ? (lassoedStrokeWidth = _, lasso) : lassoedStrokeWidth; - }; - lasso.eventCatcher = function (_) { - return arguments.length ? (eventCatcher = _, lasso) : eventCatcher; - }; - - lasso.drag = drag; - lasso.draw = draw; - lasso.tick = tick; - lasso.detect = detect; - lasso.toggle = toggle; - lasso.remove = remove; - lasso.render = render; - lasso.keyFrames = keyFrames; - lasso.updateObjects = updateObjects; - lasso.applyPathAttributes = applyPathAttributes; - lasso.applyObjectAttributes = applyObjectAttributes; - - keyFrames(); - - function lasso() { - // add a dash animation if needed - if (activeQ) { - transitionDraw(); - } - } - - function toggle(state) { - // use optional param to set state, otherwise toggle state - activeQ = state != undefined ? state : !activeQ; - chartOffset = getTranslation$1(chartContainer); - objectsOffset = getTranslation$1(objectContainer); - - if (activeQ) { - svg.node().addEventListener('mousedown', render, true); - } else { - svg.node().removeEventListener('mousedown', render, true); - remove(); - } - } - - function draw() { - chartOffset = getTranslation$1(chartContainer); - objectsOffset = getTranslation$1(objectContainer); - - var container = safeSelect(objectContainer, 'g', 'lasso-container'); - var paths = container.selectAll('path[instance="' + instance + '"]'); - - // update - paths = paths.data(allPoints); - - // remove excess - var pExit = paths.exit().remove(); - // add needed paths - var pEnter = paths.enter().append('path'); - - // merge - paths = paths.merge(pEnter); - - // apply - applyPathAttributes(paths); - } - - function remove() { - var container = safeSelect(objectContainer, 'g', 'lasso-container'); - var paths = container.selectAll('path[instance="' + instance + '"]').remove(); - container.remove(); - objectContainer.selectAll(objectClass).classed("in-lasso", false); - updateObjects(); - } - - function render(event) { - // nothing can interefer with drawing the lasso - event.preventDefault();event.stopPropagation(); - - var container = safeSelect(objectContainer, 'g', 'lasso-container'); - - /* - each time the user presses down, while the state is active, the lasso - the lasso should make a seperate segment. - */ - currentPoints = []; - - svg.node().addEventListener('mousemove', drag); - svg.node().addEventListener('mouseup', function (event) { - svg.node().removeEventListener('mousemove', drag); - allPoints.push(currentPoints); - // BUG: somehow this is pushing currentPoints n times where n is the nth lasso path for the current instance - // NOTE: allPoints = unique(allPoints) is a temporary and inefficient fix - allPoints = unique(allPoints); - }); - - path = container.append('path').data([currentPoints]); - applyPathAttributes(path); - } - - function transitionDraw() { - var container = safeSelect(objectContainer, 'g', 'lasso-container'); - var paths = container.selectAll('path[instance="' + instance + '"]'); - - // update - paths = paths.data(allPoints); - - // remove excess - var pExit = paths.exit().remove(); - // add needed paths - var pEnter = paths.enter().append('path'); - - // merge - paths = paths.merge(pEnter).transition().duration(transitionDuration).ease(easeFunc); - applyPathAttributes(paths); - } - - function applyPathAttributes(path) { - path.attr("class", hypenate(namespace, "lasso-path")).style('opacity', opacity).attr('fill', color).attr("d", line).attr('instance', instance).style("stroke-dasharray", dashArray).attr("stroke", stroke).attr("stroke-width", strokeWidth).style('animation', 'lassoDash ' + animationRate + ' linear').style("animation-iteration-count", "infinite"); - } - - function drag(event) { - /* - effectively create a mouse down and move event (which normally is inteperated - as 'drag' by the browser) by dynamically adding / removing this event on - mouse down / mouse up. - */ - - if (eventCatcher != undefined) { - eventCatcher.dispatch(hypenate(namespace, "drag")); - } - // d3.dispatch(hypenate(namespace,"drag")) - - if (event.which != 1) { - return; - } // ensures left mouse button set - d3.event = event; - var pt = d3.mouse(objectContainer.node()); - var pt = d3.mouse(svg.node()); - - if (xScale != undefined) { - pt[0] = xScale.invert(pt[0]); - } - if (yScale != undefined) { - pt[1] = yScale.invert(pt[1]); - } - pt[0] = pt[0] - chartOffset[0] - objectsOffset[0]; - pt[1] = pt[1] - chartOffset[1] - objectsOffset[1]; - - /* if we have a point already, test if it passes a minimum distance to prevent overwhelming with too many tick functions */ - if (currentPoints.length) { - var lastPt = currentPoints[currentPoints.length - 1]; - var a = [pt[0], pt[1]], - b = [lastPt[0], lastPt[1]]; - - if (xScale) { - b[0] = xScale(b[0]);a[0] = xScale(a[0]); - } - if (yScale) { - b[1] = yScale(b[1]);a[1] = yScale(a[1]); - } - - var dist = euclideanDistance(b, a); - if (dist > tickDistance) { - tick(pt); - } - } else { - tick(pt); - } - } - - function tick(pt) { - /* - If a point is provided update data and objects. - Otherwise just call on data we already have. - Why like this?: - 1. currentPoints is current points to allow disjunct lassos, currentPoints is only pushed to - allPoints after mouseup. - 2. to allow render of objects in the lasso class / updating the data list - just by toggling the button - */ - - if (pt != undefined) { - currentPoints.push(pt); - path.attr("d", line); - if (currentPoints.length < 3) { - return; - } // need at least 3 points to detect anything. - detect(allPoints.concat([currentPoints])); - } else { - detect(allPoints); - } - } - - function detect(lassos) { - if (lassos == undefined) { - lassos = allPoints; - } - objectContainer.selectAll(objectClass).each(function (d, i) { - var current = d3.select(this), - box = current.absolutePosition(), - - // box = current.relativePositionTo(objectContainer.node()), - - boxPts = [[box.left - chartOffset[0] - objectsOffset[0], box.top - chartOffset[1] - objectsOffset[1]], [box.right - chartOffset[0] - objectsOffset[0], box.top - chartOffset[1] - objectsOffset[1]], [box.left - chartOffset[0] - objectsOffset[0], box.bottom - chartOffset[1] - objectsOffset[1]], [box.right - chartOffset[0] - objectsOffset[0], box.bottom - chartOffset[1] - objectsOffset[1]]]; - - if (xScale != undefined) { - boxPts[0][0] = xScale.invert(boxPts[0][0]); - boxPts[1][0] = xScale.invert(boxPts[1][0]); - boxPts[2][0] = xScale.invert(boxPts[2][0]); - boxPts[3][0] = xScale.invert(boxPts[3][0]); - } - if (yScale != undefined) { - boxPts[0][1] = yScale.invert(boxPts[0][1]); - boxPts[1][1] = yScale.invert(boxPts[1][1]); - boxPts[2][1] = yScale.invert(boxPts[2][1]); - boxPts[3][1] = yScale.invert(boxPts[3][1]); - } - - /* - flag needed as we have to test multiple lasso segments, and if the point - is not in one segment, it does not mean it is not in any - */ - var inAnyLassoQ = false; - for (var i = 0; i < lassos.length; i++) { - var lassoPoints = lassos[i]; - // .map(function(pt){ - // var x, y = pt - // if (xScale!=undefined) {x = xScale(x)} - // if (yScale!=undefined) {y = yScale(y)} - // return [x, y] - // }) - var boxInLassoQ = boxPts.every(function (coord) { - return d3.polygonContains(lassoPoints, coord); - }); - - if (boxInLassoQ) { - inAnyLassoQ = true; - } // only update flag in the positive case. - } - - current.classed('in-lasso', inAnyLassoQ); - current.classed('in-lasso-' + instance, inAnyLassoQ); - }); - - updateObjects(); - return objectContainer.selectAll('.in-lasso-' + instance); - } - - function updateObjects() { - objectContainer.selectAll(objectClass).each(function (d, i) { - var t = d3.select(this); - applyObjectAttributes(t, t.classed('in-lasso')); - }); - } - - function applyObjectAttributes(obj, setQ) { - var preLassoFill = obj.attr('_pre_lasso_fill'), - preLassoStroke = obj.attr('_pre_lasso_stroke'), - preLassoStrokeWidth = obj.attr('_pre_lasso_stroke-width'); - - if (setQ) { - obj.classed("in-lasso", true); - obj.classed('in-lasso-' + instance, true); - if (preLassoFill == undefined) { - obj.attr('_pre_lasso_fill', obj.attr('fill')); - } - if (preLassoStroke == undefined) { - obj.attr('_pre_lasso_stroke', obj.attr('stroke')); - } - if (preLassoStrokeWidth == undefined) { - obj.attr('_pre_lasso_stroke-width', obj.attr('stroke-width')); - } - - obj - //BUG: when .raise() - .attr('fill', lassoedFill).attr('stroke', lassoedStroke).attr('stoke-width', lassoedStrokeWidth); - } else { - obj.classed("in-lasso", false); - obj.classed('in-lasso-' + instance, false); - if (preLassoFill != undefined) { - obj.attr('fill', preLassoFill); - } - if (preLassoStroke != undefined) { - obj.attr('stroke', preLassoStroke); - } - if (preLassoStrokeWidth != undefined) { - obj.attr('stroke-width', preLassoStrokeWidth); - } - } - } - - function keyFrames() { - var style = d3.select("html").select('style.' + hypenate(namespace, "lasso-dash")); - if (style.empty()) { - d3.select("html").append('style').classed(hypenate(namespace, "lasso-dash"), true).html("@keyframes lassoDash {to { stroke-dashoffset: 1000;}}"); - } - } - return lasso; - } - - function lassoWidget(selection) { - var namespace = 'd3sm-lasso', - selection = selection, - svg, - chartContainer, - objectContainer, - objectClass, - lassoLine = d3.line().x(function (d, i) { - return d[0]; - }).y(function (d, i) { - return d[1]; - }).curve(d3.curveLinearClosed), - colorFunction$$1 = colorFunction(), - maxNumberOfGroups, - dataExtractor, - xScale, - yScale; - - function onError(msg, style) { - console.log(msg, style); - } - // setup the container - setupDataselectContainer(); - - lassoWidget.objectClass = function (_) { - return arguments.length ? (objectClass = '.' + _.replace('.', ''), lassoWidget) : objectClass; - }; - lassoWidget.svg = function (_) { - return arguments.length ? (svg = _, lassoWidget) : svg; - }; - lassoWidget.submit = function (_) { - return arguments.length ? (submit = _, lassoWidget) : submit; - }; - lassoWidget.maxNumberOfGroups = function (_) { - return arguments.length ? (maxNumberOfGroups = _, lassoWidget) : maxNumberOfGroups; - }; - lassoWidget.onError = function (_) { - return arguments.length ? (onError = _, lassoWidget) : onError; - }; - lassoWidget.objectContainer = function (_) { - return arguments.length ? (objectContainer = _, lassoWidget) : objectContainer; - }; - lassoWidget.chartContainer = function (_) { - return arguments.length ? (chartContainer = _, lassoWidget) : chartContainer; - }; - lassoWidget.dataExtractor = function (_) { - return arguments.length ? (dataExtractor = _, lassoWidget) : dataExtractor; - }; - lassoWidget.xScale = function (_) { - return arguments.length ? (xScale = _, lassoWidget) : xScale; - }; - lassoWidget.yScale = function (_) { - return arguments.length ? (yScale = _, lassoWidget) : yScale; - }; - - function styles() { - var s = d3.select("html").select("style." + namespace + 'lasso-widget'); - if (s.empty()) { - d3.select("html").append("style").classed(namespace + 'lasso-widget', true).html("." + hypenate(namespace, "data-table") + "{\ - height:100px;\ - overflow:auto;\ - }"); - } - } - - function lassoWidget() { - styles(); - } - - function submit(data) { - console.log(data); - } - - function plusTab(tabList) { - var tab = safeSelect(tabList, 'li', hypenate(namespace, 'plus-tab')).classed('ml-auto', true).classed('nav-item', true).on('click', makeNewGroup), - anchor = safeSelect(tab, 'a', 'nav-link'), - icon = safeSelect(anchor, 'i', 'fa').classed('fa-plus fa-2x text-success', true); - } - - function sendTab(tabList) { - var tab = safeSelect(tabList, 'li', hypenate(namespace, 'send-tab')).classed('ml-auto', true).classed('nav-item', true).on('click', clickSend), - anchor = safeSelect(tab, 'a', 'nav-link'), - icon = safeSelect(anchor, 'i', 'fa').classed('fa-paper-plane-o fa-2x text-primary', true); - } - - function clickSend() { - var data = gatherDataLists(); - submit(data); - } - - function closeTab(tabList) { - var tab = safeSelect(tabList, 'li', hypenate(namespace, 'close-tab')).classed('ml-auto', true).classed('nav-item', true).on('click', function () { - var m = d3.mouse(d3.select("html").node()); - }), - anchor = safeSelect(tab, 'a', 'nav-link'), - icon = safeSelect(anchor, 'i', 'fa').classed('fa-window-close-o fa-2x text-danger', true); - } - - function setupDataselectContainer() { - var card = safeSelect(selection, 'div', 'card'), - cardHeader = safeSelect(card, 'div', 'card-header'), - tabList = safeSelect(cardHeader, 'ul', 'nav').classed('nav-tabs card-header-tabs', true).classed(hypenate(namespace, 'tab-list'), true).attr('role', 'tablist'), - cardBody = safeSelect(card, 'div', 'card-body'), - tabContent = safeSelect(cardBody, 'div', 'tab-content').classed(hypenate(namespace, 'tab-content'), true), - - - // leftTabs = safeSelect(tabList, 'div', 'nav mr-auto left-aligned-tabs') - rightTabs = safeSelect(tabList, 'div', 'right-aligned-tabs').classed('nav ml-auto ', true); - - plusTab(rightTabs); - sendTab(rightTabs); - closeTab(rightTabs); - var defaultTab = safeSelect(tabContent, 'div', 'tab-pane').classed(hypenate(namespace, 'default-tab'), true).classed("active", true).classed('text-left', true), - p = safeSelect(defaultTab, 'div').html("Click to add a new group.
" + "Click to submit for re-analysis.
" + "Click to close the dataselect widget."); - // .text('Click the green plus to add a new group.') - } - - function makeRemoveButton(paneBtnList) { - var btn = safeSelect(paneBtnList, 'button', 'remove-btn').classed('btn btn-danger', true).on('click', removeBtnClickToRemove), - i = safeSelect(btn, 'i', 'fa').classed('fa-trash-o', true), - s = safeSelect(btn, 'span').text('Remove group'); - return btn; - } - - function removeBtnClickToRemove(d, i) { - var tab = selection.select('#' + hypenate(namespace, 'tab', d)), - pane = selection.select('#' + hypenate(namespace, 'tab', 'pane', d)); - - showRemainingPanes(); - updateTabAndPaneNumbers(); - } - - function togglePaneById(id) { - var panes = selection.select('.' + hypenate(namespace, 'tab-content')); - } - - function insertTab(tabs, n) { - - // var li = tabs.insert("li", ':nth-child('+(n)+')') - var li = tabs.insert("li", '.right-aligned-tabs').classed('nav-item', true).classed('alert', true).classed('alert-secondary', true).classed('alert-dismissable', true).classed('fade', true).classed('show', true) - // .classed('mr-auto', true) - .attr("role", 'alert').attr("id", hypenate(namespace, 'tab', n)).classed(hypenate(namespace, 'tab'), true); - - var a = safeSelect(li, 'a').attr('data-toggle', 'tab').text('Group ' + n).attr('href', '#' + hypenate(namespace, 'tab', 'pane', n)).on('dblclick', function (d, i) { - var t = d3.select(this); - t.attr('contenteditable', true); - d3.select(t.node().parentNode).classed('alert-secondary', false).classed('alert-warning', true); - - // d3.select("html").on("click", dispatchBlur) - // - // function dispatchBlur(d, i) { - // if (d3.event.target != d3.select(this)) { - // d3.select(this).dispatch("blur") - // } - // } - - }).on('blur', function (d, i) { - - var t = d3.select(this); - t.attr('contenteditable', false); - d3.select(t.node().parentNode).classed('alert-secondary', true).classed('alert-warning', false); - }).on('input', function (d, i) { - var t = d3.select(this); - var txt = t.text(); - d3.select(t.attr('href')).select("p.lead").text(txt); - }); - - return li; - } - - function makeTabPane(panes, n) { - var pane = panes.append('div').datum(n).attr('role', 'tabpanel').classed('tab-pane', true).classed('text-left', true).classed(hypenate(namespace, 'tab', 'pane'), true).attr('id', hypenate(namespace, 'tab', 'pane', n)); - return pane; - } - - function populatePane(pane, n) { - var lead = safeSelect(pane, 'p', 'lead').text('Group ' + n), - tableContainer = safeSelect(pane, 'div', 'table-responsive').attr("class", hypenate(namespace, "data-table")), - table = safeSelect(tableContainer, "table", "table").classed("table-sm", true).classed("table-hover", true), - caption = safeSelect(table, "caption", "caption").html("List of selected"), - btns = safeSelect(pane, 'div', 'text-right'), - cN = n % colorFunction$$1.colors().length; - if (n % 2 != 0) { - cN = colorFunction$$1.colors().length - 1 - cN; - } - - var lassoBtn = makeLassoButton(btns); - var currentLasso = makeLassoFunction(n, colorFunction$$1.colors()[cN]); - var clearBtn = makeClearButton(btns); - - bindButtons(lassoBtn, clearBtn, currentLasso, table); - - var removeBtn = makeRemoveButton(btns); - - lead.on("mouseover", function () { - currentLasso.draw(); - }); - lead.on("mouseout", function () { - currentLasso.remove(); - }); - } - - function makeLassoButton(btns) { - var btn = safeSelect(btns, 'button', 'lasso-btn').classed('btn btn-info', true).classed(namespace, true); - // .datum([lasso]) - var i = safeSelect(btn, 'i', 'fa').classed('fa-hand-pointer-o', true); - var s = safeSelect(btn, 'span').text('Lasso select'); - return btn; - } - - function makeClearButton(btns) { - var btn = safeSelect(btns, 'button', 'clear-btn').classed('btn btn-light', true).classed(namespace, true); - var i = safeSelect(btn, 'i', 'fa').classed('fa-eraser', true); - var s = safeSelect(btn, 'span').text('Clear selection'); - return btn; - } - - function makeLassoFunction(instance, color) { - var currentLasso = lasso().namespace(namespace).svg(svg).objectClass(objectClass).chartContainer(chartContainer).objectContainer(objectContainer).instance(instance).color(color).yScale(yScale).xScale(xScale); - - return currentLasso; - } - - function bindButtons(lassoBtn, clearBtn, currentLasso, table) { - currentLasso.eventCatcher(lassoBtn); - lassoBtn.node().addEventListener("click", lassoBtnToggle); - - lassoBtn.datum([currentLasso]).on(hypenate(namespace, 'render'), function () { - d3.select(this).datum()[0].draw(); - }).on(hypenate(namespace, "drag"), function (las) { - var nodes = chartContainer.selectAll(".in-lasso-" + las[0].instance()).nodes(); - var tableData = nodes.map(function (d, i) { - var extracted = dataExtractor(d3.select(d).datum()); - extracted["__node"] = d; - return extracted; - }); - - makeTable(table, tableData, currentLasso); - }); - - clearBtn.on('click', function () { - currentLasso.allPoints([]); - currentLasso.currentPoints([]); - lassoBtn.dispatch(hypenate(namespace, "drag")); - }); - } - - function lassoBtnToggle() { - var that = d3.select(this); - var las = that.datum()[0]; - - las.toggle(); - var activeQ = las.activeQ(); - - if (las.activeQ()) { - that.classed('btn-info', !activeQ); - that.classed('btn-warning', activeQ); - that.select("span").text("Lasso select (active)"); - selection.selectAll("." + namespace + ".lasso-btn").dispatch(hypenate(namespace, 'render')); - d3.select("html").node().addEventListener('mousedown', monitorLassoButtonState); - } else { - that.classed('btn-info', !activeQ); - that.classed('btn-warning', activeQ); - that.select("span").text("Lasso select"); - d3.select("html").node().removeEventListener('mousedown', monitorLassoButtonState); - } - - function monitorLassoButtonState(event) { - /* - activeLasso stops event stopPropagation, so this event will not register in - that case. Thus we only need to ensure that the usre is clicking on the lasso button - otherwise, de-spawn lasso. - */ - if (event.target != that.node() && event.target != that.select("span").node() && event.target != that.select("i").node()) { - // event.preventDefault() - // event.stopPropagation() - las.toggle(false); - that.classed('btn-info', true); - that.classed('btn-warning', false); - that.select("span").text("Lasso select"); - // console.log(that, that.node()) - // that.dispatch("focusout") - } - } - } - - function updateTableHeaderColumns(headR, tableData) { - var headerKeys = d3.keys(tableData[0]).filter(function (k) { - return k != "__node"; - }); - if (headerKeys.length > 0) { - // headerKeys = ["remove"].concat(headerKeys) - headerKeys.push("remove"); - } - - var headerCols = headR.selectAll("th"); - - headerCols = headerCols.data(headerKeys); - headerCols.exit().remove(); - headerCols = headerCols.merge(headerCols.enter().append("th").attr("scope", "col")).text(function (d, i) { - return d; - }); - - return headerKeys; - } - - function updateTableRows(body, tableData) { - var bodyRows = body.selectAll("tr"); - - bodyRows = bodyRows.data(tableData); - bodyRows.exit().remove(); - bodyRows = bodyRows.merge(bodyRows.enter().append("tr")); - - return bodyRows; - } - - function updateTableRowColumns(cols, headerKeys, rowData, tableData, lasso$$1, table) { - cols = cols.data(headerKeys); - cols.exit().remove(); - cols = cols.merge(cols.enter().append("td")); - - cols.html(function (d, i) { - if (d != "remove") { - return rowData[d]; - } - return ""; - }).classed("text-left", function (d, i) { - if (d != "remove") { - return false; - } - return true; - }); - // .attr("scope",function(d, i){ - // if (d != "remove") { return false } - // return true - // }) - - cols.select("i.fa-close").on("click", function (d, i) { - var node = rowData["__node"], - n = d3.select(node); - n.classed("in-lasso", false); - n.classed("in-lasso-" + lasso$$1.instance(), false); - - tableData.map(function (dd, j) { - if (dd["__node"] == node) { - tableData.splice(j, 1); - makeTable(table, tableData, lasso$$1); - } - }); - }); - } - - function makeTable(table, tableData, lasso$$1) { - var head = safeSelect(table, "thead"), - headR = safeSelect(head, "tr"), - body = safeSelect(table, "tbody"), - headerKeys = updateTableHeaderColumns(headR, tableData), - bodyRows = updateTableRows(body, tableData); - - bodyRows.each(function (rowData, i) { - var t = d3.select(this); - var cols = t.selectAll("td"); - - updateTableRowColumns(cols, headerKeys, rowData, tableData, lasso$$1, table); - - t.on("mouseover", function (d, i) { - lasso$$1.applyObjectAttributes(d3.select(d["__node"]), true); - }).on("mouseout", function (d, i) { - lasso$$1.applyObjectAttributes(d3.select(d["__node"]), false); - }); - }); - } - - function makeNewGroup(d, i) { - - var tabs = selection.select('.' + hypenate(namespace, 'tab-list')), - panes = selection.select('.' + hypenate(namespace, 'tab-content')), - n = newGroupNumber(); - - if (tabs.selectAll('.' + hypenate(namespace, 'tab')).size() == maxNumberOfGroups) { - onError('only ' + maxNumberOfGroups + ' allowed.', 'warning'); - return; - } - - var tab = insertTab(tabs, n), - pane = makeTabPane(panes, n); - - populatePane(pane, n); - togglePaneById(pane.attr('id')); - } - - function newGroupNumber() { - var tabs = selection.select('.' + hypenate(namespace, 'tab-list')); //, - var n = tabs.selectAll('li').size() - 3, - // minus 1 for plus tab - s = 'Group ' + n, - gs = []; - while (gs.includes(s)) { - n += 1;s = 'Group ' + n; - } - return n; - } - - function updateTabAndPaneNumbers() { - var tabs = selection.select('.' + hypenate(namespace, 'tab-list')), - panes = selection.select('.' + hypenate(namespace, 'tab-content')); - - tabs = tabs.selectAll('.' + hypenate(namespace, 'tab')); - panes = panes.selectAll('.' + hypenate(namespace, 'tab', 'pane')); - - tabs.each(function (d, i) { - d3.select(this).datum(i).attr("id", hypenate(namespace, 'tab', i)).select('a').attr('href', '#' + hypenate(namespace, 'tab', 'pane', i)).text(function (dd, ii) { - var curText = d3.select(this).text(); - if (curText.split(' ')[0] == 'Group') { - return 'Group ' + i; - } - return curText; - }); - }); - - panes.each(function (d, i) { - d3.select(this).datum(i).attr('id', hypenate(namespace, 'tab', 'pane', i)); - safeSelect(d3.select(this), 'p', 'lead').text(function (dd, ii) { - var curText = d3.select(this).text(); - if (curText.split(' ')[0] == 'Group') { - return 'Group ' + i; - } - return curText; - }); - safeSelect(d3.select(this), 'button', 'remove-btn').on('click', removeBtnClickToRemove); - }); - } - - function gatherDataLists() { - var tabs = selection.select('.' + hypenate(namespace, 'tab-list')); - var panes = selection.select('.' + hypenate(namespace, 'tab-content')); - var tables = panes.selectAll('.' + hypenate(namespace, "data-table")); - var data = {}; - - return data; - } - - function showRemainingPanes() { - var tabs = selection.select('.' + hypenate(namespace, 'tab-list')), - panes = selection.select('.' + hypenate(namespace, 'tab-content')), - remainingTabs = tabs.selectAll('.' + hypenate(namespace, 'tab')); - - if (remainingTabs.size() == 0) ; else { - var lastTab = remainingTabs.nodes()[remainingTabs.size() - 1], - lastPaneId = d3.select(lastTab).select('a').attr('href'); - } - } - - return lassoWidget; - } - - function upset(selection) { - var data, - orient = 'horizontal', - spaceX, - spaceY, - overflowQ = false, - minObjectSize = 20, - maxObjectSize = 50, - circleStrokeWidth = 2, - - // colorFunction= - backgroundFill = 'transparent', - namespace = 'd3sm-upset', - objectClass = 'upset', - transitionDuration = 1000, - easeFunc = d3.easeExp, - setKey = "set", - intersectionKey = "intersection", - elementsKey = "elements", - setExtractor = function setExtractor(key, i) { - return data[key][setKey]; - }, - intersectionExtractor = function intersectionExtractor(key, i) { - return data[key][intersectionKey]; - }, - elementExtractor = function elementExtractor(key, i) { - return data[key][elementsKey]; - }, - cellKeys, - setValues, - intersectionValues, - xObjectSpacer = 0.05, - yObjectSpacer = 0.05, - radius, - - - // listDelim = ';' - - yObjectSize, - ySpacerSize, - xObjectSize, - xSpacerSize, - setKeySortingFunction = function setKeySortingFunction(a, b) { - return setValues.indexOf(setExtractor(a)) - setValues.indexOf(setExtractor(b)); - }, - intersectionKeySortingFunction = function intersectionKeySortingFunction(a, b) { - return intersectionValues.indexOf(intersectionExtractor(a)) - intersectionValues.indexOf(intersectionExtractor(b)); - }; - - upset.selection = function (_) { - return arguments.length ? (selection = _, upset) : selection; - }; - upset.data = function (_) { - return arguments.length ? (data = _, upset) : data; - }; - upset.orient = function (_) { - return arguments.length ? (orient = _, upset) : orient; - }; - upset.spaceX = function (_) { - return arguments.length ? (spaceX = _, upset) : spaceX; - }; - upset.spaceY = function (_) { - return arguments.length ? (spaceY = _, upset) : spaceY; - }; - upset.overflowQ = function (_) { - return arguments.length ? (overflowQ = _, upset) : overflowQ; - }; - upset.minObjectSize = function (_) { - return arguments.length ? (minObjectSize = _, upset) : minObjectSize; - }; - upset.maxObjectSize = function (_) { - return arguments.length ? (maxObjectSize = _, upset) : maxObjectSize; - }; - upset.circleStrokeWidth = function (_) { - return arguments.length ? (circleStrokeWidth = _, upset) : circleStrokeWidth; - }; - upset.backgroundFill = function (_) { - return arguments.length ? (backgroundFill = _, upset) : backgroundFill; - }; - upset.namespace = function (_) { - return arguments.length ? (namespace = _, upset) : namespace; - }; - upset.objectClass = function (_) { - return arguments.length ? (objectClass = _, upset) : objectClass; - }; - upset.transitionDuration = function (_) { - return arguments.length ? (transitionDuration = _, upset) : transitionDuration; - }; - upset.easeFunc = function (_) { - return arguments.length ? (easeFunc = _, upset) : easeFunc; - }; - upset.cellKeys = function (_) { - return arguments.length ? (cellKeys = _, upset) : cellKeys; - }; - upset.setValues = function (_) { - return arguments.length ? (setValues = _, upset) : setValues; - }; - upset.intersectionValues = function (_) { - return arguments.length ? (intersectionValues = _, upset) : intersectionValues; - }; - upset.xObjectSpacer = function (_) { - return arguments.length ? (xObjectSpacer = _, upset) : xObjectSpacer; - }; - upset.yObjectSpacer = function (_) { - return arguments.length ? (yObjectSpacer = _, upset) : yObjectSpacer; - }; - upset.radius = function (_) { - return arguments.length ? (radius = _, upset) : radius; - }; - upset.setExtractor = function (_) { - return arguments.length ? (setExtractor = _, upset) : setExtractor; - }; - upset.intersectionExtractor = function (_) { - return arguments.length ? (intersectionExtractor = _, upset) : intersectionExtractor; - }; - upset.elementExtractor = function (_) { - return arguments.length ? (elementExtractor = _, upset) : elementExtractor; - }; - upset.setKeySortingFunction = function (_) { - return arguments.length ? (setKeySortingFunction = _, upset) : setKeySortingFunction; - }; - upset.intersectionKeySortingFunction = function (_) { - return arguments.length ? (intersectionKeySortingFunction = _, upset) : intersectionKeySortingFunction; - }; - - upset.yObjectSize = function (_) { - return arguments.length ? (yObjectSize = _, upset) : yObjectSize; - }; - upset.ySpacerSize = function (_) { - return arguments.length ? (ySpacerSize = _, upset) : ySpacerSize; - }; - upset.xObjectSize = function (_) { - return arguments.length ? (xObjectSize = _, upset) : xObjectSize; - }; - upset.xSpacerSize = function (_) { - return arguments.length ? (xSpacerSize = _, upset) : xSpacerSize; - }; - - function upset() { - // for convenience in handling orientation specific values - var horizontalQ = orient == 'horizontal' ? true : false; - var verticalQ = !horizontalQ; - - // background cliping rectangle - var bgcpRect = { x: 0, y: 0, width: spaceX, height: spaceY }; - var container = setupContainer(selection, namespace, bgcpRect, backgroundFill); - - cellKeys = d3.keys(data); - setValues = unique(cellKeys.map(setExtractor)).sort(); - intersectionValues = unique(cellKeys.map(intersectionExtractor)).sort().sort(function (a, b) { - return a.split(';').length - b.split(';').length; - }); - - if (!horizontalQ) { - cellKeys.sort(function (a, b) { - return setKeySortingFunction(a, b) || intersectionKeySortingFunction(a, b); - }); - } else { - cellKeys.sort(function (a, b) { - return intersectionKeySortingFunction(a, b) || setKeySortingFunction(a, b); - }); - } - - var xValues = horizontalQ ? intersectionValues : setValues, - yValues = horizontalQ ? setValues : intersectionValues, - xDim = horizontalQ ? xValues.length : yValues.length, - yDim = horizontalQ ? yValues.length : xValues.length; - - // console.log(xValues, yValues) - - - xObjectSize = calculateWidthOfObject(spaceX, xDim, minObjectSize, maxObjectSize, xObjectSpacer, overflowQ); - yObjectSize = calculateWidthOfObject(spaceY, yDim, minObjectSize, maxObjectSize, yObjectSpacer, overflowQ); - xSpacerSize = calculateWidthOfSpacer(xValues, spaceX, xObjectSize, xDim, xObjectSpacer, overflowQ); - ySpacerSize = calculateWidthOfSpacer(yValues, spaceY, yObjectSize, yDim, yObjectSpacer, overflowQ); - - var ySpacer = groupingSpacer().horizontalQ(false).moveby('category').numberOfObjects(yDim).objectSize(yObjectSize).spacerSize(ySpacerSize).transitionDuration(transitionDuration).easeFunc(easeFunc); - - var xSpacer = groupingSpacer().horizontalQ(true).moveby('category').numberOfObjects(xDim).objectClass(objectClass).objectSize(xObjectSize).spacerSize(xSpacerSize).transitionDuration(transitionDuration).easeFunc(easeFunc); - - if (verticalQ) { - xSpacer.objectClass(objectClass); - ySpacer.namespace('across').objectClass(hypenate(objectClass, 'across')); - - ySpacer(container, yValues, 0); - container.selectAll('g.' + hypenate(objectClass, 'across')).each(function (d, i) { - xSpacer(d3.select(this), xValues, 0); - }); - } else { - xSpacer.namespace('across').objectClass(hypenate(objectClass, 'across')); - ySpacer.objectClass(objectClass); - - xSpacer(container, xValues, 0); - container.selectAll('g.' + hypenate(objectClass, 'across')).each(function (d, i) { - ySpacer(d3.select(this), yValues, 0); - }); - } - - var cells = container.selectAll('g:not(.to-remove).' + objectClass); - var lookup = {}; - cellKeys.map(function (k, i) { - lookup[setExtractor(k) + '::' + intersectionExtractor(k)] = k; - }); - - // var positionedCellKeys = [] - // for (var i = 0; i < setValues.length; i++) { - // for (var j = 0; j < intersectionValues.length; j++) { - // var lookupValue = lookup[setValues[j]+"::"+intersectionValues[i]] - // if (lookupValue == undefined) { - // positionedCellKeys.push(undefined) - // } else { - // positionedCellKeys.push(lookupValue) - // } - // console.log(i, j, lookupValue) - // } - // } - // - // // console.log(positionedCellKeys) - // - // cells.data(positionedCellKeys); - - - cells.data(cellKeys); - - cells.each(function (key, i) { - var t = d3.select(this); - if (key == undefined) { - return; - } - var currentData = data[key]; - // console.log(key, currentData) - var set = setExtractor(key, i), - intersection = intersectionExtractor(key, i); - - // console.log(set, intersection) - - t.classed(intersection, true); - t.classed(set, true); - - var c = safeSelect(t, 'circle', hypenate(objectClass, 'circle')); - c.attr('cx', xObjectSize / 2).attr('cy', yObjectSize / 2).attr('r', radius == undefined ? Math.min(xObjectSize, yObjectSize) / 2 : radius).attr('fill', intersection.includes(set) ? "black" : 'rgb(233,233,233)').attr('stroke', "black").attr("in-intersection", intersection.includes(set)); - }); - } - - function intersectionTotals() { - var totals = {}; - // intersectionValues.sort(function(a, b){ return intersectionKeySortingFunction(a, b) }) - - intersectionValues.map(function (k, i) { - totals[k] = { 'total': 0 }; - }); - cellKeys.map(function (k, i) { - var e = elementExtractor(k, i); - if (totals[intersectionExtractor(k, i)]['total'] == 0) { - if (Array.isArray(e)) { - totals[intersectionExtractor(k, i)]['total'] += e.length; - totals[intersectionExtractor(k, i)]['values'] = e; - } else { - totals[intersectionExtractor(k, i)]['total'] += e; - } - } - }); - return totals; - } - - function setTotals() { - var totals = {}; - // intersectionValues.sort(function(a, b){ return intersectionKeySortingFunction(a, b) }) - - setValues.map(function (k, i) { - totals[k] = { 'total': 0 }; - }); - - cellKeys.map(function (k, i) { - var e = elementExtractor(k, i); - if (Array.isArray(e)) { - totals[setExtractor(k, i)]['total'] += e.length; - } else { - totals[setExtractor(k, i)]['total'] += e; - } - }); - return totals; - } - - upset.intersectionTotals = intersectionTotals; - upset.setTotals = setTotals; - - return upset; - } - - function filterTable(selection) { - var data, - namespace = 'd3sm-filter-table', - fieldFunction = function fieldFunction(record, columnKey, recordValue) { - return recordValue; - }; - - filterTable.data = function (_) { - return arguments.length ? (data = _, filterTable) : data; - }; - filterTable.namespace = function (_) { - return arguments.length ? (namespace = _, filterTable) : namespace; - }; - filterTable.fieldFunction = function (_) { - return arguments.length ? (fieldFunction = _, filterTable) : fieldFunction; - }; - - function filterTable() { - - var container = safeSelect(selection, 'div', 'filter-table').classed(hypenate(namespace, 'container'), true), - inputGroup = safeSelect(container, 'div', 'filter-input-group').classed('input-group', true), - inputPrepend = safeSelect(inputGroup, 'div', 'input-group-prepend'), - inputPrependSpan = safeSelect(inputPrepend, 'span', 'input-group-text').classed('search-button', true), - inputPrependSpanIcon = safeSelect(inputPrependSpan, 'i', 'fa fa-search'), - input = safeSelect(inputGroup, 'input', 'form-control').attr('placeholder', 'filter').attr('type', 'text'), - inputAppend = safeSelect(inputGroup, 'div', 'input-group-append'), - inputAppendButton = safeSelect(inputAppend, 'a', 'close-button').classed('btn btn-outline-secondary', true), - inputAppendButtonIcon = safeSelect(inputAppendButton, 'i', 'fa fa-close'), - closeButton = inputAppendButton, - rTable = safeSelect(container, 'div', 'table-responsive'), - table = safeSelect(rTable, 'table', 'table').classed('table-hover', true).classed('table-bordered', true).classed("table-striped", true), - tHead = safeSelect(table, 'thead').classed("thead-dark", true), - header = safeSelect(tHead, 'tr'), - tBody = safeSelect(table, 'tbody'); - - var rows = d3.keys(data), - cols = d3.keys(data[rows[0]]); - - var th = makeColumns(header, cols); - var tr = makeRows(tBody, rows); - var tr = populateRecords(tr, cols); - - input.on('input', function (d, i) { - var val = input.property('value'), - reg = new RegExp(val, 'gi'), - use; - if (val == '') { - use = rows; - } else { - use = []; - rows.map(function (r, i) { - var row = data[r]; - var fieldJoin = cols.map(function (c, j) { - return fieldFunction(row, c, row[c]); - // return row[c] - }).join(''); - var match = fieldJoin.match(reg); - if (match == null || match.join('') == '') ; else { - use.push(r); - } - }); - } - - tr = makeRows(tBody, use); - tr = populateRecords(tr, cols); - }); - - closeButton.on('click', function (d, i) { - input.property('value', '').dispatch('input'); - }); - } - - function makeColumns(header, cols) { - var th = header.selectAll('th'); - th = th.data(cols); - th.exit().remove(); - th = th.merge(th.enter().append('th')); - th.attr('scope', 'col').text(function (d, i) { - return d; - }); - return th; - } - - function makeRows(body, rows) { - var tr = body.selectAll('tr'); - tr = tr.data(rows); - tr.exit().remove(); - tr = tr.merge(tr.enter().append('tr')); - return tr; - } - - function populateRecords(rows, cols) { - rows.each(function (r, i) { - var record = data[r], - t = d3.select(this); - - var fields = t.selectAll('td'); - fields = fields.data(cols); - fields.exit().remove(); - fields = fields.merge(fields.enter().append('td')); - - fields.attr('scope', function (f, j) { - return j == 0; - }).html(function (f, j) { - return fieldFunction(record, f, record[f]); - }); - }); - return rows; - } - - return filterTable; - } - - // Import styles (automatically inject into ). - - // /** @module d3sm */ - var d3sm$1 = {}; - d3sm$1.axis = axis; - d3sm$1.bar = bar; - d3sm$1.bubbleHeatmap = bubbleHeatmap; - d3sm$1.heatmap = heatmap; - d3sm$1.boxwhisker = boxwhisker; - d3sm$1.colorFunction = colorFunction; - d3sm$1.datatoggle = datatoggle; - d3sm$1.groupingSpacer = groupingSpacer; - d3sm$1.tooltip = tooltip; - d3sm$1.scatter = scatter; - d3sm$1.plotZoom = plotZoom; - d3sm$1.multiPlotZoom = multiPlotZoom; - d3sm$1.violin = violin; - d3sm$1.numericLegend = numericLegend; - d3sm$1.categoricLegend = categoricLegend; - d3sm$1.lasso = lasso; - d3sm$1.lassoWidget = lassoWidget; - d3sm$1.selectFilter = selectFilter; - d3sm$1.upset = upset; - d3sm$1.filterTable = filterTable; - - d3sm$1.uniqueElements = uniqueElements; - d3sm$1.getTranslation = getTranslation; - d3sm$1.modifyHexidecimalColorLuminance = modifyHexidecimalColorLuminance; - d3sm$1.tickRange = tickRange; - d3sm$1.quartiles = quartiles; - d3sm$1.extractViolinValues = extractViolinValues; - d3sm$1.hypenate = hypenate; - d3sm$1.round = round; - d3sm$1.getContainingSVG = getContainingSVG; - d3sm$1.interpolateColors = interpolateColors; - d3sm$1.truncateText = truncateText; - d3sm$1.safeSelect = safeSelect; - - d3sm$1.whichBin = whichBin; - d3sm$1.unique = unique; - d3sm$1.flatten = flatten; - - d3sm$1.setupStandardChartContainers = setupStandardChartContainers; - d3sm$1.log = log; - d3sm$1.warn = warn; - d3sm$1.info = info; - d3sm$1.error = error; - d3sm$1.consoleGroup = consoleGroup; - d3sm$1.consoleGroupEnd = consoleGroupEnd; - d3sm$1.resizeDebounce = resizeDebounce; - - d3sm$1.debugQ = false; - - // Import a logger for easier debugging - // import debug from 'debug'; - // const log = debug('app:log'); - - // The logger should only be disabled if we're not in production. - // if ("development" !== 'production') { - // // Enable the logger. - // debug.enable('*'); - // log('Logging is enabled!'); - // - // // Enable LiveReload - // document.write( - // ' - - @@ -61,219 +59,6 @@ - + diff --git a/demos/axes/js/v001.js b/demos/axes/js/v001.js index ab67ca491e01128909952036f9e58b9ecf423b75..50cacce12562f43de0796221b04985edcbae81ed 100644 --- a/demos/axes/js/v001.js +++ b/demos/axes/js/v001.js @@ -3,11 +3,11 @@ var data = d3smDemoData['basicViolins'] var selection = d3.select("#axes-by-value") namespace = 'axes', -container = d3sm.safeSelect(selection, 'svg', namespace).style('width', '1000px'), -lAxis = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'left-axis')).attr('transform', "translate(100,100)"), -rAxis = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'right-axis')).attr('transform', "translate(900,100)") -uAxis = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'up-axis')).attr('transform', "translate(100,100)") -dAxis = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'down-axis')).attr('transform', "translate(100,400)") +container = d3sm.utils.sel.safeSelect(selection, 'svg', namespace).style('width', '1000px'), +lAxis = d3sm.utils.sel.safeSelect(container, 'g', d3sm.utils.str.hypenate(namespace, 'left-axis')).attr('transform', "translate(100,100)"), +rAxis = d3sm.utils.sel.safeSelect(container, 'g', d3sm.utils.str.hypenate(namespace, 'right-axis')).attr('transform', "translate(900,100)") +uAxis = d3sm.utils.sel.safeSelect(container, 'g', d3sm.utils.str.hypenate(namespace, 'up-axis')).attr('transform', "translate(100,100)") +dAxis = d3sm.utils.sel.safeSelect(container, 'g', d3sm.utils.str.hypenate(namespace, 'down-axis')).attr('transform', "translate(100,400)") tickValues = [1,2,3,4,5] @@ -27,24 +27,31 @@ var dA = d3sm.axis(dAxis) .spaceX(800) .spaceY(100) .orient("bottom") +.label('bottom') .overflowQ(false) .tickValues(tickValues) .numberOfTicks(5) .namespace('d') // .guideLinesQ(true) .guidelineSpace(300) +.tickLabelRotation(315) +// .tickTickLabelSpacer(0) + var lA = d3sm.axis(lAxis) .spaceX(100) .spaceY(300) .orient("left") +.label('left') .overflowQ(false) .tickValues(tickValues) .numberOfTicks(5) .namespace('l') // .guideLinesQ(true) .guidelineSpace(800) +// .tickLabelRotation(45) + var rA = d3sm.axis(rAxis) .spaceX(100) @@ -56,6 +63,8 @@ var rA = d3sm.axis(rAxis) .namespace('r') // .guideLinesQ(true) .guidelineSpace(800) +// .tickLabelRotation(45) + uA() dA() @@ -67,11 +76,11 @@ rA() var selection = d3.select("#axes-by-cat") namespace = 'axes', -container = d3sm.safeSelect(selection, 'svg', namespace).style('width', '1000px'), -lAxis = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'left-axis')).attr('transform', "translate(100,100)"), -rAxis = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'right-axis')).attr('transform', "translate(900,100)") -uAxis = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'up-axis')).attr('transform', "translate(100,100)") -dAxis = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'down-axis')).attr('transform', "translate(100,400)") +container = d3sm.utils.sel.safeSelect(selection, 'svg', namespace).style('width', '1000px'), +lAxis = d3sm.utils.sel.safeSelect(container, 'g', d3sm.utils.str.hypenate(namespace, 'left-axis')).attr('transform', "translate(100,100)"), +rAxis = d3sm.utils.sel.safeSelect(container, 'g', d3sm.utils.str.hypenate(namespace, 'right-axis')).attr('transform', "translate(900,100)") +uAxis = d3sm.utils.sel.safeSelect(container, 'g', d3sm.utils.str.hypenate(namespace, 'up-axis')).attr('transform', "translate(100,100)") +dAxis = d3sm.utils.sel.safeSelect(container, 'g', d3sm.utils.str.hypenate(namespace, 'down-axis')).attr('transform', "translate(100,400)") tickValues = [1,2,3,4,5] @@ -80,6 +89,7 @@ tickLabels = ["this", "this-text", "this-text-gets", "this-text-gets-longer", "t var uA = d3sm.axis(uAxis) .spaceX(800) .spaceY(100) +.label('top') .orient("top") .overflowQ(false) .categoricalQ(true) @@ -100,6 +110,8 @@ var dA = d3sm.axis(dAxis) .namespace('d-c') // .guideLinesQ(true) .guidelineSpace(300) +// .tickLabelRotation(315) +.tickTickLabelSpacer(0) var lA = d3sm.axis(lAxis) @@ -117,6 +129,7 @@ var lA = d3sm.axis(lAxis) var rA = d3sm.axis(rAxis) .spaceX(100) .spaceY(300) +.label('right') .orient("right") .overflowQ(false) .categoricalQ(true) @@ -136,11 +149,11 @@ rA() var selection = d3.select("#axes-by-val-g") namespace = 'axes', -container = d3sm.safeSelect(selection, 'svg', namespace).style('width', '1000px'), -lAxis = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'left-axis')).attr('transform', "translate(100,100)"), -rAxis = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'right-axis')).attr('transform', "translate(900,100)") -uAxis = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'up-axis')).attr('transform', "translate(100,100)") -dAxis = d3sm.safeSelect(container, 'g', d3sm.hypenate(namespace, 'down-axis')).attr('transform', "translate(100,400)") +container = d3sm.utils.sel.safeSelect(selection, 'svg', namespace).style('width', '1000px'), +lAxis = d3sm.utils.sel.safeSelect(container, 'g', d3sm.utils.str.hypenate(namespace, 'left-axis')).attr('transform', "translate(100,100)"), +rAxis = d3sm.utils.sel.safeSelect(container, 'g', d3sm.utils.str.hypenate(namespace, 'right-axis')).attr('transform', "translate(900,100)") +uAxis = d3sm.utils.sel.safeSelect(container, 'g', d3sm.utils.str.hypenate(namespace, 'up-axis')).attr('transform', "translate(100,100)") +dAxis = d3sm.utils.sel.safeSelect(container, 'g', d3sm.utils.str.hypenate(namespace, 'down-axis')).attr('transform', "translate(100,400)") tickValues = [1,2,3,4,5] diff --git a/demos/axes/js/v003.js b/demos/axes/js/v003.js deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/demos/bar-chart-same-data-complex-grouping/index.html b/demos/bar-chart-same-data-complex-grouping/index.html index 84a766ee1c6e385f187a3830712e749d44840773..cfdb93c40cb8c3bcb1cdcbff91f1bdedd6355f88 100644 --- a/demos/bar-chart-same-data-complex-grouping/index.html +++ b/demos/bar-chart-same-data-complex-grouping/index.html @@ -13,8 +13,8 @@ - - + + @@ -46,6 +46,10 @@ +
+
+
+
@@ -65,17 +69,26 @@ function barPlot( selection ) { var data, - namespace + namespace, + dataSelect plot.data = function(_){return arguments.length ? (data = _, plot) : data; }; plot.namespace = function(_){return arguments.length ? (namespace = _, plot) : namespace; }; function plot() { var - databar = d3sm.safeSelect(selection, 'form', d3sm.hypenate(namespace,'databar')), - dataPrint = d3sm.safeSelect(selection, 'div', d3sm.hypenate(namespace,'data-print')), - - selections = d3sm.setupStandardChartContainers(selection, namespace, {w: 1000, h:500}, undefined, {axes:{x:0.1, y:0.1},space:{w:1,h:1}}) + databar = d3sm.utils.sel.safeSelect(selection, 'form',d3sm.utils.str.hypenate(namespace,'databar')), + dataPrint = d3sm.utils.sel.safeSelect(selection, 'div', d3sm.utils.str.hypenate(namespace,'data-print')), + + selections = d3sm.utils.misc.setupStandardChartContainers( + selection, + namespace, + {w: 1000, h:800}, // container + undefined, // margins + undefined, // svg + {x:0.1, y:0.1}, // axes + {x:0, margin:0, pos:'left'} // leg + ) container = selections.svg.selection, bars = selections.plot.selection, xAxis = selections.xAxis.selection, @@ -83,30 +96,37 @@ // make data selection - var dataSelect = d3sm.datatoggle(databar) - .keys(d3.keys(data.groupings)) - .updateFunction(function(){console.log('update', d3.event);plot(); zoom.reset()}) - .namespace(namespace)() + if (dataSelect == undefined) { + dataSelect= d3sm.aux.datatoggle(databar) + .data({ + 'dataset': data.groupings, + }) + .updateFunction(function(){plot(); zoom.reset()}) + .namespace(namespace) + dataSelect() + } + + var currentKeys = dataSelect.currentKeys() // grab current selected key - var currentKey = dataSelect.currentKey() + var currentDataKey = currentKeys['dataset'] + var currentKey = currentDataKey//dataSelect.currentKey() // // extract subdata // var currentData = data[currentKey] // - + console.log(currentKey) dataPrint.text(JSON.stringify(data.groupings[currentKey])) // make bars - var b = d3sm.bar(bars) + var b = d3sm.charts.bar(bars) .data(data.data) .grouping(data.groupings[currentKey]) .spaceX(selections.plot.rect.w) .spaceY(selections.plot.rect.h) .overflowQ(true) + .orient('horizontal') .maxObjectSize(20) - .objectSpacer(0.05) .minObjectSize(10) - .orient('horizontal') .valueExtractor(function(d, i){return data.data[d]['value'] }) @@ -147,9 +167,9 @@ xA() // b.selection().selectAll("rect").nodes().map(function(d, i){ - // // console.log(d.getBoundingClientRect(), i) + // console.log(d.getBoundingClientRect(), i) // return this - // }) + // }), // console.log( // b.selection().node(), // b.selection().selectAll("rect").nodes(), @@ -163,13 +183,12 @@ // // set-up zoom, whell and drag - var zoom = d3sm.plotZoom(b, xA, yA).eventType('drag') + var zoom = d3sm.aux.plotZoom(b, xA, yA).eventType('drag') .orient('horizontal') // .xLock( // objs.getBBox().width // ) - // console.log(zoom) // zoom.setLocks() @@ -189,6 +208,7 @@ return plot } + }) diff --git a/demos/bar-chart-same-data-complex-grouping/js/v001.js b/demos/bar-chart-same-data-complex-grouping/js/v001.js index 50a640589b7e85f552c0aa75ed4cb46d8d91796d..0d79b660b47be418f0c44f36ef3e19363625e3f7 100644 --- a/demos/bar-chart-same-data-complex-grouping/js/v001.js +++ b/demos/bar-chart-same-data-complex-grouping/js/v001.js @@ -7,8 +7,8 @@ function barPlot( selection ) { function plot() { var - databar = d3sm.safeSelect(selection, 'form', d3sm.hypenate(namespace,'databar')), - dataPrint = d3sm.safeSelect(selection, 'div', d3sm.hypenate(namespace,'data-print')), + databar = d3sm.d3sm.utils.sel.safeSelect(selection, 'form',d3sm.utils.str.hypenate(namespace,'databar')), + dataPrint = d3sm.d3sm.utils.sel.safeSelect(selection, 'div', d3sm.utils.str.hypenate(namespace,'data-print')), selections = d3sm.setupStandardChartContainers(selection, namespace, {w: 1000, h:500}, undefined, {axes:{x:0.1, y:0.1},space:{w:1,h:1}}) container = selections.svg.selection, diff --git a/demos/basic-violins/index.html b/demos/basic-violins/index.html index e0cbea772ea518432e7bf65028f099ea9b5c9a16..6dd08db391647304bdd016f5dd02a5c003d6b701 100644 --- a/demos/basic-violins/index.html +++ b/demos/basic-violins/index.html @@ -13,8 +13,8 @@ - - + + @@ -62,40 +62,50 @@ function violinPlot( selection ) { var data, - namespace + namespace, + dataSelect plot.data = function(_){return arguments.length ? (data = _, plot) : data; }; plot.namespace = function(_){return arguments.length ? (namespace = _, plot) : namespace; }; function plot(){ var - databar = d3sm.safeSelect(selection, 'form', d3sm.hypenate(namespace,'databar')), - dataPrint = d3sm.safeSelect(selection, 'div', d3sm.hypenate(namespace,'data-print')), - - - selections = d3sm.setupStandardChartContainers(selection, namespace, {w: 1000, h:500}, undefined, {space:{w:1,h:1}}) + databar = d3sm.utils.sel.safeSelect(selection, 'form', d3sm.utils.str.hypenate(namespace,'databar')), + dataPrint = d3sm.utils.sel.safeSelect(selection, 'div', d3sm.utils.str.hypenate(namespace,'data-print')), + + + selections = d3sm.utils.misc.setupStandardChartContainers( + selection, + namespace, + {w: 1000, h:800}, // container + undefined, // margins + undefined, // svg + {x:0.1, y:0.1}, // axes + {x:0, margin:0, pos:'left'} // leg + ) container = selections.svg.selection, violins = selections.plot.selection, xAxis = selections.xAxis.selection, yAxis = selections.yAxis.selection - // make data selection - var dataSelect = d3sm.datatoggle(databar) - .keys(d3.keys(data.groupings)) - .currentKey(d3.keys(data.groupings)[0]) - .namespace(namespace) - .updateFunction(function(){ - plot(); - // zoom.reset(); - }) + if (dataSelect == undefined) { + dataSelect= d3sm.aux.datatoggle(databar) + .data({ + 'dataset': data.groupings, + }) + .updateFunction(function(){plot(); zoom.reset()}) + .namespace(namespace) + dataSelect() + } - dataSelect() - var currentKey = dataSelect.currentKey() + var currentKeys = dataSelect.currentKeys() + // grab current selected key + var currentDataKey = currentKeys['dataset'] + var currentKey = currentDataKey//dataSelect.currentKey() dataPrint.text(JSON.stringify(data.groupings[currentKey])) - - var vio = d3sm.violin(violins) + var vio = d3sm.charts.violin(violins) .grouping(data.groupings[currentKey]) .spaceX(selections.plot.rect.w) .spaceY(selections.plot.rect.h) @@ -112,7 +122,7 @@ // var pd = [] vk.map(function(k, i){ pd.push(...d3.values(vv[k].quartiles)) }) - pd = d3sm.unique(pd.sort(function (a, b) {return d3.ascending(a, b)})) + pd = d3sm.utils.arr.unique(pd.sort(function (a, b) {return d3.ascending(a, b)})) // // left axis var yA = d3sm.axis(yAxis) @@ -154,7 +164,7 @@ // // "getBoundingClientRect(): ", l.node().getBoundingClientRect() // // ) // - var zoom = d3sm.plotZoom(vio, xA, yA).eventType('drag') + var zoom = d3sm.aux.plotZoom(vio, xA, yA).eventType('drag') .orient('horizontal') // // diff --git a/demos/box-whiskers-points/index.html b/demos/box-whiskers-points/index.html deleted file mode 100644 index 165e1ac43e4f85992a4f6f6e53f9683dd742259c..0000000000000000000000000000000000000000 --- a/demos/box-whiskers-points/index.html +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - diff --git a/demos/box-whiskers/index.html b/demos/box-whiskers/index.html index 69abf28a7d75cdcabb1bd06e3e361081498e477d..ab45578cfdd73ccb3614d8c765a10407f1865f0c 100644 --- a/demos/box-whiskers/index.html +++ b/demos/box-whiskers/index.html @@ -13,8 +13,8 @@ - - + + @@ -62,32 +62,48 @@ function boxPlot( selection ) { var data, - namespace + namespace, + dataSelect plot.data = function(_){return arguments.length ? (data = _, plot) : data; }; plot.namespace = function(_){return arguments.length ? (namespace = _, plot) : namespace; }; function plot() { var - databar = d3sm.safeSelect(selection, 'form', d3sm.hypenate(namespace,'databar')), - - selections = d3sm.setupStandardChartContainers(selection, namespace, {w: 1000, h:500}, undefined, {axes:{x:0.1, y:0.1},space:{w:1,h:1}}) + databar = d3sm.utils.sel.safeSelect(selection, 'form', d3sm.utils.str.hypenate(namespace,'databar')), + + selections = d3sm.utils.misc.setupStandardChartContainers( + selection, + namespace, + {w: 1000, h:800}, // container + undefined, // margins + undefined, // svg + {x:0.1, y:0.1}, // axes + {x:0, margin:0, pos:'left'} // leg + ) container = selections.svg.selection, chart = selections.plot.selection, xAxis = selections.xAxis.selection, yAxis = selections.yAxis.selection - // make data selection - var dataSelect = d3sm.datatoggle(databar) - .keys(d3.keys(data.groupings)) - .updateFunction(plot) - .namespace(namespace)() + if (dataSelect == undefined) { + dataSelect= d3sm.aux.datatoggle(databar) + .data({ + 'dataset': data.groupings, + }) + .updateFunction(function(){plot(); zoom.reset()}) + .namespace(namespace) + dataSelect() + } + + var currentKeys = dataSelect.currentKeys() // grab current selected key - var currentKey = dataSelect.currentKey() + var currentDataKey = currentKeys['dataset'] + var currentKey = currentDataKey//dataSelect.currentKey() - var bw = d3sm.boxwhisker(chart) + var bw = d3sm.charts.boxwhisker(chart) .data(data.data) .grouping(data.groupings[currentKey]) .spaceX(selections.plot.rect.w) @@ -143,7 +159,7 @@ xA() // // // set-up zoom, whell and drag - var zoom = d3sm.plotZoom(bw, xA, yA).eventType('drag') + var zoom = d3sm.aux.plotZoom(bw, xA, yA).eventType('drag') var pan = d3.zoom().scaleExtent([1,1]).on('zoom', function(){zoom.eventType('drag')()}) container.call(pan).on('wheel', function(){ zoom.eventType('wheel')() }) } diff --git a/demos/bubble-heatmap/index.html b/demos/bubble-heatmap/index.html index 19fc41e621dc2784cb5556e09faf1cd411f4454c..423b32b4bc7d9c29d4bf27056a92174ea086ea10 100644 --- a/demos/bubble-heatmap/index.html +++ b/demos/bubble-heatmap/index.html @@ -13,8 +13,8 @@ - - + + @@ -66,7 +66,15 @@ function plot(){ var - selections = d3sm.setupStandardChartContainers(selection, namespace, {w: 1000, h:750}, undefined, {axes:{x:0.2, y:0.2},space:{w:1,h:1}}) + selections = d3sm.utils.misc.setupStandardChartContainers( + selection, + namespace, + {w: 1000, h:800}, // container + undefined, // margins + undefined, // svg + {x:0.1, y:0.1}, // axes + {x:0, margin:0, pos:'left'} // leg + ) container = selections.svg.selection, bubbles = selections.plot.selection, xAxis = selections.xAxis.selection, @@ -75,7 +83,7 @@ // d3sm.debugQ = true - var bhm = d3sm.bubbleHeatmap(bubbles) + var bhm = d3sm.charts.bubble(bubbles) .spaceX(selections.plot.rect.w) .spaceY(selections.plot.rect.h) .xKey('xKey') @@ -143,7 +151,7 @@ console.log(bhm.selection().node(), bhm.selection().node().getBBox(), bhm.selection().node().getBoundingClientRect()) - var zoom = d3sm.plotZoom(bhm, xA, yA).eventType('drag') + var zoom = d3sm.aux.plotZoom(bhm, xA, yA).eventType('drag') .orient('2D') var pan = d3.zoom().scaleExtent([1,1]).on('zoom', function(){zoom.eventType('drag')()}) diff --git a/demos/bundle/index.html b/demos/bundle/index.html deleted file mode 100644 index 3c70c73ae049c484134526acd59337793e1da957..0000000000000000000000000000000000000000 --- a/demos/bundle/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/demos/filter-select/index.html b/demos/filter-select/index.html deleted file mode 100644 index b289735e081c9e82d21fb3832264812cdb0cf6e1..0000000000000000000000000000000000000000 --- a/demos/filter-select/index.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - Filter Select - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
-
-
- - - - - - - - - - -
-
- - -
-
Rendered with v0.0.2
- -
-
- -
-
-
-
- - - - - - - - - diff --git a/demos/filter-select/js/v002.txt b/demos/filter-select/js/v002.txt deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/demos/filter-table/index.html b/demos/filter-table/index.html deleted file mode 100644 index 1dfaca4d429f928814ee42ecaf67f70d84e44f94..0000000000000000000000000000000000000000 --- a/demos/filter-table/index.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - Filter Table - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
-
Rendered with v0.0.3
- -
-
- -
-
-
-
- - - - - - - - - - diff --git a/demos/heatmap/index.html b/demos/heatmap/index.html index e5c7a19a73ef87270614036869ff09fdc09b21fc..504290f5d05d87da5bf3658bd269cfe4ab920a82 100644 --- a/demos/heatmap/index.html +++ b/demos/heatmap/index.html @@ -13,9 +13,9 @@ - + - + diff --git a/demos/heatmap/js/v003.js b/demos/heatmap/js/v003.js index d8cafa757351500dac373a78d44835a3a4fba808..1846d59c598ecac425a870d371de5abac4cc0771 100644 --- a/demos/heatmap/js/v003.js +++ b/demos/heatmap/js/v003.js @@ -22,9 +22,9 @@ function heatmap ( selection ) { var orient = '2D', - titleContainer = d3sm.safeSelect(selection, 'h5', d3sm.hypenate(namespace,'title')).text(title), + titleContainer = d3sm.utils.sel.safeSelect(selection, 'h5', d3sm.utils.str.hypenate(namespace,'title')).text(title), - selections = d3sm.setupStandardChartContainers( + selections = d3sm.utils.misc.setupStandardChartContainers( selection, namespace, {w:Math.min(window.innerWidth,1200), h:Math.min(window.innerHeight,700)}, @@ -41,11 +41,11 @@ function heatmap ( selection ) { legendSelect = selections.legend.selection - if (chart == undefined){ chart = d3sm.heatmap(chartSelection) } + if (chart == undefined){ chart = d3sm.charts.heatmap(chartSelection) } if (yAxis == undefined) { yAxis = d3sm.axis(yAxisSelection) } if (xAxis == undefined) { xAxis = d3sm.axis(xAxisSelection) } if (legend == undefined) { - legend = d3sm.numericLegend(legendSelect) + legend = d3sm.legends.numeric(legendSelect) .spaceX(selections.legend.rect.w).spaceY(selections.plot.rect.h) } @@ -91,7 +91,7 @@ function heatmap ( selection ) { .overflowQ(overflowQ) .categoricalQ(true) .tickLabels(yk) - .namespace(d3sm.hypenate(namespace,'axis-left')) + .namespace(d3sm.utils.str.hypenate(namespace,'axis-left')) .minObjectSize(chart.yMinObjectSize()) .maxObjectSize(chart.yMaxObjectSize()) .objectSpacer(chart.objectSpacer()) @@ -109,7 +109,7 @@ function heatmap ( selection ) { .overflowQ(overflowQ) .categoricalQ(true) .tickLabels(xk) - .namespace(d3sm.hypenate(namespace,'axis-bottom')) + .namespace(d3sm.utils.str.hypenate(namespace,'axis-bottom')) .minObjectSize(chart.xMinObjectSize()) .maxObjectSize(chart.xMaxObjectSize()) .objectSpacer(chart.objectSpacer()) @@ -119,7 +119,7 @@ function heatmap ( selection ) { .guidelineSpace(selections.yAxis.rect.h) xAxis() - var zoom = d3sm.plotZoom(chart, xAxis, yAxis).eventType('drag') + var zoom = d3sm.aux.plotZoom(chart, xAxis, yAxis).eventType('drag') .orient("vertical") var pan = d3.zoom().scaleExtent([1,1]).on('zoom', function(){zoom.eventType('drag')()}) diff --git a/demos/index.html b/demos/index.html index cbe8679a0ae0a7a3f06f27fe6f045d28436f270f..3f6112af1573e74f404bb658b9441f9a786e7812 100644 --- a/demos/index.html +++ b/demos/index.html @@ -32,17 +32,17 @@

List of demos using d3sm: an extension of d3 by Sumner Magruder

diff --git a/demos/scatter/index.html b/demos/scatter/index.html index 539f4898f859ce720e2b14c53252e01124c7c104..15c2ce7020e719b1f22f2c11a68b99b112437e9d 100644 --- a/demos/scatter/index.html +++ b/demos/scatter/index.html @@ -38,9 +38,9 @@ - + - + @@ -100,10 +100,12 @@ Code for V0.0.1 Code for V0.0.2 Code for V0.0.3 + Code for V0.0.4
+
@@ -112,12 +114,13 @@ - + - - - - - - - - - - - - - - -
- -
-
-
- Tooltip Title -
- - - - - - - - - - - - - - - - - - - -
NameTooltip
Number of Keys4
Color of valuesCoral
Thiskey has a long value
-
-
- -
- - - - diff --git a/demos/upset/index.html b/demos/upset/index.html index a9d1c802c190a132c70982ed3b1c79667483c402..71f5e2e1d1d1799be9e1eac410a29f3d6d9bfcd4 100644 --- a/demos/upset/index.html +++ b/demos/upset/index.html @@ -38,9 +38,9 @@ - + - + @@ -101,6 +101,7 @@ Code for V0.0.3
+
@@ -109,12 +110,13 @@ - + diff --git a/demos/filter-table/js/v003.js b/demos/upset/js/v004.js similarity index 55% rename from demos/filter-table/js/v003.js rename to demos/upset/js/v004.js index a32e9c37e2f1154212166ef5c9e0817688269c91..dbaec0860635c158349d43c65c81ef599d0bed3d 100644 --- a/demos/filter-table/js/v003.js +++ b/demos/upset/js/v004.js @@ -1,12 +1,8 @@ -//VERSION: 0.0.3 -function upset( selection ) { +function upset ( selection ) { var data, - namespace='upset', - barYAxis, - upsetYAxis, - ups, - bar, barR, barRXAxis + namespace='upset' + var upset, @@ -14,9 +10,11 @@ function upset( selection ) { setTotalsBarChart, setTotalsAxis, intersectionTotalsBarChart, - intersectionTotalsAxis + intersectionTotalsAxis, + intersectionSetsAxis plot.data = function(_){return arguments.length ? (data = _, plot) : data; }; + plot.namespace = function(_){return arguments.length ? (namespace = _, plot) : namespace; }; plot.upset = function(_){return arguments.length ? (upset = _, plot) : upset; }; plot.upsetAxis = function(_){return arguments.length ? (upsetAxis = _, plot) : upsetAxis; }; plot.setTotalsBarChart = function(_){return arguments.length ? (setTotalsBarChart = _, plot) : setTotalsBarChart; }; @@ -28,24 +26,27 @@ function upset( selection ) { function plot() { var - svg = d3sm.safeSelect(selection, 'svg'), + svg = d3sm.utils.sel.safeSelect(selection, 'svg'), - upsetAxisSelection = d3sm.safeSelect(svg, 'g', 'upset-chart-axis'), - setTotalsAxisSelection = d3sm.safeSelect(svg, 'g', 'set-bar-chart-axis'), - intersectionTotalsAxisSelection = d3sm.safeSelect(svg, 'g', 'intersection-bar-chart-axis'), + upsetAxisSelection = d3sm.utils.sel.safeSelect(svg, 'g', namespace+'-upset-chart-axis'), + setTotalsAxisSelection = d3sm.utils.sel.safeSelect(svg, 'g', namespace+'-set-bar-chart-axis'), + intersectionTotalsAxisSelection = d3sm.utils.sel.safeSelect(svg, 'g', namespace+'-intersection-bar-chart-axis'), + intersectionSetsAxisSelection = d3sm.utils.sel.safeSelect(svg, 'g', namespace+'-intersection-bar-set-axis'), - upsetSelection = d3sm.safeSelect(svg, 'g', 'upset-chart'), - setTotalsBarChartSelection = d3sm.safeSelect(svg, 'g', 'set-bar-chart'), - intersectionTotalsBarChartSelection = d3sm.safeSelect(svg, 'g', 'intersection-bar-chart') + upsetSelection = d3sm.utils.sel.safeSelect(svg, 'g', namespace+'-upset-chart'), + setTotalsBarChartSelection = d3sm.utils.sel.safeSelect(svg, 'g', namespace+'-set-bar-chart'), + intersectionTotalsBarChartSelection = d3sm.utils.sel.safeSelect(svg, 'g', namespace+'-intersection-bar-chart') - if (upset == undefined) { upset = d3sm.upset(upsetSelection) } + if (upset == undefined) { upset = d3sm.charts.upset(upsetSelection) } if (upsetAxis == undefined) { upsetAxis = d3sm.axis(upsetAxisSelection) } - if (setTotalsBarChart == undefined) { setTotalsBarChart = d3sm.bar(setTotalsBarChartSelection) } + if (setTotalsBarChart == undefined) { setTotalsBarChart = d3sm.charts.bar(setTotalsBarChartSelection) } if (setTotalsAxis == undefined) { setTotalsAxis = d3sm.axis(setTotalsAxisSelection) } - if (intersectionTotalsBarChart == undefined) { intersectionTotalsBarChart = d3sm.bar(intersectionTotalsBarChartSelection) } + if (intersectionTotalsBarChart == undefined) { intersectionTotalsBarChart = d3sm.charts.bar(intersectionTotalsBarChartSelection) } if (intersectionTotalsAxis == undefined) { intersectionTotalsAxis = d3sm.axis(intersectionTotalsAxisSelection) } + if (intersectionSetsAxis == undefined) { intersectionSetsAxis = d3sm.axis(intersectionSetsAxisSelection) } + var @@ -53,19 +54,20 @@ function upset( selection ) { intersectionChartSpacer = 10, percentages = { - inChart: {w: 0.75, h: 0.7 }, + inChart: {w: 0.75, h: 0.5 }, usChart: {w: 0.75, h: 0.2 }, stChart: {w: 0.10, h: 0.2 }, - inAxis : {w: 0.15, h: 0.7 }, + isAxis : {w: 0.75, h: 0.2 }, + inAxis : {w: 0.15, h: 0.5 }, usAxis : {w: 0.15, h: 0.2 }, - stAxis : {w: 0.10, h: 0.2 }, + stAxis : {w: 0.10, h: 0.1 }, - svg: {w: 0.8, h: 0.7} + svg: {w: 1, h: 0.7} } var - page = {w: window.innerWidth, h: window.innerHeight}, + page = {w: selection.node().getBoundingClientRect().width, h: window.innerHeight}, margins = {left: page.w *0.01, right: page.w *0.01, top: page.h*0.01, bottom: page.h*0.01}, svgRect = { _w: page.w * percentages.svg.w, @@ -79,52 +81,59 @@ function upset( selection ) { }, upsetRect = { x: margins.left + (chartRect.w * percentages.stChart.w) + (chartRect.w * percentages.usAxis.w) + setChartSpacer*2, - y: margins.top + chartRect.h * percentages.inChart.h + intersectionChartSpacer, + y: margins.top + chartRect.h * percentages.inChart.h + (chartRect.h * percentages.isAxis.h) + intersectionChartSpacer, w: chartRect.w * percentages.usChart.w, h: chartRect.h * percentages.usChart.h }, upsetAxisRect = { x: margins.left + (chartRect.w * percentages.stChart.w) + (chartRect.w * percentages.usAxis.w) + setChartSpacer, - y: margins.top + chartRect.h * percentages.inChart.h + intersectionChartSpacer, + y: margins.top + chartRect.h * percentages.inChart.h + (chartRect.h * percentages.isAxis.h) + intersectionChartSpacer, w: chartRect.w * percentages.usAxis.w, h: chartRect.h * percentages.usAxis.h }, setTotalsRect = { x: margins.left, - y: margins.top + chartRect.h * percentages.inChart.h + intersectionChartSpacer, + y: margins.top + chartRect.h * percentages.inChart.h + (chartRect.h * percentages.isAxis.h) + intersectionChartSpacer, w: chartRect.w * percentages.stChart.w, h: chartRect.h * percentages.stChart.h }, setTotalsAxisRect = { x: margins.left, - y: margins.top + (chartRect.h * percentages.inChart.h) + (chartRect.h * percentages.stChart.h) + intersectionChartSpacer*2, + y: margins.top + (chartRect.h * percentages.inChart.h) + (chartRect.h * percentages.stChart.h) + (chartRect.h * percentages.isAxis.h) + intersectionChartSpacer*2, w: chartRect.w * percentages.stAxis.w, h: chartRect.h * percentages.stAxis.h }, intersectionTotalsRect = { x: margins.left + (chartRect.w * percentages.stChart.w) + (chartRect.w * percentages.usAxis.w) + setChartSpacer*2, - y: margins.top, + y: margins.top + (chartRect.h * percentages.isAxis.h), w: chartRect.w * percentages.inChart.w, h: chartRect.h * percentages.inChart.h }, intersectionTotalsAxisRect = { x: margins.left + (chartRect.w * percentages.stChart.w) + (chartRect.w * percentages.usAxis.w) + setChartSpacer, - y: margins.top, + y: margins.top + (chartRect.h * percentages.isAxis.h), w: chartRect.w * percentages.inAxis.w, h: chartRect.h * percentages.inAxis.h + }, + intersectionSetsAxisRect = { + x: margins.left + (chartRect.w * percentages.stChart.w) + (chartRect.w * percentages.usAxis.w) + setChartSpacer + intersectionChartSpacer, + y: margins.top + (chartRect.h * percentages.isAxis.h), + w: chartRect.w * percentages.isAxis.w, + h: chartRect.h * percentages.isAxis.h } + svg.attr('width', svgRect._w).attr('height', svgRect._h) upsetAxisSelection.attr('transform', 'translate('+upsetAxisRect.x+','+upsetAxisRect.y+')') setTotalsAxisSelection.attr('transform', 'translate('+setTotalsAxisRect.x+','+setTotalsAxisRect.y+')') intersectionTotalsAxisSelection.attr('transform', 'translate('+intersectionTotalsAxisRect.x+','+intersectionTotalsAxisRect.y+')') + intersectionSetsAxisSelection.attr('transform', 'translate('+intersectionSetsAxisRect.x+','+intersectionSetsAxisRect.y+')') upsetSelection.attr('transform', 'translate('+upsetRect.x+','+upsetRect.y+')') setTotalsBarChartSelection.attr('transform', 'translate('+setTotalsRect.x+','+setTotalsRect.y+')') intersectionTotalsBarChartSelection.attr('transform', 'translate('+intersectionTotalsRect.x+','+intersectionTotalsRect.y+')') - - var overflowQ = false + var overflowQ = true upset .data(data) @@ -132,9 +141,18 @@ function upset( selection ) { .spaceY(upsetRect.h) .xObjectSpacer(0.01) .yObjectSpacer(0.01) - .maxObjectSize(15) - .minObjectSize(15) + .maxObjectSize(5) + .minObjectSize(20) .overflowQ(overflowQ) + .intersectionExtractor(function(k, i){ return data[k].intersection.join(';') }) + .intersectionKeySortingFunction(function(a, b){ + return ( + data[a].intersection.length - data[b].intersection.length + || + upset.intersectionValues().indexOf(data[a].intersection.join(';')) + -upset.intersectionValues().indexOf(data[b].intersection.join(';')) + ) + }) // .radius(1) upset() @@ -148,6 +166,7 @@ function upset( selection ) { .minObjectSize(upset.minObjectSize()) .maxObjectSize(upset.maxObjectSize()) .objectSpacer(upset.yObjectSpacer()) + .tickLabelMargin(30) upsetAxis() @@ -155,6 +174,24 @@ function upset( selection ) { var setTotals = upset.setTotals() + intersectionSetsAxis + .tickLabels(upset.intersectionValues()) + .categoricalQ(true) + .spaceX(intersectionSetsAxisRect.w) + .spaceY(intersectionSetsAxisRect.h) + .orient('top') + .namespace('intersection-sets-name') + .overflowQ(overflowQ) + .minObjectSize(upset.minObjectSize()) + .maxObjectSize(upset.maxObjectSize()) + .objectSpacer(upset.xObjectSpacer()) + .objectSize(upset.xObjectSize()) + .spacerSize(upset.xSpacerSize()) + // .tickLabelRotation(-45) + .tickTickLabelSpacer(0) + + intersectionSetsAxis() + intersectionTotalsBarChart.data(intersectionTotals) .grouping(upset.intersectionValues()) .spaceX(intersectionTotalsRect.w) @@ -166,8 +203,25 @@ function upset( selection ) { .minObjectSize(upset.minObjectSize()) .maxObjectSize(upset.maxObjectSize()) .objectSpacer(upset.xObjectSpacer()) + .objectSize(upset.xObjectSize()) + .spacerSize(upset.xSpacerSize()) + intersectionTotalsBarChart.tooltip().keys(['Amount','Values']) + .values([ + function(currentData, d){ + return currentData.total + }, + function(currentData, d){ + var l = currentData.values.length + // return currentData + return currentData.values.join(', ').slice(0,100)+ ((l > 100) ? '...': '') + } + ]) + + // intersectionTotalsBarChart.colorFunction().colors(['cyan', 'blue']).colorBy('value') + + // intersectionSetsAxis() intersectionTotalsBarChart() intersectionTotalsAxis @@ -195,10 +249,14 @@ function upset( selection ) { .minObjectSize(upset.minObjectSize()) .maxObjectSize(upset.maxObjectSize()) .objectSpacer(upset.yObjectSpacer()) - + .objectSize(upset.yObjectSize()) + .spacerSize(upset.ySpacerSize()) + .barPercent(0.75) setTotalsBarChart() + + setTotalsAxis .spaceX(setTotalsAxisRect.w) .spaceY(setTotalsAxisRect.h) @@ -211,11 +269,32 @@ function upset( selection ) { setTotalsAxis() - // var zoom = d3sm.plotZoom(upset, upsetAxis, function(){}).eventType('drag').orient('2D') - // var pan = d3.zoom().scaleExtent([1,1]).on('zoom', function(){ zoom.eventType('drag')() }) - // upsetSelection.call(pan).on('wheel', function(){ zoom.eventType('wheel')() }) + + + + var zoom = d3sm.aux.multiPlotZoom(upset).eventType('drag').orient('2D') + .xComponents([ + intersectionTotalsBarChart, + intersectionSetsAxis + ]) + .yComponents([ + upsetAxis, + setTotalsBarChart + ]) + var pan = d3.zoom().scaleExtent([1,1]).on('zoom', function(){ zoom.eventType('drag')() }) + upsetSelection.call(pan).on('wheel', function(){ zoom.eventType('wheel')() }) + intersectionTotalsBarChartSelection.call(pan).on('wheel', function(){ zoom.eventType('wheel')() }) + + + + intersectionTotalsBarChartSelection.selectAll('.bar.intersections > rect.bar-rect').on('click', function(d, i){ + console.log( d, i) + }) + // selection.selectAll('text').attr('pointer-events', 'none') + // .attr('pointer-events', 'none') + } return plot diff --git a/demos/vertical-violins/index.html b/demos/vertical-violins/index.html index 402097085683f6cf3e750b815e099fa64040e8d6..6f33aefde07b6699b08bade2fa9999e4bbc03c72 100644 --- a/demos/vertical-violins/index.html +++ b/demos/vertical-violins/index.html @@ -13,9 +13,9 @@ - - + + @@ -44,7 +44,7 @@ @@ -53,7 +53,8 @@ - + diff --git a/needs-to-be-bundled/distribution.js b/needs-to-be-bundled/distribution.js deleted file mode 100644 index 781b50db408baef1b82458d4007d78b723af8a0c..0000000000000000000000000000000000000000 --- a/needs-to-be-bundled/distribution.js +++ /dev/null @@ -1,241 +0,0 @@ -function distribution() { - // variables that need to be set externally - var container, - drawingSpace, - colors = ["#2c7bb6", "#00a6ca", "#00ccbc", "#90eb9d", "#ffff8c", "#f9d057", "#f29e2e", "#e76818", "#d7191c"], - data, - vScale = d3.scaleLinear(), // scale for values - nScale = d3.scaleLinear(), // number of elements - vKey, - cKey, - cOpacity = 0.2, - strokeWidth = 2, - cScale = d3.scaleSequential(interpolateColors.apply(this, colors)), - histogram, - curve = d3.curveBasis, - distributionContainer, - distributionPath, - rotation='up', - rangePad = 2 - - // variables set internally - var pointsNeeded, currentNumberOfPoints, - values, yValues, rValues, cValues, - dataExtent, fatal, - verbose = true, - animationTime = 1000, - svg - - var hexademicalOpacity = { - 1.0: "FF", 0.9: 'E6', 0.8: 'CC', - 0.7: "B3", 0.6: "99", 0.5: "80", - 0.4: "66", 0.3: "4D", 0.2: "33", - 0.1: "1A", 0.0: "00" - } - - - - - function plot(){ - fatal = warn(container, 'container', undefined, true, verbose) - if ( fatal ) {return} - fatal = warn(data, 'data', undefined, true, verbose) - if ( fatal ) {return} - fatal = warn(vKey, 'vKey', undefined, true, verbose) - if ( fatal ) {return} - fatal = warn(drawingSpace, 'drawingSpace', undefined, true, verbose) - if ( fatal ) {return} - - - svg = d3.select(container.thisSVG()) - - vValues = data.map( function(d, i) { return parseFloat( d[vKey] ) } ) - histogram = d3.histogram().value( function( d ){ return d[vKey] } )(data) - - nValues = histogram.map( function(bin, i) { return bin.length } ) - - - dataExtent = { - v: { - min: d3.min( vValues ), - max: d3.max( vValues ) - }, - n: { - min: d3.min( nValues ), - max: d3.max( nValues ) - } - } - - vScale.domain([ dataExtent.v.min -rangePad, dataExtent.v.max+rangePad ]) - .range([ 0, drawingSpace.x ]) - - nScale.domain([ 0, dataExtent.n.max ]) - .range([ drawingSpace.y, 0 ]) - - - if (cKey != undefined) { - cValues = data.map( function(d, i) { return parseFloat( d[cKey] ) } ) - cScale.domain([ d3.min(cValues), d3.max(cValues) ]) - } - - - - - histoMin = [] - histoMin.x0 = dataExtent.v.min - histoMin.x1 = dataExtent.v.min - - histoMax = [] - histoMax.x0 = dataExtent.v.max - histoMax.x1 = dataExtent.v.max - - - - line = d3.line() - .x( function(bin, i) { return vScale( d3.median( [bin.x0, bin.x1] ) ) }) - .y( function(bin, i) { return nScale( bin.length ) } ) - .curve(curve) - - - - - distributionContainer = container.select('g.distribution-container') - if (distributionContainer.empty()) { - distributionContainer = container.append('g') - .attr('class','distribution-container') - .data([histogram]) - - distributionContainer.append('path') - .attr('class', 'distribution-path') - } - - distributionPath = distributionContainer.select('path.distribution-path') - distributionPath.attr('d', function(d, i) { - var hist = [histoMin].concat(d).concat([histoMax]) - return line(hist) - }) - .attr('fill', function(d, i){ - if (cKey == undefined) { - var colorI = i % colors.length - var c = colors[colorI] - if (c.includes("#") && cOpacity != undefined) { - c += hexademicalOpacity[cOpacity] - } - return c - } else { - var c = cScale(d[cKey]) - if (c.includes("#") && cOpacity != undefined) { - c += hexademicalOpacity[cOpacity] - } else { - [r, g, b] = c.slice(3).split(',') - b = b.split(')').join('') - r = r.split('(').join('') - return 'rgb('+r+','+g+','+b+','+cOpacity+')' - } - return c - } - }) - .attr('stroke-width', strokeWidth) - .attr('stroke', function(d, i){ - if (cKey == undefined) { - var colorI = i % colors.length - var c = colors[colorI] - return c - } else { - return cScale(d[cKey]) - } - }) - - distributionContainer.attr('transform', function(d, i){ - var box = container.node().getBBox() - - var rx, ry, rr, tx, ty - - if (rotation == 'right') { - rr = 90 - rx = 0 - ry = 0 - tx = drawingSpace.y - ty = drawingSpace.x - } else if (rotation == 'left') { - rr = -90 - rx = 0 - ry = 0 - tx = 0 - ty = drawingSpace.x - } else if (rotation == 'down') { - rr = 180 - rx = drawingSpace.x / 2 - ry = drawingSpace.y / 2 - tx = - drawingSpace.x - ty = 0 - } else { - rr = 0 - rx = drawingSpace.x / 2 - ry = drawingSpace.y / 2 - tx = 0 - ty = 0 - } - - - var scale = 'scale(-1, 1)' - var rot = 'rotate('+rr+','+rx+','+ry+')' - var trans = 'translate('+tx+','+ty+')' - - if (rotation == 'down') { - return trans + rot + scale - } - if (rotation == 'right') { - return trans + rot + scale - } - return trans+rot - // return Math.abs(rotation / 180) >= 1 ? - // 'rotate('+rotation+',' + box.width / 2 + ',' + box.height + ')' - // : - // 'rotate('+rotation+',' + box.width + ',' + box.height / 2 + ')translate(0,'+-box.width+') ' - }) - - - - } - - - function setupSettersAndGetters() { - var closuredVariables = [ - 'container', - 'drawingSpace', - 'data', - 'colors', - 'vKey', 'cKey', - 'vScale', 'nScale', - 'vValues', 'nValues', - 'values', - 'cScale', - 'cOpacity', - 'strokeWidth', - 'xValues','yValues','cValues', - 'dataExtent', 'fatal', - 'verbose', 'animationTime', - 'svg', 'histogram', - 'rotation', - 'rangePad' - ] - - - for (var i = 0; i < closuredVariables.length; i++) { - var currentClosureVariable = closuredVariables[i] - var toEvaluateString = " \ - plot." + currentClosureVariable + " = function(value){ \ - if(!arguments.length) return " + currentClosureVariable + "; \ - " + currentClosureVariable + " = value; \ - return plot; \ - }; \ - " - eval(toEvaluateString) - } - } - - - setupSettersAndGetters() - return plot; -} diff --git a/needs-to-be-bundled/graph.js b/needs-to-be-bundled/graph.js deleted file mode 100644 index 4bbe410f7374c49d9ea70e2d925b541213e61324..0000000000000000000000000000000000000000 --- a/needs-to-be-bundled/graph.js +++ /dev/null @@ -1,806 +0,0 @@ -function plot() { - var id, // svg ID - to='html', // scale svg to - x, // svg width either in pixels or percent - y, // svg height either in pixels or percetn - plot // plot type - - // internal variables - var svg - - - function configureSVG() { - if (to == undefined) { - svg.style("width", x + 'px') - svg.style("height", y + 'px') - return - } - - var el = d3.select(to).node() // element to scale to - var rect = el.getBoundingClientRect() // boundaries of the element - var css = getComputedStyle(el) // rendered css styles - - - var w = rect.width - parseFloat(css.paddingLeft) - parseFloat(css.paddingRight) // remove padding - var h = rect.height - parseFloat(css.paddingTop) - parseFloat(css.paddingBottom) - - var width, height - - if (String(x).includes('%')) { width = w * parseFloat(x) / 100 } - else if (x <= 1) { width = w * x} - else { width = x} - - if (String(y).includes('%')) { height = h * parseFloat(y) / 100 } - else if (x <= 1) { height = h * y} - else { height = y} - - - svg.style("width", width + 'px') - svg.style("height", height + 'px') - return - } - - function make() { - svg = d3.select('[id='+id+']') - configureSVG() - - plot.width(parseFloat(svg.style('width'))) - plot.height(parseFloat(svg.style('height'))) - - plot() - } - - function setupSettersAndGetters() { - var closuredVariables = [ - 'id', - 'to', - 'x', - 'y', - 'plot' - ] - - for (var i = 0; i < closuredVariables.length; i++) { - var currentClosureVariable = closuredVariables[i] - var toEvaluateString = " \ - make." + currentClosureVariable + " = function(value){ \ - if(!arguments.length) return " + currentClosureVariable + "; \ - " + currentClosureVariable + " = value; \ - return make; \ - }; \ - " - eval(toEvaluateString) - } - } - setupSettersAndGetters() - return make; - -} - - -function sugiyama() { - /* GRAPH DATA VARIABLES*/ - var vertexSet, - edgeSet, - dummySet, - realSet, - layering, - vertexKeys, - edgeKeys, - vertexMeta, - edgeMeta, - pathwayMeta, - pubmedMeta, - datasourceMeta - - - - /* GRAPH DRAWING VARIABLES*/ - var container, - vertexContainer, - vertexGroup, - edgeContainer, - edgeGroup, - width, - height, - - layout, - - xScale = d3.scaleLinear(), - yScale = d3.scaleLinear(), - - rangePad = 2, - - xCoordinates, - yCoordinates, - - dataExtent, - - zoom = d3.zoom() - .scaleExtent([0.25, 1.75]) - .on("zoom", containerZoom), - panRatio = 0.1 - - function containerZoom(){ - container.attr('transform', d3.event.transform) - } - - function containerZoomReset(){ - svg.call(zoom.transform, d3.zoomIdentity) - } - - /* GRAPH STYLE VARIABLES */ - var vertexRadius = 15, - vertexFill = '#333333', // vertex color - vertexStroke = '#333333', // vertex stroke - vertexStrokeWidth = 1, // vertex stroke - - textSize=7.5, // font size for vertex labels - textWeight = "900" // font weight for vertex labels - textStroke = '#333333', // stroke of vertex font (should match vertex color) - textStrokeWidth = 0.1, // stroke size of vertex font - textFill = 'white', // color of vertex font - - edgeLine = d3.line() - .x(function(d) { return d.x; }) - .y(function(d) { return d.y; }) - .curve(d3.curveMonotoneX), - // .curve(d3.curveBasis), - // .curve(d3.curveLinear), - - edgeStroke = "#333333", // color of edges - edgeStrokeMin = 2, - edgeStrokeMax = 10, - edgeStrokeScale = d3.scaleLinear().range([edgeStrokeMin, edgeStrokeMax]), - edgeStrokeWidth = edgeWidth, - - hoverOpacityDecrease = 0.2, - vertexIncreasedExpression = 'red', - vertexDecreasedExpression = 'blue' - - - function edgeWidth(edgeKey) { - var e = edgeSet[edgeKey] - if (edgeSet[edgeKey].meta) { - return edgeSet[edgeKey].meta.pubmed_ids.length - } else { - return edgeStrokeMin - } - } - - function vertexFillColor(vertexKey) { - var v = vertexSet[vertexKey] - - if (v.class.includes('dummy')) { return vertexFill } - - - if (v.expression) { - return (v.expression > 0) ? vertexIncreasedExpression : vertexDecreasedExpression - } else { - return vertexFill - } - } - - - function predraw() { - vertexKeys = d3.keys( vertexSet ) - edgeKeys = d3.keys( edgeSet ) - - xCoordinates = vertexKeys.map( function(d, i) { return vertexSet[d].coordinates.x }) - yCoordinates = vertexKeys.map( function(d, i) { return vertexSet[d].coordinates.y }) - - numPubs = edgeKeys.map( function (d, i) {if ( edgeSet[d].meta == undefined) {return edgeStrokeMin } return edgeSet[d].meta.pubmed_ids.length } ) - - dataExtent = { - x: { - min: d3.min( xCoordinates ), - max: d3.max( xCoordinates ) - }, - y: { - min: d3.min( yCoordinates ), - max: d3.max( yCoordinates ) - }, - pubs: { - min: d3.min( numPubs ), - max: d3.max( numPubs ) - } - - } - - - xScale.domain([ dataExtent.x.min - rangePad, dataExtent.x.max + rangePad ]) - .range([ 0 + vertexRadius, width - vertexRadius ]) - - yScale.domain([ dataExtent.y.min - rangePad, dataExtent.y.max + rangePad ]) - .range([ 0 + vertexRadius, height - vertexRadius ]) - - edgeStrokeScale.domain([ dataExtent.pubs.min, dataExtent.pubs.max ]) - - edgeLine.x(function(d) { return xScale(d.x); }) - .y(function(d) { return yScale(d.y); }) - - zoom.translateExtent([[width * panRatio * -1, height * panRatio * -1], [width * (1+panRatio), height * (1+panRatio)]]) - d3.select(container.thisSVG()).call(zoom) - - vertexContainer = container.select(".vertex-container") - vertexGroup = container.selectAll(".vertex-group") - - edgeContainer = container.select(".edge-container") - edgeGroup = container.selectAll(".edge-group") - - realSet = new Set([].concat.apply([],d3.keys(edgeSet).map(function(e,i){return [edgeSet[e].source, edgeSet[e].target]}))) - dummySet = new Set( d3.keys(vertexSet).map(function(v,i) {if (!realSet.has(v)) {return v}})) - } - - - function _vertex_setup() { - - if (vertexContainer.empty()) { - vertexContainer = container.append("g").attr("class", "vertex-container") - } else { - vertexContainer = container.select('.vertex-container') - } - - var neededVertices = vertexKeys.length - var currentVertices = vertexGroup.size() - if (currentVertices < neededVertices) { - vertexGroup = vertexContainer.selectAll(".vertex-group") - .data(vertexKeys).enter() - .append("g").attr("class", "vertex-group") - .attr("id", function(d, i){return d}) - - vertexGroup.each(function(d, i){ - var thisV = d3.select(this) - if (!dummySet.has(d)) { - thisV.append("circle").attr('class', 'vertex-shape') - thisV.append("text").attr('class', 'vertex-label') - } else { - thisV.classed("dummy", true) - thisV.append("rect").attr('class', 'vertex-shape') - } - }) - } else if (currentVertices > neededVertices) { - vertexGroup = vertexContainer.selectAll(".vertex-group") - .data(vertexKeys).exit().remove() - } else { - vertexGroup = vertexContainer.selectAll(".vertex-group").data(vertexKeys) - vertexGroup.each(function(d, i){ - var thisV = d3.select(this) - thisV.attr("id", function(d, i){return d}) - // console.log(d, dummySet.has(d)) - if (!dummySet.has(d)) { // real vertex - var circ, rect, text - circ = thisV.select('circle') - rect = thisV.select('rect') - text = thisV.select('text') - - if ( !rect.empty() ) { rect.remove() } - if ( circ.empty() ) { thisV.append('circle').attr('class', 'vertex-shape') } - text.attr('class', 'vertex-label') - - thisV.classed("dummy", false) - } else { // dummy vertex - var circ, rect, text - circ = thisV.select('circle') - rect = thisV.select('rect') - text = thisV.select('text') - - if ( rect.empty() ) { thisV.append('rect').attr('class', 'vertex-shape') } - if ( !circ.empty() ) { circ.remove() } - - thisV.classed("dummy", true) - } - }) - } - - vertexGroup = vertexContainer.selectAll(".vertex-group").data(vertexKeys) - - - - vertexGroup.on("mouseover", vertexMouseover) - vertexGroup.on("mouseout", vertexMouseout) - vertexGroup.call(d3.drag() - .on("start", vertexDragStart) - .on("drag", vertexDrag) - .on("end", vertexDragStop)); - - } - - - - function _vertex_style() { - - vertexGroup.attr("transform", function(d, i) { - var x = xScale(vertexSet[d].coordinates.x) - var y = yScale(vertexSet[d].coordinates.y) - var t = "translate("+x+","+y+")" - return t - }).each( function(d, i) { - var thisV = d3.select(this) - if (!dummySet.has(d)) { - thisV.select("text") - .text(d) - .attr("text-anchor", "middle") - .style("font-size",textSize) - .style("stroke", textStroke) - .style("stroke-width", textStrokeWidth) - .style("fill", textFill) - .style("font-weight", textWeight) - .style("cursor", "default") - .style("-webkit-user-select", "none") - .style("-moz-user-select", "none") - .style("-ms-user-select", "none") - .style("user-select", "none") - .attr("transform", function(d, i) { - var x = 0 - var y = textSize / 4 + textSize / 8 - var t = "translate("+x+","+y+")" - return t - }) - - thisV.select("circle") - .attr("stroke", vertexFillColor(d)) - .attr("fill", vertexFillColor(d)) - .attr("r", vertexRadius) - - } else { - thisV.select("rect") - .attr("stroke", vertexFillColor(d)) - .attr("fill", vertexFillColor(d)) - .attr("width", vertexRadius * 2) - .attr("height", vertexRadius * 2) - .attr("transform", function(d, i) { - var x = -vertexRadius - var y = -vertexRadius - var t = "translate("+x+","+y+")" - return t - }) - .style("opacity", 0) - } - }) - } - - function drawVertices() { - _vertex_setup() - _vertex_style() - } - - - function _edge_setup() { - - if (edgeContainer.empty()) { edgeContainer = container.append("g").attr("class", "edge-container") } - else { edgeContainer = container.select("g.edge-container")} - - var neededEdges = edgeKeys.length - var currentEdges = edgeContainer.size() - - if (currentEdges < neededEdges) { - edgeGroup = edgeContainer.selectAll(".edge-group") - .data(edgeKeys).enter() - .append("g").attr("class", "edge-group") - .attr("id", function(d, i){return d}) - - edgeGroup.each(function(d, i){ - thisE = d3.select(this) - thisE.append("path") - }) - } else if (neededEdges < currentEdges) { - edgeGroup = edgeContainer.selectAll(".edge-group") - .data(edgeKeys) - .exit().remove() - } else { - edgeGroup = edgeContainer.selectAll(".edge-group") - .data(edgeKeys) - } - - edgeGroup = edgeContainer.selectAll(".edge-group").data(edgeKeys) - - } - - function _edge_style() { - edgeGroup.each(function(d, i) { - var thisE = d3.select(this) - var coords = edgeSet[d].path.map(function(e, j) { return vertexSet[e].coordinates }) - thisE.select("path") - .attr("fill", "none") - .attr("stroke-width", edgeStrokeScale(edgeStrokeWidth(d))) - .attr("stroke", edgeStroke) - .attr("fill", "none") - .attr("d", edgeLine(coords)) - .on('mouseover', edgeMouseover) - .on('mouseout', edgeMouseout) - // .attr("stroke-dasharray", function(){ - // // console.log(d, d3.select(this)) - // return d3.select(this).node().getTotalLength() * 0.8 - // }) - - }) - edgeContainer.lower() - } - - function drawEdges() { - _edge_setup() - _edge_style() - } - - function draw() { - predraw() - drawVertices() - drawEdges() - } - - - function vertexMouseover(d, i) { - - var thisV = d3.select(this) - - if ( thisV.classed("dummy") ) { - thisV.select("rect").style("opacity","0.5") - return - } - - var adj = vertexSet[d].predecessors.concat(vertexSet[d].successors).concat([d]) - // console.log(d, adj) - - vertexKeys.map(function(dd, j){ - var cV = d3.select("[id='"+dd+"']") - if (adj.indexOf(dd) == -1) { - cV.style("opacity", hoverOpacityDecrease) - } - }) - - edgeKeys.map(function(dd, j){ - var cE = d3.select("[id='"+dd+"']") - if (edgeSet[dd].source != d && edgeSet[dd].target != d) { - cE.style("opacity", hoverOpacityDecrease) - } - }) - - - var ttip = d3.select('#graph-tooltip') - if (ttip.empty()) { ttip = d3.select("html").append('div').attr('id', 'graph-tooltip') } - var [div, title, body, close, txt, move] = setupTooltipCard( ttip ) - - if (!body.selectAll('*').empty()) {body.selectAll('*').remove()} - body.html('GeneCards: ') - - var bodyA = body.select('a') - if (bodyA.empty()) {bodyA = body.append('a'); bodyA.append('strong')} - bodyA.attr('href', 'http://www.genecards.org/cgi-bin/carddisp.pl?gene='+d) - .html(d).attr('class', 'gene-card').attr("target", '_blank') - - txt.html(d) - } - - function vertexMouseout(d, i) { - - var thisV = d3.select(this) - - d3.keys(vertexSet).map(function(dd, j){ - var cV = d3.select("[id='"+dd+"']") - cV.style("opacity", 1) - }) - - if ( thisV.classed("dummy") ) { - thisV.select("rect").style("opacity","0") - } - - d3.keys(edgeSet).map(function(dd, j){ - var cE = d3.select("[id='"+dd+"']") - cE.style("opacity", 1) - }) - - } - function vertexDragStart(){} - function vertexDrag(d, i){ - var curV = d3.select(this) - var m = d3.mouse(container.node()) - - vertexSet[d].coordinates.x = xScale.invert(m[0]) - vertexSet[d].coordinates.y = yScale.invert(m[1]) - - - curV.raise() - .attr("transform",function(d, i) { - x = m[0] - y = m[1] - trans = "translate("+x+","+y+")" - return trans - }) - - drawEdges() - } - function vertexDragStop(){} - - function edgeMouseout(d, i) { - var ttip = d3.select('#graph-tooltip') - // if (!ttip.empty()) { ttip.remove() } - } - - - function makeCloseButton(closeSelection, containerSelection) { - if (closeSelection.empty()) {closeSelection = containerSelection.append('button') - .attr('type', 'button') - .attr('class', 'close align-middle tt-close') - .attr('data-dismiss', 'alert') - .on('click', function(){d3.select("#graph-tooltip").transition().duration(300).style('opacity', 0).remove()}) - .append('i').attr('class', "fa fa-times fa-lg") - .style('color', '#000') - } - } - function makeMoveButton(moveSelection, containerSelection, toMoveSelection) { - if (moveSelection.empty()) { - moveSelection = containerSelection.append('button') - .attr('class', 'move close') - .call(d3.drag().on('drag', function(){ - var m = d3.mouse(moveSelection.node()) - toMoveSelection.style('left', (parseFloat(toMoveSelection.style('left'))+m[0])+'px') - .style('top', (parseFloat(toMoveSelection.style('top'))+m[1])+'px') - })) - .style('float','right') - .style('padding','none') - .append('i').attr('class','fa fa-arrows-alt fa-sm') - .style('color', '#000') - .style('margin-right', '3px') - } - } - function movePercentInsideHtml(div, mouse, percent) { - var html = d3.select('html').node().getBoundingClientRect() - var left = Math.min( mouse[0], html.width - (html.width * percent) ) - div.transition().duration(200).style('left', left+'px').style('top', mouse[1]+'px') - } - - function setupTooltipCard( tooltip ) { - var div = tooltip.select('div.card') - var m = d3.mouse.absolute() - - if (div.empty()) { div = tooltip.append('div').attr('class', 'card col-3 px-0').style('position', 'absolute').style('left', m[0]+'px').style('top', m[1]+'px') } - movePercentInsideHtml(div, m, 0.25) - - var title, body, footer, datasources, interactions, pubmedids, pathways, close, txt, move - title = div.select('div.card-header') - body = div.select('div.card-body') - close = title.select('button.tt-close') - txt = title.select('h6') - move = title.select('button.move') - - if (title.empty()) {title = div.append('div').attr('class','card-header card-title')} - if (txt.empty()) {txt = title.append('h6').style('display', 'inline-block')} - - makeCloseButton(close, title) - makeMoveButton(move, title, div) - - if (body.empty()) {body = div.append('div').attr('class','card-body')} - return [div, title, body, close, txt, move] - } - - function edgeMouseover(d, i) { - var thisE = d3.select(this) - if (edgeMeta == undefined) { return } - - var ttip = d3.select('#graph-tooltip') - if (ttip.empty()) { ttip = d3.select("html").append('div').attr('id', 'graph-tooltip') } - - var [div, title, body, close, txt, move] = setupTooltipCard( ttip ) - - var bodyA = body.select('a.gene-card') - if (!bodyA.empty()) {bodyA.remove()} - - var bodyUL = body.select('ul.list-group') - if (bodyUL.empty()) {bodyUL = body.append('ul').attr('class', 'list-group well')} - - var metakeys = [] - var raw_metakeys = ['datasources', "interactions", 'pathways', 'pubmed_ids'] - raw_metakeys.map(function(k, i){ - if((edgeMeta[d][k].length > 0) && (d3.keys(edgeMeta[d][k]).length > 0)) {metakeys.push(k)} - }) - - var bodyUlLis = setupTooltipCardBodyUl( bodyUL, metakeys ) - fillTooltipCardBodyUlList ( d, bodyUlLis, edgeMeta ) - - txt.html(d.split('_')[0] + '' + d.split('_')[1]) - } - - function setupTooltipCardBodyUl( bodyUL, metakeys ) { - var bodyUlLis = bodyUL.selectAll('li.outer-item') - if (metakeys.length > bodyUlLis.size()) { - bodyUlLis = bodyUL.selectAll('li.outer-item') - .data(metakeys).enter() - .append('li') - .attr('class', 'list-group-item list-group-item-action outer-item toolbar-list-group-item') - .attr('href', function(d){return'#'+'graph-tooltip-'+d}).attr('data-toggle', 'collapse') - - bodyUlLis.append('i').attr('class', 'fa fa-caret-right') - bodyUlLis.append('h6').style('display', 'inline') - - bodyUlLis.on('click', function() { - var i = d3.select(this).select('i') - if (i.classed('fa-caret-right')) {i.classed('fa-caret-down', true).classed('fa-caret-right', false)} - else {i.classed('fa-caret-down', false).classed('fa-caret-right', true)} - }) - - } else if (metakeys.length < bodyUlLis.size()) { - bodyUlLis = bodyUL.selectAll('li.outer-item').data(metakeys).exit().remove() - } else { - bodyUlLis = bodyUL.selectAll('li.outer-item').data(metakeys) - } - bodyUlLis = bodyUL.selectAll('li.outer-item').data(metakeys) - - return bodyUlLis - } - - function fillTooltipCardBodyUlList ( edgeKey, bodyUlLis, edgeMeta ) { - bodyUlLis.selectAll('h6').html(function(d, i){return d}) - bodyUlLis.each(function (dd, ii) { - var li = d3.select(this) - var liUl = li.select('ul') - if (liUl.empty()) { - liUl = li.append('ul') - .attr('class', 'list-group collapse indent-1') - .attr('id',function(d){return 'graph-tooltip-'+d}) - .style('max-height', '200px') - .style('overflow-y', 'scroll') - } - var dataToUse = edgeMeta[edgeKey][dd] - dataToUse = (dd == 'pathways') ? d3.keys(dataToUse) : dataToUse - var liUlLis = liUl.selectAll('li') - - if (liUlLis.size() < dataToUse.length) { liUlLis = liUl.selectAll('li').data(dataToUse).enter().append('li').attr('class', 'list-group-item list-group-item-action toolbar-list-group-item') } - else if (liUlLis.size() > dataToUse.length) { liUlLis = liUl.selectAll('li').data(dataToUse).exit().remove() } - else { liUlLis = liUl.selectAll('li').data(dataToUse) } - - if (dd == 'datasources') { _makeSubListFromMeta(liUlLis, datasourceMeta) } - else if (dd == 'pathways') { _makeSubListFromMeta(liUlLis, pathwayMeta) } - else if (dd == 'pubmed_ids') { _makeSubListFromMeta(liUlLis, pubmedMeta, 'uid', 'http://ncbi.nlm.nih.gov/pubmed/', 'title') } - else {_makeSubList(liUlLis)} - }) - } - - function _makeSubList(liSelection) { - liSelection.each(function(d, i) { - var li = d3.select(this) - li.html(d) - }) - } - - function _makeSubListFromMeta(liSelection, meta, urlKey, urlPrefix, urlTextKey) { - liSelection.each(function(d, i) { - var li = d3.select(this) - var a = li.select('a') - var urlText - if (meta != undefined && meta[d] != undefined) { - if (urlKey == undefined) {urlKey = 'url'} - if (urlPrefix == undefined) {urlPrefix == ''} - if (urlTextKey == undefined) {urlText = d} else {urlText = meta[d][urlTextKey]} - if (a.empty()) {li.html(''); a = li.append('a')} - a.attr('href', urlPrefix + meta[d][urlKey]).attr('target', '_blank').html(urlText) - } else { - if (!a.empty()) {a.remove()} - li.html(d) - } - }) - } - - - - - function setupSettersAndGetters() { - var closuredVariables = [ - 'vertexSet', - 'edgeSet', - 'layering', - /* GRAPH DRAWING VARIABLES*/ - 'container', - 'width', - 'height', - 'layout', - 'xScale', - 'yScale', - 'rangePad', - 'xCoordinates', - 'yCoordinates', - 'dataExtent', - /* GRAPH STYLE VARIABLES */ - 'vertexRadius', - 'vertexContainer', - 'edgeContainer', - - 'vertexGroup', - 'edgeGroup', - 'vertexMeta', - 'edgeMeta', - 'pathwayMeta', - 'pubmedMeta', - 'datasourceMeta' - ] - - for (var i = 0; i < closuredVariables.length; i++) { - var currentClosureVariable = closuredVariables[i] - var toEvaluateString = " \ - draw." + currentClosureVariable + " = function(value){ \ - if(!arguments.length) return " + currentClosureVariable + "; \ - " + currentClosureVariable + " = value; \ - return draw; \ - }; \ - " - eval(toEvaluateString) - } - } - setupSettersAndGetters() - return draw; -} - - -function marker() { - var id, - markerWidth=10, - markerHeight=10, - refX=0, - refY=3, - orient="auto", - markerUnits="strokeWidth", - viewBox="0 0 20 20", - path="M0,0 L0,6 L9,3 z", - fill="#333333", - type="triangle" - - - function make() { - var defs = d3.select(svg).select("defs") - if (defs.empty()) { - defs = d3.select(svg).append("defs") - } - defs.append("marker") - .attr("id", id) - .attr("markerWidth", markerWidth) - .attr("markerHeight", markerHeight) - .attr("refX", refX) - .attr("refY", refY) - .attr("orient", orient) - .attr("markerUnits", markerUnits) - .attr("viewBox", viewBox) - .append("path") - .attr("d", path) - } - - make.triangle = function (x, y, yOffset) { - refX = yOffset + y - refY = x / 2 - path = "M0,0 L0,"+x+" L"+y+","+(x/2)+" z" - } - - function setupSettersAndGetters() { - var closuredVariables = [ - 'id', 'markerWidth', 'markerHeight', 'refX', 'refY', - 'orient', 'markerUnits', 'viewBox', 'path', "svg", "fill" - ] - - - - for (var i = 0; i < closuredVariables.length; i++) { - var currentClosureVariable = closuredVariables[i] - var toEvaluateString = " \ - make." + currentClosureVariable + " = function(value){ \ - if(!arguments.length) return " + currentClosureVariable + "; \ - " + currentClosureVariable + " = value; \ - return make; \ - }; \ - " - eval(toEvaluateString) - } - } - setupSettersAndGetters() - return make; -} - - - -// marker().id("arrow-head") -// .markerWidth("10") -// .markerHeight("10") -// .refX("0") -// .refY("3") -// .orient("auto") -// .markerUnits("strokeWidth") -// .viewBox("0 0 20 20") -// .path("M0,0 L0,6 L9,3 z") -// .fill("#FFFFFF") diff --git a/needs-to-be-bundled/scatter.js b/needs-to-be-bundled/scatter.js deleted file mode 100644 index 3c97adaec648d0f90f87f5f879e1f2cd0998dabe..0000000000000000000000000000000000000000 --- a/needs-to-be-bundled/scatter.js +++ /dev/null @@ -1,265 +0,0 @@ -function scatter() { - // variables that need to be set externally - var plotContainer, - drawingSpace, - colors = ["#2c7bb6", "#00a6ca", "#00ccbc", "#90eb9d", "#ffff8c", "#f9d057", "#f29e2e", "#e76818", "#d7191c"], - tooltipKeys, - rKey, // r key - r=2, - stroke, - data, - xScale = d3.scaleLinear(), - yScale = d3.scaleLinear(), - rScale = d3.scaleLinear().range([ 2, 10]), - xKey, yKey, // x and y keys - points, - categorical = true, - cKey, // color key - cOpacity = 0.2, - strokeWidth = 2, - cScale = d3.scaleSequential(interpolateColors.apply(this, colors)) - - - - // variables set internally - var pointsNeeded, currentNumberOfPoints, - xValues, yValues, rValues, cValues, - dataExtent, fatal, - verbose = true, - animationTime = 1000, - svg, - rScaleMin = 0.002, - rScaleMax = 0.02, - xRangePad = 2, - yRangePad = 2 - hexademicalOpacity = { - 1: "FF", - 0.9: 'E6', - 0.8: 'CC', - 0.7: "B3", - 0.6: "99", - 0.5: "80", - 0.4: "66", - 0.3: "4D", - 0.2: "33", - 0.1: "1A", - 0.0: "00" - } - - - - - function plot(){ - fatal = warn(plotContainer, 'plotContainer', undefined, true, verbose) - if ( fatal ) {return} - fatal = warn(data, 'data', undefined, true, verbose) - if ( fatal ) {return} - fatal = warn(xKey, 'xKey', undefined, true, verbose) - if ( fatal ) {return} - fatal = warn(yKey, 'yKey', undefined, true, verbose) - if ( fatal ) {return} - fatal = warn(drawingSpace, 'drawingSpace', undefined, true, verbose) - if ( fatal ) {return} - - - svg = d3.select(plotContainer.thisSVG()) - - pointsNeeded = data.length - currentNumberOfPoints = plotContainer.selectAll('.point-container').size() - - - xValues = data.map( function(d, i) { return parseFloat( d[xKey] ) } ) - yValues = data.map( function(d, i) { return parseFloat( d[yKey] ) } ) - - - - dataExtent = { - x: { - min: d3.min( xValues ), - max: d3.max( xValues ) - }, - y: { - min: d3.min( yValues ), - max: d3.max( yValues ) - } - } - - xScale.domain([ dataExtent.x.min - xRangePad, dataExtent.x.max + xRangePad]) - .range([ 0, drawingSpace.x ]) - - yScale.domain([ dataExtent.y.min - yRangePad, dataExtent.y.max + yRangePad]) - .range([ drawingSpace.y, 0 ]) - - - // set r scale if rKey is defined - if (rKey != undefined) { - rValues = data.map( function(d, i) { return parseFloat( d[rKey] ) } ) - rScale.domain([ d3.min(rValues), d3.max(rValues) ]) - .range([ - parseFloat(svg.style('width')) * rScaleMin, - parseFloat(svg.style('width')) * rScaleMax] - ) - } - - if (cKey != undefined) { - cValues = data.map( function(d, i) { return parseFloat( d[cKey] ) } ) - cScale.domain([ d3.min(cValues), d3.max(cValues) ]) - } - - - // not enough pionts add more - if (pointsNeeded > currentNumberOfPoints) { - plotContainer.selectAll('.point-container') - .data(data) - .enter() - .append('g') - .attr('class', 'point-container') - .attr('transform', function(d, i) { - x = 0 - y = parseFloat(plotContainer.thisSVG().style.height) - trans = 'translate('+x+','+y+')' - return trans - }) // for entering animation - .append('circle') - .attr('class', 'point') - } else if (pointsNeeded == currentNumberOfPoints) { - plotContainer.selectAll('.point-container').data(data) - } else { // too many points, remove - plotContainer.selectAll('.point-container').data(data) - .exit() - .transition() - .duration(function(d, i) { - return (animationTime * 0.1) + (animationTime * .9) / data.length * i - }) - .attr('transform', function(d, i) { - x = 0 - y = parseFloat(svg.style('height')) - trans = 'translate('+x+','+y+')' - return trans - }) // for exiting animation - .remove() - } - - // rebind dat for safety - points = plotContainer.selectAll('.point-container').data(data) - - points.transition().duration(function(d, i){ - return (animationTime * 0.1) + (animationTime * .9) / data.length * i - }) // animate movement - .attr('transform', function(d, i) { - x = xScale(d[xKey]) - y = yScale(d[yKey]) - trans = "translate("+(x)+","+(y)+")" - return trans - }) // move points to correct location - .select('circle') - .attr('r', function(d, i){ - if (rKey != undefined) { return rScale(d[rKey]) } - else { return r } - }) // set size to r - .attr('fill', function(d, i){ - if (cKey == undefined) { - var colorI = i % colors.length - var c = colors[colorI] - if (c.includes("#") && cOpacity != undefined) { - c += hexademicalOpacity[cOpacity] - } - return c - } else { - var c = cScale(d[cKey]) - if (c.includes("#") && cOpacity != undefined) { - c += hexademicalOpacity[cOpacity] - } else { - [r, g, b] = c.slice(3).split(',') - b = b.split(')').join('') - r = r.split('(').join('') - return 'rgba('+r+','+g+','+b+','+cOpacity+')' - } - return c - } - }) - .attr('stroke-width', strokeWidth) - .attr('stroke', function(d, i){ - if (cKey == undefined) { - var colorI = i % colors.length - var c = colors[colorI] - return c - } else { - return cScale(d[cKey]) - } - }) - - - - points.on('mouseout', mouseoutPoint) - .on('mouseover', mouseoverPoint) - - function mouseoutPoint(d, i){ - var pnt = d3.select(this).select('circle') - d3.selectAll('div.tooltip').style('display', 'none') - pnt.transition().duration(animationTime * 0.5) - .attr('r', function(d, i){ - if (rKey != undefined) { return rScale(d[rKey]) } - else { return r } - }) - } - - function mouseoverPoint(d, i){ - var pnt = d3.select(this).select('circle') - pnt.transition().duration(animationTime * 0.5) - .attr('r', function(d, i){ - return rScale.range()[1] * 1.5 - }) - - ttip = tooltip().tooltipKeys(tooltipKeys).data(d) - ttip() - } - - } - - - function setupSettersAndGetters() { - var closuredVariables = [ - 'plotContainer', - 'drawingSpace', - 'data', - 'colors', - 'tooltipKeys', - 'rKey','xKey', 'yKey', 'cKey', - 'r', - 'xScale', - 'yScale', - 'cScale', - 'rScale', - 'xRangePad', - 'yRangePad', - 'points', - 'categorical', - 'cOpacity', - 'strokeWidth', - 'pointsNeeded', - 'currentNumberOfPoints', - 'xValues','yValues','rValues','cValues', - 'dataExtent', 'fatal', - 'verbose', 'animationTime', - 'svg', 'rScaleMax', 'rScaleMin' - ] - - - for (var i = 0; i < closuredVariables.length; i++) { - var currentClosureVariable = closuredVariables[i] - var toEvaluateString = " \ - plot." + currentClosureVariable + " = function(value){ \ - if(!arguments.length) return " + currentClosureVariable + "; \ - " + currentClosureVariable + " = value; \ - return plot; \ - }; \ - " - eval(toEvaluateString) - } - } - - - setupSettersAndGetters() - return plot; -} diff --git a/needs-to-be-bundled/tooltip.js b/needs-to-be-bundled/tooltip.js deleted file mode 100644 index c4ba690d4f1b708b22c07b39191d576318356306..0000000000000000000000000000000000000000 --- a/needs-to-be-bundled/tooltip.js +++ /dev/null @@ -1,79 +0,0 @@ -function tooltip() { - var - ttip, - tooltipKeys, - tooltipContent, - divs, data - - - function make() { - ttip = d3.select('body').select('div.tooltip') - .style('display', 'flex') - - if (ttip.empty()) { - ttip = d3.select('body').append('div').attr('class','tooltip') - .style('display', 'flex').attr('id', 'tooltip') - } - - tooltipContent = ttip.select('div.tooltip-vertical-flex') - if (tooltipContent.empty()) { - tooltipContent = ttip.append('div').attr('class','tooltip-vertical-flex') - } - - divs = tooltipContent.selectAll('.tooltip-element-flex') - if (divs.empty() || divs.size() < tooltipKeys.length) { - divs = tooltipContent.selectAll('.tooltip-element-flex') - .data(tooltipKeys) - .enter() - .append('div').attr('class', 'tooltip-element-flex') - - divs.append('div').attr('class', 'tooltip-element-key') - divs.append('div').attr('class', 'tooltip-element-value') - } else { - tooltipContent.selectAll('.tooltip-element-flex') - .data(tooltipKeys) - .exit() - .remove() - } - divs = tooltipContent.selectAll('.tooltip-element-flex').data(tooltipKeys) - - divs.each(function(curKey){ - var k = d3.select(this).select('.tooltip-element-key') - var v = d3.select(this).select('.tooltip-element-value') - - k.html(curKey) - v.html(data[curKey]) - }) - - var mouse = d3.mouse.smart("tooltip") - ttip.style('left', mouse[0]+'px') - .style('top', mouse[1]+'px') - - } - - function setupSettersAndGetters() { - var closuredVariables = [ - 'ttipConatiner', - 'ttip', - 'tooltipKeys', - 'tooltipContent', - 'divs', 'data' - ] - - - for (var i = 0; i < closuredVariables.length; i++) { - var currentClosureVariable = closuredVariables[i] - var toEvaluateString = " \ - make." + currentClosureVariable + " = function(value){ \ - if(!arguments.length) return " + currentClosureVariable + "; \ - " + currentClosureVariable + " = value; \ - return make; \ - }; \ - " - eval(toEvaluateString) - } - } - - setupSettersAndGetters() - return make -} diff --git a/rollup.config.js b/rollup.config.js index f638afd79e0b4814670fdcf5b584d3650280ca29..186a4da4d2124a533096910060ffa1b7210bfe45 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,8 +1,8 @@ -import babel from 'rollup-plugin-babel'; +// import babel from 'rollup-plugin-babel'; import uglify from 'rollup-plugin-uglify-es'; import minimist from 'minimist'; import commonjs from 'rollup-plugin-commonjs'; -import resolve from 'rollup-plugin-node-resolve'; +import nodeResolve from 'rollup-plugin-node-resolve'; import pkg from './package.json'; @@ -10,39 +10,25 @@ import pkg from './package.json'; const argv = minimist(process.argv.slice(2)); const config = { - input: 'src/scripts/main.js', + input: 'src/entry.js', output: { name: pkg.name, exports: 'named', extend: true, - // external: ['d3'], - // globals: { - // d3: 'd3' - // }, + external: ['d3'], + globals: { + d3: 'd3' + }, }, plugins: [ - // babel({ // exclude: 'node_modules/**', // externalHelpers: true, - // runtimeHelpers: true, - // plugins: [ - // [ - // 'wildcard', - // { - // exts: ['vue'], - // nostrip: true, - // }, - // ], - // '@babel/plugin-external-helpers', - // - // ], + // runtimeHelpers: true, // }), - resolve({ - jsnext: true, - main: true - + nodeResolve({ + mainFields:['jsnext', 'main'], }), commonjs({ // non-CommonJS modules will be ignored, but you can also diff --git a/src/entry.js b/src/entry.js new file mode 100644 index 0000000000000000000000000000000000000000..2ac38673d15ba8c5f751b4cb603047450d4e17e8 --- /dev/null +++ b/src/entry.js @@ -0,0 +1,27 @@ +import utils from './modules/utils/index.js' +import axis from './modules/axis' +import groupingSpacer from './modules/grouping-spacer' +import tooltip from './modules/tooltip' +import colorFunction from './modules/color-function' +import charts from './modules/charts/index.js' +import legends from './modules/legends/index.js' +import aux from './modules/aux/index.js' + + + +let d3sm = { + aux, + axis, + charts, + colorFunction, + debugQ: false, + groupingSpacer, + legends, + tooltip, + utils, +} + +if (typeof window !== 'undefined') { + window.d3sm = d3sm; +} +export default d3sm diff --git a/src/scripts/modules/data-toggle.js b/src/modules/aux/data-toggle.js similarity index 85% rename from src/scripts/modules/data-toggle.js rename to src/modules/aux/data-toggle.js index d261e487f5872012510778f71310af372af99e80..be2e016593697ab4307c92fcac6e242aa166c407 100644 --- a/src/scripts/modules/data-toggle.js +++ b/src/modules/aux/data-toggle.js @@ -1,5 +1,5 @@ -import {hypenate, safeSelect} from './helpers'; -import {selectFilter} from './select-filter'; +import utils from '../utils/index.js' +import selectFilter from './select-filter'; /******************************************************************************* ** ** @@ -15,7 +15,7 @@ import {selectFilter} from './select-filter'; * @namespace datatoggle * @returns {function} datatoggle */ -export function datatoggle( selection ) { +export default function datatoggle( selection ) { var /** * Keys to make toggle-able options @@ -110,8 +110,8 @@ export function datatoggle( selection ) { // selection options // selection.classed('d-flex flex-row', true) - // var filterButton = safeSelect(selection, 'a', 'slider-buttons') - // var filterI = safeSelect(filterButton, 'i', 'fa fa-sliders') + // var filterButton = utils.sel.safeSelect(selection, 'a', 'slider-buttons') + // var filterI = utils.sel.safeSelect(filterButton, 'i', 'fa fa-sliders') /*BUG: unexpected behavior. - when using bootstrap-eque way for collapse, clicking button submits to @@ -121,13 +121,13 @@ export function datatoggle( selection ) { */ // filterButton.attr('class', 'btn btn-secondary') // .attr('data-toggle', 'collapse') - // .attr('href', '#'+hypenate(namespace, 'data-toggle')) + // .attr('href', '#'+utils.str.hypenate(namespace, 'data-toggle')) // .attr('target', '_blank') // .html(filterButton.html()+' Filters') // .on('click', function(d, i){ // d3.event.preventDefault() // d3.event.stopPropagation() - // var dt = d3.select("#"+hypenate(namespace, 'data-toggle')) + // var dt = d3.select("#"+utils.str.hypenate(namespace, 'data-toggle')) // dt.classed('show', !dt.classed('show')) // dt.classed('d-inline-flex', dt.classed('show')) // @@ -139,14 +139,14 @@ export function datatoggle( selection ) { - // var datatoggleCollapse = safeSelect(selection, 'div', hypenate(namespace,'collapse')) - // .attr('id', hypenate(namespace, 'data-toggle')) + // var datatoggleCollapse = utils.sel.safeSelect(selection, 'div', utils.str.hypenate(namespace,'collapse')) + // .attr('id', utils.str.hypenate(namespace, 'data-toggle')) // .classed('collapse', true) - // var flexRow = safeSelect(datatoggleCollapse, 'div', 'd-inline-flex flex-row flex-wrap') - var flexRow = safeSelect(selection, 'div', 'd-inline-flex flex-row flex-wrap') + // var flexRow = utils.sel.safeSelect(datatoggleCollapse, 'div', 'd-inline-flex flex-row flex-wrap') + var flexRow = utils.sel.safeSelect(selection, 'div', 'd-inline-flex flex-row flex-wrap') - var dataopts = flexRow.selectAll('div.'+hypenate(namespace,'select-filter')) + var dataopts = flexRow.selectAll('div.'+utils.str.hypenate(namespace,'select-filter')) // remove excess dataopts.exit().remove() // bind data @@ -161,7 +161,7 @@ export function datatoggle( selection ) { var t = d3.select(this) var sf = selectFilter(t) .data(data[d]) - .namespace(hypenate(namespace, d)) + .namespace(utils.str.hypenate(namespace, d)) .selectionName(d) sf() filterSelects[d] = sf diff --git a/src/modules/aux/index.js b/src/modules/aux/index.js new file mode 100644 index 0000000000000000000000000000000000000000..b59c31222deefccc972c977c6fd54b18dc582d7e --- /dev/null +++ b/src/modules/aux/index.js @@ -0,0 +1,13 @@ +import lasso from './lasso' +import lassoWidget from './lasso-widget' +import multiPlotZoom from './multi-plot-zoom' +import plotZoom from './plot-zoom' +import datatoggle from './data-toggle' +import selectFilter from './select-filter' + +let aux = { + lasso, plotZoom, multiPlotZoom, datatoggle, selectFilter, lassoWidget +} + +export {lasso, plotZoom, multiPlotZoom, datatoggle, selectFilter, lassoWidget} +export default aux diff --git a/src/scripts/modules/lasso-widget.js b/src/modules/aux/lasso-widget.js similarity index 70% rename from src/scripts/modules/lasso-widget.js rename to src/modules/aux/lasso-widget.js index 53f0e83ee1adeea9fbef65734c82c863049224c4..c90eacae863519bdea13d88098bdea83325393a3 100644 --- a/src/scripts/modules/lasso-widget.js +++ b/src/modules/aux/lasso-widget.js @@ -1,13 +1,11 @@ -import {hypenate, safeSelect, modifyHexidecimalColorLuminance, extractViolinValues, quartiles} from './helpers'; -import {setupContainer, calculateWidthOfObject, calculateWidthOfSpacer} from './utils'; -import {unique, hasQ, flatten, whichBin} from './array-functions'; -import {groupingSpacer} from './grouping-spacer'; -import {colorFunction as CF} from './color-function'; -import {tooltip as TTip} from './tooltip'; -import {lasso} from './lasso'; -import './d3-prototypes'; - -export function lassoWidget( selection ) { +import utils from '../utils/index.js' +import groupingSpacer from '../grouping-spacer'; +import CF from '../color-function'; +import TTip from '../tooltip'; +import lasso from './lasso'; +import '../d3-prototypes'; + +export default function lassoWidget( selection ) { var namespace = 'd3sm-lasso', selection = selection, @@ -49,7 +47,7 @@ export function lassoWidget( selection ) { d3.select("html").append("style") .classed(namespace+'lasso-widget', true) .html( - "."+hypenate(namespace, "data-table") + "{\ + "."+utils.str.hypenate(namespace, "data-table") + "{\ height:100px;\ overflow:auto;\ }" @@ -68,25 +66,25 @@ export function lassoWidget( selection ) { } function plusTab(tabList) { - var tab = safeSelect(tabList, 'li', hypenate(namespace, 'plus-tab')) + var tab = utils.sel.safeSelect(tabList, 'li', utils.str.hypenate(namespace, 'plus-tab')) .classed('ml-auto', true) .classed('nav-item', true) .on('click', makeNewGroup), - anchor = safeSelect(tab, 'a', 'nav-link'), - icon = safeSelect(anchor, 'i', 'fa') + anchor = utils.sel.safeSelect(tab, 'a', 'nav-link'), + icon = utils.sel.safeSelect(anchor, 'i', 'fa') .classed('fa-plus fa-2x text-success', true) } function sendTab(tabList) { - var tab = safeSelect(tabList, 'li', hypenate(namespace, 'send-tab')) + var tab = utils.sel.safeSelect(tabList, 'li', utils.str.hypenate(namespace, 'send-tab')) .classed('ml-auto', true) .classed('nav-item', true) .on('click', clickSend) , - anchor = safeSelect(tab, 'a', 'nav-link'), - icon = safeSelect(anchor, 'i', 'fa') + anchor = utils.sel.safeSelect(tab, 'a', 'nav-link'), + icon = utils.sel.safeSelect(anchor, 'i', 'fa') .classed('fa-paper-plane-o fa-2x text-primary', true) } @@ -96,7 +94,7 @@ export function lassoWidget( selection ) { } function closeTab(tabList) { - var tab = safeSelect(tabList, 'li', hypenate(namespace, 'close-tab')) + var tab = utils.sel.safeSelect(tabList, 'li', utils.str.hypenate(namespace, 'close-tab')) .classed('ml-auto', true) .classed('nav-item', true) .on('click', function(){ @@ -109,8 +107,8 @@ export function lassoWidget( selection ) { }) , - anchor = safeSelect(tab, 'a', 'nav-link'), - icon = safeSelect(anchor, 'i', 'fa') + anchor = utils.sel.safeSelect(tab, 'a', 'nav-link'), + icon = utils.sel.safeSelect(anchor, 'i', 'fa') .classed('fa-window-close-o fa-2x text-danger', true) } @@ -118,31 +116,31 @@ export function lassoWidget( selection ) { function setupDataselectContainer() { var - card = safeSelect(selection, 'div', 'card'), - cardHeader = safeSelect(card, 'div', 'card-header'), + card = utils.sel.safeSelect(selection, 'div', 'card'), + cardHeader = utils.sel.safeSelect(card, 'div', 'card-header'), - tabList = safeSelect(cardHeader, 'ul', 'nav') + tabList = utils.sel.safeSelect(cardHeader, 'ul', 'nav') .classed('nav-tabs card-header-tabs', true) - .classed(hypenate(namespace, 'tab-list'), true) + .classed(utils.str.hypenate(namespace, 'tab-list'), true) .attr('role', 'tablist'), - cardBody = safeSelect(card, 'div', 'card-body'), - tabContent = safeSelect(cardBody, 'div', 'tab-content') - .classed(hypenate(namespace, 'tab-content'), true), + cardBody = utils.sel.safeSelect(card, 'div', 'card-body'), + tabContent = utils.sel.safeSelect(cardBody, 'div', 'tab-content') + .classed(utils.str.hypenate(namespace, 'tab-content'), true), - // leftTabs = safeSelect(tabList, 'div', 'nav mr-auto left-aligned-tabs') - rightTabs = safeSelect(tabList, 'div', 'right-aligned-tabs').classed('nav ml-auto ', true) + // leftTabs = utils.sel.safeSelect(tabList, 'div', 'nav mr-auto left-aligned-tabs') + rightTabs = utils.sel.safeSelect(tabList, 'div', 'right-aligned-tabs').classed('nav ml-auto ', true) plusTab(rightTabs) sendTab(rightTabs) closeTab(rightTabs) var - defaultTab = safeSelect(tabContent, 'div', 'tab-pane') - .classed(hypenate(namespace,'default-tab'), true) + defaultTab = utils.sel.safeSelect(tabContent, 'div', 'tab-pane') + .classed(utils.str.hypenate(namespace,'default-tab'), true) .classed("active", true) .classed('text-left', true), - p = safeSelect(defaultTab, 'div') + p = utils.sel.safeSelect(defaultTab, 'div') .html( "Click to add a new group.
"+ "Click to submit for re-analysis.
"+ @@ -154,18 +152,18 @@ export function lassoWidget( selection ) { function makeRemoveButton(paneBtnList) { var - btn = safeSelect(paneBtnList, 'button', 'remove-btn') + btn = utils.sel.safeSelect(paneBtnList, 'button', 'remove-btn') .classed('btn btn-danger', true) .on('click', removeBtnClickToRemove), - i = safeSelect(btn, 'i', 'fa').classed('fa-trash-o', true), - s = safeSelect(btn, 'span').text('Remove group') + i = utils.sel.safeSelect(btn, 'i', 'fa').classed('fa-trash-o', true), + s = utils.sel.safeSelect(btn, 'span').text('Remove group') return btn } function removeBtnClickToRemove(d, i) { var - tab = selection.select('#'+hypenate(namespace,'tab',d)), - pane = selection.select('#'+hypenate(namespace,'tab','pane',d)) + tab = selection.select('#'+utils.str.hypenate(namespace,'tab',d)), + pane = selection.select('#'+utils.str.hypenate(namespace,'tab','pane',d)) tab.remove() pane.remove() @@ -176,7 +174,7 @@ export function lassoWidget( selection ) { function togglePaneById(id) { - var panes = selection.select('.'+hypenate(namespace, 'tab-content')) + var panes = selection.select('.'+utils.str.hypenate(namespace, 'tab-content')) panes.selectAll('div.tab-pane') .each(function(d, i){ d3.select(this).classed('active show', d3.select(this).attr('id') == id) @@ -195,13 +193,13 @@ export function lassoWidget( selection ) { .classed('show', true) // .classed('mr-auto', true) .attr("role", 'alert') - .attr("id", hypenate(namespace,'tab',n)) - .classed(hypenate(namespace,'tab'), true) + .attr("id", utils.str.hypenate(namespace,'tab',n)) + .classed(utils.str.hypenate(namespace,'tab'), true) - var a = safeSelect(li, 'a') + var a = utils.sel.safeSelect(li, 'a') .attr('data-toggle', 'tab') .text('Group ' + n) - .attr('href', '#'+hypenate(namespace,'tab','pane',n)) + .attr('href', '#'+utils.str.hypenate(namespace,'tab','pane',n)) .on('dblclick', function(d, i){ var t = d3.select(this) t.attr('contenteditable', true) @@ -244,24 +242,24 @@ export function lassoWidget( selection ) { .attr('role', 'tabpanel') .classed('tab-pane', true) .classed('text-left', true) - .classed(hypenate(namespace,'tab','pane'), true) - .attr('id', hypenate(namespace,'tab','pane',n)) + .classed(utils.str.hypenate(namespace,'tab','pane'), true) + .attr('id', utils.str.hypenate(namespace,'tab','pane',n)) return pane } function populatePane(pane, n) { var - lead = safeSelect(pane, 'p', 'lead').text('Group '+n), + lead = utils.sel.safeSelect(pane, 'p', 'lead').text('Group '+n), - tableContainer = safeSelect(pane, 'div', 'table-responsive') - .attr("class", hypenate(namespace, "data-table")), + tableContainer = utils.sel.safeSelect(pane, 'div', 'table-responsive') + .attr("class", utils.str.hypenate(namespace, "data-table")), - table = safeSelect(tableContainer, "table", "table") + table = utils.sel.safeSelect(tableContainer, "table", "table") .classed("table-sm", true).classed("table-hover", true), - caption = safeSelect(table, "caption", "caption").html("List of selected"), + caption = utils.sel.safeSelect(table, "caption", "caption").html("List of selected"), - btns = safeSelect(pane, 'div', 'text-right'), + btns = utils.sel.safeSelect(pane, 'div', 'text-right'), cN = n % colorFunction.colors().length if (n % 2 != 0) { cN = (colorFunction.colors().length - 1) - cN } @@ -288,22 +286,22 @@ export function lassoWidget( selection ) { } function makeLassoButton(btns) { - var btn = safeSelect(btns, 'button', 'lasso-btn') + var btn = utils.sel.safeSelect(btns, 'button', 'lasso-btn') .classed('btn btn-info', true) .classed(namespace, true) // .datum([lasso]) - var i = safeSelect(btn, 'i', 'fa').classed('fa-hand-pointer-o', true) - var s = safeSelect(btn, 'span').text('Lasso select') + var i = utils.sel.safeSelect(btn, 'i', 'fa').classed('fa-hand-pointer-o', true) + var s = utils.sel.safeSelect(btn, 'span').text('Lasso select') return btn } function makeClearButton(btns) { - var btn = safeSelect(btns, 'button', 'clear-btn') + var btn = utils.sel.safeSelect(btns, 'button', 'clear-btn') .classed('btn btn-light', true) .classed(namespace, true) - var i = safeSelect(btn, 'i', 'fa').classed('fa-eraser', true) - var s = safeSelect(btn, 'span').text('Clear selection') + var i = utils.sel.safeSelect(btn, 'i', 'fa').classed('fa-eraser', true) + var s = utils.sel.safeSelect(btn, 'span').text('Clear selection') return btn } @@ -327,10 +325,10 @@ export function lassoWidget( selection ) { lassoBtn.node().addEventListener("click", lassoBtnToggle) lassoBtn.datum([currentLasso]) - .on(hypenate(namespace,'render'), function(){ + .on(utils.str.hypenate(namespace,'render'), function(){ d3.select(this).datum()[0].draw() }) - .on(hypenate(namespace,"drag"), function(las){ + .on(utils.str.hypenate(namespace,"drag"), function(las){ var nodes = chartContainer.selectAll(".in-lasso-"+las[0].instance()).nodes() var tableData = nodes.map(function(d, i){ var extracted = dataExtractor(d3.select(d).datum()) @@ -345,7 +343,7 @@ export function lassoWidget( selection ) { clearBtn.on('click', function(){ currentLasso.allPoints([]) currentLasso.currentPoints([]) - lassoBtn.dispatch(hypenate(namespace,"drag")) + lassoBtn.dispatch(utils.str.hypenate(namespace,"drag")) }) @@ -362,7 +360,7 @@ export function lassoWidget( selection ) { that.classed('btn-info', !activeQ) that.classed('btn-warning', activeQ) that.select("span").text("Lasso select (active)") - selection.selectAll("."+namespace+".lasso-btn").dispatch(hypenate(namespace,'render')) + selection.selectAll("."+namespace+".lasso-btn").dispatch(utils.str.hypenate(namespace,'render')) d3.select("html").node().addEventListener('mousedown', monitorLassoButtonState) } else { that.classed('btn-info', !activeQ) @@ -458,9 +456,9 @@ export function lassoWidget( selection ) { function makeTable(table, tableData, lasso) { var - head = safeSelect(table, "thead"), - headR = safeSelect(head, "tr"), - body = safeSelect(table, "tbody"), + head = utils.sel.safeSelect(table, "thead"), + headR = utils.sel.safeSelect(head, "tr"), + body = utils.sel.safeSelect(table, "tbody"), headerKeys = updateTableHeaderColumns(headR, tableData), @@ -491,11 +489,11 @@ export function lassoWidget( selection ) { function makeNewGroup(d, i) { - var tabs = selection.select('.'+hypenate(namespace, 'tab-list')), - panes = selection.select('.'+hypenate(namespace, 'tab-content')), + var tabs = selection.select('.'+utils.str.hypenate(namespace, 'tab-list')), + panes = selection.select('.'+utils.str.hypenate(namespace, 'tab-content')), n = newGroupNumber() - if (tabs.selectAll('.'+hypenate(namespace,'tab')).size() == maxNumberOfGroups) { + if (tabs.selectAll('.'+utils.str.hypenate(namespace,'tab')).size() == maxNumberOfGroups) { onError('only '+maxNumberOfGroups+' allowed.', 'warning') return } @@ -510,7 +508,7 @@ export function lassoWidget( selection ) { } function newGroupNumber() { - var tabs = selection.select('.'+hypenate(namespace, 'tab-list'))//, + var tabs = selection.select('.'+utils.str.hypenate(namespace, 'tab-list'))//, var n = tabs.selectAll('li').size() - 3, // minus 1 for plus tab s = 'Group ' + n, @@ -522,17 +520,17 @@ export function lassoWidget( selection ) { function updateTabAndPaneNumbers() { var - tabs = selection.select('.'+hypenate(namespace, 'tab-list')), - panes = selection.select('.'+hypenate(namespace, 'tab-content')) + tabs = selection.select('.'+utils.str.hypenate(namespace, 'tab-list')), + panes = selection.select('.'+utils.str.hypenate(namespace, 'tab-content')) - tabs = tabs.selectAll('.'+hypenate(namespace,'tab')) - panes = panes.selectAll('.'+hypenate(namespace,'tab', 'pane')) + tabs = tabs.selectAll('.'+utils.str.hypenate(namespace,'tab')) + panes = panes.selectAll('.'+utils.str.hypenate(namespace,'tab', 'pane')) tabs.each(function(d, i){ d3.select(this).datum(i) - .attr("id", hypenate(namespace,'tab',i)) + .attr("id", utils.str.hypenate(namespace,'tab',i)) .select('a') - .attr('href', '#'+hypenate(namespace,'tab','pane',i)) + .attr('href', '#'+utils.str.hypenate(namespace,'tab','pane',i)) .text(function(dd, ii){ var curText = d3.select(this).text(); if (curText.split(' ')[0] == 'Group') { @@ -544,8 +542,8 @@ export function lassoWidget( selection ) { panes.each(function(d, i){ d3.select(this).datum(i) - .attr('id', hypenate(namespace,'tab','pane',i)) - safeSelect(d3.select(this), 'p', 'lead') + .attr('id', utils.str.hypenate(namespace,'tab','pane',i)) + utils.sel.safeSelect(d3.select(this), 'p', 'lead') .text(function(dd, ii){ var curText = d3.select(this).text(); if (curText.split(' ')[0] == 'Group') { @@ -553,19 +551,19 @@ export function lassoWidget( selection ) { } return curText }) - safeSelect(d3.select(this), 'button', 'remove-btn') + utils.sel.safeSelect(d3.select(this), 'button', 'remove-btn') .on('click', removeBtnClickToRemove) }) } function gatherDataLists() { - var tabs = selection.select('.'+hypenate(namespace, 'tab-list')) - var panes = selection.select('.'+hypenate(namespace, 'tab-content')) - var tables = panes.selectAll('.'+hypenate(namespace, "data-table")) + var tabs = selection.select('.'+utils.str.hypenate(namespace, 'tab-list')) + var panes = selection.select('.'+utils.str.hypenate(namespace, 'tab-content')) + var tables = panes.selectAll('.'+utils.str.hypenate(namespace, "data-table")) var data = {} - var textGroups = tabs.selectAll('li.'+hypenate(namespace,'tab') + ' > a') + var textGroups = tabs.selectAll('li.'+utils.str.hypenate(namespace,'tab') + ' > a') .nodes().map(function(d, i){return d3.select(d).text()}) textGroups.map(function(e, i){ @@ -583,12 +581,12 @@ export function lassoWidget( selection ) { function showRemainingPanes() { var - tabs = selection.select('.'+hypenate(namespace, 'tab-list')), - panes = selection.select('.'+hypenate(namespace, 'tab-content')), - remainingTabs = tabs.selectAll('.'+hypenate(namespace,'tab')) + tabs = selection.select('.'+utils.str.hypenate(namespace, 'tab-list')), + panes = selection.select('.'+utils.str.hypenate(namespace, 'tab-content')), + remainingTabs = tabs.selectAll('.'+utils.str.hypenate(namespace,'tab')) if (remainingTabs.size() == 0) { - panes.select('.'+hypenate(namespace,'default-tab')) + panes.select('.'+utils.str.hypenate(namespace,'default-tab')) .classed("active", true) .classed('text-left', true) } diff --git a/src/scripts/modules/lasso.js b/src/modules/aux/lasso.js similarity index 89% rename from src/scripts/modules/lasso.js rename to src/modules/aux/lasso.js index 0ccf0e9f4b7612e9c73e5dc9f19db7154d36d939..78e30490cfd176619d190bf9b97147c05345ae98 100644 --- a/src/scripts/modules/lasso.js +++ b/src/modules/aux/lasso.js @@ -1,10 +1,8 @@ -import {hypenate, safeSelect, euclideanDistance} from './helpers'; -import {setupContainer, calculateWidthOfObject, calculateWidthOfSpacer} from './utils'; -import {unique, hasQ, flatten, whichBin} from './array-functions'; -import {groupingSpacer} from './grouping-spacer'; -import {colorFunction as CF} from './color-function'; -import {tooltip as TTip} from './tooltip'; -import './d3-prototypes'; +import utils from '../utils/index.js'; +import groupingSpacer from '../grouping-spacer'; +import CF from '../color-function'; +import TTip from '../tooltip'; +import '../d3-prototypes'; function getTranslation(selection){ var transform = selection.attr('transform') @@ -14,7 +12,7 @@ function getTranslation(selection){ return [parseFloat(x), parseFloat(y)] } -export function lasso( selection ) { +export default function lasso( selection ) { var svg, // svg that is target of events objectContainer, // container which houses objects we are selecting (allows for transform to be applied to lasso) @@ -114,8 +112,8 @@ export function lasso( selection ) { function toggle(state) { // use optional param to set state, otherwise toggle state activeQ = (state!=undefined) ? state : !activeQ - chartOffset = getTranslation(chartContainer) - objectsOffset = getTranslation(objectContainer) + chartOffset = getTranslation(chartContainer) //utils.sel.getTranslation(chartContainer) + objectsOffset = getTranslation(objectContainer) //utils.sel.getTranslation(objectContainer) if (activeQ) { svg.node().addEventListener('mousedown', render, true) @@ -127,10 +125,10 @@ export function lasso( selection ) { } function draw() { - chartOffset = getTranslation(chartContainer) - objectsOffset = getTranslation(objectContainer) + chartOffset = getTranslation(chartContainer) //utils.sel.getTranslation(chartContainer) + objectsOffset = getTranslation(objectContainer) //utils.sel.getTranslation(objectContainer) - var container = safeSelect(objectContainer, 'g', 'lasso-container') + var container = utils.sel.safeSelect(objectContainer, 'g', 'lasso-container') var paths = container.selectAll('path[instance="'+instance+'"]') // update @@ -149,7 +147,7 @@ export function lasso( selection ) { } function remove() { - var container = safeSelect(objectContainer, 'g', 'lasso-container') + var container = utils.sel.safeSelect(objectContainer, 'g', 'lasso-container') var paths = container.selectAll('path[instance="'+instance+'"]').remove() container.remove() objectContainer.selectAll(objectClass).classed("in-lasso", false) @@ -160,7 +158,7 @@ export function lasso( selection ) { // nothing can interefer with drawing the lasso event.preventDefault(); event.stopPropagation(); - var container = safeSelect(objectContainer, 'g', 'lasso-container') + var container = utils.sel.safeSelect(objectContainer, 'g', 'lasso-container') /* each time the user presses down, while the state is active, the lasso @@ -173,8 +171,8 @@ export function lasso( selection ) { svg.node().removeEventListener('mousemove', drag) allPoints.push(currentPoints) // BUG: somehow this is pushing currentPoints n times where n is the nth lasso path for the current instance - // NOTE: allPoints = unique(allPoints) is a temporary and inefficient fix - allPoints = unique(allPoints) + // NOTE: allPoints = utils.arr.unique(allPoints) is a temporary and inefficient fix + allPoints = utils.arr.unique(allPoints) }) path = container.append('path').data([currentPoints]) @@ -182,7 +180,7 @@ export function lasso( selection ) { } function transitionDraw() { - var container = safeSelect(objectContainer, 'g', 'lasso-container') + var container = utils.sel.safeSelect(objectContainer, 'g', 'lasso-container') var paths = container.selectAll('path[instance="'+instance+'"]') // update @@ -203,7 +201,7 @@ export function lasso( selection ) { function applyPathAttributes(path) { path - .attr("class", hypenate(namespace, "lasso-path")) + .attr("class", utils.str.hypenate(namespace, "lasso-path")) .style('opacity', opacity) .attr('fill', color) .attr("d", line) @@ -222,8 +220,8 @@ export function lasso( selection ) { mouse down / mouse up. */ - if (eventCatcher != undefined) {eventCatcher.dispatch(hypenate(namespace,"drag"))} - // d3.dispatch(hypenate(namespace,"drag")) + if (eventCatcher != undefined) {eventCatcher.dispatch(utils.str.hypenate(namespace,"drag"))} + // d3.dispatch(utils.str.hypenate(namespace,"drag")) if (event.which != 1) {return} // ensures left mouse button set d3.event = event @@ -243,7 +241,7 @@ export function lasso( selection ) { if (xScale) {b[0] = xScale(b[0]); a[0] = xScale(a[0])} if (yScale) {b[1] = yScale(b[1]); a[1] = yScale(a[1])} - var dist = euclideanDistance(b, a) + var dist = utils.math.euclideanDistance(b, a) if (dist > tickDistance) { tick(pt) } } else { tick(pt) } @@ -379,10 +377,10 @@ export function lasso( selection ) { function keyFrames() { var style = - d3.select("html").select('style.'+hypenate(namespace,"lasso-dash")) + d3.select("html").select('style.'+utils.str.hypenate(namespace,"lasso-dash")) if (style.empty()) { d3.select("html").append('style') - .classed(hypenate(namespace,"lasso-dash"), true) + .classed(utils.str.hypenate(namespace,"lasso-dash"), true) .html("@keyframes lassoDash {to { stroke-dashoffset: 1000;}}") } diff --git a/src/scripts/modules/multi-plot-zoom.js b/src/modules/aux/multi-plot-zoom.js similarity index 88% rename from src/scripts/modules/multi-plot-zoom.js rename to src/modules/aux/multi-plot-zoom.js index 1565e4a677085aba42a07b9f58acc9ca0cc6c457..18db8b3b1a1da98b435c3f5759c60f92f0125e4f 100644 --- a/src/scripts/modules/multi-plot-zoom.js +++ b/src/modules/aux/multi-plot-zoom.js @@ -1,5 +1,4 @@ -import {hypenate, safeSelect, getTranslation} from './helpers'; -import {log, warn, error, info} from './utils'; +import utils from '../utils/index.js' /******************************************************************************* ** ** @@ -17,7 +16,7 @@ import {log, warn, error, info} from './utils'; * @namespace plotZoom * @returns {function} zoom */ -export function multiPlotZoom( chart ) { +export default function multiPlotZoom( chart ) { var /** * The event on which to fire @@ -127,14 +126,14 @@ export function multiPlotZoom( chart ) { function setLocks() { - var chartObjSel = chartSel.select('.'+hypenate(chart.namespace(),'object-container')) - var chartObjTrans = getTranslation(chartObjSel.attr('transform')) + var chartObjSel = chartSel.select('.'+utils.str.hypenate(chart.namespace(),'object-container')) + var chartObjTrans = utils.sel.getTranslation(chartObjSel.attr('transform')) var cos = chartObjSel.attr('transform', 'translate(0,0)') xLock = chartSel.node().getBBox().width - chart.spaceX()// * .9 yLock = chartSel.node().getBBox().height - chart.spaceY()// * .9 cos.attr('transform', 'translate('+chartObjTrans[0]+','+chartObjTrans[1]+')') - log('plotZoom', 'setLocks', {xLock:xLock, yLock:yLock}) + utils.con.log('plotZoom', 'setLocks', {xLock:xLock, yLock:yLock}) } @@ -194,20 +193,20 @@ export function multiPlotZoom( chart ) { - var chartObjSel = chartSel.select('.'+hypenate(chart.namespace(),'object-container')) + var chartObjSel = chartSel.select('.'+utils.str.hypenate(chart.namespace(),'object-container')) var xComponentObjSel = xComponentsSel.map(function(d, i){ - return d.select('.'+hypenate(xComponents[i].namespace(),'object-container')) + return d.select('.'+utils.str.hypenate(xComponents[i].namespace(),'object-container')) }) var yComponentObjSel = yComponentsSel.map(function(d, i){ - return d.select('.'+hypenate(yComponents[i].namespace(),'object-container')) + return d.select('.'+utils.str.hypenate(yComponents[i].namespace(),'object-container')) }) - var chartObjTrans = getTranslation(chartObjSel.attr('transform')) + var chartObjTrans = utils.sel.getTranslation(chartObjSel.attr('transform')) var xComponentsObjTrans = xComponentObjSel.map(function(d, i){ - return getTranslation(d.attr('transform')) + return utils.sel.getTranslation(d.attr('transform')) }) var yComponentsObjTrans = yComponentObjSel.map(function(d, i){ - return getTranslation(d.attr('transform')) + return utils.sel.getTranslation(d.attr('transform')) }) var x = horizontalQ ? transform.applyX(chartObjTrans[0]) : 0 @@ -236,9 +235,9 @@ export function multiPlotZoom( chart ) { if (orient == 'horizontal') {horizontalQ = true; verticalQ = false;} if (orient == 'vertical') {verticalQ = true; horizontalQ = false;} - var chartObjSel = chartSel.select('.'+hypenate(chart.namespace(),'object-container')) - var xAxisObjSel = xAxisSel.select('.'+hypenate(xAxis.namespace(),'object-container')) - var yAxisObjSel = yAxisSel.select('.'+hypenate(yAxis.namespace(),'object-container')) + var chartObjSel = chartSel.select('.'+utils.str.hypenate(chart.namespace(),'object-container')) + var xAxisObjSel = xAxisSel.select('.'+utils.str.hypenate(xAxis.namespace(),'object-container')) + var yAxisObjSel = yAxisSel.select('.'+utils.str.hypenate(yAxis.namespace(),'object-container')) chartObjSel.attr('transform', 'translate('+0+','+0+')') xAxisObjSel.attr('transform', 'translate('+0+','+0+')') yAxisObjSel.attr('transform', 'translate('+0+','+0+')') diff --git a/src/scripts/modules/plot-zoom.js b/src/modules/aux/plot-zoom.js similarity index 87% rename from src/scripts/modules/plot-zoom.js rename to src/modules/aux/plot-zoom.js index 6cca5f6f2e4a96fa4d48be3b6bd04e66f0a98359..6aef3f48950bdf10f39ffdd88d255e63fa316da3 100644 --- a/src/scripts/modules/plot-zoom.js +++ b/src/modules/aux/plot-zoom.js @@ -1,5 +1,4 @@ -import {hypenate, safeSelect, getTranslation} from './helpers'; -import {log, warn, error, info} from './utils'; +import utils from '../utils/index.js'; /******************************************************************************* ** ** @@ -17,7 +16,7 @@ import {log, warn, error, info} from './utils'; * @namespace plotZoom * @returns {function} zoom */ -export function plotZoom( chart, xAxis, yAxis ) { +export default function plotZoom( chart, xAxis, yAxis ) { var /** * The event on which to fire @@ -122,13 +121,13 @@ export function plotZoom( chart, xAxis, yAxis ) { function setLocks() { - var chartObjSel = chartSel.select('.'+hypenate(chart.namespace(),'object-container')) - var chartObjTrans = getTranslation(chartObjSel.attr('transform')) + var chartObjSel = chartSel.select('.'+utils.str.hypenate(chart.namespace(),'object-container')) + var chartObjTrans = utils.sel.getTranslation(chartObjSel.attr('transform')) var cos = chartObjSel.attr('transform', 'translate(0,0)') xLock = chartSel.node().getBBox().width - chart.spaceX() * .9 yLock = chartSel.node().getBBox().height - chart.spaceY() * .9 cos.attr('transform', 'translate('+chartObjTrans[0]+','+chartObjTrans[1]+')') - log('plotZoom', 'setLocks', {xLock:xLock, yLock:yLock}) + utils.con.log('plotZoom', 'setLocks', {xLock:xLock, yLock:yLock}) } @@ -187,9 +186,9 @@ export function plotZoom( chart, xAxis, yAxis ) { - var chartObjSel = chartSel.select('.'+hypenate(chart.namespace(),'object-container')) - var xAxisObjSel = xAxisSel.select('.'+hypenate(xAxis.namespace(),'object-container')) - var yAxisObjSel = yAxisSel.select('.'+hypenate(yAxis.namespace(),'object-container')) + var chartObjSel = chartSel.select('.'+utils.str.hypenate(chart.namespace(),'object-container')) + var xAxisObjSel = xAxisSel.select('.'+utils.str.hypenate(xAxis.namespace(),'object-container')) + var yAxisObjSel = yAxisSel.select('.'+utils.str.hypenate(yAxis.namespace(),'object-container')) // xLock = chartSel.node().getBBox().width - chart.spaceX() - chartSel.node().getBBox().x // yLock = chartSel.node().getBBox().height - chart.spaceY() @@ -197,9 +196,9 @@ export function plotZoom( chart, xAxis, yAxis ) { // bhm.selection().node().getBBox().width - bhm.spaceX() - var chartObjTrans = getTranslation(chartObjSel.attr('transform')) - var xAxisObjTrans = getTranslation(xAxisObjSel.attr('transform')) - var yAxisObjTrans = getTranslation(yAxisObjSel.attr('transform')) + var chartObjTrans = utils.sel.getTranslation(chartObjSel.attr('transform')) + var xAxisObjTrans = utils.sel.getTranslation(xAxisObjSel.attr('transform')) + var yAxisObjTrans = utils.sel.getTranslation(yAxisObjSel.attr('transform')) var x = horizontalQ ? transform.applyX(chartObjTrans[0]) : 0 @@ -225,9 +224,9 @@ export function plotZoom( chart, xAxis, yAxis ) { if (orient == 'horizontal') {horizontalQ = true; verticalQ = false;} if (orient == 'vertical') {verticalQ = true; horizontalQ = false;} - var chartObjSel = chartSel.select('.'+hypenate(chart.namespace(),'object-container')) - var xAxisObjSel = xAxisSel.select('.'+hypenate(xAxis.namespace(),'object-container')) - var yAxisObjSel = yAxisSel.select('.'+hypenate(yAxis.namespace(),'object-container')) + var chartObjSel = chartSel.select('.'+utils.str.hypenate(chart.namespace(),'object-container')) + var xAxisObjSel = xAxisSel.select('.'+utils.str.hypenate(xAxis.namespace(),'object-container')) + var yAxisObjSel = yAxisSel.select('.'+utils.str.hypenate(yAxis.namespace(),'object-container')) chartObjSel.attr('transform', 'translate('+0+','+0+')') xAxisObjSel.attr('transform', 'translate('+0+','+0+')') yAxisObjSel.attr('transform', 'translate('+0+','+0+')') diff --git a/src/scripts/modules/select-filter.js b/src/modules/aux/select-filter.js similarity index 56% rename from src/scripts/modules/select-filter.js rename to src/modules/aux/select-filter.js index 22f8423551ab23a45ebd48502b25197b82a0204a..288eb419d084d3de4084b469ce311029ca54d333 100644 --- a/src/scripts/modules/select-filter.js +++ b/src/modules/aux/select-filter.js @@ -1,6 +1,6 @@ -import {hypenate, safeSelect} from './helpers'; +import utils from '../utils/index.js' -export function selectFilter(selection) { +export default function selectFilter(selection) { var data, @@ -21,26 +21,26 @@ export function selectFilter(selection) { function selectFilter() { var - container = safeSelect(selection, 'div', 'input-group').classed(hypenate(namespace,'container'),true), + container = utils.sel.safeSelect(selection, 'div', 'input-group').classed(utils.str.hypenate(namespace,'container'),true), - selectPrepend = safeSelect(container, 'div', 'select-prepend').classed('input-group-prepend', true), - selectPrependSpan = safeSelect(selectPrepend, 'span', 'input-group-text').text(selectionName), + selectPrepend = utils.sel.safeSelect(container, 'div', 'select-prepend').classed('input-group-prepend', true), + selectPrependSpan = utils.sel.safeSelect(selectPrepend, 'span', 'input-group-text').text(selectionName), - select = safeSelect(container, 'select', 'custom-select').classed(hypenate(namespace,'select'),true), + select = utils.sel.safeSelect(container, 'select', 'custom-select').classed(utils.str.hypenate(namespace,'select'),true), - selectAppend = safeSelect(container, 'div', 'select-append').classed('input-group-prepend', true), - selectAppendButton = safeSelect(selectAppend, 'a', 'filter-button').classed('btn btn-outline-secondary', true), - filterButtonIcon = safeSelect(selectAppendButton, 'i', 'fa fa-filter'), + selectAppend = utils.sel.safeSelect(container, 'div', 'select-append').classed('input-group-prepend', true), + selectAppendButton = utils.sel.safeSelect(selectAppend, 'a', 'filter-button').classed('btn btn-outline-secondary', true), + filterButtonIcon = utils.sel.safeSelect(selectAppendButton, 'i', 'fa fa-filter'), - inputGroup = safeSelect(container, 'div', 'filter-input-group').classed('input-group',true).classed('d-none', true), - inputPrepend = safeSelect(inputGroup, 'div', 'input-group-prepend'), - inputPrependSpan = safeSelect(inputPrepend, 'span', 'input-group-text').classed('search-button', true), - inputPrependSpanIcon = safeSelect(inputPrependSpan,'i','fa fa-search'), + inputGroup = utils.sel.safeSelect(container, 'div', 'filter-input-group').classed('input-group',true).classed('d-none', true), + inputPrepend = utils.sel.safeSelect(inputGroup, 'div', 'input-group-prepend'), + inputPrependSpan = utils.sel.safeSelect(inputPrepend, 'span', 'input-group-text').classed('search-button', true), + inputPrependSpanIcon = utils.sel.safeSelect(inputPrependSpan,'i','fa fa-search'), - input = safeSelect(inputGroup, 'input', 'form-control').attr('placeholder', 'all').attr('type', 'text'), - inputAppend = safeSelect(inputGroup, 'div', 'input-group-append'), - inputAppendButton = safeSelect(inputAppend, 'a', 'close-button').classed('btn btn-outline-secondary', true), - inputAppendButtonIcon = safeSelect(inputAppendButton, 'i', 'fa fa-close') + input = utils.sel.safeSelect(inputGroup, 'input', 'form-control').attr('placeholder', 'all').attr('type', 'text'), + inputAppend = utils.sel.safeSelect(inputGroup, 'div', 'input-group-append'), + inputAppendButton = utils.sel.safeSelect(inputAppend, 'a', 'close-button').classed('btn btn-outline-secondary', true), + inputAppendButtonIcon = utils.sel.safeSelect(inputAppendButton, 'i', 'fa fa-close') var keys = d3.keys(data), diff --git a/src/scripts/modules/axis.js b/src/modules/axis.js similarity index 91% rename from src/scripts/modules/axis.js rename to src/modules/axis.js index e2dae61f4c08ac2615e8eaaf370ee8d5c22bff5c..c3f3d1fb1f80cbc806258f7768fa78f8783a26cf 100644 --- a/src/scripts/modules/axis.js +++ b/src/modules/axis.js @@ -1,12 +1,5 @@ -import { - hypenate, safeSelect, extractViolinValues, - tickRange, modifyHexidecimalColorLuminance, truncateText, - truncateString, - round -} from './helpers'; -import {setupContainer, calculateWidthOfObject, calculateWidthOfSpacer} from './utils'; -import {unique, hasQ, flatten} from './array-functions'; -import {groupingSpacer} from './grouping-spacer'; +import utils from './utils/index.js' +import groupingSpacer from './grouping-spacer'; /******************************************************************************* ** ** ** ** @@ -24,7 +17,7 @@ import {groupingSpacer} from './grouping-spacer'; * @namespace axis * @returns {function} axis */ -export function axis ( selection ) { +export default function axis ( selection ) { var /** * The orientation of the axis @@ -780,7 +773,7 @@ export function axis ( selection ) { function axis () { // for convenience in handling orientation specific values - var horizontalQ = hasQ(['top', 'bottom', 'horizontal'], orient) ? true : false + var horizontalQ = utils.arr.hasQ(['top', 'bottom', 'horizontal'], orient) ? true : false var verticalQ = !horizontalQ // background cliping rectangle @@ -815,7 +808,7 @@ export function axis ( selection ) { } - var container = setupContainer( selection, namespace, bgcpRect, backgroundFill ); + var container = utils.sel.setupContainer( selection, namespace, bgcpRect, backgroundFill ); // defaults for text-anchor and text rotation if (orient == 'top') { @@ -853,12 +846,12 @@ export function axis ( selection ) { : (grouping == undefined) ? (numberOfTicks != undefined) // ? (tickValues.length < numberOfTicks) - ? (tickRange(...d3.extent(tickValues), numberOfTicks)) + ? (utils.math.tickRange(...d3.extent(tickValues), numberOfTicks)) : tickValues : grouping - var flatTickData = flatten(tickData) + var flatTickData = utils.arr.flatten(tickData) var numberOfObjects = flatTickData.length var space = horizontalQ ? spaceX : spaceY var extent = d3.extent(flatTickData) @@ -882,16 +875,16 @@ export function axis ( selection ) { // calculate object size if needed objectSize = (objectSize == undefined) - ? calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ) + ? utils.math.calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ) : objectSize // calculate spacer size if needed spacerSize = (spacerSize == undefined) - ? calculateWidthOfSpacer(flatTickData, space, objectSize, numberOfObjects, objectSpacer, overflowQ) + ? utils.math.calculateWidthOfSpacer(flatTickData, space, objectSize, numberOfObjects, objectSpacer, overflowQ) : spacerSize - var objClass = hypenate(namespace, categoricalQ ? objectClass+'-categorical' : objectClass) + var objClass = utils.str.hypenate(namespace, categoricalQ ? objectClass+'-categorical' : objectClass) var spacerFunction = groupingSpacer() .horizontalQ(horizontalQ).scale(scale).moveby((categoricalQ?'category':'scale')).numberOfObjects(numberOfObjects) @@ -956,11 +949,11 @@ export function axis ( selection ) { - var labelNameGroup = safeSelect(selection, 'g', hypenate(namespace,'axis-name')) + var labelNameGroup = utils.sel.safeSelect(selection, 'g', utils.str.hypenate(namespace,'axis-name')) - var labelElement = safeSelect(labelNameGroup, 'text', hypenate(namespace, 'name')) + var labelElement = utils.sel.safeSelect(labelNameGroup, 'text', utils.str.hypenate(namespace, 'name')) if (labelElement != undefined) { labelElement.text(label) @@ -1008,8 +1001,8 @@ export function axis ( selection ) { to use clip path to make things fit in fixed size. Have yet got this to work nicely. */ // var defs = d3.select(container.node().parentNode).select('defs') - // var tickLabelClipPath = safeSelect(defs, 'clipPath', hypenate(namespace,'tick-label-clip-path')).attr('id', hypenate(namespace,'tick-label-clip-path')) - // var tickLabelClipPathRect = safeSelect(tickLabelClipPath, 'rect', hypenate(namespace,'tick-label-clip-path-rect')) + // var tickLabelClipPath = utils.sel.safeSelect(defs, 'clipPath', utils.str.hypenate(namespace,'tick-label-clip-path')).attr('id', utils.str.hypenate(namespace,'tick-label-clip-path')) + // var tickLabelClipPathRect = utils.sel.safeSelect(tickLabelClipPath, 'rect', utils.str.hypenate(namespace,'tick-label-clip-path-rect')) // .attr('x', 0) // .attr('y', 0) // .attr('width', function(d, i){ @@ -1027,7 +1020,7 @@ export function axis ( selection ) { var that = d3.select(this).style('opacity', 1) // make and move tick - var tick = safeSelect(that, 'line', hypenate(namespace,'tick')) + var tick = utils.sel.safeSelect(that, 'line', utils.str.hypenate(namespace,'tick')) .attr("x1", 0) .attr("x2", horizontalQ ? 0 : orient == "left" ? -tickLength : tickLength) .attr("y1", 0) @@ -1043,15 +1036,15 @@ export function axis ( selection ) { }) // make and move label - var label = safeSelect(that, 'text', hypenate(namespace,'label')) + var label = utils.sel.safeSelect(that, 'text', utils.str.hypenate(namespace,'label')) .text(function(d, i){ - var s = typeof d == 'number' ? round(d, roundTo) : d - s = truncateString(String(s), (horizontalQ ? spaceY : spaceX) - tickLength-tickLabelMargin-tickTickLabelSpacer, tickLabelFontSize * 0.45) + var s = typeof d == 'number' ? utils.math.round(d, roundTo) : d + s = utils.str.truncateString(String(s), (horizontalQ ? spaceY : spaceX) - tickLength-tickLabelMargin-tickTickLabelSpacer, tickLabelFontSize * 0.45) return s }) .attr('font-size', tickLabelFontSize) .attr('text-anchor', tickLabelTextAnchor) - // truncateText(label, label.text(), orient, tickLength, horizontalQ ? spaceY : spaceX, overflowQ) + // utils.str.truncateText(label, label.text(), orient, tickLength, horizontalQ ? spaceY : spaceX, overflowQ) label.attr('transform', function(d, i) { var @@ -1097,11 +1090,11 @@ export function axis ( selection ) { .on('mousemove', labelHover) .on('mouseout', labelHoverOff) .on('click', tickLabelOnClick) - // .attr('clip-path', 'url(#'+hypenate(namespace,'tick-label-clip-path')+')') + // .attr('clip-path', 'url(#'+utils.str.hypenate(namespace,'tick-label-clip-path')+')') // add guidlines as needed if (guideLinesQ) { - var gline = safeSelect(that, 'line', hypenate(namespace, 'guideline')) + var gline = utils.sel.safeSelect(that, 'line', utils.str.hypenate(namespace, 'guideline')) .transition().duration(transitionDuration).ease(easeFunc) .attr("x1", 0) .attr("x2", horizontalQ ? 0 : orient == "left" ? guidelineSpace : -guidelineSpace) @@ -1114,15 +1107,15 @@ export function axis ( selection ) { t = 'translate('+x+','+y+')' return t }) - } else { that.select('line.'+hypenate(namespace, 'guideline')).remove() } + } else { that.select('line.'+utils.str.hypenate(namespace, 'guideline')).remove() } }) // apply alternating guidline thickness if (guideLinesQ) { - container.selectAll('.'+hypenate(namespace,'guideline')) + container.selectAll('.'+utils.str.hypenate(namespace,'guideline')) .attr('stroke', function(d, i){ - if (i % 2 == 0) { return modifyHexidecimalColorLuminance(guideLineStroke, 0.8) } + if (i % 2 == 0) { return utils.color.modifyHexidecimalColorLuminance(guideLineStroke, 0.8) } return guideLineStroke }) .attr('stroke-width', function(d, i){ @@ -1136,7 +1129,7 @@ export function axis ( selection ) { /*************************************************************************** ** Make the line of the axis ***************************************************************************/ - var line = safeSelect(selection, 'path', hypenate(namespace,'line')) + var line = utils.sel.safeSelect(selection, 'path', utils.str.hypenate(namespace,'line')) // .attr('x1', 0) // .attr('x2', horizontalQ ? spaceX : 0) // .attr('y1', 0) @@ -1156,21 +1149,21 @@ export function axis ( selection ) { // hover of label show full text label in case it is truncated function labelHover(d, i){ var t = d3.select(this).style('fill', 'red') - d3.select(t.node().parentNode).select("line."+hypenate(namespace,'tick')) + d3.select(t.node().parentNode).select("line."+utils.str.hypenate(namespace,'tick')) .attr("stroke", 'red') .attr("stroke-width", tickStrokeWidth*2) if (guideLinesQ) { - d3.select(t.node().parentNode).select('line.'+hypenate(namespace, 'guideline')) + d3.select(t.node().parentNode).select('line.'+utils.str.hypenate(namespace, 'guideline')) .attr('stroke', 'red') .attr('stroke-width', guideLineStrokeWidth*2) } - var s = typeof d == 'number' ? round(d, roundTo) : d + var s = typeof d == 'number' ? utils.math.round(d, roundTo) : d var m = d3.mouse(d3.select('html').node()) - var div = safeSelect(d3.select('body'), 'div', hypenate(namespace,'guideline-tooltip')) - .attr('id', hypenate(namespace,'guideline-tooltip')) + var div = utils.sel.safeSelect(d3.select('body'), 'div', utils.str.hypenate(namespace,'guideline-tooltip')) + .attr('id', utils.str.hypenate(namespace,'guideline-tooltip')) .style('position', 'absolute') .style('left', (d3.event.pageX+15)+'px') .style('top', (d3.event.pageY+15)+'px') @@ -1187,7 +1180,7 @@ export function axis ( selection ) { .style('border-style', 'solid') .style('border-width', 2) - var text = safeSelect(div, 'div') + var text = utils.sel.safeSelect(div, 'div') .text(tickLabelOnHoverFunc(s, i)) .style('color', 'black') .style('align-self', 'center') @@ -1200,15 +1193,15 @@ export function axis ( selection ) { function labelHoverOff(d, i){ var t = d3.select(this).style('fill', 'black') - d3.select(t.node().parentNode).select("line."+hypenate(namespace,'tick')) + d3.select(t.node().parentNode).select("line."+utils.str.hypenate(namespace,'tick')) .attr("stroke", tickStroke) .attr("stroke-width", tickStrokeWidth) if (guideLinesQ) { - var gline = d3.select(t.node().parentNode).select('line.'+hypenate(namespace, 'guideline')) + var gline = d3.select(t.node().parentNode).select('line.'+utils.str.hypenate(namespace, 'guideline')) var minorQ = gline.attr('minor') gline.attr('stroke', function(d, ii){ - if (minorQ == 'true') { return modifyHexidecimalColorLuminance(guideLineStroke, 0.8) } + if (minorQ == 'true') { return utils.color.modifyHexidecimalColorLuminance(guideLineStroke, 0.8) } return guideLineStroke }) .attr('stroke-width', function(d, ii){ @@ -1216,7 +1209,7 @@ export function axis ( selection ) { return guideLineStrokeWidth }) } - d3.select("#"+hypenate(namespace,'guideline-tooltip')).remove() + d3.select("#"+utils.str.hypenate(namespace,'guideline-tooltip')).remove() } diff --git a/src/scripts/modules/bar.js b/src/modules/charts/bar.js similarity index 96% rename from src/scripts/modules/bar.js rename to src/modules/charts/bar.js index 6e75c754c9edfa2d569e8f419d805a8efa44cc89..82318b91353631316da89827b7a1fbf011265b8a 100644 --- a/src/scripts/modules/bar.js +++ b/src/modules/charts/bar.js @@ -1,9 +1,7 @@ -import {hypenate, safeSelect} from './helpers'; -import {setupContainer, calculateWidthOfObject, calculateWidthOfSpacer} from './utils'; -import {unique, flatten} from './array-functions'; -import {groupingSpacer} from './grouping-spacer'; -import {colorFunction as CF} from './color-function'; -import {tooltip as TTip} from './tooltip'; +import utils from '../utils/index.js' +import groupingSpacer from '../grouping-spacer'; +import CF from '../color-function'; +import TTip from '../tooltip'; /******************************************************************************* ** ** ** ** @@ -21,7 +19,7 @@ import {tooltip as TTip} from './tooltip'; * @namespace bar * @returns {function} bar */ -export function bar ( selection ) { +export default function bar ( selection ) { /* Assumes that data is list an object. @@ -503,7 +501,7 @@ export function bar ( selection ) { // background cliping rectangle var bgcpRect = {x:0, y:0, width: spaceX, height:spaceY} - var container = setupContainer( selection, namespace, bgcpRect, backgroundFill ); + var container = utils.sel.setupContainer( selection, namespace, bgcpRect, backgroundFill ); // to prevent re-calculation and getters to be passed to axes barKeys = d3.keys(data) @@ -512,7 +510,7 @@ export function bar ( selection ) { // if grouping is undefined sort barKeys by sortingFunction var ordered = (grouping == undefined) ? barKeys.sort(sortingFunction) : grouping // ordered might be nested depending on grouping - barKeys = flatten(ordered) + barKeys = utils.arr.flatten(ordered) var numberOfObjects = barKeys.length var extent = [Math.min(...barValues) - domainPadding,Math.max(...barValues) + domainPadding]; @@ -530,12 +528,12 @@ export function bar ( selection ) { var space = horizontalQ ? spaceX : spaceY // calculate object size objectSize = (objectSize == undefined) - ? calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ) + ? utils.math.calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ) : objectSize // calculate spacer size if needed spacerSize = (spacerSize == undefined) - ? calculateWidthOfSpacer(barKeys, space, objectSize, numberOfObjects, objectSpacer, overflowQ) + ? utils.math.calculateWidthOfSpacer(barKeys, space, objectSize, numberOfObjects, objectSpacer, overflowQ) : spacerSize // make the nested groups var spacerFunction = groupingSpacer() @@ -602,7 +600,7 @@ export function bar ( selection ) { strokeColor = colorFunction(key, value, i, 'stroke') - var bar = safeSelect(t, 'rect', 'bar-rect') + var bar = utils.sel.safeSelect(t, 'rect', 'bar-rect') if (bar.attr('transform') == undefined) { bar.attr('transform', function(d, i) { diff --git a/src/scripts/modules/box-whisker.js b/src/modules/charts/box-whisker.js similarity index 94% rename from src/scripts/modules/box-whisker.js rename to src/modules/charts/box-whisker.js index 03a0842e4fe0f715963e0506f45459801b42b2b9..ee7121feeb113560779a5cfa66e0916318aba005 100644 --- a/src/scripts/modules/box-whisker.js +++ b/src/modules/charts/box-whisker.js @@ -1,9 +1,7 @@ -import {hypenate, safeSelect} from './helpers'; -import {setupContainer, calculateWidthOfObject, calculateWidthOfSpacer, whiskerPath} from './utils'; -import {unique, hasQ, flatten} from './array-functions'; -import {groupingSpacer} from './grouping-spacer'; -import {colorFunction as CF} from './color-function'; -import {tooltip as TTip} from './tooltip'; +import utils from '../utils/index.js'; +import groupingSpacer from '../grouping-spacer'; +import CF from '../color-function'; +import TTip from '../tooltip'; /******************************************************************************* ** ** ** ** @@ -20,7 +18,7 @@ import {tooltip as TTip} from './tooltip'; * @namespace boxwhisker * @returns {function} boxwhisker */ -export function boxwhisker( selection ) { +export default function boxwhisker( selection ) { var /** * Data to plot. Assumed to be a object, where each key corresponds to a box @@ -550,12 +548,12 @@ export function boxwhisker( selection ) { // background cliping rectangle var bgcpRect = {x:0, y:0, width: spaceX, height:spaceY} - var container = setupContainer( selection, namespace, bgcpRect, backgroundFill ); + var container = utils.sel.setupContainer( selection, namespace, bgcpRect, backgroundFill ); // if grouping is undefined sort keys by sorting funct var ordered = (grouping == undefined) ? d3.keys(data).sort(sortingFunction) : grouping // to prevent re-calculation and getters to be passed to axes - boxKeys = flatten(ordered) + boxKeys = utils.arr.flatten(ordered) boxValues = boxKeys.map(valueExtractor) @@ -569,9 +567,9 @@ export function boxwhisker( selection ) { scale.domain(extent).range(horizontalQ ? [0,spaceY] : [spaceX, 0]) var space = horizontalQ ? spaceX : spaceY // calculate object size - objectSize = calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ) + objectSize = utils.math.calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ) // calculate spacer size if needed - spacerSize = calculateWidthOfSpacer(boxKeys, space, objectSize, numberOfObjects, objectSpacer, overflowQ) + spacerSize = utils.math.calculateWidthOfSpacer(boxKeys, space, objectSize, numberOfObjects, objectSpacer, overflowQ) // make the nested groups var spacerFunction = groupingSpacer() .horizontalQ(horizontalQ).scale(scale).moveby('category').numberOfObjects(numberOfObjects) @@ -584,7 +582,7 @@ export function boxwhisker( selection ) { var parentIndexArray = [] container.selectAll('g:not(.to-remove).'+objectClass) - .each(function(d, i){if (hasQ(boxKeys, d)){ parentIndexArray.push(Number(d3.select(this).attr('parent-index')))}}) + .each(function(d, i){if (utils.arr.hasQ(boxKeys, d)){ parentIndexArray.push(Number(d3.select(this).attr('parent-index')))}}) @@ -611,13 +609,13 @@ export function boxwhisker( selection ) { var - whisk = safeSelect(t, 'g', 'whisker'), - uWhisk = safeSelect(whisk, 'path', 'upper'), - lWhisk = safeSelect(whisk, 'path', 'lower'), - quart = safeSelect(t, 'g', 'quartile'), - uQuart = safeSelect(quart, 'rect', 'upper'), - lQuart = safeSelect(quart, 'rect', 'lower'), - mQuart = safeSelect(quart, 'circle', 'median') + whisk = utils.sel.safeSelect(t, 'g', 'whisker'), + uWhisk = utils.sel.safeSelect(whisk, 'path', 'upper'), + lWhisk = utils.sel.safeSelect(whisk, 'path', 'lower'), + quart = utils.sel.safeSelect(t, 'g', 'quartile'), + uQuart = utils.sel.safeSelect(quart, 'rect', 'upper'), + lQuart = utils.sel.safeSelect(quart, 'rect', 'lower'), + mQuart = utils.sel.safeSelect(quart, 'circle', 'median') // set upper quartile (q3) @@ -678,7 +676,7 @@ export function boxwhisker( selection ) { y = 0, h = horizontalQ ? scale(q1) - scale(q0) : objectSize, w = verticalQ ? scale(q1) - scale(q0) : objectSize - return whiskerPath(dir, x, y, w, h, whiskerWidthPercent, orient) + return utils.paths.whiskerPath(dir, x, y, w, h, whiskerWidthPercent, orient) }) .attr('transform', function(d, i){ var @@ -699,7 +697,7 @@ export function boxwhisker( selection ) { y = 0, h = horizontalQ ? scale(q4) - scale(q3) : objectSize, w = verticalQ ? scale(q4) - scale(q3) : objectSize - return whiskerPath(dir, x, y, w, h, whiskerWidthPercent, orient) + return utils.paths.whiskerPath(dir, x, y, w, h, whiskerWidthPercent, orient) }) .attr('transform', function(d, i){ var diff --git a/src/scripts/modules/bubble-heatmap.js b/src/modules/charts/bubble-heatmap.js similarity index 91% rename from src/scripts/modules/bubble-heatmap.js rename to src/modules/charts/bubble-heatmap.js index 8d4707ee52f81ffc4baafe5daa5dd97bfd5d806a..906e05c8bb73e29ff5f4bd67896026377f0c6f51 100644 --- a/src/scripts/modules/bubble-heatmap.js +++ b/src/modules/charts/bubble-heatmap.js @@ -1,9 +1,7 @@ -import {hypenate, safeSelect} from './helpers'; -import {setupContainer, calculateWidthOfObject, calculateWidthOfSpacer, log} from './utils'; -import {unique} from './array-functions'; -import {groupingSpacer} from './grouping-spacer'; -import {colorFunction as CF} from './color-function'; -import {tooltip as TTip} from './tooltip'; +import utils from '../utils/index.js' +import groupingSpacer from '../grouping-spacer'; +import CF from '../color-function'; +import TTip from '../tooltip'; /** @@ -15,7 +13,7 @@ import {tooltip as TTip} from './tooltip'; * @namespace bubbleHeatmap * @returns {function} bubbleHeatmap */ -function bubbleHeatmap( selection ) { +export default function bubbleHeatmap( selection ) { var /** * Data to plot. Assumed to be a object, where each key corresponds to a cell @@ -220,7 +218,7 @@ function bubbleHeatmap( selection ) { */ cellKeys, /** - * Stores the list of unique xValues + * Stores the list of utils.arr.unique xValues * Calculated after bubbleHeatmap called. * @param {string[]} [xValues=undefined] * @memberof bubbleHeatmap# @@ -228,7 +226,7 @@ function bubbleHeatmap( selection ) { */ xValues, /** - * Stores the list of unique yValues + * Stores the list of utils.arr.unique yValues * Calculated after bubbleHeatmap called. * @param {string[]} [yValues=undefined] * @memberof bubbleHeatmap# @@ -236,7 +234,7 @@ function bubbleHeatmap( selection ) { */ yValues, /** - * Stores the list of unique rValues + * Stores the list of utils.arr.unique rValues * Calculated after bubbleHeatmap called. * @param {string[]} [rValues=undefined] * @memberof bubbleHeatmap# @@ -244,7 +242,7 @@ function bubbleHeatmap( selection ) { */ rValues, /** - * Stores the list of unique vValues + * Stores the list of utils.arr.unique vValues * Calculated after bubbleHeatmap called. * @param {string[]} [vValues=undefined] * @memberof bubbleHeatmap# @@ -673,19 +671,19 @@ function bubbleHeatmap( selection ) { function bhm() { var horizontalQ = true; // no orientation in heatmaps. Aids as placeholder in functions that take orient as a parameter var bgcpRect = {x:0, y:0, width: spaceX, height:spaceY} - var container = setupContainer( selection, namespace, bgcpRect, backgroundFill ); + var container = utils.sel.setupContainer( selection, namespace, bgcpRect, backgroundFill ); cellKeys = d3.keys(data); cellKeys.sort(function(a, b){ return xKeySortingFunction(a, b) || yKeySortingFunction(a, b) }) - log('bubbleHeatmap', 'cells are sorted by', cellKeys) + utils.con.log('bubbleHeatmap', 'cells are sorted by', cellKeys) - xValues = unique(cellKeys.map(xExtractor)); - yValues = unique(cellKeys.map(yExtractor)); - rValues = unique(cellKeys.map(rExtractor)); - vValues = unique(cellKeys.map(vExtractor)); - log('bubbleHeatmap', 'x and y keys are', {x: xValues, y:yValues}) + xValues = utils.arr.unique(cellKeys.map(xExtractor)); + yValues = utils.arr.unique(cellKeys.map(yExtractor)); + rValues = utils.arr.unique(cellKeys.map(rExtractor)); + vValues = utils.arr.unique(cellKeys.map(vExtractor)); + utils.con.log('bubbleHeatmap', 'x and y keys are', {x: xValues, y:yValues}) var xDim = xValues.length, yDim = yValues.length; @@ -694,11 +692,11 @@ function bubbleHeatmap( selection ) { var extent = [Math.min(...rValues) - domainPadding,Math.max(...rValues) + domainPadding]; - ySize = calculateWidthOfObject(spaceY, yDim, minObjectSize, maxObjectSize, objectSpacer, overflowQ) - xSize = calculateWidthOfObject(spaceX, xDim, minObjectSize, maxObjectSize, objectSpacer, overflowQ) - ySpacerSize = calculateWidthOfSpacer(yValues, spaceY, ySize, yDim, objectSpacer, overflowQ) - xSpacerSize = calculateWidthOfSpacer(xValues, spaceX, xSize, xDim, objectSpacer, overflowQ) - log('bubbleHeatmap', 'size of', {x: xSize, y: ySize}) + ySize = utils.math.calculateWidthOfObject(spaceY, yDim, minObjectSize, maxObjectSize, objectSpacer, overflowQ) + xSize = utils.math.calculateWidthOfObject(spaceX, xDim, minObjectSize, maxObjectSize, objectSpacer, overflowQ) + ySpacerSize = utils.math.calculateWidthOfSpacer(yValues, spaceY, ySize, yDim, objectSpacer, overflowQ) + xSpacerSize = utils.math.calculateWidthOfSpacer(xValues, spaceX, xSize, xDim, objectSpacer, overflowQ) + utils.con.log('bubbleHeatmap', 'size of', {x: xSize, y: ySize}) scale.domain(extent).range([Math.min(minObjectSize/2, Math.min(ySize, xSize)/2), Math.min(ySize, xSize)/2]) @@ -706,7 +704,7 @@ function bubbleHeatmap( selection ) { var ySpacer = groupingSpacer() .horizontalQ(false) .moveby('category').numberOfObjects(yDim) - .objectClass(hypenate(objectClass, 'row')) + .objectClass(utils.str.hypenate(objectClass, 'row')) .objectSize(ySize).spacerSize(ySpacerSize) .transitionDuration(transitionDuration).easeFunc(easeFunc) .namespace('row') @@ -720,7 +718,7 @@ function bubbleHeatmap( selection ) { ySpacer(container, yValues, 0) - container.selectAll('g.'+hypenate(objectClass, 'row')) + container.selectAll('g.'+utils.str.hypenate(objectClass, 'row')) .each(function(d, i){ xSpacer(d3.select(this), xValues, 0) }) @@ -735,7 +733,7 @@ function bubbleHeatmap( selection ) { : colorFunction.dataExtent([0, Math.max(...vValues)]) cells.each(function(key, i) { - log('bubbleHeatmap', 'each cell', {key: key, index: i, node: d3.select(this).node()}) + utils.con.log('bubbleHeatmap', 'each cell', {key: key, index: i, node: d3.select(this).node()}) var t = d3.select(this), currentData = data[key], @@ -745,9 +743,9 @@ function bubbleHeatmap( selection ) { fillColor = colorFunction(key, value, i, 'fill'), // prevent duplicate computation strokeColor = colorFunction(key, value, i, 'stroke') - log('bubbleHeatmap', 'radius',{radius: radius, scaled: scale(radius), extent: extent, range:scale.range()}) + utils.con.log('bubbleHeatmap', 'radius',{radius: radius, scaled: scale(radius), extent: extent, range:scale.range()}) - var c = safeSelect(t, 'circle', hypenate(objectClass,'circle')) + var c = utils.sel.safeSelect(t, 'circle', utils.str.hypenate(objectClass,'circle')) c.attr('cx', xSize / 2) .attr('cy', ySize / 2 ) .attr('r', scale(radius)) @@ -757,10 +755,10 @@ function bubbleHeatmap( selection ) { }) - tooltip.selection(cells.selectAll('circle.'+hypenate(objectClass, 'circle'))) + tooltip.selection(cells.selectAll('circle.'+utils.str.hypenate(objectClass, 'circle'))) .data(data) // .keys(['r', 'v']) - // .header(function(d, i){return hypenate(data[d][xKey], data[d][yKey]) }) + // .header(function(d, i){return utils.str.hypenate(data[d][xKey], data[d][yKey]) }) tooltip() @@ -769,5 +767,3 @@ function bubbleHeatmap( selection ) { return bhm; } - -export {bubbleHeatmap} diff --git a/src/scripts/modules/heatmap.js b/src/modules/charts/heatmap.js similarity index 92% rename from src/scripts/modules/heatmap.js rename to src/modules/charts/heatmap.js index a55c7f687f7779c8270c136f6f1a9663b55550ab..57777c09f36f8b8be45dea6a7ea683919c65478a 100644 --- a/src/scripts/modules/heatmap.js +++ b/src/modules/charts/heatmap.js @@ -1,9 +1,7 @@ -import {hypenate, safeSelect} from './helpers'; -import {setupContainer, calculateWidthOfObject, calculateWidthOfSpacer, log} from './utils'; -import {unique} from './array-functions'; -import {groupingSpacer} from './grouping-spacer'; -import {colorFunction as CF} from './color-function'; -import {tooltip as TTip} from './tooltip'; +import utils from '../utils/index.js' +import groupingSpacer from '../grouping-spacer'; +import CF from '../color-function'; +import TTip from '../tooltip'; /** @@ -15,7 +13,7 @@ import {tooltip as TTip} from './tooltip'; * @namespace heatmap * @returns {function} heatmap */ -function heatmap( selection ) { +export default function heatmap( selection ) { var /** * Data to plot. Assumed to be a object, where each key corresponds to a cell @@ -204,7 +202,7 @@ function heatmap( selection ) { */ cellKeys, /** - * Stores the list of unique xValues + * Stores the list of utils.arr.unique xValues * Calculated after heatmap called. * @param {string[]} [xValues=undefined] * @memberof heatmap# @@ -212,7 +210,7 @@ function heatmap( selection ) { */ xValues, /** - * Stores the list of unique yValues + * Stores the list of utils.arr.unique yValues * Calculated after heatmap called. * @param {string[]} [yValues=undefined] * @memberof heatmap# @@ -220,7 +218,7 @@ function heatmap( selection ) { */ yValues, /** - * Stores the list of unique vValues + * Stores the list of utils.arr.unique vValues * Calculated after heatmap called. * @param {string[]} [vValues=undefined] * @memberof heatmap# @@ -619,29 +617,29 @@ function heatmap( selection ) { function hm() { var horizontalQ = true; // no orientation in heatmaps. Aids as placeholder in functions that take orient as a parameter var bgcpRect = {x:0, y:0, width: spaceX, height:spaceY} - var container = setupContainer( selection, namespace, bgcpRect, backgroundFill ); + var container = utils.sel.setupContainer( selection, namespace, bgcpRect, backgroundFill ); cellKeys = d3.keys(data); - xValues = unique(cellKeys.map(xExtractor)); - yValues = unique(cellKeys.map(yExtractor)); - vValues = unique(cellKeys.map(vExtractor)); + xValues = utils.arr.unique(cellKeys.map(xExtractor)); + yValues = utils.arr.unique(cellKeys.map(yExtractor)); + vValues = utils.arr.unique(cellKeys.map(vExtractor)); cellKeys.sort(function(a, b){ return xKeySortingFunction(a, b) || yKeySortingFunction(a, b) }) - log('heatmap', 'cells are sorted by', cellKeys) + utils.con.log('heatmap', 'cells are sorted by', cellKeys) - log('heatmap', 'x and y keys are', {x: xValues, y:yValues}) + utils.con.log('heatmap', 'x and y keys are', {x: xValues, y:yValues}) var xDim = xValues.length, yDim = yValues.length; - ySize = calculateWidthOfObject(spaceY, yDim, yMinObjectSize, yMaxObjectSize, objectSpacer, overflowQ) - xSize = calculateWidthOfObject(spaceX, xDim, xMinObjectSize, xMaxObjectSize, objectSpacer, overflowQ) - ySpacerSize = calculateWidthOfSpacer(yValues, spaceY, ySize, yDim, objectSpacer, overflowQ) - xSpacerSize = calculateWidthOfSpacer(xValues, spaceX, xSize, xDim, objectSpacer, overflowQ) + ySize = utils.math.calculateWidthOfObject(spaceY, yDim, yMinObjectSize, yMaxObjectSize, objectSpacer, overflowQ) + xSize = utils.math.calculateWidthOfObject(spaceX, xDim, xMinObjectSize, xMaxObjectSize, objectSpacer, overflowQ) + ySpacerSize = utils.math.calculateWidthOfSpacer(yValues, spaceY, ySize, yDim, objectSpacer, overflowQ) + xSpacerSize = utils.math.calculateWidthOfSpacer(xValues, spaceX, xSize, xDim, objectSpacer, overflowQ) // console.table({ // x:{ // object: xSize, @@ -655,7 +653,7 @@ function heatmap( selection ) { // } // // }) - log('heatmap', 'size of', {x: xSize, y: ySize}) + utils.con.log('heatmap', 'size of', {x: xSize, y: ySize}) @@ -663,7 +661,7 @@ function heatmap( selection ) { .horizontalQ(false) .moveby('category') .numberOfObjects(yDim) - .objectClass(hypenate(objectClass, 'row')) + .objectClass(utils.str.hypenate(objectClass, 'row')) .objectSize(ySize + ySpacerSize) .spacerSize(0) .transitionDuration(transitionDuration) @@ -682,7 +680,7 @@ function heatmap( selection ) { ySpacer(container, yValues, 0) - container.selectAll('g.'+hypenate(objectClass, 'row')) + container.selectAll('g.'+utils.str.hypenate(objectClass, 'row')) .each(function(d, i){ xSpacer(d3.select(this), xValues, 0) }) var cells = container.selectAll('g:not(.to-remove).'+objectClass) @@ -725,7 +723,7 @@ function heatmap( selection ) { : colorFunction.dataExtent([0, Math.max(...vValues)]) cells.each(function(key, i) { - log('heatmap', 'each cell', {key: key, index: i, node: d3.select(this).node()}) + utils.con.log('heatmap', 'each cell', {key: key, index: i, node: d3.select(this).node()}) var t = d3.select(this) if (key == undefined) {return} @@ -735,7 +733,7 @@ function heatmap( selection ) { fillColor = colorFunction(key, value, i, 'fill'), // prevent duplicate computation strokeColor = colorFunction(key, value, i, 'stroke') - var c = safeSelect(t, 'rect', hypenate(objectClass,'rect')) + var c = utils.sel.safeSelect(t, 'rect', utils.str.hypenate(objectClass,'rect')) c.attr('width', xSize + xSpacerSize - objectStrokeWidth) .attr('height', ySize + ySpacerSize - objectStrokeWidth) .attr('fill', fillColor) @@ -746,10 +744,10 @@ function heatmap( selection ) { }) - tooltip.selection(cells.selectAll('rect.'+hypenate(objectClass, 'rect'))) + tooltip.selection(cells.selectAll('rect.'+utils.str.hypenate(objectClass, 'rect'))) .data(data) // .keys(['r', 'v']) - // .header(function(d, i){return hypenate(data[d][xKey], data[d][yKey]) }) + // .header(function(d, i){return utils.str.hypenate(data[d][xKey], data[d][yKey]) }) tooltip() @@ -758,5 +756,3 @@ function heatmap( selection ) { return hm; } - -export {heatmap} diff --git a/src/modules/charts/index.js b/src/modules/charts/index.js new file mode 100644 index 0000000000000000000000000000000000000000..7f9cc5645bdf64fad048925d49436e2bead6046c --- /dev/null +++ b/src/modules/charts/index.js @@ -0,0 +1,15 @@ +import scatter from './scatter' +import bar from './bar' +import bubble from './bubble-heatmap' +import boxwhisker from './box-whisker' +import heatmap from './heatmap' +import violin from './violin' +import {neededViolinValues} from './violin' +import upset from './upset' + +let charts = { + scatter, bar, bubble, boxwhisker, heatmap, violin, neededViolinValues, upset +} + +export {scatter, bar, bubble, boxwhisker, heatmap, violin, neededViolinValues, upset} +export default charts diff --git a/src/scripts/modules/scatter.js b/src/modules/charts/scatter.js similarity index 97% rename from src/scripts/modules/scatter.js rename to src/modules/charts/scatter.js index 2dcb81b4ffadc92d41e501bfe7df34d4ea62a3ad..07aea69685b214248288f82e34bb55fa6a0df67a 100644 --- a/src/scripts/modules/scatter.js +++ b/src/modules/charts/scatter.js @@ -1,9 +1,6 @@ -import {hypenate, safeSelect} from './helpers'; -import {setupContainer, calculateWidthOfObject, calculateWidthOfSpacer} from './utils'; -import {unique, flatten} from './array-functions'; -import {groupingSpacer} from './grouping-spacer'; -import {colorFunction as CF} from './color-function'; -import {tooltip as TTip} from './tooltip'; +import utils from '../utils/index.js' +import CF from '../color-function'; +import TTip from '../tooltip'; /******************************************************************************* ** ** ** ** @@ -20,7 +17,7 @@ import {tooltip as TTip} from './tooltip'; * @namespace scatter * @returns {function} scatter */ -export function scatter ( selection ) { +export default function scatter ( selection ) { var /** @@ -500,7 +497,7 @@ export function scatter ( selection ) { function scatter() { // background cliping rectangle var bgcpRect = {x:0, y:0, width: spaceX, height:spaceY} - var container = setupContainer( selection, namespace, bgcpRect, backgroundFill ); + var container = utils.sel.setupContainer( selection, namespace, bgcpRect, backgroundFill ); pointKeys = d3.keys(data) diff --git a/src/scripts/modules/upset.js b/src/modules/charts/upset.js similarity index 84% rename from src/scripts/modules/upset.js rename to src/modules/charts/upset.js index 506f6e30b4ba408c914ba40a55f8cec1101dfeff..aedfde4352210ea7b78b304af9e45701f56ec41c 100644 --- a/src/scripts/modules/upset.js +++ b/src/modules/charts/upset.js @@ -1,10 +1,8 @@ -import {hypenate, safeSelect} from './helpers'; -import {setupContainer, calculateWidthOfObject, calculateWidthOfSpacer, log} from './utils'; -import {unique, flatten} from './array-functions'; -import {groupingSpacer} from './grouping-spacer'; -import {colorFunction as CF} from './color-function'; -import {tooltip as TTip} from './tooltip'; -export function upset ( selection ) { +import utils from '../utils/index.js' +import groupingSpacer from '../grouping-spacer'; +import CF from '../color-function'; +import TTip from '../tooltip'; +export default function upset ( selection ) { var data, orient='horizontal', @@ -88,12 +86,12 @@ export function upset ( selection ) { // background cliping rectangle var bgcpRect = {x:0, y:0, width: spaceX, height:spaceY} - var container = setupContainer( selection, namespace, bgcpRect, backgroundFill ); + var container = utils.sel.setupContainer( selection, namespace, bgcpRect, backgroundFill ); cellKeys = d3.keys(data) - setValues = unique(cellKeys.map(setExtractor)).sort() - intersectionValues = unique(cellKeys.map(intersectionExtractor)).sort().sort(function(a, b){ + setValues = utils.arr.unique(cellKeys.map(setExtractor)).sort() + intersectionValues = utils.arr.unique(cellKeys.map(intersectionExtractor)).sort().sort(function(a, b){ return a.split(';').length - b.split(';').length }) @@ -112,13 +110,13 @@ export function upset ( selection ) { xDim = horizontalQ ? xValues.length : yValues.length, yDim = horizontalQ ? yValues.length : xValues.length - // console.log(xValues, yValues) + // console.utils.con.log(xValues, yValues) - xObjectSize = calculateWidthOfObject(spaceX, xDim, minObjectSize, maxObjectSize, xObjectSpacer, overflowQ) - yObjectSize = calculateWidthOfObject(spaceY, yDim, minObjectSize, maxObjectSize, yObjectSpacer, overflowQ) - xSpacerSize = calculateWidthOfSpacer(xValues, spaceX, xObjectSize, xDim, xObjectSpacer, overflowQ) - ySpacerSize = calculateWidthOfSpacer(yValues, spaceY, yObjectSize, yDim, yObjectSpacer, overflowQ) + xObjectSize = utils.math.calculateWidthOfObject(spaceX, xDim, minObjectSize, maxObjectSize, xObjectSpacer, overflowQ) + yObjectSize = utils.math.calculateWidthOfObject(spaceY, yDim, minObjectSize, maxObjectSize, yObjectSpacer, overflowQ) + xSpacerSize = utils.math.calculateWidthOfSpacer(xValues, spaceX, xObjectSize, xDim, xObjectSpacer, overflowQ) + ySpacerSize = utils.math.calculateWidthOfSpacer(yValues, spaceY, yObjectSize, yDim, yObjectSpacer, overflowQ) var ySpacer = groupingSpacer() .horizontalQ(false) @@ -137,17 +135,17 @@ export function upset ( selection ) { if (verticalQ) { xSpacer.objectClass(objectClass) - ySpacer.namespace('across').objectClass(hypenate(objectClass, 'across')) + ySpacer.namespace('across').objectClass(utils.str.hypenate(objectClass, 'across')) ySpacer(container, yValues, 0) - container.selectAll('g.'+hypenate(objectClass, 'across')) + container.selectAll('g.'+utils.str.hypenate(objectClass, 'across')) .each(function(d, i){ xSpacer(d3.select(this), xValues, 0) }) } else { - xSpacer.namespace('across').objectClass(hypenate(objectClass, 'across')) + xSpacer.namespace('across').objectClass(utils.str.hypenate(objectClass, 'across')) ySpacer.objectClass(objectClass) xSpacer(container, xValues, 0) - container.selectAll('g.'+hypenate(objectClass, 'across')) + container.selectAll('g.'+utils.str.hypenate(objectClass, 'across')) .each(function(d, i){ ySpacer(d3.select(this), yValues, 0) }) } @@ -167,11 +165,11 @@ export function upset ( selection ) { // } else { // positionedCellKeys.push(lookupValue) // } - // console.log(i, j, lookupValue) + // console.utils.con.log(i, j, lookupValue) // } // } // - // // console.log(positionedCellKeys) + // // console.utils.con.log(positionedCellKeys) // // cells.data(positionedCellKeys); @@ -183,17 +181,17 @@ export function upset ( selection ) { if (key == undefined) {return } var currentData = data[key] - // console.log(key, currentData) + // console.utils.con.log(key, currentData) var set = setExtractor(key, i), intersection = intersectionExtractor(key, i) - // console.log(set, intersection) + // console.utils.con.log(set, intersection) t.classed(intersection, true) t.classed(set, true) - var c = safeSelect(t, 'circle', hypenate(objectClass,'circle')) + var c = utils.sel.safeSelect(t, 'circle', utils.str.hypenate(objectClass,'circle')) c.attr('cx', xObjectSize / 2) .attr('cy', yObjectSize / 2 ) .attr('r', radius == undefined ? Math.min(xObjectSize, yObjectSize) / 2 : radius) diff --git a/src/scripts/modules/violin.js b/src/modules/charts/violin.js similarity index 94% rename from src/scripts/modules/violin.js rename to src/modules/charts/violin.js index b6b7eea76b2965643eaf5568a430bb41affae817..ca6651bbc5832f3b41c072eb2c688b3f5d591c56 100644 --- a/src/scripts/modules/violin.js +++ b/src/modules/charts/violin.js @@ -1,9 +1,7 @@ -import {hypenate, safeSelect, modifyHexidecimalColorLuminance, extractViolinValues, quartiles} from './helpers'; -import {setupContainer, calculateWidthOfObject, calculateWidthOfSpacer} from './utils'; -import {unique, hasQ, flatten, whichBin} from './array-functions'; -import {groupingSpacer} from './grouping-spacer'; -import {colorFunction as CF} from './color-function'; -import {tooltip as TTip} from './tooltip'; +import utils from '../utils/index.js'; +import groupingSpacer from '../grouping-spacer'; +import CF from '../color-function'; +import TTip from '../tooltip'; /******************************************************************************* ** ** @@ -22,7 +20,7 @@ import {tooltip as TTip} from './tooltip'; * @namespace violin * @returns {function} violin */ -export function violin( selection ) { +export default function violin( selection ) { var /** * Data to plot. Assumed to be a object, where each key corresponds to a violin @@ -156,9 +154,9 @@ export function violin( selection ) { */ pointColorFunc = function (d, type, base, min, max) { var minMaxHexScale = d3.scaleLinear().domain([min, max]).range([-0.25, 0.05]) - var scaledColor = modifyHexidecimalColorLuminance(base.replace('#', ''), minMaxHexScale(d)) + var scaledColor = utils.color.modifyHexidecimalColorLuminance(base.replace('#', ''), minMaxHexScale(d)) var mod = type == "stroke" ? 0 : 0.25 - return modifyHexidecimalColorLuminance(scaledColor.replace('#', ''), mod) + return utils.color.modifyHexidecimalColorLuminance(scaledColor.replace('#', ''), mod) }, /** @@ -213,12 +211,12 @@ export function violin( selection ) { easeFunc = d3.easeExp, /** - * The key containing the quartiles + * The key containing the utils.math.quartiles * @param {string} [quartilesKey=undefined] * @memberof violin# * @property */ - quartilesKey = "quartiles", + quartilesKey = "utils.math.quartiles", /** * The keys corresponding to each quartile * @param {string[]} [quartileKeys=["Q0", "Q1", "Q2", "Q3", "Q4"]] @@ -578,7 +576,7 @@ export function violin( selection ) { * @returns {violin | string} * @memberof violin * @property - * by default quartileKey = "quartiles" + * by default quartileKey = "utils.math.quartiles" */ violin.quartileKey = function(_) { return arguments.length ? (quartileKey = _, violin) : quartileKey; }; /** @@ -666,14 +664,14 @@ export function violin( selection ) { // background cliping rectangle var bgcpRect = {x:0, y:0, width: spaceX, height:spaceY} - var container = setupContainer( selection, namespace, bgcpRect, backgroundFill ); + var container = utils.sel.setupContainer( selection, namespace, bgcpRect, backgroundFill ); // if grouping is undefined sort violinKeys by sortingFunction var ordered = (grouping == undefined) ? d3.keys(data).sort(sortingFunction) : grouping // console.log(ordered) - violinKeys = flatten(ordered) + violinKeys = utils.arr.flatten(ordered) var calcValues = neededViolinValues() @@ -685,7 +683,11 @@ export function violin( selection ) { // augment valus - violinKeys.map(function(vk, i){ calcValues(vk, data) }) + violinValues = {} + violinKeys.map(function(vk, i){ + let v = calcValues(vk, data) + violinValues[vk] = v + }) var numberOfObjects = violinKeys.length @@ -698,9 +700,9 @@ export function violin( selection ) { scale.domain(extent).range(horizontalQ ? [0,spaceY] : [0, spaceX]) var space = horizontalQ ? spaceX : spaceY // calculate object size - objectSize = calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ) + objectSize = utils.math.calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ) // calculate spacer size if needed - spacerSize = calculateWidthOfSpacer(ordered, space, objectSize, numberOfObjects, objectSpacer, overflowQ) + spacerSize = utils.math.calculateWidthOfSpacer(ordered, space, objectSize, numberOfObjects, objectSpacer, overflowQ) // make the nested groups var spacerFunction = groupingSpacer() .horizontalQ(horizontalQ).scale(scale).moveby('category').numberOfObjects(numberOfObjects) @@ -715,7 +717,7 @@ export function violin( selection ) { // for color function var parentIndexArray = [] container.selectAll('g:not(.to-remove).'+objectClass) - .each(function(d, i){if (hasQ(violinKeys, d)){ parentIndexArray.push(Number(d3.select(this).attr('parent-index')))}}) + .each(function(d, i){if (utils.arr.hasQ(violinKeys, d)){ parentIndexArray.push(Number(d3.select(this).attr('parent-index')))}}) // update color function colorFunction = colorFunction.colorBy() == 'index' @@ -746,17 +748,17 @@ export function violin( selection ) { var t = d3.select(this), currentData = data[key] // needed because bug in selecting .to-remove - if (!hasQ(violinKeys, key)) {return} + if (!utils.arr.hasQ(violinKeys, key)) {return} var i = t.attr('parent-index') == undefined ? i : t.attr('parent-index'), fillColor = colorFunction(key, currentData, i, 'fill'), // prevent duplicate computation strokeColor = colorFunction(key, currentData, i, 'stroke'), - area = safeSelect(t, 'g', 'area'), - la = safeSelect(area, 'path', 'left'), - ra = safeSelect(area, 'path', 'right'), - quarts = safeSelect(t, 'g', 'quarts'), - lq3 = safeSelect(quarts, 'line', 'q3'), - lq1 = safeSelect(quarts, 'line', 'q1'), + area = utils.sel.safeSelect(t, 'g', 'area'), + la = utils.sel.safeSelect(area, 'path', 'left'), + ra = utils.sel.safeSelect(area, 'path', 'right'), + quarts = utils.sel.safeSelect(t, 'g', 'quarts'), + lq3 = utils.sel.safeSelect(quarts, 'line', 'q3'), + lq1 = utils.sel.safeSelect(quarts, 'line', 'q1'), q3 = currentData.quartiles[quartileKeys[3]], q2 = currentData.quartiles[quartileKeys[2]], q1 = currentData.quartiles[quartileKeys[1]] @@ -786,7 +788,7 @@ export function violin( selection ) { }) if (pointsQ) { - var ptsContainer = safeSelect(t, 'g', 'points') + var ptsContainer = utils.sel.safeSelect(t, 'g', 'points') var pts = ptsContainer.selectAll('.point').data(currentData.pointKeys) pts.on('mouseover', null) @@ -819,7 +821,7 @@ export function violin( selection ) { .attr('cy', function(pointKey, ii){ var dd = currentData.pointValues[ii] if (horizontalQ) { return scale(extent[1]) - scale(dd) } - var j = whichBin(currentData.binned, dd) + var j = utils.arr.whichBin(currentData.binned, dd) var r = Math.random() var n = vScale(r * currentData.frequencies[j] * 0.5) var k = Math.random() > 0.5 ? n : -n @@ -828,7 +830,7 @@ export function violin( selection ) { .attr('cx', function(pointKey, ii){ var dd = currentData.pointValues[ii] if (horizontalQ) { - var j = whichBin(currentData.binned, dd) + var j = utils.arr.whichBin(currentData.binned, dd) var r = Math.random() var n = vScale(r * currentData.frequencies[j] * 0.5) var k = Math.random() > 0.5 ? n : -n @@ -900,7 +902,7 @@ export function violin( selection ) { * @returns {function} calculateViolinValues * @namespace neededViolinValues */ -function neededViolinValues() { +export function neededViolinValues() { var /** * Whether or not the orientation of the violins are horizontal @@ -911,7 +913,7 @@ function neededViolinValues() { */ horizontalQ = true, /** - * Keys to be put into the quartiles if they need to be calculated. + * Keys to be put into the utils.math.quartiles if they need to be calculated. * (see {@link violin#quartileKeys}) * @param {Object} [quartileKeys=['Q0', 'Q1', 'Q2', 'Q3', 'Q4']] * @memberof neededViolinValues# @@ -998,7 +1000,7 @@ function neededViolinValues() { * * data[violinKey].contour // the points depicting the contour of 1/2 of the violin * - * data[violinKey].quartiles // the quartiles of the points' values + * data[violinKey].utils.math.quartiles // the utils.math.quartiles of the points' values * * data[violinKey].pointKeys // the keys associated with the points * @@ -1017,8 +1019,8 @@ function neededViolinValues() { // the numerical values of those points var violinPointsValues = violinPointsKeys.map(function(pk, i){return violinPointValueExtractor(pk, violinPoints)}) - // quartiles of those points - var pointQuartiles = quartiles(violinPointsValues, quartileKeys) + // utils.math.quartiles of those points + var pointQuartiles = utils.math.quartiles(violinPointsValues, quartileKeys) // binned points var binned = d3.histogram()(violinPointsValues) @@ -1042,6 +1044,7 @@ function neededViolinValues() { violinData.quartiles = pointQuartiles violinData.pointKeys = violinPointsKeys violinData.pointValues = violinPointsValues + return violinData } return calculateViolinValues diff --git a/src/scripts/modules/color-function.js b/src/modules/color-function.js similarity index 98% rename from src/scripts/modules/color-function.js rename to src/modules/color-function.js index 5bef0c54c5edfe4456cead5ae85f3804b7da3bb9..77035b7748ce19c946536fcdb69cdab29266ed85 100644 --- a/src/scripts/modules/color-function.js +++ b/src/modules/color-function.js @@ -1,4 +1,4 @@ -import {modifyHexidecimalColorLuminance} from './helpers'; +import {color} from './utils/index.js' /** * Creates a colorFunction @@ -6,7 +6,7 @@ import {modifyHexidecimalColorLuminance} from './helpers'; * @namespace colorFunction * @returns {function} colorFunction */ -export function colorFunction() { +export default function colorFunction() { var data, @@ -30,7 +30,7 @@ export function colorFunction() { * @memberof colorFunction# * @property */ - modifyOpacity = modifyHexidecimalColorLuminance, + modifyOpacity = color.modifyHexidecimalColorLuminance, /** * How to modify color for stroke * @param {number} [strokeOpacity=0] diff --git a/src/scripts/modules/d3-prototypes.js b/src/modules/d3-prototypes.js similarity index 92% rename from src/scripts/modules/d3-prototypes.js rename to src/modules/d3-prototypes.js index db19bf0436a2953c37d70145cc573d04ca50d61e..13c50e71d11debc0906a1ec273bdb7bc2dcb6d04 100644 --- a/src/scripts/modules/d3-prototypes.js +++ b/src/modules/d3-prototypes.js @@ -1,4 +1,4 @@ -import {getContainingSVG} from "./helpers"; +import utils from './utils/index.js' // import * as d3 from "d3"; /******************************************************************************* ** ** @@ -13,7 +13,7 @@ import {getContainingSVG} from "./helpers"; * @augments d3.selection * @returns {Element} which is the svg tag, not the d3 selection of that tag */ -d3.selection.prototype.thisSVG = function() { return getContainingSVG(this.node()); } +d3.selection.prototype.thisSVG = function() { return utils.sel.getContainingSVG(this.node()); } /** @@ -40,7 +40,7 @@ d3.mouse.absolute = function() { d3.selection.prototype.absolutePosition = function() { var element = this.node(); var elementPosition = element.getBoundingClientRect(); - var containerSVG = getContainingSVG(element) + var containerSVG = utils.sel.getContainingSVG(element) var svgPosition = containerSVG.getBoundingClientRect(); return { diff --git a/src/scripts/modules/grouping-spacer.js b/src/modules/grouping-spacer.js similarity index 97% rename from src/scripts/modules/grouping-spacer.js rename to src/modules/grouping-spacer.js index acb6c6fc230de658d31295d78e97f524c456556e..e5f808ec617d146a2c87a267164ae4d71604bb1e 100644 --- a/src/scripts/modules/grouping-spacer.js +++ b/src/modules/grouping-spacer.js @@ -1,4 +1,4 @@ -import {log, warn, error, info} from './utils'; +import {con} from './utils/index.js' /******************************************************************************* ** ** ** ** @@ -12,7 +12,7 @@ import {log, warn, error, info} from './utils'; * (see {@link groupingSpacer#recursivelyPosition}) * @namespace groupingSpacer */ -export function groupingSpacer() { +export default function groupingSpacer() { var /*@var {boolean} horizontalQ @default*/ @@ -125,7 +125,7 @@ export function groupingSpacer() { x = horizontalQ ? window.outerWidth : 0, y = !horizontalQ ? window.outerWidth : 0, t = 'translate('+x+','+y+')' - // if(y == undefined) {console.log(cur.node(), y, d)} + // if(y == undefined) {console.con.log(cur.node(), y, d)} return t }) }, @@ -147,7 +147,7 @@ export function groupingSpacer() { * }).remove() */ exitFunction = function(cur){ - log("groupingSpacer", "exiting with", {current: cur, currentNode: cur.node()}) + con.log("groupingSpacer", "exiting with", {current: cur, currentNode: cur.node()}) cur.selectAll('g').classed('to-remove', true) cur.transition().duration(transitionDuration*0.9).ease(easeFunc) @@ -158,7 +158,7 @@ export function groupingSpacer() { x = horizontalQ ? window.outerWidth : 0, y = !horizontalQ ? window.outerWidth : 0, t = 'translate('+x+','+y+')' - // if(y == undefined) {console.log(cur.node(), y, d)} + // if(y == undefined) {console.con.log(cur.node(), y, d)} return t }).remove() } diff --git a/src/scripts/modules/categorical-legend.js b/src/modules/legends/categorical-legend.js similarity index 93% rename from src/scripts/modules/categorical-legend.js rename to src/modules/legends/categorical-legend.js index f20fa7cefc5dd7283644c027bfcdb24a2a8066e5..7257d9ff8d71db669d8b6deb8177b876ac0da1f9 100644 --- a/src/scripts/modules/categorical-legend.js +++ b/src/modules/legends/categorical-legend.js @@ -1,10 +1,9 @@ -import {hypenate, safeSelect, round, interpolateColors} from './helpers'; -import {setupContainer, calculateWidthOfObject, calculateWidthOfSpacer} from './utils'; -import {colorFunction as CF} from './color-function'; -import {groupingSpacer} from './grouping-spacer'; -import {unique, flatten} from './array-functions'; +import utils from '../utils/index.js' +import CF from '../color-function'; +import groupingSpacer from '../grouping-spacer'; -export function categoricLegend( selection ) { + +export default function categoricLegend( selection ) { var categories, @@ -351,7 +350,7 @@ export function categoricLegend( selection ) { var verticalQ = !horizontalQ // background cliping rectangle var bgcpRect = {x:0, y:0, width: spaceX, height:spaceY} - var container = setupContainer( selection, namespace, bgcpRect, backgroundFill ); + var container = utils.sel.setupContainer( selection, namespace, bgcpRect, backgroundFill ); colorFunction.dataExtent([0, categories.length - 1]) @@ -364,13 +363,13 @@ export function categoricLegend( selection ) { // if grouping is undefined sort barKeys by sortingFunction var ordered = (grouping == undefined) ? categories.sort(sortingFunction) : grouping // ordered might be nested depending on grouping - var catKeys = flatten(ordered) + var catKeys = utils.arr.flatten(ordered) var space = horizontalQ ? spaceX : spaceY // calculate object size - var objectSize = calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ) + var objectSize = utils.math.calculateWidthOfObject(space, numberOfObjects, minObjectSize, maxObjectSize, objectSpacer, overflowQ) // calculate spacer size if needed - var spacerSize = calculateWidthOfSpacer(catKeys, space, objectSize, numberOfObjects, objectSpacer, overflowQ) + var spacerSize = utils.math.calculateWidthOfSpacer(catKeys, space, objectSize, numberOfObjects, objectSpacer, overflowQ) // make the nested groups var spacerFunction = groupingSpacer() .horizontalQ(horizontalQ).scale(scale).moveby('category').numberOfObjects(numberOfObjects) @@ -383,7 +382,7 @@ export function categoricLegend( selection ) { container.selectAll('g:not(.to-remove).'+objectClass).each(function(cat, i) { var t = d3.select(this) - var c = safeSelect(t, 'circle') + var c = utils.sel.safeSelect(t, 'circle') var fillColor = colorFunction(undefined, cat, i, 'fill'), // prevent duplicate computation strokeColor = colorFunction(undefined, cat, i, 'stroke') @@ -401,7 +400,7 @@ export function categoricLegend( selection ) { .attr('stroke', strokeColor) .attr('stroke-width', bubbleStrokeWidth) - var text = safeSelect(t, 'text') + var text = utils.sel.safeSelect(t, 'text') text.text(cat) .attr('text-anchor', 'middle') .attr("transform", function(d, i){ diff --git a/src/modules/legends/index.js b/src/modules/legends/index.js new file mode 100644 index 0000000000000000000000000000000000000000..6e8846d57d75aea424e102677646680702e53784 --- /dev/null +++ b/src/modules/legends/index.js @@ -0,0 +1,9 @@ +import categorical from './categorical-legend' +import numeric from './numeric-legend' + +let legends = { + categorical, numeric +} + +export {categorical, numeric} +export default legends diff --git a/src/scripts/modules/numeric-legend.js b/src/modules/legends/numeric-legend.js similarity index 75% rename from src/scripts/modules/numeric-legend.js rename to src/modules/legends/numeric-legend.js index 6db251735b0f8c92dc88c01e33fd0a68913c9b26..bd4824e4a99eba0cd0bc2831e79b12c9be5417a2 100644 --- a/src/scripts/modules/numeric-legend.js +++ b/src/modules/legends/numeric-legend.js @@ -1,9 +1,7 @@ -import {hypenate, safeSelect, round, interpolateColors} from './helpers'; -import {setupContainer} from './utils'; -import {colorFunction as CF} from './color-function'; +import utils from '../utils/index.js' +import CF from '../color-function'; - -export function numericLegend( selection ) { +export default function numericLegend( selection ) { var min=0, @@ -32,15 +30,15 @@ export function numericLegend( selection ) { function legend() { // background cliping rectangle var bgcpRect = {x:0, y:0, width: spaceX, height:spaceY} - var container = setupContainer( selection, namespace, bgcpRect, backgroundFill ); + var container = utils.sel.setupContainer( selection, namespace, bgcpRect, backgroundFill ); - var defs = safeSelect(selection, 'defs') - var linearGradient = safeSelect(defs, 'linearGradient') + var defs = utils.sel.safeSelect(selection, 'defs') + var linearGradient = utils.sel.safeSelect(defs, 'linearGradient') .attr("x1", "0%") .attr("y1", "100%") .attr("x2", "0%") .attr("y2", "0%") - .attr('id', hypenate(namespace,'numerical-legend-gradient')) + .attr('id', utils.str.hypenate(namespace,'numerical-legend-gradient')) colorFunction.dataExtent([min, max]) @@ -58,18 +56,18 @@ export function numericLegend( selection ) { - var rect = safeSelect(container, 'rect', 'legend') + var rect = utils.sel.safeSelect(container, 'rect', 'legend') .attr('transform', 'translate(0,'+fontSize+')') - .style("fill", "url(#"+hypenate(namespace,'numerical-legend-gradient')+")") + .style("fill", "url(#"+utils.str.hypenate(namespace,'numerical-legend-gradient')+")") .attr('x', 0) .attr('y', 0) .attr('width', spaceX) .attr('height', spaceY - fontSize*2) .on('mousemove', function(d, i){legendMousemove(d, i, rect, d3.select(this))}) - .on('mouseout', function(d, i){ d3.select("#"+hypenate(namespace,'legend-tooltip')).remove() }) + .on('mouseout', function(d, i){ d3.select("#"+utils.str.hypenate(namespace,'legend-tooltip')).remove() }) - var minText = safeSelect(container, 'text', 'min') - .text(round(min, 2)) + var minText = utils.sel.safeSelect(container, 'text', 'min') + .text(utils.math.round(min, 2)) .attr('text-anchor', 'middle') .attr("font-size", fontSize+'px') .attr('transform', function(d, i){ @@ -80,8 +78,8 @@ export function numericLegend( selection ) { return t }) - var maxText = safeSelect(container, 'text', 'max') - .text(round(max, 2)) + var maxText = utils.sel.safeSelect(container, 'text', 'max') + .text(utils.math.round(max, 2)) .attr('text-anchor', 'middle') .attr("font-size", fontSize+'px') .attr('transform', function(d, i){ @@ -102,13 +100,13 @@ export function numericLegend( selection ) { .domain([0, rect.attr('height')]) .range([max, min]) var m = d3.mouse(rect.node()) - var v = round(s(m[1]),roundTo) + var v = utils.math.round(s(m[1]),roundTo) var strokeColor = colorFunction(undefined, v, undefined, 'stroke') var fillColor = colorFunction(undefined, v, undefined, 'fill') - var div = safeSelect(d3.select('body'), 'div', hypenate(namespace,'legend-tooltip')) - .attr('id', hypenate(namespace,'legend-tooltip')) + var div = utils.sel.safeSelect(d3.select('body'), 'div', utils.str.hypenate(namespace,'legend-tooltip')) + .attr('id', utils.str.hypenate(namespace,'legend-tooltip')) .style('position', 'absolute') .style('left', (d3.event.pageX+15)+'px') .style('top', (d3.event.pageY+15)+'px') @@ -128,7 +126,7 @@ export function numericLegend( selection ) { .style('border-style', 'solid') .style('border-width', 2) - var text = safeSelect(div, 'div') + var text = utils.sel.safeSelect(div, 'div') .text(v) .style('color', textColor) .style('align-self', 'center') diff --git a/src/scripts/modules/tooltip.js b/src/modules/tooltip.js similarity index 85% rename from src/scripts/modules/tooltip.js rename to src/modules/tooltip.js index 77262d5a680c507988bdf0d0f00b719897a88c2a..2ed0abdbd6b60a784a06710a219c0bedc03f5663 100644 --- a/src/scripts/modules/tooltip.js +++ b/src/modules/tooltip.js @@ -1,5 +1,4 @@ -import {safeSelect, round} from './helpers'; -import {log, warn, info, error, consoleGroup, consoleGroupEnd} from './utils'; +import {sel, con, math} from './utils/index.js' /******************************************************************************* ** ** ** ** @@ -15,7 +14,7 @@ import {log, warn, info, error, consoleGroup, consoleGroupEnd} from './utils'; * @returns {tooltip} * @namespace tooltip */ -export function tooltip( selection ) { +export default function tooltip( selection ) { var keys, @@ -83,16 +82,16 @@ export function tooltip( selection ) { * @private */ function mousemove(key, i) { - consoleGroup('d3sm-tooltip') + con.consoleGroup('d3sm-tooltip') var currentData = data[key] var [x, y] = d3.mouse(d3.select("html").node()) - log('tooltip', 'mousemove detected',{key: key, index: i, x:x, y:y}) - log('tooltip', 'current data', currentData) + con.log('tooltip', 'mousemove detected',{key: key, index: i, x:x, y:y}) + con.log('tooltip', 'current data', currentData) - var div = safeSelect(d3.select('html'), 'tooltip', 'd3sm-tooltip') + var div = sel.safeSelect(d3.select('html'), 'tooltip', 'd3sm-tooltip') .classed('card', true) .style('max-width', '300px') .style('background-color', "#212529") @@ -100,14 +99,14 @@ export function tooltip( selection ) { - var cardBody = safeSelect(div, 'div', 'card-body') - var cardTitle = safeSelect(cardBody, 'h5', 'card-title') + var cardBody = sel.safeSelect(div, 'div', 'card-body') + var cardTitle = sel.safeSelect(cardBody, 'h5', 'card-title') .text(header == undefined ? key : typeof header == 'function' ? header(key, currentData, i) : header) .style('color', 'cyan') - var table = safeSelect(cardBody, 'table', 'table').classed('table-dark', true) - var tBody = safeSelect(table, 'tbody') + var table = sel.safeSelect(cardBody, 'table', 'table').classed('table-dark', true) + var tBody = sel.safeSelect(table, 'tbody') tBody = tBody.selectAll('tr') tBody= tBody.data(keys == undefined ? d3.keys(currentData): keys) @@ -120,20 +119,20 @@ export function tooltip( selection ) { .attr('tooltip-row-index', function(d, i){return i}) // tBody = tBody.merge(tr) - consoleGroup('tooltip-rows') + con.consoleGroup('tooltip-rows') tBody.selectAll('.tooltip-key').text(function(d, i){return d}) tBody.selectAll('tr .tooltip-value') .text(function(d, i){ - log('tooltip', 'trying to set value', {rowKey: d, rowIndex: i}) + con.log('tooltip', 'trying to set value', {rowKey: d, rowIndex: i}) var i = d3.select(this).attr('tooltip-row-index') var v = currentData[d]; if (values != undefined) {v = values[i]; if(typeof v == "function") {v = v(currentData, d)}} - return typeof v == 'number' ? round(v, 5) : v + return typeof v == 'number' ? math.round(v, 5) : v }) - consoleGroupEnd() - consoleGroupEnd() + con.consoleGroupEnd() + con.consoleGroupEnd() x += 15 // x += 15 diff --git a/src/scripts/modules/array-functions.js b/src/modules/utils/array.js similarity index 92% rename from src/scripts/modules/array-functions.js rename to src/modules/utils/array.js index 83cb78170e990607ca618820c396ec586a66eaaf..fc66bcc74865f50e277c24b9831e7d79fb0fc5f4 100644 --- a/src/scripts/modules/array-functions.js +++ b/src/modules/utils/array.js @@ -1,11 +1,12 @@ -import {uniqueElements} from './helpers'; -/******************************************************************************* -** ** -** ** -** PROTOTYPES ** -** ** -** ** -*******************************************************************************/ +/** +* Helper function for Array.filter to get unique elements of the array +* @param {*} value current value as mapping over array (self) +* @param {number} index current index in the array +* @param {Array} self passed array from Array.filter method +* @returns {boolean} whether or not value is the first of its kind (i.e. indexOf(value) == index) +*/ +export function uniqueElements(value, index, self) { return self.indexOf(value) === index; } + /** * This function tests to see if all elements of the passed array are true. * @param {Array} array of values diff --git a/src/modules/utils/colors.js b/src/modules/utils/colors.js new file mode 100644 index 0000000000000000000000000000000000000000..2fb0faf29038925bd597a0b49f17c5440e72e6f9 --- /dev/null +++ b/src/modules/utils/colors.js @@ -0,0 +1,32 @@ +/** +* Modifies luminance of hexidecimal number +* @param {string} hex should be hexidecimal value with or without the proceeding octotrope +* @param {number} lum value to increase or decrease luminosity by +* @returns {string} updated hexidecimal value without the proceeding octotrope +*/ +export function modifyHexidecimalColorLuminance(hex, lum) { + // validate hex string + var hex = String(hex).replace(/[^0-9a-f]/gi, ''); + + if (hex.length < 6) { + hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2]; + } + lum = lum || 0; + + // convert to decimal and change luminosity + var rgb = '#', c, i; + for (i = 0; i < 3; i++) { + c = parseInt(hex.substr(i*2,2), 16); + c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); + rgb += ('00'+c).substr(c.length); + } + + return rgb; +} + +/** +* Maps arguments in to d3.interpolateRgbBasis +* @param arguments +* @returns {Function} +*/ +export function interpolateColors(){return d3.interpolateRgbBasis(arguments)} diff --git a/src/modules/utils/console.js b/src/modules/utils/console.js new file mode 100644 index 0000000000000000000000000000000000000000..8da9cfa5e9603df9622959f4aa445f70d447562c --- /dev/null +++ b/src/modules/utils/console.js @@ -0,0 +1,97 @@ +/** + * calls console.group if d3sm.debugQ == true + * @param {string} name of the group + * @returns {undefined} + */ +export function consoleGroup(name) { + if (window.d3sm.debugQ === true){ + console.group(name) + } +} + +/** + * calls console.groupEnd if d3sm.debugQ == true + * @returns {undefined} + */ +export function consoleGroupEnd() { + if (window.d3sm.debugQ === true){ + console.groupEnd() + } +} + +/** + * Calls console.log if d3sm.debugQ == true + * @param {string} func name of the function logging + * @param {string} msg to log + * @param {Object} data to be logged along side the message + * @returns {undefined} + */ +export function log(func, msg, data) { + if (window.d3sm.debugQ === true){ + console.log( + `%c[d3sm::${func}]:\t${msg}`, + [ + 'background: #6cd1ef', + 'border-radius: 5000px', + 'padding: 0px 2px', + 'font-size: 14px' + ].join(';') + ) + console.table(data) + // console.trace() + } +} + +/** + * Calls console.warn if d3sm.debugQ == true + * @param {string} func name of the function warning + * @param {string} msg to display + * @param {Object} data to be displayed along side the message + * @returns {undefined} + */ +export function warn(func, msg, data) { + if (window.d3sm.debugQ === true) + console.warn( + `%c[d3sm::${func}]:\t${msg}`, + [ + 'background: #ffd53e', + 'border-radius: 5000px', + 'padding: 0px 2px', + 'font-size: 14px' + ].join(';') + ) + console.table(data) +} +/** + * Calls the console.info if d3sm.debugQ == true + * @param {string} func name of the function providing info + * @param {string} msg to display + * @param {Object} data to be displayed along side the message + * @returns {undefined} + */ +export function info(func, msg, data) { + if (window.d3sm.debugQ) + console.info( + `%c[d3sm::${func}]:\t${msg}`, + [ + 'background: #009ccd', + 'border-radius: 5000px', + 'padding: 0px 2px', + 'font-size: 14px' + ].join(';') + ) + console.table(data) +} + + +/** + * Calls console.error if d3sm.debugQ == true + * @param {string} func name of the function which sends the error + * @param {string} msg to display + * @param {Object} data to be displayed along side the message + * @returns {undefined} + */ +export function error(func, msg, data) { + if (window.d3sm.debugQ) + console.error(`[d3sm::${func}]:\t${msg}\t%o`,data) +} diff --git a/src/modules/utils/index.js b/src/modules/utils/index.js new file mode 100644 index 0000000000000000000000000000000000000000..e117b00c3f0262d2e67a2a38a1821361433f958f --- /dev/null +++ b/src/modules/utils/index.js @@ -0,0 +1,16 @@ +import * as arr from './array.js' +import * as color from './colors.js' +import * as math from './math.js' +import * as misc from './misc.js' +import * as sel from './selections.js' +import * as str from './strings.js' +import * as con from './console.js' +import * as paths from './paths.js' + + +let utils = { + arr, color, math, misc, sel, str, con, paths +} + +export {arr, color, math, misc, sel, str, con, paths} +export default utils diff --git a/src/modules/utils/math.js b/src/modules/utils/math.js new file mode 100644 index 0000000000000000000000000000000000000000..824475fa7e83607a960c5a62d3f9946fa01242e6 --- /dev/null +++ b/src/modules/utils/math.js @@ -0,0 +1,161 @@ +import {total} from './array.js' +/** +* Rounds decimals of number to precision +* @param {number} number +* @param {number} precision +* @returns {number} rounded to precision +*/ +export function round(number, precision) { + var shift = function (number, precision, reverseShift) { + if (reverseShift) { + precision = -precision; + } + var numArray = ('' + number).split('e'); + return +(numArray[0] + 'e' + (numArray[1] ? (+numArray[1] + precision) : precision)); + }; + return shift(Math.round(shift(number, precision, false)), precision, true); +} + +/** +* evenly partitions the range [min, max] into n parts +* @param {number} min +* @param {number} max +* @param {number} n +* @returns {number[]} array of length n evenly partitioned between min and max +*/ +export function tickRange(min, max, n) { + var a = [min] + var d = max-min + var s = d / (n-1) + for (var i = 0; i < n-2; i++) { a.push(min + s * (i+1)) } + a.push(max) + return a +} + +/** +* @deprecated @see{@link tickRange} +* @param {number} min +* @param {number} max +* @param {number} parts +* @returns {number[]} array of length parts evenly partitioned between min and max +*/ +export function partitionRangeInto(min, max, parts) { + var diff = max - min + return Array(parts).map(function (e, i) { return min + diff / parts * i }) +} + + +export function euclideanDistance(p1, p2){ + var a = p1[0] - p2[0], b = p1[1] - p2[1] + return Math.sqrt(a*a + b*b) +} + +/** +* Calculated the quartiles of the passed data and stores them with qKeys +* @param {number[]} data list of numerical values +* @param {string[]} [qKeys=['q0', 'q1', 'q2', 'q3', 'q4']] how returned object with quartiles should be stored +* @returns {Object} with keys qKeys giving only the numerical values for the quartiles +*/ +export function quartiles(data, qKeys) { + var + q2 = d3.median(data), + lower = data.filter(x => x < q2), + upper = data.filter(x => x > q2), + + q1 = d3.median(lower), + q1 = q1 == undefined ? q2 : q1, + + q0 = d3.min(lower), + q0 = q0 == undefined ? q1 : q0, + + q3 = d3.median(upper), + q3 = q3 == undefined ? q2 : q3, + + q4 = d3.max(upper), + q4 = q4 == undefined ? q3 : q4, + + k0 = 'q0', k1 = 'q1', k2 = 'q2', k3 = 'q3', k4 = 'q4', + obj = {} + if (qKeys!=undefined && qKeys.length == 5) { k0 = qKeys[0]; k1 = qKeys[1]; k2 = qKeys[2]; k3 = qKeys[3]; k4 = qKeys[4]; } + obj[k0] = q0; obj[k1] = q1; obj[k2] = q2; obj[k3] = q3; obj[k4] = q4; + + return obj +} + + +/** +* determines the width of an object for the calling plotting function +* @param {number} freeSpace how much space is avalible +* @param {number} numberOfObjects how many object do we need +* @param {number} minObjectWidth how small are these objects allowed to be +* @param {number} maxObjectWidth how large are these object allowed to be +* @param {number} sizeOfSpacer percent of freeSpace that a single spacer should take up (need numberOfObjects - 1 spacers) +* @param {boolean} overflowQ can we go beyond alloted space +* @returns {number} how large object should be +* function tries to keep object within min / max width, but wil default to +* 5e-10 (smallest consistenly visible by svg size of element) if overflowQ is false +*/ +export function calculateWidthOfObject(freeSpace, numberOfObjects, minObjectWidth, maxObjectWidth, sizeOfSpacer, overflowQ) { + var sizeOfSpacer = + sizeOfSpacer == 0 || sizeOfSpacer > 1 + ? sizeOfSpacer + : freeSpace * sizeOfSpacer + + var numberOfSpacers = numberOfObjects - 1 + var spaceTakenBySpacers = numberOfSpacers * sizeOfSpacer + var remainingSpace = freeSpace - spaceTakenBySpacers + remainingSpace = remainingSpace < 0 ? 0 : remainingSpace + var objectWidth = remainingSpace / numberOfObjects + + if ( overflowQ && minObjectWidth != undefined && objectWidth < minObjectWidth ) { objectWidth = minObjectWidth } + // if ( maxObjectWidth != undefined && objectWidth > maxObjectWidth ) { objectWidth = maxObjectWidth } + if ( overflowQ && maxObjectWidth != undefined && objectWidth < maxObjectWidth ) { objectWidth = maxObjectWidth } + return Math.max(objectWidth, 5e-10) +} + +/** +* @param {Array[]} data list data (can be nested). If nested will create more complex spacer size +* @param {number} freeSpace how much space is avalible +* @param {number} objectWidth @see{@link calculateWidthOfObject} +* @param {number} numberOfObjects how many object do we need +* @param {number} baseSpacerSize percent of freeSpace that a single spacer should take up (need numberOfObjects - 1 spacers) +* @param {boolean} overflowQ can we go beyond alloted space +* @returns {number} returns size that spacer should be at level=0 +*/ +export function calculateWidthOfSpacer(data, freeSpace, objectWidth, numberOfObjects, baseSpacerSize, overflowQ) { + if (overflowQ) { + // var limitedNumberOfObjects = numberOfObjects > 6 ? 6 : numberOfObjects + // var spaceLeft = freeSpace - limitedNumberOfObjects * objectWidth + // return spaceLeft / (limitedNumberOfObjects - 1) + return freeSpace * baseSpacerSize + } + var spacersAtEachLevel = spacersNeededAtEachLevel(data) + var totalSpacerPercent = total(spacersAtEachLevel.map(function(e, i) {return e * 1 / (i+1)})) + var baseSpacerSize = (freeSpace - (objectWidth * numberOfObjects)) / totalSpacerPercent + // console.log(freeSpace, objectWidth, numberOfObjects, totalSpacerPercent) + // console.log(totalSpacerPercent, baseSpacerSize, totalSpacerPercent * baseSpacerSize) + return isNaN(baseSpacerSize) ? 0 : baseSpacerSize +} + +/** +* Calculates number of spacers needed to seperate elements at each level. +* @param {Array[]} array list data (can be nested). If nested will create more complex spacer size +* @param {number} [level=0] current level, used in recusrion +* @param {Array} [levelData=[]] how many spacers needed at a given level +* @returns {Array} levelData +* +* @example +* array = [[1,2], [3,4]] +* // returns [1, 2] +* as at level=0 the only spacer needed is between [1,2] and [3,4] +* and at level=1 the only two spacers needed is between 1 and 2 as well as +* 3 and 4 since the spacer between 2 and 3 is handled at level=0 +*/ +export function spacersNeededAtEachLevel (array, level, levelData ) { + if ( level == undefined ) { level = 0; } else { level += 1 } + if ( levelData == undefined ) { levelData = []; } + if ( level >= levelData.length ) { levelData.push(array.length - 1) } + else { levelData[level] += array.length - 1 } + array.map(function(e, i) { if (Array.isArray(e)) { spacersNeededAtEachLevel(e, level, levelData) } } ) + return levelData +} diff --git a/src/modules/utils/misc.js b/src/modules/utils/misc.js new file mode 100644 index 0000000000000000000000000000000000000000..cbc3dada8f92c30afab81b937e4a56dd5e8062fc --- /dev/null +++ b/src/modules/utils/misc.js @@ -0,0 +1,140 @@ +import {safeSelect} from './selections.js' +import {hypenate} from './strings.js' +export function resizeDebounce(f, wait) { + var resize = debounce(function(){f()},wait) + window.addEventListener('resize', resize) +} + +function debounce(func, wait, immediate) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; +} + +export function setupStandardChartContainers( + selection, + namespace, + container, + margins={top:0.01, bottom:0.01, left:0.01, right:0.01}, + svg={w:0.8, h:0.6}, // percent of container space for svg + axes={y:0.1, x:0.1}, // percent of container space for axes, + leg={x:0, margin:0, pos:'left'} // absolute width of legend and space on either size +) +{ + if (container == undefined) {container = {w:window.innerWidth, h:window.Height}} + // SVG width and height + + var svgSpace = { + w: container.w * svg.w, + h: container.h * svg.h + } + + var margPx = { + top: margins.top * svgSpace.h, + bottom: margins.bottom * svgSpace.h, + left: margins.left * svgSpace.w, + right: margins.right * svgSpace.w + }, + + + + // Space after removing margins + chartSpace = { + w: svgSpace.w - margPx.left - margPx.right, + h: svgSpace.h - margPx.top - margPx.bottom + }, + + // main dimension of x and y axies + // e.g. defines how tall x axis is as length is determined by plotRect.w + axesSpace = { + x: chartSpace.h * axes.x, + y: chartSpace.w * axes.y + }, + + // space left for drawing the chart properly (e.g. bars, violins, etc) + drawingSpace = { + x: chartSpace.w - axesSpace.y - leg.x - 2*leg.margin, + y: chartSpace.h - axesSpace.x + }, + + + legRect = { + x: leg.margin + margPx.left + (leg.pos == 'left' ? 0 : drawingSpace.x + axesSpace.y), + y: margPx.top, // this is soomehow getting calculated incorectly + w: leg.x, + h: drawingSpace.y + }, + + yAxisRect = { + x: axesSpace.y + margPx.left + (leg.pos == 'left' ? leg.x + 2*leg.margin : 0), + y: margPx.top, + w: axesSpace.y, + h: drawingSpace.y + }, + + plotRect = { + x: axesSpace.y + margPx.left + (leg.pos == 'left' ? leg.x + 2*leg.margin : 0), + y: margPx.top, + w: drawingSpace.x, + h: drawingSpace.y + }, + + xAxisRect = { + x: axesSpace.y + margPx.left + (leg.pos == 'left' ? leg.x + 2*leg.margin : 0), + y: margPx.top + drawingSpace.y, + w: drawingSpace.x, + h: axesSpace.x + } + + + + container = safeSelect(selection, 'svg', namespace) + .style('width', svgSpace.w+'px') + .style('height', svgSpace.h+'px') + + var axes = safeSelect(container, 'g', hypenate(namespace, 'axes')) + + var leg = safeSelect(container, 'g', hypenate(namespace, 'legend')) + .attr('transform', "translate("+legRect.x+","+legRect.y+")") + + var plot = safeSelect(container, 'g', hypenate(namespace, 'plot')) + .attr('transform', "translate("+plotRect.x+","+plotRect.y+")") + + var xAxis = safeSelect(axes, 'g', hypenate(namespace, 'x-axis')) + .attr('transform', "translate("+xAxisRect.x+","+xAxisRect.y+")") + + var yAxis = safeSelect(axes, 'g', hypenate(namespace, 'y-axis')) + .attr('transform', "translate("+yAxisRect.x+","+yAxisRect.y+")") + + return { + svg: { + selection: container, + rect: svgSpace + }, + plot: { + selection: plot, + rect: plotRect + }, + xAxis: { + selection: xAxis, + rect: xAxisRect + }, + yAxis: { + selection: yAxis, + rect: yAxisRect + }, + legend: { + selection: leg, + rect: legRect + } + } +} diff --git a/src/modules/utils/paths.js b/src/modules/utils/paths.js new file mode 100644 index 0000000000000000000000000000000000000000..cafc8dca1c884d86d3b4ec63da954261e6117576 --- /dev/null +++ b/src/modules/utils/paths.js @@ -0,0 +1,40 @@ + +/** +* Draws a whisker for @see{@link boxwhisker} +* @param {boolean} dir direction to draw whisker, should be either true (up, top) or false (down or bottom) +* @param {number} x starting x coordinate in which to draw whisker +* @param {number} y starting y coordinate in which to draw whisker +* @param {number} w width of space in which to draw whisker +* @param {number} h height of space in which to draw whisker +* @param {number} per percentage of w or h (depends on o) to make whisker +* @param {boolean} o orientation, true is horizontal and false is vertical +* @returns {string} representing the svg path (i.e. the d attribute for a path tag) +*/ +export function whiskerPath(dir, x, y, w, h, per, o) { + // d = direction (true is up), p = percent width + if (dir == 'up' || dir == 'top' || dir == true) {dir = true} + if (dir == 'down' || dir == 'bottom' || dir == false) {dir = false} + o = o == undefined ? 'horizontal' : o + per = per == undefined ? 1 : per + if (o != "horizontal") { + var hh = h * per , + w = dir ? w : -w , + a = dir ? x + w : x , + b = dir ? x : x + w , + c = dir ? a : b + p = "M " + a + ' ' + ( h / 2 ) + ' ' + + 'L ' + b + ' ' + ( h / 2 ) + ' ' + + 'M ' + c + ' ' + ( h / 2 - hh / 2 ) + ' ' + + 'L ' + c + ' ' + ( h / 2 + hh / 2 ) + ' ' + + return p + } + var ww = w * per, + a = dir ? y + h : y , + b = dir ? y : y + h , + p = "M " + ( w / 2 ) + ' ' + a + ' ' // straight line part + + 'L ' + ( w / 2 ) + ' ' + b + ' ' // straight line part + + 'h ' + ( -ww / 2 ) + ' ' + 0 + ' ' // horizontal line part + + 'h ' + ( ww ) + ' ' + 0 + ' ' + return p +} diff --git a/src/modules/utils/selections.js b/src/modules/utils/selections.js new file mode 100644 index 0000000000000000000000000000000000000000..044855a786ec32916aae5cf9e7358a29a42ea305 --- /dev/null +++ b/src/modules/utils/selections.js @@ -0,0 +1,120 @@ +import {hypenate} from './strings.js' +/** +* Extracts x and y of translate from transform property +* @param {string} transform transform property of svg element +* @returns {number[]} x, y of translate(x, y) +*/ +export function getTranslation(transform) { + // Create a dummy g for calculation purposes only. This will never + // be appended to the DOM and will be discarded once this function + // returns. + var g = document.createElementNS('http://www.w3.org/2000/svg', 'g'); + // Set the transform attribute to the provided string value. + transform = transform == undefined ? 'translate(0,0)' : transform; + g.setAttributeNS(null, 'transform', transform); + // consolidate the SVGTransformList containing all transformations + // to a single SVGTransform of type SVG_TRANSFORM_MATRIX and get + // its SVGMatrix. + var matrix = g.transform.baseVal.consolidate().matrix; + // As per definition values e and f are the ones for the translation. + return [matrix.e, matrix.f]; +} + +/** +* recursively ascends element.parentElement to find a svg tag +* @param {Element} element +* @returns {Element | undefined} +*/ +export function getContainingSVG(element) { + var parent = element.parentElement + var tag = parent.tagName.toLowerCase() + if (tag === 'svg') { return parent; } + if (tag === 'html') { return undefined; } + return getContainingSVG(parent); +} + + +/** +* Trys to use d3.selection to get element, if it doesnt exist, makes one +* @param {d3.selection} sel selection in which to try and find object +* @param {string} tag tag of which to try and select +* @param {string} [cls=''] class of tag to try and grab +* @returns {d3.selection} of either append or selected tag.cls within sel +*/ +export function safeSelect(sel, tag, cls) { + var clsStr = cls == undefined ? '' : '.'+cls; + var sSel = sel.select(tag+clsStr).empty() + ? sel.append(tag) + : sel.select(tag+clsStr) + return sSel + .classed(clsStr.replace('.', ''), true) + .attr('transform', sSel.attr('transform') == undefined ? 'translate(0,0)' : sSel.attr('transform')) +} + + + +/** +* Adds a clip-path rect and binds it to container +* @param {d3.selection} container in which to add the clip-path and to which to bind the cliping path to +* @param {Object} rect the coordinates (x, y, width, height) of the clip-path +* @param {string} namespace +* @returns {d3.selection} of the clip-path rect +*/ +export function cpRect(container, rect, namespace) { + var defs = safeSelect(container, 'defs', hypenate(namespace, 'definitions')) + var cp = safeSelect(defs, 'clipPath', hypenate(namespace, 'clip-path')) + .attr('id', hypenate(namespace, 'clip-path')) + + var cpRect = safeSelect(cp, 'rect') + .attr('x', rect.x) + .attr('y', rect.y) + .attr('width', rect.width) + .attr('height', rect.height) + + defs.raise() + // set clipping path to container + container.attr('clip-path', 'url(#'+ hypenate(namespace, 'clip-path')+')') + + return cpRect +} + + +/** +* Adds a background rect t to container +* @param {d3.selection} container in which to add the background rectangle +* @param {Object} rect the coordinates (x, y, width, height) of the background +* @param {string} fill the color of the background +* @returns {d3.selection} of the background fill +*/ +export function bgRect(container, rect, fill) { + return safeSelect(container, 'rect', 'bg') + .attr('x', rect.x) + .attr('y', rect.y) + .attr('width', rect.width) + .attr('height', rect.height) + .attr('fill', fill) +} + + +/** +* Sets up the container for making chart elements. This includes making +* a clip-path rect bound to the passed container, a background rect, and +* a g element with class -object-container. +* @param {d3.selection} container in which to add the clip-path and background +* @param {string} namespace +* @param {Object} rect the coordinates (x, y, width, height) of the background and clip-path +* @param {string} fill the color of the background +* @returns {d3.selection} of g.-object-container +* +* @see{@link bgRect} +* @see{@link cpRect} +*/ +export function setupContainer(selection, namespace, rect, fill) { + // the container for three main items, bg, defs, and object-container + var + container = safeSelect(selection, 'g', namespace), + bg = bgRect(container, rect, fill), + cp = cpRect(container, rect, namespace), + objectContainer = safeSelect(container, 'g', hypenate(namespace, 'object-container')) + return objectContainer +} diff --git a/src/modules/utils/strings.js b/src/modules/utils/strings.js new file mode 100644 index 0000000000000000000000000000000000000000..e1ae5c5fffeda38b577e98bb5395b66e6d97c2b9 --- /dev/null +++ b/src/modules/utils/strings.js @@ -0,0 +1,41 @@ + +/** +* Hypenates all strings together +* @param {string[]} arguments +* @returns {string} "arg1-arg2-...-argn" +*/ +export function hypenate(){ return Array.prototype.slice.call(arguments).join('-') } + + +/** +* Trys to reduce text to fit in specified area, made for tick labels as called by +* @see{@link axis} +* @param {d3.selection} t container for specific axis tick +* @param {string} text to be the label of the passed axis tick +* @param {boolean} orient of the axis, true is horizontal, false is vertical +* @param {number} tickLength is the length of the text +* @param {number} space is the amount of availble space for the text and the tick to fit in +* @param {boolean} overflowQ whether or not allowed to go over the alloted space +* @returns {none} +*/ +export function truncateText(t, text, orient, tickLength, space, overflowQ) { + var rect = t.node().getBoundingClientRect() + t.text(text) + while (Math.max(rect.width, rect.height) > space - tickLength) { + text = String(text) + text = text.slice(0, text.length - 1) + t.text(text + '...') + rect = t.node().getBoundingClientRect() + if (text.length == 0) break + } +} + + +export function truncateString(string, space, font) { + var chars = space / font; + if (chars < string.length) { + return string.slice(0, Math.round(chars-5)) + '...' + } else { + return string + } +} diff --git a/src/scripts/main.js b/src/scripts/main.js deleted file mode 100644 index 737feafe38654c79126c56978f3fcdce10d0f5e9..0000000000000000000000000000000000000000 --- a/src/scripts/main.js +++ /dev/null @@ -1,116 +0,0 @@ -// Import styles (automatically inject into ). -// import '../styles/main.css'; -import {axis} from './modules/axis'; -import {bar} from './modules/bar'; -import {bubbleHeatmap} from './modules/bubble-heatmap'; -import {heatmap} from './modules/heatmap'; -import {boxwhisker} from './modules/box-whisker'; -import {colorFunction} from './modules/color-function'; -import {datatoggle} from './modules/data-toggle'; -import {groupingSpacer} from './modules/grouping-spacer'; -import {tooltip} from './modules/tooltip'; -import {scatter} from './modules/scatter'; -import {plotZoom} from './modules/plot-zoom'; -import {multiPlotZoom} from './modules/multi-plot-zoom'; -import {violin} from './modules/violin'; -import {numericLegend} from './modules/numeric-legend'; -import {categoricLegend} from './modules/categorical-legend'; -import {lasso} from './modules/lasso'; -import {lassoWidget} from './modules/lasso-widget'; -import {selectFilter} from './modules/select-filter'; -import {upset} from './modules/upset'; -import {filterTable} from './modules/filter-table'; - -import {uniqueElements, getTranslation, modifyHexidecimalColorLuminance, tickRange, -quartiles, extractViolinValues, hypenate, round, getContainingSVG, -interpolateColors, truncateText, safeSelect} from './modules/helpers'; - -import { - all, tally, hasQ, first, last, total, unique, get, listOfListsQ, - cut, groupBy, arrayEquals, elementsAtLevels, numberOfElements, - flatten, whichBin -} from './modules/array-functions'; - - -import { - setupStandardChartContainers, log as myLog, warn, info, error, - consoleGroup, consoleGroupEnd, resizeDebounce -} from './modules/utils'; - -// /** @module d3sm */ -var d3sm = {}; -d3sm.axis = axis; -d3sm.bar = bar; -d3sm.bubbleHeatmap = bubbleHeatmap; -d3sm.heatmap = heatmap; -d3sm.boxwhisker = boxwhisker; -d3sm.colorFunction = colorFunction; -d3sm.datatoggle = datatoggle; -d3sm.groupingSpacer = groupingSpacer; -d3sm.tooltip = tooltip; -d3sm.scatter = scatter; -d3sm.plotZoom = plotZoom; -d3sm.multiPlotZoom = multiPlotZoom; -d3sm.violin = violin; -d3sm.numericLegend = numericLegend; -d3sm.categoricLegend = categoricLegend; -d3sm.lasso = lasso; -d3sm.lassoWidget = lassoWidget; -d3sm.selectFilter = selectFilter; -d3sm.upset = upset; -d3sm.filterTable = filterTable; - -d3sm.uniqueElements = uniqueElements; -d3sm.getTranslation = getTranslation; -d3sm.modifyHexidecimalColorLuminance = modifyHexidecimalColorLuminance; -d3sm.tickRange = tickRange; -d3sm.quartiles = quartiles; -d3sm.extractViolinValues = extractViolinValues; -d3sm.hypenate = hypenate; -d3sm.round = round; -d3sm.getContainingSVG = getContainingSVG; -d3sm.interpolateColors = interpolateColors; -d3sm.truncateText = truncateText; -d3sm.safeSelect = safeSelect; - -d3sm.whichBin = whichBin; -d3sm.unique = unique; -d3sm.flatten = flatten; - -d3sm.setupStandardChartContainers = setupStandardChartContainers; -d3sm.log = myLog; -d3sm.warn = warn; -d3sm.info = info; -d3sm.error = error; -d3sm.consoleGroup = consoleGroup; -d3sm.consoleGroupEnd = consoleGroupEnd; -d3sm.resizeDebounce = resizeDebounce; - -d3sm.debugQ = false - - - -// Import a logger for easier debugging -// import debug from 'debug'; -// const log = debug('app:log'); - -// The logger should only be disabled if we're not in production. -// if (ENV !== 'production') { -// // Enable the logger. -// debug.enable('*'); -// log('Logging is enabled!'); -// -// // Enable LiveReload -// document.write( -// '